This commit was manufactured by cvs2svn to create branch 'R3_2_5_patches'.
diff --git a/bundles/org.eclipse.jst.jsp.core/.classpath b/bundles/org.eclipse.jst.jsp.core/.classpath
new file mode 100644
index 0000000..ca82c98
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/.classpath
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.4">
+		<accessrules>
+			<accessrule kind="accessible" pattern="org/eclipse/wst/sse/**"/>
+		</accessrules>
+	</classpathentry>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins">
+		<accessrules>
+			<accessrule kind="accessible" pattern="org/eclipse/wst/sse/core/**"/>
+			<accessrule kind="accessible" pattern="org/eclipse/wst/xml/core/**"/>
+			<accessrule kind="accessible" pattern="org/eclipse/wst/css/core/**"/>
+			<accessrule kind="accessible" pattern="org/eclipse/wst/html/core/**"/>
+			<accessrule kind="accessible" pattern="org/eclipse/wst/validation/**"/>
+		</accessrules>
+	</classpathentry>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/bundles/org.eclipse.jst.jsp.core/.cvsignore b/bundles/org.eclipse.jst.jsp.core/.cvsignore
new file mode 100644
index 0000000..12f30eb
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/.cvsignore
@@ -0,0 +1,11 @@
+bin
+temp.folder
+jspmodel.jar
+dev.properties
+org.eclipse.jst.jsp.core_6.0.0.jar
+build.xml
+org.eclipse.jst.jsp.core_6.0.0.zip
+jspmodelsrc.zip
+@dot
+src.zip
+javaCompiler...args
diff --git a/bundles/org.eclipse.jst.jsp.core/.options b/bundles/org.eclipse.jst.jsp.core/.options
new file mode 100644
index 0000000..89a2c96
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/.options
@@ -0,0 +1,35 @@
+org.eclipse.jst.jsp.core/debug=true
+org.eclipse.jst.jsp.core/debug/tracefilter=
+org.eclipse.jst.jsp.core/debug/jspindexmanager=false
+org.eclipse.jst.jsp.core/debug/jsptranslation=false
+org.eclipse.jst.jsp.core/debug/jsptranslationstodisk=false
+org.eclipse.jst.jsp.core/debug/jspsearch=false
+
+org.eclipse.jst.jsp.core/taglib/resolve=false
+
+
+# org.eclipse.jst.jsp.core.contentmodel.tld.TLDCMDocumentManager._debug
+org.eclipse.jst.jsp.core/debug/tldcmdocument/manager=false
+org.eclipse.jst.jsp.core/debug/tldcmdocument/cache=false
+
+# org.eclipse.jst.jsp.core.contentmodel.tld.CMDocumentFactoryTLD._debug
+org.eclipse.jst.jsp.core/debug/tldcmdocument/factory=false
+
+#org.eclipse.jst.jsp.core.internal.contentmodel.ProjectDescription._debugIndexCreation
+org.eclipse.jst.jsp.core/taglib/indexcreation=false
+#org.eclipse.jst.jsp.core.internal.contentmodel.ProjectDescription._debugIndexTime
+org.eclipse.jst.jsp.core/taglib/indextime=false
+
+#org.eclipse.jst.jsp.core.internal.contentmodel.TaglibIndex._debugEvents
+org.eclipse.jst.jsp.core/taglib/events=false
+#org.eclipse.jst.jsp.core.internal.contentmodel.TaglibIndex._debugIndexCreation
+org.eclipse.jst.jsp.core/taglib/indexcreation=false
+#org.eclipse.jst.jsp.core.internal.contentmodel.TaglibIndex._debugResolution
+org.eclipse.jst.jsp.core/taglib/resolve=false
+
+org.eclipse.jst.jsp.core/debug/jspjavamapping=false
+
+org.eclipse.jst.jsp.core/debug/jspvalidator=false
+org.eclipse.jst.jsp.core/debug/taglibvars=false
+
+org.eclipse.jst.jsp.core/debug/taglibclassloader
\ No newline at end of file
diff --git a/bundles/org.eclipse.jst.jsp.core/.project b/bundles/org.eclipse.jst.jsp.core/.project
new file mode 100644
index 0000000..0f10b7a
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.jst.jsp.core</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.ManifestBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.SchemaBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.PluginNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
diff --git a/bundles/org.eclipse.jst.jsp.core/.settings/org.eclipse.core.resources.prefs b/bundles/org.eclipse.jst.jsp.core/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..afa5c91
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+#Tue Apr 04 03:36:32 EDT 2006
+eclipse.preferences.version=1
+encoding/<project>=ISO-8859-1
diff --git a/bundles/org.eclipse.jst.jsp.core/.settings/org.eclipse.core.runtime.prefs b/bundles/org.eclipse.jst.jsp.core/.settings/org.eclipse.core.runtime.prefs
new file mode 100644
index 0000000..7ec5750
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/.settings/org.eclipse.core.runtime.prefs
@@ -0,0 +1,3 @@
+#Mon Apr 17 01:48:39 EDT 2006
+eclipse.preferences.version=1
+line.separator=\r\n
diff --git a/bundles/org.eclipse.jst.jsp.core/.settings/org.eclipse.jdt.core.prefs b/bundles/org.eclipse.jst.jsp.core/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..911428b
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,79 @@
+#Wed Mar 28 02:56:12 EDT 2007

+eclipse.preferences.version=1

+org.eclipse.jdt.core.builder.cleanOutputFolder=clean

+org.eclipse.jdt.core.builder.duplicateResourceTask=warning

+org.eclipse.jdt.core.builder.invalidClasspath=ignore

+org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch

+org.eclipse.jdt.core.circularClasspath=error

+org.eclipse.jdt.core.classpath.exclusionPatterns=enabled

+org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled

+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=disabled

+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.2

+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve

+org.eclipse.jdt.core.compiler.compliance=1.4

+org.eclipse.jdt.core.compiler.debug.lineNumber=generate

+org.eclipse.jdt.core.compiler.debug.localVariable=generate

+org.eclipse.jdt.core.compiler.debug.sourceFile=generate

+org.eclipse.jdt.core.compiler.doc.comment.support=enabled

+org.eclipse.jdt.core.compiler.maxProblemPerUnit=100

+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning

+org.eclipse.jdt.core.compiler.problem.assertIdentifier=warning

+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore

+org.eclipse.jdt.core.compiler.problem.deprecation=ignore

+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled

+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=enabled

+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning

+org.eclipse.jdt.core.compiler.problem.emptyStatement=warning

+org.eclipse.jdt.core.compiler.problem.enumIdentifier=warning

+org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore

+org.eclipse.jdt.core.compiler.problem.finalParameterBound=ignore

+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=error

+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error

+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning

+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning

+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore

+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=error

+org.eclipse.jdt.core.compiler.problem.invalidJavadoc=ignore

+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled

+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled

+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=private

+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore

+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=error

+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore

+org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore

+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=enabled

+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public

+org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore

+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=enabled

+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=private

+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore

+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=error

+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=error

+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning

+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore

+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning

+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=error

+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=enabled

+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=error

+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled

+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=warning

+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=ignore

+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning

+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore

+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning

+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore

+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=error

+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore

+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore

+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled

+org.eclipse.jdt.core.compiler.problem.unusedImport=error

+org.eclipse.jdt.core.compiler.problem.unusedLabel=error

+org.eclipse.jdt.core.compiler.problem.unusedLocal=error

+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore

+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled

+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled

+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=error

+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning

+org.eclipse.jdt.core.compiler.source=1.3

+org.eclipse.jdt.core.incompatibleJDKLevel=ignore

+org.eclipse.jdt.core.incompleteClasspath=error

diff --git a/bundles/org.eclipse.jst.jsp.core/.settings/org.eclipse.jdt.ui.prefs b/bundles/org.eclipse.jst.jsp.core/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000..301c7ad
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,4 @@
+#Mon Apr 17 01:48:39 EDT 2006
+eclipse.preferences.version=1
+internal.default.compliance=default
+org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8"?>\r\n<templates/>
diff --git a/bundles/org.eclipse.jst.jsp.core/.settings/org.eclipse.ltk.core.refactoring.prefs b/bundles/org.eclipse.jst.jsp.core/.settings/org.eclipse.ltk.core.refactoring.prefs
new file mode 100644
index 0000000..c59368c
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/.settings/org.eclipse.ltk.core.refactoring.prefs
@@ -0,0 +1,3 @@
+#Tue Apr 04 03:36:32 EDT 2006
+eclipse.preferences.version=1
+org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false
diff --git a/bundles/org.eclipse.jst.jsp.core/.settings/org.eclipse.pde.prefs b/bundles/org.eclipse.jst.jsp.core/.settings/org.eclipse.pde.prefs
new file mode 100644
index 0000000..fc522bb
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/.settings/org.eclipse.pde.prefs
@@ -0,0 +1,16 @@
+#Mon Apr 17 02:01:33 EDT 2006
+compilers.incompatible-environment=0
+compilers.p.build=0
+compilers.p.deprecated=1
+compilers.p.illegal-att-value=0
+compilers.p.no-required-att=0
+compilers.p.not-externalized-att=0
+compilers.p.unknown-attribute=0
+compilers.p.unknown-class=0
+compilers.p.unknown-element=0
+compilers.p.unknown-resource=0
+compilers.p.unresolved-ex-points=0
+compilers.p.unresolved-import=0
+compilers.p.unused-element-or-attribute=0
+compilers.use-project=true
+eclipse.preferences.version=1
diff --git a/bundles/org.eclipse.jst.jsp.core/DevTimeSupport/CSSJSPParser/HowToGen.html b/bundles/org.eclipse.jst.jsp.core/DevTimeSupport/CSSJSPParser/HowToGen.html
new file mode 100644
index 0000000..ea439f1
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/DevTimeSupport/CSSJSPParser/HowToGen.html
@@ -0,0 +1,9 @@
+<html>
+<body>
+<p>
+JSPedCSSTokenizer class is a scanner generated by <a href="http://www.jflex.de/">JFlex</a> 1.4.1 
+from the JSPedCSSTokenizer.flex grammer file.
+After generating the scanner, I removed unused private field errors.
+</p>
+</body>
+<html>
diff --git a/bundles/org.eclipse.jst.jsp.core/DevTimeSupport/CSSJSPParser/JSPedCSSTokenizer.flex b/bundles/org.eclipse.jst.jsp.core/DevTimeSupport/CSSJSPParser/JSPedCSSTokenizer.flex
new file mode 100644
index 0000000..6daf75a
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/DevTimeSupport/CSSJSPParser/JSPedCSSTokenizer.flex
@@ -0,0 +1,598 @@
+/*******************************************************************************

+ * Copyright (c) 2006, 2008 IBM Corporation and others.

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ * 

+ * Contributors:

+ *     IBM Corporation - initial API and implementation

+ *******************************************************************************/

+package org.eclipse.jst.jsp.css.core.internal.parser;

+

+import java.io.CharArrayReader;

+import java.io.IOException;

+import java.util.ArrayList;

+import java.util.List;

+

+import org.eclipse.jst.jsp.css.core.internal.parserz.JSPedCSSRegionContexts;

+import org.eclipse.wst.css.core.internal.parser.CSSRegionUtil;

+import org.eclipse.wst.css.core.internal.parser.ICSSTokenizer;

+import org.eclipse.wst.css.core.internal.parser.regions.CSSTextRegionFactory;

+import org.eclipse.wst.css.core.internal.parserz.CSSTextToken;

+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;

+

+%%

+

+%public

+%class JSPedCSSTokenizer

+%implements JSPedCSSRegionContexts, ICSSTokenizer

+%function primGetNextToken

+%type String

+%char

+%line

+%unicode

+%caseless

+%pack

+

+%{

+	private final static String UNDEFINED = "undefined";

+	private String fBufferedContext = null;

+	private int fBufferedStart;

+//	private int fBufferedTextLength;

+	private int fBufferedLength;

+//	private StringBuffer fBufferedText = null;

+	private CSSTextRegionFactory fRegionFactory = CSSTextRegionFactory.getInstance();

+	private int fInitialState = YYINITIAL;

+	public final static int BUFFER_SIZE_NORMAL = 16384;

+	public final static int BUFFER_SIZE_SMALL = 256;

+	private int fInitialBufferSize = BUFFER_SIZE_NORMAL;

+

+	public void setInitialState(int state) {

+		fInitialState = state;

+	}

+	

+	public void setInitialBufferSize(int size) {

+		fInitialBufferSize = size;

+	}

+

+	/* user method */

+  	public final ITextRegion getNextToken() throws IOException {

+		String context;

+		String nextTokenType;

+		boolean spaceFollows;

+//		StringBuffer text;

+		int start;

+		int textLength;

+		int length;

+		if (fBufferedContext != null) {

+			context = fBufferedContext;

+//			text = fBufferedText;

+			start = fBufferedStart;

+			textLength = length = fBufferedLength;

+

+			fBufferedContext = null;

+		} else {

+			context = primGetNextToken();

+//			text = new StringBuffer(yytext());

+			start = yychar;

+			textLength = length = yylength();

+		}

+

+		if (context != null) {

+			if (context == CSS_JSP_SCRIPTLET || context == CSS_JSP_EL){

+				nextTokenType = primGetNextToken();

+				while (nextTokenType != CSS_JSP_END && nextTokenType != CSS_EL_END && nextTokenType != CSS_JSP_COMMENT) {

+//					text.append(yytext());

+					textLength += yylength();

+					length = textLength;

+					if (context.equals(CSS_JSP_SCRIPTLET) && (yystate() == ST_JSP_DIRECTIVE || yystate() == ST_JSP_EXP || yystate() == ST_JSP_DECLARATION)){

+						context = nextTokenType;

+					}

+					nextTokenType = primGetNextToken();

+					if (nextTokenType == null){

+						break;

+					}

+				}

+				// [236008] - Should not try and consider the token a

+				// comment unless  a comment was started

+				if (context == CSS_JSP_SCRIPTLET && nextTokenType == CSS_JSP_COMMENT){

+					while (nextTokenType != CSS_JSP_COMMENT_END) {

+//						text.append(yytext());

+						textLength += yylength();

+						length = textLength;

+						if (context.equals(CSS_JSP_SCRIPTLET) && yystate() == ST_JSP_COMMENT){

+							context = nextTokenType;

+						}

+

+						nextTokenType = primGetNextToken();

+						if (nextTokenType == null){

+							break;

+						}

+					}				

+					if (context == CSS_JSP_COMMENT){

+						context = CSS_COMMENT;

+					}

+				}

+				textLength += yylength();

+				length = textLength;

+				

+			}

+			if (context == UNDEFINED) {

+				// undef -> concatenate undef's

+				nextTokenType = primGetNextToken();

+				while (nextTokenType == UNDEFINED) {

+//					text.append(yytext());

+					textLength += yylength();

+					length = textLength;

+					nextTokenType = primGetNextToken();

+				}

+				fBufferedContext = nextTokenType;

+//				fBufferedText = new StringBuffer(yytext());

+				fBufferedStart = yychar;

+				fBufferedLength = yylength();

+			} else {

+				nextTokenType = null;

+				spaceFollows = false;

+				if (CSSRegionUtil.isDeclarationValueType(context)) { // declaration value can contain VALUE_S

+					nextTokenType = primGetNextToken();

+					spaceFollows = (nextTokenType == CSS_DECLARATION_VALUE_S);

+				} else if (canContainSpace(context)) {

+					nextTokenType = primGetNextToken();

+					spaceFollows = (nextTokenType == CSS_S);

+				}

+				if (nextTokenType != null) { // nextToken is retrieved

+					if (spaceFollows) {

+						// next is space -> append

+//						text.append(yytext());

+						length += yylength();

+					} else {

+						// next is NOT space -> push this for next time, return itself

+						fBufferedContext = nextTokenType;

+//						fBufferedText = new StringBuffer(yytext());

+						fBufferedStart = yychar;

+						fBufferedLength = yylength();

+					}

+				}

+			}

+		}

+

+		if (context != null) {

+			if (context == UNDEFINED) {

+				context = CSS_UNKNOWN;

+			}

+			return fRegionFactory.createRegion(context, start, textLength, length);

+		} else {

+			return null;

+		}

+  	}

+

+	/* user method */

+	/* for standalone use */

+  	public final List parseText() throws IOException {

+  		List tokens = new ArrayList();

+

+  		CSSTextToken token;

+		for (String kind = primGetNextToken(); kind != null; kind = primGetNextToken()) {

+			token = new CSSTextToken();

+			token.kind = kind;  				

+			token.start = yychar;

+			token.length = yylength();

+			token.image = yytext();

+			tokens.add(token);

+		}

+

+  		return tokens;

+  	}

+  	

+  	/* user method */

+  	private boolean canContainSpace(String type) {

+  		if (type == CSS_DELIMITER || type == CSS_RBRACE || type == CSS_DECLARATION_DELIMITER) {

+  			return false;

+  		} else {

+  			return true;

+  		}

+  	}

+

+	/* user method */

+	public final int getOffset() {

+		return yychar;

+	}

+	

+	/* user method */

+	public final boolean isEOF() {

+		return zzAtEOF;

+	}

+

+	/* user method */

+	public void reset(char[] charArray) {

+		reset(new CharArrayReader(charArray), 0);

+	}

+

+	/* user method */

+	public final void reset(java.io.Reader in, int newOffset) {

+		/** the input device */

+		zzReader = in;

+

+		/** the current state of the DFA */

+		zzState = 0;

+

+		/** the current lexical state */

+		zzLexicalState = fInitialState; //YYINITIAL;

+

+		/** this buffer contains the current text to be matched and is

+			the source of the yytext() string */

+		if (zzBuffer.length != fInitialBufferSize) {

+			zzBuffer = new char[fInitialBufferSize];

+		}

+		java.util.Arrays.fill(zzBuffer, (char)0);

+

+		/** the textposition at the last accepting state */

+		zzMarkedPos = 0;

+

+		/** the textposition at the last state to be included in yytext */

+		zzPushbackPos = 0;

+

+		/** the current text position in the buffer */

+		zzCurrentPos = 0;

+

+		/** startRead marks the beginning of the yytext() string in the buffer */

+		zzStartRead = 0;

+

+		/** endRead marks the last character in the buffer, that has been read

+			from input */

+		zzEndRead = 0;

+

+		/** number of newlines encountered up to the start of the matched text */

+		yyline = 0;

+

+		/** the number of characters up to the start of the matched text */

+		yychar = 0;

+

+		/**

+		 * the number of characters from the last newline up to the start of the 

+		 * matched text

+		 */

+		yycolumn = 0; 

+

+		/** 

+		 * yy_atBOL == true <=> the scanner is currently at the beginning of a line

+		 */

+		zzAtBOL = false;

+		

+		/** yy_atEOF == true <=> the scanner has returned a value for EOF */

+		zzAtEOF = false;

+

+		/* user variables */

+		//		fUndefined.delete(0, fUndefined.length());

+	}

+

+	/* user method */

+	public JSPedCSSTokenizer() {

+		super();

+	}

+	

+	private int fJSPPreviousState = fInitialState;

+	private void yyJspBegin(int newstate){

+		fJSPPreviousState = yystate();

+		yybegin(newstate);

+	}

+	private void yyJspEnd(){

+		yybegin(fJSPPreviousState);

+	}

+%}

+

+%state ST_CHARSET_NAME

+%state ST_CHARSET_DELIMITER

+%state ST_IMPORT_URI

+%state ST_IMPORT_MEDIUM

+%state ST_IMPORT_DELIMITER

+%state ST_MEDIA_MEDIUM

+%state ST_MEDIA_DELIMITER

+%state ST_PAGE_PSEUDO_PAGE

+%state ST_PAGE_DELIMITER

+%state ST_FONT_FACE_DELIMITER

+%state ST_SELECTOR

+%state ST_SELECTOR_MODIFIER

+%state ST_SELECTOR_ATTRIBUTE_NAME

+%state ST_SELECTOR_ATTRIBUTE_OPERATOR

+%state ST_SELECTOR_ATTRIBUTE_VALUE

+%state ST_SELECTOR_ATTRIBUTE_END

+%state ST_DECLARATION

+%state ST_DECLARATION_SEPARATOR

+%state ST_DECLARATION_PRE_VALUE

+%state ST_DECLARATION_VALUE

+%state ST_JSP_SCRIPTLET

+%state ST_JSP_DIRECTIVE

+%state ST_JSP_DECLARATION

+%state ST_JSP_EXP

+%state ST_JSP_EL

+%state ST_JSP_COMMENT

+

+

+h = [0-9a-f]

+nonascii = [\u0080-\uffff]

+unicode = \\{h}{1,6}[ \t\r\n\f]?

+escape = {unicode}|\\[ -~\u0080-\uffff]

+nmstart = [_a-zA-Z-]|{nonascii}|{escape}

+nmchar = [_a-zA-Z0-9-]|{nonascii}|{escape}

+string1 = \"([\t !#$%&(-~]|\\{nl}|\'|{nonascii}|{escape})*\"

+string2 = \'([\t !#$%&(-~]|\\{nl}|\"|{nonascii}|{escape})*\'

+

+ident = {nmstart}{nmchar}*

+name = {nmchar}+

+num = [+-]?([0-9]+|[0-9]*"."[0-9]+)

+string = {string1}|{string2}

+url = ([ !#$%&*-~]|{nonascii}|{escape})*

+s = [ \t\r\n\f]

+w = {s}*

+nl = \n|\r\n|\r|\f

+range = \?{1,6}|{h}(\?{0,5}|{h}(\?{0,4}|{h}(\?{0,3}|{h}(\?{0,2}|{h}(\??|{h})))))

+

+hash = "#"{name}

+uri = ("url("{w}{string}{w}")"|"url("{w}{url}{w}")")

+function = {ident}"("

+unicode_range = "U"\+[0-9a-fA-F?]{1,6}("-"[0-9a-fA-F?]{1,6})?

+

+SS = [\x20\x09\x0D\x0A]

+jspstart = "<"{SS}*"%"{SS}*

+jspend = "%"{SS}*">"

+elstart = "$"{SS}*"{"

+elend = "}"

+

+%%

+

+

+

+<YYINITIAL> {

+ {jspstart}          {yyJspBegin(ST_JSP_SCRIPTLET);  return CSS_JSP_SCRIPTLET;}

+ {elstart}          {yyJspBegin(ST_JSP_EL);  return CSS_JSP_EL;}

+}

+

+<ST_JSP_SCRIPTLET> {

+ "@"	{yybegin(ST_JSP_DIRECTIVE); return CSS_JSP_DIRECTIVE;}

+ "="	{yybegin(ST_JSP_EXP); return CSS_JSP_EXP;}

+ "!"	{yybegin(ST_JSP_DECLARATION); return CSS_JSP_DECL;}

+ {jspend} {yyJspEnd();  return CSS_JSP_END;}

+ "--" { yybegin(ST_JSP_COMMENT); return CSS_JSP_COMMENT;}

+}

+

+/* override global "}" */

+<ST_JSP_EL> {

+ {elend} {yyJspEnd(); return CSS_EL_END; }

+}

+

+<ST_JSP_DIRECTIVE, ST_JSP_EXP, ST_JSP_DECLARATION> {

+ {jspend} {yyJspEnd();  return CSS_JSP_END;}

+}

+

+<ST_JSP_COMMENT> {

+ -+-{jspend} { yyJspEnd(); return CSS_JSP_COMMENT_END; }

+ "}"         { return UNDEFINED; }

+}

+

+

+/*

+ * *** global ***

+ */

+

+{s}+ { return CSS_S; }

+"<!--" { return CSS_CDO; }

+"-->" { return CSS_CDC; }

+"}" { yybegin(YYINITIAL); return CSS_RBRACE; }

+\/\*[^*]*\*+([^/*][^*]*\*+)*\/ { return CSS_COMMENT; }

+//\<\%--[^-}]*[}]*[^}]*-+-\%\> { return CSS_COMMENT; }

+

+

+//<YYINITIAL> {

+//	"@import" {	yybegin(ST_IMPORT_URI); return CSS_IMPORT; }

+//}

+

+/*

+ * *** charset rule ***

+ * CHARSET_SYM S* STRING S* ';'

+ */

+

+"@charset" { yybegin(ST_CHARSET_NAME); return CSS_CHARSET; }

+

+<ST_CHARSET_NAME> {

+	{string} { yybegin(ST_CHARSET_DELIMITER); return CSS_STRING; }

+}

+

+<ST_CHARSET_DELIMITER> {

+	";" { yybegin(YYINITIAL); return CSS_DELIMITER; }

+}

+

+/*

+ * *** import rule ***

+ * IMPORT_SYM S* [STRING|URI] S* [ medium [ COMMA S* medium]* ]? ';' S*

+ */

+

+"@import" { yybegin(ST_IMPORT_URI); return CSS_IMPORT; }

+

+<ST_IMPORT_URI> {

+	{string} { yybegin(ST_IMPORT_MEDIUM); return CSS_STRING; }

+	//	"url("{w}{string}{w}")" { yybegin(ST_IMPORT_MEDIUM); return CSS_URI; }

+	//	"url("{w}{url}{w}")" { yybegin(ST_IMPORT_MEDIUM); return CSS_URI; }

+	{uri} { yybegin(ST_IMPORT_MEDIUM); return CSS_URI; }

+	";" { yybegin(YYINITIAL); return CSS_DELIMITER; }

+}

+

+<ST_IMPORT_MEDIUM> {

+	{ident} { yybegin(ST_IMPORT_DELIMITER); return CSS_MEDIUM; }

+	";" { yybegin(YYINITIAL); return CSS_DELIMITER; }

+}

+

+<ST_IMPORT_DELIMITER> {

+	";" { yybegin(YYINITIAL); return CSS_DELIMITER; }

+	"," { yybegin(ST_IMPORT_MEDIUM); return CSS_MEDIA_SEPARATOR; }

+}

+

+/*

+ * *** media rule ***

+ * MEDIA_SYM S* medium [ COMMA S* medium ]* LBRACE S* ruleset* '}' S*

+ */

+

+"@media" { yybegin(ST_MEDIA_MEDIUM); return CSS_MEDIA; }

+

+/* 

+ * medium

+ * IDENT S*

+ */

+<ST_MEDIA_MEDIUM> {

+	{ident} { yybegin(ST_MEDIA_DELIMITER); return CSS_MEDIUM; }

+}

+

+<ST_MEDIA_DELIMITER> {

+	"{" { yybegin(YYINITIAL); return CSS_LBRACE; }

+	"," { yybegin(ST_MEDIA_MEDIUM); return CSS_MEDIA_SEPARATOR; }

+}

+

+/*

+ * *** page rule **

+ * PAGE_SYM S* pseudo_page? S* LBRACE S* declaration [ ';' S* declaration ]* '}' S*

+ */

+

+"@page" { yybegin(ST_PAGE_PSEUDO_PAGE); return CSS_PAGE; }

+ 

+/*

+ * pseudo_page

+ * ':' IDENT

+ */

+

+<ST_PAGE_PSEUDO_PAGE> {

+	":"?{ident} { yybegin(ST_PAGE_DELIMITER); return CSS_PAGE_SELECTOR; }

+	"{" { yybegin(ST_DECLARATION); return CSS_LBRACE; }

+}

+

+<ST_PAGE_DELIMITER> {

+	"{" { yybegin(ST_DECLARATION); return CSS_LBRACE; }

+}

+

+/*

+ * font-face

+ * FONT_FACE_SYM S* '{' S* declaration [ ';' S* declaration '* '}' S*

+ */

+

+"@font-face" { yybegin(ST_FONT_FACE_DELIMITER); return CSS_FONT_FACE; }

+

+<ST_FONT_FACE_DELIMITER> {

+	"{" { yybegin(ST_DECLARATION); return CSS_LBRACE; }

+}

+

+/*

+ * selector

+ * simple_selector [ combinator simple_selector ]*

+ */

+

+/*

+ * simple_selector

+ * element_name [ HASH | class | attrib | pseudo ]* | [ HASH | class | attrib | pseudo ]+

+ */

+

+<YYINITIAL, ST_SELECTOR_MODIFIER, ST_SELECTOR> {

+	"*" { yybegin(ST_SELECTOR_MODIFIER); return CSS_SELECTOR_UNIVERSAL; }

+	{hash} { yybegin(ST_SELECTOR_MODIFIER); return CSS_SELECTOR_ID; }

+//	":"{ident} { yybegin(ST_SELECTOR_MODIFIER); return CSS_SELECTOR_PSEUDO; }

+	":"{ident}("("{s}*{ident}{s}*")")? { yybegin(ST_SELECTOR_MODIFIER); return CSS_SELECTOR_PSEUDO; }

+	"."{name} { yybegin(ST_SELECTOR_MODIFIER); return CSS_SELECTOR_CLASS; }

+	"[" { yybegin(ST_SELECTOR_ATTRIBUTE_NAME); return CSS_SELECTOR_ATTRIBUTE_START; }

+}

+

+<YYINITIAL, ST_SELECTOR> {

+	{ident} { yybegin(ST_SELECTOR_MODIFIER); return CSS_SELECTOR_ELEMENT_NAME; }

+}

+

+<ST_SELECTOR_MODIFIER> {

+	"," { yybegin(ST_SELECTOR); return CSS_SELECTOR_SEPARATOR; }

+	// using LOOKAHEAD

+	{s}+/[^+>\{] { yybegin(ST_SELECTOR); return CSS_SELECTOR_COMBINATOR; }

+	"+"|">" { yybegin(ST_SELECTOR); return CSS_SELECTOR_COMBINATOR; }

+	"{" { yybegin(ST_DECLARATION); return CSS_LBRACE; }

+}

+

+/*

+ * attrib

+ * '[' S* IDENT S* [ [ '=' | INCLUDES | DASHMATCH ] S* [ IDENT | STRING ] S* ]? ']'

+ */

+

+<ST_SELECTOR_ATTRIBUTE_NAME> {

+	{ident} { yybegin(ST_SELECTOR_ATTRIBUTE_OPERATOR); return CSS_SELECTOR_ATTRIBUTE_NAME; }

+}

+

+<ST_SELECTOR_ATTRIBUTE_OPERATOR> {

+	"="|"~="|"|=" { yybegin(ST_SELECTOR_ATTRIBUTE_VALUE); return CSS_SELECTOR_ATTRIBUTE_OPERATOR; }

+	"]" { yybegin(ST_SELECTOR_MODIFIER); return CSS_SELECTOR_ATTRIBUTE_END; }

+}

+

+<ST_SELECTOR_ATTRIBUTE_VALUE> {

+	{ident}|{string} { yybegin(ST_SELECTOR_ATTRIBUTE_END); return CSS_SELECTOR_ATTRIBUTE_VALUE; }

+}

+

+<ST_SELECTOR_ATTRIBUTE_END> {

+	"]" { yybegin(ST_SELECTOR_MODIFIER); return CSS_SELECTOR_ATTRIBUTE_END; }

+}

+

+/*

+ * declaration

+ * property ':' S* expr prio? | // empty //

+ */

+

+<ST_DECLARATION> {

+	{ident} { yybegin(ST_DECLARATION_SEPARATOR); return CSS_DECLARATION_PROPERTY; }

+    {jspstart}          {yyJspBegin(ST_JSP_SCRIPTLET);  return CSS_JSP_SCRIPTLET;}

+    {elstart}          {yyJspBegin(ST_JSP_EL);  return CSS_JSP_EL;}

+}

+

+<ST_DECLARATION_SEPARATOR> {

+	":" { yybegin(ST_DECLARATION_PRE_VALUE); return CSS_DECLARATION_SEPARATOR; }

+    {jspstart}          {yyJspBegin(ST_JSP_SCRIPTLET);  return CSS_JSP_SCRIPTLET;}

+    {elstart}          {yyJspBegin(ST_JSP_EL);  return CSS_JSP_EL;}    

+}

+

+<ST_DECLARATION_PRE_VALUE, ST_DECLARATION_VALUE> {

+	"!"{s}*"important" { yybegin(ST_DECLARATION_VALUE); return CSS_DECLARATION_VALUE_IMPORTANT; }

+	{ident} { yybegin(ST_DECLARATION_VALUE); return CSS_DECLARATION_VALUE_IDENT; }

+	")" { yybegin(ST_DECLARATION_VALUE); return CSS_DECLARATION_VALUE_PARENTHESIS_CLOSE; }

+	{num}{ident} { yybegin(ST_DECLARATION_VALUE); return CSS_DECLARATION_VALUE_DIMENSION; }

+	{num}"%" { yybegin(ST_DECLARATION_VALUE); return CSS_DECLARATION_VALUE_PERCENTAGE; }

+	{num} { yybegin(ST_DECLARATION_VALUE); return CSS_DECLARATION_VALUE_NUMBER; }

+	{function} { yybegin(ST_DECLARATION_VALUE); return CSS_DECLARATION_VALUE_FUNCTION; }

+	{string} { yybegin(ST_DECLARATION_VALUE); return CSS_DECLARATION_VALUE_STRING; }

+	{uri} { yybegin(ST_DECLARATION_VALUE); return CSS_DECLARATION_VALUE_URI; }

+	"#"{name} { yybegin(ST_DECLARATION_VALUE); return CSS_DECLARATION_VALUE_HASH; }

+	{unicode_range} { yybegin(ST_DECLARATION_VALUE); return CSS_DECLARATION_VALUE_UNICODE_RANGE; }

+	[,/] { yybegin(ST_DECLARATION_VALUE); return CSS_DECLARATION_VALUE_OPERATOR; }

+    {jspstart}          {yyJspBegin(ST_JSP_SCRIPTLET);  return CSS_JSP_SCRIPTLET;}

+    {elstart}          {yyJspBegin(ST_JSP_EL);  return CSS_JSP_EL;}    

+}

+

+<ST_DECLARATION_VALUE> {

+	{s}+/[^;}] { return CSS_DECLARATION_VALUE_S; }

+    {jspstart}          {yyJspBegin(ST_JSP_SCRIPTLET);  return CSS_JSP_SCRIPTLET;}

+    {elstart}          {yyJspBegin(ST_JSP_EL);  return CSS_JSP_EL;}

+}

+

+<ST_DECLARATION, ST_DECLARATION_SEPARATOR, ST_DECLARATION_PRE_VALUE, ST_DECLARATION_VALUE> {

+	";" { yybegin(ST_DECLARATION); return CSS_DECLARATION_DELIMITER; }

+	//	"}" { yybegin(YYINITIAL); return CSS_RBRACE; }

+}

+

+

+//<YYINITIAL, ST_IMPORT_URI, ST_IMPORT_MEDIUM, ST_IMPORT_DELIMITER> {

+//	\/\*[^*]*\*+([^/*][^*]*\*+)*\/ { return CSS_COMMENT; }

+//	{s}+ { return CSS_S; }

+//	. { return UNDEFINED; }

+//}

+

+//<YYINITIAL, ST_IMPORT_URI, ST_IMPORT_MEDIUM, ST_IMPORT_DELIMITER> {

+//	[^ \t\r\n\f]+ { return CSS_UNKNOWN; }

+//}

+

+

+

+

+

+. {

+	return UNDEFINED;

+}

diff --git a/bundles/org.eclipse.jst.jsp.core/DevTimeSupport/HeadParsers/JSPHeadTokenizer.jFlex b/bundles/org.eclipse.jst.jsp.core/DevTimeSupport/HeadParsers/JSPHeadTokenizer.jFlex
new file mode 100644
index 0000000..9cfce86
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/DevTimeSupport/HeadParsers/JSPHeadTokenizer.jFlex
@@ -0,0 +1,304 @@
+/*******************************************************************************

+ * Copyright (c) 2005, 2008 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

+ *******************************************************************************/

+/*nlsXXX*/

+package org.eclipse.jst.jsp.core.internal.contenttype;

+import java.io.IOException;

+import java.io.Reader;

+import java.util.Arrays;

+

+import org.eclipse.wst.xml.core.internal.contenttype.EncodingParserConstants;

+import org.eclipse.wst.xml.core.internal.contenttype.XMLHeadTokenizerConstants;

+

+%%

+

+%{

+

+

+

+

+        private boolean hasMore = true;

+        private final static int MAX_TO_SCAN = 8000;

+        StringBuffer string = new StringBuffer();

+        // state stack for easier state handling

+        private IntStack fStateStack = new IntStack();

+        private String valueText = null;

+        private boolean isXHTML;

+        private boolean isWML;

+

+

+        public JSPHeadTokenizer() {

+                super();

+        }

+

+          public void reset (Reader in) {

+                /* the input device */

+                zzReader = in;

+

+                /* the current state of the DFA */

+                zzState = 0;

+

+                /* the current lexical state */

+                zzLexicalState = YYINITIAL;

+

+                /* this buffer contains the current text to be matched and is

+                 the source of the yytext() string */

+                Arrays.fill(zzBuffer, (char)0);

+

+                /* the textposition at the last accepting state */

+                zzMarkedPos = 0;

+

+                /* the textposition at the last state to be included in yytext */

+                //zzPushbackPos = 0;

+

+                /* the current text position in the buffer */

+                zzCurrentPos = 0;

+

+                /* startRead marks the beginning of the yytext() string in the buffer */

+                zzStartRead = 0;

+

+                /**

+                 * endRead marks the last character in the buffer, that has been read

+                 * from input

+                 */

+                zzEndRead = 0;

+

+                /* number of newlines encountered up to the start of the matched text */

+                //yyline = 0;

+

+                /* the number of characters up to the start of the matched text */

+                yychar = 0;

+

+                /**

+                 * the number of characters from the last newline up to the start

+                 * of the matched text

+                 */

+                //yycolumn = 0;

+

+                /**

+                 * yy_atBOL == true <=> the scanner is currently at the beginning

+                 * of a line

+                 */

+                zzAtBOL = true;

+

+                /* yy_atEOF == true <=> the scanner has returned a value for EOF */

+                zzAtEOF = false;

+

+                /* denotes if the user-EOF-code has already been executed */

+                zzEOFDone = false;

+

+

+                fStateStack.clear();

+

+                hasMore = true;

+                isXHTML=false;

+                isWML=false;

+

+

+        }

+

+

+        public final HeadParserToken getNextToken() throws IOException, Exception {

+                String context = null;

+                context = primGetNextToken();

+                HeadParserToken result = null;

+                if (valueText != null) {

+                        result = createToken(context, yychar, valueText);

+                        valueText = null;

+                } else {

+                        result = createToken(context, yychar, yytext());

+                }

+                return result;

+        }

+

+        public final boolean hasMoreTokens() {

+                return hasMore && yychar < MAX_TO_SCAN;

+        }

+        private void pushCurrentState() {

+                fStateStack.push(yystate());

+

+        }

+ 

+        private void popState() {

+                yybegin(fStateStack.pop());

+        }

+        private HeadParserToken createToken(String context, int start, String text) {

+                return new HeadParserToken(context, start, text);

+        }

+        

+        public boolean isXHTML() {

+            return isXHTML;

+        }

+        public boolean isWML() {

+            return isWML;

+        }        

+

+%}

+

+%eof{

+        hasMore=false;

+%eof}

+

+%public

+%class JSPHeadTokenizer

+%function primGetNextToken

+%type String

+%char

+%unicode

+%ignorecase

+//%debug

+%switch

+%buffer 8192

+%scanerror java.lang.Exception

+

+

+UTF16BE = \xFE\xFF

+UTF16LE = \xFF\xFE

+UTF83ByteBOM = \xEF\xBB\xBF

+

+// SpaceChar = [\x20\x09]

+

+

+// [3] S ::= (0x20 | 0x9 | 0xD | 0xA)+

+S = [\x20\x09\x0D\x0A]

+

+//BeginAttributeeValue = {S}* \= {S}*

+

+LineTerminator = \r|\n

+

+

+Z = (\x00)?

+S_UTF = {Z}{S}{Z}

+BeginAttributeValueUTF = {S_UTF}* \= {S_UTF}*

+

+%state ST_XMLDecl

+%state ST_PAGE_DIRECTIVE

+%state QuotedAttributeValue

+%state DQ_STRING

+%state SQ_STRING

+%state UnDelimitedString

+

+%%

+

+

+<YYINITIAL>

+{

+         // force to start at beginning of line (^) and at beginning of file (yychar == 0)

+        ^ {UTF16BE}           {if (yychar == 0 ) {hasMore = false; return EncodingParserConstants.UTF16BE;}}

+        ^ {UTF16LE}           {if (yychar == 0 ) {hasMore = false; return EncodingParserConstants.UTF16LE;}}

+        ^ {UTF83ByteBOM}       {if (yychar == 0 ) {hasMore = false; return EncodingParserConstants.UTF83ByteBOM;}}

+        

+        // force to be started on first line, but we do allow preceeding spaces

+		^ {S_UTF}* ({Z}<{Z}\?{Z}x{Z}m{Z}l{Z}){S_UTF}+ {if (yychar == 0 ) {yybegin(ST_XMLDecl); return XMLHeadTokenizerConstants.XMLDeclStart;}}

+

+

+        // following are some simply rules to identify JSP content as "XHTML"

+        // see http://www.rfc-editor.org/rfc/rfc3236.txt

+		{Z}<{Z}\!{Z}D{Z}O{Z}C{Z}T{Z}Y{Z}P{Z}E{Z} {S_UTF}* {Z}h{Z}t{Z}m{Z}l{Z} {S_UTF}* {Z}P{Z}U{Z}B{Z}L{Z}I{Z}C{Z} .* {Z}\/{Z}\/{Z}D{Z}T{Z}D{Z}{S_UTF}{Z}X{Z}H{Z}T{Z}M{Z}L{Z}                {isXHTML = true;}

+		{Z}<{Z}h{Z}t{Z}m{Z}l{Z} {S_UTF}* {Z}x{Z}m{Z}l{Z}n{Z}s{Z} {S_UTF}* {Z}\={Z} {S_UTF}* (({Z}\"{Z}) | ({Z}\'{Z})) {Z}h{Z}t{Z}t{Z}p{Z}:{Z}\/{Z}\/{Z}w{Z}w{Z}w{Z}\.{Z}w{Z}3{Z}\.{Z}o{Z}r{Z}g{Z}\/{Z}1{Z}9{Z}9{Z}9{Z}\/{Z}x{Z}h{Z}t{Z}m{Z}l{Z}     {isXHTML = true;}

+         // another case that's part of the "HTML family" is WML 1.0 (WML 2.0 is part of XHTML)

+		{Z}<{Z}\!{Z}D{Z}O{Z}C{Z}T{Z}Y{Z}P{Z}E{Z} {S_UTF}* {Z}w{Z}m{Z}l{Z} {S_UTF}* {Z}P{Z}U{Z}B{Z}L{Z}I{Z}C{Z} .* {Z}\/{Z}\/{Z}D{Z}T{Z}D {S}{Z}W{Z}M{Z}L{Z}                   {isWML = true;}

+

+		{Z}<{Z}%{Z} {S_UTF}* {Z}@{Z} {S_UTF}* (({Z}p{Z}a{Z}g{Z}e{Z})|({Z}t{Z}a{Z}g{Z})) {S_UTF}+   {yybegin(ST_PAGE_DIRECTIVE); return JSPHeadTokenizerConstants.PageDirectiveStart;}

+		(({Z}<{Z}j{Z}s{Z}p{Z}:{Z}d{Z}i{Z}r{Z}e{Z}c{Z}t{Z}i{Z}v{Z}e{Z}\.{Z}p{Z}a{Z}g{Z}e{Z})|({Z}<{Z}j{Z}s{Z}p{Z}:{Z}d{Z}i{Z}r{Z}e{Z}c{Z}t{Z}i{Z}v{Z}e{Z}\.{Z}t{Z}a{Z}g{Z})) {S_UTF}+           {yybegin(ST_PAGE_DIRECTIVE); return JSPHeadTokenizerConstants.PageDirectiveStart;}

+

+}

+

+<ST_XMLDecl>

+{

+        ({Z}v{Z}e{Z}r{Z}s{Z}i{Z}o{Z}n{Z}) {BeginAttributeValueUTF} {pushCurrentState(); yybegin(QuotedAttributeValue); return XMLHeadTokenizerConstants.XMLDeclVersion;}

+        ({Z}e{Z}n{Z}c{Z}o{Z}d{Z}i{Z}n{Z}g{Z}) {BeginAttributeValueUTF} {pushCurrentState(); yybegin(QuotedAttributeValue); return XMLHeadTokenizerConstants.XMLDelEncoding;}

+        // note the "forced end" (via 'hasMore=false') once the end of XML Declaration found

+        // This is since non-ascii chars may follow and may cause IOExceptions which would not occur once stream is

+        // read with incorrect encoding (such as if platform encoding is in effect until true encoding detected).

+        // BUT, the hasMore=false was removed for this JSP case (probably still ok for pure XML) because

+        // in a JSP, we must parse past xmlDecl to get at JSP page directive.

+        // We'll assume all chars in this area are "readable" as is.

+		{S_UTF}* {Z}\?{Z}>{Z}    {yybegin(YYINITIAL); return XMLHeadTokenizerConstants.XMLDeclEnd;}

+}

+

+<ST_PAGE_DIRECTIVE>

+{

+//  removed 'language' since it really can be handled seperately from encoding, but may add it back later for simple re-use.

+		{Z}l{Z}a{Z}n{Z}g{Z}u{Z}a{Z}g{Z}e{Z}     {BeginAttributeValueUTF} {pushCurrentState(); yybegin(QuotedAttributeValue); return JSPHeadTokenizerConstants.PageLanguage;}

+        {Z}c{Z}o{Z}n{Z}t{Z}e{Z}n{Z}t{Z}T{Z}y{Z}p{Z}e{Z} {BeginAttributeValueUTF}  {pushCurrentState(); yybegin(QuotedAttributeValue); return JSPHeadTokenizerConstants.PageContentType;}

+        {Z}p{Z}a{Z}g{Z}e{Z}E{Z}n{Z}c{Z}o{Z}d{Z}i{Z}n{Z}g{Z} {BeginAttributeValueUTF} {pushCurrentState(); yybegin(QuotedAttributeValue); return JSPHeadTokenizerConstants.PageEncoding;}

+        // note the "forced end" (via 'hasMore=false') once the end of XML Declaration found

+        // This is since non-ascii chars may follow and may cause IOExceptions which would not occur once stream is

+        // read in correct encoding.

+

+        // https://w3.opensource.ibm.com/bugzilla/show_bug.cgi?id=4205 demonstrates how we need to keep parsing,

+        // even if come to end of one page directive, so hasMore=false was removed from these rules.

+		{Z}%{Z}>{Z}    { yybegin(YYINITIAL);  return JSPHeadTokenizerConstants.PageDirectiveEnd;}

+        {Z}\/{Z}>{Z}    { yybegin(YYINITIAL); return JSPHeadTokenizerConstants.PageDirectiveEnd;}

+}

+

+

+<QuotedAttributeValue>

+{

+        {Z}\"{Z}                      { yybegin(DQ_STRING); string.setLength(0); }

+        {Z}\'{Z}                      { yybegin(SQ_STRING); string.setLength(0); }

+        // in this state, anything other than a space character can start an undelimited string

+		{S_UTF}*.           { yypushback(1); yybegin(UnDelimitedString); string.setLength(0);}

+}

+

+

+<DQ_STRING>

+{

+

+        {Z}\"{Z}			{ popState(); valueText = string.toString(); return EncodingParserConstants.StringValue; }

+        {Z}{LineTerminator}{Z}        { yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}

+        {Z}\?{Z}>{Z}	{ yypushback(yylength()); popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}

+        {Z}<{Z}				{ yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}

+		[^\x00]			{ string.append( yytext() ); }

+        {Z}%{Z}>{Z}		{ yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}

+

+

+}

+

+<SQ_STRING>

+{

+

+        {Z}\'{Z}                      { popState(); valueText = string.toString(); return EncodingParserConstants.StringValue;}

+		{Z}{LineTerminator}{Z}        { yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}

+        {Z}%{Z}>{Z}               { yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}

+        {Z}<{Z}                     { yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}

+		// Skip over the single-byte 0s

+		[^\x00]			{ string.append( yytext() ); }

+        {Z}%{Z}>{Z}                    { yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}

+

+

+}

+

+<UnDelimitedString>

+{

+

+

+        {S_UTF}                     { yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.UnDelimitedStringValue; }

+        {Z}{LineTerminator}{Z}        { yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}

+        {Z}\?{Z}>{Z}                   { yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}

+        {Z}<{Z}                     { yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}

+        // these are a bit special, since we started an undelimit string, but found a quote ... probably indicates a missing beginning quote

+        {Z}\'{Z}                      { yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTermintatedUnDelimitedStringValue;}

+        {Z}\"{Z}                      { yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTermintatedUnDelimitedStringValue;}        

+

+		[^\x00]			{ string.append( yytext() ); }

+        {Z}%{Z}>{Z}                    { yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}

+

+}

+

+// The "match anything" rule should always be in effect except for when looking for end of string

+// (That is, remember to update state list if/when new states added)

+.|\n	{if(yychar > MAX_TO_SCAN) {hasMore=false; return EncodingParserConstants.MAX_CHARS_REACHED;}}

+

+// this rule always in effect

+<<EOF>>         {hasMore = false; return EncodingParserConstants.EOF;}

+

+

diff --git a/bundles/org.eclipse.jst.jsp.core/DevTimeSupport/buildParser.xml b/bundles/org.eclipse.jst.jsp.core/DevTimeSupport/buildParser.xml
new file mode 100644
index 0000000..2ebe182
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/DevTimeSupport/buildParser.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="tokenizer" default="HeadTokenizer">
+	
+	<!-- Note: for Eclipse env., the JFlex 1.4 jar should be added 
+	to the ant global entries  -->
+	<taskdef classname="JFlex.anttask.JFlexTask" name="jflex" />
+		
+	<target name="init">
+		<property name="src.file" value="JSPHeadTokenizer.jFlex"/>			
+		<property name="src.dir" value="HeadParsers"/>
+		<property name="dest.dir" value="../src"/>
+		<!-- touch causes to always build, remove for real 'make' behavior -->
+		<touch file="${src.dir}/${src.file}"/>
+					
+	</target>
+
+	<target name="HeadTokenizer" depends="init">
+		<antcall target="run-jflex"/>
+	</target>
+
+	<target name="run-jflex" depends="init">
+		<jflex
+	    	file="${src.dir}/${src.file}"
+	    	destdir="${dest.dir}"
+			verbose="true"
+			nobak="true"
+			time="on"
+	    />
+	</target>
+	
+
+</project>
\ No newline at end of file
diff --git a/bundles/org.eclipse.jst.jsp.core/META-INF/MANIFEST.MF b/bundles/org.eclipse.jst.jsp.core/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..b0ce616
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/META-INF/MANIFEST.MF
@@ -0,0 +1,63 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %pluginName
+Bundle-SymbolicName: org.eclipse.jst.jsp.core; singleton:=true
+Bundle-Version: 1.2.308.qualifier
+Bundle-Activator: org.eclipse.jst.jsp.core.internal.JSPCorePlugin
+Bundle-Vendor: %providerName
+Bundle-Localization: plugin
+Export-Package: org.eclipse.jst.jsp.core.internal;x-friends:="org.eclipse.jst.jsp.ui",
+ org.eclipse.jst.jsp.core.internal.contentmodel;x-friends:="org.eclipse.jst.jsp.ui",
+ org.eclipse.jst.jsp.core.internal.contentmodel.tld;x-friends:="org.eclipse.jst.jsp.ui",
+ org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional;x-friends:="org.eclipse.jst.jsp.ui",
+ org.eclipse.jst.jsp.core.internal.contentproperties;x-friends:="org.eclipse.jst.jsp.ui",
+ org.eclipse.jst.jsp.core.internal.contenttype;x-friends:="org.eclipse.jst.jsp.ui",
+ org.eclipse.jst.jsp.core.internal.document;x-friends:="org.eclipse.jst.jsp.ui",
+ org.eclipse.jst.jsp.core.internal.domdocument;x-friends:="org.eclipse.jst.jsp.ui",
+ org.eclipse.jst.jsp.core.internal.encoding;x-friends:="org.eclipse.jst.jsp.ui",
+ org.eclipse.jst.jsp.core.internal.java;x-friends:="org.eclipse.jst.jsp.ui",
+ org.eclipse.jst.jsp.core.internal.java.jspel;x-friends:="org.eclipse.jst.jsp.ui",
+ org.eclipse.jst.jsp.core.internal.java.search;x-friends:="org.eclipse.jst.jsp.ui",
+ org.eclipse.jst.jsp.core.internal.modelhandler;x-friends:="org.eclipse.jst.jsp.ui",
+ org.eclipse.jst.jsp.core.internal.modelquery;x-friends:="org.eclipse.jst.jsp.ui",
+ org.eclipse.jst.jsp.core.internal.parser;x-friends:="org.eclipse.jst.jsp.ui",
+ org.eclipse.jst.jsp.core.internal.parser.internal;x-friends:="org.eclipse.jst.jsp.ui",
+ org.eclipse.jst.jsp.core.internal.preferences;x-friends:="org.eclipse.jst.jsp.ui",
+ org.eclipse.jst.jsp.core.internal.provisional;x-friends:="org.eclipse.jst.jsp.ui",
+ org.eclipse.jst.jsp.core.internal.provisional.contenttype;x-friends:="org.eclipse.jst.jsp.ui",
+ org.eclipse.jst.jsp.core.internal.provisional.text;x-friends:="org.eclipse.jst.jsp.ui",
+ org.eclipse.jst.jsp.core.internal.regions;x-friends:="org.eclipse.jst.jsp.ui",
+ org.eclipse.jst.jsp.core.internal.taglib;x-friends:="org.eclipse.jst.jsp.ui",
+ org.eclipse.jst.jsp.core.internal.tasks;x-friends:="org.eclipse.jst.jsp.ui",
+ org.eclipse.jst.jsp.core.internal.text;x-friends:="org.eclipse.jst.jsp.ui",
+ org.eclipse.jst.jsp.core.internal.util;x-friends:="org.eclipse.jst.jsp.ui",
+ org.eclipse.jst.jsp.core.internal.validation;x-friends:="org.eclipse.jst.jsp.ui",
+ org.eclipse.jst.jsp.core.jspel,
+ org.eclipse.jst.jsp.core.taglib,
+ org.eclipse.jst.jsp.core.text,
+ org.eclipse.jst.jsp.css.core.internal.contentmodel;x-internal:=true,
+ org.eclipse.jst.jsp.css.core.internal.contenttype;x-internal:=true,
+ org.eclipse.jst.jsp.css.core.internal.document;x-internal:=true,
+ org.eclipse.jst.jsp.css.core.internal.encoding;x-internal:=true,
+ org.eclipse.jst.jsp.css.core.internal.modelhandler;x-friends:="org.eclipse.jst.jsp.ui",
+ org.eclipse.jst.jsp.css.core.internal.parser;x-internal:=true,
+ org.eclipse.jst.jsp.css.core.internal.parserz;x-internal:=true
+Import-Package: com.ibm.icu.text;version="3.8",
+ com.ibm.icu.util;version="3.8",
+ javax.servlet.jsp.tagext;version="[2.0.0,2.2.0)"
+Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.5.0,4.0.0)",
+ org.eclipse.core.resources;bundle-version="[3.5.0,4.0.0)",
+ org.eclipse.core.jobs;bundle-version="[3.5.0,4.0.0)",
+ org.eclipse.core.filebuffers;bundle-version="[3.5.0,4.0.0)",
+ org.eclipse.jdt.core;bundle-version="[3.5.0,3.9.0)",
+ org.eclipse.wst.common.uriresolver;bundle-version="[1.1.301,1.2.0)",
+ org.eclipse.wst.sse.core;bundle-version="[1.1.500,1.2.0)",
+ org.eclipse.wst.xml.core;bundle-version="[1.1.500,1.2.0)",
+ org.eclipse.wst.css.core;bundle-version="[1.1.300,1.2.0)",
+ org.eclipse.wst.html.core;bundle-version="[1.1.400,1.2.0)",
+ org.eclipse.wst.validation;bundle-version="[1.2.100,1.3.0)",
+ org.eclipse.wst.common.project.facet.core;bundle-version="[1.4.0,2.0.0)";resolution:=optional,
+ org.eclipse.wst.common.modulecore;bundle-version="[1.1.300,2.0.0)";resolution:=optional,
+ org.eclipse.osgi.services;bundle-version="3.2.0"
+Bundle-ActivationPolicy: lazy; exclude:="org.eclipse.jst.jsp.core.internal.contenttype,org.eclipse.jst.jsp.css.core.internal.contenttype,org.eclipse.jst.jsp.core.internal.provisional.contenttype"
+Bundle-RequiredExecutionEnvironment: J2SE-1.4
diff --git a/bundles/org.eclipse.jst.jsp.core/about.html b/bundles/org.eclipse.jst.jsp.core/about.html
new file mode 100644
index 0000000..2199df3
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/about.html
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
+<HTML>
+
+<head>
+<title>About</title>
+<meta http-equiv=Content-Type content="text/html; charset=ISO-8859-1">
+</head>
+
+<BODY lang="EN-US">
+
+<H3>About This Content</H3>
+
+<P>June, 2008</P>
+
+<H3>License</H3>
+
+<P>The Eclipse Foundation makes available all content in this plug-in 
+("Content"). Unless otherwise indicated below, the Content is provided to you 
+under the terms and conditions of the Eclipse Public License Version 1.0 
+("EPL"). A copy of the EPL is available at
+<A href="http://www.eclipse.org/org/documents/epl-v10.php">http://www.eclipse.org/org/documents/epl-v10.php</A>. 
+For purposes of the EPL, "Program" will mean the Content.</P>
+
+<P>If you did not receive this Content directly from the Eclipse Foundation, the 
+Content is being redistributed by another party ("Redistributor") and different 
+terms and conditions may apply to your use of any object code in the Content. 
+Check the RedistributorÂ’s license that was provided with the Content. If no such 
+license exists, contact the Redistributor. Unless otherwise indicated below, the 
+terms and conditions of the EPL still apply to any source code in the Content 
+and such source code may be obtained at
+<A href="http://www.eclipse.org/">http://www.eclipse.org/</A>.</P>
+
+</BODY>
+</HTML>
diff --git a/bundles/org.eclipse.jst.jsp.core/build.properties b/bundles/org.eclipse.jst.jsp.core/build.properties
new file mode 100644
index 0000000..09a522d
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/build.properties
@@ -0,0 +1,21 @@
+###############################################################################
+# Copyright (c) 2004, 2006 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
+###############################################################################
+bin.includes = plugin.xml,\
+               .options,\
+               plugin.properties,\
+               META-INF/,\
+               .,\
+               about.html
+bin.excludes = @dot/**,\
+               temp.folder/**
+src.includes = DevTimeSupport/,\
+               schema/
+source.. = src/
diff --git a/bundles/org.eclipse.jst.jsp.core/plugin.properties b/bundles/org.eclipse.jst.jsp.core/plugin.properties
new file mode 100644
index 0000000..f63b037
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/plugin.properties
@@ -0,0 +1,33 @@
+###############################################################################
+# 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
+###############################################################################
+providerName=Eclipse Web Tools Platform
+pluginName=Structured Source JSP Model
+Structured_JSP_Document_Factory_Extension.name=Structured JSP Document Factory Extension
+JSP_Content_Type_Extension_Element.name=JSP
+JSP_Tag_Content_Type_Extension_Element.name=JSP Tag Definition
+JSP_TagX_Content_Type_Extension_Element.name=JSP Tag Definition (XML)
+JSP_TLD_Content_Type_Extension_Element.name=Tag Library Descriptor
+JSP_Fragment_Content_Type_Extension_Element.name=JSP Fragment
+JSP_Syntax_Validator.name=JSP Syntax Validator
+JSP_Directive_Validator.name=JSP Directive Validator
+EL_Syntax_Validator.name=EL Syntax Validator
+JSP_Content_Validator.name=JSP Content Validator
+TLDValidator.name=Tag Library Descriptor Validator
+Structured_JSP_Document_Setup_participant.name=Structured JSP Document Setup Participant
+_validationMarker.name=JSP Problem
+_taskMarker.name=JSP Task
+
+extension-point.name.0 = JSP EL Translator
+
+contentTypeCSSJSPName=CSS JSP
+contentTypeCSSJSPFName=CSS JSP Fragment
+
+contentTypeCSSDocumentFactoryName=Content Type CSS JSP document factory extension
diff --git a/bundles/org.eclipse.jst.jsp.core/plugin.xml b/bundles/org.eclipse.jst.jsp.core/plugin.xml
new file mode 100644
index 0000000..315fd6c
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/plugin.xml
@@ -0,0 +1,382 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+<plugin>
+   <extension-point id="elTranslator" name="%extension-point.name.0" schema="schema/eltranslator.exsd"/>
+
+	<extension point="org.eclipse.wst.sse.core.modelHandler">
+		<modelHandler
+			class="org.eclipse.jst.jsp.core.internal.modelhandler.ModelHandlerForJSP"
+			associatedContentTypeId="org.eclipse.jst.jsp.core.jspsource"
+			id="org.eclipse.jst.jsp.core.internal.modelhandler">
+		</modelHandler>
+		<modelHandler
+			class="org.eclipse.jst.jsp.core.internal.modelhandler.ModelHandlerForJSP"
+			associatedContentTypeId="org.eclipse.jst.jsp.core.jspfragmentsource"
+			id="org.eclipse.jst.jsp.core.internal.modelhandler">
+		</modelHandler>
+		<modelHandler
+			class="org.eclipse.jst.jsp.core.internal.modelhandler.ModelHandlerForTag"
+			associatedContentTypeId="org.eclipse.jst.jsp.core.tagsource"
+			id="org.eclipse.jst.jsp.core.internal.modelhandler.tag">
+		</modelHandler>
+	</extension>
+
+	<extension point="org.eclipse.wst.xml.core.documentFactories">
+		<factory
+			type="tld"
+			class="org.eclipse.jst.jsp.core.internal.contentmodel.tld.CMDocumentFactoryTLD">
+		</factory>
+	</extension>
+
+	<extension point="org.eclipse.wst.sse.core.taskscanner">
+		<scanner
+			id="org.eclipse.jst.jsp.core.internal.tasks.JSPFileTaskScanner"
+			class="org.eclipse.jst.jsp.core.internal.tasks.JSPFileTaskScanner:org.eclipse.jst.jsp.core.taskMarker"
+			contentTypeIds="org.eclipse.jst.jsp.core.jspsource" />
+	</extension>
+	<extension
+		id="taskMarker"
+		name="%_taskMarker.name"
+		point="org.eclipse.core.resources.markers">
+      <super type="org.eclipse.core.resources.taskmarker"/>
+		<persistent value="true"/>
+	</extension>
+ <extension
+         id="validationMarker"
+         name="%_validationMarker.name"
+         point="org.eclipse.core.resources.markers">
+      <super type="org.eclipse.wst.validation.problemmarker"/>
+      <persistent value="true"/>
+ </extension>
+
+	<extension
+		point="org.eclipse.core.filebuffers.documentCreation"
+		id="org.eclipse.jst.jsp.core.documentfactories"
+		name="%Structured_JSP_Document_Factory_Extension.name">
+		<factory
+			contentTypeId="org.eclipse.jst.jsp.core.jspsource"
+			class="org.eclipse.wst.sse.core.internal.filebuffers.BasicStructuredDocumentFactory" />
+	</extension>
+	<extension
+		point="org.eclipse.core.filebuffers.documentSetup"
+		id="org.eclipse.jst.jsp.core.documentsetup"
+		name="%Structured_JSP_Document_Setup_participant.name">
+		<participant
+			contentTypeId="org.eclipse.jst.jsp.core.jspsource"
+			class="org.eclipse.jst.jsp.core.internal.contentmodel.TaglibController" />
+	</extension>
+	<extension point="org.eclipse.team.core.fileTypes">
+		<fileTypes
+			type="text"
+			extension="jsp">
+		</fileTypes>
+		<fileTypes
+			type="text"
+			extension="jspf" />
+		<fileTypes
+			type="text"
+			extension="jspx" />
+		<fileTypes
+			type="text"
+			extension="jsf">
+		</fileTypes>
+		<fileTypes
+			type="text"
+			extension="jsv">
+		</fileTypes>
+		<fileTypes
+			type="text"
+			extension="jtpl">
+		</fileTypes>
+		<fileTypes
+			type="text"
+			extension="tld" />
+		<fileTypes
+			type="text"
+			extension="tag" />
+		<fileTypes
+			type="text"
+			extension="tagx" />
+		<fileTypes
+			type="text"
+			extension="tagf" />
+	</extension>
+	<extension point="org.eclipse.wst.sse.core.formatProcessors">
+		<processor
+			class="org.eclipse.wst.html.core.internal.format.HTMLFormatProcessorImpl"
+			contentTypeId="org.eclipse.jst.jsp.core.jspsource">
+		</processor>
+	</extension>
+
+	<extension point="org.eclipse.core.contenttype.contentTypes">
+		<!-- create content type for JSP files -->
+		<content-type
+			file-extensions="jsp,jsv,jtpl,jspx"
+			priority="high"
+			name="%JSP_Content_Type_Extension_Element.name"
+			id="jspsource"
+			base-type="org.eclipse.core.runtime.text"
+			default-charset="ISO-8859-1">
+			<describer
+				class="org.eclipse.jst.jsp.core.internal.contenttype.ContentDescriberForJSP" />
+		</content-type>
+		<!-- create content type for JSP fragment files -->
+		<content-type
+			file-extensions="jspf,jsf"
+			priority="high"
+			name="%JSP_Fragment_Content_Type_Extension_Element.name"
+			id="jspfragmentsource"
+			base-type="org.eclipse.jst.jsp.core.jspsource"
+			default-charset="ISO-8859-1">
+			<describer
+				class="org.eclipse.jst.jsp.core.internal.contenttype.ContentDescriberForJSP" />
+		</content-type>
+		<!-- create content type for JSP 2.0 Tag file types -->
+		<content-type
+			file-extensions="tag,tagx,tagf"
+			priority="high"
+			name="%JSP_Tag_Content_Type_Extension_Element.name"
+			id="tagsource"
+			base-type="org.eclipse.jst.jsp.core.jspsource"
+			default-charset="ISO-8859-1"/>
+		<!-- create content type for .tld files -->
+		<content-type
+			file-extensions="tld"
+			priority="high"
+			name="%JSP_TLD_Content_Type_Extension_Element.name"
+			id="tldsource"
+			base-type="org.eclipse.core.runtime.xml"
+			default-charset="UTF-8">
+			<!-- add the describer so it's properly detected when opened from within .jar files -->
+			<describer class="org.eclipse.core.runtime.content.XMLRootElementContentDescriber">
+				<parameter name="element" value="taglib"/>
+			</describer>
+		</content-type>
+		
+
+  	<!--======================================================================================-->
+	<!-- minimal content-type css jsp support                                                 -->
+	<!--======================================================================================-->
+        <content-type
+			file-extensions="jsp"
+			priority="high"
+			name="%contentTypeCSSJSPName"
+			id="cssjspsource"
+			base-type="org.eclipse.jst.jsp.core.jspsource">
+			<describer
+				class="org.eclipse.jst.jsp.css.core.internal.contenttype.ContentDescriberForJSPedCSS" />
+		</content-type>
+        <content-type
+	        file-extensions="jspf"
+			priority="high"
+			name="%contentTypeCSSJSPFName"
+			id="cssjspfragmentsource"
+			base-type="org.eclipse.jst.jsp.core.cssjspsource">
+			<describer
+				class="org.eclipse.jst.jsp.css.core.internal.contenttype.ContentDescriberForJSPedCSS" />
+		</content-type>
+	</extension>
+
+	<!-- initialize jsp core preferences -->
+	<extension point="org.eclipse.core.runtime.preferences">
+		<initializer
+			class="org.eclipse.jst.jsp.core.internal.preferences.JSPCorePreferenceInitializer" />
+	</extension>
+
+	<!--======================================================================================-->
+	<!-- JSP batch validation                                       						  -->
+	<!--======================================================================================-->
+   <extension id="JSPBatchValidator" name="%JSP_Syntax_Validator.name" point="org.eclipse.wst.validation.validatorV2">
+      <validator
+            build="true"
+            class="org.eclipse.jst.jsp.core.internal.validation.JSPBatchValidator"
+            manual="true"
+            version="1"
+            markerId="org.eclipse.jst.jsp.core.validationMarker"
+            sourceid="org.eclipse.jst.jsp.jspelsourcevalidator, org.eclipse.jst.jsp.ui.internal.validation.jspactionvalidator, org.eclipse.jst.jsp.tldsourcevalidator, org.eclipse.jst.jsp.jspsourcevalidator">
+         <include>
+            <rules>
+	           <projectNature id="org.eclipse.jdt.core.javanature"/>
+            </rules>
+         </include>
+         <include>
+            <rules>
+				<contentType id="org.eclipse.jst.jsp.core.jspsource"/>
+				<!-- needed until bug 181443 is implemented -->
+				<contentType id="org.eclipse.jst.jsp.core.jspfragmentsource"/>
+				<contentType id="org.eclipse.jst.jsp.core.tagsource"/>
+               <fileext
+                     caseSensitive="false"
+                     ext="jsp">
+               </fileext>
+               <fileext
+                     caseSensitive="false"
+                     ext="jspf">
+               </fileext>
+               <fileext
+                     caseSensitive="false"
+                     ext="jsf">
+               </fileext>
+               <fileext
+                     caseSensitive="false"
+                     ext="tag">
+               </fileext>
+               <fileext
+                     caseSensitive="false"
+                     ext="tagf">
+               </fileext>
+               <fileext
+                     caseSensitive="false"
+                     ext="jsv">
+               </fileext>
+               <fileext
+                     caseSensitive="false"
+                     ext="jtpl">
+               </fileext>
+            </rules>
+         </include>
+         <group id="org.eclipse.wst.sse.core.structuredModelGroup"/>
+      </validator>
+   </extension>
+	
+   <extension id="JSPContentValidator" name="%JSP_Content_Validator.name" point="org.eclipse.wst.validation.validatorV2">
+      <validator
+            build="true"
+            class="org.eclipse.jst.jsp.core.internal.validation.JSPContentValidator"
+            manual="true"
+            version="1"
+            markerId="org.eclipse.jst.jsp.core.validationMarker"
+            sourceid="org.eclipse.jst.jsp.ui.internal.validation.markupvalidator, org.eclipse.jst.jsp.ui.internal.validation.htmlsyntaxvalidator">
+         <include>
+            <rules>
+				<contentType id="org.eclipse.jst.jsp.core.jspsource"/>
+				<!-- needed until bug 181443 is implemented -->
+				<contentType id="org.eclipse.jst.jsp.core.jspfragmentsource"/>
+               <fileext
+                     caseSensitive="false"
+                     ext="jsp">
+               </fileext>
+               <fileext
+                     caseSensitive="false"
+                     ext="jspf">
+               </fileext>
+               <fileext
+                     caseSensitive="false"
+                     ext="jsf">
+               </fileext>
+               <fileext
+                     caseSensitive="false"
+                     ext="tag">
+               </fileext>
+               <fileext
+                     caseSensitive="false"
+                     ext="tagf">
+               </fileext>
+               <fileext
+                     caseSensitive="false"
+                     ext="jsv">
+               </fileext>
+               <fileext
+                     caseSensitive="false"
+                     ext="jtpl">
+               </fileext>
+            </rules>
+         </include>
+         <group id="org.eclipse.wst.sse.core.structuredModelGroup"/>
+      </validator>
+   </extension>
+   
+   <extension id="TLDValidator" name="%TLDValidator.name" point="org.eclipse.wst.validation.validatorV2">
+      <validator
+            build="true"
+            class="org.eclipse.jst.jsp.core.internal.validation.TLDValidator"
+            manual="true"
+            version="1"
+            markerId="org.eclipse.jst.jsp.core.validationMarker">
+         <include>
+            <rules>
+				<contentType id="org.eclipse.jst.jsp.core.tldsource"/>
+               <fileext
+                     caseSensitive="false"
+                     ext="tld">
+               </fileext>
+           </rules>
+         </include>
+         <group id="org.eclipse.wst.sse.core.structuredModelGroup"/>
+      </validator>
+   </extension>
+		
+    <extension
+       point="org.eclipse.jst.jsp.core.elTranslator">
+       <elTranslator
+          class="org.eclipse.jst.jsp.core.internal.java.jspel.JSPELTranslator"
+          name="Default JSP 2.0 EL Translator"
+          id="org.eclipse.jst.jsp.defaultJSP20"/>
+    </extension>
+    
+	<extension point="org.eclipse.wst.sse.core.modelHandler">
+		<modelHandler
+			class="org.eclipse.jst.jsp.css.core.internal.modelhandler.ModelHandlerForJSPedCSS"
+			associatedContentTypeId="org.eclipse.jst.jsp.core.cssjspsource"
+			id="org.eclipse.jst.jsp.css.core.modelhandler">
+		</modelHandler>
+		<modelHandler
+			class="org.eclipse.jst.jsp.css.core.internal.modelhandler.ModelHandlerForJSPedCSS"
+			associatedContentTypeId="org.eclipse.jst.jsp.core.cssjspfragmentsource"
+			id="org.eclipse.jst.jsp.css.core.modelhandler">
+		</modelHandler>
+	</extension>
+	
+	<extension
+		point="org.eclipse.core.filebuffers.documentCreation"
+		id="org.eclipse.jst.jsp.css.core.internal.documentfactories"
+		name="%contentTypeCSSDocumentFactoryName">
+		<factory
+			contentTypeId="org.eclipse.jst.jsp.core.cssjspsource"
+			class="org.eclipse.wst.sse.core.internal.filebuffers.BasicStructuredDocumentFactory" />
+	</extension>
+	<extension
+		point="org.eclipse.core.filebuffers.documentSetup"
+		id="org.eclipse.jst.jsp.css.core.documentsetup"
+		name="%Structured_JSP_Document_Setup_participant.name">
+		<participant
+			contentTypeId="org.eclipse.jst.jsp.core.cssjspsource"
+			class="org.eclipse.jst.jsp.css.core.internal.contentmodel.JSPedCSSTaglibController" />
+	</extension>
+	<!--
+	<extension
+		point="org.eclipse.core.filebuffers.documentCreation"
+		id="org.eclipse.jst.jsp.css.core.internal.documentfactories.fragment"
+		name="%contentTypeCSSDocumentFactoryName">
+		<factory
+			contentTypeId="org.eclipse.jst.jsp.core.cssjspfragmentsource"
+			class="org.eclipse.wst.sse.core.internal.filebuffers.BasicStructuredDocumentFactory" />
+	</extension>	
+	-->
+	<extension point="org.eclipse.wst.xml.core.modelQueryExtensions">
+		<modelQueryExtension
+			class="org.eclipse.jst.jsp.core.internal.modelquery.JSPModelQueryExtension"
+			contentType="org.eclipse.jst.jsp.core.jspsource">
+		</modelQueryExtension>
+	</extension>
+	<extension point="org.eclipse.wst.xml.core.modelQueryExtensions">
+		<modelQueryExtension
+			class="org.eclipse.jst.jsp.core.internal.modelquery.TaglibModelQueryExtension"
+			contentType="org.eclipse.jst.jsp.core.jspsource">
+		</modelQueryExtension>
+	</extension>
+	<extension point="org.eclipse.wst.xml.core.modelQueryExtensions">
+		<modelQueryExtension
+			class="org.eclipse.jst.jsp.core.internal.modelquery.JSPModelQueryExtension"
+			contentType="org.eclipse.jst.jsp.core.tagsource">
+		</modelQueryExtension>
+	</extension>
+	<extension point="org.eclipse.wst.xml.core.modelQueryExtensions">
+		<modelQueryExtension
+			class="org.eclipse.jst.jsp.core.internal.modelquery.TaglibModelQueryExtension"
+			contentType="org.eclipse.jst.jsp.core.tagsource">
+		</modelQueryExtension>
+	</extension>	
+	
+
+</plugin>
diff --git a/bundles/org.eclipse.jst.jsp.core/schema/eltranslator.exsd b/bundles/org.eclipse.jst.jsp.core/schema/eltranslator.exsd
new file mode 100644
index 0000000..34e412b
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/schema/eltranslator.exsd
@@ -0,0 +1,121 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.jst.jsp.core">
+<annotation>
+      <appInfo>
+         <meta.schema plugin="org.eclipse.jst.jsp.core" id="elTranslator" name="JSP EL Translator"/>
+      </appInfo>
+      <documentation>
+         Extension point to customer JSP Expression Language Generation
+      </documentation>
+   </annotation>
+
+   <element name="extension">
+      <complexType>
+         <sequence>
+            <element ref="elTranslator"/>
+         </sequence>
+         <attribute name="point" type="string" use="required">
+            <annotation>
+               <documentation>
+                  A fully qualified identifier of the target extension point.
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="id" type="string">
+            <annotation>
+               <documentation>
+                  An optional identifier of the extension instance.
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="name" type="string">
+            <annotation>
+               <documentation>
+                  An optional name of the extension instance.
+               </documentation>
+               <appInfo>
+                  <meta.attribute translatable="true"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <element name="elTranslator">
+      <annotation>
+         <appInfo>
+            <meta.element labelAttribute="name"/>
+         </appInfo>
+      </annotation>
+      <complexType>
+         <attribute name="class" type="string" use="required">
+            <annotation>
+               <documentation>
+                  Fully qualified class name for the EL Translator.  Must be an implementor of org.eclipse.jst.jsp.core.jspel.IJSPELTranslator.
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="name" type="string">
+            <annotation>
+               <documentation>
+                  The name of the EL translator.
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="id" type="string" use="required">
+            <annotation>
+               <documentation>
+                  A unique string identifier for an EL Translator.
+               </documentation>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="since"/>
+      </appInfo>
+      <documentation>
+         [Enter the first release in which this extension point appears.]
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="examples"/>
+      </appInfo>
+      <documentation>
+         [Enter extension point usage example here.]
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="apiInfo"/>
+      </appInfo>
+      <documentation>
+         [Enter API information here.]
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="implementation"/>
+      </appInfo>
+      <documentation>
+         [Enter information about supplied implementation of this extension point.]
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="copyright"/>
+      </appInfo>
+      <documentation>
+         
+      </documentation>
+   </annotation>
+
+</schema>
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/Assert.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/Assert.java
new file mode 100644
index 0000000..a5d8e17
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/Assert.java
@@ -0,0 +1,121 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal;
+
+
+
+/**
+ * <code>Assert</code> is useful for for embedding runtime sanity checks in
+ * code. The predicate methods all test a condition and throw some type of
+ * unchecked exception if the condition does not hold.
+ * <p>
+ * Assertion failure exceptions, like most runtime exceptions, are thrown when
+ * something is misbehaving. Assertion failures are invariably unspecified
+ * behavior; consequently, clients should never rely on these being thrown
+ * (and certainly should not being catching them specifically).
+ * </p>
+ */
+public final class Assert {
+
+	/**
+	 * <code>AssertionFailedException</code> is a runtime exception thrown
+	 * by some of the methods in <code>Assert</code>.
+	 * <p>
+	 * This class is not declared public to prevent some misuses; programs
+	 * that catch or otherwise depend on assertion failures are susceptible to
+	 * unexpected breakage when assertions in the code are added or removed.
+	 * </p>
+	 */
+	class AssertionFailedException extends RuntimeException {
+		/**
+		 * Comment for <code>serialVersionUID</code>
+		 */
+		private static final long serialVersionUID = 1L;
+
+		/**
+		 * Constructs a new exception.
+		 */
+		public AssertionFailedException() {
+			super();
+		}
+
+		/**
+		 * Constructs a new exception with the given message.
+		 */
+		public AssertionFailedException(String detail) {
+			super(detail);
+		}
+	}
+
+	/**
+	 * Asserts that an argument is legal. If the given boolean is not
+	 * <code>true</code>, an <code>IllegalArgumentException</code> is
+	 * thrown. The given message is included in that exception, to aid
+	 * debugging.
+	 * 
+	 * @param expression
+	 *            the outcode of the check
+	 * @param message
+	 *            the message to include in the exception
+	 * @return <code>true</code> if the check passes (does not return if the
+	 *         check fails)
+	 * @exception IllegalArgumentException
+	 *                if the legality test failed
+	 */
+	public static boolean isLegal(boolean expression, String message) {
+		if (!expression)
+			throw new IllegalArgumentException(message);
+		return expression;
+	}
+
+	/**
+	 * Asserts that the given object is not <code>null</code>. If this is
+	 * not the case, some kind of unchecked exception is thrown. The given
+	 * message is included in that exception, to aid debugging.
+	 * 
+	 * @param object
+	 *            the value to test
+	 * @param message
+	 *            the message to include in the exception
+	 * @exception IllegalArgumentException
+	 *                if the object is <code>null</code>
+	 */
+	public static void isNotNull(Object object, String message) {
+		if (object == null) {
+			throw new Assert().new AssertionFailedException(message);
+		}
+	}
+
+	/**
+	 * Asserts that the given boolean is <code>true</code>. If this is not
+	 * the case, some kind of unchecked exception is thrown. The given message
+	 * is included in that exception, to aid debugging.
+	 * 
+	 * @param expression
+	 *            the outcode of the check
+	 * @param message
+	 *            the message to include in the exception
+	 * @return <code>true</code> if the check passes (does not return if the
+	 *         check fails)
+	 */
+	public static boolean isTrue(boolean expression, String message) {
+		if (!expression) {
+			throw new Assert().new AssertionFailedException(message);
+		}
+		return expression;
+	}
+
+	/* This class is not intended to be instantiated. */
+	private Assert() {
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/JSPCoreMessages.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/JSPCoreMessages.java
new file mode 100644
index 0000000..697124d
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/JSPCoreMessages.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Strings used by JSP Core
+ * 
+ * @plannedfor 1.0
+ */
+public class JSPCoreMessages extends NLS {
+	private static final String BUNDLE_NAME = "org.eclipse.jst.jsp.core.internal.JSPCorePluginResources"; //$NON-NLS-1$
+
+	public static String JSPDirectiveValidator_0;
+	public static String JSPDirectiveValidator_1;
+	public static String JSPDirectiveValidator_2;
+	public static String JSPDirectiveValidator_3;
+	public static String JSPDirectiveValidator_4;
+	public static String JSPDirectiveValidator_5;
+	public static String JSPDirectiveValidator_6;
+	public static String JSPDirectiveValidator_7;
+	public static String JSPDirectiveValidator_8;
+	public static String JSPDirectiveValidator_9;
+	public static String JSPDirectiveValidator_10;
+	public static String JSPDirectiveValidator_11;
+	public static String JSPActionValidator_0;
+
+	public static String JSPActionValidator_1;
+	public static String JSPIndexManager_0;
+	public static String JSPIndexManager_2;
+	public static String JSP_Search;
+	public static String JSPEL_Syntax;
+	public static String JSPEL_Token;
+	public static String JSPDocumentLoader_1;
+	public static String JSPFContentPropertiesManager_Updating;
+	public static String JSPFContentPropertiesManager_Problems_Updating;
+	public static String JSPBatchValidator_0;
+	public static String TaglibHelper_0;
+	public static String TaglibHelper_1;
+	public static String TaglibHelper_2;
+	public static String TaglibHelper_3;
+	public static String JSPTranslator_0;
+	public static String JSPTranslator_1;
+	public static String JSPTranslator_2;
+	public static String JSPTranslator_3;
+	public static String JSPTranslator_4;
+	public static String JSPTranslator_5;
+	public static String JSPELTranslator_0;
+	public static String TLDValidator_MissingValidator;
+	public static String TLDValidator_MissingVariable;
+	public static String TLDValidator_MissingListener;
+	public static String Initializing;
+	public static String Persisting_JSP_Translations;
+	
+	/**
+	 * @deprecated
+	 */
+	public static String MESSAGE_JSP_VALIDATING_MESSAGE_UI_;
+	
+	private JSPCoreMessages() {
+	}
+
+	static {
+		// initialize resource bundle
+		NLS.initializeMessages(BUNDLE_NAME, JSPCoreMessages.class);
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/JSPCorePlugin.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/JSPCorePlugin.java
new file mode 100644
index 0000000..3b50941
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/JSPCorePlugin.java
@@ -0,0 +1,230 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal;
+
+import org.eclipse.core.resources.IResourceChangeEvent;
+import org.eclipse.core.resources.IResourceChangeListener;
+import org.eclipse.core.resources.ISaveContext;
+import org.eclipse.core.resources.ISaveParticipant;
+import org.eclipse.core.resources.ISavedState;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.IWorkspaceRunnable;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Plugin;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jst.jsp.core.internal.contentmodel.TaglibController;
+import org.eclipse.jst.jsp.core.internal.contentproperties.JSPFContentPropertiesManager;
+import org.eclipse.jst.jsp.core.internal.contenttype.DeploymentDescriptorPropertyCache;
+import org.eclipse.jst.jsp.core.internal.java.search.JSPIndexManager;
+import org.eclipse.jst.jsp.core.internal.taglib.TaglibHelperManager;
+import org.eclipse.jst.jsp.core.taglib.TaglibIndex;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The main plugin class to be used in the desktop.
+ */
+public class JSPCorePlugin extends Plugin {
+	/** singleton instance of the plugin */
+	private static JSPCorePlugin plugin;
+
+	/**
+	 * <p>Job used to finish tasks needed to start up the plugin but that did not have
+	 * to block the plugin start up process.</p>
+	 */
+	private Job fPluginInitializerJob;
+	
+	/**
+	 * The constructor.
+	 */
+	public JSPCorePlugin() {
+		super();
+		plugin = this;
+		this.fPluginInitializerJob = new PluginInitializerJob();
+	}
+
+	/**
+	 * Returns the shared instance.
+	 */
+	public static JSPCorePlugin getDefault() {
+		return plugin;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.core.runtime.Plugin#start(org.osgi.framework.BundleContext)
+	 */
+	public void start(BundleContext context) throws Exception {
+		super.start(context);
+
+		/*
+		 * JSPIndexManager depends on TaglibController, so TaglibController
+		 * should be started first
+		 */
+		TaglibIndex.startup();
+		TaglibController.startup();
+
+		// listen for classpath changes
+		JavaCore.addElementChangedListener(TaglibHelperManager.getInstance());
+		
+		//schedule delayed initialization
+		this.fPluginInitializerJob.schedule(2000);
+
+		// listen for resource changes to update content properties keys
+		JSPFContentPropertiesManager.startup();
+
+		DeploymentDescriptorPropertyCache.start();
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.core.runtime.Plugin#stop(org.osgi.framework.BundleContext)
+	 */
+	public void stop(BundleContext context) throws Exception {
+		DeploymentDescriptorPropertyCache.stop();
+
+		// stop listening for resource changes to update content properties keys
+		JSPFContentPropertiesManager.shutdown();
+
+		//remove the plugin save participant
+		ResourcesPlugin.getWorkspace().removeSaveParticipant(plugin.getBundle().getSymbolicName());
+		
+		// stop any indexing
+		JSPIndexManager.getDefault().stop();
+
+		// stop listening for classpath changes
+		JavaCore.removeElementChangedListener(TaglibHelperManager.getInstance());
+
+		// stop taglib controller
+		TaglibController.shutdown();
+		TaglibIndex.shutdown();
+
+		super.stop(context);
+	}
+	
+	/**
+	 * <p>A {@link Job} used to perform delayed initialization for the plugin</p>
+	 */
+	private static class PluginInitializerJob extends Job {
+		/**
+		 * <p>Default constructor to set up this {@link Job} as a
+		 * long running system {@link Job}</p>
+		 */
+		protected PluginInitializerJob() {
+			super(JSPCoreMessages.Initializing);
+			
+			this.setUser(false);
+			this.setSystem(true);
+			this.setPriority(Job.LONG);
+		}
+		
+		/**
+		 * <p>Perform delayed initialization for the plugin</p>
+		 * 
+		 * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
+		 */
+		protected IStatus run(IProgressMonitor monitor) {
+			IStatus status = Status.OK_STATUS;
+			final IWorkspace workspace = ResourcesPlugin.getWorkspace();
+			try {
+				/*
+				 * Restore save state and process any events that happened before
+				 * plug-in loaded. Don't do it immediately since adding the save
+				 * participant requires a lock on the workspace to compute the
+				 * accumulated deltas, and if the tree is not already locked it
+				 * becomes a blocking call.
+				 */
+				workspace.run(new IWorkspaceRunnable() {
+					public void run(final IProgressMonitor worspaceMonitor) throws CoreException {
+						ISavedState savedState = null;
+						
+						try {
+							//add the save participant for this bundle
+							savedState = ResourcesPlugin.getWorkspace().addSaveParticipant(
+									JSPCorePlugin.plugin.getBundle().getSymbolicName(), new SaveParticipant());
+						} catch (CoreException e) {
+							Logger.logException("JSP Core Plugin failed at loading previously saved state." + //$NON-NLS-1$
+									" All componenets dependent on this state will start as if first workspace load.", e); //$NON-NLS-1$
+						}
+						
+						//if there is a saved state start up using that, else start up cold
+						if(savedState != null) {
+							try {
+								Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
+							} finally {
+								savedState.processResourceChangeEvents(new IResourceChangeListener() {
+									/**
+									 * @see org.eclipse.core.resources.IResourceChangeListener#resourceChanged(org.eclipse.core.resources.IResourceChangeEvent)
+									 */
+									public void resourceChanged(IResourceChangeEvent event) {
+										JSPIndexManager.getDefault().start(event.getDelta(), worspaceMonitor);
+									}
+								});
+							}
+						} else {
+							JSPIndexManager.getDefault().start(null, worspaceMonitor);
+						}
+					}
+				}, monitor);
+			} catch(CoreException e) {
+				status = e.getStatus();
+			}
+			return status;
+		}
+		
+	}
+	
+	/**
+	 * Used so that all of the IResourceChangeEvents that occurred before
+	 * this plugin loaded can be processed.
+	 */
+	private static class SaveParticipant implements ISaveParticipant {
+		/**
+		 * <p>Default constructor</p>
+		 */
+		protected SaveParticipant() {
+		}
+		
+		/**
+		 * @see org.eclipse.core.resources.ISaveParticipant#doneSaving(org.eclipse.core.resources.ISaveContext)
+		 */
+		public void doneSaving(ISaveContext context) {
+			//ignore
+		}
+	
+		/**
+		 * @see org.eclipse.core.resources.ISaveParticipant#prepareToSave(org.eclipse.core.resources.ISaveContext)
+		 */
+		public void prepareToSave(ISaveContext context) throws CoreException {
+			//ignore
+		}
+	
+		/**
+		 * @see org.eclipse.core.resources.ISaveParticipant#rollback(org.eclipse.core.resources.ISaveContext)
+		 */
+		public void rollback(ISaveContext context) {
+			//ignore
+		}
+	
+		/**
+		 * @see org.eclipse.core.resources.ISaveParticipant#saving(org.eclipse.core.resources.ISaveContext)
+		 */
+		public void saving(ISaveContext context) throws CoreException {
+			context.needDelta();
+		}
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/JSPCorePluginResources.properties b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/JSPCorePluginResources.properties
new file mode 100644
index 0000000..e7e91b5
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/JSPCorePluginResources.properties
@@ -0,0 +1,50 @@
+###############################################################################
+# Copyright (c) 2004, 2009 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
+###############################################################################
+JSPIndexManager_0=Updating JSP Index
+JSPIndexManager_2=JSP Indexer indexing {0} files
+JSP_Search=JSP Search - 
+JSPDocumentLoader_1=Program Error: structured model had no structuredDocument
+JSPEL_Syntax=EL Syntax Error 
+JSPEL_Token=Unable to analyze EL expression due to lexical analysis error
+MESSAGE_JSP_VALIDATING_MESSAGE_UI_=JSP Validator validating {0}
+JSPFContentPropertiesManager_Updating=Updating JSP Fragment Content Settings
+JSPFContentPropertiesManager_Problems_Updating=Problem saving JSP Fragment Content Settings for {0}
+JSPDirectiveValidator_0={0} is a reserved prefix.  Try another
+JSPDirectiveValidator_1=Can not find the tag library descriptor for "{0}"
+JSPDirectiveValidator_2=The prefix "{0} "is used more than once
+JSPDirectiveValidator_3=A {0} value is required in this directive
+JSPDirectiveValidator_4=Fragment "{0}" was not found at expected path {1}
+JSPDirectiveValidator_5=Missing required attribute "{0}"
+JSPDirectiveValidator_6=Undefined attribute name "{0}"
+JSPDirectiveValidator_7=A {0} or {1} value is required in this directive
+JSPDirectiveValidator_8=The superclass "{0}" was not found on the Java Build Path
+JSPDirectiveValidator_9=Can not find the tag library descriptor for "{0}".  Try increasing the version of the Dynamic Web Module project facet.
+JSPDirectiveValidator_10=Can not find the tag library descriptor for "{0}".  Try using a newer grammar or declared version in the Web Deployment Descriptor.
+JSPDirectiveValidator_11=Can not find the tag directory "{0}"
+JSPActionValidator_0=Tag ({0}) must be empty
+JSPActionValidator_1="{0}" does not support runtime expressions
+JSPBatchValidator_0=Gathering files in {0}
+TaglibHelper_0=The TagExtraInfo class for "{0}" ({1}) was not found on the Java Build Path
+TaglibHelper_1=The TagExtraInfo class for "{0}" ({1}) could not be instantiated
+TaglibHelper_2=A problem was encountered using TagExtraInfo class {1} for '{0}' 
+TaglibHelper_3=The tag handler class for "{0}" ({1}) was not found on the Java Build Path
+JSPTranslator_0=Invalid identifier: "{0}"
+JSPTranslator_1=Undefined type: {0}
+JSPTranslator_2=Can not declare both "class" and "beanName" attributes
+JSPTranslator_3=Unknown type for identifier "{0}"
+JSPTranslator_4=Missing start tag for "{0}"
+JSPTranslator_5=Missing end tag for "{0}"
+JSPELTranslator_0=The function {0} is undefined
+TLDValidator_MissingValidator=The TagLibraryValidator subclass '{0}' was not found on the Java Build Path
+TLDValidator_MissingVariable=The variable class '{0}' was not found on the Java Build Path
+TLDValidator_MissingListener=The listener class '{0}' was not found on the Java Build Path
+Initializing=Processing JSP changes since last activation
+Persisting_JSP_Translations=Persisting JSP Translations
\ No newline at end of file
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/Logger.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/Logger.java
new file mode 100644
index 0000000..02d02ae
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/Logger.java
@@ -0,0 +1,144 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal;
+
+import com.ibm.icu.util.StringTokenizer;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.osgi.framework.Bundle;
+
+/**
+ * Small convenience class to log messages to plugin's log file and also, if desired,
+ * the console. This class should only be used by classes in this plugin. Other
+ * plugins should make their own copy, with appropriate ID.
+ */
+public class Logger {
+	private static final String PLUGIN_ID = "org.eclipse.jst.jsp.core"; //$NON-NLS-1$
+	
+	private static final String TRACEFILTER_LOCATION = "/debug/tracefilter"; //$NON-NLS-1$
+
+	public static final int OK = IStatus.OK; // 0
+	public static final int INFO = IStatus.INFO; // 1
+	public static final int WARNING = IStatus.WARNING; // 2
+	public static final int ERROR = IStatus.ERROR; // 4
+
+	public static final int OK_DEBUG = 200 + OK;
+	public static final int INFO_DEBUG = 200 + INFO;
+	public static final int WARNING_DEBUG = 200 + WARNING;
+	public static final int ERROR_DEBUG = 200 + ERROR;
+
+	/**
+	 * Adds message to log.
+	 * @param level severity level of the message (OK, INFO, WARNING, ERROR, OK_DEBUG, INFO_DEBUG, WARNING_DEBUG, ERROR_DEBUG)
+	 * @param message text to add to the log
+	 * @param exception exception thrown
+	 */
+	protected static void _log(int level, String message, Throwable exception) {
+		if (level == OK_DEBUG || level == INFO_DEBUG || level == WARNING_DEBUG || level == ERROR_DEBUG) {
+			if (!isDebugging())
+				return;
+		}
+
+		int severity = IStatus.OK;
+		switch (level) {
+			case INFO_DEBUG :
+			case INFO :
+				severity = IStatus.INFO;
+				break;
+			case WARNING_DEBUG :
+			case WARNING :
+				severity = IStatus.WARNING;
+				break;
+			case ERROR_DEBUG :
+			case ERROR :
+				severity = IStatus.ERROR;
+		}
+		message = (message != null) ? message : "null"; //$NON-NLS-1$
+		Status statusObj = new Status(severity, PLUGIN_ID, severity, message, exception);
+		Bundle bundle = Platform.getBundle(PLUGIN_ID);
+		if (bundle != null) 
+			Platform.getLog(bundle).log(statusObj);
+	}
+
+	/**
+	 * Prints message to log if category matches /debug/tracefilter option.
+	 * @param message text to print
+	 * @param category category of the message, to be compared with /debug/tracefilter
+	 */
+	protected static void _trace(String category, String message, Throwable exception) {
+		if (isTracing(category)) {
+			message = (message != null) ? message : "null"; //$NON-NLS-1$
+			Status statusObj = new Status(IStatus.OK, PLUGIN_ID, IStatus.OK, message, exception);
+			Bundle bundle = Platform.getBundle(PLUGIN_ID);
+			if (bundle != null) 
+				Platform.getLog(bundle).log(statusObj);
+		}
+	}
+
+	/**
+	 * @return true if the platform is debugging
+	 */
+	public static boolean isDebugging() {
+		return Platform.inDebugMode();
+	}
+
+	/**
+	 * Determines if currently tracing a category
+	 * @param category
+	 * @return true if tracing category, false otherwise
+	 */
+	public static boolean isTracing(String category) {
+		if (!isDebugging())
+			return false;
+
+		String traceFilter = Platform.getDebugOption(PLUGIN_ID + TRACEFILTER_LOCATION);
+		if (traceFilter != null) {
+			StringTokenizer tokenizer = new StringTokenizer(traceFilter, ","); //$NON-NLS-1$
+			while (tokenizer.hasMoreTokens()) {
+				String cat = tokenizer.nextToken().trim();
+				if (category.equals(cat)) {
+					return true;
+				}
+			}
+		}
+		return false;
+	}
+
+	public static void log(int level, String message) {
+		_log(level, message, null);
+	}
+
+	public static void log(int level, String message, Throwable exception) {
+		_log(level, message, exception);
+	}
+
+	public static void logException(String message, Throwable exception) {
+		_log(ERROR, message, exception);
+	}
+
+	public static void logException(Throwable exception) {
+		_log(ERROR, exception.getMessage(), exception);
+	}
+
+	public static void traceException(String category, String message, Throwable exception) {
+		_trace(category, message, exception);
+	}
+
+	public static void traceException(String category, Throwable exception) {
+		_trace(category, exception.getMessage(), exception);
+	}
+
+	public static void trace(String category, String message) {
+		_trace(category, message, null);
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/CMContentWrapperImpl.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/CMContentWrapperImpl.java
new file mode 100644
index 0000000..11707b7
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/CMContentWrapperImpl.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMContent;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+public class CMContentWrapperImpl extends CMNodeWrapperImpl implements CMContent {
+
+	private CMContent fCMContent = null;
+
+	/**
+	 * CMContentWrapper constructor comment.
+	 * @param prefix java.lang.String
+	 * @param node org.eclipse.wst.xml.core.internal.contentmodel.CMNode
+	 */
+	public CMContentWrapperImpl(String prefix, org.eclipse.wst.xml.core.internal.contentmodel.CMContent node) {
+		super(prefix, node);
+		fCMContent = node;
+	}
+
+	/**
+	 * getMaxOccur method
+	 * @return int
+	 *
+	 * If -1, it's UNBOUNDED.
+	 */
+	public int getMaxOccur() {
+		return fCMContent.getMaxOccur();
+	}
+
+	/**
+	 * getMinOccur method
+	 * @return int
+	 *
+	 * If 0, it's OPTIONAL.
+	 * If 1, it's REQUIRED.
+	 */
+	public int getMinOccur() {
+		return fCMContent.getMinOccur();
+	}
+
+	public CMNode getOriginNode() {
+		return fCMContent;
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/CMDocumentWrapperImpl.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/CMDocumentWrapperImpl.java
new file mode 100644
index 0000000..b330f92
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/CMDocumentWrapperImpl.java
@@ -0,0 +1,216 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.contentmodel;
+
+
+
+import java.util.Hashtable;
+import java.util.Iterator;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.provisional.contentmodel.CMNodeWrapper;
+
+public class CMDocumentWrapperImpl implements CMDocument, CMNodeWrapper {
+
+	class CMNamedNodeMapImpl implements CMNamedNodeMap {
+
+		protected Hashtable table = new Hashtable();
+
+		public CMNamedNodeMapImpl() {
+			super();
+		}
+
+		Hashtable getHashtable() {
+			return table;
+		}
+
+		public int getLength() {
+			return table.size();
+		}
+
+		public CMNode getNamedItem(String name) {
+			return (CMNode) table.get(name);
+		}
+
+		public CMNode item(int index) {
+			Object result = null;
+			int size = table.size();
+			if (index < size) {
+				Iterator values = iterator();
+				for (int i = 0; i <= index; i++) {
+					result = values.next();
+				}
+			}
+			return (CMNode) result;
+		}
+
+		public Iterator iterator() {
+			return table.values().iterator();
+		}
+
+		public void setNamedItem(String name, CMNode aNode) {
+			if (name != null && aNode != null)
+				table.put(name, aNode);
+		}
+	}
+
+	public class CMNamespaceImpl implements CMNamespace {
+		public String getNodeName() {
+			return CMDocumentWrapperImpl.this.getURI();
+		}
+
+		public int getNodeType() {
+			return CMNode.NAME_SPACE;
+		}
+
+		public String getPrefix() {
+			return CMDocumentWrapperImpl.this.getPrefix();
+		}
+
+		public Object getProperty(String property) {
+			return null;
+		}
+
+		public String getURI() {
+			return CMDocumentWrapperImpl.this.getURI();
+		}
+
+		public boolean supports(String feature) {
+			return false;
+		}
+	}
+
+	private CMDocument fDocument;
+	private CMNamedNodeMap fElements = null;
+	private CMNamedNodeMap fEntities = null;
+	private CMNamespace fNamespace = new CMNamespaceImpl();
+	private String fPrefix;
+	private String fURI;
+
+	public CMDocumentWrapperImpl(String newURI, String newPrefix, CMDocument tld) {
+		fURI = newURI;
+		fPrefix = newPrefix;
+		fDocument = tld;
+	}
+
+	/**
+	 * 
+	 * @return org.eclipse.wst.xml.core.internal.contentmodel.CMDocument
+	 */
+	public CMDocument getDocument() {
+		return fDocument;
+	}
+
+	/**
+	 * getElements method
+	 * @return CMNamedNodeMap
+	 *
+	 * Returns CMNamedNodeMap of ElementDeclaration
+	 */
+	public CMNamedNodeMap getElements() {
+		if (fElements == null) {
+			int length = getDocument().getElements().getLength();
+			CMNamedNodeMapImpl elements = new CMNamedNodeMapImpl();
+			for (int i = 0; i < length; i++) {
+				CMElementDeclaration ed = new CMElementDeclarationWrapperImpl(fPrefix, (CMElementDeclaration) getDocument().getElements().item(i));
+				elements.setNamedItem(ed.getNodeName(), ed);
+			}
+			fElements = elements;
+		}
+		return fElements;
+	}
+
+	/**
+	 * getEntities method
+	 * @return CMNamedNodeMap
+	 *
+	 * Returns CMNamedNodeMap of EntityDeclaration
+	 */
+	public CMNamedNodeMap getEntities() {
+		if (fEntities == null) {
+			fEntities = getDocument().getEntities();
+		}
+		return fEntities;
+	}
+
+	/**
+	 * getNamespace method
+	 * @return CMNamespace
+	 */
+	public CMNamespace getNamespace() {
+		return fNamespace;
+	}
+
+	/**
+	 * getNodeName method
+	 * @return java.lang.String
+	 */
+	public String getNodeName() {
+		return getDocument().getNodeName();
+	}
+
+	/**
+	 * getNodeType method
+	 * @return int
+	 *
+	 * Returns one of :
+	 *
+	 */
+	public int getNodeType() {
+		return getDocument().getNodeType();
+	}
+
+	public CMNode getOriginNode() {
+		return fDocument;
+	}
+
+	/**
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getPrefix() {
+		return fPrefix;
+	}
+
+	/**
+	 * getProperty method
+	 * @return java.lang.Object
+	 *
+	 * Returns the object property desciped by the propertyName
+	 *
+	 */
+	public Object getProperty(String propertyName) {
+		return getDocument().getProperty(propertyName);
+	}
+
+	/**
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getURI() {
+		return fURI;
+	}
+
+	/**
+	 * supports method
+	 * @return boolean
+	 *
+	 * Returns true if the CMNode supports a specified property
+	 *
+	 */
+	public boolean supports(String propertyName) {
+		return getDocument().supports(propertyName);
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/CMElementDeclarationWrapperImpl.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/CMElementDeclarationWrapperImpl.java
new file mode 100644
index 0000000..69eeca3
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/CMElementDeclarationWrapperImpl.java
@@ -0,0 +1,128 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMContent;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+public class CMElementDeclarationWrapperImpl extends CMNodeWrapperImpl implements CMElementDeclaration {
+	private CMContent fCMContent = null;
+
+	protected CMElementDeclaration fElementDecl = null;
+
+	/**
+	 * CMElementDeclarationWrapper constructor comment.
+	 * @param prefix java.lang.String
+	 * @param node org.eclipse.wst.xml.core.internal.contentmodel.CMNode
+	 */
+	public CMElementDeclarationWrapperImpl(String prefix, CMElementDeclaration node) {
+		super(prefix, node);
+		fElementDecl = node;
+	}
+
+	/**
+	 * getAttributes method
+	 * @return CMNamedNodeMap
+	 *
+	 * Returns CMNamedNodeMap of AttributeDeclaration
+	 */
+	public CMNamedNodeMap getAttributes() {
+		return fElementDecl.getAttributes();
+	}
+
+	/**
+	 * getCMContent method
+	 * @return CMContent
+	 *
+	 * Returns the root node of this element's content model.
+	 * This can be an CMElementDeclaration or a CMGroup
+	 */
+	public CMContent getContent() {
+		if (fCMContent == null) {
+			CMContent content = fElementDecl.getContent();
+			if (content == null)
+				return null;
+			if (content instanceof CMGroup)
+				fCMContent = new CMGroupWrapperImpl(fPrefix, (CMGroup) content);
+			else
+				fCMContent = new CMContentWrapperImpl(fPrefix, content);
+		}
+		return fCMContent;
+	}
+
+	/**
+	 * getContentType method
+	 * @return int
+	 *
+	 * Returns one of :
+	 * ANY, EMPTY, ELEMENT, MIXED, PCDATA, CDATA.
+	 */
+	public int getContentType() {
+		return fElementDecl.getContentType();
+	}
+
+	/**
+	 * getDataType method
+	 * @return java.lang.String
+	 */
+	public CMDataType getDataType() {
+		return fElementDecl.getDataType();
+	}
+
+	/**
+	 * getElementName method
+	 * @return java.lang.String
+	 */
+	public String getElementName() {
+		return getNodeName();
+	}
+
+	/**
+	 * getLocalElements method
+	 * @return CMNamedNodeMap
+	 *
+	 * Returns a list of locally defined elements.
+	 */
+	public CMNamedNodeMap getLocalElements() {
+		return fElementDecl.getLocalElements();
+	}
+
+	/**
+	 * getMaxOccur method
+	 * @return int
+	 *
+	 * If -1, it's UNBOUNDED.
+	 */
+	public int getMaxOccur() {
+		return fElementDecl.getMaxOccur();
+	}
+
+	/**
+	 * getMinOccur method
+	 * @return int
+	 *
+	 * If 0, it's OPTIONAL.
+	 * If 1, it's REQUIRED.
+	 */
+	public int getMinOccur() {
+		return fElementDecl.getMinOccur();
+	}
+
+	public CMNode getOriginNode() {
+		return fElementDecl;
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/CMGroupWrapperImpl.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/CMGroupWrapperImpl.java
new file mode 100644
index 0000000..ee8619e
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/CMGroupWrapperImpl.java
@@ -0,0 +1,112 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.contentmodel;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNodeList;
+
+public class CMGroupWrapperImpl extends CMContentWrapperImpl implements CMGroup {
+	class CMNodeListImpl implements CMNodeList {
+		private List nodes = null;
+
+		/**
+		 * CMNodeListImpl constructor comment.
+		 */
+		public CMNodeListImpl() {
+			super();
+			nodes = new ArrayList();
+		}
+
+		/**
+		 * @return org.eclipse.wst.xml.core.internal.contentmodel.CMNode
+		 * @param node org.eclipse.wst.xml.core.internal.contentmodel.CMNode
+		 */
+		public void appendItem(CMNode node) {
+			nodes.add(node);
+		}
+
+		/**
+		 * getLength method
+		 * @return int
+		 */
+		public int getLength() {
+			return nodes.size();
+		}
+
+		/**
+		 * item method
+		 * @return CMNode
+		 * @param index int
+		 */
+		public CMNode item(int index) {
+			if (index < 0 || index >= nodes.size())
+				return null;
+			return (CMNode) nodes.get(index);
+		}
+	}
+
+	private CMNodeList fChildNodes = null;
+	private CMGroup fGroup = null;
+
+	/**
+	 * CMGroupWrapper constructor comment.
+	 * @param prefix java.lang.String
+	 * @param node org.eclipse.wst.xml.core.internal.contentmodel.CMContent
+	 */
+	public CMGroupWrapperImpl(String prefix, CMGroup node) {
+		super(prefix, node);
+	}
+
+	/**
+	 * getChildNodes method
+	 * @return CMNodeList
+	 *
+	 * Returns child CMNodeList, which includes ElementDefinition or CMElement.
+	 */
+	public CMNodeList getChildNodes() {
+		if (fChildNodes == null) {
+			CMNodeListImpl childNodes = new CMNodeListImpl();
+			CMNodeList children = fGroup.getChildNodes();
+			for (int i = 0; i < children.getLength(); i++) {
+				CMNode child = children.item(i);
+				if (child instanceof CMGroup)
+					childNodes.appendItem(new CMGroupWrapperImpl(fPrefix, (CMGroup) child));
+				else if (child instanceof CMElementDeclaration)
+					childNodes.appendItem(new CMElementDeclarationWrapperImpl(fPrefix, (CMElementDeclaration) child));
+				else
+					// error?
+					childNodes.appendItem(new CMNodeWrapperImpl(fPrefix, child));
+			}
+			fChildNodes = childNodes;
+		}
+		return fChildNodes;
+	}
+
+	/**
+	 * getOperation method
+	 * @return int
+	 *
+	 * Returns one of :
+	 * ALONE (a), SEQUENCE (a,b), CHOICE (a|b), ALL (a&b).
+	 */
+	public int getOperator() {
+		return fGroup.getOperator();
+	}
+
+	public CMNode getOriginNode() {
+		return fGroup;
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/CMNodeWrapperImpl.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/CMNodeWrapperImpl.java
new file mode 100644
index 0000000..a8b7d21
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/CMNodeWrapperImpl.java
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.provisional.contentmodel.CMNodeWrapper;
+
+public class CMNodeWrapperImpl implements CMNode, CMNodeWrapper {
+	private CMNode fNode = null;
+	private String fNodeName = null;
+
+	protected String fPrefix = null;
+
+	/**
+	 * CMNodeWrapper constructor comment.
+	 */
+	public CMNodeWrapperImpl(String prefix, CMNode node) {
+		super();
+		fPrefix = prefix;
+		fNode = node;
+
+		fNodeName = fPrefix + ":" + fNode.getNodeName(); //$NON-NLS-1$
+	}
+
+	/**
+	 * getNodeName method
+	 * @return java.lang.String
+	 */
+	public String getNodeName() {
+		return fNodeName;
+	}
+
+	/**
+	 * getNodeType method
+	 * @return int
+	 *
+	 * Returns one of :
+	 *
+	 */
+	public int getNodeType() {
+		return fNode.getNodeType();
+	}
+
+	public CMNode getOriginNode() {
+		return fNode;
+	}
+
+	/**
+	 * getProperty method
+	 * @return java.lang.Object
+	 *
+	 * Returns the object property desciped by the propertyName
+	 *
+	 */
+	public Object getProperty(String propertyName) {
+		return fNode.getProperty(propertyName);
+	}
+
+	/**
+	 * supports method
+	 * @return boolean
+	 *
+	 * Returns true if the CMNode supports a specified property
+	 *
+	 */
+	public boolean supports(String propertyName) {
+		return fNode.supports(propertyName);
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/JSPCMDocumentFactory.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/JSPCMDocumentFactory.java
new file mode 100644
index 0000000..3ae1d2e
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/JSPCMDocumentFactory.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.contentmodel;
+
+import org.eclipse.wst.html.core.internal.contentmodel.HTMLCMDocumentFactory;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.provisional.contentmodel.CMDocType;
+
+/**
+ * CMDocument factory for JSP documents (which for now live in the HTML Core
+ * plugin).
+ */
+public final class JSPCMDocumentFactory {
+
+	private JSPCMDocumentFactory() {
+		super();
+	}
+
+	public static CMDocument getCMDocument() {
+		return getCMDocument(CMDocType.JSP21_DOC_TYPE);
+	}
+
+	/**
+	 * @return org.eclipse.wst.xml.core.internal.contentmodel.CMDocument
+	 * @param cmtype
+	 *            java.lang.String
+	 */
+	public static CMDocument getCMDocument(String cmtype) {
+		if (cmtype == null)
+			return getCMDocument();
+		return HTMLCMDocumentFactory.getCMDocument(cmtype);
+	}
+
+	public static CMDocument getCMDocument(float jspVersion) {
+		if (jspVersion >= 2.1f)
+			return getCMDocument(CMDocType.JSP21_DOC_TYPE);
+		else if (jspVersion >= 2)
+			return getCMDocument(CMDocType.JSP20_DOC_TYPE);
+		else if (jspVersion >= 1.2f)
+			return getCMDocument(CMDocType.JSP12_DOC_TYPE);
+		else if (jspVersion >= 1)
+			return getCMDocument(CMDocType.JSP11_DOC_TYPE);
+		return getCMDocument();
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/TaglibController.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/TaglibController.java
new file mode 100644
index 0000000..bea60aa
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/TaglibController.java
@@ -0,0 +1,373 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.contentmodel;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.filebuffers.FileBuffers;
+import org.eclipse.core.filebuffers.IDocumentSetupParticipant;
+import org.eclipse.core.filebuffers.IDocumentSetupParticipantExtension;
+import org.eclipse.core.filebuffers.IFileBuffer;
+import org.eclipse.core.filebuffers.IFileBufferListener;
+import org.eclipse.core.filebuffers.ITextFileBuffer;
+import org.eclipse.core.filebuffers.LocationKind;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jst.jsp.core.internal.contentmodel.tld.TLDCMDocumentManager;
+import org.eclipse.jst.jsp.core.taglib.ITaglibIndexDelta;
+import org.eclipse.jst.jsp.core.taglib.ITaglibIndexListener;
+import org.eclipse.jst.jsp.core.taglib.TaglibIndex;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+import org.eclipse.wst.sse.core.internal.text.BasicStructuredDocument;
+import org.eclipse.wst.sse.core.internal.util.Assert;
+import org.eclipse.wst.xml.core.internal.parser.XMLSourceParser;
+
+/**
+ * Provides a direct mapping from IStructuredDocument to supporting
+ * TLDCMDocumentManager.
+ * 
+ * Listens to the creation of JSP type TextFileBuffers and forces a text-less
+ * reparse after connecting taglib-supporting listeners. Connecting the
+ * listeners before the text is set would be ideal, but there is no way to
+ * look up taglib references since the location is not yet knowable. Since
+ * taglibs can affect the parsing of the document, a reparse is currently
+ * required to react to custom tags with tagdependent content.
+ * 
+ * TODO: Remove the reparse penalty.
+ */
+public class TaglibController implements IDocumentSetupParticipant, IDocumentSetupParticipantExtension {
+
+	class DocumentInfo implements ITaglibIndexListener {
+		IStructuredDocument document;
+		ITextFileBuffer textFileBuffer;
+		IPath location;
+		LocationKind locationKind;
+		TLDCMDocumentManager tldDocumentManager;
+
+		public void indexChanged(ITaglibIndexDelta delta) {
+			int type = delta.getKind();
+			if (type == ITaglibIndexDelta.CHANGED || type == ITaglibIndexDelta.REMOVED) {
+				ITaglibIndexDelta[] deltas = delta.getAffectedChildren();
+				boolean affected = false;
+				for (int i = 0; i < deltas.length; i++) {
+					Object key = TLDCMDocumentManager.getUniqueIdentifier(deltas[i].getTaglibRecord());
+					if (tldDocumentManager.getDocuments().containsKey(key)) {
+						affected = true;
+					}
+				}
+				if (affected) {
+					if (_debugCache) {
+						System.out.println("TLDCMDocumentManager cleared its private CMDocument cache"); //$NON-NLS-1$
+					}
+					tldDocumentManager.getDocuments().clear();
+					tldDocumentManager.getSourceParser().resetHandlers();
+
+					if (document instanceof BasicStructuredDocument) {
+						((BasicStructuredDocument) document).reparse(this);
+					}
+				}
+			}
+			tldDocumentManager.indexChanged(delta);
+		}
+	}
+
+	static final boolean _debugCache = "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.jst.jsp.core/debug/tldcmdocument/cache")); //$NON-NLS-1$ //$NON-NLS-2$
+
+	class FileBufferListener implements IFileBufferListener {
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see org.eclipse.core.filebuffers.IFileBufferListener#bufferContentAboutToBeReplaced(org.eclipse.core.filebuffers.IFileBuffer)
+		 */
+		public void bufferContentAboutToBeReplaced(IFileBuffer buffer) {
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see org.eclipse.core.filebuffers.IFileBufferListener#bufferContentReplaced(org.eclipse.core.filebuffers.IFileBuffer)
+		 */
+		public void bufferContentReplaced(IFileBuffer buffer) {
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see org.eclipse.core.filebuffers.IFileBufferListener#bufferCreated(org.eclipse.core.filebuffers.IFileBuffer)
+		 */
+		public void bufferCreated(IFileBuffer buffer) {
+			if (buffer instanceof ITextFileBuffer) {
+				IDocument document = ((ITextFileBuffer) buffer).getDocument();
+				// ignore non-JSP documents
+				synchronized (_instance.fJSPdocuments) {
+					if (!_instance.fJSPdocuments.contains(document))
+						return;
+				}
+				Assert.isTrue(document instanceof IStructuredDocument, getClass().getName() + " SetupParticipant was called for non-IStructuredDocument"); //$NON-NLS-1$
+
+				DocumentInfo info = null;
+				synchronized (_instance.fDocumentMap) {
+					info = (DocumentInfo) _instance.fDocumentMap.get(document);
+				}
+				if (info != null) {
+					// remember the buffer now
+					info.textFileBuffer = (ITextFileBuffer) buffer;
+				}
+				else {
+					info = new DocumentInfo();
+					info.document = (IStructuredDocument) document;
+					info.textFileBuffer = (ITextFileBuffer) buffer;
+					info.location = buffer.getLocation();
+					info.locationKind = LocationKind.NORMALIZE;
+					info.tldDocumentManager = new TLDCMDocumentManager();
+					info.tldDocumentManager.setSourceParser((XMLSourceParser) info.document.getParser());
+					synchronized (_instance.fDocumentMap) {
+						_instance.fDocumentMap.put(document, info);
+					}
+					TaglibIndex.addTaglibIndexListener(info);
+					if (document instanceof BasicStructuredDocument && document.getLength() > 0) {
+						((BasicStructuredDocument) document).reparse(this);
+					}
+				}
+			}
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see org.eclipse.core.filebuffers.IFileBufferListener#bufferDisposed(org.eclipse.core.filebuffers.IFileBuffer)
+		 */
+		public void bufferDisposed(IFileBuffer buffer) {
+			if (buffer instanceof ITextFileBuffer) {
+				IDocument document = ((ITextFileBuffer) buffer).getDocument();
+				synchronized (_instance.fJSPdocuments) {
+					if (!_instance.fJSPdocuments.remove(document))
+						return;
+				}
+			}
+			DocumentInfo info = null;
+			synchronized (fDocumentMap) {
+				Map.Entry[] entries = (Map.Entry[]) fDocumentMap.entrySet().toArray(new Map.Entry[fDocumentMap.size()]);
+				for (int i = 0; i < entries.length; i++) {
+					info = (DocumentInfo) entries[i].getValue();
+					/**
+					 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=222137
+					 * 
+					 * Might be null if setup() has been called but
+					 * bufferCreated() has not, yet.
+					 */
+					if (info != null && info.textFileBuffer != null && info.textFileBuffer.equals(buffer)) {
+						fDocumentMap.remove(entries[i].getKey());
+						break;
+					}
+				}
+			}
+			if (info != null) {
+				info.tldDocumentManager.clearCache();
+				TaglibIndex.removeTaglibIndexListener(info);
+			}
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see org.eclipse.core.filebuffers.IFileBufferListener#dirtyStateChanged(org.eclipse.core.filebuffers.IFileBuffer,
+		 *      boolean)
+		 */
+		public void dirtyStateChanged(IFileBuffer buffer, boolean isDirty) {
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see org.eclipse.core.filebuffers.IFileBufferListener#stateChangeFailed(org.eclipse.core.filebuffers.IFileBuffer)
+		 */
+		public void stateChangeFailed(IFileBuffer buffer) {
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see org.eclipse.core.filebuffers.IFileBufferListener#stateChanging(org.eclipse.core.filebuffers.IFileBuffer)
+		 */
+		public void stateChanging(IFileBuffer buffer) {
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see org.eclipse.core.filebuffers.IFileBufferListener#stateValidationChanged(org.eclipse.core.filebuffers.IFileBuffer,
+		 *      boolean)
+		 */
+		public void stateValidationChanged(IFileBuffer buffer, boolean isStateValidated) {
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see org.eclipse.core.filebuffers.IFileBufferListener#underlyingFileDeleted(org.eclipse.core.filebuffers.IFileBuffer)
+		 */
+		public void underlyingFileDeleted(IFileBuffer buffer) {
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see org.eclipse.core.filebuffers.IFileBufferListener#underlyingFileMoved(org.eclipse.core.filebuffers.IFileBuffer,
+		 *      org.eclipse.core.runtime.IPath)
+		 */
+		public void underlyingFileMoved(IFileBuffer buffer, IPath path) {
+		}
+
+
+	}
+
+	static TaglibController _instance = null;
+	static private boolean fIsShutdown = false;
+
+	public static IPath getLocation(IDocument document) {
+		synchronized (_instance.fDocumentMap) {
+			DocumentInfo info = (DocumentInfo) _instance.fDocumentMap.get(document);
+			if (info != null)
+				return info.location;
+			return null;
+		}
+	}
+
+	/**
+	 * @param manager
+	 * @return
+	 */
+	public static IPath getLocation(TLDCMDocumentManager manager) {
+		// if _instance is null, we are already shutting donw
+		if (_instance == null)
+			return null;
+
+		IPath location = null;
+		synchronized (_instance.fDocumentMap) {
+			Iterator docInfos = _instance.fDocumentMap.values().iterator();
+			while (docInfos.hasNext() && location == null) {
+				DocumentInfo info = (DocumentInfo) docInfos.next();
+				if (info.tldDocumentManager.equals(manager))
+					location = info.location;
+			}
+		}
+		return location;
+	}
+
+	public static TLDCMDocumentManager getTLDCMDocumentManager(IDocument document) {
+		// if _instance is null, we are already shutting down
+		if (_instance == null)
+			return null;
+		synchronized (_instance.fDocumentMap) {
+			DocumentInfo info = (DocumentInfo) _instance.fDocumentMap.get(document);
+			if (info != null)
+				return info.tldDocumentManager;
+			return null;
+
+		}
+	}
+
+	private static synchronized boolean isShutdown() {
+		return fIsShutdown;
+	}
+
+	private static synchronized void setShutdown(boolean isShutdown) {
+		fIsShutdown = isShutdown;
+	}
+
+	public synchronized static void shutdown() {
+		setShutdown(true);
+		FileBuffers.getTextFileBufferManager().removeFileBufferListener(_instance.fBufferListener);
+		_instance = null;
+	}
+
+	public synchronized static void startup() {
+		if (_instance == null) {
+			_instance = new TaglibController();
+			FileBuffers.getTextFileBufferManager().addFileBufferListener(_instance.fBufferListener);
+		}
+		setShutdown(false);
+	}
+
+	IFileBufferListener fBufferListener;
+
+	Map fDocumentMap;
+
+	List fJSPdocuments;
+
+	/*
+	 * This constructor is only to be called as part of the FileBuffer
+	 * framework
+	 */
+	public TaglibController() {
+		super();
+		fBufferListener = new FileBufferListener();
+		fJSPdocuments = new ArrayList(1);
+		fDocumentMap = new HashMap(1);
+	}
+
+
+	/*
+	 * This method is only to be called as part of the FileBuffer framework
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.core.filebuffers.IDocumentSetupParticipant#setup(org.eclipse.jface.text.IDocument)
+	 */
+	public void setup(IDocument document) {
+		// if we've already shutdown, just ignore
+		if (isShutdown())
+			return;
+		// reference the shared instance's documents directly
+		synchronized (_instance.fJSPdocuments) {
+			_instance.fJSPdocuments.add(document);
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.core.filebuffers.IDocumentSetupParticipantExtension#setup(org.eclipse.jface.text.IDocument,
+	 *      org.eclipse.core.runtime.IPath,
+	 *      org.eclipse.core.filebuffers.LocationKind)
+	 */
+	public void setup(IDocument document, IPath location, LocationKind locationKind) {
+		// if we've already shutdown, just ignore
+		if (isShutdown())
+			return;
+		// reference the shared instance's documents directly
+		synchronized (_instance.fJSPdocuments) {
+			_instance.fJSPdocuments.add(document);
+		}
+
+		DocumentInfo info = new DocumentInfo();
+		info.document = (IStructuredDocument) document;
+		info.textFileBuffer = null; // will be supplied later
+		info.location = location;
+		info.locationKind = locationKind;
+		info.tldDocumentManager = new TLDCMDocumentManager();
+		synchronized (_instance.fDocumentMap) {
+			_instance.fDocumentMap.put(document, info);
+		}
+		info.tldDocumentManager.setSourceParser((XMLSourceParser) info.document.getParser());
+		if (document instanceof BasicStructuredDocument && document.getLength() > 0) {
+			((BasicStructuredDocument) document).reparse(this);
+		}
+		TaglibIndex.addTaglibIndexListener(info);
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/CMAttributeDeclarationImpl.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/CMAttributeDeclarationImpl.java
new file mode 100644
index 0000000..f26a744
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/CMAttributeDeclarationImpl.java
@@ -0,0 +1,287 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.contentmodel.tld;
+
+
+
+import java.util.Enumeration;
+
+import org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.JSP12TLDNames;
+import org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.TLDAttributeDeclaration;
+import org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.TLDDocument;
+import org.eclipse.wst.sse.core.utils.StringUtils;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+public class CMAttributeDeclarationImpl implements TLDAttributeDeclaration {
+
+	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=170556
+	private static final CMDataType attrType = new CMDataTypeImpl(CMDataType.CDATA);
+	
+	private String fDescription;
+
+	//
+	private boolean fIsFragment = false;
+
+	private CMDocument fOwnerDocument;
+	// optional id
+	private String id = null;
+
+	// required name
+	private String name = null;
+	// optional "required" element present, defaults to not present
+	private boolean required = false;
+
+	// optional run-time (scriplet derived) value of attributes, defaults to
+	// none/false
+	private String rtexprvalue = null;
+
+	private String type = null;
+
+	/**
+	 * CMAttributeDeclarationImpl constructor comment.
+	 */
+	public CMAttributeDeclarationImpl(CMDocument owner) {
+		super();
+		fOwnerDocument = owner;
+	}
+
+	public CMAttributeDeclarationImpl(CMDocument owner, String defaultRtexprvalue) {
+		this(owner);
+		rtexprvalue = defaultRtexprvalue;
+	}
+
+	/**
+	 * getAttrName method
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getAttrName() {
+		return getNodeName();
+	}
+
+	/**
+	 * getAttrType method
+	 * 
+	 * @return CMDataType
+	 */
+	public CMDataType getAttrType() {
+		return attrType;
+	}
+
+	/**
+	 * @deprecated in superclass
+	 */
+	public String getDefaultValue() {
+		return ""; //$NON-NLS-1$
+	}
+
+	/**
+	 * @return Returns the description.
+	 */
+	public String getDescription() {
+		return fDescription;
+	}
+
+	/**
+	 * @deprecated in superclass
+	 */
+	public Enumeration getEnumAttr() {
+		return null;
+	}
+
+	/**
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getId() {
+		return id;
+	}
+
+	/**
+	 * getNodeName method
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getNodeName() {
+		return name;
+	}
+
+	/**
+	 * getNodeType method
+	 * 
+	 * @return int
+	 * 
+	 * Returns one of :
+	 * 
+	 */
+	public int getNodeType() {
+		return CMNode.ATTRIBUTE_DECLARATION;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jst.jsp.core.contentmodel.tld.TLDAttributeDeclaration#getOwnerDocument()
+	 */
+	public CMDocument getOwnerDocument() {
+		return fOwnerDocument;
+	}
+
+	/**
+	 * getProperty method
+	 * 
+	 * @return java.lang.Object
+	 * 
+	 * Returns the object property described by the propertyName
+	 * 
+	 */
+	public Object getProperty(String propertyName) {
+		if (propertyName != null && propertyName.equals(JSP12TLDNames.DESCRIPTION)) {
+			return getDescription(); // return attribute description
+		}
+		else if (propertyName.equals(TLDDocument.CM_KIND)) {
+			return TLDDocument.JSP_TLD;
+		}
+		else if (propertyName.equals(JSP12TLDNames.SMALL_ICON) || propertyName.equals(JSP12TLDNames.LARGE_ICON)) {
+			return getOwnerDocument().getProperty(propertyName);
+		}
+		return null;
+	}
+
+	/**
+	 * 
+	 * @return java.lang.String
+	 */
+	public java.lang.String getRtexprvalue() {
+		return rtexprvalue;
+	}
+
+	public String getType() {
+		return type;
+	}
+
+	/**
+	 * getUsage method
+	 * 
+	 * @return int OPTIONAL|REQUIRED
+	 */
+	public int getUsage() {
+		return required ? REQUIRED : OPTIONAL;
+	}
+
+	/**
+	 * @return Returns the isFragment.
+	 */
+	public boolean isFragment() {
+		return fIsFragment;
+	}
+
+	/**
+	 * 
+	 * @return boolean
+	 */
+	public boolean isRequired() {
+		return required;
+	}
+
+	/**
+	 * @param description
+	 *            The description to set.
+	 */
+	public void setDescription(String description) {
+		fDescription = description;
+	}
+
+	/**
+	 * @param isFragment
+	 *            The isFragment to set.
+	 */
+	public void setFragment(boolean isFragment) {
+		fIsFragment = isFragment;
+	}
+
+	/**
+	 * 
+	 * @param newId
+	 *            java.lang.String
+	 */
+	public void setId(String newId) {
+		id = newId;
+	}
+
+	public void setNodeName(String string) {
+		name = string;
+	}
+
+	/**
+	 * 
+	 * @param newRequired
+	 *            boolean
+	 */
+	public void setRequired(boolean newRequired) {
+		required = newRequired;
+	}
+
+	/**
+	 * 
+	 * @param newRequired
+	 *            boolean
+	 */
+	public void setRequiredString(String newRequired) {
+		if (newRequired != null) {
+			if (newRequired.equalsIgnoreCase(JSP12TLDNames.TRUE) || newRequired.equalsIgnoreCase(JSP12TLDNames.YES))
+				setRequired(true);
+			else if (newRequired.equalsIgnoreCase(JSP12TLDNames.FALSE) || newRequired.equalsIgnoreCase(JSP12TLDNames.NO))
+				setRequired(false);
+		}
+	}
+
+	/**
+	 * 
+	 * @param newRtexprvalue
+	 *            java.lang.String
+	 */
+	public void setRtexprvalue(String newRtexprvalue) {
+		rtexprvalue = newRtexprvalue;
+	}
+
+	public void setType(String type) {
+		this.type = type;
+	}
+
+	/**
+	 * supports method
+	 * 
+	 * @return boolean
+	 * 
+	 * Returns true if the CMNode supports a specified property
+	 * 
+	 */
+	public boolean supports(String propertyName) {
+		return propertyName == null || propertyName.equals(JSP12TLDNames.DESCRIPTION) || propertyName.equals(TLDDocument.CM_KIND) || propertyName.equals(JSP12TLDNames.SMALL_ICON) || propertyName.equals(JSP12TLDNames.LARGE_ICON);
+	}
+
+	public String toString() {
+		StringBuffer buffer = new StringBuffer();
+		buffer.append("\n\t " + super.toString()); //$NON-NLS-1$
+		buffer.append("\n\t name:" + StringUtils.escape(getNodeName())); //$NON-NLS-1$
+		// Boolean.toString(boolean) is introduced in 1.4
+		// buffer.append("\n\t required:" +
+		// StringUtils.escape(Boolean.toString(isRequired())));
+		buffer.append("\n\t required:" + StringUtils.toString(isRequired())); //$NON-NLS-1$
+		buffer.append("\n\t rtexpr:" + StringUtils.escape(getRtexprvalue())); //$NON-NLS-1$
+		if (getId() != null)
+			buffer.append("\n\t id:" + StringUtils.escape(getId())); //$NON-NLS-1$
+		return buffer.toString();
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/CMDataTypeImpl.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/CMDataTypeImpl.java
new file mode 100644
index 0000000..1c325a3
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/CMDataTypeImpl.java
@@ -0,0 +1,100 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.contentmodel.tld;
+
+
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+public class CMDataTypeImpl implements CMDataType {
+
+	protected String dataTypeName;
+
+	public CMDataTypeImpl(String dataTypeName) {
+		this.dataTypeName = dataTypeName;
+	}
+
+	/**
+	 * getTypeName method
+	 * @return java.lang.String
+	 *
+	 * This method returns a suitable default value that can be used when an instance of the data type is created.
+	 * This returns null of a suitable default is not available.
+	 */
+	public String generateInstanceValue() {
+		return null;
+	}
+
+	public String getDataTypeName() {
+		return dataTypeName;
+	}
+
+	/**
+	 * getTypeName method
+	 * @return java.lang.String[]
+	 *
+	 */
+	public String[] getEnumeratedValues() {
+		return null;
+	}
+
+	/**
+	 * getTypeName method
+	 * @return java.lang.String  
+	 *
+	 * Returns the implied value or null if none exists.
+	 */
+	public String getImpliedValue() {
+		return null;
+	}
+
+	/**
+	 * getImpliedValueKind method
+	 * @return int
+	 *
+	 * Returns one of :
+	 * IMPLIED_VALUE_NONE, IMPLIED_VALUE_FIXED, IMPLIED_VALUE_DEFAULT.
+	 */
+	public int getImpliedValueKind() {
+		return IMPLIED_VALUE_NONE;
+	}
+
+	public String getNodeName() {
+		return dataTypeName;
+	}
+
+	public int getNodeType() {
+		return CMNode.DATA_TYPE;
+	}
+
+	/**
+	 * getProperty method
+	 * @return java.lang.Object
+	 *
+	 * Returns the object property described by the propertyName
+	 *
+	 */
+	public Object getProperty(String propertyName) {
+		return null;
+	}
+
+	/**
+	 * supports method
+	 * @return boolean
+	 *
+	 * Returns true if the CMNode supports a specified property
+	 *
+	 */
+	public boolean supports(String propertyName) {
+		return false;
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/CMDocumentFactoryTLD.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/CMDocumentFactoryTLD.java
new file mode 100644
index 0000000..18d777e
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/CMDocumentFactoryTLD.java
@@ -0,0 +1,1119 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.contentmodel.tld;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jst.jsp.core.internal.Logger;
+import org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.JSP11TLDNames;
+import org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.JSP12TLDNames;
+import org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.JSP20TLDNames;
+import org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.TLDDocument;
+import org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.TLDElementDeclaration;
+import org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.TLDFunction;
+import org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.TLDInitParam;
+import org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.TLDListener;
+import org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.TLDValidator;
+import org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.TLDVariable;
+import org.eclipse.jst.jsp.core.internal.modelhandler.ModelHandlerForJSP;
+import org.eclipse.jst.jsp.core.internal.provisional.JSP11Namespace;
+import org.eclipse.jst.jsp.core.internal.provisional.JSP20Namespace;
+import org.eclipse.jst.jsp.core.internal.regions.DOMJSPRegionContexts;
+import org.eclipse.jst.jsp.core.internal.util.DocumentProvider;
+import org.eclipse.jst.jsp.core.internal.util.FacetModuleCoreSupport;
+import org.eclipse.jst.jsp.core.taglib.IJarRecord;
+import org.eclipse.jst.jsp.core.taglib.ITLDRecord;
+import org.eclipse.jst.jsp.core.taglib.ITagDirRecord;
+import org.eclipse.jst.jsp.core.taglib.ITaglibRecord;
+import org.eclipse.jst.jsp.core.taglib.IURLRecord;
+import org.eclipse.wst.common.uriresolver.internal.util.URIHelper;
+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.ITextRegionList;
+import org.eclipse.wst.sse.core.internal.util.JarUtilities;
+import org.eclipse.wst.sse.core.utils.StringUtils;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.factory.CMDocumentFactory;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+import org.w3c.dom.Element;
+import org.w3c.dom.EntityReference;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * CMDocumentBuilder for Taglib Descriptors
+ * 
+ * Returns namespace-less CMDocuments for a taglib descriptor, loading it
+ * directly from a file or extracted from a JAR archive. Content Model objects
+ * will implement the TLDCMDocument, TLDElementDeclaration, and
+ * TLDAttributeDeclaration interfaces for extended properties.
+ */
+public class CMDocumentFactoryTLD implements CMDocumentFactory {
+	static final boolean _debug = "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.jst.jsp.core/debug/tldcmdocument/factory")); //$NON-NLS-1$ //$NON-NLS-2$
+
+	/**
+	 * CMDocumentFactoryTLD constructor comment.
+	 */
+	public CMDocumentFactoryTLD() {
+		super();
+	}
+
+	/**
+	 * NOT API
+	 * 
+	 * @param baselocation
+	 * @param input
+	 * @return
+	 */
+	public CMDocument buildCMDocument(String baselocation, InputStream input) {
+		DocumentProvider provider = new DocumentProvider();
+		provider.setValidating(false);
+		provider.setRootElementName(JSP11TLDNames.TAGLIB);
+		provider.setInputStream(input);
+		if (baselocation != null)
+			provider.setBaseReference(baselocation);
+		return loadDocument(baselocation, provider.getRootElement());
+	}
+
+	/**
+	 * @param fileName
+	 * @return
+	 */
+	private CMDocumentImpl buildCMDocumentFromFolder(IPath path) {
+		if (_debug) {
+			System.out.println("tagdir loading for " + path); //$NON-NLS-1$
+		}
+		// EBNF is listed at 1.3.10
+		CMDocumentImpl document = new CMDocumentImpl();
+		document.setBaseLocation(path.toString());
+		document.setTlibversion("1.0"); //$NON-NLS-1$
+		IFolder folder = ResourcesPlugin.getWorkspace().getRoot().getFolder(path);
+		IResource[] tagfiles;
+		try {
+			tagfiles = folder.members();
+			for (int i = 0; i < tagfiles.length; i++) {
+				if (tagfiles[i].getType() == IResource.FILE) {
+					if (tagfiles[i].getType() != IResource.FILE)
+						continue;
+					String extension = tagfiles[i].getFileExtension();
+					if (extension != null && (extension.equals("tag") || extension.equals("tagx"))) {
+						CMElementDeclaration ed = createElementDeclaration(document, (IFile) tagfiles[i]);
+						if (ed != null) {
+							document.fElements.setNamedItem(ed.getNodeName(), ed);
+						}
+					}
+				}
+			}
+		}
+		catch (CoreException e) {
+			Logger.logException(e);
+		}
+		return document;
+	}
+
+	/**
+	 * NOT API
+	 * 
+	 * @param fileName
+	 * @return
+	 */
+	protected CMDocument buildCMDocumentFromFile(String fileName) {
+		// load the taglib descriptor file
+		DocumentProvider provider = new DocumentProvider();
+		provider.setValidating(false);
+		provider.setBaseReference(fileName);
+		provider.setRootElementName(JSP11TLDNames.TAGLIB);
+		provider.setFileName(fileName);
+		Node rootElement = provider.getRootElement();
+		return loadDocument(fileName, rootElement);
+	}
+
+	/**
+	 * Builds a CMDocument assuming the JSP v1.1 default path
+	 * 
+	 * @param jarFileName -
+	 *            the name of the containing JAR file
+	 */
+	protected CMDocument buildCMDocumentFromJar(String jarFileName) {
+		// load the taglib descriptor file
+		return buildCMDocumentFromJar(jarFileName, JarUtilities.JSP11_TAGLIB);
+	}
+
+	/**
+	 * Builds a CMDocument
+	 * 
+	 * @param jarFileName -
+	 *            the name of the containing JAR file
+	 * @param contentFileName -
+	 *            the path within the JAR for a valid taglib descriptor
+	 */
+	protected CMDocument buildCMDocumentFromJar(String jarFileName, String contentFileName) {
+		// load the taglib descriptor file
+		DocumentProvider provider = new DocumentProvider();
+		provider.setValidating(false);
+		provider.setBaseReference(jarFileName);
+		provider.setRootElementName(JSP11TLDNames.TAGLIB);
+		provider.setJarFileName(jarFileName);
+		provider.setFileName(contentFileName);
+		CMDocument document = loadDocument("jar:file://" + jarFileName + "!" + contentFileName, provider.getRootElement()); //$NON-NLS-1$ //$NON-NLS-2$
+		// TODO: Add the tags declared in META-INF/tags, see JSP 2.0 section
+		// 8.4.1
+		return document;
+	}
+
+	protected CMAttributeDeclaration createAttributeDeclaration(CMDocument document, Node attrNode) {
+		CMAttributeDeclarationImpl attr = new CMAttributeDeclarationImpl(document);
+
+		Node child = attrNode.getFirstChild();
+		while (child != null) {
+			if (child.getNodeType() == Node.ELEMENT_NODE) {
+				if (child.getNodeName().equals(JSP11TLDNames.NAME) && child.hasChildNodes()) {
+					attr.setNodeName(getContainedText(child));
+				}
+				else if (child.getNodeName().equals(JSP12TLDNames.DESCRIPTION) && child.hasChildNodes()) {
+					attr.setDescription(getContainedText(child));
+				}
+				else if (child.getNodeName().equals(JSP11TLDNames.ID) && child.hasChildNodes()) {
+					attr.setId(getContainedText(child));
+				}
+				else if (child.getNodeName().equals(JSP11TLDNames.REQUIRED) && child.hasChildNodes()) {
+					attr.setRequiredString(getContainedText(child));
+				}
+				else if (child.getNodeName().equals(JSP11TLDNames.RTEXPRVALUE) && child.hasChildNodes()) {
+					attr.setRtexprvalue(getContainedText(child));
+				}
+				else if (child.getNodeName().equals(JSP20TLDNames.FRAGMENT) && child.hasChildNodes()) {
+					attr.setFragment(Boolean.valueOf(getContainedText(child)).booleanValue());
+				}
+			}
+			child = child.getNextSibling();
+		}
+
+		return attr;
+	}
+
+	/**
+	 * Builds a CMDocument from a taglib descriptor
+	 * 
+	 * @param uri -
+	 *            the location of a valid taglib descriptor
+	 */
+	public CMDocument createCMDocument(String uri) {
+		CMDocument result = null;
+		URL url = null;
+		try {
+			url = new URL(uri);
+		}
+		catch (MalformedURLException e) {
+			result = createCMDocumentFromFile(uri);
+		}
+		if (result == null && url != null) {
+			if (url.getProtocol().equals("file")) { //$NON-NLS-1$
+				result = createCMDocumentFromFile(url.getFile());
+			}
+			else {
+				/**
+				 * Skip anything else since trying to load a TLD from a remote
+				 * location has unpredictable performance impact.
+				 */
+			}
+		}
+		if (result == null)
+			result = new CMDocumentImpl();
+		return result;
+	}
+
+	/**
+	 * @param fileName
+	 * @return
+	 */
+	private CMDocument createCMDocumentFromFile(String fileName) {
+		CMDocument result = null;
+		if (fileName.endsWith(".jar")) { //$NON-NLS-1$
+			result = buildCMDocumentFromJar(fileName);
+		}
+		else {
+			File file = new File(fileName);
+			try {
+				if (file.isDirectory()) {
+					result = buildCMDocumentFromDirectory(file);
+				}
+				else {
+					result = buildCMDocumentFromFile(fileName);
+				}
+			}
+			catch (SecurityException e) {
+				result = null;
+			}
+		}
+		return result;
+	}
+
+	private CMDocument buildCMDocumentFromDirectory(File file) {
+		IFile[] foundFilesForLocation = ResourcesPlugin.getWorkspace().getRoot().findFilesForLocation(new Path(file.getPath()));
+		for (int i = 0; i < foundFilesForLocation.length; i++) {
+			if (foundFilesForLocation[i].isAccessible() && foundFilesForLocation[i].getType() == IResource.FOLDER) {
+				return buildCMDocumentFromFolder(foundFilesForLocation[i].getFullPath());
+			}
+		}
+		return null;
+	}
+
+	protected CMElementDeclaration createElementDeclaration(CMDocumentImpl document, Element tagFileNode, String path) {
+		CMElementDeclarationImpl ed = new CMElementDeclarationImpl(document);
+		/*
+		 * Preload with information from the tag file--it can be overwritten
+		 * by the values from the TLD
+		 */
+		IPath tagPath = FacetModuleCoreSupport.resolve(new Path(document.getBaseLocation()), path);
+		if (tagPath.segmentCount() > 1) {
+			IFile tagFile = ResourcesPlugin.getWorkspace().getRoot().getFile(tagPath);
+			if (tagFile.isAccessible()) {
+				ed.setPath(tagFile.getFullPath().toString());
+				if (tagPath.getFileExtension().equals("tag")) {
+					loadTagFile(ed, tagFile, true);
+				}
+				else if (tagPath.getFileExtension().equals("tagx")) {
+					loadTagXFile(ed, tagFile, true);
+				}
+
+				if (tagFile.getLocation() != null && ed.getSmallIcon() != null) {
+					ed.setSmallIconURL(URIHelper.normalize(ed.getSmallIcon(), "file:" + tagFile.getLocation().toString(), tagFile.getLocation().removeLastSegments(1).toString()));
+				}
+			}
+			else if (isJarFile(document.getBaseLocation())) {
+				String jarLocation = document.getBaseLocation();
+				String[] entries = JarUtilities.getEntryNames(jarLocation);
+				boolean tag;
+				for (int jEntry = 0; jEntry < entries.length; jEntry++) {
+					tag = false;
+					if (((tag = entries[jEntry].endsWith(".tag")) || entries[jEntry].endsWith(".tagx")) && entries[jEntry].startsWith("META-INF/tags/")) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+							InputStream contents = JarUtilities.getInputStream(jarLocation, entries[jEntry]);
+							if (tag) {//$NON-NLS-1$ 
+								loadTagFile(ed, tagFile, true, contents);
+							}
+							else {
+								loadTagXFile(ed, tagFile, true, contents);
+							}
+							try {
+								contents.close();
+							}
+							catch (IOException e) {
+								Logger.log(Logger.ERROR_DEBUG, null, e);
+							}
+						}
+					}	
+			}
+		}
+
+		// load information declared within the .tld
+		Node child = tagFileNode.getFirstChild();
+		while (child != null) {
+			if (child.getNodeType() == Node.ELEMENT_NODE) {
+				String nodeName = child.getNodeName();
+				if (nodeName.equals(JSP12TLDNames.DESCRIPTION) && child.hasChildNodes()) {
+					ed.setDescription(getContainedText(child));
+				}
+				else if (nodeName.equals(JSP12TLDNames.DISPLAY_NAME) && child.hasChildNodes()) {
+					ed.setDisplayName(getContainedText(child));
+				}
+				else if (nodeName.equals(JSP20TLDNames.EXAMPLE) && child.hasChildNodes()) {
+					ed.setExample(getContainedText(child));
+				}
+				else if (nodeName.equals(JSP20TLDNames.ICON) && child.hasChildNodes()) {
+					ed.setSmallIcon(getContainedText(child));
+				}
+				else if (nodeName.equals(JSP12TLDNames.NAME) && child.hasChildNodes()) {
+					ed.setNodeName(getContainedText(child));
+				}
+				else if (nodeName.equals(JSP20TLDNames.PATH) && child.hasChildNodes()) {
+					ed.setPath(getContainedText(child));
+				}
+				else if (nodeName.equals(JSP20TLDNames.TAG_EXTENSION)) {
+					ed.getExtensions().add(child);
+				}
+			}
+			child = child.getNextSibling();
+		}
+		
+		return ed;
+	}
+
+	private boolean isJarFile(String path) {
+		if (path == null)
+			return false;
+		final int idx = path.lastIndexOf('.');
+		return idx >= 0 && idx < (path.length() - 1) && path.substring(idx + 1).equalsIgnoreCase("jar"); //$NON-NLS-1$
+	}
+
+	protected CMElementDeclaration createElementDeclaration(CMDocument document, Node tagNode) {
+		CMElementDeclarationImpl ed = new CMElementDeclarationImpl(document);
+
+		Node child = tagNode.getFirstChild();
+		while (child != null) {
+			if (child.getNodeType() == Node.ELEMENT_NODE) {
+				// tag information
+				String nodeName = child.getNodeName();
+				if (nodeName.equals(JSP11TLDNames.NAME) && child.hasChildNodes()) {
+					ed.setNodeName(getContainedText(child));
+				}
+				else if ((nodeName.equals(JSP11TLDNames.TAGCLASS) || nodeName.equals(JSP12TLDNames.TAG_CLASS)) && child.hasChildNodes()) {
+					ed.setTagclass(getContainedText(child));
+				}
+				else if ((nodeName.equals(JSP11TLDNames.TEICLASS) || nodeName.equals(JSP12TLDNames.TEI_CLASS)) && child.hasChildNodes()) {
+					ed.setTeiclass(getContainedText(child));
+				}
+				else if ((nodeName.equals(JSP11TLDNames.BODYCONTENT) || nodeName.equals(JSP12TLDNames.BODY_CONTENT)) && child.hasChildNodes()) {
+					String bodycontent = getContainedText(child);
+					// Apparently, Apache Tomcat is not case sensitive about
+					// these values
+					if (bodycontent.equalsIgnoreCase(JSP11TLDNames.CONTENT_JSP))
+						ed.setBodycontent(JSP11TLDNames.CONTENT_JSP);
+					else if (bodycontent.equalsIgnoreCase(JSP11TLDNames.CONTENT_TAGDEPENDENT))
+						ed.setBodycontent(JSP11TLDNames.CONTENT_TAGDEPENDENT);
+					else if (bodycontent.equalsIgnoreCase(JSP11TLDNames.CONTENT_EMPTY))
+						ed.setBodycontent(JSP11TLDNames.CONTENT_EMPTY);
+					else if (bodycontent.equalsIgnoreCase(JSP20TLDNames.CONTENT_SCRIPTLESS))
+						ed.setBodycontent(JSP20TLDNames.CONTENT_SCRIPTLESS);
+				}
+				// info (1.1 only) or description (1.2 only)
+				else if ((nodeName.equals(JSP11TLDNames.INFO) || nodeName.equals(JSP12TLDNames.DESCRIPTION)) && child.hasChildNodes()) {
+					ed.setDescription(getContainedText(child));
+				}
+				// attributes
+				else if (nodeName.equals(JSP11TLDNames.ATTRIBUTE)) {
+					CMAttributeDeclaration attr = createAttributeDeclaration(document, child);
+					ed.fAttributes.setNamedItem(attr.getAttrName(), attr);
+				}
+				// variables
+				else if (nodeName.equals(JSP12TLDNames.VARIABLE)) {
+					ed.getVariables().add(createVariable(child));
+				}
+				else if (nodeName.equals(JSP12TLDNames.LARGE_ICON) && child.hasChildNodes()) {
+					ed.setLargeIcon(getContainedText(child));
+				}
+				else if (nodeName.equals(JSP12TLDNames.SMALL_ICON) && child.hasChildNodes()) {
+					ed.setSmallIcon(getContainedText(child));
+				}
+				else if (nodeName.equals(JSP20TLDNames.TAG_EXTENSION) && child.getNodeType() == Node.ELEMENT_NODE) {
+					ed.getExtensions().add(child);
+				}
+				else if (nodeName.equals(JSP20TLDNames.DYNAMIC_ATTRIBUTES) && child.hasChildNodes()) {
+					ed.setDynamicAttributes(getContainedText(child));
+				}
+			}
+			child = child.getNextSibling();
+		}
+		return ed;
+	}
+
+	private CMElementDeclaration createElementDeclaration(CMDocument document, IFile tagFile) {
+		CMElementDeclarationImpl ed = new CMElementDeclarationImpl(document);
+		// in tag files, the default body content is scriptless instead of JSP
+		ed.setBodycontent(JSP20TLDNames.CONTENT_SCRIPTLESS);
+		String shortFilename = tagFile.getName();
+		String fileExtension = tagFile.getFileExtension();
+		if (fileExtension != null && fileExtension.length() > 0) {
+			shortFilename = shortFilename.substring(0, shortFilename.length() - fileExtension.length() - 1);
+		}
+		ed.setNodeName(shortFilename);
+		ed.setPath(tagFile.getFullPath().toString());
+		if (fileExtension.equals("tag")) {
+			loadTagFile(ed, tagFile, true);
+		}
+		else if (fileExtension.equals("tagx")) {
+			loadTagXFile(ed, tagFile, true);
+		}
+
+		if (tagFile.getLocation() != null && ed.getSmallIcon() != null) {
+			ed.setSmallIconURL(URIHelper.normalize(ed.getSmallIcon(), "file:" + tagFile.getLocation().toString(), tagFile.getLocation().removeLastSegments(1).toString()));
+		}
+		return ed;
+	}
+
+	protected TLDFunction createFunction(CMDocument document, Node functionNode) {
+		TLDFunctionImpl function = new TLDFunctionImpl(document);
+		boolean hasName = false;
+
+		Node child = functionNode.getFirstChild();
+		while (child != null) {
+			if (child.getNodeType() == Node.ELEMENT_NODE) {
+				// tag information
+				String nodeName = child.getNodeName();
+				if (nodeName.equals(JSP12TLDNames.DESCRIPTION) && child.hasChildNodes()) {
+					function.setDescription(getContainedText(child));
+				}
+				else if (nodeName.equals(JSP12TLDNames.DISPLAY_NAME) && child.hasChildNodes()) {
+					function.setName(getContainedText(child));
+				}
+				else if (nodeName.equals(JSP20TLDNames.EXAMPLE) && child.hasChildNodes()) {
+					function.setExample(getContainedText(child));
+				}
+				else if (nodeName.equals(JSP20TLDNames.FUNCTION_CLASS) && child.hasChildNodes()) {
+					function.setClassName(getContainedText(child));
+				}
+				else if (nodeName.equals(JSP20TLDNames.FUNCTION_EXTENSION) && child.hasChildNodes()) {
+					function.getExtensions().add(child);
+				}
+				else if (nodeName.equals(JSP20TLDNames.FUNCTION_SIGNATURE) && child.hasChildNodes()) {
+					function.setSignature(getContainedText(child));
+				}
+				else if (nodeName.equals(JSP20TLDNames.ICON) && child.hasChildNodes()) {
+					function.setIcon(getContainedText(child));
+				}
+				else if (nodeName.equals(JSP12TLDNames.NAME) && child.hasChildNodes()) {
+					function.setName(getContainedText(child));
+					hasName = function.getName().trim().length() > 0;
+				}
+			}
+			child = child.getNextSibling();
+		}
+		if (hasName) {
+			return function;
+		}
+		return null;
+	}
+
+	protected TLDInitParam createInitParam(Node initParamNode) {
+		TLDInitParamImpl initParam = new TLDInitParamImpl();
+		Node child = initParamNode.getFirstChild();
+		while (child != null) {
+			if (child.getNodeType() == Node.ELEMENT_NODE) {
+				String nodeName = child.getNodeName();
+				if (nodeName.equals(JSP12TLDNames.VALIDATOR_PARAM_NAME) && child.hasChildNodes()) {
+					initParam.setName(getContainedText(child));
+				}
+				else if (nodeName.equals(JSP12TLDNames.VALIDATOR_PARAM_VALUE) && child.hasChildNodes()) {
+					initParam.setValue(getContainedText(child));
+				}
+				else if (nodeName.equals(JSP12TLDNames.DESCRIPTION) && child.hasChildNodes()) {
+					initParam.setDescription(getContainedText(child));
+				}
+			}
+			child = child.getNextSibling();
+		}
+		return initParam;
+	}
+
+	protected TLDListener createListener(Node listenerNode) {
+		TLDListenerImpl listener = new TLDListenerImpl();
+		Node child = listenerNode.getFirstChild();
+		while (child != null) {
+			if (child.getNodeType() == Node.ELEMENT_NODE) {
+				String nodeName = child.getNodeName();
+				if (nodeName.equals(JSP12TLDNames.LISTENER_CLASS) && child.hasChildNodes()) {
+					listener.setListenerClass(getContainedText(child));
+				}
+			}
+			child = child.getNextSibling();
+		}
+		return listener;
+	}
+
+	protected TLDValidator createValidator(Node validatorNode) {
+		TLDValidatorImpl validator = new TLDValidatorImpl();
+		Node child = validatorNode.getFirstChild();
+		while (child != null) {
+			if (child.getNodeType() == Node.ELEMENT_NODE) {
+				String nodeName = child.getNodeName();
+				if (nodeName.equals(JSP12TLDNames.VALIDATOR_CLASS) && child.hasChildNodes()) {
+					validator.setValidatorClass(getContainedText(child));
+				}
+				else if (nodeName.equals(JSP12TLDNames.VALIDATOR_INIT_PARAM) && child.hasChildNodes()) {
+					validator.getInitParams().add(createInitParam(child));
+				}
+			}
+			child = child.getNextSibling();
+		}
+		return validator;
+	}
+
+	protected TLDVariable createVariable(Node variableNode) {
+		TLDVariableImpl variable = new TLDVariableImpl();
+		Node child = variableNode.getFirstChild();
+		while (child != null) {
+			if (child.getNodeType() == Node.ELEMENT_NODE) {
+				String nodeName = child.getNodeName();
+				if (nodeName.equals(JSP12TLDNames.VARIABLE_CLASS) && child.hasChildNodes()) {
+					variable.setVariableClass(getContainedText(child));
+				}
+				else if (nodeName.equals(JSP12TLDNames.VARIABLE_DECLARE) && child.hasChildNodes()) {
+					variable.setDeclareString(getContainedText(child));
+				}
+				else if (nodeName.equals(JSP12TLDNames.VARIABLE_NAME_FROM_ATTRIBUTE) && child.hasChildNodes()) {
+					variable.setNameFromAttribute(getContainedText(child));
+				}
+				else if (nodeName.equals(JSP12TLDNames.VARIABLE_NAME_GIVEN) && child.hasChildNodes()) {
+					variable.setNameGiven(getContainedText(child));
+				}
+				else if (nodeName.equals(JSP12TLDNames.VARIABLE_SCOPE) && child.hasChildNodes()) {
+					variable.setScope(getContainedText(child));
+				}
+				else if (nodeName.equals(JSP12TLDNames.DESCRIPTION) && child.hasChildNodes()) {
+					variable.setDescription(getContainedText(child));
+				}
+			}
+			child = child.getNextSibling();
+		}
+		return variable;
+	}
+
+	protected String getContainedText(Node parent) {
+		NodeList children = parent.getChildNodes();
+		if (children.getLength() == 1) {
+			return getValue(children.item(0));
+		}
+		StringBuffer s = new StringBuffer();
+		Node child = parent.getFirstChild();
+		while (child != null) {
+			if (child.getNodeType() == Node.ENTITY_REFERENCE_NODE) {
+				String reference = ((EntityReference) child).getNodeValue();
+				if (reference == null && child.getNodeName() != null) {
+					reference = "&" + child.getNodeName() + ";"; //$NON-NLS-1$ //$NON-NLS-2$
+				}
+				if (reference != null) {
+					s.append(reference.trim());
+				}
+			}
+			else {
+				s.append(getValue(child));
+			}
+			child = child.getNextSibling();
+		}
+		return s.toString().trim();
+	}
+
+	private String getValue(Node n) {
+		if (n == null)
+			return ""; //$NON-NLS-1$
+		String value = n.getNodeValue();
+		if (value == null)
+			return ""; //$NON-NLS-1$
+		return value.trim();
+	}
+
+	public boolean isBuilderForGrammar(String grammarFileName) {
+		String fileName = grammarFileName.toLowerCase();
+		return fileName.endsWith(".tld") || fileName.endsWith(".jar"); //$NON-NLS-2$//$NON-NLS-1$
+	}
+
+	private CMDocument loadDocument(String baseLocation, Node taglib) {
+		Node root = taglib;
+
+		// create the CMDocument
+		CMDocumentImpl document = new CMDocumentImpl();
+		document.setBaseLocation(baseLocation);
+
+		if (root == null) {
+			if (_debug) {
+				System.out.println("null \"taglib\" element for TLD " + baseLocation); //$NON-NLS-1$
+			}
+			return document;
+		}
+
+		// populate the CMDocument
+		Node child = root.getFirstChild();
+		while (child != null) {
+			if (child.getNodeType() != Node.ELEMENT_NODE) {
+				child = child.getNextSibling();
+				continue;
+			}
+			String nodeName = child.getNodeName();
+			if(nodeName.indexOf(':') > 0) {
+				nodeName = nodeName.substring(nodeName.indexOf(':'));
+			}
+			// tag
+			if (nodeName.equals(JSP11TLDNames.TAG)) {
+				CMElementDeclaration ed = createElementDeclaration(document, child);
+				if (ed != null) {
+					document.fElements.setNamedItem(ed.getNodeName(), ed);
+				}
+			}
+			// tag-file
+			else if (nodeName.equals(JSP20TLDNames.TAG_FILE) && child.getNodeType() == Node.ELEMENT_NODE && child.hasChildNodes()) {
+				Element tagFileElement = (Element) child;
+				Node path = tagFileElement.getFirstChild();
+				while (path != null) {
+					if (path.getNodeType() == Node.ELEMENT_NODE && (JSP20TLDNames.PATH.equals(path.getNodeName()) || JSP20TLDNames.PATH.equals(path.getLocalName()))) {
+						String pathValue = getContainedText(path);
+						if (pathValue != null && pathValue.length() > 0) {
+							CMElementDeclarationImpl ed = (CMElementDeclarationImpl) createElementDeclaration(document, tagFileElement, pathValue);
+							if (ed != null) {
+								document.fElements.setNamedItem(ed.getNodeName(), ed);
+							}
+						}
+					}
+					path = path.getNextSibling();
+				}
+			}
+			// other one-of-a-kind children
+			// JSP version
+			else if ((nodeName.equals(JSP11TLDNames.JSPVERSION) || nodeName.equals(JSP12TLDNames.JSP_VERSION)) && child.hasChildNodes()) {
+				document.setJspversion(getContainedText(child));
+			}
+			// tag library version
+			else if ((nodeName.equals(JSP11TLDNames.TLIBVERSION) || nodeName.equals(JSP12TLDNames.TLIB_VERSION)) && child.hasChildNodes()) {
+				document.setTlibversion(getContainedText(child));
+			}
+			// short name
+			else if ((nodeName.equals(JSP11TLDNames.SHORTNAME) || nodeName.equals(JSP12TLDNames.SHORT_NAME)) && child.hasChildNodes()) {
+				document.setShortname(getContainedText(child));
+			}
+			// URI/URN
+			else if ((nodeName.equals(JSP11TLDNames.URI) || nodeName.equals(JSP11TLDNames.URN)) && child.hasChildNodes()) { //$NON-NLS-1$
+				document.setUri(getContainedText(child));
+			}
+			// info
+			else if (nodeName.equals(JSP11TLDNames.INFO) && child.hasChildNodes()) {
+				document.setInfo(getContainedText(child));
+			}
+			// New JSP 1.2
+			// description
+			else if (nodeName.equals(JSP12TLDNames.DESCRIPTION) && child.hasChildNodes()) {
+				document.setDescription(getContainedText(child));
+			}
+			// display name
+			else if (nodeName.equals(JSP12TLDNames.DISPLAY_NAME) && child.hasChildNodes()) {
+				document.setDisplayName(getContainedText(child));
+			}
+			// large icon
+			else if (nodeName.equals(JSP12TLDNames.LARGE_ICON) && child.hasChildNodes()) {
+				document.setLargeIcon(getContainedText(child));
+			}
+			// small icon
+			else if (nodeName.equals(JSP12TLDNames.SMALL_ICON) && child.hasChildNodes()) {
+				document.setSmallIcon(getContainedText(child));
+			}
+			// validator
+			else if (nodeName.equals(JSP12TLDNames.VALIDATOR)) {
+				document.setValidator(createValidator(child));
+			}
+			// listener
+			else if (nodeName.equals(JSP12TLDNames.LISTENER)) {
+				document.getListeners().add(createListener(child));
+			}
+			else if (nodeName.equals(JSP20TLDNames.FUNCTION)) {
+				TLDFunction function = createFunction(document, child);
+				if (function != null) {
+					document.getFunctions().add(function);
+				}
+			}
+			else if (nodeName.equals(JSP20TLDNames.TAGLIB_EXTENSION)) {
+				document.getExtensions().add(child);
+			}
+
+			child = child.getNextSibling();
+		}
+		return document;
+	}
+
+	private void loadTagXFile(final CMElementDeclarationImpl ed, IFile tagxFile, boolean allowIncludes) {
+	  loadTagXFile(ed, tagxFile, allowIncludes, null);
+	}
+	
+	private void loadTagXFile(final CMElementDeclarationImpl ed, IFile tagxFile, boolean allowIncludes, InputStream inputStream) {
+		ed.setPath(tagxFile.getFullPath().toString());
+		ed.setTagSource(TLDElementDeclaration.SOURCE_TAG_FILE);
+		try {
+			SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
+			InputSource inputSource = new InputSource(tagxFile.getFullPath().toString());
+			InputStream input = inputStream != null ? inputStream : tagxFile.getContents(false);
+			inputSource.setByteStream(input);
+			parser.parse(inputSource, new DefaultHandler() {
+				public InputSource resolveEntity(String publicId, String systemId) throws SAXException {
+					InputSource inputSource2 = new InputSource(systemId);
+					inputSource2.setByteStream(new ByteArrayInputStream(new byte[0]));
+					return inputSource2;
+				}
+
+				public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
+					super.startElement(uri, localName, qName, attributes);
+					if (qName.equals(JSP20Namespace.ElementName.DIRECTIVE_TAG)) {
+						if (attributes.getIndex(JSP12TLDNames.DISPLAY_NAME) >= 0)
+							ed.setDisplayName(attributes.getValue(JSP12TLDNames.DISPLAY_NAME));
+						if (attributes.getIndex(JSP12TLDNames.BODY_CONTENT) >= 0)
+							ed.setBodycontent(attributes.getValue(JSP12TLDNames.BODY_CONTENT));
+						if (attributes.getIndex(JSP20TLDNames.DYNAMIC_ATTRIBUTES) >= 0)
+							ed.setDynamicAttributes(attributes.getValue(JSP20TLDNames.DYNAMIC_ATTRIBUTES));
+						if (attributes.getIndex(JSP12TLDNames.SMALL_ICON) >= 0)
+							ed.setSmallIcon(attributes.getValue(JSP12TLDNames.SMALL_ICON));
+						if (attributes.getIndex(JSP12TLDNames.LARGE_ICON) >= 0)
+							ed.setLargeIcon(attributes.getValue(JSP12TLDNames.LARGE_ICON));
+						if (attributes.getIndex(JSP12TLDNames.DESCRIPTION) >= 0)
+							ed.setDescription(attributes.getValue(JSP12TLDNames.DESCRIPTION));
+						if (attributes.getIndex(JSP20TLDNames.EXAMPLE) >= 0)
+							ed.setExample(attributes.getValue(JSP20TLDNames.EXAMPLE));
+						if (attributes.getIndex(JSP20TLDNames.SCRIPTING_LANGUAGE) >= 0)
+							ed.setScriptingLanguage(attributes.getValue(JSP20TLDNames.SCRIPTING_LANGUAGE));
+						if (attributes.getIndex(JSP20TLDNames.IMPORT) >= 0)
+							ed.setImport(attributes.getValue(JSP20TLDNames.IMPORT));
+						if (attributes.getIndex(JSP20TLDNames.PAGE_ENCODING) >= 0)
+							ed.setPageEncoding(attributes.getValue(JSP20TLDNames.PAGE_ENCODING));
+						if (attributes.getIndex(JSP20TLDNames.IS_EL_IGNORED) >= 0)
+							ed.setIsELIgnored(attributes.getValue(JSP20TLDNames.IS_EL_IGNORED));
+					}
+					else if (qName.equals(JSP20Namespace.ElementName.DIRECTIVE_ATTRIBUTE)) {
+						CMAttributeDeclarationImpl attribute = new CMAttributeDeclarationImpl(ed.getOwnerDocument());
+						String nameValue = attributes.getValue(JSP12TLDNames.NAME);
+						attribute.setNodeName(nameValue);
+						if (attributes.getIndex(JSP20TLDNames.FRAGMENT) >= 0)
+							attribute.setFragment(Boolean.valueOf(attributes.getValue(JSP20TLDNames.FRAGMENT)).booleanValue());
+						if (attributes.getIndex(JSP12TLDNames.RTEXPRVALUE) >= 0)
+							attribute.setRtexprvalue(attributes.getValue(JSP12TLDNames.RTEXPRVALUE));
+						if (attributes.getIndex(JSP20TLDNames.TYPE) >= 0)
+							attribute.setType(attributes.getValue(JSP20TLDNames.TYPE));
+						if (attributes.getIndex(JSP12TLDNames.DESCRIPTION) >= 0)
+							attribute.setDescription(attributes.getValue(JSP12TLDNames.DESCRIPTION));
+						if (attributes.getIndex(JSP12TLDNames.REQUIRED) >= 0)
+							attribute.setRequiredString(attributes.getValue(JSP12TLDNames.REQUIRED));
+						if (nameValue != null && nameValue.length() > 0) {
+							ed.fAttributes.setNamedItem(nameValue, attribute);
+						}
+					}
+					else if (qName.equals(JSP20Namespace.ElementName.DIRECTIVE_VARIABLE)) {
+						TLDVariableImpl variable = new TLDVariableImpl();
+						if (attributes.getIndex(JSP12TLDNames.VARIABLE_NAME_GIVEN) >= 0)
+							variable.setNameGiven(attributes.getValue(JSP12TLDNames.VARIABLE_NAME_GIVEN));
+						if (attributes.getIndex(JSP12TLDNames.VARIABLE_NAME_FROM_ATTRIBUTE) >= 0)
+							variable.setNameFromAttribute(attributes.getValue(JSP12TLDNames.VARIABLE_NAME_FROM_ATTRIBUTE));
+						if (attributes.getIndex(JSP20TLDNames.VARIABLE_ALIAS) >= 0)
+							variable.setAlias(attributes.getValue(JSP20TLDNames.VARIABLE_ALIAS));
+						if (attributes.getIndex(JSP12TLDNames.VARIABLE_CLASS) >= 0)
+							variable.setVariableClass(attributes.getValue(JSP12TLDNames.VARIABLE_CLASS));
+						if (attributes.getIndex(JSP12TLDNames.VARIABLE_DECLARE) >= 0)
+							variable.setDeclareString(attributes.getValue(JSP12TLDNames.VARIABLE_DECLARE));
+						if (attributes.getIndex(JSP11Namespace.ATTR_NAME_SCOPE) >= 0)
+							variable.setScope(attributes.getValue(JSP11Namespace.ATTR_NAME_SCOPE));
+						if (attributes.getIndex(JSP12TLDNames.DESCRIPTION) >= 0)
+							variable.setDescription(attributes.getValue(JSP12TLDNames.DESCRIPTION));
+						if (variable.getAlias() != null || variable.getNameFromAttribute() != null || variable.getNameGiven() != null) {
+							ed.getVariables().add(variable);
+						}
+					}
+					else if (qName.equals(JSP11Namespace.ElementName.DIRECTIVE_INCLUDE)) {
+						IPath filePath = null;
+						String text = attributes.getValue(JSP11Namespace.ATTR_NAME_FILE);
+						if (text != null) {
+							filePath = FacetModuleCoreSupport.resolve(new Path(((CMDocumentImpl) ed.getOwnerDocument()).getBaseLocation()), text);
+							IFile includedFile = ResourcesPlugin.getWorkspace().getRoot().getFile(filePath);
+							if (includedFile.isAccessible()) {
+								loadTagXFile(ed, includedFile, false);
+							}
+						}
+					}
+				}
+			});
+			input.close();
+		}
+		catch (ParserConfigurationException e) {
+			Logger.logException(e);
+		}
+		catch (SAXException e) {
+			Logger.logException(e);
+		}
+		catch (IOException e) {
+			Logger.logException(e);
+		}
+		catch (CoreException e) {
+			Logger.logException(e);
+		}
+		ed.setLocationString(tagxFile.getFullPath().toString());
+	}
+
+	private void loadTagFile(CMElementDeclarationImpl ed, IFile tagFile, boolean allowIncludes) {
+		loadTagFile(ed, tagFile, allowIncludes, null);
+	}
+	
+	private void loadTagFile(CMElementDeclarationImpl ed, IFile tagFile, boolean allowIncludes, InputStream inputStream) {
+		try {
+			ed.setPath(tagFile.getFullPath().toString());
+			ed.setTagSource(TLDElementDeclaration.SOURCE_TAG_FILE);
+			ed.setLocationString(tagFile.getFullPath().toString());
+			IStructuredDocument document = null;
+			if(inputStream != null) {
+				document = (IStructuredDocument)new ModelHandlerForJSP().getDocumentLoader().createNewStructuredDocument(tagFile.getName(), inputStream);
+			}
+			else if(tagFile.isAccessible()) {
+				document = (IStructuredDocument) new ModelHandlerForJSP().getDocumentLoader().createNewStructuredDocument(tagFile);
+			}
+			if (document == null)
+				return;
+			IStructuredDocumentRegion documentRegion = document.getFirstStructuredDocumentRegion();
+			while (documentRegion != null) {
+				if (documentRegion.getType().equals(DOMJSPRegionContexts.JSP_DIRECTIVE_NAME)) {
+					if (documentRegion.getNumberOfRegions() > 2) {
+						ITextRegionList regions = documentRegion.getRegions();
+						String directiveName = documentRegion.getText(regions.get(1));
+						if (JSP12TLDNames.TAG.equals(directiveName)) {
+							// 8.5.1
+							String attrName = null;
+							for (int i = 2; i < documentRegion.getNumberOfRegions(); i++) {
+								ITextRegion region = regions.get(i);
+								String text = documentRegion.getText(region);
+								if (region.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) {
+									attrName = text;
+								}
+								// process value
+								else if (region.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
+									text = StringUtils.strip(text);
+									if (JSP12TLDNames.DISPLAY_NAME.equals(attrName)) {
+										ed.setDisplayName(text);
+									}
+									else if (JSP12TLDNames.BODY_CONTENT.equals(attrName)) {
+										ed.setBodycontent(text);
+									}
+									else if (JSP20TLDNames.DYNAMIC_ATTRIBUTES.equals(attrName)) {
+										ed.setDynamicAttributes(text);
+									}
+									else if (JSP12TLDNames.SMALL_ICON.equals(attrName)) {
+										ed.setSmallIcon(text);
+									}
+									else if (JSP12TLDNames.LARGE_ICON.equals(attrName)) {
+										ed.setLargeIcon(text);
+									}
+									else if (JSP12TLDNames.DESCRIPTION.equals(attrName)) {
+										ed.setDescription(text);
+									}
+									else if (JSP20TLDNames.EXAMPLE.equals(attrName)) {
+										ed.setExample(text);
+									}
+									else if (JSP20TLDNames.SCRIPTING_LANGUAGE.equals(attrName)) {
+										ed.setScriptingLanguage(text);
+									}
+									else if (JSP20TLDNames.IMPORT.equals(attrName)) {
+										ed.setImport(text);
+									}
+									else if (JSP20TLDNames.PAGE_ENCODING.equals(attrName)) {
+										ed.setPageEncoding(text);
+									}
+									else if (JSP20TLDNames.IS_EL_IGNORED.equals(attrName)) {
+										ed.setIsELIgnored(text);
+									}
+								}
+							}
+						}
+						else if (JSP12TLDNames.ATTRIBUTE.equals(directiveName)) {
+							CMAttributeDeclarationImpl attribute = new CMAttributeDeclarationImpl(ed.getOwnerDocument());
+							// 8.5.2
+							String attrName = null;
+							for (int i = 2; i < documentRegion.getNumberOfRegions(); i++) {
+								ITextRegion region = regions.get(i);
+								String text = documentRegion.getText(region);
+								if (region.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) {
+									attrName = text;
+								}
+								// process value
+								else if (region.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE && attrName != null) {
+									text = StringUtils.strip(text);
+									if (JSP12TLDNames.NAME.equals(attrName)) {
+										attribute.setNodeName(text);
+									}
+									else if (JSP20TLDNames.FRAGMENT.equals(attrName)) {
+										attribute.setFragment(Boolean.valueOf(text).booleanValue());
+									}
+									else if (JSP12TLDNames.RTEXPRVALUE.equals(attrName)) {
+										attribute.setRtexprvalue(text);
+									}
+									else if (JSP20TLDNames.TYPE.equals(attrName)) {
+										attribute.setType(text);
+									}
+									else if (JSP12TLDNames.DESCRIPTION.equals(attrName)) {
+										attribute.setDescription(text);
+									}
+									else if (JSP12TLDNames.REQUIRED.equals(attrName)) {
+										attribute.setRequiredString(text);
+									}
+								}
+							}
+							if (attribute.getNodeName() != null) {
+								ed.fAttributes.setNamedItem(attribute.getNodeName(), attribute);
+							}
+						}
+						else if (JSP12TLDNames.VARIABLE.equals(directiveName)) {
+							TLDVariableImpl variable = new TLDVariableImpl();
+							String attrName = null;
+							for (int i = 2; i < documentRegion.getNumberOfRegions(); i++) {
+								ITextRegion region = regions.get(i);
+								String text = documentRegion.getText(region);
+								if (region.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) {
+									attrName = text;
+								}
+								// process value
+								else if (region.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE && attrName != null) {
+									text = StringUtils.strip(text);
+									if (JSP12TLDNames.VARIABLE_NAME_GIVEN.equals(attrName)) {
+										variable.setNameGiven(text);
+									}
+									else if (JSP12TLDNames.VARIABLE_NAME_FROM_ATTRIBUTE.equals(attrName)) {
+										variable.setNameFromAttribute(text);
+									}
+									else if (JSP20TLDNames.VARIABLE_ALIAS.equals(attrName)) {
+										variable.setAlias(text);
+									}
+									else if (JSP12TLDNames.VARIABLE_CLASS.equals(attrName)) {
+										variable.setVariableClass(text);
+									}
+									else if (JSP12TLDNames.VARIABLE_DECLARE.equals(attrName)) {
+										variable.setDeclareString(text);
+									}
+									else if (JSP11Namespace.ATTR_NAME_SCOPE.equals(attrName)) {
+										variable.setScope(text);
+									}
+									else if (JSP12TLDNames.DESCRIPTION.equals(attrName)) {
+										variable.setDescription(text);
+									}
+								}
+							}
+							if (variable.getAlias() != null || variable.getNameFromAttribute() != null || variable.getNameGiven() != null) {
+								ed.getVariables().add(variable);
+							}
+						}
+						else if ("include".equals(directiveName) && allowIncludes) {
+							String attrName = null;
+							for (int i = 2; i < documentRegion.getNumberOfRegions(); i++) {
+								ITextRegion region = regions.get(i);
+								String text = documentRegion.getText(region);
+								if (region.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) {
+									attrName = text;
+								}
+								// process value
+								else if (region.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE && attrName != null) {
+									text = StringUtils.strip(text);
+									if (JSP11Namespace.ATTR_NAME_FILE.equals(attrName)) {
+										IPath filePath = FacetModuleCoreSupport.resolve(new Path(((CMDocumentImpl) ed.getOwnerDocument()).getBaseLocation()), text);
+
+										IFile includedFile = ResourcesPlugin.getWorkspace().getRoot().getFile(filePath);
+										if (includedFile.isAccessible()) {
+											loadTagFile(ed, includedFile, false);
+										}
+									}
+								}
+							}
+						}
+					}
+				}
+
+				documentRegion = documentRegion.getNext();
+			}
+
+		}
+		catch (IOException e) {
+			// Logger.logException("problem parsing " + tagFile, e); // can be caused by a still-in-development file
+		}
+		catch (CoreException e) {
+			// Logger.logException("problem parsing " + tagFile, e); // frequently out of sync
+		}
+	}
+
+	/**
+	 * @param reference
+	 * @return
+	 */
+	public CMDocument createCMDocument(ITaglibRecord reference) {
+		CMDocumentImpl document = null;
+		switch (reference.getRecordType()) {
+			case (ITaglibRecord.TLD) : {
+				ITLDRecord record = (ITLDRecord) reference;
+				IResource file = ResourcesPlugin.getWorkspace().getRoot().getFile(record.getPath());
+				if (file.getLocation() != null) {
+					document = (CMDocumentImpl) buildCMDocumentFromFile(file.getLocation().toString());
+					document.setLocationString(record.getPath().toString());
+					if (_debug && document != null && document.getElements().getLength() == 0) {
+						System.out.println("failure parsing " + record.getPath()); //$NON-NLS-1$
+					}
+
+					if (document.getSmallIcon() != null) {
+						String iconPath = URIHelper.normalize(((TLDDocument) document).getSmallIcon(), file.getLocation().toString(), "/"); //$NON-NLS-1$
+						document.setProperty(JSP12TLDNames.SMALL_ICON, "file:" + iconPath); //$NON-NLS-1$
+					}
+					if (document.getLargeIcon() != null) {
+						String iconPath = URIHelper.normalize(((TLDDocument) document).getLargeIcon(), file.getLocation().toString(), "/"); //$NON-NLS-1$
+						document.setProperty(JSP12TLDNames.LARGE_ICON, "file:" + iconPath); //$NON-NLS-1$
+					}
+				}
+			}
+				break;
+			case (ITaglibRecord.JAR) : {
+				IJarRecord record = (IJarRecord) reference;
+				document = (CMDocumentImpl) buildCMDocumentFromJar(record.getLocation().toString());
+				document.setLocationString("jar:file:" + record.getLocation().toString() + "!/META-INF/taglib.tld");
+				if (document.getSmallIcon() != null) {
+					String iconPath = URIHelper.normalize(((TLDDocument) document).getSmallIcon(), record.getLocation().toString() + "!/META-INF/", "/"); //$NON-NLS-1$ //$NON-NLS-2$
+					document.setProperty(JSP12TLDNames.SMALL_ICON, "jar:file:" + iconPath); //$NON-NLS-1$
+				}
+				if (document.getLargeIcon() != null) {
+					String iconPath = URIHelper.normalize(((TLDDocument) document).getLargeIcon(), record.getLocation().toString() + "!/META-INF/", "/"); //$NON-NLS-1$ //$NON-NLS-2$
+					document.setProperty(JSP12TLDNames.LARGE_ICON, "jar:file:" + iconPath); //$NON-NLS-1$
+				}
+				if (_debug && document != null && document.getElements().getLength() == 0) {
+					System.out.println("failure parsing " + record.getLocation()); //$NON-NLS-1$
+				}
+			}
+				break;
+			case (ITaglibRecord.TAGDIR) : {
+				ITagDirRecord record = (ITagDirRecord) reference;
+				document = buildCMDocumentFromFolder(record.getPath());
+			}
+				break;
+			case (ITaglibRecord.URL) : {
+				IURLRecord record = (IURLRecord) reference;
+				URL url = record.getURL();
+				InputStream urlContents = JarUtilities.getInputStream(url);
+				if (urlContents != null) {
+					document = (CMDocumentImpl) buildCMDocument(record.getBaseLocation(), urlContents);
+					String urlString = url.toString();
+					document.setLocationString(urlString);
+					if (document.getSmallIcon() != null) {
+						String iconPath = URIHelper.normalize(((TLDDocument) document).getSmallIcon(), urlString, "/"); //$NON-NLS-1$
+						document.setProperty(JSP12TLDNames.SMALL_ICON, iconPath);
+					}
+					if (document.getLargeIcon() != null) {
+						String iconPath = URIHelper.normalize(((TLDDocument) document).getLargeIcon(), urlString, "/"); //$NON-NLS-1$
+						document.setProperty(JSP12TLDNames.LARGE_ICON, iconPath);
+					}
+				}
+				if (urlContents != null) {
+					try {
+						urlContents.close();
+					}
+					catch (IOException e) {
+					}
+				}
+			}
+				break;
+		}
+		return document;
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/CMDocumentImpl.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/CMDocumentImpl.java
new file mode 100644
index 0000000..936684b
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/CMDocumentImpl.java
@@ -0,0 +1,455 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.contentmodel.tld;
+
+
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.jst.jsp.core.internal.Logger;
+import org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.TLDDocument;
+import org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.TLDValidator;
+import org.eclipse.wst.sse.core.utils.StringUtils;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.contentmodel.ContentModelManager;
+import org.eclipse.wst.xml.core.internal.contentmodel.annotation.AnnotationMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.internal.annotation.AnnotationFileInfo;
+import org.eclipse.wst.xml.core.internal.contentmodel.internal.annotation.AnnotationFileParser;
+
+public class CMDocumentImpl implements TLDDocument {
+	
+	/** Contains taginfo and/or any other misc properties*/
+	private AnnotationMap fAnnotationMap = null;
+	
+	private Map fProperties = new HashMap(0);
+
+	/**
+	 * Records from where this document was created
+	 */
+	private String fBaseLocation;
+	/** 
+	 * since JSP 1.2
+	 */
+	private String fDescription;
+	
+	private String fDisplayName;
+
+	/**
+	 * NOT public API
+	 */
+	public CMNamedNodeMapImpl fElements = new CMNamedNodeMapImpl();
+
+	private List fFunctions = new ArrayList(0);
+	
+	// id of the taglib
+	private String fId = null;
+	/**
+	 * Children of "taglib" within a .tld file each allow
+	 * one Text node (#PCDATA) beneath them.  Store the values
+	 * here for simplicity.
+	 */
+	// The JSP specification required for this taglib to function
+	private String fJSPVersion = null;
+	
+	private String fLargeIcon;
+
+	private List fListeners;
+	
+	private String fParentURI = null;
+	// A short name suggested as the default prefix for tags within the lib
+	private String fShortName = null;
+	
+	private String fSmallIcon;
+	
+	/**
+	 * since JSP 2.0
+	 * 
+	 * The entire element is stored here since its layout is undefined 
+	 */
+	private List fTaglibExtensions = new ArrayList(0);
+	
+	// Version information for the taglib itself
+	private String fTLibVersion = null;
+	
+	// A unique public URI describing this taglib.  Recommended to be the URL
+	// to the descriptor
+	private String fURI = null;
+	
+	private String fLocationString;
+
+	protected TLDValidator validator;
+	
+	/**
+	 * CMDocumentImpl constructor comment.
+	 */
+	public CMDocumentImpl() {
+		super();
+	}
+
+	/**
+	 * Get the annotation map associated with this document.  Lazily creates
+	 * and loads annotation map.
+	 * @return AnnotationMap
+	 */
+	private AnnotationMap getAnnotationMap() {
+		// create a new annotation map and load it up
+		if (fAnnotationMap == null) {
+			fAnnotationMap = new AnnotationMap();
+			
+			List annotationFiles = ContentModelManager.getInstance().getAnnotationFilesInfos(getUri());
+		    for (Iterator i = annotationFiles.iterator(); i.hasNext();) {
+		    	try {
+		    		AnnotationFileInfo fileInfo = (AnnotationFileInfo) i.next();
+		    		AnnotationFileParser parser = new AnnotationFileParser();
+		    		parser.parse(fAnnotationMap, fileInfo);
+		        } catch (Exception e) {
+		        	Logger.log(Logger.WARNING_DEBUG, "Exception thrown in CMDocumentImpl#getAnnotationMap", e); //$NON-NLS-1$
+		        }
+		    }
+		}
+		return fAnnotationMap;
+	}
+	/**
+	 * @return Returns the baseLocation.
+	 */
+	public String getBaseLocation() {
+		return fBaseLocation;
+	}
+
+	/**
+	 * Gets the description.
+	 * @return Returns a String
+	 */
+	public String getDescription() {
+		return fDescription;
+	}
+
+	/**
+	 * Gets the displayName.
+	 * @return Returns a String
+	 */
+	public String getDisplayName() {
+		return fDisplayName;
+	}
+
+	/**
+	 * getElements method
+	 * @return CMNamedNodeMap
+	 *
+	 * Returns CMNamedNodeMap of ElementDeclaration
+	 */
+	public CMNamedNodeMap getElements() {
+		return fElements;
+	}
+
+	/**
+	 * getEntities method
+	 * @return CMNamedNodeMap
+	 *
+	 * Returns CMNamedNodeMap of EntityDeclaration
+	 */
+	public CMNamedNodeMap getEntities() {
+		return null;
+	}
+	
+	public List getExtensions() {
+		return fTaglibExtensions;
+	}
+	/**
+	 * @return Returns the functions.
+	 */
+	public List getFunctions() {
+		return fFunctions;
+	}
+
+	/**
+	 * Gets the id.
+	 * @return Returns a String
+	 */
+	public String getId() {
+		return fId;
+	}
+
+	/**
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getInfo() {
+		return getDescription();
+	}
+
+	/**
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getJspversion() {
+		return fJSPVersion;
+	}
+
+	/**
+	 * Gets the largeIcon.
+	 * @return Returns a String
+	 */
+	public String getLargeIcon() {
+		return fLargeIcon;
+	}
+
+	public List getListeners() {
+		if (fListeners == null)
+			fListeners = new ArrayList();
+		return fListeners;
+	}
+
+	/**
+	 * getNamespace method
+	 * @return CMNamespace
+	 */
+	public CMNamespace getNamespace() {
+		return null;
+	}
+
+	/**
+	 * getNodeName method
+	 * @return java.lang.String
+	 */
+	public String getNodeName() {
+		return "#cmdocument"; //$NON-NLS-1$
+	}
+
+	/**
+	 * getNodeType method
+	 * @return int
+	 *
+	 * Returns one of :
+	 *
+	 */
+	public int getNodeType() {
+		return CMNode.DOCUMENT;
+	}
+	/**
+	 * @return Returns the parentURI.
+	 */
+	public String getParentURI() {
+		return fParentURI;
+	}
+
+	/**
+	 * getProperty method
+	 * @return java.lang.Object
+	 *
+	 * Returns the object property desciped by the propertyName
+	 *
+	 */
+	public Object getProperty(String propertyName) {
+		if (propertyName.equals(TLDDocument.CM_KIND)) {
+			return TLDDocument.JSP_TLD;
+		}
+		else if (propertyName.equals("annotationMap")) { //$NON-NLS-1$
+			return getAnnotationMap();
+		}
+		return fProperties.get(propertyName);
+	}
+
+	/**
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getShortname() {
+		return fShortName;
+	}
+
+	/**
+	 * Gets the smallIcon.
+	 * @return Returns a String
+	 */
+	public String getSmallIcon() {
+		return fSmallIcon;
+	}
+
+	/**
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getTlibversion() {
+		return fTLibVersion;
+	}
+
+	/**
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getUri() {
+		return fURI;
+	}
+
+	/*
+	 * @see TLDDocument#getValidator()
+	 */
+	public TLDValidator getValidator() {
+		return validator;
+	}
+	/**
+	 * @param baseLocation The baseLocation to set.
+	 */
+	public void setBaseLocation(String baseLocation) {
+		fBaseLocation = baseLocation;
+	}
+
+	/**
+	 * Sets the description.
+	 * @param description The description to set
+	 */
+	public void setDescription(String description) {
+		this.fDescription = description;
+	}
+
+	/**
+	 * Sets the displayName.
+	 * @param displayName The displayName to set
+	 */
+	public void setDisplayName(String displayName) {
+		this.fDisplayName = displayName;
+	}
+
+	/**
+	 * Sets the id.
+	 * @param id The id to set
+	 */
+	public void setId(String id) {
+		this.fId = id;
+	}
+
+	/**
+	 * 
+	 * @param newInfo java.lang.String
+	 */
+	public void setInfo(String newInfo) {
+		setDescription(newInfo);
+	}
+
+	/**
+	 * 
+	 * @param newJspversion java.lang.String
+	 */
+	public void setJspversion(String newJspversion) {
+		fJSPVersion = newJspversion;
+	}
+
+	/**
+	 * Sets the largeIcon.
+	 * @param largeIcon The largeIcon to set
+	 */
+	public void setLargeIcon(String largeIcon) {
+		this.fLargeIcon = largeIcon;
+	}
+
+	public void setListeners(List listeners) {
+		this.fListeners = listeners;
+	}
+	/**
+	 * @param parentURI The parentURI to set.
+	 */
+	public void setParentURI(String parentURI) {
+		fParentURI = parentURI;
+	}
+	
+	public void setProperty(String property, Object value) {
+		fProperties.put(property, value);
+	}
+
+	/**
+	 * 
+	 * @param newShortname java.lang.String
+	 */
+	public void setShortname(String newShortname) {
+		fShortName = newShortname;
+	}
+
+	/**
+	 * Sets the smallIcon.
+	 * @param smallIcon The smallIcon to set
+	 */
+	public void setSmallIcon(String smallIcon) {
+		this.fSmallIcon = smallIcon;
+	}
+
+	/**
+	 * 
+	 * @param newTlibversion java.lang.String
+	 */
+	public void setTlibversion(String newTlibversion) {
+		fTLibVersion = newTlibversion;
+	}
+
+	/**
+	 * 
+	 * @param newUri java.lang.String
+	 */
+	public void setUri(String newUri) {
+		fURI = newUri;
+	}
+
+	public void setValidator(TLDValidator validator) {
+		this.validator = validator;
+	}
+
+	/**
+	 * supports method
+	 * @return boolean
+	 *
+	 * Returns true if the CMNode supports a specified property
+	 *
+	 */
+	public boolean supports(String propertyName) {
+		if (TLDDocument.CM_KIND.equals(propertyName) || "annotationMap".equals(propertyName)) //$NON-NLS-1$
+			return true;
+		return fProperties.containsKey(propertyName);
+	}
+
+	public String toString() {
+		StringBuffer buffer = new StringBuffer();
+		buffer.append(super.toString());
+		buffer.append("\n\t short name:" + StringUtils.escape(getShortname())); //$NON-NLS-1$
+		buffer.append("\n\t display name:" + StringUtils.escape(getDisplayName())); //$NON-NLS-1$
+		buffer.append("\n\t description (info):" + StringUtils.escape(getDescription())); //$NON-NLS-1$
+		buffer.append("\n\t URI:" + StringUtils.escape(getUri())); //$NON-NLS-1$
+		buffer.append("\n\t jsp version:" + StringUtils.escape(getJspversion())); //$NON-NLS-1$
+		buffer.append("\n\t taglib version:" + StringUtils.escape(getTlibversion())); //$NON-NLS-1$
+		buffer.append("\n\t small icon:" + StringUtils.escape(getSmallIcon())); //$NON-NLS-1$
+		buffer.append("\n\t large icon:" + StringUtils.escape(getLargeIcon())); //$NON-NLS-1$
+		if (getValidator() != null)
+			buffer.append("\n\t validator:" + StringUtils.replace(getValidator().toString(), "\n", "\n\t\t")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+		buffer.append("\n\t listeners:"); //$NON-NLS-1$
+		for (int i = 0; i < getListeners().size(); i++) {
+			buffer.append("\n" + StringUtils.replace(getListeners().get(i).toString(), "\n", "\n\t\t")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+		}
+		buffer.append("\n\t elements:"); //$NON-NLS-1$
+		CMNamedNodeMap elements = getElements();
+		for (int i = 0; i < elements.getLength(); i++) {
+			buffer.append(StringUtils.replace(elements.item(i).toString(), "\n", "\n\t\t")); //$NON-NLS-1$ //$NON-NLS-2$
+		}
+		return buffer.toString();
+	}
+
+	public String getLocationString() {
+		return fLocationString;
+	}
+
+	public void setLocationString(String url) {
+		fLocationString = url;
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/CMElementDeclarationImpl.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/CMElementDeclarationImpl.java
new file mode 100644
index 0000000..7984fba
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/CMElementDeclarationImpl.java
@@ -0,0 +1,590 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.contentmodel.tld;
+
+
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.JSP11TLDNames;
+import org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.JSP12TLDNames;
+import org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.TLDDocument;
+import org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.TLDElementDeclaration;
+import org.eclipse.wst.sse.core.utils.StringUtils;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMContent;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.contentmodel.annotation.AnnotationMap;
+
+public class CMElementDeclarationImpl implements TLDElementDeclaration {
+
+	// optional attributes
+	CMNamedNodeMapImpl fAttributes = new CMNamedNodeMapImpl();
+	// (empty|JSP|tagdependant|scriptless) - optional, defaults to JSP
+	private String bodycontent = JSP11TLDNames.CONTENT_JSP;
+
+	/**
+	 * since JSP 1.2
+	 * 
+	 * Usage information
+	 */
+	private String description;
+
+	/**
+	 * since JSP 1.2
+	 */
+	private String displayName;
+
+	private CMDocument fOwnerDocument;
+
+	private String fPath = null;
+
+	private List fTagExtensions = new ArrayList(0);
+	/**
+	 * since JSP 1.2
+	 */
+	private String largeIcon;
+
+
+	private int maxOccur = -1;
+	private int minOccur = 0;
+
+	// required tag name
+	private String nodeName = null;
+
+	/**
+	 * since JSP 1.2
+	 */
+	private String smallIcon;
+
+	// tag handler class - required
+	private String tagclass = null;
+
+	// tag extra info class (subclass of javax.servlet.jsp.TagExtraInfo) -
+	// optional
+	private String teiclass = null;
+
+	/**
+	 * since JSP 1.2
+	 */
+	private List variables;
+
+	/**
+	 * since JSP 2.0
+	 */
+	private String fExample;
+	private String fImport;
+	private String fScriptingLanguage;
+	private String fDynamicAttributes;
+	private String fIsELIgnored;
+	private String fPageEncoding;
+	private String fTagSource;
+
+	private String fLocationString;
+	private String smallIconURL;
+
+	/**
+	 * CMElementDeclarationImpl constructor comment.
+	 */
+	public CMElementDeclarationImpl(CMDocument owner) {
+		super();
+		fOwnerDocument = owner;
+	}
+
+	/**
+	 * getAttributes method
+	 * 
+	 * @return CMNamedNodeMap
+	 * 
+	 * Returns CMNamedNodeMap of AttributeDeclaration
+	 */
+	public CMNamedNodeMap getAttributes() {
+		return fAttributes;
+	}
+
+	/**
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getBodycontent() {
+		return bodycontent;
+	}
+
+	/**
+	 * getCMContent method
+	 * 
+	 * @return CMContent
+	 * 
+	 * Returns the root node of this element's content model. This can be an
+	 * CMElementDeclaration or a CMGroup
+	 */
+	public CMContent getContent() {
+		return null;
+	}
+
+	/**
+	 * getContentType method
+	 * 
+	 * @return int
+	 * 
+	 * Returns one of : ANY, EMPTY, ELEMENT, MIXED, PCDATA, CDATA.
+	 */
+	public int getContentType() {
+		if (getBodycontent().equals(JSP11TLDNames.CONTENT_EMPTY))
+			return EMPTY;
+		if (getBodycontent().equals(JSP11TLDNames.CONTENT_TAGDEPENDENT))
+			return PCDATA;
+		else
+			// JSP
+			return ANY;
+	}
+
+	/**
+	 * getDataType method
+	 * 
+	 * @return java.lang.String
+	 */
+	public CMDataType getDataType() {
+		return new CMDataTypeImpl(CMDataType.CDATA);
+	}
+
+	/**
+	 * Gets the description.
+	 * 
+	 * @return Returns a String
+	 */
+	public String getDescription() {
+		return description;
+	}
+
+	/**
+	 * Gets the displayName.
+	 * 
+	 * @return Returns a String
+	 */
+	public String getDisplayName() {
+		return displayName;
+	}
+
+	/**
+	 * getElementName method
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getElementName() {
+		return getNodeName();
+	}
+
+	/**
+	 * @return Returns the example.
+	 */
+	public String getExample() {
+		return fExample;
+	}
+
+	/**
+	 * @return Returns the extensions.
+	 */
+	public List getExtensions() {
+		return fTagExtensions;
+	}
+
+	/**
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getInfo() {
+		return getDescription();
+	}
+
+	/**
+	 * Gets the largeIcon.
+	 * 
+	 * @return Returns a String
+	 */
+	public String getLargeIcon() {
+		return largeIcon;
+	}
+
+	/**
+	 * getLocalElements method
+	 * 
+	 * @return CMNamedNodeMap
+	 * 
+	 * Returns a list of locally defined elements.
+	 */
+	public CMNamedNodeMap getLocalElements() {
+		return null;
+	}
+
+	/**
+	 * getMaxOccur method
+	 * 
+	 * @return int
+	 * 
+	 * If -1, it's UNBOUNDED.
+	 */
+	public int getMaxOccur() {
+		return maxOccur;
+	}
+
+	/**
+	 * getMinOccur method
+	 * 
+	 * @return int
+	 * 
+	 * If 0, it's OPTIONAL. If 1, it's REQUIRED.
+	 */
+	public int getMinOccur() {
+		return minOccur;
+	}
+
+	/**
+	 * getNodeName method
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getNodeName() {
+		return nodeName;
+	}
+
+	/**
+	 * getNodeType method
+	 * 
+	 * @return int
+	 * 
+	 * Returns one of :
+	 * 
+	 */
+	public int getNodeType() {
+		return CMNode.ELEMENT_DECLARATION;
+	}
+
+	/**
+	 * @return
+	 */
+	public CMDocument getOwnerDocument() {
+		return fOwnerDocument;
+	}
+
+	/**
+	 * @return Returns the path.
+	 */
+	public String getPath() {
+		return fPath;
+	}
+
+	/**
+	 * getProperty method
+	 * 
+	 * @return java.lang.Object
+	 * 
+	 * Returns the object property described by the propertyName
+	 * 
+	 */
+	public Object getProperty(String propertyName) {
+		if ("tagInfo".equals(propertyName)) { //$NON-NLS-1$
+			return getTagInfo(); // return tag info
+			// bug88336 no need to restore markers
+			// return StringUtils.restoreMarkers(getTagInfo()); // return tag
+			// description
+		}
+		// Bug 155800
+		else if ("name".equals(propertyName)) { //$NON-NLS-1$
+			return getNodeName();
+		}
+		else if ("description".equals(propertyName)) { //$NON-NLS-1$
+			return getDescription();
+			// bug88336 no need to restore markers
+			// return StringUtils.restoreMarkers(getDescription()); // return
+			// tag description
+		}
+		else if (TLDDocument.CM_KIND.equals(propertyName)) {
+			return TLDDocument.JSP_TLD;
+		}
+		else if (TLDElementDeclaration.TAG_SOURCE.equals(propertyName)) {
+			return (fTagSource != null ? fTagSource :TLDElementDeclaration.SOURCE_JSP_TLD);
+		}
+		else if (JSP12TLDNames.SMALL_ICON.equals(propertyName) || JSP12TLDNames.LARGE_ICON.equals(propertyName)) {
+			if (smallIconURL != null) {
+				return smallIconURL;
+			}
+			return getOwnerDocument().getProperty(propertyName);
+		}
+		else if(TLDElementDeclaration.IS_LIBRARY_TAG.equals(propertyName)) {
+			return Boolean.TRUE;
+		}
+		return null;
+	}
+
+	/**
+	 * Gets the smallIcon.
+	 * 
+	 * @return Returns a String
+	 */
+	public String getSmallIcon() {
+		return smallIcon;
+	}
+
+	String getSmallIconURL() {
+		return smallIconURL;
+	}
+
+	/**
+	 * Returns the XPath of this element (currently just returns the node
+	 * name)
+	 * 
+	 * @return
+	 */
+	private String getSpec() {
+		return getNodeName();
+	}
+
+	/**
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getTagclass() {
+		return tagclass;
+	}
+
+	/**
+	 * Get the taginfo for this current element
+	 * 
+	 * @return String taginfo if it exists, null otherwise
+	 */
+	private String getTagInfo() {
+		if (getOwnerDocument().supports("annotationMap")) { //$NON-NLS-1$
+			AnnotationMap map = (AnnotationMap) getOwnerDocument().getProperty("annotationMap"); //$NON-NLS-1$
+			String spec = getSpec();
+			String result = map.getProperty(spec, "tagInfo"); //$NON-NLS-1$
+			return result;
+			// bug88336 no need to restore markers
+			// return StringUtils.restoreMarkers(result); // return tag info
+		}
+		return null;
+	}
+
+	/**
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getTeiclass() {
+		return teiclass;
+	}
+
+	/**
+	 * Gets the variables.
+	 * 
+	 * @return Returns a List
+	 */
+	public List getVariables() {
+		if (variables == null) {
+			variables = new ArrayList();
+		}
+		return variables;
+	}
+
+	/**
+	 * 
+	 * @param newBodycontent
+	 *            java.lang.String
+	 */
+	public void setBodycontent(String newBodycontent) {
+		bodycontent = newBodycontent;
+	}
+
+	/**
+	 * Sets the description.
+	 * 
+	 * @param description
+	 *            The description to set
+	 */
+	public void setDescription(String description) {
+		this.description = description;
+	}
+
+	/**
+	 * Sets the displayName.
+	 * 
+	 * @param displayName
+	 *            The displayName to set
+	 */
+	public void setDisplayName(String displayName) {
+		this.displayName = displayName;
+	}
+
+	/**
+	 * @param example
+	 *            The example to set.
+	 */
+	public void setExample(String example) {
+		fExample = example;
+	}
+
+	/**
+	 * Sets the largeIcon.
+	 * 
+	 * @param largeIcon
+	 *            The largeIcon to set
+	 */
+	public void setLargeIcon(String largeIcon) {
+		this.largeIcon = largeIcon;
+	}
+
+	public void setNodeName(String string) {
+		nodeName = string;
+	}
+
+	/**
+	 * @param path
+	 *            The path to set.
+	 */
+	public void setPath(String path) {
+		fPath = path;
+	}
+
+	/**
+	 * Sets the smallIcon.
+	 * 
+	 * @param smallIcon
+	 *            The smallIcon to set
+	 */
+	public void setSmallIcon(String smallIcon) {
+		this.smallIcon = smallIcon;
+	}
+
+	void setSmallIconURL(String url) {
+		smallIconURL = url;
+	}
+
+	/**
+	 * 
+	 * @param newTagclass
+	 *            java.lang.String
+	 */
+	public void setTagclass(String newTagclass) {
+		tagclass = newTagclass;
+	}
+
+	/**
+	 * 
+	 * @param newTagclass
+	 *            java.lang.String
+	 */
+	public void setTagSource(String sourceKind) {
+		fTagSource = sourceKind;
+	}
+
+	/**
+	 * 
+	 * @param newTeiclass
+	 *            java.lang.String
+	 */
+	public void setTeiclass(String newTeiclass) {
+		teiclass = newTeiclass;
+	}
+
+	/**
+	 * Sets the variables.
+	 * 
+	 * @param variables
+	 *            The variables to set
+	 */
+	public void setVariables(List variables) {
+		this.variables = variables;
+	}
+
+	/**
+	 * supports method
+	 * 
+	 * @return boolean
+	 * 
+	 * Returns true if the CMNode supports a specified property
+	 * 
+	 */
+	public boolean supports(String propertyName) {
+		return propertyName == null || propertyName.equals("tagInfo") || propertyName.equals(JSP12TLDNames.DESCRIPTION) || propertyName.equals(TLDDocument.CM_KIND) || propertyName.equals(JSP12TLDNames.SMALL_ICON) || propertyName.equals(JSP12TLDNames.LARGE_ICON) || propertyName.equals(TLDElementDeclaration.TAG_SOURCE) || propertyName.equals(TLDElementDeclaration.IS_LIBRARY_TAG);//$NON-NLS-1$ //$NON-NLS-2$
+	}
+
+	public String toString() {
+		StringBuffer buffer = new StringBuffer();
+		buffer.append("\n\t " + super.toString()); //$NON-NLS-1$
+		buffer.append("\n\t name:" + StringUtils.escape(getNodeName())); //$NON-NLS-1$
+		buffer.append("\n\t tag class:" + StringUtils.escape(getTagclass())); //$NON-NLS-1$
+		buffer.append("\n\t tei class:" + StringUtils.escape(getTeiclass())); //$NON-NLS-1$
+		buffer.append("\n\t body content:" + StringUtils.escape(getBodycontent())); //$NON-NLS-1$
+		buffer.append("\n\t description (info):" + StringUtils.escape(getDescription())); //$NON-NLS-1$
+		buffer.append("\n\t attributes:"); //$NON-NLS-1$
+		CMNamedNodeMap attributes = getAttributes();
+		for (int i = 0; i < attributes.getLength(); i++) {
+			buffer.append("\n\t\t" + StringUtils.replace(attributes.item(i).toString(), "\n", "\n\t\t")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+		}
+		buffer.append("\n\t variables:"); //$NON-NLS-1$
+		for (int i = 0; i < getVariables().size(); i++) {
+			buffer.append("\n\t\t" + StringUtils.replace(getVariables().get(i).toString(), "\n", "\n\t\t")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+		}
+		return buffer.toString();
+	}
+
+	public String getImport() {
+		return fImport;
+	}
+
+	public String getScriptingLanguage() {
+		return fScriptingLanguage;
+	}
+
+	public String getDynamicAttributes() {
+		return fDynamicAttributes;
+	}
+
+	public void setImport(String import1) {
+		fImport = import1;
+	}
+
+	public void setScriptingLanguage(String scriptingLanguage) {
+		fScriptingLanguage = scriptingLanguage;
+	}
+
+	public void setDynamicAttributes(String dynamicAttributes) {
+		fDynamicAttributes = dynamicAttributes;
+	}
+
+	public String getIsELIgnored() {
+		return fIsELIgnored;
+	}
+
+	public String getPageEncoding() {
+		return fPageEncoding;
+	}
+
+	public void setIsELIgnored(String isELIgnored) {
+		fIsELIgnored = isELIgnored;
+	}
+
+	public void setPageEncoding(String pageEncoding) {
+		fPageEncoding = pageEncoding;
+	}
+
+	public String getLocationString() {
+		if (fLocationString == null)
+			return ((CMDocumentImpl) fOwnerDocument).getLocationString();
+		return fLocationString;
+	}
+
+	public void setLocationString(String url) {
+		fLocationString = url;
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/CMNamedNodeMapImpl.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/CMNamedNodeMapImpl.java
new file mode 100644
index 0000000..b8f378c
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/CMNamedNodeMapImpl.java
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.contentmodel.tld;
+
+
+
+import java.util.Hashtable;
+import java.util.Iterator;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+public class CMNamedNodeMapImpl implements CMNamedNodeMap {
+
+	public static CMNamedNodeMapImpl EMPTY_NAMED_NODE_MAP = new CMNamedNodeMapImpl();
+	protected Hashtable table = new Hashtable();
+
+	/**
+	 * CMNamedNodeMapImpl constructor comment.
+	 */
+	public CMNamedNodeMapImpl() {
+		super();
+	}
+
+	Hashtable getHashtable() {
+		return table;
+	}
+
+	/**
+	 * getLength method
+	 * @return int
+	 */
+	public int getLength() {
+		return table.size();
+	}
+
+	/**
+	 * getNamedItem method
+	 * @return CMNode
+	 * @param name java.lang.String
+	 */
+	public CMNode getNamedItem(String name) {
+		return (CMNode) table.get(name);
+	}
+
+	/**
+	 * item method
+	 * @return CMNode
+	 * @param index int
+	 */
+	public CMNode item(int index) {
+		Object result = null;
+		int size = table.size();
+		if (index < size) {
+			Iterator values = iterator();
+			for (int i = 0; i <= index; i++) {
+				result = values.next();
+			}
+		}
+		return (CMNode) result;
+	}
+
+	public Iterator iterator() {
+		return table.values().iterator();
+	}
+
+	/**
+	 * getNamedItem method
+	 * @return
+	 * @param name java.lang.String
+	 * @param aNode CMNode
+	 */
+	public void setNamedItem(String name, CMNode aNode) {
+		if (name != null && aNode != null)
+			table.put(name, aNode);
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/CMNodeListImpl.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/CMNodeListImpl.java
new file mode 100644
index 0000000..318c617
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/CMNodeListImpl.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.contentmodel.tld;
+
+
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNodeList;
+
+public class CMNodeListImpl implements CMNodeList {
+	static CMNodeListImpl EMPTY_NODE_LIST = new CMNodeListImpl(Collections.EMPTY_LIST);
+	protected List list;
+
+	public CMNodeListImpl() {
+		this(new ArrayList());
+	}
+
+	public CMNodeListImpl(List list) {
+		this.list = list;
+	}
+
+	public void appendItem(CMNode node) {
+		list.add(node);
+	}
+
+	/**
+	 * getLength method
+	 * @return int
+	 */
+	public int getLength() {
+		return list.size();
+	}
+
+	public List getList() {
+		return list;
+	}
+
+	/**
+	 * item method
+	 * @return CMNode
+	 * @param index int
+	 */
+	public CMNode item(int index) {
+		return (CMNode) list.get(index);
+	}
+
+	public Iterator iterator() {
+		return list.iterator();
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/TLDCMDocumentManager.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/TLDCMDocumentManager.java
new file mode 100644
index 0000000..363ce95
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/TLDCMDocumentManager.java
@@ -0,0 +1,1107 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.contentmodel.tld;
+
+import java.io.File;
+import java.lang.ref.Reference;
+import java.lang.ref.SoftReference;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Stack;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Platform;
+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.provisional.JSP11TLDNames;
+import org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.JSP12TLDNames;
+import org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.JSP20TLDNames;
+import org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.TLDDocument;
+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.JSP12Namespace;
+import org.eclipse.jst.jsp.core.internal.regions.DOMJSPRegionContexts;
+import org.eclipse.jst.jsp.core.internal.util.FacetModuleCoreSupport;
+import org.eclipse.jst.jsp.core.internal.util.FileContentCache;
+import org.eclipse.jst.jsp.core.internal.util.ZeroStructuredDocumentRegion;
+import org.eclipse.jst.jsp.core.taglib.IJarRecord;
+import org.eclipse.jst.jsp.core.taglib.ITLDRecord;
+import org.eclipse.jst.jsp.core.taglib.ITagDirRecord;
+import org.eclipse.jst.jsp.core.taglib.ITaglibIndexDelta;
+import org.eclipse.jst.jsp.core.taglib.ITaglibIndexListener;
+import org.eclipse.jst.jsp.core.taglib.ITaglibRecord;
+import org.eclipse.jst.jsp.core.taglib.IURLRecord;
+import org.eclipse.jst.jsp.core.taglib.TaglibIndex;
+import org.eclipse.wst.common.uriresolver.internal.provisional.URIResolverPlugin;
+import org.eclipse.wst.sse.core.internal.ltk.parser.BlockMarker;
+import org.eclipse.wst.sse.core.internal.ltk.parser.JSPCapableParser;
+import org.eclipse.wst.sse.core.internal.ltk.parser.StructuredDocumentRegionHandler;
+import org.eclipse.wst.sse.core.internal.ltk.parser.StructuredDocumentRegionHandlerExtension;
+import org.eclipse.wst.sse.core.internal.ltk.parser.TagMarker;
+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.ITextRegionList;
+import org.eclipse.wst.sse.core.internal.util.Assert;
+import org.eclipse.wst.sse.core.internal.util.Debug;
+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.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.parser.XMLSourceParser;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+
+public class TLDCMDocumentManager implements ITaglibIndexListener {
+
+	protected class DirectiveStructuredDocumentRegionHandler implements StructuredDocumentRegionHandler, StructuredDocumentRegionHandlerExtension {
+		/**
+		 * Adds a block tagname (fully namespace qualified) into the list of
+		 * block tag names for the parser. The marker
+		 * IStructuredDocumentRegion along with position cues during reparses
+		 * allow the XMLSourceParser to enable/ignore the tags as blocks.
+		 */
+		protected void addBlockTag(String tagnameNS, ITextRegionCollection marker) {
+			if (getParser() == null)
+				return;
+			if (getParser().getBlockMarker(tagnameNS) == null) {
+				getParser().addBlockMarker(new BlockMarker(tagnameNS, marker, DOMRegionContext.BLOCK_TEXT, true, false));
+				if (_debug) {
+					System.out.println("TLDCMDocumentManager added block marker: " + tagnameNS + "@" + marker.getStartOffset()); //$NON-NLS-2$//$NON-NLS-1$
+				}
+			}
+		}
+
+		protected void addTaglibTracker(String prefix, String uri, IStructuredDocumentRegion anchorStructuredDocumentRegion, CMDocument tldCMDocument) {
+			getTaglibTrackers().add(new TaglibTracker(uri, prefix, tldCMDocument, anchorStructuredDocumentRegion));
+		}
+
+		/**
+		 * Enables a TLD owning the given prefix loaded from the given URI at
+		 * the anchorStructuredDocumentRegion. The list of
+		 * additionalCMDocuments will claim to not know any of its tags at
+		 * positions earlier than that IStructuredDocumentRegion's position.
+		 * 
+		 * For taglib directives, the taglib is the anchor while taglibs
+		 * registered through include directives use the parent document's
+		 * include directive as their anchor.
+		 * 
+		 * @param prefix
+		 * @param uri
+		 * @param anchorStructuredDocumentRegion
+		 */
+		protected void enableTaglibFromURI(String prefix, String uri, IStructuredDocumentRegion anchorStructuredDocumentRegion) {
+			enableTags(prefix, uri, anchorStructuredDocumentRegion);
+			if (_debug) {
+				System.out.println("TLDCMDocumentManager registered a tracker for " + uri + " with prefix " + prefix); //$NON-NLS-2$//$NON-NLS-1$
+			}
+		}
+
+		private void enableTags(String prefix, String uri, IStructuredDocumentRegion anchorStructuredDocumentRegion) {
+			if (prefix == null || uri == null || bannedPrefixes.contains(prefix))
+				return;
+			// Try to load the CMDocument for this URI
+			CMDocument tld = getCMDocument(uri);
+			if (tld == null || !(tld instanceof TLDDocument)) {
+				if (_debug) {
+					System.out.println("TLDCMDocumentManager failed to create a CMDocument for " + uri); //$NON-NLS-1$
+				}
+				return;
+			}
+			registerTaglib(prefix, uri, anchorStructuredDocumentRegion, tld);
+		}
+
+		/**
+		 * Enables a TLD owning the given prefix loaded from the given URI at
+		 * the anchorStructuredDocumentRegion. The list of
+		 * additionalCMDocuments will claim to not know any of its tags at
+		 * positions earlier than that IStructuredDocumentRegion's position.
+		 * 
+		 * For taglib directives, the taglib is the anchor while taglibs
+		 * registered through include directives use the parent document's
+		 * include directive as their anchor.
+		 * 
+		 * @param prefix
+		 * @param uri
+		 * @param taglibStructuredDocumentRegion
+		 */
+		protected void enableTagsInDir(String prefix, String tagdir, IStructuredDocumentRegion anchorStructuredDocumentRegion) {
+			enableTags(prefix, tagdir, anchorStructuredDocumentRegion);
+			if (_debug) {
+				System.out.println("TLDCMDocumentManager registered a tracker for directory" + tagdir + " with prefix " + prefix); //$NON-NLS-2$//$NON-NLS-1$
+			}
+		}
+		
+		protected void processRegionCollection(ITextRegionCollection regionCollection, IStructuredDocumentRegion anchorStructuredDocumentRegion, XMLSourceParser textSource) {
+			/*
+			 * Would test > 1, but since we only care if there are 8 (<%@,
+			 * taglib, uri, =, where, prefix, =, what) [or 4 for include
+			 * directives]
+			 */
+			if (regionCollection.getNumberOfRegions() > 4 && regionCollection.getRegions().get(1).getType() == DOMJSPRegionContexts.JSP_DIRECTIVE_NAME) {
+				ITextRegion name = regionCollection.getRegions().get(1);
+				boolean taglibDetected = false;
+				boolean taglibDirectiveDetected = false;
+				boolean includeDetected = false;
+				boolean includeDirectiveDetected = false;
+				int startOffset = regionCollection.getStartOffset(name);
+				int textLength = name.getTextLength();
+
+				taglibDetected = textSource.regionMatches(startOffset, textLength, JSP12TLDNames.TAGLIB);
+				if (!taglibDetected)
+					taglibDirectiveDetected = textSource.regionMatches(startOffset, textLength, JSP12Namespace.ElementName.DIRECTIVE_TAGLIB);
+				if (!taglibDirectiveDetected)
+					includeDetected = textSource.regionMatches(startOffset, textLength, JSP12TLDNames.INCLUDE);
+				if (!includeDetected)
+					includeDirectiveDetected = textSource.regionMatches(startOffset, textLength, JSP12Namespace.ElementName.DIRECTIVE_INCLUDE);
+				if (taglibDetected || taglibDirectiveDetected) {
+					processTaglib(regionCollection, anchorStructuredDocumentRegion, textSource);
+				}
+				else if (includeDetected || includeDirectiveDetected) {
+					processInclude(regionCollection, anchorStructuredDocumentRegion, textSource);
+				}
+			}
+			else if (regionCollection.getNumberOfRegions() > 1 && DOMRegionContext.XML_TAG_OPEN.equals(regionCollection.getFirstRegion().getType())) {
+				processXMLStartTag(regionCollection, anchorStructuredDocumentRegion, textSource);
+			}			
+		}
+
+		public void nodeParsed(IStructuredDocumentRegion structuredDocumentRegion) {
+			if (!preludesHandled) {
+				handlePreludes();
+				preludesHandled = true;
+			}
+			processRegionCollection(structuredDocumentRegion, structuredDocumentRegion, getParser());
+		}
+
+		/**
+		 * Process an include directive found by the textSource parser and
+		 * anchor any taglibs found within at the
+		 * anchorStructuredDocumentRegion. Includes use the including file as
+		 * the point of reference, not necessarily the "top" file.
+		 */
+		protected void processInclude(ITextRegionCollection includeDirectiveCollection, IStructuredDocumentRegion anchorStructuredDocumentRegion, XMLSourceParser textSource) {
+			ITextRegionList regions = includeDirectiveCollection.getRegions();
+			String includedFile = null;
+			boolean isFilename = false;
+			try {
+				for (int i = 2; includedFile == null && i < regions.size(); i++) {
+					ITextRegion region = regions.get(i);
+					if (region.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) {
+						if (textSource.regionMatches(includeDirectiveCollection.getStartOffset(region), region.getTextLength(), JSP12TLDNames.FILE)) {
+							isFilename = true;
+						}
+						else {
+							isFilename = false;
+						}
+					}
+					else if (isFilename && region.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
+						includedFile = textSource.getText(includeDirectiveCollection.getStartOffset(region), region.getTextLength());
+						isFilename = false;
+					}
+				}
+			}
+			catch (StringIndexOutOfBoundsException sioobExc) {
+				// nothing to be done
+				includedFile = null;
+			}
+
+			if (fProcessIncludes && includedFile != null) {
+				// strip any extraneous quotes and white space
+				includedFile = StringUtils.strip(includedFile).trim();
+				IPath filePath = null;
+				/*
+				 * 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.
+				 */
+				IPath modelBaseLocation = TaglibController.getLocation(TLDCMDocumentManager.this);
+				if(modelBaseLocation != null) {
+					if (getIncludes().isEmpty())
+						filePath = FacetModuleCoreSupport.resolve(modelBaseLocation, includedFile);
+					else
+						filePath = FacetModuleCoreSupport.resolve((IPath) getIncludes().peek(), includedFile);
+				}
+
+				// check for "loops"
+				if (filePath != null && !getIncludes().contains(filePath) && !filePath.equals(modelBaseLocation)) {
+					/*
+					 * Prevent slow performance when editing scriptlet part of
+					 * the JSP by only processing includes if they've been
+					 * modified. The IncludeHelper remembers any CMDocuments
+					 * created from the files it parses. Caching the URI and
+					 * prefix/tagdir allows us to just enable the CMDocument
+					 * when the previously parsed files.
+					 * 
+					 * REMAINING PROBLEM: fTLDCMReferencesMap does not map
+					 * from a fragment's path and also include all of the CM
+					 * references in fragments that *it* includes. The
+					 * fragments that it includes won't have its CM references
+					 * loaded, but then we'd need to record the URI and
+					 * location of the included fragment to resolve them
+					 * correctly, modifying enableTaglib() to also take a base
+					 * path and resolve the URI appropriately.
+					 */
+					if (hasAnyIncludeBeenModified(filePath)) {
+						getIncludes().push(filePath);
+
+						IncludeHelper includeHelper = new IncludeHelper(anchorStructuredDocumentRegion, getParser());
+						includeHelper.parse(filePath);
+						List references = includeHelper.taglibReferences;
+						fTLDCMReferencesMap.put(filePath, references);
+						if (getParser() instanceof JSPCapableParser) {
+							for (int i = 0; references != null && i < references.size(); i++) {
+								TLDCMDocumentReference reference = (TLDCMDocumentReference) references.get(i);
+								((JSPCapableParser) getParser()).addNestablePrefix(new TagMarker(reference.prefix + ":")); //$NON-NLS-1$
+							}
+						}
+						/*
+						 * TODO: walk up the include hierarchy and add
+						 * these references to each of the parents?
+						 */
+
+						getIncludes().pop();
+					}
+					else {
+						// Add from that saved list of uris/prefixes/documents
+						List references = (List) fTLDCMReferencesMap.get(filePath);
+						for (int i = 0; references != null && i < references.size(); i++) {
+							TLDCMDocumentReference reference = (TLDCMDocumentReference) references.get(i);
+							/*
+							 * The uri might not be resolved properly if
+							 * relative to the JSP fragment.
+							 */
+							enableTaglibFromURI(reference.prefix, reference.uri, anchorStructuredDocumentRegion);
+							if (getParser() instanceof JSPCapableParser) {
+								((JSPCapableParser) getParser()).addNestablePrefix(new TagMarker(reference.prefix + ":")); //$NON-NLS-1$
+							}
+						}
+					}
+				}
+				else if (getIncludes().contains(filePath)) {
+					if (Debug.debugTokenizer)
+						System.out.println("LOOP IN @INCLUDES FOUND: " + filePath); //$NON-NLS-1$
+				}
+			}
+		}
+
+		protected void processXMLStartTag(ITextRegionCollection startTagRegionCollection, IStructuredDocumentRegion anchorStructuredDocumentRegion, XMLSourceParser textSource) {
+			ITextRegionList regions = startTagRegionCollection.getRegions();
+			String uri = null;
+			String prefix = null;
+			boolean isTaglibValue = false;
+			// skip the first two, they're the open bracket and name
+			for (int i = 2; i < regions.size(); i++) {
+				ITextRegion region = regions.get(i);
+				if (region instanceof ITextRegionCollection) {
+					// Handle nested directives
+					processRegionCollection((ITextRegionCollection) region, anchorStructuredDocumentRegion, textSource);
+				}
+				else {
+					// Handle xmlns:xxx=yyy
+					int regionStartOffset = startTagRegionCollection.getStartOffset(region);
+					int regionTextLength = region.getTextLength();
+					if (region.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) {
+						if (regionTextLength > XMLNS_LENGTH && textSource.regionMatches(regionStartOffset, XMLNS_LENGTH, XMLNS)) {
+							prefix = textSource.getText(regionStartOffset + XMLNS_LENGTH, regionTextLength - XMLNS_LENGTH);
+							if (!bannedPrefixes.contains(prefix))
+								isTaglibValue = true;
+						}
+						else {
+							prefix = null;
+							isTaglibValue = false;
+						}
+					}
+					else if (isTaglibValue && region.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
+						if (prefix != null && prefix.length() > 0) {
+							uri = textSource.getText(regionStartOffset, regionTextLength);
+							uri = StringUtils.strip(uri);
+							int uriLength = uri.length();
+							if (uri != null && uriLength > 0) {
+								if (uriLength > URN_TLD_LENGTH && uri.startsWith(URN_TLD)) {
+									uri = uri.substring(URN_TLD_LENGTH);
+								}
+								else if (uriLength > URN_TAGDIR_LENGTH && uri.startsWith(URN_TAGDIR)) {
+									uri = uri.substring(URN_TAGDIR_LENGTH);
+								}
+								enableTags(prefix, uri, anchorStructuredDocumentRegion);
+								uri = null;
+								prefix = null;
+							}
+						}
+					}
+				}
+			}
+		}
+
+		/**
+		 * Pulls the URI and prefix from the given taglib directive
+		 * IStructuredDocumentRegion and makes sure the tags are known.
+		 */
+		protected void processTaglib(ITextRegionCollection taglibDirectiveCollection, IStructuredDocumentRegion anchorStructuredDocumentRegion, XMLSourceParser textSource) {
+			ITextRegionList regions = taglibDirectiveCollection.getRegions();
+			String uri = null;
+			String prefix = null;
+			String tagdir = null;
+			String attrName = null;
+			try {
+				for (int i = 2; i < regions.size(); i++) {
+					ITextRegion region = regions.get(i);
+					// remember attribute name
+					int startOffset = taglibDirectiveCollection.getStartOffset(region);
+					int textLength = region.getTextLength();
+					if (region.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) {
+						// String name = textSource.getText(startOffset,
+						// textLength);
+						if (textSource.regionMatches(startOffset, textLength, JSP11TLDNames.PREFIX)) {
+							attrName = JSP11TLDNames.PREFIX;
+						}
+						else if (textSource.regionMatches(startOffset, textLength, JSP12TLDNames.URI)) {
+							attrName = JSP11TLDNames.URI;
+						}
+						else if (textSource.regionMatches(startOffset, textLength, JSP20TLDNames.TAGDIR)) {
+							attrName = JSP20TLDNames.TAGDIR;
+						}
+						else {
+							attrName = null;
+						}
+					}
+					// process value
+					else if (region.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
+						if (JSP11TLDNames.PREFIX.equals(attrName))
+							prefix = StringUtils.strip(textSource.getText(startOffset, textLength));
+						else if (JSP11TLDNames.URI.equals(attrName))
+							uri = StringUtils.strip(textSource.getText(startOffset, textLength));
+						else if (JSP20TLDNames.TAGDIR.equals(attrName))
+							tagdir = StringUtils.strip(textSource.getText(startOffset, textLength));
+					}
+				}
+			}
+			catch (StringIndexOutOfBoundsException sioobExc) {
+				// nothing to be done
+				uri = null;
+				prefix = null;
+			}
+			if (uri != null && prefix != null && uri.length() > 0 && prefix.length() > 0) {
+				enableTaglibFromURI(prefix, StringUtils.strip(uri), anchorStructuredDocumentRegion);
+			}
+			else if (tagdir != null && prefix != null && tagdir.length() > 0 && prefix.length() > 0) {
+				enableTagsInDir(StringUtils.strip(prefix), StringUtils.strip(tagdir), anchorStructuredDocumentRegion);
+			}
+		}
+
+		private void registerTaglib(String prefix, String uri, IStructuredDocumentRegion anchorStructuredDocumentRegion, CMDocument tld) {
+			CMNamedNodeMap elements = tld.getElements();
+			/*
+			 * Go through the CMDocument for any tags that must be marked as
+			 * block tags starting at the anchoring IStructuredDocumentRegion.
+			 * As the document is edited and the IStructuredDocumentRegion
+			 * moved around, the block tag enablement will automatically
+			 * follow it.
+			 */
+			for (int i = 0; i < elements.getLength(); i++) {
+				TLDElementDeclaration ed = (TLDElementDeclaration) elements.item(i);
+				if (ed.getBodycontent() == JSP12TLDNames.CONTENT_TAGDEPENDENT)
+					addBlockTag(prefix + ":" + ed.getNodeName(), anchorStructuredDocumentRegion); //$NON-NLS-1$
+			}
+			/*
+			 * Since modifications to StructuredDocumentRegions adjacent to a
+			 * taglib directive can cause that IStructuredDocumentRegion to be
+			 * reported, filter out any duplicated URIs. When the taglib is
+			 * actually modified, a full rebuild will occur and no duplicates
+			 * will/should be found.
+			 */
+			boolean doTrack = true;
+			List trackers = getTaglibTrackers();
+			for (int i = 0; i < trackers.size(); i++) {
+				TaglibTracker tracker = (TaglibTracker) trackers.get(i);
+				if (tracker.getPrefix().equals(prefix) && tracker.getURI().equals(uri)) {
+					doTrack = false;
+				}
+			}
+			if (doTrack) {
+				addTaglibTracker(prefix, uri, anchorStructuredDocumentRegion, tld);
+			}
+		}
+
+		private void resetBlockTags() {
+			if (getParser() == null)
+				return;
+			Iterator names = getParser().getBlockMarkers().iterator();
+			while (names.hasNext()) {
+				BlockMarker marker = (BlockMarker) names.next();
+				if (!marker.isGlobal() && marker.getContext() == DOMRegionContext.BLOCK_TEXT) {
+					if (_debug) {
+						System.out.println("TLDCMDocumentManager removing block tag named: " + marker.getTagName()); //$NON-NLS-1$
+					}
+					names.remove();
+				}
+			}
+		}
+
+		public void resetNodes() {
+			if (Debug.debugTaglibs)
+				System.out.println(getClass().getName() + ": resetting"); //$NON-NLS-1$
+			getIncludes().clear();
+			resetBlockTags();
+			resetTaglibTrackers();
+		}
+
+		public void setStructuredDocument(IStructuredDocument newDocument) {
+			Assert.isTrue(newDocument != null, "null document"); //$NON-NLS-1$
+			Assert.isTrue(newDocument.getParser() != null, "null document parser"); //$NON-NLS-1$
+			Assert.isTrue(newDocument.getParser() instanceof XMLSourceParser, "can only listen to document with a XMLSourceParser"); //$NON-NLS-1$
+			getSourceParser().removeStructuredDocumentRegionHandler(this);
+			setSourceParser((XMLSourceParser) newDocument.getParser());
+			getSourceParser().addStructuredDocumentRegionHandler(this);
+		}
+	}
+
+	protected class IncludeHelper extends DirectiveStructuredDocumentRegionHandler {
+		protected IStructuredDocumentRegion fAnchor = null;
+		protected XMLSourceParser fLocalParser = null;
+		protected XMLSourceParser fParentParser = null;
+		List taglibReferences = null;
+
+		public IncludeHelper(IStructuredDocumentRegion anchor, XMLSourceParser rootParser) {
+			super();
+			fAnchor = anchor;
+			fParentParser = rootParser;
+			taglibReferences = new ArrayList(0);
+		}
+
+		protected void addTaglibTracker(String prefix, String uri, IStructuredDocumentRegion anchorStructuredDocumentRegion, CMDocument tldCMDocument) {
+			super.addTaglibTracker(prefix, uri, anchorStructuredDocumentRegion, tldCMDocument);
+			TLDCMDocumentReference reference = new TLDCMDocumentReference();
+			reference.prefix = prefix;
+			reference.uri = uri;
+			taglibReferences.add(reference);
+		}
+
+		protected String getContents(IPath filePath) {
+			return FileContentCache.getInstance().getContents(filePath);
+		}
+
+		public void nodeParsed(IStructuredDocumentRegion structuredDocumentRegion) {
+			processRegionCollection(structuredDocumentRegion, fAnchor, fLocalParser);
+		}
+
+		/**
+		 * @param path -
+		 *            the fullpath for the resource to be parsed
+		 */
+		void parse(IPath path) {
+			XMLSourceParser p = (XMLSourceParser) getParser().newInstance();
+			fLocalParser = p;
+			String s = getContents(path);
+			// Should we consider preludes on this segment?
+			fLocalParser.addStructuredDocumentRegionHandler(IncludeHelper.this);
+			fLocalParser.reset(s);
+			List blockTags = fParentParser.getBlockMarkers();
+			for (int i = 0; i < blockTags.size(); i++) {
+				BlockMarker marker = (BlockMarker) blockTags.get(i);
+				fLocalParser.addBlockMarker(new BlockMarker(marker.getTagName(), null, marker.getContext(), marker.isCaseSensitive()));
+			}
+			if (fParentParser instanceof JSPCapableParser && fLocalParser instanceof JSPCapableParser) {
+				TagMarker[] knownPrefixes = (TagMarker[]) ((JSPCapableParser) fParentParser).getNestablePrefixes().toArray(new TagMarker[0]);
+				for (int i = 0; i < knownPrefixes.length; i++) {
+					((JSPCapableParser) fLocalParser).addNestablePrefix(new TagMarker(knownPrefixes[i].getTagName(), null));
+				}
+			}
+			// force parse
+			fLocalParser.getDocumentRegions();
+			fLocalParser = null;
+		}
+
+		public void resetNodes() {
+		}
+	}
+
+	/**
+	 * An entry in the shared cache map
+	 */
+	static class TLDCacheEntry {
+		CMDocument document;
+		long modificationStamp;
+		int referenceCount;
+	}
+
+	private class TLDCMDocumentReference {
+		String prefix;
+		String uri;
+	}
+
+	static final boolean _debug = "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.jst.jsp.core/debug/tldcmdocument/manager")); //$NON-NLS-1$ //$NON-NLS-2$
+	static final boolean _debugCache = "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.jst.jsp.core/debug/tldcmdocument/cache")); //$NON-NLS-1$ //$NON-NLS-2$
+	// will hold the prefixes banned by the specification; taglibs may not use
+	// them
+	protected static List bannedPrefixes = null;
+
+	private static Hashtable fCache = null;
+	final String XMLNS = "xmlns:"; //$NON-NLS-1$ 
+	final String URN_TAGDIR = "urn:jsptagdir:";
+	final String URN_TLD = "urn:jsptld:";
+
+	final int XMLNS_LENGTH = XMLNS.length();
+	final int URN_TAGDIR_LENGTH = URN_TAGDIR.length();
+	final int URN_TLD_LENGTH = URN_TLD.length();
+
+	static {
+		bannedPrefixes = new ArrayList(7);
+		bannedPrefixes.add("jsp"); //$NON-NLS-1$
+		bannedPrefixes.add("jspx"); //$NON-NLS-1$
+		bannedPrefixes.add("java"); //$NON-NLS-1$
+		bannedPrefixes.add("javax"); //$NON-NLS-1$
+		bannedPrefixes.add("servlet"); //$NON-NLS-1$
+		bannedPrefixes.add("sun"); //$NON-NLS-1$
+		bannedPrefixes.add("sunw"); //$NON-NLS-1$
+	}
+
+	/**
+	 * Gets all of the known documents.
+	 * 
+	 * @return Returns a Hashtable of either TLDCacheEntrys or WeakReferences
+	 *         to TLD CMDocuments
+	 */
+	public static Hashtable getSharedDocumentCache() {
+		if (fCache == null) {
+			fCache = new Hashtable();
+		}
+		return fCache;
+	}
+
+
+	public static Object getUniqueIdentifier(ITaglibRecord reference) {
+		if (reference == null)
+			return null;
+		Object identifier = null;
+		switch (reference.getRecordType()) {
+			case (ITaglibRecord.TLD) : {
+				ITLDRecord record = (ITLDRecord) reference;
+				identifier = record.getPath();
+			}
+				break;
+			case (ITaglibRecord.JAR) : {
+				IJarRecord record = (IJarRecord) reference;
+				identifier = record.getLocation();
+			}
+				break;
+			case (ITaglibRecord.TAGDIR) : {
+				ITagDirRecord record = (ITagDirRecord) reference;
+				identifier = record.getPath();
+			}
+				break;
+			case (ITaglibRecord.URL) : {
+				IURLRecord record = (IURLRecord) reference;
+				identifier = record.getURL();
+			}
+				break;
+			default :
+				identifier = reference;
+				break;
+		}
+		return identifier;
+	}
+
+	private CMDocumentFactoryTLD fCMDocumentBuilder = null;
+
+	private DirectiveStructuredDocumentRegionHandler fDirectiveHandler = null;
+
+	/**
+	 * The locally-know list of CMDocuments
+	 */
+	private Hashtable fDocuments = null;
+
+	// timestamp cache to prevent excessive reparsing
+	// of included files
+	// IPath (filepath) > Long (modification stamp)
+	HashMap fInclude2TimestampMap = new HashMap();
+
+	private Stack fIncludes = null;
+
+	private XMLSourceParser fParser = null;
+
+	private List fTaglibTrackers = null;
+
+	Map fTLDCMReferencesMap = new HashMap();
+	boolean fProcessIncludes = true;
+	boolean preludesHandled = false;
+
+	public TLDCMDocumentManager() {
+		super();
+	}
+
+	public void clearCache() {
+		if (_debugCache) {
+			System.out.println("TLDCMDocumentManager cleared its private CMDocument cache"); //$NON-NLS-1$
+		}
+		for (Iterator iter = getDocuments().keySet().iterator(); iter.hasNext();) {
+			Object key = iter.next();
+			synchronized (getSharedDocumentCache()) {
+				Object o = getSharedDocumentCache().get(key);
+				if (o instanceof TLDCacheEntry) {
+					TLDCacheEntry entry = (TLDCacheEntry) o;
+					entry.referenceCount--;
+					if (entry.referenceCount <= 0) {
+						getSharedDocumentCache().put(key, new SoftReference(entry));
+					}
+				}
+			}
+		}
+	}
+
+	/**
+	 * Derives an unique cache key for the give URI. The URI is "resolved" and
+	 * a unique value generated from the result. This ensures that two
+	 * different relative references from different files do not have
+	 * overlapping TLD records in the shared cache if they don't resolve to
+	 * the same TLD.
+	 * 
+	 * @param uri
+	 * @return
+	 */
+	protected Object getCacheKey(String uri) {
+		IPath currentParserPath = getCurrentParserPath();
+		if (currentParserPath == null)
+			return null;
+		
+		ITaglibRecord record = TaglibIndex.resolve(currentParserPath.toString(), uri, false);
+		if (record != null) {
+			return getUniqueIdentifier(record);
+		}
+		String location = URIResolverPlugin.createResolver().resolve(getCurrentBaseLocation().toString(), null, uri);
+		return location;
+	}
+
+	/**
+	 * Return the CMDocument at the uri (cached)
+	 */
+	protected CMDocument getCMDocument(String uri) {
+		if (uri == null || uri.length() == 0)
+			return null;
+		String reference = uri;
+		Object cacheKey = getCacheKey(reference);
+		if (cacheKey == null)
+			return null;
+		
+		CMDocument doc = (CMDocument) getDocuments().get(cacheKey);
+		if (doc == null) {
+			long lastModified = getModificationStamp(reference);
+			/*
+			 * If hasn't been moved into the local table, do so and increment
+			 * the count. A local URI reference can be different depending on
+			 * the file from which it was referenced. Use a computed key to
+			 * keep them straight.
+			 */
+			Object o = getSharedDocumentCache().get(cacheKey);
+			if (o != null) {
+				if (o instanceof TLDCacheEntry) {
+					TLDCacheEntry entry = (TLDCacheEntry) o;
+					if (_debugCache) {
+						System.out.println("TLDCMDocument cache hit on " + cacheKey);
+					}
+					if (entry != null && entry.modificationStamp != IResource.NULL_STAMP && entry.modificationStamp >= lastModified) {
+						doc = entry.document;
+						entry.referenceCount++;
+					}
+					else {
+						getSharedDocumentCache().remove(cacheKey);
+					}
+				}
+				else if (o instanceof Reference) {
+					TLDCacheEntry entry = (TLDCacheEntry) ((Reference) o).get();
+					if (entry != null) {
+						if (entry.modificationStamp != IResource.NULL_STAMP && entry.modificationStamp >= lastModified) {
+							doc = entry.document;
+							entry.referenceCount = 1;
+							getSharedDocumentCache().put(cacheKey, entry);
+						}
+					}
+					else {
+						getSharedDocumentCache().remove(cacheKey);
+					}
+				}
+			}
+			/* No document was found cached, create a new one and share it */
+			if (doc == null) {
+				if (_debugCache) {
+					System.out.println("TLDCMDocument cache miss on " + cacheKey);
+				}
+				CMDocument document = loadTaglib(reference);
+				if (document != null) {
+					TLDCacheEntry entry = new TLDCacheEntry();
+					doc = entry.document = document;
+					entry.referenceCount = 1;
+					entry.modificationStamp = lastModified;
+					getSharedDocumentCache().put(cacheKey, entry);
+				}
+			}
+			if (doc != null) {
+				getDocuments().put(cacheKey, doc);
+			}
+		}
+		return doc;
+	}
+
+	private long getModificationStamp(String reference) {
+		IPath currentParserPath = getCurrentParserPath();
+		if (currentParserPath == null) {
+			return IResource.NULL_STAMP;
+		}
+		
+		ITaglibRecord record = TaglibIndex.resolve(currentParserPath.toString(), reference, false);
+		long modificationStamp = IResource.NULL_STAMP;
+		if (record != null) {
+			switch (record.getRecordType()) {
+				case (ITaglibRecord.TLD) : {
+					IFile tldfile = ResourcesPlugin.getWorkspace().getRoot().getFile(((ITLDRecord) record).getPath());
+					if (tldfile.isAccessible()) {
+						modificationStamp = tldfile.getModificationStamp();
+					}
+				}
+					break;
+				case (ITaglibRecord.JAR) : {
+					File jarfile = new File(((IJarRecord) record).getLocation().toOSString());
+					if (jarfile.exists()) {
+						try {
+							modificationStamp = jarfile.lastModified();
+						}
+						catch (SecurityException e) {
+							modificationStamp = IResource.NULL_STAMP;
+						}
+					}
+				}
+					break;
+				case (ITaglibRecord.TAGDIR) : {
+					IFolder tagFolder = ResourcesPlugin.getWorkspace().getRoot().getFolder(((ITagDirRecord) record).getPath());
+					if (tagFolder.isAccessible()) {
+						IResource[] members;
+						try {
+							members = tagFolder.members();
+							for (int i = 0; i < members.length; i++) {
+								modificationStamp = Math.max(modificationStamp, members[i].getModificationStamp());
+							}
+						}
+						catch (CoreException e) {
+							modificationStamp = IResource.NULL_STAMP;
+						}
+					}
+				}
+					break;
+				case (ITaglibRecord.URL) : {
+                    String loc = ((IURLRecord) record).getBaseLocation();
+                    if (loc != null && loc.endsWith(".jar")) { //$NON-NLS-1$
+                        File jarfile = new File(loc);
+                        if (jarfile.exists()) {
+                            try {
+                                modificationStamp = jarfile.lastModified();
+                            }
+                            catch (SecurityException e) {
+                                modificationStamp = IResource.NULL_STAMP;
+                            }
+                        }
+                    }
+				}
+					break;
+				default :
+					break;
+			}
+		}
+		return modificationStamp;
+	}
+
+
+	/**
+	 * Gets the cMDocumentBuilder.
+	 * 
+	 * @return Returns a CMDocumentFactoryTLD, since it has more builder
+	 *         methods
+	 */
+	protected CMDocumentFactoryTLD getCMDocumentBuilder() {
+		if (fCMDocumentBuilder == null)
+			fCMDocumentBuilder = new CMDocumentFactoryTLD();
+		return fCMDocumentBuilder;
+	}
+
+	public List getCMDocumentTrackers(int offset) {
+		List validDocs = new ArrayList();
+		Object[] alldocs = getTaglibTrackers().toArray();
+		for (int i = 0; i < alldocs.length; i++) {
+			TaglibTracker aTracker = (TaglibTracker) alldocs[i];
+			if (aTracker.getStructuredDocumentRegion().getStartOffset() <= offset || offset < 0) {
+				validDocs.add(aTracker);
+			}
+		}
+		return validDocs;
+	}
+
+	public List getCMDocumentTrackers(String prefix, int offset) {
+		List validDocs = new ArrayList();
+		Object[] alldocs = getTaglibTrackers().toArray();
+		for (int i = 0; i < alldocs.length; i++) {
+			TaglibTracker aTracker = (TaglibTracker) alldocs[i];
+			/**
+			 * '<' is used to support the immediate use of a custom tag in jspx files (instead of '<=')
+			 */
+			if ((aTracker.getStructuredDocumentRegion().getStartOffset() <= offset || offset < 0) && aTracker.getPrefix().equals(prefix)) {
+				validDocs.add(aTracker);
+			}
+		}
+		return validDocs;
+	}
+
+	/**
+	 * Return the filesystem location in the current parser. This method is
+	 * called while recursing through included fragments, so it much check the
+	 * include stack. The filesystem location is needed for common URI
+	 * resolution in case the Taglib Index doesn't know the URI being loaded.
+	 * 
+	 * @return
+	 */
+	IPath getCurrentBaseLocation() {
+		IPath baseLocation = null;
+		IPath path = getCurrentParserPath();
+		if (path == null || path.segmentCount() < 2)
+			return path;
+		baseLocation = ResourcesPlugin.getWorkspace().getRoot().getFile(path).getLocation();
+		if (baseLocation == null) {
+			baseLocation = path;
+		}
+		return baseLocation;
+	}
+
+	/**
+	 * Return the path used in the current parser. This method is called while
+	 * recursing through included fragments, so it much check the include
+	 * stack.
+	 * 
+	 * @return
+	 */
+	IPath getCurrentParserPath() {
+		IPath path = null;
+		if (!getIncludes().isEmpty()) {
+			path = (IPath) getIncludes().peek();
+		}
+		else {
+			path = TaglibController.getLocation(this);
+		}
+
+		return path;
+	}
+
+	protected DirectiveStructuredDocumentRegionHandler getDirectiveStructuredDocumentRegionHandler() {
+		if (fDirectiveHandler == null)
+			fDirectiveHandler = new DirectiveStructuredDocumentRegionHandler();
+		return fDirectiveHandler;
+	}
+
+	/**
+	 * Gets the documents.
+	 * 
+	 * @return Returns a java.util.Hashtable
+	 */
+	public Hashtable getDocuments() {
+		if (fDocuments == null)
+			fDocuments = new Hashtable();
+		return fDocuments;
+	}
+
+	/**
+	 * Gets the includes.
+	 * 
+	 * @return Returns a Stack
+	 */
+	protected Stack getIncludes() {
+		if (fIncludes == null)
+			fIncludes = new Stack();
+		return fIncludes;
+	}
+
+	XMLSourceParser getParser() {
+		return fParser;
+	}
+
+	public XMLSourceParser getSourceParser() {
+		return fParser;
+	}
+
+	public StructuredDocumentRegionHandler getStructuredDocumentRegionHandler() {
+		return getDirectiveStructuredDocumentRegionHandler();
+	}
+
+	/**
+	 * 
+	 * @return java.util.List
+	 */
+	public List getTaglibTrackers() {
+		if (fTaglibTrackers == null)
+			fTaglibTrackers = new ArrayList();
+		return fTaglibTrackers;
+	}
+
+	void handlePreludes() {
+		IStructuredDocumentRegion anchor = new ZeroStructuredDocumentRegion(null, -1);
+		fProcessIncludes = false;
+
+		IPath currentPath = getCurrentParserPath();
+		if (currentPath != null) {
+			PropertyGroup[] propertyGroups = DeploymentDescriptorPropertyCache.getInstance().getPropertyGroups(currentPath);
+			for(int k = 0; k < propertyGroups.length; k++) {
+				IPath[] preludes = propertyGroups[k].getIncludePrelude();
+				for (int i = 0; i < preludes.length; i++) {
+					if (!getIncludes().contains(preludes[i]) && !preludes[i].equals(currentPath)) {
+						getIncludes().push(preludes[i]);
+						if (getParser() != null) {
+							IncludeHelper includeHelper = new IncludeHelper(anchor, getParser());
+							includeHelper.parse(preludes[i]);
+							List references = includeHelper.taglibReferences;
+							fTLDCMReferencesMap.put(preludes[i], references);
+							if (getParser() instanceof JSPCapableParser) {
+								for (int j = 0; j < references.size(); j++) {
+									TLDCMDocumentReference reference = (TLDCMDocumentReference) references.get(j);
+									((JSPCapableParser) getParser()).addNestablePrefix(new TagMarker(reference.prefix + ":")); //$NON-NLS-1$
+								}
+							}
+						}
+						else
+							Logger.log(Logger.WARNING, "Warning: parser text was requested by " + getClass().getName() + " but none was available; taglib support disabled"); //$NON-NLS-1$ //$NON-NLS-2$
+						getIncludes().pop();
+					}
+				}
+			}
+		}
+
+		fProcessIncludes = true;
+	}
+
+	/**
+	 * @param filePath
+	 *            the path to check for modification
+	 */
+	boolean hasAnyIncludeBeenModified(IPath filePath) {
+		boolean result = false;
+		// check the top level
+		if (hasBeenModified(filePath)) {
+			result = true;
+		}
+		else {
+			// check all includees
+			Iterator iter = fInclude2TimestampMap.keySet().iterator();
+			while (iter.hasNext()) {
+				if (hasBeenModified((IPath) iter.next())) {
+					result = true;
+					break;
+				}
+			}
+		}
+		return result;
+	}
+
+	/**
+	 * @param filename
+	 * @return
+	 */
+	boolean hasBeenModified(IPath filePath) {
+		boolean result = false;
+		// quick filename/timestamp cache check here...
+		IFile f = null;
+		if (f == null && filePath.segmentCount() > 1) {
+			f = ResourcesPlugin.getWorkspace().getRoot().getFile(filePath);
+		}
+		if (f != null && f.exists()) {
+			Long currentStamp = new Long(f.getModificationStamp());
+			Object o = fInclude2TimestampMap.get(filePath);
+			if (o != null) {
+				Long previousStamp = (Long) o;
+				// stamps don't match, file changed
+				if (currentStamp.longValue() != previousStamp.longValue()) {
+					result = true;
+					// store for next time
+					fInclude2TimestampMap.put(filePath, currentStamp);
+				}
+			}
+			else {
+				// return true, since we've not encountered this file yet.
+				result = true;
+				// store for next time
+				fInclude2TimestampMap.put(filePath, currentStamp);
+			}
+		}
+		return result;
+	}
+
+	public void indexChanged(ITaglibIndexDelta event) {
+		synchronized (getSharedDocumentCache()) {
+			Iterator values = getSharedDocumentCache().values().iterator();
+			while (values.hasNext()) {
+				Object o = values.next();
+				if (o instanceof Reference) {
+					values.remove();
+				}
+			}
+		}
+	}
+
+	/**
+	 * Loads the taglib from the specified URI. It must point to a valid
+	 * taglib descriptor to work.
+	 */
+	protected CMDocument loadTaglib(String uri) {
+		CMDocument document = null;
+		IPath currentPath = getCurrentParserPath();
+		if (currentPath != null) {
+			ITaglibRecord record = TaglibIndex.resolve(currentPath.toString(), uri, false);
+			if (record != null) {
+				document = getCMDocumentBuilder().createCMDocument(record);
+			}
+			else {
+				/* Not a very-often used code path (we hope) */
+				IPath currentBaseLocation = getCurrentBaseLocation();
+				if (currentBaseLocation != null) {
+					String location = URIResolverPlugin.createResolver().resolve(currentBaseLocation.toString(), null, uri);
+					if (location != null) {
+						if (_debug) {
+							System.out.println("Loading tags from " + uri + " at " + location); //$NON-NLS-2$//$NON-NLS-1$
+						}
+						document = getCMDocumentBuilder().createCMDocument(location);
+					}
+				}
+			}
+		}
+		return document;
+	}
+
+	protected void resetTaglibTrackers() {
+		if (_debug) {
+			System.out.println("TLDCMDocumentManager cleared its taglib trackers\n"); //$NON-NLS-1$
+		}
+		preludesHandled = false;
+		getTaglibTrackers().clear();
+	}
+
+	public void setSourceParser(XMLSourceParser parser) {
+		if (fParser != null)
+			fParser.removeStructuredDocumentRegionHandler(getStructuredDocumentRegionHandler());
+		fParser = parser;
+		if (fParser != null)
+			fParser.addStructuredDocumentRegionHandler(getStructuredDocumentRegionHandler());
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/TLDFunctionImpl.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/TLDFunctionImpl.java
new file mode 100644
index 0000000..364711b
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/TLDFunctionImpl.java
@@ -0,0 +1,151 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.contentmodel.tld;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.TLDFunction;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+
+public class TLDFunctionImpl implements TLDFunction {
+	private String fClassName = null;
+	private String fDescription = null;
+	private String fDisplayName = null;
+	private String fExample = null;
+	private List fExtensions = new ArrayList(0);
+	private String fIcon = null;
+	private String fName = null;
+
+	private CMDocument fOwnerDocument = null;
+	private String fSignature = null;
+
+	public TLDFunctionImpl(CMDocument owner) {
+		super();
+		fOwnerDocument = owner;
+	}
+
+	/**
+	 * @return Returns the className.
+	 */
+	public String getClassName() {
+		return fClassName;
+	}
+	/**
+	 * @return Returns the description.
+	 */
+	public String getDescription() {
+		return fDescription;
+	}
+
+	/**
+	 * @return Returns the displayName.
+	 */
+	public String getDisplayName() {
+		return fDisplayName;
+	}
+
+	/**
+	 * @return Returns the example.
+	 */
+	public String getExample() {
+		return fExample;
+	}
+
+	/**
+	 * @return Returns the extensions.
+	 */
+	public List getExtensions() {
+		return fExtensions;
+	}
+
+	/**
+	 * @return Returns the icon.
+	 */
+	public String getIcon() {
+		return fIcon;
+	}
+
+	/**
+	 * @return Returns the name.
+	 */
+	public String getName() {
+		return fName;
+	}
+
+	/**
+	 * @return Returns the ownerDocument.
+	 */
+	public CMDocument getOwnerDocument() {
+		return fOwnerDocument;
+	}
+
+	/**
+	 * @return Returns the signature.
+	 */
+	public String getSignature() {
+		return fSignature;
+	}
+
+	/**
+	 * @param className
+	 *            The className to set.
+	 */
+	public void setClassName(String className) {
+		fClassName = className;
+	}
+	/**
+	 * @param description The description to set.
+	 */
+	public void setDescription(String description) {
+		fDescription = description;
+	}
+
+	/**
+	 * @param displayName
+	 *            The displayName to set.
+	 */
+	public void setDisplayName(String displayName) {
+		fDisplayName = displayName;
+	}
+
+	/**
+	 * @param example
+	 *            The example to set.
+	 */
+	public void setExample(String example) {
+		fExample = example;
+	}
+
+	/**
+	 * @param icon
+	 *            The icon to set.
+	 */
+	public void setIcon(String icon) {
+		fIcon = icon;
+	}
+
+	/**
+	 * @param name
+	 *            The name to set.
+	 */
+	public void setName(String name) {
+		fName = name;
+	}
+
+	/**
+	 * @param signature
+	 *            The signature to set.
+	 */
+	public void setSignature(String signature) {
+		fSignature = signature;
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/TLDInitParamImpl.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/TLDInitParamImpl.java
new file mode 100644
index 0000000..c1cdfe6
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/TLDInitParamImpl.java
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 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
+ *******************************************************************************/
+/*
+ * Created on Sep 9, 2003
+ *
+ * To change the template for this generated file go to
+ * Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments
+ */
+package org.eclipse.jst.jsp.core.internal.contentmodel.tld;
+
+import org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.TLDInitParam;
+import org.eclipse.wst.sse.core.utils.StringUtils;
+
+
+public class TLDInitParamImpl implements TLDInitParam {
+	private String description;
+	private String name;
+	private String value;
+
+	public TLDInitParamImpl() {
+		super();
+	}
+
+	public String getDescription() {
+		return description;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public String getValue() {
+		return value;
+	}
+
+	public void setDescription(String description) {
+		this.description = description;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	public void setValue(String value) {
+		this.value = value;
+	}
+
+	public String toString() {
+		StringBuffer buffer = new StringBuffer();
+		buffer.append(super.toString());
+		buffer.append("\n\t name:" + StringUtils.escape(getName())); //$NON-NLS-1$
+		buffer.append("\n\t description:" + StringUtils.escape(getDescription())); //$NON-NLS-1$
+		buffer.append("\n\t value:" + StringUtils.escape(getValue())); //$NON-NLS-1$
+		return buffer.toString();
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/TLDListenerImpl.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/TLDListenerImpl.java
new file mode 100644
index 0000000..24ef99c
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/TLDListenerImpl.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 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
+ *******************************************************************************/
+/*
+ * Created on Sep 9, 2003
+ *
+ * To change the template for this generated file go to
+ * Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments
+ */
+package org.eclipse.jst.jsp.core.internal.contentmodel.tld;
+
+import org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.TLDListener;
+import org.eclipse.wst.sse.core.utils.StringUtils;
+
+
+public class TLDListenerImpl implements TLDListener {
+	protected String listenerClass;
+
+	public String getListenerClass() {
+		return listenerClass;
+	}
+
+	public void setListenerClass(String className) {
+		listenerClass = className;
+	}
+
+	public String toString() {
+		StringBuffer buffer = new StringBuffer();
+		buffer.append(super.toString());
+		buffer.append("\n\t listener class:" + StringUtils.escape(getListenerClass())); //$NON-NLS-1$
+		return buffer.toString();
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/TLDValidatorImpl.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/TLDValidatorImpl.java
new file mode 100644
index 0000000..446f743
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/TLDValidatorImpl.java
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 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
+ *******************************************************************************/
+/*
+ * Created on Sep 9, 2003
+ *
+ * To change the template for this generated file go to
+ * Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments
+ */
+package org.eclipse.jst.jsp.core.internal.contentmodel.tld;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.TLDValidator;
+import org.eclipse.wst.sse.core.utils.StringUtils;
+
+
+public class TLDValidatorImpl implements TLDValidator {
+	protected List initParams;
+	protected String validatorClass;
+
+	public List getInitParams() {
+		if (initParams == null)
+			initParams = new ArrayList();
+		return initParams;
+	}
+
+	public String getValidatorClass() {
+		return validatorClass;
+	}
+
+	public void setInitParams(List initParams) {
+		this.initParams = initParams;
+	}
+
+	public void setValidatorClass(String validatorClass) {
+		this.validatorClass = validatorClass;
+	}
+
+	public String toString() {
+		StringBuffer buffer = new StringBuffer();
+		buffer.append(super.toString());
+		buffer.append("\n\t validator class:" + StringUtils.escape(getValidatorClass())); //$NON-NLS-1$
+		buffer.append("\n\t init-parms:"); //$NON-NLS-1$
+		for (int i = 0; i < getInitParams().size(); i++) {
+			buffer.append("\n" + StringUtils.replace(getInitParams().get(i).toString(), "\n", "\n\t\t")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+		}
+		return buffer.toString();
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/TLDVariableImpl.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/TLDVariableImpl.java
new file mode 100644
index 0000000..ff7b75c
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/TLDVariableImpl.java
@@ -0,0 +1,116 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.contentmodel.tld;
+
+import org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.JSP12TLDNames;
+import org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.TLDVariable;
+import org.eclipse.wst.sse.core.utils.StringUtils;
+
+
+public class TLDVariableImpl implements TLDVariable {
+	// optional - defaults to true
+	private boolean declare = true;
+
+	private String fDescription;
+	// required
+	private String nameFromAttribute;
+	// required
+	private String nameGiven;
+	// optional - defaults to NESTED
+	private String scope = JSP12TLDNames.VARIABLE_SCOPE_NESTED;
+	// required - defaults to a String
+	private String variableClass = "java.lang.String"; //$NON-NLS-1$
+
+	private String fAlias;
+
+	public boolean getDeclare() {
+		return declare;
+	}
+
+	/**
+	 * @return Returns the description.
+	 */
+	public String getDescription() {
+		return fDescription;
+	}
+
+	public String getNameFromAttribute() {
+		return nameFromAttribute;
+	}
+
+	public String getNameGiven() {
+		return nameGiven;
+	}
+
+	public String getScope() {
+		return scope;
+	}
+
+	public String getVariableClass() {
+		return variableClass;
+	}
+
+	public void setDeclare(boolean declare) {
+		this.declare = declare;
+	}
+
+	public void setDeclareString(String decl) {
+		if (decl != null) {
+			setDeclare(decl.equals(JSP12TLDNames.TRUE) || decl.equals(JSP12TLDNames.YES));
+		}
+	}
+
+	/**
+	 * @param description
+	 *            The description to set.
+	 */
+	public void setDescription(String description) {
+		fDescription = description;
+	}
+
+	public void setNameFromAttribute(String nameFromAttribute) {
+		this.nameFromAttribute = nameFromAttribute;
+	}
+
+	public void setNameGiven(String nameGiven) {
+		this.nameGiven = nameGiven;
+	}
+
+	public void setScope(String scope) {
+		this.scope = scope;
+	}
+
+	public void setVariableClass(String variableClass) {
+		this.variableClass = variableClass;
+	}
+
+	public String toString() {
+		StringBuffer buffer = new StringBuffer();
+		buffer.append(super.toString());
+		buffer.append("\n\t name given:" + StringUtils.escape(getNameGiven())); //$NON-NLS-1$
+		buffer.append("\n\t name from attribute:" + StringUtils.escape(getNameFromAttribute())); //$NON-NLS-1$
+		// Boolean.toString(boolean) is introduced in JDK 1.4
+		// buffer.append("\n\t declare:" +
+		// StringUtils.escape(Boolean.toString(getDeclare())));
+		buffer.append("\n\t declare:" + StringUtils.toString(getDeclare())); //$NON-NLS-1$
+		buffer.append("\n\t scope:" + StringUtils.escape(getScope())); //$NON-NLS-1$
+		buffer.append("\n\t variable class:" + StringUtils.escape(getVariableClass())); //$NON-NLS-1$
+		return buffer.toString();
+	}
+
+	public String getAlias() {
+		return fAlias;
+	}
+
+	public void setAlias(String alias) {
+		fAlias = alias;
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/TaglibTracker.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/TaglibTracker.java
new file mode 100644
index 0000000..a8351aa
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/TaglibTracker.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.contentmodel.tld;
+
+
+
+import org.eclipse.jst.jsp.core.internal.contentmodel.CMDocumentWrapperImpl;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.provisional.contentmodel.CMDocumentTracker;
+
+/**
+ * TaglibTracker class
+ */
+public class TaglibTracker extends CMDocumentWrapperImpl implements CMDocumentTracker {
+
+	private IStructuredDocumentRegion fStructuredDocumentRegion;
+
+	public TaglibTracker(String newURI, String newPrefix, CMDocument tld, IStructuredDocumentRegion aStructuredDocumentRegion) {
+		super(newURI, newPrefix, tld);
+		fStructuredDocumentRegion = aStructuredDocumentRegion;
+	}
+
+	public IStructuredDocumentRegion getStructuredDocumentRegion() {
+		return fStructuredDocumentRegion;
+	}
+
+	public String toString() {
+		if (getStructuredDocumentRegion() != null)
+			return getPrefix() + "@" + getStructuredDocumentRegion().getStartOffset(); //$NON-NLS-1$
+		return super.toString();
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/provisional/JSP11TLDNames.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/provisional/JSP11TLDNames.java
new file mode 100644
index 0000000..c24959a
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/provisional/JSP11TLDNames.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 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
+ *******************************************************************************/
+/*nlsXXX*/
+package org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional;
+
+public interface JSP11TLDNames {
+
+	String TAGLIB = "taglib"; //$NON-NLS-1$
+
+	String CONTENT_JSP = "JSP"; //$NON-NLS-1$
+	String CONTENT_EMPTY = "empty"; //$NON-NLS-1$
+	String CONTENT_TAGDEPENDENT = "tagdependent"; //$NON-NLS-1$
+
+	String TAG = "tag"; //$NON-NLS-1$
+	String JSPVERSION = "jspversion"; //$NON-NLS-1$
+	String TLIBVERSION = "tlibversion"; //$NON-NLS-1$
+	String SHORTNAME = "shortname"; //$NON-NLS-1$
+	String URI = "uri"; //$NON-NLS-1$
+	String URN = "urn"; //$NON-NLS-1$
+	String INFO = "info"; //$NON-NLS-1$
+
+	String NAME = "name"; //$NON-NLS-1$
+	String TEICLASS = "teiclass"; //$NON-NLS-1$
+	String TAGCLASS = "tagclass"; //$NON-NLS-1$
+	String BODYCONTENT = "bodycontent"; //$NON-NLS-1$
+	String ATTRIBUTE = "attribute"; //$NON-NLS-1$
+
+	String ID = "id"; //$NON-NLS-1$
+	String REQUIRED = "required"; //$NON-NLS-1$
+	String RTEXPRVALUE = "rtexprvalue"; //$NON-NLS-1$
+
+	String PREFIX = "prefix"; //$NON-NLS-1$
+
+	String INCLUDE = "include"; //$NON-NLS-1$
+	String FILE = "file"; //$NON-NLS-1$
+
+	String TRUE = "true"; //$NON-NLS-1$
+	String FALSE = "false"; //$NON-NLS-1$
+	String YES = "yes"; //$NON-NLS-1$
+	String NO = "no"; //$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/provisional/JSP12TLDNames.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/provisional/JSP12TLDNames.java
new file mode 100644
index 0000000..0ab3124
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/provisional/JSP12TLDNames.java
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 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
+ *******************************************************************************/
+/*nlsXXX*/
+package org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional;
+
+public interface JSP12TLDNames {
+
+	String TAGLIB = JSP11TLDNames.TAGLIB;
+
+	String CONTENT_JSP = JSP11TLDNames.CONTENT_JSP;
+	String CONTENT_EMPTY = JSP11TLDNames.CONTENT_EMPTY;
+	String CONTENT_TAGDEPENDENT = JSP11TLDNames.CONTENT_TAGDEPENDENT;
+
+	String TAG = JSP11TLDNames.TAG;
+	String JSP_VERSION = "jsp-version"; //$NON-NLS-1$
+	String TLIB_VERSION = "tlib-version"; //$NON-NLS-1$
+	String SHORT_NAME = "short-name"; //$NON-NLS-1$
+	String URI = JSP11TLDNames.URI;
+	String URN = JSP11TLDNames.URN;
+
+	String NAME = JSP11TLDNames.NAME;
+	String TEI_CLASS = "tei-class"; //$NON-NLS-1$
+	String TAG_CLASS = "tag-class"; //$NON-NLS-1$
+	String BODY_CONTENT = "body-content"; //$NON-NLS-1$
+	String ATTRIBUTE = JSP11TLDNames.ATTRIBUTE;
+
+	String ID = JSP11TLDNames.ID;
+	String REQUIRED = JSP11TLDNames.REQUIRED;
+	String RTEXPRVALUE = JSP11TLDNames.RTEXPRVALUE;
+
+	String PREFIX = JSP11TLDNames.PREFIX;
+
+	String INCLUDE = JSP11TLDNames.INCLUDE;
+	String FILE = JSP11TLDNames.FILE;
+
+	String TRUE = JSP11TLDNames.TRUE;
+	String FALSE = JSP11TLDNames.FALSE;
+	String YES = JSP11TLDNames.YES;
+	String NO = JSP11TLDNames.NO;
+
+	/*
+	 * @see Eclipse JSP 1.2
+	 */
+	String DESCRIPTION = "description"; //$NON-NLS-1$
+	String DISPLAY_NAME = "display-name"; //$NON-NLS-1$
+	String SMALL_ICON = "small-icon"; //$NON-NLS-1$
+	String LARGE_ICON = "large-icon"; //$NON-NLS-1$
+
+
+	String VALIDATOR = "validator"; //$NON-NLS-1$
+	String VALIDATOR_CLASS = "validator-class"; //$NON-NLS-1$
+	String VALIDATOR_INIT_PARAM = "init-param"; //$NON-NLS-1$
+	String VALIDATOR_PARAM_NAME = "param-name"; //$NON-NLS-1$
+	String VALIDATOR_PARAM_VALUE = "param-value"; //$NON-NLS-1$
+
+
+	String LISTENER = "listener"; //$NON-NLS-1$
+	String LISTENER_CLASS = "listener-class"; //$NON-NLS-1$
+
+	String VARIABLE = "variable"; //$NON-NLS-1$
+	String VARIABLE_NAME_GIVEN = "name-given"; //$NON-NLS-1$
+	String VARIABLE_NAME_FROM_ATTRIBUTE = "name-from-attribute"; //$NON-NLS-1$
+	String VARIABLE_CLASS = "variable-class"; //$NON-NLS-1$
+	String VARIABLE_DECLARE = "declare"; //$NON-NLS-1$
+	String VARIABLE_SCOPE = "scope"; //$NON-NLS-1$
+	String VARIABLE_SCOPE_NESTED = "NESTED"; //$NON-NLS-1$
+	String VARIABLE_SCOPE_AT_BEGIN = "AT_BEGIN"; //$NON-NLS-1$
+	String VARIABLE_SCOPE_AT_END = "AT_END"; //$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/provisional/JSP20TLDNames.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/provisional/JSP20TLDNames.java
new file mode 100644
index 0000000..b52ae61
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/provisional/JSP20TLDNames.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional;
+
+/* nlsXXX */
+public interface JSP20TLDNames extends JSP12TLDNames {
+	String CONTENT_SCRIPTLESS = "scriptless"; //$NON-NLS-1$
+	String EXAMPLE = "example"; //$NON-NLS-1$
+	String FRAGMENT = "fragment"; //$NON-NLS-1$
+	String FUNCTION = "function"; //$NON-NLS-1$
+	String FUNCTION_CLASS = "function-class"; //$NON-NLS-1$
+	String FUNCTION_EXTENSION = "function-extension"; //$NON-NLS-1$
+	String FUNCTION_SIGNATURE = "function-signature"; //$NON-NLS-1$
+	String ICON = "icon"; //$NON-NLS-1$
+	String PATH = "path"; //$NON-NLS-1$
+	String TAG_EXTENSION = "tag-extension"; //$NON-NLS-1$
+	String TAG_FILE = "tag-file"; //$NON-NLS-1$
+
+	String TAGDIR = "tagdir"; //$NON-NLS-1$
+
+	String TAGLIB_EXTENSION = "taglib-extension"; //$NON-NLS-1$
+
+	String DYNAMIC_ATTRIBUTES = "dynamic-attributes"; //$NON-NLS-1$
+	String SCRIPTING_LANGUAGE = "language"; //$NON-NLS-1$
+	String IMPORT = "import"; //$NON-NLS-1$
+	String IS_EL_IGNORED = "isELIgnored"; //$NON-NLS-1$
+	String PAGE_ENCODING = "pageEncoding"; //$NON-NLS-1$
+	String TYPE = "type"; //$NON-NLS-1$
+	String VARIABLE_ALIAS = "alias"; //$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/provisional/TLDAttributeDeclaration.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/provisional/TLDAttributeDeclaration.java
new file mode 100644
index 0000000..3f57eeb
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/provisional/TLDAttributeDeclaration.java
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional;
+
+
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+
+/**
+ * Represents an attribute definition from a TLD
+ */
+public interface TLDAttributeDeclaration extends CMAttributeDeclaration {
+
+	/**
+	 * a description of the attribute
+	 * @return String
+	 * @see  JSP 2.0
+	 */
+	String getDescription();
+	
+	/**
+	 * the attribute's name
+	 * @see  JSP 1.1
+	 */
+	String getId();
+
+	CMDocument getOwnerDocument();
+
+	/**
+	 * whether the attribute's value may be dynamically calculated at runtime by an expression
+	 * @see  JSP 1.1
+	 */
+	String getRtexprvalue();
+
+	/**
+	 * the type of the attribute's value
+	 * @see  JSP 1.2
+	 */
+	String getType();
+
+	/**
+	 * whether this attribute is a fragment
+	 * 
+	 * @return boolean
+	 */
+	boolean isFragment();
+	
+	/**
+	 * if the attribute is required or optional
+	 * @see  JSP 1.1
+	 */
+	boolean isRequired();
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/provisional/TLDDocument.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/provisional/TLDDocument.java
new file mode 100644
index 0000000..81351e5
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/provisional/TLDDocument.java
@@ -0,0 +1,105 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional;
+
+import java.util.List;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+
+public interface TLDDocument extends CMDocument {
+
+	String CM_KIND = "Content Model Kind"; //$NON-NLS-1$
+	String JSP_TLD = "JSP Tag Library Descriptor"; //$NON-NLS-1$
+
+	/**
+	 * @see  JSP 2.0
+	 * 
+	 * @return
+	 */
+	String getBaseLocation();
+	
+	/**
+	 * @return String - The contents of the "description" element of a JSP 1.2 tag library descriptor; a simple string describing the "use" of this taglib, should be user discernable.
+	 * @see  JSP 1.2
+	 */
+	String getDescription();
+
+	/**
+	 * @return String - The contents of the "display-name" element of a JSP 1.2 tag library descriptor; it is a short name that is intended to be displayed by tools
+	 * @see  JSP 1.2
+	 */
+	String getDisplayName();
+
+	/**
+	 * @return List - A list of extension elements describing the tag library
+	 * @see  JSP 2.0
+	 */
+	List getExtensions();
+	
+	/**
+	 * @return List - A list of TLDFunctions describing the declared functions
+	 * @see  JSP 2.0
+	 */
+	List getFunctions();
+	
+	/**
+	 * @return String - The contents of the "info" element of a JSP 1.1 tag library descriptor; a simple string describing the "use" of this taglib, should be user discernable.
+	 * @see  JSP 1.1
+	 */
+	String getInfo();
+
+	/**
+	 * @return String - The version of JSP the tag library depends upon
+	 * @see  JSP 1.1
+	 */
+	String getJspversion();
+
+	/**
+	 * @return String - The contents of the "large-icon" element of a JSP 1.2 tag library descriptor; optional large-icon that can be used by tools
+	 * @see  JSP 1.2
+	 */
+	String getLargeIcon();
+
+	/**
+	 * @see  JSP 1.2
+	 * @return List - a List of TLDListeners
+	 */
+	List getListeners();
+
+	/**
+	 * @return String - A simple default short name that could be used by a JSP authoring tool to create names with a mnemonic value; for example, it may be used as the preferred prefix value in taglib directives
+	 * @see  JSP 1.1
+	 */
+	String getShortname();
+
+	/**
+	 * @return String - The contents of the "small-icon" element of a JSP 1.2 tag library descriptor; optional small-icon that can be used by tools
+	 * @see  JSP 1.2
+	 */
+	String getSmallIcon();
+
+	/**
+	 * @return String - The version of the tag library (it's implementation)
+	 * @see  JSP 1.1
+	 */
+	String getTlibversion();
+
+	/**
+	 * @return String - the URI declared within the descriptor
+	 * @see  JSP 1.1
+	 */
+	String getUri();
+
+	/**
+	 * @see  JSP 1.2
+	 */
+	TLDValidator getValidator();
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/provisional/TLDElementDeclaration.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/provisional/TLDElementDeclaration.java
new file mode 100644
index 0000000..dd34980
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/provisional/TLDElementDeclaration.java
@@ -0,0 +1,133 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional;
+
+import java.util.List;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+
+public interface TLDElementDeclaration extends CMElementDeclaration {
+	/** 
+	 * Property stating whether the {@link CMElementDeclaration}
+	 * is a library tag or not
+	 */
+	String IS_LIBRARY_TAG = "isLibraryTag"; //$NON-NLS-1$
+	
+	String TAG_SOURCE = "Tag Definition Source"; //$NON-NLS-1$
+	String SOURCE_JSP_TLD = "JSP Tag Library Descriptor"; //$NON-NLS-1$
+	String SOURCE_TAG_FILE = "JSP Tag 2.0 File"; //$NON-NLS-1$
+
+	/**
+	 * The body content type
+	 * 
+	 * @see JSP 1.1
+	 */
+	String getBodycontent();
+
+	/**
+	 * Optional tag-specific information
+	 * 
+	 * @see JSP 1.2
+	 */
+	String getDescription();
+
+	/**
+	 * A short name that is intended to be displayed by tools
+	 * 
+	 * @see JSP 1.2
+	 */
+	String getDisplayName();
+
+
+	/**
+	 * Indicates that the declared tag handler supports dynamic attributes. It
+	 * is not a guarantee that the class itself implements
+	 * javax.servlet.jsp.tagext.DynamicAttributes.
+	 * 
+	 * @see JSP 2.0
+	 */
+	String getDynamicAttributes();
+	
+	/**
+	 * Optional informal description of an example of a use of this tag
+	 * 
+	 * @see JSP 2.0
+	 */
+	String getExample();
+
+	/**
+	 * Zero or more extensions that provide extra information about this tag,
+	 * for tool consumption
+	 * 
+	 * @see JSP 2.0
+	 */
+	List getExtensions();
+
+	/**
+	 * Optional tag-specific information
+	 * 
+	 * @see JSP 1.1
+	 */
+	String getInfo();
+
+	/**
+	 * Name of an optional large icon that can be used by tools
+	 * 
+	 * @see JSP 1.2
+	 */
+	String getLargeIcon();
+
+	CMDocument getOwnerDocument();
+
+	/**
+	 * Where to find the .tag file implementing this action, relative to the
+	 * root of the web application or the root of the JAR file for a tag
+	 * library packaged in a JAR. This must begin with /WEB-INF/tags if the
+	 * .tag file resides in the WAR, or /META-INF/tags if the .tag file
+	 * resides in a JAR.
+	 * 
+	 * 
+	 * @return the path to the .tag(x) file as defined in the .tld file, null
+	 *         if internal to the .tld
+	 * @see JSP 2.0
+	 */
+	String getPath();
+
+	/**
+	 * Name of an optional small icon that can be used by tools
+	 * 
+	 * @see JSP 1.2
+	 */
+	String getSmallIcon();
+
+	/**
+	 * The name of the tag handler class implementing
+	 * javax.servlet.jsp.tagext.Tag
+	 * 
+	 * @see JSP 1.1
+	 */
+	String getTagclass();
+
+	/**
+	 * The name of an optional subclass of
+	 * javax.servlet.jsp.tagext.TagExtraInfo
+	 * 
+	 * @see JSP 1.1
+	 */
+	String getTeiclass();
+
+	/**
+	 * @see JSP 1.2
+	 * @return List of TLDVariables
+	 */
+	List getVariables();
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/provisional/TLDFunction.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/provisional/TLDFunction.java
new file mode 100644
index 0000000..a43e963
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/provisional/TLDFunction.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional;
+
+import java.util.List;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+
+public interface TLDFunction {
+
+	String getClassName();
+	
+	String getDescription();
+
+	String getDisplayName();
+
+	String getExample();
+
+	List getExtensions();
+
+	String getIcon();
+
+	String getName();
+
+	CMDocument getOwnerDocument();
+
+	String getSignature();
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/provisional/TLDInitParam.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/provisional/TLDInitParam.java
new file mode 100644
index 0000000..fed09aa
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/provisional/TLDInitParam.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional;
+
+
+/**
+ * A name/value pair as an initialization param along with a description
+ * @see JSP 1.2
+ */
+public interface TLDInitParam {
+	String getDescription();
+
+	/**
+	 * The param-name element contains the name of a parameter.
+	 */
+	String getName();
+
+	/**
+	 * The param-value element contains the name of a parameter.
+	 */
+	String getValue();
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/provisional/TLDListener.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/provisional/TLDListener.java
new file mode 100644
index 0000000..8d6f0e5
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/provisional/TLDListener.java
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional;
+
+
+/**
+ * Defines an optional event listener object to be instantiated and registered automatically
+ * @see JSP 1.2
+ */
+public interface TLDListener {
+	String getListenerClass();
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/provisional/TLDValidator.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/provisional/TLDValidator.java
new file mode 100644
index 0000000..09ee730
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/provisional/TLDValidator.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional;
+
+import java.util.List;
+
+
+/**
+ * Defines an optional validator that can be used to validate the conformance of a JSP page to using this tag library
+ * @see JSP 1.2
+ */
+public interface TLDValidator {
+	/**
+	 * @return List - a List of TLDInitParams
+	 */
+	List getInitParams();
+
+	String getValidatorClass();
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/provisional/TLDVariable.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/provisional/TLDVariable.java
new file mode 100644
index 0000000..611382c
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/provisional/TLDVariable.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional;
+
+/**
+ * Information on the scripting variables defined by this tag.
+ * 
+ * @see JSP 1.2
+ */
+public interface TLDVariable {
+
+	/**
+	 * Whether the variable is declared or not, true is the default.
+	 */
+	boolean getDeclare();
+
+	/**
+	 * @returnthe the description for this variable
+	 */
+	String getDescription();
+
+	/**
+	 * The name of an attribute whose (translation time) value will give the
+	 * name of the variable, or null of the name is not to be obtained this
+	 * way.
+	 */
+	String getNameFromAttribute();
+
+	/**
+	 * The variable name given as a constant, or null of the name is not
+	 * specified.
+	 */
+	String getNameGiven();
+
+	/**
+	 * The scope of the scripting variable defined.
+	 */
+	String getScope();
+
+	/**
+	 * Name of the class of the variable, java.lang.String if null
+	 */
+	String getVariableClass();
+
+	/**
+	 * A locally scoped attribute to hold the value of this variable
+	 */
+	String getAlias();
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentproperties/JSPFContentProperties.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentproperties/JSPFContentProperties.java
new file mode 100644
index 0000000..2ece904
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentproperties/JSPFContentProperties.java
@@ -0,0 +1,213 @@
+/*******************************************************************************
+ * Copyright (c) 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.contentproperties;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ProjectScope;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jst.jsp.core.internal.JSPCorePlugin;
+import org.eclipse.jst.jsp.core.internal.Logger;
+import org.osgi.service.prefs.BackingStoreException;
+import org.osgi.service.prefs.Preferences;
+
+/**
+ * Properties constants used by JSP Fragments. Clients should only read and
+ * modify the JSP Fragment properties programmatically using this class.
+ * 
+ * @since 1.1
+ */
+public class JSPFContentProperties {
+	static final String JSPCORE_ID = JSPCorePlugin.getDefault().getBundle().getSymbolicName();
+	private static final String PROJECT_KEY = "<project>"; //$NON-NLS-1$
+
+	/**
+	 * A named key that controls the default language for JSP Fragments
+	 * <p>
+	 * Value is of type <code>String</code>.
+	 * </p>
+	 * 
+	 * @since 1.1
+	 */
+	public static final String JSPLANGUAGE = "jsp-language"; //$NON-NLS-1$
+	/**
+	 * A named key that controls the default content type for JSP Fragments
+	 * <p>
+	 * Value is of type <code>String</code>.
+	 * </p>
+	 * 
+	 * @since 1.1
+	 */
+	public static final String JSPCONTENTTYPE = "jsp-content-type"; //$NON-NLS-1$
+	/**
+	 * Indicates if JSP fragments should be compiled/validated. JSP fragments
+	 * will be validated when true.
+	 * <p>
+	 * Value is of type <code>String</code>.
+	 * </p>
+	 * 
+	 * @since 1.1
+	 */
+	public static final String VALIDATE_FRAGMENTS = "validateFragments";//$NON-NLS-1$
+
+	/**
+	 * Generates a preference key based on resourcePath
+	 * 
+	 * @param resourcePath
+	 *            the path the key will be based off of
+	 * @return preference key based on resourcePath (basically the
+	 *         resourcePath without the filename); PROJECT_KEY if resourcePath
+	 *         is null
+	 */
+	static String getKeyFor(IPath resourcePath) {
+		String key = PROJECT_KEY;
+		if (resourcePath != null && resourcePath.segmentCount() > 1) {
+			key = resourcePath.removeFirstSegments(1).toString();
+		}
+		return key;
+	}
+
+	/**
+	 * Get the preferences node associated with the given project scope and
+	 * preference key (subNode) If create is true, the preference node will be
+	 * created if one does not already exist
+	 * 
+	 * @param project
+	 *            the project the preference node is under
+	 * @param preferenceKey
+	 *            the subnode/category the preference node is located in
+	 * @param create
+	 *            if true, a preference node will be created if one does not
+	 *            already exist
+	 * @return Preferences associated with the given project scope and
+	 *         preference key. null if one could not be found and create is
+	 *         false
+	 */
+	static Preferences getPreferences(IProject project, String preferenceKey, boolean create) {
+		if (create)
+			// create all nodes down to the one we are interested in
+			return new ProjectScope(project).getNode(JSPCORE_ID).node(preferenceKey);
+		// be careful looking up for our node so not to create any nodes as
+		// side effect
+		Preferences node = Platform.getPreferencesService().getRootNode().node(ProjectScope.SCOPE);
+		try {
+			// TODO once bug 90500 is fixed, should be as simple as this:
+			// String path = project.getName() + IPath.SEPARATOR +
+			// ResourcesPlugin.PI_RESOURCES + IPath.SEPARATOR +
+			// ENCODING_PREF_NODE;
+			// return node.nodeExists(path) ? node.node(path) : null;
+			// for now, take the long way
+			if (!node.nodeExists(project.getName()))
+				return null;
+			node = node.node(project.getName());
+			if (!node.nodeExists(JSPCORE_ID))
+				return null;
+			node = node.node(JSPCORE_ID);
+			if (!node.nodeExists(preferenceKey))
+				return null;
+			return node.node(preferenceKey);
+		}
+		catch (BackingStoreException e) {
+			// nodeExists failed
+			Logger.log(Logger.WARNING_DEBUG, "Could not retrieve preference node", e); //$NON-NLS-1$
+		}
+		return null;
+	}
+
+	/**
+	 * Returns the value for the given key in the given context.
+	 * 
+	 * @param key
+	 *            The property key
+	 * @param resource
+	 *            The current context or <code>null</code> if no context is
+	 *            available and the workspace setting should be taken. Note
+	 *            that passing <code>null</code> should be avoided.
+	 * @param recurse
+	 *            whether the parent should be queried till property is found
+	 * @return Returns the current value for the key.
+	 * @since 1.1
+	 */
+	public static String getProperty(String key, IResource resource, boolean recurse) {
+		String val = null;
+		if (resource != null) {
+			IProject project = resource.getProject();
+			if (project != null) {
+				Preferences preferences = getPreferences(project, key, false);
+				if (preferences != null) {
+					val = internalGetProperty(resource, recurse, preferences);
+				}
+			}
+		}
+		// no preferences found - for performance reasons,
+		// short-circuit
+		// lookup by falling back to workspace's default
+		// setting
+		if (val == null && recurse)
+			val = getWorkbenchPreference(key);
+		return val;
+	}
+
+	private static String getWorkbenchPreference(String key) {
+		return Platform.getPreferencesService().getString(JSPCORE_ID, key, null, null);
+	}
+
+	private static String internalGetProperty(IResource resource, boolean recurse, Preferences preferences) {
+		String value = preferences.get(getKeyFor(resource.getFullPath()), null);
+		if (value == null && resource != resource.getProject() && recurse) {
+			value = preferences.get(getKeyFor(null), null);
+		}
+
+		return value;
+	}
+
+	/**
+	 * Sets the value for the given key in the given context.
+	 * 
+	 * @param key
+	 *            The property key
+	 * @param resource
+	 *            The current context. Note context cannot be
+	 *            <code>null</code>.
+	 * @param value
+	 *            The value to set for the key. If value is <code>null</code>
+	 *            the key is removed from properties.
+	 * @since 1.1
+	 */
+	public static void setProperty(String key, IResource resource, String value) throws CoreException {
+		if (resource != null) {
+			IProject project = resource.getProject();
+			if (project != null) {
+				Preferences preferences = getPreferences(project, key, true);
+				if (value == null || value.trim().length() == 0)
+					preferences.remove(getKeyFor(resource.getFullPath()));
+				else
+					preferences.put(getKeyFor(resource.getFullPath()), value);
+				try {
+					// save changes
+					preferences.flush();
+				}
+				catch (BackingStoreException e) {
+					throw new CoreException(new Status(IStatus.ERROR, JSPCORE_ID, IStatus.ERROR, "Unable to set property", e)); //$NON-NLS-1$
+				}
+			}
+		}
+		// Workbench preference may not be needed so leave out for now
+		// just set a preference in the instance scope
+		// if (!preferenceFound) {
+		// setWorkbenchPreference(key);
+		// }
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentproperties/JSPFContentPropertiesManager.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentproperties/JSPFContentPropertiesManager.java
new file mode 100644
index 0000000..d3cd4cf
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentproperties/JSPFContentPropertiesManager.java
@@ -0,0 +1,245 @@
+/*******************************************************************************
+ * Copyright (c) 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.contentproperties;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResourceChangeEvent;
+import org.eclipse.core.resources.IResourceChangeListener;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.resources.IResourceStatus;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.MultiStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jst.jsp.core.internal.JSPCoreMessages;
+import org.eclipse.jst.jsp.core.internal.Logger;
+import org.eclipse.osgi.util.NLS;
+import org.osgi.framework.Bundle;
+import org.osgi.service.prefs.BackingStoreException;
+import org.osgi.service.prefs.Preferences;
+
+public class JSPFContentPropertiesManager {
+	public JSPFContentPropertiesManager() {
+		super();
+		fResourceChangeListener = new ResourceChangeListener();
+		fJob = new ContentPropertiesManagerJob();
+	}
+
+	private static JSPFContentPropertiesManager _instance = null;
+	private IResourceChangeListener fResourceChangeListener;
+	ContentPropertiesManagerJob fJob;
+
+	/**
+	 * This job implementation is used to allow the resource change listener
+	 * to schedule operations that need to modify the workspace.
+	 */
+	private class ContentPropertiesManagerJob extends Job {
+		private static final int PROPERTIES_UPDATE_DELAY = 500;
+		private List asyncChanges = new ArrayList();
+
+		public ContentPropertiesManagerJob() {
+			super(JSPCoreMessages.JSPFContentPropertiesManager_Updating);
+			setSystem(true);
+			setPriority(Job.INTERACTIVE);
+		}
+
+		public void addChanges(Set newChanges) {
+			if (newChanges.isEmpty())
+				return;
+			synchronized (asyncChanges) {
+				asyncChanges.addAll(newChanges);
+				asyncChanges.notify();
+			}
+			schedule(PROPERTIES_UPDATE_DELAY);
+		}
+
+		public IProject getNextChange() {
+			synchronized (asyncChanges) {
+				return asyncChanges.isEmpty() ? null : (IProject) asyncChanges.remove(asyncChanges.size() - 1);
+			}
+		}
+
+		protected IStatus run(IProgressMonitor monitor) {
+			MultiStatus result = new MultiStatus(JSPFContentProperties.JSPCORE_ID, IResourceStatus.FAILED_SETTING_CHARSET, JSPCoreMessages.JSPFContentPropertiesManager_Updating, null);
+			monitor = monitor == null ? new NullProgressMonitor() : monitor;
+			try {
+				monitor.beginTask(JSPCoreMessages.JSPFContentPropertiesManager_Updating, asyncChanges.size());
+				try {
+					IProject next;
+					while ((next = getNextChange()) != null) {
+						// just exit if the system is shutting down or has
+						// been shut down
+						// it is too late to change the workspace at this
+						// point anyway
+						if (Platform.getBundle("org.eclipse.osgi").getState() != Bundle.ACTIVE) //$NON-NLS-1$
+							return Status.OK_STATUS;
+						try {
+							// save the preferences nodes
+							if (next.isAccessible()) {
+								// save content type preferences
+								Preferences projectPrefs = JSPFContentProperties.getPreferences(next, JSPFContentProperties.JSPCONTENTTYPE, false);
+								if (projectPrefs != null)
+									projectPrefs.flush();
+								// save language preferences
+								projectPrefs = JSPFContentProperties.getPreferences(next, JSPFContentProperties.JSPLANGUAGE, false);
+								if (projectPrefs != null)
+									projectPrefs.flush();
+
+							}
+						}
+						catch (BackingStoreException e) {
+							// we got an error saving
+							String detailMessage = NLS.bind(JSPCoreMessages.JSPFContentPropertiesManager_Problems_Updating, next.getFullPath());
+							result.add(new Status(1 << (IResourceStatus.FAILED_SETTING_CHARSET % 100 / 33), ResourcesPlugin.PI_RESOURCES, IResourceStatus.FAILED_SETTING_CHARSET, detailMessage, e));
+						}
+					}
+					monitor.worked(1);
+				}
+				catch (OperationCanceledException e) {
+					throw e;
+				}
+			}
+			finally {
+				monitor.done();
+			}
+			return result;
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see org.eclipse.core.runtime.jobs.Job#shouldRun()
+		 */
+		public boolean shouldRun() {
+			synchronized (asyncChanges) {
+				return !asyncChanges.isEmpty();
+			}
+		}
+	}
+
+	class ResourceChangeListener implements IResourceChangeListener {
+		private void processEntryChanges(IResourceDelta projectDelta, Set projectsToSave) {
+			// check each resource with jsp fragment setting to see if it has
+			// been moved/deleted
+			boolean resourceChanges = false;
+			boolean resourceChanges2 = false;
+
+			// project affected
+			IProject currentProject = (IProject) projectDelta.getResource();
+
+			resourceChanges = processPreferences(currentProject, JSPFContentProperties.JSPCONTENTTYPE, projectDelta, projectsToSave);
+			resourceChanges2 = processPreferences(currentProject, JSPFContentProperties.JSPLANGUAGE, projectDelta, projectsToSave);
+
+			// if there was a preference key change, need to save preferences
+			if (resourceChanges || resourceChanges2)
+				projectsToSave.add(currentProject);
+		}
+
+		/**
+		 * Goes through all the resource-dependent preferences associated with
+		 * currentProject & key and updates the preference keys if needed
+		 * based on projectDelta
+		 * 
+		 * @param currentProject
+		 *            current project of the preferences to be looked at
+		 * @param key
+		 *            current key/subcategory of the preferences to be looked
+		 *            at
+		 * @param projectDelta
+		 *            the changes to process the preference keys against
+		 * @param projectsToSave
+		 *            the projects that need to be updated/saved
+		 * @return true if currentProject's preferences were modified
+		 */
+		private boolean processPreferences(IProject currentProject, String key, IResourceDelta projectDelta, Set projectsToSave) {
+			boolean resourceChanges = false;
+
+			// get the project-key preference node
+			Preferences projectPrefs = JSPFContentProperties.getPreferences(currentProject, key, false);
+			if (projectPrefs == null)
+				// no preferences for this project-key, just bail
+				return false;
+			String[] affectedResources;
+			try {
+				affectedResources = projectPrefs.keys();
+			}
+			catch (BackingStoreException e) {
+				// problems with the project scope... we gonna miss the
+				// changes (but will log)
+				Logger.log(Logger.WARNING_DEBUG, "Problem retreiving JSP Fragment preferences", e); //$NON-NLS-1$
+				return false;
+			}
+
+			// go through each preference key (which is really a file name)
+			for (int i = 0; i < affectedResources.length; i++) {
+				// see if preference key/file name was file that was changed
+				IResourceDelta memberDelta = projectDelta.findMember(new Path(affectedResources[i]));
+				// no changes for the given resource
+				if (memberDelta == null)
+					continue;
+				if (memberDelta.getKind() == IResourceDelta.REMOVED) {
+					resourceChanges = true;
+					// remove the setting for the original location
+					String currentValue = projectPrefs.get(affectedResources[i], null);
+					projectPrefs.remove(affectedResources[i]);
+					if ((memberDelta.getFlags() & IResourceDelta.MOVED_TO) != 0) {
+						// if moving, copy the setting for the new location
+						IProject targetProject = ResourcesPlugin.getWorkspace().getRoot().getProject(memberDelta.getMovedToPath().segment(0));
+						Preferences targetPrefs = JSPFContentProperties.getPreferences(targetProject, key, true);
+						targetPrefs.put(JSPFContentProperties.getKeyFor(memberDelta.getMovedToPath()), currentValue);
+						if (targetProject != currentProject)
+							projectsToSave.add(targetProject);
+					}
+				}
+			}
+			return resourceChanges;
+		}
+
+		/**
+		 * For any change to the encoding file or any resource with encoding
+		 * set, just discard the cache for the corresponding project.
+		 */
+		public void resourceChanged(IResourceChangeEvent event) {
+			IResourceDelta delta = event.getDelta();
+			if (delta == null)
+				return;
+			IResourceDelta[] projectDeltas = delta.getAffectedChildren();
+			// process each project in the delta
+			Set projectsToSave = new HashSet();
+			for (int i = 0; i < projectDeltas.length; i++)
+				// nothing to do if a project has been added/removed/moved
+				if (projectDeltas[i].getKind() == IResourceDelta.CHANGED && (projectDeltas[i].getFlags() & IResourceDelta.OPEN) == 0)
+					processEntryChanges(projectDeltas[i], projectsToSave);
+			fJob.addChanges(projectsToSave);
+		}
+	}
+
+	public synchronized static void startup() {
+		_instance = new JSPFContentPropertiesManager();
+		ResourcesPlugin.getWorkspace().addResourceChangeListener(_instance.fResourceChangeListener, IResourceChangeEvent.POST_CHANGE);
+	}
+
+	public synchronized static void shutdown() {
+		ResourcesPlugin.getWorkspace().removeResourceChangeListener(_instance.fResourceChangeListener);
+		_instance = null;
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contenttype/ByteReader.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contenttype/ByteReader.java
new file mode 100644
index 0000000..c91119e
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contenttype/ByteReader.java
@@ -0,0 +1,109 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.contenttype;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+
+import org.eclipse.wst.sse.core.internal.encoding.CodedIO;
+
+/**
+ * This is an "adapter" class, simply to get in input stream to act like a
+ * reader. We could not use InputStreamReader directly because its internal
+ * buffers are not controllable, and it sometimes pulls too much out of input
+ * stream (even when it wasn't needed for our purposes).
+ * 
+ * The use of this class is highly specialized and by not means meant to be
+ * general purpose. Its use is restricted to those cases where the input
+ * stream can be regarded as ascii just long enough to determine what the real
+ * encoding should be.
+ */
+
+public class ByteReader extends Reader {
+
+	
+	public static final int DEFAULT_BUFFER_SIZE = CodedIO.MAX_BUF_SIZE;
+
+	protected byte[] fBuffer;
+
+	protected InputStream fInputStream;
+
+	protected ByteReader() {
+		super();
+	}
+
+	public ByteReader(InputStream inputStream) {
+		this(inputStream, DEFAULT_BUFFER_SIZE);
+		if (!inputStream.markSupported()) {
+			throw new IllegalArgumentException("ByteReader is required to have a resettable stream"); //$NON-NLS-1$
+		}
+	}
+
+	public ByteReader(InputStream inputStream, int size) {
+		this.fInputStream = inputStream;
+		if (!inputStream.markSupported()) {
+			throw new IllegalArgumentException("ByteReader is required to have a resettable stream"); //$NON-NLS-1$
+		}
+		this.fBuffer = new byte[size];
+
+	}
+
+	public void close() throws IOException {
+		this.fInputStream.close();
+	}
+
+	public void mark(int readAheadLimit) {
+		this.fInputStream.mark(readAheadLimit);
+	}
+
+	public boolean markSupported() {
+		return true;
+	}
+
+	public int read() throws IOException {
+		int b0 = this.fInputStream.read();
+		return (b0 & 0x00FF);
+	}
+
+	public int read(char ch[], int offset, int length) throws IOException {
+		if (length > this.fBuffer.length) {
+			length = this.fBuffer.length;
+		}
+
+		int count = this.fInputStream.read(this.fBuffer, 0, length);
+
+		for (int i = 0; i < count; i++) {
+			int b0 = this.fBuffer[i];
+			// the 0x00FF is to "lose" the negative bits filled in the byte to
+			// int conversion
+			// (and which would be there if cast directly from byte to char).
+			char c0 = (char) (b0 & 0x00FF);
+			ch[offset + i] = c0;
+		}
+		return count;
+	}
+
+	public boolean ready() throws IOException {
+		return this.fInputStream.available() > 0;
+	}
+
+	public void reset() throws IOException {
+		this.fInputStream.reset();
+	}
+
+	public long skip(long n) throws IOException {
+		return this.fInputStream.skip(n);
+	}
+
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contenttype/ContentDescriberForJSP.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contenttype/ContentDescriberForJSP.java
new file mode 100644
index 0000000..47ec7b9
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contenttype/ContentDescriberForJSP.java
@@ -0,0 +1,253 @@
+/*******************************************************************************
+ * Copyright (c) 2004-2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.contenttype;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+
+import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.core.runtime.content.IContentDescriber;
+import org.eclipse.core.runtime.content.IContentDescription;
+import org.eclipse.core.runtime.content.ITextContentDescriber;
+import org.eclipse.jst.jsp.core.internal.provisional.contenttype.IContentDescriptionForJSP;
+import org.eclipse.wst.html.core.internal.provisional.contenttype.ContentTypeFamilyForHTML;
+import org.eclipse.wst.sse.core.internal.encoding.EncodingMemento;
+import org.eclipse.wst.sse.core.internal.encoding.IContentDescriptionExtended;
+import org.eclipse.wst.sse.core.internal.encoding.IResourceCharsetDetector;
+
+public final class ContentDescriberForJSP implements ITextContentDescriber {
+	private final static QualifiedName[] SUPPORTED_OPTIONS = {IContentDescription.CHARSET, IContentDescription.BYTE_ORDER_MARK, IContentDescriptionExtended.DETECTED_CHARSET, IContentDescriptionExtended.UNSUPPORTED_CHARSET, IContentDescriptionExtended.APPROPRIATE_DEFAULT, IContentDescriptionForJSP.CONTENT_TYPE_ATTRIBUTE, IContentDescriptionForJSP.LANGUAGE_ATTRIBUTE, IContentDescriptionForJSP.CONTENT_FAMILY_ATTRIBUTE};
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.core.runtime.content.IContentDescriber#describe(java.io.InputStream,
+	 *      org.eclipse.core.runtime.content.IContentDescription)
+	 */
+	public int describe(InputStream contents, IContentDescription description) throws IOException {
+		int result = IContentDescriber.INVALID;
+
+		// if discription is null, we are just being asked to
+		// assess contents validity
+		if (description != null) {
+			result = calculateSupportedOptions(contents, description);
+		}
+		else {
+			result = determineValidity(contents);
+		}
+
+		return result;
+	}
+
+	private int determineValidity(InputStream contents) {
+		// There's little to prove, via contents, that
+		// a file is JSP, so always return interminant, and
+		// let filetypes decide.
+		return IContentDescriber.INDETERMINATE;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.core.runtime.content.ITextContentDescriber#describe(java.io.Reader,
+	 *      org.eclipse.core.runtime.content.IContentDescription)
+	 */
+	public int describe(Reader contents, IContentDescription description) throws IOException {
+		int result = IContentDescriber.INVALID;
+
+		// if discription is null, we are just being asked to
+		// assess contents validity
+		if (description != null) {
+			result = calculateSupportedOptions(contents, description);
+		}
+		else {
+			result = determineValidity(contents);
+		}
+
+		return result;
+	}
+
+	private int determineValidity(Reader contents) {
+		// There's little to prove, via contents, that
+		// a file is JSP, so always return interminant, and
+		// let filetypes decide.
+		return IContentDescriber.INDETERMINATE;
+	}
+
+	public QualifiedName[] getSupportedOptions() {
+		return SUPPORTED_OPTIONS;
+	}
+
+	private int calculateSupportedOptions(InputStream contents, IContentDescription description) throws IOException {
+		int result = IContentDescriber.INDETERMINATE;
+		if (isRelevent(description)) {
+			IResourceCharsetDetector detector = getDetector();
+			detector.set(contents);
+			handleCalculations(description, detector);
+			result = IContentDescriber.VALID;
+		}
+		return result;
+	}
+
+	/**
+	 * @param contents
+	 * @param description
+	 * @throws IOException
+	 */
+	private int calculateSupportedOptions(Reader contents, IContentDescription description) throws IOException {
+		int result = IContentDescriber.INDETERMINATE;
+		if (isRelevent(description)) {
+			IResourceCharsetDetector detector = getDetector();
+			detector.set(contents);
+			handleCalculations(description, detector);
+			result = IContentDescriber.VALID;
+		}
+		return result;
+	}
+
+	private IResourceCharsetDetector getDetector() {
+		return new JSPResourceEncodingDetector();
+	}
+
+	private void handleCalculations(IContentDescription description, IResourceCharsetDetector detector) throws IOException {
+		// handle standard ones first, to be sure detector processes
+		handleStandardCalculations(description, detector);
+		// now do those specific for JSPs
+		// note: detector should always be of correct instance, but we'll
+		// check, for now.
+		if (detector instanceof JSPResourceEncodingDetector) {
+			JSPResourceEncodingDetector jspDetector = (JSPResourceEncodingDetector) detector;
+			String language = jspDetector.getLanguage();
+			if (language != null && language.length() > 0) {
+				description.setProperty(IContentDescriptionForJSP.LANGUAGE_ATTRIBUTE, language);
+			}
+			/*
+			 * content type is literally the content type that's in the page
+			 * directive
+			 */
+			String contentTypeAttribute = jspDetector.getContentType();
+			if (contentTypeAttribute != null && contentTypeAttribute.length() > 0) {
+				description.setProperty(IContentDescriptionForJSP.CONTENT_TYPE_ATTRIBUTE, contentTypeAttribute);
+			}
+			/*
+			 * content family is the general class of content, when its
+			 * different from what's defined by content type
+			 */
+			if (jspDetector.isXHTML() || jspDetector.isWML()) {
+				// ISSUE: long term this logic and value should be contributed by extension point
+				description.setProperty(IContentDescriptionForJSP.CONTENT_FAMILY_ATTRIBUTE, ContentTypeFamilyForHTML.HTML_FAMILY);
+			}
+
+
+		}
+	}
+
+	private void handleDetectedSpecialCase(IContentDescription description, Object detectedCharset, Object javaCharset) {
+		if (detectedCharset != null) {
+			// Once we detected a charset, we should set the property even
+			// though it's the same as javaCharset
+			// because there are clients that rely on this property to
+			// determine if the charset is actually detected in file or not.
+			description.setProperty(IContentDescriptionExtended.DETECTED_CHARSET, detectedCharset);
+		}
+	}
+
+	/**
+	 * @param description
+	 * @param detector
+	 * @throws IOException
+	 */
+	private void handleStandardCalculations(IContentDescription description, IResourceCharsetDetector detector) throws IOException {
+		// note: if we're asked for one, we set them all. I need to be sure if
+		// called
+		// mulitiple times (one for each, say) that we don't waste time
+		// processing same
+		// content again.
+		EncodingMemento encodingMemento = ((JSPResourceEncodingDetector) detector).getEncodingMemento();
+		// TODO: I need to verify to see if this BOM work is always done
+		// by text type.
+		Object detectedByteOrderMark = encodingMemento.getUnicodeBOM();
+		if (detectedByteOrderMark != null) {
+			Object existingByteOrderMark = description.getProperty(IContentDescription.BYTE_ORDER_MARK);
+			// not sure why would ever be different, so if is different, may
+			// need to "push" up into base.
+			if (!detectedByteOrderMark.equals(existingByteOrderMark))
+				description.setProperty(IContentDescription.BYTE_ORDER_MARK, detectedByteOrderMark);
+		}
+
+
+		if (!encodingMemento.isValid()) {
+			// note: after setting here, its the mere presence of
+			// IContentDescriptionExtended.UNSUPPORTED_CHARSET
+			// in the resource's description that can be used to determine if
+			// invalid
+			// in those cases, the "detected" property contains an
+			// "appropriate default" to use.
+			description.setProperty(IContentDescriptionExtended.UNSUPPORTED_CHARSET, encodingMemento.getInvalidEncoding());
+			description.setProperty(IContentDescriptionExtended.APPROPRIATE_DEFAULT, encodingMemento.getAppropriateDefault());
+		}
+
+		Object detectedCharset = encodingMemento.getDetectedCharsetName();
+		Object javaCharset = encodingMemento.getJavaCharsetName();
+
+		// we always include detected, if its different than java
+		handleDetectedSpecialCase(description, detectedCharset, javaCharset);
+
+		if (javaCharset != null) {
+			Object existingCharset = description.getProperty(IContentDescription.CHARSET);
+			if (javaCharset.equals(existingCharset)) {
+				handleDetectedSpecialCase(description, detectedCharset, javaCharset);
+			}
+			else {
+				// we may need to add what we found, but only need to add
+				// if different from the default.
+				Object defaultCharset = detector.getSpecDefaultEncoding();
+				if (defaultCharset != null) {
+					if (!defaultCharset.equals(javaCharset)) {
+						description.setProperty(IContentDescription.CHARSET, javaCharset);
+					}
+				}
+				else {
+					// assuming if there is no spec default, we always need to
+					// add, I'm assuming
+					description.setProperty(IContentDescription.CHARSET, javaCharset);
+				}
+			}
+		}
+
+	}
+
+	/**
+	 * @param description
+	 * @return
+	 */
+	private boolean isRelevent(IContentDescription description) {
+		boolean result = false;
+		if (description == null)
+			result = false;
+		else if (description.isRequested(IContentDescription.BYTE_ORDER_MARK))
+			result = true;
+		else if (description.isRequested(IContentDescription.CHARSET))
+			result = true;
+		else if (description.isRequested(IContentDescriptionExtended.APPROPRIATE_DEFAULT))
+			result = true;
+		else if (description.isRequested(IContentDescriptionExtended.DETECTED_CHARSET))
+			result = true;
+		else if (description.isRequested(IContentDescriptionExtended.UNSUPPORTED_CHARSET))
+			result = true;
+		else if (description.isRequested(IContentDescriptionForJSP.CONTENT_TYPE_ATTRIBUTE))
+			result = true;
+		else if (description.isRequested(IContentDescriptionForJSP.LANGUAGE_ATTRIBUTE))
+			result = true;
+		return result;
+	}
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contenttype/DeploymentDescriptorPropertyCache.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contenttype/DeploymentDescriptorPropertyCache.java
new file mode 100644
index 0000000..87b73c7
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contenttype/DeploymentDescriptorPropertyCache.java
@@ -0,0 +1,958 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.contenttype;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.StringReader;
+import java.lang.ref.Reference;
+import java.lang.ref.SoftReference;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.parsers.DocumentBuilder;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceChangeEvent;
+import org.eclipse.core.resources.IResourceChangeListener;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.resources.IResourceDeltaVisitor;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.SubProgressMonitor;
+import org.eclipse.jst.jsp.core.internal.Logger;
+import org.eclipse.jst.jsp.core.internal.util.CommonXML;
+import org.eclipse.jst.jsp.core.internal.util.FacetModuleCoreSupport;
+import org.eclipse.jst.jsp.core.internal.util.FileContentCache;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Element;
+import org.w3c.dom.EntityReference;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+/**
+ * A cache for property group information stored in web.xml files. Information
+ * is not persisted.
+ */
+public final class DeploymentDescriptorPropertyCache {
+	private static final PropertyGroup[] NO_PROPERTY_GROUPS = new PropertyGroup[0];
+
+	static class DeploymentDescriptor {
+		PropertyGroup[] groups;
+		long modificationStamp;
+		StringMatcher[] urlPatterns;
+		Float version = new Float(defaultWebAppVersion);
+	}
+
+	/**
+	 * Representation of the JSP 2.0 property-group definitions from a servlet
+	 * deployment descriptor.
+	 */
+	public static final class PropertyGroup {
+		static PropertyGroup createFrom(IPath path, Node propertyGroupNode, int groupNumber) {
+			PropertyGroup group = new PropertyGroup(path, groupNumber);
+			Node propertyGroupID = propertyGroupNode.getAttributes().getNamedItem(ID);
+			if (propertyGroupID != null) {
+				group.setId(propertyGroupID.getNodeValue());
+			}
+			Node node = propertyGroupNode.getFirstChild();
+			while (node != null) {
+				if (node.getNodeType() == Node.ELEMENT_NODE) {
+					String name = node.getLocalName();
+					if (name == null) {
+						name = node.getNodeName();
+					}
+					if (IS_XML.equals(name)) {
+						group.setIsXML(getContainedText(node));
+					}
+					else if (EL_IGNORED.equals(name)) {
+						group.setElignored(getContainedText(node));
+					}
+					else if (INCLUDE_CODA.equals(name)) {
+						group.addCoda(getContainedText(node));
+					}
+					else if (INCLUDE_PRELUDE.equals(name)) {
+						group.addPrelude(getContainedText(node));
+					}
+					else if (SCRIPTING_INVALID.equals(name)) {
+						group.setScriptingInvalid(getContainedText(node));
+					}
+					else if (PAGE_ENCODING.equals(name)) {
+						group.setPageEncoding(getContainedText(node));
+					}
+					else if (URL_PATTERN.equals(name)) {
+						group.setUrlPattern(getContainedText(node));
+					}
+				}
+
+				node = node.getNextSibling();
+			}
+
+			return group;
+		}
+
+		private boolean el_ignored;
+
+		private String id;
+
+		private IPath[] include_coda = new IPath[0];
+
+		private IPath[] include_prelude = new IPath[0];
+		private boolean is_xml;
+		private StringMatcher matcher;
+		private String page_encoding;
+		private boolean scripting_invalid;
+		String url_pattern;
+		private IPath webxmlPath;
+
+		int number;
+
+		private PropertyGroup(IPath path, int number) {
+			super();
+			this.webxmlPath = path;
+			this.number = number;
+		}
+
+		private void addCoda(String containedText) {
+			if (containedText.length() > 0) {
+				IPath[] codas = new IPath[include_coda.length + 1];
+				System.arraycopy(include_coda, 0, codas, 0, include_coda.length);
+				codas[include_coda.length] = webxmlPath.removeLastSegments(2).append(containedText);
+				include_coda = codas;
+			}
+		}
+
+		private void addPrelude(String containedText) {
+			if (containedText.length() > 0) {
+				IPath[] preludes = new IPath[include_prelude.length + 1];
+				System.arraycopy(include_prelude, 0, preludes, 0, include_prelude.length);
+				preludes[include_prelude.length] = webxmlPath.removeLastSegments(2).append(containedText);
+				include_prelude = preludes;
+			}
+		}
+
+		public String getId() {
+			return id;
+		}
+
+		public IPath[] getIncludeCoda() {
+			return include_coda;
+		}
+
+		public IPath[] getIncludePrelude() {
+			return include_prelude;
+		}
+
+		public String getPageEncoding() {
+			return page_encoding;
+		}
+
+		public String getUrlPattern() {
+			return url_pattern;
+		}
+
+		public boolean isELignored() {
+			return el_ignored;
+		}
+
+		public boolean isIsXML() {
+			return is_xml;
+		}
+
+		public boolean isScriptingInvalid() {
+			return scripting_invalid;
+		}
+
+		boolean matches(String pattern, boolean optimistic) {
+			if (matcher == null)
+				return optimistic;
+			return matcher.match(pattern);
+		}
+
+		private void setElignored(String el_ignored) {
+			this.el_ignored = Boolean.valueOf(el_ignored).booleanValue();
+		}
+
+		private void setId(String id) {
+			this.id = id;
+		}
+
+		private void setIsXML(String is_xml) {
+			this.is_xml = Boolean.valueOf(is_xml).booleanValue();
+		}
+
+		private void setPageEncoding(String page_encoding) {
+			this.page_encoding = page_encoding;
+		}
+
+		private void setScriptingInvalid(String scripting_invalid) {
+			this.scripting_invalid = Boolean.valueOf(scripting_invalid).booleanValue();
+		}
+
+		private void setUrlPattern(String url_pattern) {
+			this.url_pattern = url_pattern;
+			if (url_pattern != null && url_pattern.length() > 0) {
+				this.matcher = new StringMatcher(url_pattern);
+			}
+		}
+
+		public String toString() {
+			return number + ":" + url_pattern; //$NON-NLS-1$
+		}
+	}
+
+	static class ResourceChangeListener implements IResourceChangeListener {
+		public void resourceChanged(IResourceChangeEvent event) {
+			IResourceDelta delta = event.getDelta();
+			if (event.getType() != IResourceChangeEvent.POST_CHANGE)
+				return;
+			if (delta.getKind() == IResourceDelta.CHANGED && (delta.getFlags() == IResourceDelta.ENCODING || delta.getFlags() == IResourceDelta.MARKERS))
+				return;
+
+			IResourceDeltaVisitor visitor = new IResourceDeltaVisitor() {
+				public boolean visit(IResourceDelta delta) {
+					IResource resource = delta.getResource();
+					if (resource.getType() == IResource.FILE) {
+						if (delta.getKind() == IResourceDelta.CHANGED && (delta.getFlags() == IResourceDelta.ENCODING || delta.getFlags() == IResourceDelta.MARKERS))
+							return false;
+
+						IPath path = resource.getFullPath();
+						int segmentCount = path.segmentCount();
+						if (segmentCount > 1 && path.lastSegment().equals(WEB_XML) && path.segment(segmentCount - 2).equals(WEB_INF)) {
+							getInstance().deploymentDescriptorChanged(path);
+						}
+					}
+					else if (resource.getType() == IResource.PROJECT) {
+						String name = resource.getName();
+						if (_debugResolutionCache) {
+							System.out.println("Removing DeploymentDescriptorPropertyCache resolution cache for project " + name); //$NON-NLS-1$ 
+						}
+						synchronized (LOCK) {
+							getInstance().resolvedMap.remove(name);
+						}
+					}
+					return true;
+				}
+			};
+			try {
+				delta.accept(visitor);
+			}
+			catch (CoreException e) {
+				Logger.logException(e);
+			}
+		}
+	}
+
+	private static class ResourceErrorHandler implements ErrorHandler {
+		private boolean fDoLogExceptions = false;
+		private IPath fPath;
+
+		ResourceErrorHandler(boolean logExceptions) {
+			super();
+			fDoLogExceptions = logExceptions;
+		}
+
+		public void error(SAXParseException exception) throws SAXException {
+			if (fDoLogExceptions)
+				Logger.log(Logger.WARNING, "SAXParseException with " + fPath + " (error) while reading descriptor: " + exception.getMessage()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+		}
+
+		public void fatalError(SAXParseException exception) throws SAXException {
+			if (fDoLogExceptions)
+				Logger.log(Logger.WARNING, "SAXParseException with " + fPath + " (fatalError) while reading descriptor: " + exception.getMessage()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+		}
+
+		public void setPath(IPath path) {
+			fPath = path;
+		}
+
+		public void warning(SAXParseException exception) throws SAXException {
+			if (fDoLogExceptions)
+				Logger.log(Logger.WARNING, "SAXParseException with " + fPath + " (warning) while reading descriptor: " + exception.getMessage()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+		}
+	}
+
+	/**
+	 * Copied from org.eclipse.core.internal.propertytester.StringMatcher, but
+	 * should be replaced with a more accurate implementation of the rules in
+	 * Servlet spec SRV.11.2 and RFC 2396
+	 */
+	private static class StringMatcher {
+		private static final char SINGLE_WILD_CARD = '\u0000';
+
+		/**
+		 * Boundary value beyond which we don't need to search in the text
+		 */
+		private int bound = 0;
+
+		private boolean hasLeadingStar;
+
+		private boolean hasTrailingStar;
+
+		final String pattern;
+
+		private final int patternLength;
+
+		/**
+		 * The pattern split into segments separated by *
+		 */
+		private String segments[];
+
+		/**
+		 * StringMatcher constructor takes in a String object that is a simple
+		 * pattern which may contain '*' for 0 and many characters and '?' for
+		 * exactly one character.
+		 * 
+		 * Literal '*' and '?' characters must be escaped in the pattern e.g.,
+		 * "\*" means literal "*", etc.
+		 * 
+		 * Escaping any other character (including the escape character
+		 * itself), just results in that character in the pattern. e.g., "\a"
+		 * means "a" and "\\" means "\"
+		 * 
+		 * If invoking the StringMatcher with string literals in Java, don't
+		 * forget escape characters are represented by "\\".
+		 * 
+		 * @param pattern
+		 *            the pattern to match text against
+		 */
+		StringMatcher(String pattern) {
+			if (pattern == null)
+				throw new IllegalArgumentException();
+			this.pattern = pattern;
+			patternLength = pattern.length();
+			parseWildCards();
+		}
+
+		/**
+		 * @param text
+		 *            a simple regular expression that may only contain '?'(s)
+		 * @param start
+		 *            the starting index in the text for search, inclusive
+		 * @param end
+		 *            the stopping point of search, exclusive
+		 * @param p
+		 *            a simple regular expression that may contain '?'
+		 * @return the starting index in the text of the pattern , or -1 if
+		 *         not found
+		 */
+		private int findPosition(String text, int start, int end, String p) {
+			boolean hasWildCard = p.indexOf(SINGLE_WILD_CARD) >= 0;
+			int plen = p.length();
+			for (int i = start, max = end - plen; i <= max; ++i) {
+				if (hasWildCard) {
+					if (regExpRegionMatches(text, i, p, 0, plen))
+						return i;
+				}
+				else {
+					if (text.regionMatches(true, i, p, 0, plen))
+						return i;
+				}
+			}
+			return -1;
+		}
+
+		/**
+		 * Given the starting (inclusive) and the ending (exclusive) positions
+		 * in the <code>text</code>, determine if the given substring matches
+		 * with aPattern
+		 * 
+		 * @return true if the specified portion of the text matches the
+		 *         pattern
+		 * @param text
+		 *            a String object that contains the substring to match
+		 */
+		public boolean match(String text) {
+			if (text == null)
+				return false;
+			final int end = text.length();
+			final int segmentCount = segments.length;
+			if (segmentCount == 0 && (hasLeadingStar || hasTrailingStar)) // pattern
+				// contains
+				// only
+				// '*'(s)
+				return true;
+			if (end == 0)
+				return patternLength == 0;
+			if (patternLength == 0)
+				return false;
+			int currentTextPosition = 0;
+			if ((end - bound) < 0)
+				return false;
+			int segmentIndex = 0;
+			String current = segments[segmentIndex];
+
+			/* process first segment */
+			if (!hasLeadingStar) {
+				int currentLength = current.length();
+				if (!regExpRegionMatches(text, 0, current, 0, currentLength))
+					return false;
+				segmentIndex++;
+				currentTextPosition = currentTextPosition + currentLength;
+			}
+			if ((segmentCount == 1) && (!hasLeadingStar) && (!hasTrailingStar)) {
+				// only one segment to match, no wild cards specified
+				return currentTextPosition == end;
+			}
+			/* process middle segments */
+			while (segmentIndex < segmentCount) {
+				current = segments[segmentIndex];
+				int currentMatch = findPosition(text, currentTextPosition, end, current);
+				if (currentMatch < 0)
+					return false;
+				currentTextPosition = currentMatch + current.length();
+				segmentIndex++;
+			}
+
+			/* process final segment */
+			if (!hasTrailingStar && currentTextPosition != end) {
+				int currentLength = current.length();
+				return regExpRegionMatches(text, end - currentLength, current, 0, currentLength);
+			}
+			return segmentIndex == segmentCount;
+		}
+
+		/**
+		 * Parses the pattern into segments separated by wildcard '*'
+		 * characters.
+		 */
+		private void parseWildCards() {
+			if (pattern.startsWith("*"))//$NON-NLS-1$
+				hasLeadingStar = true;
+			if (pattern.endsWith("*")) {//$NON-NLS-1$
+				/* make sure it's not an escaped wildcard */
+				if (patternLength > 1 && pattern.charAt(patternLength - 2) != '\\') {
+					hasTrailingStar = true;
+				}
+			}
+
+			ArrayList temp = new ArrayList();
+
+			int pos = 0;
+			StringBuffer buf = new StringBuffer();
+			while (pos < patternLength) {
+				char c = pattern.charAt(pos++);
+				switch (c) {
+					case '\\' :
+						if (pos >= patternLength) {
+							buf.append(c);
+						}
+						else {
+							char next = pattern.charAt(pos++);
+							/* if it's an escape sequence */
+							if (next == '*' || next == '?' || next == '\\') {
+								buf.append(next);
+							}
+							else {
+								/*
+								 * not an escape sequence, just insert
+								 * literally
+								 */
+								buf.append(c);
+								buf.append(next);
+							}
+						}
+						break;
+					case '*' :
+						if (buf.length() > 0) {
+							/* new segment */
+							temp.add(buf.toString());
+							bound += buf.length();
+							buf.setLength(0);
+						}
+						break;
+					case '?' :
+						/*
+						 * append special character representing single match
+						 * wildcard
+						 */
+						buf.append(SINGLE_WILD_CARD);
+						break;
+					default :
+						buf.append(c);
+				}
+			}
+
+			/* add last buffer to segment list */
+			if (buf.length() > 0) {
+				temp.add(buf.toString());
+				bound += buf.length();
+			}
+			segments = (String[]) temp.toArray(new String[temp.size()]);
+		}
+
+		/**
+		 * 
+		 * @return boolean
+		 * @param text
+		 *            a String to match
+		 * @param tStart
+		 *            the starting index of match, inclusive
+		 * @param p
+		 *            a simple regular expression that may contain '?'
+		 * @param pStart
+		 *            The start position in the pattern
+		 * @param plen
+		 *            The length of the pattern
+		 */
+		private boolean regExpRegionMatches(String text, int tStart, String p, int pStart, int plen) {
+			while (plen-- > 0) {
+				char tchar = text.charAt(tStart++);
+				char pchar = p.charAt(pStart++);
+
+				// process wild cards, skipping single wild cards
+				if (pchar == SINGLE_WILD_CARD)
+					continue;
+				if (pchar == tchar)
+					continue;
+				if (Character.toUpperCase(tchar) == Character.toUpperCase(pchar))
+					continue;
+				// comparing after converting to upper case doesn't handle all
+				// cases;
+				// also compare after converting to lower case
+				if (Character.toLowerCase(tchar) == Character.toLowerCase(pchar))
+					continue;
+				return false;
+			}
+			return true;
+		}
+		
+		public String toString() {
+			return "StringMatcher: " + pattern; //$NON-NLS-1$
+		}
+	}
+
+	private static final DeploymentDescriptorPropertyCache _instance = new DeploymentDescriptorPropertyCache();
+	private static final boolean _debugResolutionCache = false;
+
+	private static final float defaultWebAppVersion = 3f;
+	static final String EL_IGNORED = "el-ignored"; //$NON-NLS-1$
+	static final String ID = "id"; //$NON-NLS-1$
+	static final String INCLUDE_CODA = "include-coda"; //$NON-NLS-1$
+	static final String INCLUDE_PRELUDE = "include-prelude"; //$NON-NLS-1$
+
+	static final String IS_XML = "is-xml"; //$NON-NLS-1$
+	private static String JSP_PROPERTY_GROUP = "jsp-property-group"; //$NON-NLS-1$
+	static final String PAGE_ENCODING = "page-encoding"; //$NON-NLS-1$
+
+	static final String SCRIPTING_INVALID = "scripting-invalid"; //$NON-NLS-1$
+	static final String URL_PATTERN = "url-pattern"; //$NON-NLS-1$
+	private static final String SERVLET_MAPPING = "servlet-mapping"; //$NON-NLS-1$
+	private static final String WEB_APP_ELEMENT_LOCAL_NAME = ":web-app"; //$NON-NLS-1$
+	private static final String WEB_APP_ELEMENT_NAME = "web-app"; //$NON-NLS-1$
+
+	private static final String WEB_APP_VERSION_NAME = "version"; //$NON-NLS-1$
+	private static final String WEB_INF = "WEB-INF"; //$NON-NLS-1$
+	private static final String WEB_XML = "web.xml"; //$NON-NLS-1$
+	// private static final String WEB_INF_WEB_XML = WEB_INF + IPath.SEPARATOR
+	// + WEB_XML;
+	private static final String SLASH_WEB_INF_WEB_XML = Path.ROOT.toString() + WEB_INF + IPath.SEPARATOR + WEB_XML;
+
+	static String getContainedText(Node parent) {
+		NodeList children = parent.getChildNodes();
+		if (children.getLength() == 1) {
+			return children.item(0).getNodeValue().trim();
+		}
+		StringBuffer s = new StringBuffer();
+		Node child = parent.getFirstChild();
+		while (child != null) {
+			if (child.getNodeType() == Node.ENTITY_REFERENCE_NODE) {
+				String reference = ((EntityReference) child).getNodeValue();
+				if (reference == null && child.getNodeName() != null) {
+					reference = "&" + child.getNodeName() + ";"; //$NON-NLS-1$ //$NON-NLS-2$
+				}
+				if (reference != null) {
+					s.append(reference.trim());
+				}
+			}
+			else {
+				s.append(child.getNodeValue().trim());
+			}
+			child = child.getNextSibling();
+		}
+		return s.toString().trim();
+	}
+
+	public static DeploymentDescriptorPropertyCache getInstance() {
+		return _instance;
+	}
+
+	/**
+	 * This method is not meant to be called by clients.
+	 */
+	public static void start() {
+		ResourcesPlugin.getWorkspace().addResourceChangeListener(getInstance().fResourceChangeListener, IResourceChangeEvent.POST_CHANGE);
+	}
+
+	/**
+	 * This method is not meant to be called by clients.
+	 */
+	public static void stop() {
+		ResourcesPlugin.getWorkspace().removeResourceChangeListener(getInstance().fResourceChangeListener);
+	}
+
+	private ResourceErrorHandler errorHandler;
+
+	private Map fDeploymentDescriptors = new Hashtable();
+
+	private IResourceChangeListener fResourceChangeListener = new ResourceChangeListener();
+
+	// for use when reading TLDs
+	private EntityResolver resolver;
+
+	Map resolvedMap = new HashMap();
+
+	final static Object LOCK = new Object();
+
+	private DeploymentDescriptorPropertyCache() {
+		super();
+	}
+
+	private void _parseDocument(IPath path, Float[] version, List groupList, List urlPatterns, SubProgressMonitor subMonitor, Document document) {
+		Element webapp = document.getDocumentElement();
+		if (webapp != null) {
+			if (webapp.getTagName().equals(WEB_APP_ELEMENT_NAME) || webapp.getNodeName().endsWith(WEB_APP_ELEMENT_LOCAL_NAME)) {
+				// this convention only started with 2.4?
+				if (webapp.hasAttribute(WEB_APP_VERSION_NAME)) {
+					String versionValue = webapp.getAttribute(WEB_APP_VERSION_NAME);
+					versionValue = versionValue.trim();
+					if (versionValue.length() > 0) {
+						try {
+							version[0] = Float.valueOf(versionValue);
+						}
+						catch (NumberFormatException e) {
+							// doesn't matter
+						}
+					}
+				}
+				if (version[0] == null) {
+					// try determining the version from the doctype reference
+					DocumentType doctype = document.getDoctype();
+					if (doctype != null) {
+						String systemId = doctype.getSystemId();
+						String publicId = doctype.getPublicId();
+						if ((systemId != null && systemId.endsWith("web-app_2_3.dtd")) || (publicId != null && publicId.indexOf("Web Application 2.3") > 0)) { //$NON-NLS-1$ //$NON-NLS-2$
+							version[0] = new Float(2.3);
+						}
+						else if ((systemId != null && systemId.endsWith("web-app_2_2.dtd")) || (publicId != null && publicId.indexOf("Web Application 2.2") > 0)) { //$NON-NLS-1$ //$NON-NLS-2$
+							version[0] = new Float(2.2);
+						}
+						else if ((systemId != null && systemId.endsWith("web-app_2_1.dtd")) || (publicId != null && publicId.indexOf("Web Application 2.1") > 0)) { //$NON-NLS-1$ //$NON-NLS-2$
+							version[0] = new Float(2.1);
+						}
+					}
+				}
+			}
+		}
+		NodeList propertyGroupElements = document.getElementsByTagName(JSP_PROPERTY_GROUP);
+		int length = propertyGroupElements.getLength();
+		subMonitor.beginTask("Reading Property Groups", length); //$NON-NLS-1$
+		for (int i = 0; i < length; i++) {
+			PropertyGroup group = PropertyGroup.createFrom(path, propertyGroupElements.item(i), i);
+			subMonitor.worked(1);
+			if (group != null) {
+				groupList.add(group);
+			}
+		}
+		
+		// 325554 : only apply to URL patterns for Servlet mappings
+		NodeList urlPatternElements = document.getElementsByTagName(URL_PATTERN);
+		int urlPatternElementCount = urlPatternElements.getLength();
+		for (int i = 0; i < urlPatternElementCount; i++) {
+			Node urlPatternElement = urlPatternElements.item(i);
+			if (SERVLET_MAPPING.equals(urlPatternElement.getParentNode().getNodeName())) {
+				String urlPattern = getContainedText(urlPatternElement);
+				if (urlPattern != null && urlPattern.length() > 0) {
+					urlPatterns.add(new StringMatcher(urlPattern));
+				}
+			}
+		}
+	}
+
+	/**
+	 * Convert the SRV spec version to the JSP spec version
+	 */
+	private float convertSpecVersions(float version) {
+		if (version > 0) {
+			if (version == 3f)
+				return 2.2f;
+			if (version == 2.5f)
+				return 2.1f;
+			else if (version == 2.4f)
+				return 2.0f;
+			else if (version == 2.3f)
+				return 1.2f;
+			else if (version == 2.2f)
+				return 1.1f;
+			else if (version == 2.1f)
+				return 1.0f;
+		}
+		return convertSpecVersions(defaultWebAppVersion);
+	}
+
+	void deploymentDescriptorChanged(final IPath fullPath) {
+		if (fDeploymentDescriptors.containsKey(fullPath.makeAbsolute())) {
+			updateCacheEntry(fullPath);
+		}
+	}
+
+	/**
+	 * parse the specified resource using Xerces, and if that fails, use the
+	 * SSE XML parser to find the property groups.
+	 */
+	private DeploymentDescriptor fetchDescriptor(IPath path, IProgressMonitor monitor) {
+		monitor.beginTask(Messages.DeploymentDescriptorPropertyCache_1, 3);
+		IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(path);
+
+		PropertyGroup groups[] = null;
+
+		IStructuredModel model = null;
+		List groupList = new ArrayList();
+		List urlPatterns = new ArrayList();
+		Float[] version = new Float[1];
+		SubProgressMonitor subMonitor = new SubProgressMonitor(monitor, 2);
+		DocumentBuilder builder = CommonXML.getDocumentBuilder(false);
+		builder.setEntityResolver(getEntityResolver());
+		builder.setErrorHandler(getErrorHandler(path));
+		try {
+			InputSource inputSource = new InputSource();
+			String s = FileContentCache.getInstance().getContents(path);
+			inputSource.setCharacterStream(new StringReader(s));
+			inputSource.setSystemId(path.toString());
+			Document document = builder.parse(inputSource);
+			_parseDocument(path, version, groupList, urlPatterns, subMonitor, document);
+		}
+		catch (SAXException e1) {
+			/* encountered a fatal parsing error, try our own parser */
+			try {
+				/**
+				 * Chiefly because the web.xml file itself is editable, use
+				 * SSE to get the DOM Document because it is more fault
+				 * tolerant.
+				 */
+				model = StructuredModelManager.getModelManager().getModelForRead(file);
+				monitor.worked(1);
+				if (model instanceof IDOMModel) {
+					IDOMDocument document = ((IDOMModel) model).getDocument();
+					_parseDocument(path, version, groupList, urlPatterns, subMonitor, document);
+				}
+			}
+			catch (Exception e) {
+				Logger.logException(e);
+			}
+			finally {
+				if (model != null) {
+					model.releaseFromRead();
+				}
+			}
+		}
+		catch (IOException e1) {
+			/* file is unreadable, create no property groups */
+		}
+		finally {
+			groups = (PropertyGroup[]) groupList.toArray(new PropertyGroup[groupList.size()]);
+			subMonitor.done();
+		}
+
+		if (groups == null) {
+			groups = NO_PROPERTY_GROUPS;
+		}
+
+		DeploymentDescriptor deploymentDescriptor = new DeploymentDescriptor();
+		deploymentDescriptor.modificationStamp = file.getModificationStamp();
+		deploymentDescriptor.groups = groups;
+		deploymentDescriptor.urlPatterns = ((StringMatcher[]) urlPatterns.toArray(new StringMatcher[urlPatterns.size()]));
+		deploymentDescriptor.version = version[0];
+		monitor.done();
+		fDeploymentDescriptors.put(path, new SoftReference(deploymentDescriptor));
+		return deploymentDescriptor;
+	}
+
+	private DeploymentDescriptor getCachedDescriptor(IPath jspFilePath) {
+		IPath webxmlPath = getWebXMLPath(jspFilePath);
+		if (webxmlPath == null)
+			return null;
+
+		IFile webxmlFile = ResourcesPlugin.getWorkspace().getRoot().getFile(webxmlPath);
+		if (!webxmlFile.isAccessible())
+			return null;
+
+		Reference descriptorHolder = (Reference) fDeploymentDescriptors.get(webxmlPath);
+		DeploymentDescriptor descriptor = null;
+
+		if (descriptorHolder == null || ((descriptor = (DeploymentDescriptor) descriptorHolder.get()) == null) || (descriptor.modificationStamp == IResource.NULL_STAMP) || (descriptor.modificationStamp != webxmlFile.getModificationStamp())) {
+			descriptor = fetchDescriptor(webxmlPath, new NullProgressMonitor());
+		}
+		return descriptor;
+	}
+
+	private EntityResolver getEntityResolver() {
+		if (resolver == null) {
+			resolver = new EntityResolver() {
+				public InputSource resolveEntity(String publicID, String systemID) throws SAXException, IOException {
+					InputSource result = new InputSource(new ByteArrayInputStream(new byte[0]));
+					result.setPublicId(publicID);
+					result.setSystemId(systemID != null ? systemID : "/_" + getClass().getName()); //$NON-NLS-1$
+					return result;
+				}
+			};
+		}
+		return resolver;
+	}
+
+	/**
+	 * Returns an ErrorHandler that will not stop the parser on reported
+	 * errors
+	 */
+	private ErrorHandler getErrorHandler(IPath path) {
+		if (errorHandler == null) {
+			errorHandler = new ResourceErrorHandler(false);
+		}
+		errorHandler.setPath(path);
+		return errorHandler;
+	}
+
+	/**
+	 * @param fullPath
+	 * @return the JSP version supported by the web application containing the
+	 *         path. A value stated within a web.xml file takes priority.
+	 */
+	public float getJSPVersion(IPath fullPath) {
+		float version = defaultWebAppVersion;
+		/* try applicable web.xml file first */
+		DeploymentDescriptor descriptor = getCachedDescriptor(fullPath);
+		if (descriptor != null && descriptor.version != null) {
+			version = descriptor.version.floatValue();
+			return convertSpecVersions(version);
+		}
+
+		/* check facet settings */
+		IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(fullPath.segment(0));
+		version = FacetModuleCoreSupport.getDynamicWebProjectVersion(project);
+
+		return convertSpecVersions(version);
+	}
+
+	/**
+	 * @param jspFilePath
+	 * @return PropertyGroups matching the file at the given path or an empty
+	 *         array if no web.xml file exists or no matching property group
+	 *         was defined. A returned PropertyGroup object should be
+	 *         considered short-lived and not saved for later use.
+	 */
+	public PropertyGroup[] getPropertyGroups(IPath jspFilePath) {
+		List matchingGroups = new ArrayList(1);
+		DeploymentDescriptor descriptor = getCachedDescriptor(jspFilePath);
+		if (descriptor == null)
+			return NO_PROPERTY_GROUPS;
+
+		for (int i = 0; i < descriptor.groups.length; i++) {
+			if (descriptor.groups[i].matches(FacetModuleCoreSupport.getRuntimePath(jspFilePath).toString(), false)) {
+				matchingGroups.add(descriptor.groups[i]);
+			}
+		}
+		if (matchingGroups.isEmpty()) {
+			for (int i = 0; i < descriptor.groups.length; i++) {
+				if (descriptor.groups[i].matches(FacetModuleCoreSupport.getRuntimePath(jspFilePath).toString(), true)) {
+					matchingGroups.add(descriptor.groups[i]);
+				}
+			}
+		}
+		return (PropertyGroup[]) matchingGroups.toArray(new PropertyGroup[matchingGroups.size()]);
+	}
+
+	/**
+	 * @param jspFilePath
+	 *            the path of the JSP file
+	 * @param reference
+	 *            a path reference to test for
+	 * @return a matching url-mapping value in the corresponding deployment
+	 *         descriptor for the given JSP file path, if a deployment
+	 *         descriptor could be found, null otherwise
+	 */
+	public String getURLMapping(IPath jspFilePath, String reference) {
+		DeploymentDescriptor descriptor = getCachedDescriptor(jspFilePath);
+		if (descriptor == null)
+			return null;
+		StringMatcher[] mappings = descriptor.urlPatterns;
+		for (int i = 0; i < mappings.length; i++) {
+			if (mappings[i].match(reference)) {
+				return mappings[i].pattern;
+			}
+		}
+		return null;
+	}
+	
+	private IPath getWebXMLPath(IPath fullPath) {
+		/*
+		 * It can take the better part of a full second to do this, so cache
+		 * the result.
+		 */
+		IPath resolved = null;
+		Map mapForProject = null;
+		synchronized (LOCK) {
+			mapForProject = (Map) resolvedMap.get(fullPath.segment(0));
+			if (mapForProject != null) {
+				resolved = (IPath) mapForProject.get(fullPath);
+			}
+			else {
+				mapForProject = new HashMap();
+				resolvedMap.put(fullPath.segment(0), mapForProject);
+			}
+		}
+		if (resolved != null) {
+			if (_debugResolutionCache) {
+				System.out.println("DeploymentDescriptorPropertyCache resolution cache hit for " + fullPath); //$NON-NLS-1$ 
+			}
+		}
+		else {
+			if (_debugResolutionCache) {
+				System.out.println("DeploymentDescriptorPropertyCache resolution cache miss for " + fullPath); //$NON-NLS-1$ 
+			}
+			resolved = FacetModuleCoreSupport.resolve(fullPath, SLASH_WEB_INF_WEB_XML);
+			mapForProject.put(fullPath, resolved);
+		}
+		return resolved;
+	}
+
+	public IFile getWebXML(IPath jspFilePath) {
+		IPath webxmlPath = getWebXMLPath(jspFilePath);
+		if (webxmlPath == null)
+			return null;
+
+		return ResourcesPlugin.getWorkspace().getRoot().getFile(webxmlPath);
+	}
+
+	private void updateCacheEntry(IPath fullPath) {
+		/* don't update right now; remove and wait for another query to update */
+		fDeploymentDescriptors.remove(fullPath);
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contenttype/HeadParserToken.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contenttype/HeadParserToken.java
new file mode 100644
index 0000000..9a58ad2
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contenttype/HeadParserToken.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.contenttype;
+
+public class HeadParserToken {
+	private int fStart;
+
+	private String fText;
+	private String fType;
+
+	protected HeadParserToken() {
+		super();
+	}
+
+	public HeadParserToken(String type, int start, String text) {
+		this();
+		fType = type;
+		fStart = start;
+		fText = text;
+
+	}
+
+	public String getText() {
+		return fText;
+	}
+
+	public String getType() {
+		return fType;
+	}
+
+	public String toString() {
+		return ("text: " + fText + " offset: " + fStart + " type: " + fType); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contenttype/IntStack.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contenttype/IntStack.java
new file mode 100644
index 0000000..89fdc13
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contenttype/IntStack.java
@@ -0,0 +1,114 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.contenttype;
+
+/*
+ * 
+ * A non-resizable class implementing the behavior of java.util.Stack, but
+ * directly for the <code> integer </code> primitive.
+ */
+import java.util.EmptyStackException;
+
+public class IntStack {
+	private int[] list = null;
+
+	private int size = 0;
+
+	public IntStack() {
+		this(100);
+	}
+
+	public IntStack(int maxdepth) {
+		super();
+		list = new int[maxdepth];
+		initialize();
+	}
+
+	public void clear() {
+		initialize();
+	}
+
+	public boolean empty() {
+		return size == 0;
+	}
+
+	public int get(int slot) {
+		return list[slot];
+	}
+
+	private void initialize() {
+		for (int i = 0; i < list.length; i++)
+			list[i] = -1;
+	}
+
+	/**
+	 * Returns the int at the top of the stack without removing it
+	 * 
+	 * @return int at the top of this stack.
+	 * @exception EmptyStackException
+	 *                when empty.
+	 */
+	public int peek() {
+		if (size == 0)
+			throw new EmptyStackException();
+		return list[size - 1];
+	}
+
+	/**
+	 * Removes and returns the int at the top of the stack
+	 * 
+	 * @return int at the top of this stack.
+	 * @exception EmptyStackException
+	 *                when empty.
+	 */
+	public int pop() {
+		int value = peek();
+		list[size - 1] = -1;
+		size--;
+		return value;
+	}
+
+	/**
+	 * Pushes an item onto the top of this stack.
+	 * 
+	 * @param newValue -
+	 *            the int to be pushed onto this stack.
+	 * @return the <code>newValue</code> argument.
+	 */
+	public int push(int newValue) {
+		if (size == list.length) {
+			throw new StackOverflowError();
+		}
+		list[size++] = newValue;
+		return newValue;
+	}
+
+	public int size() {
+		return size;
+	}
+	
+	/* (non-Javadoc)
+	 * @see java.lang.Object#toString()
+	 */
+	public String toString() {
+		StringBuffer s = new StringBuffer(getClass().getName() + ":" +size + " [");
+		for (int i = 0; i < size; i++) {
+			s.append(list[i]);
+			if(i < size - 1) {
+				s.append(", ");
+			}
+		}
+		s.append("]");
+		return s.toString();
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contenttype/JSPHeadTokenizer.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contenttype/JSPHeadTokenizer.java
new file mode 100644
index 0000000..176c532
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contenttype/JSPHeadTokenizer.java
@@ -0,0 +1,3924 @@
+/* The following code was generated by JFlex 1.4.2 on 7/28/08 9:29 AM */
+
+/*******************************************************************************
+ * Copyright (c) 2005, 2008 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
+ *******************************************************************************/
+/*nlsXXX*/
+package org.eclipse.jst.jsp.core.internal.contenttype;
+import java.io.IOException;
+import java.io.Reader;
+import java.util.Arrays;
+
+import org.eclipse.wst.xml.core.internal.contenttype.EncodingParserConstants;
+import org.eclipse.wst.xml.core.internal.contenttype.XMLHeadTokenizerConstants;
+
+
+/**
+ * This class is a scanner generated by 
+ * <a href="http://www.jflex.de/">JFlex</a> 1.4.2
+ * on 7/28/08 9:29 AM from the specification file
+ * <tt>D:/workspaces/wtp301/workspace/org.eclipse.jst.jsp.core/DevTimeSupport/HeadParsers/JSPHeadTokenizer.jFlex</tt>
+ */
+public class JSPHeadTokenizer {
+
+  /** This character denotes the end of file */
+  public static final int YYEOF = -1;
+
+  /** initial size of the lookahead buffer */
+  private static final int ZZ_BUFFERSIZE = 8192;
+
+  /** lexical states */
+  public static final int YYINITIAL = 0;
+  public static final int UnDelimitedString = 12;
+  public static final int DQ_STRING = 8;
+  public static final int SQ_STRING = 10;
+  public static final int ST_XMLDecl = 2;
+  public static final int ST_PAGE_DIRECTIVE = 4;
+  public static final int QuotedAttributeValue = 6;
+
+  /**
+   * ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l
+   * ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l
+   *                  at the beginning of a line
+   * l is of the form l = 2*k, k a non negative integer
+   */
+  private static final int ZZ_LEXSTATE[] = { 
+     0,  1,  2,  2,  3,  3,  4,  4,  5,  5,  6,  6,  7, 7
+  };
+
+  /** 
+   * Translates characters to character classes
+   */
+  private static final String ZZ_CMAP_PACKED = 
+    "\1\11\10\0\1\6\1\10\2\0\1\7\22\0\1\6\1\20\1\37"+
+    "\2\0\1\51\1\0\1\40\6\0\1\43\1\34\1\0\1\47\1\0"+
+    "\1\44\5\0\1\50\1\41\1\0\1\13\1\12\1\56\1\14\1\52"+
+    "\1\53\1\32\1\23\1\21\1\27\1\0\1\46\1\30\1\33\1\54"+
+    "\1\0\1\17\1\16\1\35\1\22\1\26\1\0\1\45\1\36\1\24"+
+    "\1\31\1\55\1\42\1\15\1\25\7\0\1\53\1\32\1\23\1\21"+
+    "\1\27\1\0\1\46\1\30\1\33\1\54\1\0\1\17\1\16\1\35"+
+    "\1\22\1\26\1\0\1\45\1\36\1\24\1\31\1\55\1\42\1\15"+
+    "\1\25\101\0\1\4\3\0\1\5\17\0\1\3\16\0\1\1\20\0"+
+    "\1\3\16\0\1\1\1\2\170\0\1\2\ufe87\0";
+
+  /** 
+   * Translates characters to character classes
+   */
+  private static final char [] ZZ_CMAP = zzUnpackCMap(ZZ_CMAP_PACKED);
+
+  /** 
+   * Translates DFA states to action switch labels.
+   */
+  private static final int [] ZZ_ACTION = zzUnpackAction();
+
+  private static final String ZZ_ACTION_PACKED_0 =
+    "\10\0\24\1\2\2\1\1\1\2\1\3\1\4\1\5"+
+    "\1\6\1\1\1\5\1\7\1\5\1\1\1\10\1\1"+
+    "\1\11\6\0\1\12\1\13\15\0\1\14\20\0\1\15"+
+    "\1\0\1\16\1\0\1\2\1\3\1\4\1\6\3\0"+
+    "\1\17\1\7\1\0\1\10\1\11\10\0\1\20\5\0"+
+    "\1\14\12\0\1\15\1\16\1\2\1\17\67\0\1\21"+
+    "\20\0\1\22\4\0\1\21\17\0\1\22\6\0\1\23"+
+    "\15\0\1\24\1\0\1\23\2\0\1\25\14\0\1\24"+
+    "\2\0\1\25\34\0\1\26\14\0\1\26\2\0\1\27"+
+    "\13\0\1\27\132\0\1\30\1\0\1\30\6\0\2\30"+
+    "\11\0\1\31\1\0\1\31\2\0\2\31\11\0";
+
+  private static int [] zzUnpackAction() {
+    int [] result = new int[446];
+    int offset = 0;
+    offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result);
+    return result;
+  }
+
+  private static int zzUnpackAction(String packed, int offset, int [] result) {
+    int i = 0;       /* index in packed string  */
+    int j = offset;  /* index in unpacked array */
+    int l = packed.length();
+    while (i < l) {
+      int count = packed.charAt(i++);
+      int value = packed.charAt(i++);
+      do result[j++] = value; while (--count > 0);
+    }
+    return j;
+  }
+
+
+  /* error codes */
+  private static final int ZZ_UNKNOWN_ERROR = 0;
+  private static final int ZZ_NO_MATCH = 1;
+  private static final int ZZ_PUSHBACK_2BIG = 2;
+
+  /* error messages for the codes above */
+  private static final String ZZ_ERROR_MSG[] = {
+    "Unkown internal scanner error",
+    "Error: could not match input",
+    "Error: pushback value was too large"
+  };
+
+  /** the input device */
+  private java.io.Reader zzReader;
+
+  /** the current state of the DFA */
+  private int zzState;
+
+  /** the current lexical state */
+  private int zzLexicalState = YYINITIAL;
+
+  /** this buffer contains the current text to be matched and is
+      the source of the yytext() string */
+  private char zzBuffer[] = new char[ZZ_BUFFERSIZE];
+
+  /** the textposition at the last accepting state */
+  private int zzMarkedPos;
+
+  /** the current text position in the buffer */
+  private int zzCurrentPos;
+
+  /** startRead marks the beginning of the yytext() string in the buffer */
+  private int zzStartRead;
+
+  /** endRead marks the last character in the buffer, that has been read
+      from input */
+  private int zzEndRead;
+
+  /** the number of characters up to the start of the matched text */
+  private int yychar;
+
+  /** 
+   * zzAtBOL == true <=> the scanner is currently at the beginning of a line
+   */
+  private boolean zzAtBOL = true;
+
+  /** zzAtEOF == true <=> the scanner is at the EOF */
+  private boolean zzAtEOF;
+
+  /** denotes if the user-EOF-code has already been executed */
+  private boolean zzEOFDone;
+
+  /* user code: */
+
+
+
+
+        private boolean hasMore = true;
+        private final static int MAX_TO_SCAN = 8000;
+        StringBuffer string = new StringBuffer();
+        // state stack for easier state handling
+        private IntStack fStateStack = new IntStack();
+        private String valueText = null;
+        private boolean isXHTML;
+        private boolean isWML;
+
+
+        public JSPHeadTokenizer() {
+                super();
+        }
+
+          public void reset (Reader in) {
+                /* the input device */
+                zzReader = in;
+
+                /* the current state of the DFA */
+                zzState = 0;
+
+                /* the current lexical state */
+                zzLexicalState = YYINITIAL;
+
+                /* this buffer contains the current text to be matched and is
+                 the source of the yytext() string */
+                Arrays.fill(zzBuffer, (char)0);
+
+                /* the textposition at the last accepting state */
+                zzMarkedPos = 0;
+
+                /* the textposition at the last state to be included in yytext */
+                //zzPushbackPos = 0;
+
+                /* the current text position in the buffer */
+                zzCurrentPos = 0;
+
+                /* startRead marks the beginning of the yytext() string in the buffer */
+                zzStartRead = 0;
+
+                /**
+                 * endRead marks the last character in the buffer, that has been read
+                 * from input
+                 */
+                zzEndRead = 0;
+
+                /* number of newlines encountered up to the start of the matched text */
+                //yyline = 0;
+
+                /* the number of characters up to the start of the matched text */
+                yychar = 0;
+
+                /**
+                 * the number of characters from the last newline up to the start
+                 * of the matched text
+                 */
+                //yycolumn = 0;
+
+                /**
+                 * yy_atBOL == true <=> the scanner is currently at the beginning
+                 * of a line
+                 */
+                zzAtBOL = true;
+
+                /* yy_atEOF == true <=> the scanner has returned a value for EOF */
+                zzAtEOF = false;
+
+                /* denotes if the user-EOF-code has already been executed */
+                zzEOFDone = false;
+
+
+                fStateStack.clear();
+
+                hasMore = true;
+                isXHTML=false;
+                isWML=false;
+
+
+        }
+
+
+        public final HeadParserToken getNextToken() throws IOException, Exception {
+                String context = null;
+                context = primGetNextToken();
+                HeadParserToken result = null;
+                if (valueText != null) {
+                        result = createToken(context, yychar, valueText);
+                        valueText = null;
+                } else {
+                        result = createToken(context, yychar, yytext());
+                }
+                return result;
+        }
+
+        public final boolean hasMoreTokens() {
+                return hasMore && yychar < MAX_TO_SCAN;
+        }
+        private void pushCurrentState() {
+                fStateStack.push(yystate());
+
+        }
+ 
+        private void popState() {
+                yybegin(fStateStack.pop());
+        }
+        private HeadParserToken createToken(String context, int start, String text) {
+                return new HeadParserToken(context, start, text);
+        }
+        
+        public boolean isXHTML() {
+            return isXHTML;
+        }
+        public boolean isWML() {
+            return isWML;
+        }        
+
+
+
+  /**
+   * Creates a new scanner
+   * There is also a java.io.InputStream version of this constructor.
+   *
+   * @param   in  the java.io.Reader to read input from.
+   */
+  public JSPHeadTokenizer(java.io.Reader in) {
+    this.zzReader = in;
+  }
+
+  /**
+   * Creates a new scanner.
+   * There is also java.io.Reader version of this constructor.
+   *
+   * @param   in  the java.io.Inputstream to read input from.
+   */
+  public JSPHeadTokenizer(java.io.InputStream in) {
+    this(new java.io.InputStreamReader(in));
+  }
+
+  /** 
+   * Unpacks the compressed character translation table.
+   *
+   * @param packed   the packed character translation table
+   * @return         the unpacked character translation table
+   */
+  private static char [] zzUnpackCMap(String packed) {
+    char [] map = new char[0x10000];
+    int i = 0;  /* index in packed string  */
+    int j = 0;  /* index in unpacked array */
+    while (i < 194) {
+      int  count = packed.charAt(i++);
+      char value = packed.charAt(i++);
+      do map[j++] = value; while (--count > 0);
+    }
+    return map;
+  }
+
+
+  /**
+   * Refills the input buffer.
+   *
+   * @return      <code>false</code>, iff there was new input.
+   * 
+   * @exception   java.io.IOException  if any I/O-Error occurs
+   */
+  private boolean zzRefill() throws java.io.IOException {
+
+    /* first: make room (if you can) */
+    if (zzStartRead > 0) {
+      System.arraycopy(zzBuffer, zzStartRead,
+                       zzBuffer, 0,
+                       zzEndRead-zzStartRead);
+
+      /* translate stored positions */
+      zzEndRead-= zzStartRead;
+      zzCurrentPos-= zzStartRead;
+      zzMarkedPos-= zzStartRead;
+      zzStartRead = 0;
+    }
+
+    /* is the buffer big enough? */
+    if (zzCurrentPos >= zzBuffer.length) {
+      /* if not: blow it up */
+      char newBuffer[] = new char[zzCurrentPos*2];
+      System.arraycopy(zzBuffer, 0, newBuffer, 0, zzBuffer.length);
+      zzBuffer = newBuffer;
+    }
+
+    /* finally: fill the buffer with new input */
+    int numRead = zzReader.read(zzBuffer, zzEndRead,
+                                            zzBuffer.length-zzEndRead);
+
+    if (numRead > 0) {
+      zzEndRead+= numRead;
+      return false;
+    }
+    // unlikely but not impossible: read 0 characters, but not at end of stream    
+    if (numRead == 0) {
+      int c = zzReader.read();
+      if (c == -1) {
+        return true;
+      } else {
+        zzBuffer[zzEndRead++] = (char) c;
+        return false;
+      }     
+    }
+
+	// numRead < 0
+    return true;
+  }
+
+    
+  /**
+   * Closes the input stream.
+   */
+  public final void yyclose() throws java.io.IOException {
+    zzAtEOF = true;            /* indicate end of file */
+    zzEndRead = zzStartRead;  /* invalidate buffer    */
+
+    if (zzReader != null)
+      zzReader.close();
+  }
+
+
+  /**
+   * Resets the scanner to read from a new input stream.
+   * Does not close the old reader.
+   *
+   * All internal variables are reset, the old input stream 
+   * <b>cannot</b> be reused (internal buffer is discarded and lost).
+   * Lexical state is set to <tt>ZZ_INITIAL</tt>.
+   *
+   * @param reader   the new input stream 
+   */
+  public final void yyreset(java.io.Reader reader) {
+    zzReader = reader;
+    zzAtBOL  = true;
+    zzAtEOF  = false;
+    zzEndRead = zzStartRead = 0;
+    zzCurrentPos = zzMarkedPos = 0;
+    yychar = 0;
+    zzLexicalState = YYINITIAL;
+  }
+
+
+  /**
+   * Returns the current lexical state.
+   */
+  public final int yystate() {
+    return zzLexicalState;
+  }
+
+
+  /**
+   * Enters a new lexical state
+   *
+   * @param newState the new lexical state
+   */
+  public final void yybegin(int newState) {
+    zzLexicalState = newState;
+  }
+
+
+  /**
+   * Returns the text matched by the current regular expression.
+   */
+  public final String yytext() {
+    return new String( zzBuffer, zzStartRead, zzMarkedPos-zzStartRead );
+  }
+
+
+  /**
+   * Returns the character at position <tt>pos</tt> from the 
+   * matched text. 
+   * 
+   * It is equivalent to yytext().charAt(pos), but faster
+   *
+   * @param pos the position of the character to fetch. 
+   *            A value from 0 to yylength()-1.
+   *
+   * @return the character at position pos
+   */
+  public final char yycharat(int pos) {
+    return zzBuffer[zzStartRead+pos];
+  }
+
+
+  /**
+   * Returns the length of the matched text region.
+   */
+  public final int yylength() {
+    return zzMarkedPos-zzStartRead;
+  }
+
+
+  /**
+   * Reports an error that occured while scanning.
+   *
+   * In a wellformed scanner (no or only correct usage of 
+   * yypushback(int) and a match-all fallback rule) this method 
+   * will only be called with things that "Can't Possibly Happen".
+   * If this method is called, something is seriously wrong
+   * (e.g. a JFlex bug producing a faulty scanner etc.).
+   *
+   * Usual syntax/scanner level error handling should be done
+   * in error fallback rules.
+   *
+   * @param   errorCode  the code of the errormessage to display
+   */
+  private void zzScanError(int errorCode) throws java.lang.Exception {
+    String message;
+    try {
+      message = ZZ_ERROR_MSG[errorCode];
+    }
+    catch (ArrayIndexOutOfBoundsException e) {
+      message = ZZ_ERROR_MSG[ZZ_UNKNOWN_ERROR];
+    }
+
+    throw new java.lang.Exception(message);
+  } 
+
+
+  /**
+   * Pushes the specified amount of characters back into the input stream.
+   *
+   * They will be read again by then next call of the scanning method
+   *
+   * @param number  the number of characters to be read again.
+   *                This number must not be greater than yylength()!
+   */
+  public void yypushback(int number)  throws java.lang.Exception {
+    if ( number > yylength() )
+      zzScanError(ZZ_PUSHBACK_2BIG);
+
+    zzMarkedPos -= number;
+  }
+
+
+  /**
+   * Contains user EOF-code, which will be executed exactly once,
+   * when the end of file is reached
+   */
+  private void zzDoEOF() {
+    if (!zzEOFDone) {
+      zzEOFDone = true;
+            hasMore=false;
+
+    }
+  }
+
+
+  /**
+   * Resumes scanning until the next regular expression is matched,
+   * the end of input is encountered or an I/O-Error occurs.
+   *
+   * @return      the next token
+   * @exception   java.io.IOException  if any I/O-Error occurs
+   */
+  public String primGetNextToken() throws java.io.IOException, java.lang.Exception {
+    int zzInput;
+    int zzAction;
+
+    // cached fields:
+    int zzCurrentPosL;
+    int zzMarkedPosL;
+    int zzEndReadL = zzEndRead;
+    char [] zzBufferL = zzBuffer;
+    char [] zzCMapL = ZZ_CMAP;
+
+
+    while (true) {
+      zzMarkedPosL = zzMarkedPos;
+
+      yychar+= zzMarkedPosL-zzStartRead;
+
+      if (zzMarkedPosL > zzStartRead) {
+        switch (zzBufferL[zzMarkedPosL-1]) {
+        case '\n':
+        case '\u000B':
+        case '\u000C':
+        case '\u0085':
+        case '\u2028':
+        case '\u2029':
+          zzAtBOL = true;
+          break;
+        case '\r': 
+          if (zzMarkedPosL < zzEndReadL)
+            zzAtBOL = zzBufferL[zzMarkedPosL] != '\n';
+          else if (zzAtEOF)
+            zzAtBOL = false;
+          else {
+            boolean eof = zzRefill();
+            zzMarkedPosL = zzMarkedPos;
+            zzEndReadL = zzEndRead;
+            zzBufferL = zzBuffer;
+            if (eof) 
+              zzAtBOL = false;
+            else 
+              zzAtBOL = zzBufferL[zzMarkedPosL] != '\n';
+          }
+          break;
+        default:
+          zzAtBOL = false;
+        }
+      }
+      zzAction = -1;
+
+      zzCurrentPosL = zzCurrentPos = zzStartRead = zzMarkedPosL;
+  
+      if (zzAtBOL)
+        zzState = ZZ_LEXSTATE[zzLexicalState+1];
+      else
+        zzState = ZZ_LEXSTATE[zzLexicalState];
+
+
+      zzForAction: {
+        while (true) {
+    
+          if (zzCurrentPosL < zzEndReadL)
+            zzInput = zzBufferL[zzCurrentPosL++];
+          else if (zzAtEOF) {
+            zzInput = YYEOF;
+            break zzForAction;
+          }
+          else {
+            // store back cached positions
+            zzCurrentPos  = zzCurrentPosL;
+            zzMarkedPos   = zzMarkedPosL;
+            boolean eof = zzRefill();
+            // get translated positions and possibly new buffer
+            zzCurrentPosL  = zzCurrentPos;
+            zzMarkedPosL   = zzMarkedPos;
+            zzBufferL      = zzBuffer;
+            zzEndReadL     = zzEndRead;
+            if (eof) {
+              zzInput = YYEOF;
+              break zzForAction;
+            }
+            else {
+              zzInput = zzBufferL[zzCurrentPosL++];
+            }
+          }
+          zzInput = zzCMapL[zzInput];
+
+          boolean zzIsFinal = false;
+          boolean zzNoLookAhead = false;
+
+          zzForNext: { switch (zzState) {
+            case 0:
+              switch (zzInput) {
+                case 9: zzIsFinal = true; zzState = 9; break zzForNext;
+                case 11: zzIsFinal = true; zzState = 10; break zzForNext;
+                default: zzIsFinal = true; zzNoLookAhead = true; zzState = 8; break zzForNext;
+              }
+
+            case 1:
+              switch (zzInput) {
+                case 1: zzIsFinal = true; zzState = 11; break zzForNext;
+                case 2: zzIsFinal = true; zzState = 12; break zzForNext;
+                case 3: zzIsFinal = true; zzState = 13; break zzForNext;
+                case 6: 
+                case 7: 
+                case 8: zzIsFinal = true; zzState = 14; break zzForNext;
+                case 9: zzIsFinal = true; zzState = 15; break zzForNext;
+                case 11: zzIsFinal = true; zzState = 16; break zzForNext;
+                default: zzIsFinal = true; zzNoLookAhead = true; zzState = 8; break zzForNext;
+              }
+
+            case 2:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzIsFinal = true; zzState = 17; break zzForNext;
+                case 9: zzIsFinal = true; zzState = 18; break zzForNext;
+                case 12: zzIsFinal = true; zzState = 19; break zzForNext;
+                case 23: zzIsFinal = true; zzState = 20; break zzForNext;
+                case 45: zzIsFinal = true; zzState = 21; break zzForNext;
+                default: zzIsFinal = true; zzNoLookAhead = true; zzState = 8; break zzForNext;
+              }
+
+            case 3:
+              switch (zzInput) {
+                case 9: zzIsFinal = true; zzState = 22; break zzForNext;
+                case 15: zzIsFinal = true; zzState = 23; break zzForNext;
+                case 19: zzIsFinal = true; zzState = 24; break zzForNext;
+                case 22: zzIsFinal = true; zzState = 25; break zzForNext;
+                case 28: zzIsFinal = true; zzState = 26; break zzForNext;
+                case 41: zzIsFinal = true; zzState = 27; break zzForNext;
+                default: zzIsFinal = true; zzNoLookAhead = true; zzState = 8; break zzForNext;
+              }
+
+            case 4:
+              switch (zzInput) {
+                case 6: 
+                case 7: zzIsFinal = true; zzState = 29; break zzForNext;
+                case 8: zzIsFinal = true; zzState = 30; break zzForNext;
+                case 9: zzIsFinal = true; zzState = 31; break zzForNext;
+                case 31: zzIsFinal = true; zzState = 32; break zzForNext;
+                case 32: zzIsFinal = true; zzState = 33; break zzForNext;
+                default: zzIsFinal = true; zzNoLookAhead = true; zzState = 28; break zzForNext;
+              }
+
+            case 5:
+              switch (zzInput) {
+                case 7: 
+                case 8: 
+                case 11: zzIsFinal = true; zzState = 35; break zzForNext;
+                case 9: zzIsFinal = true; zzState = 36; break zzForNext;
+                case 12: zzIsFinal = true; zzState = 37; break zzForNext;
+                case 31: zzIsFinal = true; zzState = 38; break zzForNext;
+                case 41: zzIsFinal = true; zzState = 39; break zzForNext;
+                default: zzIsFinal = true; zzNoLookAhead = true; zzState = 34; break zzForNext;
+              }
+
+            case 6:
+              switch (zzInput) {
+                case 7: 
+                case 8: 
+                case 11: zzIsFinal = true; zzState = 35; break zzForNext;
+                case 32: zzIsFinal = true; zzState = 38; break zzForNext;
+                case 41: zzIsFinal = true; zzState = 39; break zzForNext;
+                case 9: zzIsFinal = true; zzState = 40; break zzForNext;
+                default: zzIsFinal = true; zzNoLookAhead = true; zzState = 34; break zzForNext;
+              }
+
+            case 7:
+              switch (zzInput) {
+                case 11: zzIsFinal = true; zzState = 35; break zzForNext;
+                case 12: 
+                case 41: zzIsFinal = true; zzState = 39; break zzForNext;
+                case 6: 
+                case 7: 
+                case 8: zzIsFinal = true; zzState = 41; break zzForNext;
+                case 9: zzIsFinal = true; zzState = 42; break zzForNext;
+                case 31: 
+                case 32: zzIsFinal = true; zzState = 43; break zzForNext;
+                default: zzIsFinal = true; zzNoLookAhead = true; zzState = 34; break zzForNext;
+              }
+
+            case 9:
+              switch (zzInput) {
+                case 11: zzState = 44; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 10:
+              switch (zzInput) {
+                case 9: zzState = 45; break zzForNext;
+                case 16: zzState = 46; break zzForNext;
+                case 24: zzState = 47; break zzForNext;
+                case 41: zzState = 48; break zzForNext;
+                case 44: zzState = 49; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 11:
+              switch (zzInput) {
+                case 2: zzIsFinal = true; zzNoLookAhead = true; zzState = 50; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 12:
+              switch (zzInput) {
+                case 1: zzIsFinal = true; zzNoLookAhead = true; zzState = 51; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 13:
+              switch (zzInput) {
+                case 4: zzState = 52; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 14:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzState = 53; break zzForNext;
+                case 9: zzState = 54; break zzForNext;
+                case 11: zzState = 55; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 15:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzState = 53; break zzForNext;
+                case 11: zzState = 56; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 16:
+              switch (zzInput) {
+                case 16: zzState = 46; break zzForNext;
+                case 24: zzState = 47; break zzForNext;
+                case 41: zzState = 48; break zzForNext;
+                case 44: zzState = 49; break zzForNext;
+                case 9: zzState = 57; break zzForNext;
+                case 12: zzState = 58; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 17:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzState = 59; break zzForNext;
+                case 9: zzState = 60; break zzForNext;
+                case 12: zzState = 61; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 18:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzState = 59; break zzForNext;
+                case 12: zzState = 61; break zzForNext;
+                case 23: zzState = 62; break zzForNext;
+                case 45: zzState = 63; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 19:
+              switch (zzInput) {
+                case 9: zzState = 64; break zzForNext;
+                case 46: zzIsFinal = true; zzState = 65; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 20:
+              switch (zzInput) {
+                case 9: zzState = 66; break zzForNext;
+                case 29: zzState = 67; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 21:
+              switch (zzInput) {
+                case 9: zzState = 68; break zzForNext;
+                case 23: zzState = 69; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 22:
+              switch (zzInput) {
+                case 15: zzState = 70; break zzForNext;
+                case 19: zzState = 71; break zzForNext;
+                case 22: zzState = 72; break zzForNext;
+                case 28: zzState = 73; break zzForNext;
+                case 41: zzState = 74; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 23:
+              switch (zzInput) {
+                case 9: zzState = 75; break zzForNext;
+                case 43: zzState = 76; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 24:
+              switch (zzInput) {
+                case 9: zzState = 77; break zzForNext;
+                case 18: zzState = 78; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 25:
+              switch (zzInput) {
+                case 9: zzState = 79; break zzForNext;
+                case 43: zzState = 80; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 26:
+              switch (zzInput) {
+                case 9: zzState = 81; break zzForNext;
+                case 46: zzIsFinal = true; zzState = 82; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 27:
+              switch (zzInput) {
+                case 9: zzState = 83; break zzForNext;
+                case 46: zzIsFinal = true; zzState = 84; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 29:
+              switch (zzInput) {
+                case 6: 
+                case 7: zzIsFinal = true; break zzForNext;
+                case 8: zzState = 85; break zzForNext;
+                case 9: zzIsFinal = true; zzState = 86; break zzForNext;
+                default: zzIsFinal = true; zzNoLookAhead = true; zzState = 28; break zzForNext;
+              }
+
+            case 30:
+              switch (zzInput) {
+                case 6: 
+                case 7: zzIsFinal = true; zzState = 29; break zzForNext;
+                case 8: zzState = 85; break zzForNext;
+                case 9: zzIsFinal = true; zzState = 86; break zzForNext;
+                default: zzIsFinal = true; zzNoLookAhead = true; zzState = 28; break zzForNext;
+              }
+
+            case 31:
+              switch (zzInput) {
+                case 31: zzIsFinal = true; zzState = 32; break zzForNext;
+                case 32: zzIsFinal = true; zzState = 33; break zzForNext;
+                case 6: 
+                case 7: 
+                case 8: zzState = 85; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 32:
+              switch (zzInput) {
+                case 9: zzIsFinal = true; zzNoLookAhead = true; zzState = 87; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 33:
+              switch (zzInput) {
+                case 9: zzIsFinal = true; zzNoLookAhead = true; zzState = 88; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 35:
+              switch (zzInput) {
+                case 9: zzIsFinal = true; zzNoLookAhead = true; zzState = 89; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 36:
+              switch (zzInput) {
+                case 7: 
+                case 8: 
+                case 11: zzIsFinal = true; zzState = 35; break zzForNext;
+                case 31: zzIsFinal = true; zzState = 38; break zzForNext;
+                case 12: zzState = 90; break zzForNext;
+                case 41: zzState = 91; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 37:
+              switch (zzInput) {
+                case 9: zzState = 92; break zzForNext;
+                case 46: zzIsFinal = true; zzState = 93; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 38:
+              switch (zzInput) {
+                case 9: zzIsFinal = true; zzNoLookAhead = true; zzState = 94; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 39:
+              switch (zzInput) {
+                case 46: zzIsFinal = true; zzState = 35; break zzForNext;
+                case 9: zzState = 95; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 40:
+              switch (zzInput) {
+                case 7: 
+                case 8: 
+                case 11: zzIsFinal = true; zzState = 35; break zzForNext;
+                case 32: zzIsFinal = true; zzState = 38; break zzForNext;
+                case 41: zzState = 91; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 41:
+              switch (zzInput) {
+                case 9: zzIsFinal = true; zzNoLookAhead = true; zzState = 96; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 42:
+              switch (zzInput) {
+                case 11: zzIsFinal = true; zzState = 35; break zzForNext;
+                case 6: 
+                case 7: 
+                case 8: zzIsFinal = true; zzState = 41; break zzForNext;
+                case 31: 
+                case 32: zzIsFinal = true; zzState = 43; break zzForNext;
+                case 12: 
+                case 41: zzState = 91; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 43:
+              switch (zzInput) {
+                case 9: zzIsFinal = true; zzNoLookAhead = true; zzState = 97; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 44:
+              switch (zzInput) {
+                case 9: zzState = 45; break zzForNext;
+                case 16: zzState = 46; break zzForNext;
+                case 24: zzState = 47; break zzForNext;
+                case 41: zzState = 48; break zzForNext;
+                case 44: zzState = 49; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 45:
+              switch (zzInput) {
+                case 16: zzState = 46; break zzForNext;
+                case 24: zzState = 47; break zzForNext;
+                case 41: zzState = 48; break zzForNext;
+                case 44: zzState = 49; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 46:
+              switch (zzInput) {
+                case 9: zzState = 98; break zzForNext;
+                case 17: zzState = 99; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 47:
+              switch (zzInput) {
+                case 9: zzState = 100; break zzForNext;
+                case 20: zzState = 101; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 48:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: break zzForNext;
+                case 9: zzState = 102; break zzForNext;
+                case 42: zzState = 103; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 49:
+              switch (zzInput) {
+                case 9: zzState = 104; break zzForNext;
+                case 30: zzState = 105; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 52:
+              switch (zzInput) {
+                case 5: zzIsFinal = true; zzNoLookAhead = true; zzState = 106; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 53:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: break zzForNext;
+                case 9: zzState = 54; break zzForNext;
+                case 11: zzState = 55; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 54:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzState = 53; break zzForNext;
+                case 11: zzState = 55; break zzForNext;
+                case 9: zzState = 107; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 55:
+              switch (zzInput) {
+                case 12: zzState = 58; break zzForNext;
+                case 9: zzState = 108; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 56:
+              switch (zzInput) {
+                case 16: zzState = 46; break zzForNext;
+                case 24: zzState = 47; break zzForNext;
+                case 41: zzState = 48; break zzForNext;
+                case 44: zzState = 49; break zzForNext;
+                case 9: zzState = 57; break zzForNext;
+                case 12: zzState = 58; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 57:
+              switch (zzInput) {
+                case 16: zzState = 46; break zzForNext;
+                case 24: zzState = 47; break zzForNext;
+                case 41: zzState = 48; break zzForNext;
+                case 44: zzState = 49; break zzForNext;
+                case 12: zzState = 58; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 58:
+              switch (zzInput) {
+                case 9: zzState = 109; break zzForNext;
+                case 13: zzState = 110; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 59:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: break zzForNext;
+                case 9: zzState = 60; break zzForNext;
+                case 12: zzState = 61; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 60:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzState = 59; break zzForNext;
+                case 12: zzState = 61; break zzForNext;
+                case 9: zzState = 111; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 61:
+              switch (zzInput) {
+                case 9: zzState = 64; break zzForNext;
+                case 46: zzIsFinal = true; zzState = 65; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 62:
+              switch (zzInput) {
+                case 9: zzState = 66; break zzForNext;
+                case 29: zzState = 67; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 63:
+              switch (zzInput) {
+                case 9: zzState = 68; break zzForNext;
+                case 23: zzState = 69; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 64:
+              switch (zzInput) {
+                case 46: zzIsFinal = true; zzState = 65; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 65:
+              switch (zzInput) {
+                case 9: zzIsFinal = true; zzNoLookAhead = true; zzState = 112; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 66:
+              switch (zzInput) {
+                case 29: zzState = 67; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 67:
+              switch (zzInput) {
+                case 9: zzState = 113; break zzForNext;
+                case 19: zzState = 114; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 68:
+              switch (zzInput) {
+                case 23: zzState = 69; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 69:
+              switch (zzInput) {
+                case 9: zzState = 115; break zzForNext;
+                case 37: zzState = 116; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 70:
+              switch (zzInput) {
+                case 9: zzState = 75; break zzForNext;
+                case 43: zzState = 76; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 71:
+              switch (zzInput) {
+                case 9: zzState = 77; break zzForNext;
+                case 18: zzState = 78; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 72:
+              switch (zzInput) {
+                case 9: zzState = 79; break zzForNext;
+                case 43: zzState = 80; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 73:
+              switch (zzInput) {
+                case 9: zzState = 81; break zzForNext;
+                case 46: zzIsFinal = true; zzState = 82; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 74:
+              switch (zzInput) {
+                case 9: zzState = 83; break zzForNext;
+                case 46: zzIsFinal = true; zzState = 84; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 75:
+              switch (zzInput) {
+                case 43: zzState = 76; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 76:
+              switch (zzInput) {
+                case 9: zzState = 117; break zzForNext;
+                case 29: zzState = 118; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 77:
+              switch (zzInput) {
+                case 18: zzState = 78; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 78:
+              switch (zzInput) {
+                case 9: zzState = 119; break zzForNext;
+                case 29: zzState = 120; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 79:
+              switch (zzInput) {
+                case 43: zzState = 80; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 80:
+              switch (zzInput) {
+                case 9: zzState = 121; break zzForNext;
+                case 38: zzState = 122; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 81:
+              switch (zzInput) {
+                case 46: zzIsFinal = true; zzState = 82; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 82:
+              switch (zzInput) {
+                case 9: zzIsFinal = true; zzNoLookAhead = true; zzState = 123; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 83:
+              switch (zzInput) {
+                case 46: zzIsFinal = true; zzState = 84; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 84:
+              switch (zzInput) {
+                case 9: zzIsFinal = true; zzNoLookAhead = true; zzState = 124; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 85:
+              switch (zzInput) {
+                case 6: 
+                case 7: zzIsFinal = true; zzState = 29; break zzForNext;
+                case 8: break zzForNext;
+                case 9: zzIsFinal = true; zzState = 86; break zzForNext;
+                default: zzIsFinal = true; zzNoLookAhead = true; zzState = 28; break zzForNext;
+              }
+
+            case 86:
+              switch (zzInput) {
+                case 6: 
+                case 7: zzIsFinal = true; zzState = 29; break zzForNext;
+                case 8: zzState = 85; break zzForNext;
+                case 9: zzIsFinal = true; zzState = 125; break zzForNext;
+                default: zzIsFinal = true; zzNoLookAhead = true; zzState = 28; break zzForNext;
+              }
+
+            case 90:
+              switch (zzInput) {
+                case 9: zzState = 92; break zzForNext;
+                case 46: zzIsFinal = true; zzState = 93; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 91:
+              switch (zzInput) {
+                case 46: zzIsFinal = true; zzState = 35; break zzForNext;
+                case 9: zzState = 95; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 92:
+              switch (zzInput) {
+                case 46: zzIsFinal = true; zzState = 93; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 93:
+              switch (zzInput) {
+                case 9: zzIsFinal = true; zzNoLookAhead = true; zzState = 126; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 95:
+              switch (zzInput) {
+                case 46: zzIsFinal = true; zzState = 35; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 98:
+              switch (zzInput) {
+                case 17: zzState = 99; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 99:
+              switch (zzInput) {
+                case 9: zzState = 127; break zzForNext;
+                case 18: zzState = 128; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 100:
+              switch (zzInput) {
+                case 20: zzState = 101; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 101:
+              switch (zzInput) {
+                case 9: zzState = 129; break zzForNext;
+                case 14: zzState = 130; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 102:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzState = 48; break zzForNext;
+                case 42: zzState = 103; break zzForNext;
+                case 9: zzState = 131; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 103:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: break zzForNext;
+                case 9: zzState = 132; break zzForNext;
+                case 20: zzState = 133; break zzForNext;
+                case 22: zzState = 134; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 104:
+              switch (zzInput) {
+                case 30: zzState = 105; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 105:
+              switch (zzInput) {
+                case 9: zzState = 135; break zzForNext;
+                case 22: zzState = 136; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 107:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzState = 53; break zzForNext;
+                case 11: zzState = 55; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 108:
+              switch (zzInput) {
+                case 12: zzState = 58; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 109:
+              switch (zzInput) {
+                case 13: zzState = 110; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 110:
+              switch (zzInput) {
+                case 9: zzState = 137; break zzForNext;
+                case 14: zzState = 138; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 111:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzState = 59; break zzForNext;
+                case 12: zzState = 61; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 113:
+              switch (zzInput) {
+                case 19: zzState = 114; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 114:
+              switch (zzInput) {
+                case 9: zzState = 139; break zzForNext;
+                case 18: zzState = 140; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 115:
+              switch (zzInput) {
+                case 37: zzState = 116; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 116:
+              switch (zzInput) {
+                case 9: zzState = 141; break zzForNext;
+                case 30: zzState = 142; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 117:
+              switch (zzInput) {
+                case 29: zzState = 118; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 118:
+              switch (zzInput) {
+                case 9: zzState = 143; break zzForNext;
+                case 38: zzState = 144; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 119:
+              switch (zzInput) {
+                case 29: zzState = 120; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 120:
+              switch (zzInput) {
+                case 9: zzState = 145; break zzForNext;
+                case 20: zzState = 146; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 121:
+              switch (zzInput) {
+                case 38: zzState = 122; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 122:
+              switch (zzInput) {
+                case 9: zzState = 147; break zzForNext;
+                case 23: zzState = 148; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 125:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzState = 85; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 127:
+              switch (zzInput) {
+                case 18: zzState = 128; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 128:
+              switch (zzInput) {
+                case 9: zzState = 149; break zzForNext;
+                case 19: zzState = 150; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 129:
+              switch (zzInput) {
+                case 14: zzState = 130; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 130:
+              switch (zzInput) {
+                case 9: zzState = 151; break zzForNext;
+                case 15: zzState = 152; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 131:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzState = 48; break zzForNext;
+                case 42: zzState = 103; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 132:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzState = 103; break zzForNext;
+                case 20: zzState = 133; break zzForNext;
+                case 22: zzState = 134; break zzForNext;
+                case 9: zzState = 153; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 133:
+              switch (zzInput) {
+                case 9: zzState = 154; break zzForNext;
+                case 43: zzState = 155; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 134:
+              switch (zzInput) {
+                case 9: zzState = 156; break zzForNext;
+                case 43: zzState = 157; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 135:
+              switch (zzInput) {
+                case 22: zzState = 136; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 136:
+              switch (zzInput) {
+                case 9: zzState = 158; break zzForNext;
+                case 33: zzState = 159; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 137:
+              switch (zzInput) {
+                case 14: zzState = 138; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 138:
+              switch (zzInput) {
+                case 9: zzState = 160; break zzForNext;
+                case 15: zzState = 161; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 139:
+              switch (zzInput) {
+                case 18: zzState = 140; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 140:
+              switch (zzInput) {
+                case 9: zzState = 162; break zzForNext;
+                case 17: zzState = 163; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 141:
+              switch (zzInput) {
+                case 30: zzState = 142; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 142:
+              switch (zzInput) {
+                case 9: zzState = 164; break zzForNext;
+                case 27: zzState = 165; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 143:
+              switch (zzInput) {
+                case 38: zzState = 144; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 144:
+              switch (zzInput) {
+                case 9: zzState = 166; break zzForNext;
+                case 25: zzState = 167; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 145:
+              switch (zzInput) {
+                case 20: zzState = 146; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 146:
+              switch (zzInput) {
+                case 9: zzState = 168; break zzForNext;
+                case 23: zzState = 169; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 147:
+              switch (zzInput) {
+                case 23: zzState = 148; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 148:
+              switch (zzInput) {
+                case 9: zzState = 170; break zzForNext;
+                case 23: zzState = 171; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 149:
+              switch (zzInput) {
+                case 19: zzState = 150; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 150:
+              switch (zzInput) {
+                case 9: zzState = 172; break zzForNext;
+                case 20: zzState = 173; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 151:
+              switch (zzInput) {
+                case 15: zzState = 152; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 152:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: break zzForNext;
+                case 9: zzState = 174; break zzForNext;
+                case 13: zzState = 175; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 153:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzState = 103; break zzForNext;
+                case 20: zzState = 133; break zzForNext;
+                case 22: zzState = 134; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 154:
+              switch (zzInput) {
+                case 43: zzState = 155; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 155:
+              switch (zzInput) {
+                case 9: zzState = 176; break zzForNext;
+                case 38: zzState = 177; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 156:
+              switch (zzInput) {
+                case 43: zzState = 157; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 157:
+              switch (zzInput) {
+                case 9: zzState = 178; break zzForNext;
+                case 38: zzState = 179; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 158:
+              switch (zzInput) {
+                case 33: zzState = 159; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 159:
+              switch (zzInput) {
+                case 9: zzState = 180; break zzForNext;
+                case 17: zzState = 181; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 160:
+              switch (zzInput) {
+                case 15: zzState = 161; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 161:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzIsFinal = true; zzState = 182; break zzForNext;
+                case 9: zzState = 183; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 162:
+              switch (zzInput) {
+                case 17: zzState = 163; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 163:
+              switch (zzInput) {
+                case 9: zzState = 184; break zzForNext;
+                case 27: zzState = 185; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 164:
+              switch (zzInput) {
+                case 27: zzState = 165; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 165:
+              switch (zzInput) {
+                case 9: zzState = 186; break zzForNext;
+                case 18: zzState = 187; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 166:
+              switch (zzInput) {
+                case 25: zzState = 167; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 167:
+              switch (zzInput) {
+                case 9: zzState = 188; break zzForNext;
+                case 43: zzState = 189; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 168:
+              switch (zzInput) {
+                case 23: zzState = 169; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 169:
+              switch (zzInput) {
+                case 9: zzState = 190; break zzForNext;
+                case 29: zzState = 191; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 170:
+              switch (zzInput) {
+                case 23: zzState = 171; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 171:
+              switch (zzInput) {
+                case 9: zzState = 192; break zzForNext;
+                case 29: zzState = 193; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 172:
+              switch (zzInput) {
+                case 20: zzState = 173; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 173:
+              switch (zzInput) {
+                case 9: zzState = 194; break zzForNext;
+                case 21: zzState = 195; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 174:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzState = 152; break zzForNext;
+                case 13: zzState = 175; break zzForNext;
+                case 9: zzState = 196; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 175:
+              switch (zzInput) {
+                case 9: zzState = 197; break zzForNext;
+                case 14: zzState = 198; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 176:
+              switch (zzInput) {
+                case 38: zzState = 177; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 177:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzIsFinal = true; zzState = 199; break zzForNext;
+                case 9: zzState = 200; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 178:
+              switch (zzInput) {
+                case 38: zzState = 179; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 179:
+              switch (zzInput) {
+                case 23: zzState = 177; break zzForNext;
+                case 9: zzState = 201; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 180:
+              switch (zzInput) {
+                case 17: zzState = 181; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 181:
+              switch (zzInput) {
+                case 9: zzState = 202; break zzForNext;
+                case 27: zzState = 203; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 182:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzIsFinal = true; break zzForNext;
+                case 9: zzIsFinal = true; zzState = 204; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 183:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzIsFinal = true; zzState = 182; break zzForNext;
+                case 9: zzState = 205; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 184:
+              switch (zzInput) {
+                case 27: zzState = 185; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 185:
+              switch (zzInput) {
+                case 9: zzState = 206; break zzForNext;
+                case 29: zzState = 207; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 186:
+              switch (zzInput) {
+                case 18: zzState = 187; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 187:
+              switch (zzInput) {
+                case 9: zzState = 208; break zzForNext;
+                case 29: zzState = 209; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 188:
+              switch (zzInput) {
+                case 43: zzState = 189; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 189:
+              switch (zzInput) {
+                case 9: zzState = 210; break zzForNext;
+                case 38: zzState = 211; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 190:
+              switch (zzInput) {
+                case 29: zzState = 191; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 191:
+              switch (zzInput) {
+                case 9: zzState = 212; break zzForNext;
+                case 20: zzState = 213; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 192:
+              switch (zzInput) {
+                case 29: zzState = 193; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 193:
+              switch (zzInput) {
+                case 9: zzState = 214; break zzForNext;
+                case 19: zzState = 215; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 194:
+              switch (zzInput) {
+                case 21: zzState = 195; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 195:
+              switch (zzInput) {
+                case 9: zzState = 216; break zzForNext;
+                case 22: zzState = 217; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 196:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzState = 152; break zzForNext;
+                case 13: zzState = 175; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 197:
+              switch (zzInput) {
+                case 14: zzState = 198; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 198:
+              switch (zzInput) {
+                case 9: zzState = 218; break zzForNext;
+                case 15: zzState = 219; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 199:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzIsFinal = true; break zzForNext;
+                case 9: zzIsFinal = true; zzState = 220; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 200:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzIsFinal = true; zzState = 199; break zzForNext;
+                case 9: zzState = 221; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 201:
+              switch (zzInput) {
+                case 23: zzState = 177; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 202:
+              switch (zzInput) {
+                case 27: zzState = 203; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 203:
+              switch (zzInput) {
+                case 9: zzState = 222; break zzForNext;
+                case 37: zzState = 223; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 204:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzIsFinal = true; zzState = 182; break zzForNext;
+                case 9: zzState = 205; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 205:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzIsFinal = true; zzState = 182; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 206:
+              switch (zzInput) {
+                case 29: zzState = 207; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 207:
+              switch (zzInput) {
+                case 9: zzState = 224; break zzForNext;
+                case 38: zzState = 225; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 208:
+              switch (zzInput) {
+                case 29: zzState = 209; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 209:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: break zzForNext;
+                case 9: zzState = 226; break zzForNext;
+                case 10: zzIsFinal = true; zzState = 227; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 210:
+              switch (zzInput) {
+                case 38: zzState = 211; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 211:
+              switch (zzInput) {
+                case 9: zzState = 228; break zzForNext;
+                case 23: zzState = 229; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 212:
+              switch (zzInput) {
+                case 20: zzState = 213; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 213:
+              switch (zzInput) {
+                case 9: zzState = 230; break zzForNext;
+                case 20: zzState = 231; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 214:
+              switch (zzInput) {
+                case 19: zzState = 215; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 215:
+              switch (zzInput) {
+                case 9: zzState = 232; break zzForNext;
+                case 18: zzState = 233; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 216:
+              switch (zzInput) {
+                case 22: zzState = 217; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 217:
+              switch (zzInput) {
+                case 9: zzState = 234; break zzForNext;
+                case 23: zzState = 235; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 218:
+              switch (zzInput) {
+                case 15: zzState = 219; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 219:
+              switch (zzInput) {
+                case 9: zzState = 236; break zzForNext;
+                case 29: zzState = 237; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 220:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzIsFinal = true; zzState = 199; break zzForNext;
+                case 9: zzState = 221; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 221:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzIsFinal = true; zzState = 199; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 222:
+              switch (zzInput) {
+                case 37: zzState = 223; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 223:
+              switch (zzInput) {
+                case 9: zzState = 238; break zzForNext;
+                case 23: zzState = 239; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 224:
+              switch (zzInput) {
+                case 38: zzState = 225; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 225:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: break zzForNext;
+                case 9: zzState = 240; break zzForNext;
+                case 10: zzIsFinal = true; zzState = 241; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 226:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzState = 209; break zzForNext;
+                case 10: zzIsFinal = true; zzState = 227; break zzForNext;
+                case 9: zzState = 242; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 227:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzIsFinal = true; zzState = 243; break zzForNext;
+                case 9: zzState = 244; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 228:
+              switch (zzInput) {
+                case 23: zzState = 229; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 229:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: break zzForNext;
+                case 9: zzState = 245; break zzForNext;
+                case 10: zzIsFinal = true; zzState = 246; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 230:
+              switch (zzInput) {
+                case 20: zzState = 231; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 231:
+              switch (zzInput) {
+                case 9: zzState = 247; break zzForNext;
+                case 21: zzState = 248; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 232:
+              switch (zzInput) {
+                case 18: zzState = 233; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 233:
+              switch (zzInput) {
+                case 9: zzState = 249; break zzForNext;
+                case 17: zzState = 250; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 234:
+              switch (zzInput) {
+                case 23: zzState = 235; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 235:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: break zzForNext;
+                case 9: zzState = 251; break zzForNext;
+                case 24: zzState = 252; break zzForNext;
+                case 34: zzState = 253; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 236:
+              switch (zzInput) {
+                case 29: zzState = 237; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 237:
+              switch (zzInput) {
+                case 9: zzState = 254; break zzForNext;
+                case 30: zzState = 255; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 238:
+              switch (zzInput) {
+                case 23: zzState = 239; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 239:
+              switch (zzInput) {
+                case 9: zzState = 256; break zzForNext;
+                case 19: zzState = 257; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 240:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzState = 225; break zzForNext;
+                case 10: zzIsFinal = true; zzState = 241; break zzForNext;
+                case 9: zzState = 258; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 241:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzIsFinal = true; zzState = 259; break zzForNext;
+                case 9: zzState = 260; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 242:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzState = 209; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 243:
+              switch (zzInput) {
+                case 9: zzIsFinal = true; zzState = 227; break zzForNext;
+                case 6: 
+                case 7: 
+                case 8: zzIsFinal = true; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 244:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzIsFinal = true; zzState = 243; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 245:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzState = 229; break zzForNext;
+                case 10: zzIsFinal = true; zzState = 246; break zzForNext;
+                case 9: zzState = 261; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 246:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzIsFinal = true; zzState = 262; break zzForNext;
+                case 9: zzState = 263; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 247:
+              switch (zzInput) {
+                case 21: zzState = 248; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 248:
+              switch (zzInput) {
+                case 9: zzState = 264; break zzForNext;
+                case 22: zzState = 265; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 249:
+              switch (zzInput) {
+                case 17: zzState = 250; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 250:
+              switch (zzInput) {
+                case 9: zzState = 266; break zzForNext;
+                case 27: zzState = 267; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 251:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzState = 235; break zzForNext;
+                case 24: zzState = 252; break zzForNext;
+                case 34: zzState = 253; break zzForNext;
+                case 9: zzState = 268; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 252:
+              switch (zzInput) {
+                case 9: zzState = 269; break zzForNext;
+                case 20: zzState = 270; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 253:
+              switch (zzInput) {
+                case 9: zzState = 271; break zzForNext;
+                case 14: zzState = 272; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 254:
+              switch (zzInput) {
+                case 30: zzState = 255; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 255:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: break zzForNext;
+                case 9: zzState = 273; break zzForNext;
+                case 10: zzState = 274; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 256:
+              switch (zzInput) {
+                case 19: zzState = 257; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 257:
+              switch (zzInput) {
+                case 9: zzState = 275; break zzForNext;
+                case 20: zzState = 276; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 258:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzState = 225; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 259:
+              switch (zzInput) {
+                case 9: zzIsFinal = true; zzState = 241; break zzForNext;
+                case 6: 
+                case 7: 
+                case 8: zzIsFinal = true; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 260:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzIsFinal = true; zzState = 259; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 261:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzState = 229; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 262:
+              switch (zzInput) {
+                case 9: zzIsFinal = true; zzState = 246; break zzForNext;
+                case 6: 
+                case 7: 
+                case 8: zzIsFinal = true; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 263:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzIsFinal = true; zzState = 262; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 264:
+              switch (zzInput) {
+                case 22: zzState = 265; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 265:
+              switch (zzInput) {
+                case 9: zzState = 277; break zzForNext;
+                case 23: zzState = 278; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 266:
+              switch (zzInput) {
+                case 27: zzState = 267; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 267:
+              switch (zzInput) {
+                case 9: zzState = 279; break zzForNext;
+                case 29: zzState = 280; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 268:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzState = 235; break zzForNext;
+                case 24: zzState = 252; break zzForNext;
+                case 34: zzState = 253; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 269:
+              switch (zzInput) {
+                case 20: zzState = 270; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 270:
+              switch (zzInput) {
+                case 9: zzState = 281; break zzForNext;
+                case 14: zzState = 282; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 271:
+              switch (zzInput) {
+                case 14: zzState = 272; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 272:
+              switch (zzInput) {
+                case 9: zzState = 283; break zzForNext;
+                case 15: zzState = 284; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 273:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzState = 255; break zzForNext;
+                case 10: zzState = 274; break zzForNext;
+                case 9: zzState = 285; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 274:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: break zzForNext;
+                case 9: zzState = 286; break zzForNext;
+                case 31: 
+                case 32: zzState = 287; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 275:
+              switch (zzInput) {
+                case 20: zzState = 276; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 276:
+              switch (zzInput) {
+                case 9: zzState = 288; break zzForNext;
+                case 27: zzState = 289; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 277:
+              switch (zzInput) {
+                case 23: zzState = 278; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 278:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: break zzForNext;
+                case 9: zzState = 290; break zzForNext;
+                case 10: zzIsFinal = true; zzState = 291; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 279:
+              switch (zzInput) {
+                case 29: zzState = 280; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 280:
+              switch (zzInput) {
+                case 9: zzState = 292; break zzForNext;
+                case 38: zzState = 293; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 281:
+              switch (zzInput) {
+                case 14: zzState = 282; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 282:
+              switch (zzInput) {
+                case 9: zzState = 294; break zzForNext;
+                case 15: zzState = 295; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 283:
+              switch (zzInput) {
+                case 15: zzState = 284; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 284:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: break zzForNext;
+                case 9: zzState = 296; break zzForNext;
+                case 22: zzState = 297; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 285:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzState = 255; break zzForNext;
+                case 10: zzState = 274; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 286:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzState = 274; break zzForNext;
+                case 31: 
+                case 32: zzState = 287; break zzForNext;
+                case 9: zzState = 298; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 287:
+              switch (zzInput) {
+                case 9: zzState = 299; break zzForNext;
+                case 24: zzState = 300; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 288:
+              switch (zzInput) {
+                case 27: zzState = 289; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 289:
+              switch (zzInput) {
+                case 9: zzState = 301; break zzForNext;
+                case 45: zzState = 302; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 290:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzState = 278; break zzForNext;
+                case 10: zzIsFinal = true; zzState = 291; break zzForNext;
+                case 9: zzState = 303; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 291:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzIsFinal = true; zzState = 304; break zzForNext;
+                case 9: zzState = 305; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 292:
+              switch (zzInput) {
+                case 38: zzState = 293; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 293:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: break zzForNext;
+                case 9: zzState = 306; break zzForNext;
+                case 10: zzIsFinal = true; zzState = 307; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 294:
+              switch (zzInput) {
+                case 15: zzState = 295; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 295:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: break zzForNext;
+                case 9: zzState = 308; break zzForNext;
+                case 22: zzState = 309; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 296:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzState = 284; break zzForNext;
+                case 22: zzState = 297; break zzForNext;
+                case 9: zzState = 310; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 297:
+              switch (zzInput) {
+                case 9: zzState = 311; break zzForNext;
+                case 25: zzState = 312; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 298:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzState = 274; break zzForNext;
+                case 31: 
+                case 32: zzState = 287; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 299:
+              switch (zzInput) {
+                case 24: zzState = 300; break zzForNext;
+                case 9: zzState = 313; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 300:
+              switch (zzInput) {
+                case 9: zzState = 314; break zzForNext;
+                case 20: zzState = 315; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 301:
+              switch (zzInput) {
+                case 45: zzState = 302; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 302:
+              switch (zzInput) {
+                case 9: zzState = 316; break zzForNext;
+                case 23: zzState = 317; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 303:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzState = 278; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 304:
+              switch (zzInput) {
+                case 9: zzIsFinal = true; zzState = 291; break zzForNext;
+                case 6: 
+                case 7: 
+                case 8: zzIsFinal = true; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 305:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzIsFinal = true; zzState = 304; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 306:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzState = 293; break zzForNext;
+                case 10: zzIsFinal = true; zzState = 307; break zzForNext;
+                case 9: zzState = 318; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 307:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzIsFinal = true; zzState = 319; break zzForNext;
+                case 9: zzState = 320; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 308:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzState = 295; break zzForNext;
+                case 22: zzState = 309; break zzForNext;
+                case 9: zzState = 321; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 309:
+              switch (zzInput) {
+                case 9: zzState = 322; break zzForNext;
+                case 25: zzState = 323; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 310:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzState = 284; break zzForNext;
+                case 22: zzState = 297; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 311:
+              switch (zzInput) {
+                case 25: zzState = 312; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 312:
+              switch (zzInput) {
+                case 9: zzState = 324; break zzForNext;
+                case 26: zzState = 325; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 313:
+              switch (zzInput) {
+                case 24: zzState = 300; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 314:
+              switch (zzInput) {
+                case 20: zzState = 315; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 315:
+              switch (zzInput) {
+                case 9: zzState = 326; break zzForNext;
+                case 20: zzState = 327; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 316:
+              switch (zzInput) {
+                case 23: zzState = 317; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 317:
+              switch (zzInput) {
+                case 9: zzState = 328; break zzForNext;
+                case 35: zzState = 329; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 318:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzState = 293; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 319:
+              switch (zzInput) {
+                case 9: zzIsFinal = true; zzState = 307; break zzForNext;
+                case 6: 
+                case 7: 
+                case 8: zzIsFinal = true; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 320:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzIsFinal = true; zzState = 319; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 321:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzState = 295; break zzForNext;
+                case 22: zzState = 309; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 322:
+              switch (zzInput) {
+                case 25: zzState = 323; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 323:
+              switch (zzInput) {
+                case 9: zzState = 330; break zzForNext;
+                case 26: zzState = 331; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 324:
+              switch (zzInput) {
+                case 26: zzState = 325; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 325:
+              switch (zzInput) {
+                case 9: zzState = 332; break zzForNext;
+                case 15: zzState = 333; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 326:
+              switch (zzInput) {
+                case 20: zzState = 327; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 327:
+              switch (zzInput) {
+                case 9: zzState = 334; break zzForNext;
+                case 22: zzState = 335; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 328:
+              switch (zzInput) {
+                case 35: zzState = 329; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 329:
+              switch (zzInput) {
+                case 20: zzState = 133; break zzForNext;
+                case 22: zzState = 134; break zzForNext;
+                case 9: zzState = 336; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 330:
+              switch (zzInput) {
+                case 26: zzState = 331; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 331:
+              switch (zzInput) {
+                case 9: zzState = 337; break zzForNext;
+                case 15: zzState = 338; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 332:
+              switch (zzInput) {
+                case 15: zzState = 333; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 333:
+              switch (zzInput) {
+                case 9: zzState = 339; break zzForNext;
+                case 27: zzState = 340; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 334:
+              switch (zzInput) {
+                case 22: zzState = 335; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 335:
+              switch (zzInput) {
+                case 9: zzState = 341; break zzForNext;
+                case 33: zzState = 342; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 336:
+              switch (zzInput) {
+                case 20: zzState = 133; break zzForNext;
+                case 22: zzState = 134; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 337:
+              switch (zzInput) {
+                case 15: zzState = 338; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 338:
+              switch (zzInput) {
+                case 9: zzState = 343; break zzForNext;
+                case 27: zzState = 344; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 339:
+              switch (zzInput) {
+                case 27: zzState = 340; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 340:
+              switch (zzInput) {
+                case 9: zzState = 345; break zzForNext;
+                case 19: zzState = 346; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 341:
+              switch (zzInput) {
+                case 33: zzState = 342; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 342:
+              switch (zzInput) {
+                case 9: zzState = 347; break zzForNext;
+                case 28: zzState = 348; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 343:
+              switch (zzInput) {
+                case 27: zzState = 344; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 344:
+              switch (zzInput) {
+                case 9: zzState = 349; break zzForNext;
+                case 19: zzState = 350; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 345:
+              switch (zzInput) {
+                case 19: zzState = 346; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 346:
+              switch (zzInput) {
+                case 28: zzState = 351; break zzForNext;
+                case 8: break zzForAction;
+                default: break zzForNext;
+              }
+
+            case 347:
+              switch (zzInput) {
+                case 28: zzState = 348; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 348:
+              switch (zzInput) {
+                case 9: zzState = 352; break zzForNext;
+                case 28: zzState = 353; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 349:
+              switch (zzInput) {
+                case 19: zzState = 350; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 350:
+              switch (zzInput) {
+                case 28: zzState = 354; break zzForNext;
+                case 8: break zzForAction;
+                default: break zzForNext;
+              }
+
+            case 351:
+              switch (zzInput) {
+                case 9: zzState = 355; break zzForNext;
+                case 28: zzState = 356; break zzForNext;
+                case 8: break zzForAction;
+                default: zzState = 346; break zzForNext;
+              }
+
+            case 352:
+              switch (zzInput) {
+                case 28: zzState = 353; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 353:
+              switch (zzInput) {
+                case 9: zzState = 357; break zzForNext;
+                case 34: zzState = 358; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 354:
+              switch (zzInput) {
+                case 9: zzState = 359; break zzForNext;
+                case 28: zzState = 360; break zzForNext;
+                case 8: break zzForAction;
+                default: zzState = 350; break zzForNext;
+              }
+
+            case 355:
+              switch (zzInput) {
+                case 28: zzState = 356; break zzForNext;
+                case 8: break zzForAction;
+                default: zzState = 346; break zzForNext;
+              }
+
+            case 356:
+              switch (zzInput) {
+                case 28: break zzForNext;
+                case 9: zzState = 361; break zzForNext;
+                case 17: zzState = 362; break zzForNext;
+                case 8: break zzForAction;
+                default: zzState = 346; break zzForNext;
+              }
+
+            case 357:
+              switch (zzInput) {
+                case 34: zzState = 358; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 358:
+              switch (zzInput) {
+                case 9: zzState = 363; break zzForNext;
+                case 34: zzState = 364; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 359:
+              switch (zzInput) {
+                case 28: zzState = 360; break zzForNext;
+                case 8: break zzForAction;
+                default: zzState = 350; break zzForNext;
+              }
+
+            case 360:
+              switch (zzInput) {
+                case 28: break zzForNext;
+                case 9: zzState = 365; break zzForNext;
+                case 17: zzState = 366; break zzForNext;
+                case 8: break zzForAction;
+                default: zzState = 350; break zzForNext;
+              }
+
+            case 361:
+              switch (zzInput) {
+                case 28: zzState = 356; break zzForNext;
+                case 17: zzState = 362; break zzForNext;
+                case 8: break zzForAction;
+                default: zzState = 346; break zzForNext;
+              }
+
+            case 362:
+              switch (zzInput) {
+                case 28: zzState = 351; break zzForNext;
+                case 9: zzState = 367; break zzForNext;
+                case 20: zzState = 368; break zzForNext;
+                case 8: break zzForAction;
+                default: zzState = 346; break zzForNext;
+              }
+
+            case 363:
+              switch (zzInput) {
+                case 34: zzState = 364; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 364:
+              switch (zzInput) {
+                case 9: zzState = 369; break zzForNext;
+                case 34: zzState = 370; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 365:
+              switch (zzInput) {
+                case 28: zzState = 360; break zzForNext;
+                case 17: zzState = 366; break zzForNext;
+                case 8: break zzForAction;
+                default: zzState = 350; break zzForNext;
+              }
+
+            case 366:
+              switch (zzInput) {
+                case 28: zzState = 354; break zzForNext;
+                case 9: zzState = 371; break zzForNext;
+                case 20: zzState = 372; break zzForNext;
+                case 8: break zzForAction;
+                default: zzState = 350; break zzForNext;
+              }
+
+            case 367:
+              switch (zzInput) {
+                case 28: zzState = 351; break zzForNext;
+                case 20: zzState = 368; break zzForNext;
+                case 8: break zzForAction;
+                default: zzState = 346; break zzForNext;
+              }
+
+            case 368:
+              switch (zzInput) {
+                case 28: zzState = 351; break zzForNext;
+                case 9: zzState = 373; break zzForNext;
+                case 17: zzState = 374; break zzForNext;
+                case 8: break zzForAction;
+                default: zzState = 346; break zzForNext;
+              }
+
+            case 369:
+              switch (zzInput) {
+                case 34: zzState = 370; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 370:
+              switch (zzInput) {
+                case 9: zzState = 375; break zzForNext;
+                case 35: zzState = 376; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 371:
+              switch (zzInput) {
+                case 28: zzState = 354; break zzForNext;
+                case 20: zzState = 372; break zzForNext;
+                case 8: break zzForAction;
+                default: zzState = 350; break zzForNext;
+              }
+
+            case 372:
+              switch (zzInput) {
+                case 28: zzState = 354; break zzForNext;
+                case 9: zzState = 377; break zzForNext;
+                case 17: zzState = 378; break zzForNext;
+                case 8: break zzForAction;
+                default: zzState = 350; break zzForNext;
+              }
+
+            case 373:
+              switch (zzInput) {
+                case 28: zzState = 351; break zzForNext;
+                case 17: zzState = 374; break zzForNext;
+                case 8: break zzForAction;
+                default: zzState = 346; break zzForNext;
+              }
+
+            case 374:
+              switch (zzInput) {
+                case 28: zzState = 351; break zzForNext;
+                case 6: 
+                case 7: zzState = 379; break zzForNext;
+                case 8: zzState = 380; break zzForNext;
+                default: zzState = 346; break zzForNext;
+              }
+
+            case 375:
+              switch (zzInput) {
+                case 35: zzState = 376; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 376:
+              switch (zzInput) {
+                case 9: zzState = 381; break zzForNext;
+                case 34: zzState = 382; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 377:
+              switch (zzInput) {
+                case 28: zzState = 354; break zzForNext;
+                case 17: zzState = 378; break zzForNext;
+                case 8: break zzForAction;
+                default: zzState = 350; break zzForNext;
+              }
+
+            case 378:
+              switch (zzInput) {
+                case 28: zzState = 354; break zzForNext;
+                case 6: 
+                case 7: zzState = 383; break zzForNext;
+                case 8: zzState = 384; break zzForNext;
+                case 9: zzState = 385; break zzForNext;
+                default: zzState = 350; break zzForNext;
+              }
+
+            case 379:
+              switch (zzInput) {
+                case 28: zzState = 351; break zzForNext;
+                case 9: zzState = 386; break zzForNext;
+                case 34: zzState = 387; break zzForNext;
+                case 8: break zzForAction;
+                default: zzState = 346; break zzForNext;
+              }
+
+            case 380:
+              switch (zzInput) {
+                case 9: zzState = 388; break zzForNext;
+                case 34: zzState = 389; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 381:
+              switch (zzInput) {
+                case 34: zzState = 382; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 382:
+              switch (zzInput) {
+                case 9: zzState = 390; break zzForNext;
+                case 36: zzState = 391; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 383:
+              switch (zzInput) {
+                case 28: zzState = 354; break zzForNext;
+                case 9: zzState = 392; break zzForNext;
+                case 13: zzState = 393; break zzForNext;
+                case 8: break zzForAction;
+                default: zzState = 350; break zzForNext;
+              }
+
+            case 384:
+              switch (zzInput) {
+                case 9: zzState = 394; break zzForNext;
+                case 13: zzState = 395; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 385:
+              switch (zzInput) {
+                case 28: zzState = 354; break zzForNext;
+                case 6: 
+                case 7: zzState = 383; break zzForNext;
+                case 8: zzState = 384; break zzForNext;
+                case 9: zzState = 396; break zzForNext;
+                default: zzState = 350; break zzForNext;
+              }
+
+            case 386:
+              switch (zzInput) {
+                case 28: zzState = 351; break zzForNext;
+                case 34: zzState = 387; break zzForNext;
+                case 8: break zzForAction;
+                default: zzState = 346; break zzForNext;
+              }
+
+            case 387:
+              switch (zzInput) {
+                case 28: zzState = 351; break zzForNext;
+                case 9: zzState = 397; break zzForNext;
+                case 14: zzState = 398; break zzForNext;
+                case 8: break zzForAction;
+                default: zzState = 346; break zzForNext;
+              }
+
+            case 388:
+              switch (zzInput) {
+                case 34: zzState = 389; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 389:
+              switch (zzInput) {
+                case 9: zzState = 399; break zzForNext;
+                case 14: zzState = 400; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 390:
+              switch (zzInput) {
+                case 36: zzState = 391; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 391:
+              switch (zzInput) {
+                case 9: zzState = 401; break zzForNext;
+                case 35: zzState = 402; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 392:
+              switch (zzInput) {
+                case 28: zzState = 354; break zzForNext;
+                case 13: zzState = 393; break zzForNext;
+                case 9: zzState = 403; break zzForNext;
+                case 8: break zzForAction;
+                default: zzState = 350; break zzForNext;
+              }
+
+            case 393:
+              switch (zzInput) {
+                case 28: zzState = 354; break zzForNext;
+                case 9: zzState = 404; break zzForNext;
+                case 24: zzState = 405; break zzForNext;
+                case 8: break zzForAction;
+                default: zzState = 350; break zzForNext;
+              }
+
+            case 394:
+              switch (zzInput) {
+                case 13: zzState = 395; break zzForNext;
+                case 9: zzState = 406; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 395:
+              switch (zzInput) {
+                case 9: zzState = 407; break zzForNext;
+                case 24: zzState = 408; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 396:
+              switch (zzInput) {
+                case 28: zzState = 354; break zzForNext;
+                case 6: 
+                case 7: zzState = 383; break zzForNext;
+                case 8: zzState = 384; break zzForNext;
+                default: zzState = 350; break zzForNext;
+              }
+
+            case 397:
+              switch (zzInput) {
+                case 28: zzState = 351; break zzForNext;
+                case 14: zzState = 398; break zzForNext;
+                case 8: break zzForAction;
+                default: zzState = 346; break zzForNext;
+              }
+
+            case 398:
+              switch (zzInput) {
+                case 28: zzState = 351; break zzForNext;
+                case 9: zzState = 409; break zzForNext;
+                case 15: zzIsFinal = true; zzState = 410; break zzForNext;
+                case 8: break zzForAction;
+                default: zzState = 346; break zzForNext;
+              }
+
+            case 399:
+              switch (zzInput) {
+                case 14: zzState = 400; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 400:
+              switch (zzInput) {
+                case 9: zzState = 411; break zzForNext;
+                case 15: zzIsFinal = true; zzState = 412; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 401:
+              switch (zzInput) {
+                case 35: zzState = 402; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 402:
+              switch (zzInput) {
+                case 9: zzState = 413; break zzForNext;
+                case 18: zzState = 414; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 403:
+              switch (zzInput) {
+                case 28: zzState = 354; break zzForNext;
+                case 13: zzState = 393; break zzForNext;
+                case 8: break zzForAction;
+                default: zzState = 350; break zzForNext;
+              }
+
+            case 404:
+              switch (zzInput) {
+                case 28: zzState = 354; break zzForNext;
+                case 24: zzState = 405; break zzForNext;
+                case 8: break zzForAction;
+                default: zzState = 350; break zzForNext;
+              }
+
+            case 405:
+              switch (zzInput) {
+                case 28: zzState = 354; break zzForNext;
+                case 9: zzState = 415; break zzForNext;
+                case 20: zzState = 416; break zzForNext;
+                case 8: break zzForAction;
+                default: zzState = 350; break zzForNext;
+              }
+
+            case 406:
+              switch (zzInput) {
+                case 13: zzState = 395; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 407:
+              switch (zzInput) {
+                case 24: zzState = 408; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 408:
+              switch (zzInput) {
+                case 9: zzState = 417; break zzForNext;
+                case 20: zzState = 418; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 409:
+              switch (zzInput) {
+                case 28: zzState = 351; break zzForNext;
+                case 15: zzIsFinal = true; zzState = 410; break zzForNext;
+                case 8: break zzForAction;
+                default: zzState = 346; break zzForNext;
+              }
+
+            case 410:
+              switch (zzInput) {
+                case 28: zzState = 351; break zzForNext;
+                case 9: zzIsFinal = true; zzState = 419; break zzForNext;
+                case 8: break zzForAction;
+                default: zzState = 346; break zzForNext;
+              }
+
+            case 411:
+              switch (zzInput) {
+                case 15: zzIsFinal = true; zzState = 412; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 412:
+              switch (zzInput) {
+                case 9: zzIsFinal = true; zzNoLookAhead = true; zzState = 420; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 413:
+              switch (zzInput) {
+                case 18: zzState = 414; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 414:
+              switch (zzInput) {
+                case 9: zzState = 421; break zzForNext;
+                case 37: zzState = 422; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 415:
+              switch (zzInput) {
+                case 28: zzState = 354; break zzForNext;
+                case 20: zzState = 416; break zzForNext;
+                case 8: break zzForAction;
+                default: zzState = 350; break zzForNext;
+              }
+
+            case 416:
+              switch (zzInput) {
+                case 28: zzState = 354; break zzForNext;
+                case 9: zzState = 423; break zzForNext;
+                case 14: zzState = 424; break zzForNext;
+                case 8: break zzForAction;
+                default: zzState = 350; break zzForNext;
+              }
+
+            case 417:
+              switch (zzInput) {
+                case 20: zzState = 418; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 418:
+              switch (zzInput) {
+                case 9: zzState = 425; break zzForNext;
+                case 14: zzState = 426; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 419:
+              switch (zzInput) {
+                case 28: zzState = 351; break zzForNext;
+                case 8: break zzForAction;
+                default: zzState = 346; break zzForNext;
+              }
+
+            case 421:
+              switch (zzInput) {
+                case 37: zzState = 422; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 422:
+              switch (zzInput) {
+                case 9: zzState = 427; break zzForNext;
+                case 38: zzState = 428; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 423:
+              switch (zzInput) {
+                case 28: zzState = 354; break zzForNext;
+                case 14: zzState = 424; break zzForNext;
+                case 8: break zzForAction;
+                default: zzState = 350; break zzForNext;
+              }
+
+            case 424:
+              switch (zzInput) {
+                case 28: zzState = 354; break zzForNext;
+                case 9: zzState = 429; break zzForNext;
+                case 15: zzIsFinal = true; zzState = 430; break zzForNext;
+                case 8: break zzForAction;
+                default: zzState = 350; break zzForNext;
+              }
+
+            case 425:
+              switch (zzInput) {
+                case 14: zzState = 426; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 426:
+              switch (zzInput) {
+                case 9: zzState = 431; break zzForNext;
+                case 15: zzIsFinal = true; zzState = 432; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 427:
+              switch (zzInput) {
+                case 38: zzState = 428; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 428:
+              switch (zzInput) {
+                case 9: zzState = 433; break zzForNext;
+                case 28: zzState = 434; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 429:
+              switch (zzInput) {
+                case 28: zzState = 354; break zzForNext;
+                case 15: zzIsFinal = true; zzState = 430; break zzForNext;
+                case 8: break zzForAction;
+                default: zzState = 350; break zzForNext;
+              }
+
+            case 430:
+              switch (zzInput) {
+                case 28: zzState = 354; break zzForNext;
+                case 9: zzIsFinal = true; zzState = 435; break zzForNext;
+                case 8: break zzForAction;
+                default: zzState = 350; break zzForNext;
+              }
+
+            case 431:
+              switch (zzInput) {
+                case 15: zzIsFinal = true; zzState = 432; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 432:
+              switch (zzInput) {
+                case 9: zzIsFinal = true; zzNoLookAhead = true; zzState = 436; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 433:
+              switch (zzInput) {
+                case 28: zzState = 434; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 434:
+              switch (zzInput) {
+                case 9: zzState = 437; break zzForNext;
+                case 39: zzState = 438; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 435:
+              switch (zzInput) {
+                case 28: zzState = 354; break zzForNext;
+                case 8: break zzForAction;
+                default: zzState = 350; break zzForNext;
+              }
+
+            case 437:
+              switch (zzInput) {
+                case 39: zzState = 438; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 438:
+              switch (zzInput) {
+                case 9: zzState = 439; break zzForNext;
+                case 40: zzState = 440; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 439:
+              switch (zzInput) {
+                case 40: zzState = 440; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 440:
+              switch (zzInput) {
+                case 9: zzState = 441; break zzForNext;
+                case 40: zzState = 442; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 441:
+              switch (zzInput) {
+                case 40: zzState = 442; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 442:
+              switch (zzInput) {
+                case 9: zzState = 443; break zzForNext;
+                case 40: zzState = 444; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 443:
+              switch (zzInput) {
+                case 40: zzState = 444; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 444:
+              switch (zzInput) {
+                case 28: zzState = 394; break zzForNext;
+                case 9: zzState = 445; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 445:
+              switch (zzInput) {
+                case 28: zzState = 394; break zzForNext;
+                default: break zzForAction;
+              }
+
+            default:
+              // if this is ever reached, there is a serious bug in JFlex
+              zzScanError(ZZ_UNKNOWN_ERROR);
+              break;
+          } }
+
+          if ( zzIsFinal ) {
+            zzAction = zzState;
+            zzMarkedPosL = zzCurrentPosL;
+            if ( zzNoLookAhead ) break zzForAction;
+          }
+
+        }
+      }
+
+      // store back cached position
+      zzMarkedPos = zzMarkedPosL;
+
+      switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) {
+        case 10: 
+          { if (yychar == 0 ) {hasMore = false; return EncodingParserConstants.UTF16BE;}
+          }
+        case 26: break;
+        case 16: 
+          { if (yychar == 0 ) {hasMore = false; return EncodingParserConstants.UTF83ByteBOM;}
+          }
+        case 27: break;
+        case 1: 
+          { if(yychar > MAX_TO_SCAN) {hasMore=false; return EncodingParserConstants.MAX_CHARS_REACHED;}
+          }
+        case 28: break;
+        case 4: 
+          { yybegin(SQ_STRING); string.setLength(0);
+          }
+        case 29: break;
+        case 8: 
+          { yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.UnDelimitedStringValue;
+          }
+        case 30: break;
+        case 5: 
+          { string.append( yytext() );
+          }
+        case 31: break;
+        case 9: 
+          { yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTermintatedUnDelimitedStringValue;
+          }
+        case 32: break;
+        case 21: 
+          { pushCurrentState(); yybegin(QuotedAttributeValue); return JSPHeadTokenizerConstants.PageLanguage;
+          }
+        case 33: break;
+        case 15: 
+          { yypushback(yylength()); popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;
+          }
+        case 34: break;
+        case 25: 
+          { isXHTML = true;
+          }
+        case 35: break;
+        case 23: 
+          { pushCurrentState(); yybegin(QuotedAttributeValue); return JSPHeadTokenizerConstants.PageEncoding;
+          }
+        case 36: break;
+        case 11: 
+          { if (yychar == 0 ) {hasMore = false; return EncodingParserConstants.UTF16LE;}
+          }
+        case 37: break;
+        case 7: 
+          { popState(); valueText = string.toString(); return EncodingParserConstants.StringValue;
+          }
+        case 38: break;
+        case 14: 
+          { yybegin(YYINITIAL);  return JSPHeadTokenizerConstants.PageDirectiveEnd;
+          }
+        case 39: break;
+        case 22: 
+          { pushCurrentState(); yybegin(QuotedAttributeValue); return JSPHeadTokenizerConstants.PageContentType;
+          }
+        case 40: break;
+        case 17: 
+          { if (yychar == 0 ) {yybegin(ST_XMLDecl); return XMLHeadTokenizerConstants.XMLDeclStart;}
+          }
+        case 41: break;
+        case 2: 
+          { yypushback(1); yybegin(UnDelimitedString); string.setLength(0);
+          }
+        case 42: break;
+        case 12: 
+          { yybegin(YYINITIAL); return XMLHeadTokenizerConstants.XMLDeclEnd;
+          }
+        case 43: break;
+        case 13: 
+          { yybegin(YYINITIAL); return JSPHeadTokenizerConstants.PageDirectiveEnd;
+          }
+        case 44: break;
+        case 24: 
+          { isWML = true;
+          }
+        case 45: break;
+        case 18: 
+          { yybegin(ST_PAGE_DIRECTIVE); return JSPHeadTokenizerConstants.PageDirectiveStart;
+          }
+        case 46: break;
+        case 6: 
+          { yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;
+          }
+        case 47: break;
+        case 20: 
+          { pushCurrentState(); yybegin(QuotedAttributeValue); return XMLHeadTokenizerConstants.XMLDelEncoding;
+          }
+        case 48: break;
+        case 19: 
+          { pushCurrentState(); yybegin(QuotedAttributeValue); return XMLHeadTokenizerConstants.XMLDeclVersion;
+          }
+        case 49: break;
+        case 3: 
+          { yybegin(DQ_STRING); string.setLength(0);
+          }
+        case 50: break;
+        default: 
+          if (zzInput == YYEOF && zzStartRead == zzCurrentPos) {
+            zzAtEOF = true;
+            zzDoEOF();
+              {
+                hasMore = false; return EncodingParserConstants.EOF;
+              }
+          } 
+          else {
+            zzScanError(ZZ_NO_MATCH);
+          }
+      }
+    }
+  }
+
+
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contenttype/JSPHeadTokenizerConstants.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contenttype/JSPHeadTokenizerConstants.java
new file mode 100644
index 0000000..7b71657
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contenttype/JSPHeadTokenizerConstants.java
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.contenttype;
+
+import org.eclipse.wst.xml.core.internal.contenttype.XMLHeadTokenizerConstants;
+
+public interface JSPHeadTokenizerConstants extends XMLHeadTokenizerConstants {
+	String PageDirectiveStart = "PageDirectiveStart"; //$NON-NLS-1$
+	String PageDirectiveEnd = "PageDirectiveEnd"; //$NON-NLS-1$
+	String PageLanguage = "PageLanguage"; //$NON-NLS-1$
+	String PageEncoding = "PageEncoding"; //$NON-NLS-1$
+	String PageContentType = "PageContentType"; //$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contenttype/JSPResourceEncodingDetector.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contenttype/JSPResourceEncodingDetector.java
new file mode 100644
index 0000000..8a6e5c6
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contenttype/JSPResourceEncodingDetector.java
@@ -0,0 +1,541 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.contenttype;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.nio.charset.Charset;
+import java.nio.charset.IllegalCharsetNameException;
+import java.nio.charset.UnsupportedCharsetException;
+import java.util.regex.Pattern;
+
+import org.eclipse.core.resources.IStorage;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.content.IContentDescription;
+import org.eclipse.jst.jsp.core.internal.Logger;
+import org.eclipse.wst.sse.core.internal.encoding.CodedIO;
+import org.eclipse.wst.sse.core.internal.encoding.EncodingMemento;
+import org.eclipse.wst.sse.core.internal.encoding.IResourceCharsetDetector;
+import org.eclipse.wst.sse.core.internal.encoding.NonContentBasedEncodingRules;
+import org.eclipse.wst.sse.core.utils.StringUtils;
+import org.eclipse.wst.xml.core.internal.contenttype.EncodingParserConstants;
+import org.eclipse.wst.xml.core.internal.contenttype.XMLHeadTokenizerConstants;
+
+import com.ibm.icu.util.StringTokenizer;
+
+public class JSPResourceEncodingDetector implements IResourceCharsetDetector {
+
+	private String fCharset;
+
+	private String fContentType;
+
+	private String fContentTypeValue;
+
+	private String fLanguage;
+
+	private String fPageEncodingValue;
+
+	private JSPHeadTokenizer fTokenizer;
+
+	private String fXMLDecEncodingName;
+
+	private boolean unicodeCase;
+
+	private EncodingMemento fEncodingMemento;
+
+	private boolean fHeaderParsed;
+
+	private Reader fReader;
+
+	private boolean fXHTML;
+
+	private boolean fWML;
+
+
+	/**
+	 * No Arg constructor.
+	 */
+	public JSPResourceEncodingDetector() {
+		super();
+	}
+
+	class NullMemento extends EncodingMemento {
+		/**
+		 * 
+		 */
+		public NullMemento() {
+			super();
+			String defaultCharset = NonContentBasedEncodingRules.useDefaultNameRules(null);
+			setJavaCharsetName(defaultCharset);
+			setAppropriateDefault(defaultCharset);
+			setDetectedCharsetName(null);
+		}
+
+	}
+
+	/**
+	 * @return Returns the contentType.
+	 */
+	public String getContentType() throws IOException {
+		ensureInputSet();
+		if (!fHeaderParsed) {
+			parseInput();
+			// we keep track of if header's already been parse, so can make
+			// multiple 'get' calls, without causing reparsing.
+			fHeaderParsed = true;
+			// Note: there is a "hidden assumption" here that an empty
+			// string in content should be treated same as not present.
+		}
+		return fContentType;
+	}
+
+	public String getEncoding() throws IOException {
+		return getEncodingMemento().getDetectedCharsetName();
+	}
+
+	// to ensure consist overall rules used, we'll mark as
+	// final,
+	// and require subclasses to provide certain pieces of
+	// the
+	// implementation
+	public EncodingMemento getEncodingMemento() throws IOException {
+		ensureInputSet();
+		if (!fHeaderParsed) {
+			parseInput();
+			// we keep track of if header's already been
+			// parse, so can make
+			// multiple 'get' calls, without causing
+			// reparsing.
+			fHeaderParsed = true;
+			// Note: there is a "hidden assumption" here
+			// that an empty
+			// string in content should be treated same as
+			// not present.
+		}
+		if (fEncodingMemento == null) {
+			handleSpecDefault();
+		}
+		if (fEncodingMemento == null) {
+			// safty net
+			fEncodingMemento = new NullMemento();
+		}
+		return fEncodingMemento;
+	}
+
+	public String getLanguage() throws IOException {
+		ensureInputSet();
+		if (!fHeaderParsed) {
+			parseInput();
+			fHeaderParsed = true;
+		}
+		return fLanguage;
+	}
+
+	public String getSpecDefaultEncoding() {
+		// by JSP Spec
+		final String enc = "ISO-8859-1"; //$NON-NLS-1$
+		return enc;
+	}
+
+	public EncodingMemento getSpecDefaultEncodingMemento() {
+		resetAll();
+		EncodingMemento result = null;
+		String enc = getSpecDefaultEncoding();
+		if (enc != null) {
+			createEncodingMemento(enc, EncodingMemento.DEFAULTS_ASSUMED_FOR_EMPTY_INPUT);
+			fEncodingMemento.setAppropriateDefault(enc);
+			result = fEncodingMemento;
+		}
+		return result;
+	}
+
+	/**
+	 * 
+	 */
+	public void set(InputStream inputStream) {
+		resetAll();
+		fReader = new ByteReader(inputStream);
+		try {
+			fReader.mark(CodedIO.MAX_MARK_SIZE);
+		}
+		catch (IOException e) {
+			// impossible, since we know ByteReader
+			// supports marking
+			throw new Error(e);
+		}
+	}
+
+	/**
+	 * 
+	 */
+	public void set(IStorage iStorage) throws CoreException {
+		resetAll();
+		InputStream inputStream = iStorage.getContents();
+		InputStream resettableStream = new BufferedInputStream(inputStream, CodedIO.MAX_BUF_SIZE);
+		resettableStream.mark(CodedIO.MAX_MARK_SIZE);
+		set(resettableStream);
+		// TODO we'll need to "remember" IFile, or
+		// get its (or its project's) settings, in case
+		// those are needed to handle cases when the
+		// encoding is not in the file stream.
+	}
+
+	/**
+	 * Note: this is not part of interface to help avoid confusion ... it
+	 * expected this Reader is a well formed character reader ... that is, its
+	 * all ready been determined to not be a unicode marked input stream. And,
+	 * its assumed to be in the correct position, at position zero, ready to
+	 * read first character.
+	 */
+	public void set(Reader reader) {
+		resetAll();
+		fReader = reader;
+		if (!fReader.markSupported()) {
+			fReader = new BufferedReader(fReader);
+		}
+		try {
+			fReader.mark(CodedIO.MAX_MARK_SIZE);
+		}
+		catch (IOException e) {
+			// impossble, since we just checked if markable
+			throw new Error(e);
+		}
+	}
+
+	private boolean canHandleAsUnicodeStream(String tokenType) {
+		boolean canHandleAsUnicode = false;
+		if (tokenType == EncodingParserConstants.UTF83ByteBOM) {
+			canHandleAsUnicode = true;
+			String enc = "UTF-8"; //$NON-NLS-1$
+			createEncodingMemento(enc, EncodingMemento.DETECTED_STANDARD_UNICODE_BYTES);
+			fEncodingMemento.setUTF83ByteBOMUsed(true);
+		}
+		else if (tokenType == EncodingParserConstants.UTF16BE || tokenType == EncodingParserConstants.UTF16LE) {
+			canHandleAsUnicode = true;
+			String enc = "UTF-16"; //$NON-NLS-1$
+			byte[] bom = (tokenType == EncodingParserConstants.UTF16BE) ? IContentDescription.BOM_UTF_16BE : IContentDescription.BOM_UTF_16LE;
+			createEncodingMemento(enc, EncodingMemento.DETECTED_STANDARD_UNICODE_BYTES);
+			fEncodingMemento.setUnicodeStream(true);
+			fEncodingMemento.setUnicodeBOM(bom);
+		}
+		return canHandleAsUnicode;
+	}
+
+	/**
+	 * Note: once this instance is created, trace info still needs to be
+	 * appended by caller, depending on the context its created.
+	 */
+	private void createEncodingMemento(String detectedCharsetName) {
+		fEncodingMemento = new EncodingMemento();
+		fEncodingMemento.setJavaCharsetName(getAppropriateJavaCharset(detectedCharsetName));
+		fEncodingMemento.setDetectedCharsetName(detectedCharsetName);
+		// TODO: if detectedCharset and spec default is
+		// null, need to use "work
+		// bench based" defaults.
+		fEncodingMemento.setAppropriateDefault(getSpecDefaultEncoding());
+	}
+
+	/**
+	 * There can sometimes be mulitple 'encodings' specified in a file. This
+	 * is an attempt to centralize the rules for deciding between them.
+	 * Returns encoding according to priority: 1. XML Declaration 2. page
+	 * directive pageEncoding name 3. page directive contentType charset name
+	 */
+	private String getAppropriateEncoding() {
+		String result = null;
+		if (fXMLDecEncodingName != null)
+			result = fXMLDecEncodingName;
+		else if (fPageEncodingValue != null)
+			result = fPageEncodingValue;
+		else if (fCharset != null)
+			result = fCharset;
+		return result;
+	}
+
+	/**
+	 * This method can return null, if invalid charset name (in which case
+	 * "appropriateDefault" should be used, if a name is really need for some
+	 * "save anyway" cases).
+	 * 
+	 * @param detectedCharsetName
+	 * @return
+	 */
+	private String getAppropriateJavaCharset(String detectedCharsetName) {
+		String result = null;
+		// 1. Check explicit mapping overrides from
+		// property file -- its here we pick up "rules" for cases
+		// that are not even in Java
+		result = CodedIO.checkMappingOverrides(detectedCharsetName);
+		// 2. Use the "canonical" name from JRE mappings
+		// Note: see Charset JavaDoc, the name you get one
+		// with can be alias,
+		// the name you get back is "standard" name.
+		Charset javaCharset = null;
+		try {
+			javaCharset = Charset.forName(detectedCharsetName);
+		}
+		catch (UnsupportedCharsetException e) {
+			// only set invalid, if result is same as detected -- they won't
+			// be equal if
+			// overridden
+			if (result != null && result.equals(detectedCharsetName)) {
+				fEncodingMemento.setInvalidEncoding(detectedCharsetName);
+			}
+		}
+		catch (IllegalCharsetNameException e) {
+			// only set invalid, if result is same as detected -- they won't
+			// be equal if
+			// overridden
+			if (result != null && result.equals(detectedCharsetName)) {
+				fEncodingMemento.setInvalidEncoding(detectedCharsetName);
+			}
+		}
+		// give priority to java cononical name, if present
+		if (javaCharset != null) {
+			result = javaCharset.name();
+			// but still allow overrides
+			result = CodedIO.checkMappingOverrides(result);
+		}
+		return result;
+	}
+
+	private JSPHeadTokenizer getTokinizer() {
+		if (fTokenizer == null) {
+			fTokenizer = new JSPHeadTokenizer();
+		}
+		return fTokenizer;
+	}
+
+	private void handleSpecDefault() {
+		String encodingName;
+		encodingName = getSpecDefaultEncoding();
+		if (encodingName != null) {
+			// createEncodingMemento(encodingName,
+			// EncodingMemento.USED_CONTENT_TYPE_DEFAULT);
+			fEncodingMemento = new EncodingMemento();
+			fEncodingMemento.setJavaCharsetName(encodingName);
+			fEncodingMemento.setAppropriateDefault(encodingName);
+		}
+	}
+
+	private boolean isLegalString(String valueTokenType) {
+		boolean result = false;
+		if (valueTokenType != null) {
+			result = valueTokenType.equals(EncodingParserConstants.StringValue) || valueTokenType.equals(EncodingParserConstants.UnDelimitedStringValue) || valueTokenType.equals(EncodingParserConstants.InvalidTerminatedStringValue) || valueTokenType.equals(EncodingParserConstants.InvalidTermintatedUnDelimitedStringValue);
+		}
+		return result;
+	}
+
+
+	/**
+	 * This method should be exactly the same as what is in 
+	 * JSPHeadTokenizerTester
+	 * @param contentType
+	 */
+	private void parseContentTypeValue(String contentType) {
+		/*
+		 * Based partially on
+		 * org.eclipse.jst.jsp.core.internal.document.PageDirectiveAdapterImpl
+		 * .getMimeTypeFromContentTypeValue(String) , divides the full value
+		 * into segments according to ';', assumes the first specifies the
+		 * content type itself if it has no '=', and that the remainder are
+		 * parameters which may specify a charset
+		 */
+		
+		String cleanContentTypeValue = StringUtils.stripNonLetterDigits(contentType);
+		/* Break the mime header into the main value and its parameters, separated by ';' */
+		StringTokenizer tokenizer = new StringTokenizer(cleanContentTypeValue, ";"); //$NON-NLS-1$
+		int tLen = tokenizer.countTokens();
+		if (tLen == 0)
+			return;
+		String[] tokens = new String[tLen];
+		int j = 0;
+		while (tokenizer.hasMoreTokens()) {
+			tokens[j] = tokenizer.nextToken();
+			j++;
+		}
+		
+		int firstParameter = 0;
+		if (tokens[0].indexOf('=') == -1) {
+			/*
+			 * no equal sign in the first segment, so assume it indicates a
+			 * content type properly
+			 */
+			fContentType = tokens[0].trim();
+			firstParameter = 1;
+		}
+		/*
+		 * now handle parameters as name=value pairs, looking for "charset"
+		 * specifically
+		 */
+		Pattern equalPattern = Pattern.compile("\\s*=\\s*"); //$NON-NLS-1$
+		for (int i = firstParameter; i < tokens.length; i++) {
+			String[] pair = equalPattern.split(tokens[i]);
+			if (pair.length < 2)
+				continue;
+			if (pair[0].trim().equals("charset")) { //$NON-NLS-1$
+				fCharset = pair[1].trim();
+			}
+		}
+	}
+
+
+	/**
+	 * Looks for what ever encoding properties the tokenizer returns. Its the
+	 * responsibility of the tokenizer to stop when appropriate and not go too
+	 * far.
+	 */
+	private void parseHeader(JSPHeadTokenizer tokenizer) throws Exception {
+		fPageEncodingValue = null;
+		fCharset = null;
+
+		HeadParserToken token = null;
+		do {
+			// don't use 'get' here (at least until reset issue fixed)
+			token = tokenizer.getNextToken();
+			String tokenType = token.getType();
+			if (canHandleAsUnicodeStream(tokenType))
+				unicodeCase = true;
+			else {
+				if (tokenType == XMLHeadTokenizerConstants.XMLDelEncoding) {
+					if (tokenizer.hasMoreTokens()) {
+						HeadParserToken valueToken = tokenizer.getNextToken();
+						String valueTokenType = valueToken.getType();
+						if (isLegalString(valueTokenType)) {
+							fXMLDecEncodingName = valueToken.getText();
+						}
+					}
+				}
+				else if (tokenType == JSPHeadTokenizerConstants.PageEncoding) {
+					if (tokenizer.hasMoreTokens()) {
+						HeadParserToken valueToken = tokenizer.getNextToken();
+						String valueTokenType = valueToken.getType();
+						if (isLegalString(valueTokenType)) {
+							fPageEncodingValue = valueToken.getText();
+						}
+					}
+				}
+				else if (tokenType == JSPHeadTokenizerConstants.PageContentType) {
+					if (tokenizer.hasMoreTokens()) {
+						HeadParserToken valueToken = tokenizer.getNextToken();
+						String valueTokenType = valueToken.getType();
+						if (isLegalString(valueTokenType)) {
+							fContentTypeValue = valueToken.getText();
+						}
+					}
+				}
+				else if (tokenType == JSPHeadTokenizerConstants.PageLanguage) {
+					if (tokenizer.hasMoreTokens()) {
+						HeadParserToken valueToken = tokenizer.getNextToken();
+						String valueTokenType = valueToken.getType();
+						if (isLegalString(valueTokenType)) {
+							fLanguage = valueToken.getText();
+						}
+					}
+				}
+			}
+		}
+		while (tokenizer.hasMoreTokens());
+		if (fContentTypeValue != null) {
+			parseContentTypeValue(fContentTypeValue);
+		}
+		if (tokenizer.isXHTML()) {
+			fXHTML = true;
+		}
+		if (tokenizer.isWML() ) {
+			fWML = true;
+		}
+	}
+
+	private void parseInput() throws IOException {
+		JSPHeadTokenizer tokenizer = getTokinizer();
+		fReader.reset();
+		tokenizer.reset(fReader);
+		try {
+			parseHeader(tokenizer);
+			// unicode stream cases are created directly in parseHeader
+			if (!unicodeCase) {
+				String enc = getAppropriateEncoding();
+				if (enc != null && enc.length() > 0) {
+					createEncodingMemento(enc, EncodingMemento.FOUND_ENCODING_IN_CONTENT);
+				}
+			}
+		} catch (Exception e) {
+			Logger.log(Logger.ERROR_DEBUG, e.getMessage());
+		}
+	}
+
+	/**
+	 * 
+	 */
+	private void resetAll() {
+		fReader = null;
+		fHeaderParsed = false;
+		fEncodingMemento = null;
+		fCharset = null;
+		fContentTypeValue = null;
+		fPageEncodingValue = null;
+		fXMLDecEncodingName = null;
+		unicodeCase = false;
+		fXHTML=false;
+		fWML=false;
+	}
+
+
+
+	/**
+	 * convience method all subclasses can use (but not override)
+	 * 
+	 * @param detectedCharsetName
+	 * @param reason
+	 */
+	private void createEncodingMemento(String detectedCharsetName, String reason) {
+		createEncodingMemento(detectedCharsetName);
+	}
+
+	/**
+	 * convience method all subclasses can use (but not override)
+	 */
+	private void ensureInputSet() {
+		if (fReader == null) {
+			throw new IllegalStateException("input must be set before use"); //$NON-NLS-1$
+		}
+	}
+
+	public boolean isWML() throws IOException {
+		ensureInputSet();
+		if (!fHeaderParsed) {
+			parseInput();
+			// we keep track of if header's already been parse, so can make
+			// multiple 'get' calls, without causing reparsing.
+			fHeaderParsed = true;
+			// Note: there is a "hidden assumption" here that an empty
+			// string in content should be treated same as not present.
+		}
+		return fWML;
+	}
+
+	public boolean isXHTML() throws IOException {
+		ensureInputSet();
+		if (!fHeaderParsed) {
+			parseInput();
+			// we keep track of if header's already been parse, so can make
+			// multiple 'get' calls, without causing reparsing.
+			fHeaderParsed = true;
+			// Note: there is a "hidden assumption" here that an empty
+			// string in content should be treated same as not present.
+		}
+		return fXHTML;
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contenttype/Messages.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contenttype/Messages.java
new file mode 100644
index 0000000..bd8b462
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contenttype/Messages.java
@@ -0,0 +1,15 @@
+package org.eclipse.jst.jsp.core.internal.contenttype;

+

+import org.eclipse.osgi.util.NLS;

+

+public class Messages extends NLS {

+	private static final String BUNDLE_NAME = "org.eclipse.jst.jsp.core.internal.contenttype.messages"; //$NON-NLS-1$

+	public static String DeploymentDescriptorPropertyCache_1;

+	static {

+		// initialize resource bundle

+		NLS.initializeMessages(BUNDLE_NAME, Messages.class);

+	}

+

+	private Messages() {

+	}

+}

diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contenttype/messages.properties b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contenttype/messages.properties
new file mode 100644
index 0000000..269d3ad
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contenttype/messages.properties
@@ -0,0 +1 @@
+DeploymentDescriptorPropertyCache_1=Reading Deployment Descriptor

diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/document/DocumentFactoryForJSP.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/document/DocumentFactoryForJSP.java
new file mode 100644
index 0000000..fdf9a70
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/document/DocumentFactoryForJSP.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.document;
+
+import org.eclipse.core.filebuffers.IDocumentFactory;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jst.jsp.core.internal.parser.JSPSourceParser;
+import org.eclipse.jst.jsp.core.internal.provisional.JSP11Namespace;
+import org.eclipse.wst.sse.core.internal.document.StructuredDocumentFactory;
+import org.eclipse.wst.sse.core.internal.ltk.parser.RegionParser;
+import org.eclipse.wst.sse.core.internal.ltk.parser.TagMarker;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+
+
+public class DocumentFactoryForJSP implements IDocumentFactory {
+
+	public DocumentFactoryForJSP() {
+		super();
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.core.filebuffers.IDocumentFactory#createDocument()
+	 */
+	public IDocument createDocument() {
+		IStructuredDocument structuredDocument = StructuredDocumentFactory.getNewStructuredDocumentInstance(new JSPSourceParser());
+		return structuredDocument;
+	}
+
+	public RegionParser getParser() {
+		// remember, the Loader
+		// will need to finish initialization of parser
+		// based on "embedded content"
+		JSPSourceParser parser = new JSPSourceParser();
+		// add default nestable tag list
+		addNestablePrefix(parser, JSP11Namespace.JSP_TAG_PREFIX);
+		return parser;
+	}
+
+	private void addNestablePrefix(JSPSourceParser parser, String tagName) {
+		TagMarker bm = new TagMarker(tagName);
+		parser.addNestablePrefix(bm);
+	}
+
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/document/PageDirectiveAdapter.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/document/PageDirectiveAdapter.java
new file mode 100644
index 0000000..d2b321f
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/document/PageDirectiveAdapter.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.document;
+
+import org.eclipse.wst.sse.core.internal.ltk.modelhandler.EmbeddedTypeHandler;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapter;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapterFactory;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+
+/**
+ * Classes which implement this interface have two responsibilities. 
+ * One is to provide
+ * and embedded factory registry for JSP Aware INodeAdapter Factories
+ * to use. The other is to monitor page directives and if 
+ * a change in embedded type is is made, it will signal 
+ * the structuredModel that it needs to reinitialize itself.
+ */
+public interface PageDirectiveAdapter extends INodeAdapter {
+
+	public String getContentType();
+
+	public String getLanguage();
+
+	/**
+	 * This setter method should be called once, shortly after
+	 * initialization.
+	 */
+	void setEmbeddedType(EmbeddedTypeHandler handler);
+
+	EmbeddedTypeHandler getEmbeddedType();
+
+	/**
+	 * This method is to give this adapter a chance to use
+	 * the AdapterFactories from the EmbeddedTypeHandler
+	 * to adapt the node. Its to be used by JSPAwareAdapterFactories
+	 * to (potentially) adapt nodes from the embedded content type.
+	 */
+	INodeAdapter adapt(INodeNotifier notifier, Object type);
+
+	void addEmbeddedFactory(INodeAdapterFactory factory);
+
+	/**
+	 * Method setLanguage.
+	 * @param language
+	 */
+	void setLanguage(String language);
+
+	INodeNotifier getTarget();
+
+	public void release();
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/document/PageDirectiveAdapterFactory.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/document/PageDirectiveAdapterFactory.java
new file mode 100644
index 0000000..fc986da
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/document/PageDirectiveAdapterFactory.java
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.document;
+
+import org.eclipse.jst.jsp.core.internal.Assert;
+import org.eclipse.wst.sse.core.internal.provisional.AbstractAdapterFactory;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapter;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapterFactory;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.w3c.dom.Node;
+
+/**
+ * This class adapts document 
+ * with the an instance of PageDirectiveAdapter
+ */
+public class PageDirectiveAdapterFactory extends AbstractAdapterFactory implements INodeAdapterFactory {
+
+
+	private PageDirectiveAdapter pageDirectiveAdapterInstance = null;
+
+	/**
+	 * Constructor for PageDirectiveAdapterFactory.
+	 * Note: its important not to be a singleton, since
+	 * this factory needs to track its adapter(s) and release
+	 * them when they are released.
+	 * 
+	 * @param adapterKey
+	 * @param registerAdapters
+	 */
+	protected PageDirectiveAdapterFactory(Object adapterKey, boolean registerAdapters) {
+		super(adapterKey, registerAdapters);
+	}
+
+	/**
+	 * The no argument constructor assumes its a 
+	 * Factory for PageDirectiveAdapter
+	 */
+	public PageDirectiveAdapterFactory() {
+		this(PageDirectiveAdapter.class, true);
+	}
+
+	protected INodeAdapter createAdapter(INodeNotifier target) {
+		PageDirectiveAdapter result = null;
+		if (target instanceof IDOMNode) {
+			IDOMNode node = (IDOMNode) target;
+			if (node.getNodeType() == Node.DOCUMENT_NODE) {
+				result = getAdapterInstance(target);
+			}
+
+		}
+		return result;
+	}
+
+	public void release() {
+		if (pageDirectiveAdapterInstance != null) {
+			pageDirectiveAdapterInstance.release();
+		}
+	}
+
+	/**
+	 * We assume this is only called for 'document' target
+	 */
+	protected PageDirectiveAdapter getAdapterInstance(INodeNotifier target) {
+		// if our instance already exists with a different
+		// target, then, somehow, the document node must 
+		// have changed for a model, so we should release 
+		// old adapter and create new one for new document 
+		// node. This is probably a programming error.
+		if (pageDirectiveAdapterInstance != null) {
+			if (target != pageDirectiveAdapterInstance.getTarget()) {
+				release();
+				pageDirectiveAdapterInstance = new PageDirectiveAdapterImpl(target);
+			}
+			// else return the one we have
+		}
+		else {
+			// if is equal to null, create a new one
+			pageDirectiveAdapterInstance = new PageDirectiveAdapterImpl(target);
+		}
+		Assert.isNotNull(pageDirectiveAdapterInstance, "pageDipageDirectiveAdapterInstance was null"); //$NON-NLS-1$
+		return pageDirectiveAdapterInstance;
+	}
+
+	public INodeAdapterFactory copy() {
+
+		return new PageDirectiveAdapterFactory(getAdapterKey(), isShouldRegisterAdapter());
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/document/PageDirectiveAdapterImpl.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/document/PageDirectiveAdapterImpl.java
new file mode 100644
index 0000000..4c0cc87
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/document/PageDirectiveAdapterImpl.java
@@ -0,0 +1,712 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.document;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.content.IContentDescription;
+import org.eclipse.core.runtime.content.IContentType;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentExtension3;
+import org.eclipse.jface.text.IDocumentPartitioner;
+import org.eclipse.jst.jsp.core.internal.Logger;
+import org.eclipse.jst.jsp.core.internal.contentproperties.JSPFContentProperties;
+import org.eclipse.jst.jsp.core.internal.modelhandler.EmbeddedTypeStateData;
+import org.eclipse.jst.jsp.core.internal.provisional.contenttype.ContentTypeIdForJSP;
+import org.eclipse.jst.jsp.core.internal.provisional.contenttype.IContentDescriptionForJSP;
+import org.eclipse.jst.jsp.core.internal.text.StructuredTextPartitionerForJSP;
+import org.eclipse.wst.html.core.internal.provisional.contenttype.ContentTypeFamilyForHTML;
+import org.eclipse.wst.sse.core.internal.document.DocumentReader;
+import org.eclipse.wst.sse.core.internal.ltk.modelhandler.EmbeddedTypeHandler;
+import org.eclipse.wst.sse.core.internal.modelhandler.EmbeddedTypeRegistry;
+import org.eclipse.wst.sse.core.internal.modelhandler.EmbeddedTypeRegistryImpl;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapter;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapterFactory;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredPartitioning;
+import org.eclipse.wst.sse.core.internal.util.Debug;
+import org.eclipse.wst.sse.core.utils.StringUtils;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+
+import com.ibm.icu.util.StringTokenizer;
+
+/**
+ * This class has the responsibility to provide an embedded factory registry
+ * for JSP Aware INodeAdapter Factories to use.
+ * 
+ * Typically, the embedded type is to be considered a feature of the document,
+ * so JSP Aware AdpaterFactories should call
+ * getAdapter(PageDirectiveAdapter.class) directoy on the document (or owning
+ * document) node.
+ */
+public class PageDirectiveAdapterImpl implements PageDirectiveAdapter {
+
+	protected static final String STR_CHARSET = "charset"; //$NON-NLS-1$
+	private final static Object adapterType = PageDirectiveAdapter.class;
+	private IStructuredModel model;
+	protected final String[] JAVASCRIPT_LANGUAGE_KEYS = new String[]{"javascript", "javascript1.0", "javascript1.1_3", "javascript1.2", "javascript1.3", "javascript1.4", "javascript1.5", "javascript1.6", "jscript", "sashscript"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ //$NON-NLS-9$ //$NON-NLS-10$
+	protected final String[] JAVA_LANGUAGE_KEYS = new String[]{"java"}; //$NON-NLS-1$
+
+	/**
+	 * Constructor for PageDirectiveAdapterImpl.
+	 */
+	public PageDirectiveAdapterImpl(INodeNotifier target) {
+		super();
+		notifierAtCreation = target;
+		// we need to remember our instance of model,
+		// in case we need to "signal" a re-init needed.
+		if (target instanceof IDOMNode) {
+			IDOMNode node = (IDOMNode) target;
+			model = node.getModel();
+		}
+
+	}
+
+	/**
+	 * parses the full contentType value into its two parts the contentType,
+	 * and the charset, if present. Note: this method is a lightly modified
+	 * version of a method in AbstractHeadParser. There, we're mostly
+	 * interested in the charset part of contentTypeValue. Here, we're mostly
+	 * interested in the mimeType part.
+	 */
+	private String getMimeTypeFromContentTypeValue(String contentTypeValue) {
+		if (contentTypeValue == null)
+			return null;
+		String cleanContentTypeValue = StringUtils.stripNonLetterDigits(contentTypeValue);
+		StringTokenizer tokenizer = new StringTokenizer(cleanContentTypeValue, ";= \t\n\r\f"); //$NON-NLS-1$
+		int tLen = tokenizer.countTokens();
+		// if contains encoding should have three tokens, the mimetype, the
+		// word 'charset', and the encoding value
+		String[] tokens = new String[tLen];
+		int j = 0;
+		while (tokenizer.hasMoreTokens()) {
+			tokens[j] = tokenizer.nextToken();
+			j++;
+		}
+		// 
+		// Following is the common form for target expression
+		// <META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+		// But apparrently is also valid without the content type there,
+		// just the charset, as follows:
+		// <META http-equiv="Content-Type" content="charset=UTF-8">
+		// So we'll loop through tokens and key off of 'charset'
+
+		int charsetPos = -1;
+		for (int i = 0; i < tokens.length; i++) {
+			if (tokens[i].equalsIgnoreCase(STR_CHARSET)) {
+				charsetPos = i;
+				break;
+			}
+		}
+		// String charset = null;
+		String contentType = null;
+		if (charsetPos > -1) {
+			// case where charset was present
+			// int charsetValuePos = charsetPos + 1;
+			// if (charsetValuePos < tokens.length) {
+			// charset = tokens[charsetValuePos];
+			// }
+			int contentTypeValuePos = charsetPos - 1;
+			if (contentTypeValuePos > -1) {
+				contentType = tokens[contentTypeValuePos];
+			}
+		}
+		else {
+			// charset was not present, so if there's
+			// a value, we assume its the contentType value
+			if (tokens.length > 0) {
+				contentType = tokens[0];
+			}
+		}
+		return contentType;
+	}
+
+	private EmbeddedTypeHandler embeddedTypeHandler;
+	private List embeddedFactoryRegistry = new ArrayList();
+	private String cachedLanguage;
+	private String cachedContentType;
+	private INodeNotifier notifierAtCreation;
+	private String elIgnored = null;
+
+	private int firstLanguagePosition = -1;
+	private int firstContentTypePosition = -1;
+
+	/*
+	 * @see INodeAdapter#isAdapterForType(Object)
+	 */
+	public boolean isAdapterForType(Object type) {
+		return (type == adapterType);
+	}
+
+	/*
+	 * @see INodeAdapter#notifyChanged(INodeNotifier, int, Object, Object,
+	 *      Object, int)
+	 */
+	public void notifyChanged(INodeNotifier notifier, int eventType, Object changedFeature, Object oldValue, Object newValue, int pos) {
+	}
+
+	public void setEmbeddedType(EmbeddedTypeHandler handler) {
+		// if really the same handler, no need for further processing
+		if (embeddedTypeHandler == handler) {
+			return;
+		}
+		// then one exists, and the new one is truely different, so we need to
+		// release and remove current factories
+		if (embeddedTypeHandler != null) {
+			Iterator list = embeddedFactoryRegistry.iterator();
+			while (list.hasNext()) {
+				INodeAdapterFactory factory = (INodeAdapterFactory) list.next();
+				factory.release();
+			}
+
+			embeddedFactoryRegistry.clear();
+		}
+
+		embeddedTypeHandler = handler;
+		// when the handler is set, "transfer" its factories to our own list.
+		// note: our own list may also be added to else where, such as on
+		// "editor side".
+		if (embeddedTypeHandler != null) {
+			Iterator iterator = embeddedTypeHandler.getAdapterFactories().iterator();
+			while (iterator.hasNext()) {
+				INodeAdapterFactory factory = (INodeAdapterFactory) iterator.next();
+				embeddedFactoryRegistry.add(factory);
+			}
+		}
+	}
+
+	/**
+	 * @see PageDirectiveAdapter#adapt(INodeNotifier, Object)
+	 */
+	public INodeAdapter adapt(INodeNotifier notifier, Object type) {
+		INodeAdapter result = null;
+		// if embeddedContentType hasn't been set,
+		// then we can not adapt it.
+		if (embeddedTypeHandler != null) {
+			if (embeddedFactoryRegistry != null) {
+				Iterator iterator = embeddedFactoryRegistry.iterator();
+				INodeAdapterFactory factory = null;
+				while (iterator.hasNext()) {
+					factory = (INodeAdapterFactory) iterator.next();
+					if (factory.isFactoryForType(type)) {
+						result = factory.adapt(notifier);
+						break;
+					}
+				}
+			}
+		}
+		return result;
+
+	}
+
+	/**
+	 * @see PageDirectiveAdapter#getEmbeddedType()
+	 */
+	public EmbeddedTypeHandler getEmbeddedType() {
+		if (embeddedTypeHandler == null) {
+			embeddedTypeHandler = getDefaultEmbeddedType();
+		}
+		return embeddedTypeHandler;
+	}
+
+	public void addEmbeddedFactory(INodeAdapterFactory factory) {
+		// should we check if already exists in list?
+		embeddedFactoryRegistry.add(factory);
+	}
+
+	// /**
+	// * Used by PageDirectiveWatchers to signal that some important attribute
+	// has changed, and
+	// * any cached values should be re-calcuated
+	// */
+	// void changed() {
+	// // we won't actually check if change is needed, if the model state is
+	// already changing.
+	// if (!model.isReinitializationNeeded()) {
+	// // go through our list of page watcher adapters, and updates the
+	// attributes
+	// // we're interested in, if and only if they are the earliest occurance
+	// in the resource
+	// String potentialContentType = null;
+	// String potentialLanguage = null;
+	// int contentTypePosition = -1;
+	// int languagePosition = -1;
+	// Iterator iterator = pageDirectiveWatchers.iterator();
+	// while (iterator.hasNext()) {
+	// PageDirectiveWatcher pdWatcher = (PageDirectiveWatcher)
+	// iterator.next();
+	// String contentType = pdWatcher.getContentType();
+	// String language = pdWatcher.getLanguage();
+	// int offset = pdWatcher.getOffset();
+	// if (potentialContentType == null || (hasValue(contentType) && (offset <
+	// contentTypePosition))) {
+	// potentialContentType = contentType;
+	// contentTypePosition = offset;
+	// }
+	// }
+	// // now we have the best candiates for cached values, let's see if
+	// they've really changed from
+	// // what we had. If so, note we go through the setters so side effects
+	// can take place there.
+	// potentialContentType =
+	// getMimeTypeFromContentTypeValue(potentialContentType);
+	// if (potentialContentType == null || potentialContentType.length() == 0)
+	// {
+	// //potentialContentType = getDefaultContentType();
+	// } else {
+	// setCachedContentType(potentialContentType);
+	// }
+	//
+	// if (potentialLanguage != null && hasValue(potentialLanguage)) {
+	// setCachedLanguage(potentialLanguage);
+	// }
+	// }
+	// }
+	void changedContentType(int elementOffset, String newValue) {
+		// only need to process if this new value is
+		// earlier in the file than our current value
+		if (firstContentTypePosition == -1 || elementOffset <= firstContentTypePosition) {
+			// dw_TODO: update embedded partitioner in JSP document
+			// partitioner
+			// nsd_TODO: update embedded partitioner in JSP document
+			// partitioner
+
+			// no need to change current value, if we're told some
+			// earlier value is null or blank (sounds like an error, anyway)
+			if (hasValue(newValue)) {
+				firstContentTypePosition = elementOffset;
+				String potentialContentType = getMimeTypeFromContentTypeValue(newValue);
+				// only do the set processing if different
+				// from what it already is
+				// if (!potentialContentType.equalsIgnoreCase(cachedLanguage))
+				// {
+				setCachedContentType(potentialContentType);
+				// }
+			}
+		}
+	}
+
+	/**
+	 * Used by PageDirectiveWatchers to signal that some important attribute
+	 * has changed, and any cached values should be re-calcuated
+	 */
+	void changedLanguage(int elementOffset, String newValue) {
+		// only need to process if this new value is
+		// earlier in the file than our current value
+		// has to be less than or equal to, in case our previous earliest one,
+		// is itself changing!
+		if (firstLanguagePosition == -1 || elementOffset <= firstLanguagePosition) {
+
+			// no need to change current value, if we're told some
+			// earlier value is null or blank (sounds like an error, anyway)
+			if (hasValue(newValue)) {
+				firstLanguagePosition = elementOffset;
+				// only do the set processing if different
+				// from what it already is
+				if (!newValue.equalsIgnoreCase(cachedLanguage)) {
+					setCachedLanguage(newValue);
+				}
+			}
+
+			// dw_TODO: set language in document partitioner
+			// nsd_TODO: set language in document partitioner
+		}
+	}
+
+	/**
+	 * Used by PageDirectiveWatchers to signal that some important attribute
+	 * has changed, and any cached values should be re-calcuated
+	 */
+	void changedPageEncoding(int elementOffset, String newValue) {
+
+		// we don't currently track active value, since
+		// just need during read and write (where its
+		// calculated. We will need in future, to
+		// acurately clone a model and to display
+		// "current encoding" to user in status bar.
+	}
+
+	/**
+	 * Method hasValue.
+	 * 
+	 * @param contentType
+	 * @return boolean
+	 */
+	private boolean hasValue(String value) {
+		if (value != null && value.length() > 0)
+			return true;
+		else
+			return false;
+	}
+
+	/**
+	 * Returns the cachedContentType.
+	 * 
+	 * @return String
+	 */
+	public String getContentType() {
+		if (cachedContentType == null) {
+			cachedContentType = getDefaultContentType();
+		}
+		return cachedContentType;
+	}
+
+	/**
+	 * Method getDefaultContentType.
+	 * 
+	 * @return String
+	 */
+	private String getDefaultContentType() {
+		String type = null;
+		IFile file = getFile(model);
+		if (file != null) {
+			type = JSPFContentProperties.getProperty(JSPFContentProperties.JSPCONTENTTYPE, file, true);
+		}
+		// BUG136468
+		if (type == null)
+			type = "text/html"; //$NON-NLS-1$
+		return type;
+	}
+
+	/**
+	 * Returns the cachedLanguage.
+	 * 
+	 * @return String
+	 */
+	public String getLanguage() {
+		if (cachedLanguage == null)
+			cachedLanguage = getDefaultLanguage();
+		return cachedLanguage;
+	}
+
+	/**
+	 * Method getDefaultLanguage.
+	 * 
+	 * @return String
+	 */
+	private String getDefaultLanguage() {
+		String language = null;
+		IFile file = getFile(model);
+		if (file != null) {
+			language = JSPFContentProperties.getProperty(JSPFContentProperties.JSPLANGUAGE, file, true);
+		}
+		// BUG136468
+		if (language == null)
+			language = "java"; //$NON-NLS-1$
+		return language;
+	}
+
+	/**
+	 * Sets the cachedContentType.
+	 * 
+	 * @param cachedContentType
+	 *            The cachedContentType to set
+	 */
+	public void setCachedContentType(String newContentType) {
+		/*
+		 * if the passed in value is the same as existing, there's nothing to
+		 * do. if its different, then we need to change the contentHandler as
+		 * well and, more to the point, signal a re-initializtation is needed.
+		 * 
+		 * Note: if the value we're getting set to does not have a handler in
+		 * the registry, we'll actually not set it to null or anything, we'll
+		 * just continue on with the one we have. This is pretty important to
+		 * avoid re-initializing on every key stroke if someone is typing in a
+		 * new content type, but haven't yet finished the whole "word".
+		 * However, if an contentType is not recognized, the registry returns
+		 * the one for XML.
+		 */
+		
+		/* set the actual value first, the rest is "side effect" */
+		this.cachedContentType = newContentType;
+
+		/* see if we need to update embedded handler */
+
+		/*
+		 * If the document is a type of XHTML, we do not use the page
+		 * directive's contentType to determine the embedded type ... its
+		 * XHTML! ... and, eventually, the DOCTYPE adapter should determine
+		 * if/when it needs to change.
+		 */
+
+		/* just safety check, can be removed later, early in release cycle */
+		if (model == null) {
+			// throw IllegalStateException("model should never be null in
+			// PageDirective Adapter");
+			Logger.log(Logger.ERROR, "model should never be null in PageDirective Adapter");
+			return;
+		}
+
+		EmbeddedTypeHandler potentialNewandler = null;
+		IContentDescription contentDescription = getContentDescription(model.getStructuredDocument());
+		Object prop = contentDescription.getProperty(IContentDescriptionForJSP.CONTENT_FAMILY_ATTRIBUTE);
+		if (prop != null) {
+			if (ContentTypeFamilyForHTML.HTML_FAMILY.equals(prop)) {
+				potentialNewandler = EmbeddedTypeRegistryImpl.getInstance().getTypeFor("text/html");
+			}
+		}
+
+		if (potentialNewandler == null) {
+			/*
+			 * getHandler should always return something (never null), based
+			 * on the rules in the factory.
+			 */
+			potentialNewandler = getHandlerFor(this.cachedContentType);
+		}
+		/*
+		 * we do this check for re-init here, instead of in setEmbeddedType,
+		 * since setEmbeddedType is called during the normal initializtion
+		 * process, when re-init is not needed (since there is no content)
+		 */
+		if (embeddedTypeHandler == null) {
+			setEmbeddedType(potentialNewandler);
+		}
+		else if (potentialNewandler != null && embeddedTypeHandler != potentialNewandler) {
+			/*
+			 * changing this embedded handler here may be in the middle of a
+			 * notify loop. That's why we set that "it's needed". Then the
+			 * model decides when its "safe" to actually do the re-init.
+			 * 
+			 * be sure to hold oldHandler in temp var or else setEmbeddedType
+			 * will "reset" it before modelReinitNeeded(oldHandler, handler)
+			 * is called
+			 * 
+			 */
+			EmbeddedTypeHandler oldHandler = embeddedTypeHandler;
+			setEmbeddedType(potentialNewandler);
+			modelReinitNeeded(oldHandler, potentialNewandler);
+		}
+
+	}
+
+	/**
+	 * This method is used to re-init based on embeddedTypeHandler changing.
+	 * It is given priority over the language change, since there its more
+	 * important to have old and new handlers's in the stateData field.
+	 */
+	private void modelReinitNeeded(EmbeddedTypeHandler oldHandler, EmbeddedTypeHandler newHandler) {
+		if (model.isReinitializationNeeded()) {
+			System.out.println("already being initialized"); //$NON-NLS-1$
+		}
+
+		try {
+			model.aboutToChangeModel();
+			model.setReinitializeStateData(new EmbeddedTypeStateData(oldHandler, newHandler));
+			model.setReinitializeNeeded(true);
+		}
+		finally {
+			model.changedModel();
+		}
+	}
+
+	/**
+	 * Method modelReinitNeeded.
+	 */
+	private void modelReinitNeeded(String oldlanguage, String newLanguage) {
+		// bit of a short cut for now .... we dont' need language at the
+		// moment,
+		// but should set the state data
+		if (model.isReinitializationNeeded()) {
+			if (Debug.displayWarnings) {
+				System.out.println("already being initialized"); //$NON-NLS-1$
+			}
+		}
+		else {
+			try {
+				// if already being re-initialized, we don't want to
+				// reset the data in the stateData field.
+				model.aboutToChangeModel();
+				model.setReinitializeStateData(newLanguage);
+				model.setReinitializeNeeded(true);
+			}
+			finally {
+				model.changedModel();
+			}
+		}
+	}
+
+	public void setCachedLanguage(String newLanguage) {
+		if (cachedLanguage != null && languageStateChanged(cachedLanguage, newLanguage)) {
+			/*
+			 * a complete re-init overkill in current system, since really
+			 * just need for the line style providers, BUT, a change in
+			 * language could effect other things, and we don't expect to
+			 * happen often so a little overkill isn't too bad. The deep
+			 * problem is that there is no way to get at the "edit side"
+			 * adpapters specifically here in model class. we have to do the
+			 * model changed sequence to get the screen to update. do not
+			 * signal again, if signaled once (the reinit state data will be
+			 * wrong. (this needs to be improved in future)
+			 */
+			if (!model.isReinitializationNeeded()) {
+				modelReinitNeeded(cachedLanguage, newLanguage);
+			}
+		}
+		setLanguage(newLanguage);
+	}
+
+	/**
+	 * This is public access method, used especially from loader, for JSP
+	 * Fragment support.
+	 */
+	public void setLanguage(String newLanguage) {
+		this.cachedLanguage = newLanguage;
+		IDocumentPartitioner partitioner = ((IDocumentExtension3) model.getStructuredDocument()).getDocumentPartitioner(IStructuredPartitioning.DEFAULT_STRUCTURED_PARTITIONING);
+		if (partitioner instanceof StructuredTextPartitionerForJSP) {
+			((StructuredTextPartitionerForJSP) partitioner).setLanguage(newLanguage);
+		}
+	}
+
+	/**
+	 * Method languageStateChange.
+	 * 
+	 * @param cachedLanguage
+	 * @param newLanguage
+	 * @return boolean
+	 */
+	private boolean languageStateChanged(String cachedLanguage, String newLanguage) {
+		boolean result = false; // languages are equal, then no change in
+		// state
+		if (!cachedLanguage.equalsIgnoreCase(newLanguage)) {
+			boolean oldLanguageKnown = languageKnown(cachedLanguage);
+			boolean newLanguageKnown = languageKnown(newLanguage);
+			result = newLanguageKnown || (!newLanguageKnown && oldLanguageKnown);
+		}
+		return result;
+	}
+
+	/**
+	 * Method languageKnown.
+	 * 
+	 * @param cachedLanguage
+	 * @return boolean
+	 */
+	private boolean languageKnown(String language) {
+		return (StringUtils.contains(JAVA_LANGUAGE_KEYS, language, false) || StringUtils.contains(JAVASCRIPT_LANGUAGE_KEYS, language, false));
+	}
+
+	private IFile getFile(IStructuredModel model) {
+		String location = model.getBaseLocation();
+		if (location != null) {
+			IPath path = new Path(location);
+			if (path.segmentCount() > 1) {
+				return ResourcesPlugin.getWorkspace().getRoot().getFile(path);
+			}
+		}
+		return null;
+	}
+
+	private EmbeddedTypeHandler getHandlerFor(String contentType) {
+		EmbeddedTypeRegistry reg = getEmbeddedContentTypeRegistry();
+		EmbeddedTypeHandler handler = null;
+		if (reg != null)
+			handler = reg.getTypeFor(contentType);
+		return handler;
+	}
+
+	/**
+	 * Gets the embeddedContentTypeRegistry.
+	 * 
+	 * @return Returns a EmbeddedContentTypeRegistry
+	 */
+	private EmbeddedTypeRegistry getEmbeddedContentTypeRegistry() {
+		return EmbeddedTypeRegistryImpl.getInstance();
+	}
+
+	/**
+	 * For JSP files, text/html is the default content type. This may want
+	 * this different for types like jsv (jsp for voice xml) For now, hard
+	 * code to new instance. In future, should get instance from registry.
+	 * 
+	 * Specification cites HTML as the default contentType.
+	 */
+	protected EmbeddedTypeHandler getDefaultEmbeddedType() {
+		return getHandlerFor(getDefaultContentType());
+	}
+
+	public INodeNotifier getTarget() {
+		return notifierAtCreation;
+	}
+
+	public void release() {
+		if (embeddedTypeHandler != null) {
+			if (embeddedFactoryRegistry != null) {
+				Iterator iterator = embeddedFactoryRegistry.iterator();
+				INodeAdapterFactory factory = null;
+				while (iterator.hasNext()) {
+					factory = (INodeAdapterFactory) iterator.next();
+					factory.release();
+				}
+			}
+			// pa_TODO: possibly need to release here...
+			// or "uninitializeFactoryRegistry"
+			// initializeFactoryRegistry was called from JSPModelLoader
+			embeddedTypeHandler = null;
+		}
+	}
+
+	private IContentDescription getContentDescription(IDocument doc) {
+		if (doc == null)
+			return null;
+		DocumentReader in = new DocumentReader(doc);
+		return getContentDescription(in);
+	}
+
+	/**
+	 * Returns content description for an input stream Assumes it's JSP
+	 * content. Closes the input stream when finished.
+	 * 
+	 * @param in
+	 * @return the IContentDescription for in, or null if in is null
+	 */
+	private IContentDescription getContentDescription(Reader in) {
+
+		if (in == null)
+			return null;
+
+		IContentDescription desc = null;
+		try {
+
+			IContentType contentTypeJSP = Platform.getContentTypeManager().getContentType(ContentTypeIdForJSP.ContentTypeID_JSP);
+			desc = contentTypeJSP.getDescriptionFor(in, IContentDescription.ALL);
+		}
+		catch (IOException e) {
+			Logger.logException(e);
+		}
+		finally {
+			try {
+				in.close();
+			}
+			catch (IOException e) {
+				Logger.logException(e);
+			}
+		}
+		return desc;
+	}
+
+	public String getElIgnored() {
+		return elIgnored;
+	}
+
+	public void setElIgnored(String ignored) {
+		elIgnored = ignored;
+	}
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/document/PageDirectiveWatcher.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/document/PageDirectiveWatcher.java
new file mode 100644
index 0000000..b443a8a
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/document/PageDirectiveWatcher.java
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.document;
+
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapter;
+
+interface PageDirectiveWatcher extends INodeAdapter {
+
+	String getContentType();
+
+	String getLanguage();
+
+	int getOffset();
+
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/document/PageDirectiveWatcherFactory.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/document/PageDirectiveWatcherFactory.java
new file mode 100644
index 0000000..1fbb07a
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/document/PageDirectiveWatcherFactory.java
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.document;
+
+import org.eclipse.wst.sse.core.internal.PropagatingAdapterFactory;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapter;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapterFactory;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.xml.core.internal.propagate.PropagatingAdapterFactoryImpl;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
+import org.w3c.dom.Node;
+
+public class PageDirectiveWatcherFactory extends PropagatingAdapterFactoryImpl implements PropagatingAdapterFactory {
+
+	/**
+	 * Constructor for PageDirectiveWatcherFactory.
+	 */
+	public PageDirectiveWatcherFactory() {
+		this(PageDirectiveWatcher.class, true);
+	}
+
+	/**
+	 * Constructor for PageDirectiveWatcherFactory.
+	 * 
+	 * @param adapterKey
+	 * @param registerAdapters
+	 */
+	public PageDirectiveWatcherFactory(Object adapterKey, boolean registerAdapters) {
+		super(adapterKey, registerAdapters);
+	}
+
+	protected INodeAdapter createAdapter(INodeNotifier target) {
+		PageDirectiveWatcher result = null;
+		if (target instanceof IDOMElement) {
+			IDOMElement xmlElement = (IDOMElement) target;
+			if (xmlElement.getNodeType() == Node.ELEMENT_NODE) {
+				String nodeName = xmlElement.getNodeName();
+				if (nodeName.equals("jsp:directive.page")) { //$NON-NLS-1$
+					result = new PageDirectiveWatcherImpl(xmlElement);
+				}
+
+			}
+		}
+		return result;
+
+	}
+
+public INodeAdapterFactory copy() {
+		return new PageDirectiveWatcherFactory(getAdapterKey(), isShouldRegisterAdapter());
+	}}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/document/PageDirectiveWatcherImpl.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/document/PageDirectiveWatcherImpl.java
new file mode 100644
index 0000000..be4ce58
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/document/PageDirectiveWatcherImpl.java
@@ -0,0 +1,112 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.document;
+
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
+import org.eclipse.wst.xml.core.internal.document.AttrImpl;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+
+
+
+/** 
+ * The responsibility of this class is to monitor page directives and if 
+ * a change in embedded type is is made, it will signal 
+ * the structuredModel that it needs to reinitialize itself.
+ */
+class PageDirectiveWatcherImpl implements PageDirectiveWatcher {
+
+	private static Object adapterType = PageDirectiveWatcher.class;
+	IDOMElement targetElement;
+
+	/**
+	 * Constructor for PageDirectiveWatcherImpl.
+	 */
+	public PageDirectiveWatcherImpl(IDOMElement target) {
+		super();
+		targetElement = target;
+		if (target.hasAttribute("contentType")) { //$NON-NLS-1$
+			String contentTypeValue = target.getAttribute("contentType"); //$NON-NLS-1$
+			// using concrete class below, since "changed" is something of an internal method
+			PageDirectiveAdapterImpl pageDirectiveAdapter = (PageDirectiveAdapterImpl) ((IDOMDocument) targetElement.getOwnerDocument()).getAdapterFor(PageDirectiveAdapter.class);
+			pageDirectiveAdapter.changedContentType(((IndexedRegion) targetElement).getStartOffset(), contentTypeValue);
+		}
+		if (target.hasAttribute("language")) { //$NON-NLS-1$
+			String languageValue = target.getAttribute("language"); //$NON-NLS-1$
+			// using concrete class below, since "changed" is something of an internal method
+			PageDirectiveAdapterImpl pageDirectiveAdapter = (PageDirectiveAdapterImpl) ((IDOMDocument) targetElement.getOwnerDocument()).getAdapterFor(PageDirectiveAdapter.class);
+			pageDirectiveAdapter.changedLanguage(((IndexedRegion) targetElement).getStartOffset(), languageValue);
+		}
+		if (target.hasAttribute("isELIgnored")) { //$NON-NLS-1$
+			String elIgnored = target.getAttribute("isELIgnored"); //$NON-NLS-1$
+			PageDirectiveAdapterImpl pageDirectiveAdapter = (PageDirectiveAdapterImpl) ((IDOMDocument) targetElement.getOwnerDocument()).getAdapterFor(PageDirectiveAdapter.class);
+			pageDirectiveAdapter.setElIgnored(elIgnored);
+		}
+
+	}
+
+	public boolean isAdapterForType(Object type) {
+		return (type == adapterType);
+	}
+
+	public void notifyChanged(INodeNotifier notifier, int eventType, Object changedFeature, Object oldValue, Object newValue, int pos) {
+		// we should only be added to page directives, so if we see a page directive
+		// change, we need to check its attributes, and notify the PageDirectiveAdapter when 
+		// certain ones chane, so it can make its "centralized" decisions.
+		if (notifier instanceof IDOMNode) {
+
+			switch (eventType) {
+				case INodeNotifier.CHANGE :
+					if (changedFeature instanceof AttrImpl) {
+						AttrImpl attribute = (AttrImpl) changedFeature;
+						String name = attribute.getName();
+						if (name.equals("contentType")) { //$NON-NLS-1$
+							// using concrete class below, since "changed" is something of an internal method
+							PageDirectiveAdapterImpl pageDirectiveAdapter = (PageDirectiveAdapterImpl) ((IDOMDocument) targetElement.getOwnerDocument()).getAdapterFor(PageDirectiveAdapter.class);
+							pageDirectiveAdapter.changedContentType(((IndexedRegion) targetElement).getStartOffset(), (String) newValue);
+						}
+						if (name.equals("language")) { //$NON-NLS-1$ //$NON-NLS-2$
+							// using concrete class below, since "changed" is something of an internal method
+							PageDirectiveAdapterImpl pageDirectiveAdapter = (PageDirectiveAdapterImpl) ((IDOMDocument) targetElement.getOwnerDocument()).getAdapterFor(PageDirectiveAdapter.class);
+							pageDirectiveAdapter.changedLanguage(((IndexedRegion) targetElement).getStartOffset(), (String) newValue);
+						}
+					}
+
+					break;
+				case INodeNotifier.REMOVE :
+					//System.out.println("removed"+new Date().toString());
+					break;
+
+
+				default :
+					break;
+			}
+		}
+
+	}
+
+	public String getContentType() {
+		String contentTypeValue = targetElement.getAttribute("contentType"); //$NON-NLS-1$
+		return contentTypeValue;
+	}
+
+	public String getLanguage() {
+		String languageValue = targetElement.getAttribute("language"); //$NON-NLS-1$
+		return languageValue;
+	}
+
+	public int getOffset() {
+		return targetElement.getStartOffset();
+	}
+
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/domdocument/AttrImplForJSP.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/domdocument/AttrImplForJSP.java
new file mode 100644
index 0000000..ff30c55
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/domdocument/AttrImplForJSP.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+
+package org.eclipse.jst.jsp.core.internal.domdocument;
+
+import org.eclipse.jst.jsp.core.internal.regions.DOMJSPRegionContexts;
+import org.eclipse.wst.xml.core.internal.document.AttrImpl;
+import org.w3c.dom.Document;
+
+public class AttrImplForJSP extends AttrImpl {
+
+	protected boolean isNestedLanguageOpening(String regionType) {
+		boolean result = regionType == DOMJSPRegionContexts.JSP_SCRIPTLET_OPEN || regionType == DOMJSPRegionContexts.JSP_EXPRESSION_OPEN || regionType == DOMJSPRegionContexts.JSP_DECLARATION_OPEN || regionType == DOMJSPRegionContexts.JSP_DIRECTIVE_OPEN;
+		return result;
+	}
+	protected void setOwnerDocument(Document ownerDocument) {
+		super.setOwnerDocument(ownerDocument);
+	}
+	protected void setName(String name) {
+		super.setName(name);
+	}
+	protected void setNamespaceURI(String namespaceURI) {
+		super.setNamespaceURI(namespaceURI);
+	}
+
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/domdocument/CommentImplForJSP.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/domdocument/CommentImplForJSP.java
new file mode 100644
index 0000000..c9ccc58
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/domdocument/CommentImplForJSP.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+
+package org.eclipse.jst.jsp.core.internal.domdocument;
+
+import org.eclipse.jst.jsp.core.internal.regions.DOMJSPRegionContexts;
+import org.eclipse.wst.xml.core.internal.document.CommentImpl;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+/**
+ * CommentImplForJSP
+ */
+public class CommentImplForJSP extends CommentImpl {
+	protected CommentImplForJSP() {
+		super();
+	}
+
+	protected CommentImplForJSP(CommentImpl that) {
+		super(that);
+	}
+
+	protected boolean isNestedCommentClose(String regionType) {
+		boolean result = regionType == DOMJSPRegionContexts.JSP_COMMENT_CLOSE;
+		return result;
+	}
+
+	protected boolean isNestedCommentOpenClose(String regionType) {
+		boolean result = regionType == DOMJSPRegionContexts.JSP_COMMENT_OPEN || regionType == DOMJSPRegionContexts.JSP_COMMENT_CLOSE;
+		return result;
+	}
+
+	protected void setOwnerDocument(Document ownerDocument) {
+		super.setOwnerDocument(ownerDocument);
+	}
+	
+	public Node cloneNode(boolean deep) {
+		CommentImpl cloned = new CommentImplForJSP(this);
+		return cloned;
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/domdocument/DOMDocumentForJSP.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/domdocument/DOMDocumentForJSP.java
new file mode 100644
index 0000000..23a8baa
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/domdocument/DOMDocumentForJSP.java
@@ -0,0 +1,120 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+
+package org.eclipse.jst.jsp.core.internal.domdocument;
+
+import org.eclipse.wst.html.core.internal.document.DocumentStyleImpl;
+import org.eclipse.wst.xml.core.internal.document.DocumentImpl;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Comment;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.Text;
+
+public class DOMDocumentForJSP extends DocumentStyleImpl {
+
+	/**
+	 * 
+	 */
+	public DOMDocumentForJSP() {
+		super();
+	}
+
+	/**
+	 * @param that
+	 */
+	protected DOMDocumentForJSP(DocumentImpl that) {
+		super(that);
+	}
+	/**
+	 * cloneNode method
+	 * @return org.w3c.dom.Node
+	 * @param deep boolean
+	 */
+	public Node cloneNode(boolean deep) {
+		DOMDocumentForJSP cloned = new DOMDocumentForJSP(this);
+		if (deep)
+			cloned.importChildNodes(this, true);
+		return cloned;
+	}
+	/**
+	 * createElement method
+	 * 
+	 * @return org.w3c.dom.Element
+	 * @param tagName
+	 *            java.lang.String
+	 */
+	public Element createElement(String tagName) throws DOMException {
+		checkTagNameValidity(tagName);
+
+		ElementImplForJSP element = new ElementImplForJSP();
+		element.setOwnerDocument(this);
+		element.setTagName(tagName);
+		return element;
+	}
+	/**
+	 * createComment method
+	 * 
+	 * @return org.w3c.dom.Comment
+	 * @param data
+	 *            java.lang.String
+	 */
+	public Comment createComment(String data) {
+		CommentImplForJSP comment = new CommentImplForJSP();
+		comment.setOwnerDocument(this);
+		if (data != null)
+			comment.setData(data);
+		return comment;
+	}
+
+	/**
+	 * createAttribute method
+	 * 
+	 * @return org.w3c.dom.Attr
+	 * @param name
+	 *            java.lang.String
+	 */
+	public Attr createAttribute(String name) throws DOMException {
+		AttrImplForJSP attr = new AttrImplForJSP();
+		attr.setOwnerDocument(this);
+		attr.setName(name);
+		return attr;
+	}
+
+	/**
+	 */
+	public Attr createAttributeNS(String uri, String name) throws DOMException {
+		AttrImplForJSP attr = new AttrImplForJSP();
+		attr.setOwnerDocument(this);
+		attr.setName(name);
+		attr.setNamespaceURI(uri);
+		return attr;
+	}
+	/**
+	 * createTextNode method
+	 * 
+	 * @return org.w3c.dom.Text
+	 * @param data
+	 *            java.lang.String
+	 */
+	public Text createTextNode(String data) {
+		TextImplForJSP text = new TextImplForJSP();
+		text.setOwnerDocument(this);
+		text.setData(data);
+		return text;
+	}
+	protected void setModel(IDOMModel model) {
+		super.setModel(model);
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/domdocument/DOMModelForJSP.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/domdocument/DOMModelForJSP.java
new file mode 100644
index 0000000..dcc8ce2
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/domdocument/DOMModelForJSP.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+
+package org.eclipse.jst.jsp.core.internal.domdocument;
+
+import org.eclipse.wst.html.core.internal.document.DOMStyleModelImpl;
+import org.eclipse.wst.xml.core.internal.document.XMLModelParser;
+import org.eclipse.wst.xml.core.internal.document.XMLModelUpdater;
+import org.w3c.dom.Document;
+
+public class DOMModelForJSP extends DOMStyleModelImpl {
+
+	/**
+	 * 
+	 */
+	public DOMModelForJSP() {
+		super();
+		// remember, the document is created in super constructor, 
+		// via internalCreateDocument
+	}
+	/**
+	 * createDocument method
+	 * @return org.w3c.dom.Document
+	 */
+	protected Document internalCreateDocument() {
+		DOMDocumentForJSP document = new DOMDocumentForJSP();
+		document.setModel(this);
+		return document;
+	}
+	protected XMLModelParser createModelParser() {
+		return new NestedDOMModelParser(this);
+	}
+	protected XMLModelUpdater createModelUpdater() {
+		return new NestDOMModelUpdater(this);
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/domdocument/ElementImplForJSP.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/domdocument/ElementImplForJSP.java
new file mode 100644
index 0000000..05fa231
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/domdocument/ElementImplForJSP.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+
+package org.eclipse.jst.jsp.core.internal.domdocument;
+
+import org.eclipse.jst.jsp.core.internal.regions.DOMJSPRegionContexts;
+import org.eclipse.wst.html.core.internal.document.ElementStyleImpl;
+import org.eclipse.wst.xml.core.internal.document.ElementImpl;
+import org.w3c.dom.Document;
+
+public class ElementImplForJSP extends ElementStyleImpl {
+	/**
+	 * 
+	 */
+	public ElementImplForJSP() {
+		super();
+	}
+
+	/**
+	 * @param that
+	 */
+	public ElementImplForJSP(ElementImpl that) {
+		super(that);
+	}
+
+	protected boolean isNestedEndTag(String regionType) {
+		boolean result = regionType == DOMJSPRegionContexts.JSP_ROOT_TAG_NAME || regionType == DOMJSPRegionContexts.JSP_DIRECTIVE_NAME;
+		return result;
+	}
+
+	protected boolean isNestedClosed(String regionType) {
+		boolean result = (regionType == DOMJSPRegionContexts.JSP_CLOSE || regionType == DOMJSPRegionContexts.JSP_DIRECTIVE_CLOSE);
+		return result;
+	}
+
+	protected boolean isNestedClosedComment(String regionType) {
+		boolean result = regionType == DOMJSPRegionContexts.JSP_COMMENT_CLOSE;
+		return result;
+	}
+
+	protected boolean isClosedNestedDirective(String regionType) {
+		boolean result = regionType == DOMJSPRegionContexts.JSP_DIRECTIVE_CLOSE;
+		return result;
+	}
+
+	protected void setOwnerDocument(Document ownerDocument) {
+		super.setOwnerDocument(ownerDocument);
+	}
+
+	protected void setTagName(String tagName) {
+		super.setTagName(tagName);
+	}
+
+	protected ElementImpl newInstance() {
+		return new ElementImplForJSP(this);
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/domdocument/NestDOMModelUpdater.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/domdocument/NestDOMModelUpdater.java
new file mode 100644
index 0000000..337d75b
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/domdocument/NestDOMModelUpdater.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+
+package org.eclipse.jst.jsp.core.internal.domdocument;
+
+import org.eclipse.jst.jsp.core.internal.regions.DOMJSPRegionContexts;
+import org.eclipse.wst.xml.core.internal.document.DOMModelImpl;
+import org.eclipse.wst.xml.core.internal.document.XMLModelUpdater;
+
+
+public class NestDOMModelUpdater extends XMLModelUpdater {
+
+	/**
+	 * @param model
+	 */
+	public NestDOMModelUpdater(DOMModelImpl model) {
+		super(model);
+	}
+
+	protected boolean isNestedTagClose(String regionType) {
+		boolean result = regionType == DOMJSPRegionContexts.JSP_CLOSE || regionType == DOMJSPRegionContexts.JSP_DIRECTIVE_CLOSE;
+		return result;
+	}
+
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/domdocument/NestedDOMModelParser.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/domdocument/NestedDOMModelParser.java
new file mode 100644
index 0000000..afaa719
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/domdocument/NestedDOMModelParser.java
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+
+package org.eclipse.jst.jsp.core.internal.domdocument;
+
+import org.eclipse.jst.jsp.core.internal.regions.DOMJSPRegionContexts;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+import org.eclipse.wst.xml.core.internal.document.DOMModelImpl;
+import org.eclipse.wst.xml.core.internal.document.JSPTag;
+import org.eclipse.wst.xml.core.internal.document.XMLModelParser;
+
+public class NestedDOMModelParser extends XMLModelParser {
+
+	/**
+	 * @param model
+	 */
+	public NestedDOMModelParser(DOMModelImpl model) {
+		super(model);
+	}
+
+	protected boolean isNestedCommentOpen(String regionType) {
+		boolean result = regionType == DOMJSPRegionContexts.JSP_COMMENT_OPEN;
+		return result;
+	}
+
+	protected boolean isNestedCommentText(String regionType) {
+		boolean result = regionType == DOMJSPRegionContexts.JSP_COMMENT_TEXT;
+		return result;
+	}
+
+	protected boolean isNestedContent(String regionType) {
+		boolean result = regionType == DOMJSPRegionContexts.JSP_CONTENT;
+		return result;
+	}
+
+	protected boolean isNestedTag(String regionType) {
+		boolean result = regionType == DOMJSPRegionContexts.JSP_SCRIPTLET_OPEN || regionType == DOMJSPRegionContexts.JSP_EXPRESSION_OPEN || regionType == DOMJSPRegionContexts.JSP_DECLARATION_OPEN || regionType == DOMJSPRegionContexts.JSP_DIRECTIVE_OPEN || regionType == DOMJSPRegionContexts.JSP_CLOSE;
+		return result;
+	}
+
+	protected boolean isNestedTagName(String regionType) {
+		boolean result = regionType == DOMJSPRegionContexts.JSP_ROOT_TAG_NAME || regionType == DOMJSPRegionContexts.JSP_DIRECTIVE_NAME;
+		return result;
+	}
+	protected boolean isNestedTagOpen(String regionType) {
+		boolean result = regionType == DOMJSPRegionContexts.JSP_SCRIPTLET_OPEN || regionType == DOMJSPRegionContexts.JSP_EXPRESSION_OPEN || regionType == DOMJSPRegionContexts.JSP_DECLARATION_OPEN || regionType == DOMJSPRegionContexts.JSP_DIRECTIVE_OPEN;
+		return result;
+	}
+	protected String computeNestedTag(String regionType, String tagName, IStructuredDocumentRegion structuredDocumentRegion, ITextRegion region) {
+		String resultTagName = tagName;
+		if (regionType == DOMJSPRegionContexts.JSP_SCRIPTLET_OPEN) {
+			resultTagName = JSPTag.JSP_SCRIPTLET;
+		}
+		else if (regionType == DOMJSPRegionContexts.JSP_EXPRESSION_OPEN) {
+			resultTagName = JSPTag.JSP_EXPRESSION;
+		}
+		else if (regionType == DOMJSPRegionContexts.JSP_DECLARATION_OPEN) {
+			resultTagName = JSPTag.JSP_DECLARATION;
+		}
+		else if (regionType == DOMJSPRegionContexts.JSP_DIRECTIVE_OPEN) {
+			resultTagName = JSPTag.JSP_DIRECTIVE;
+		}
+		else if (regionType == DOMJSPRegionContexts.JSP_DIRECTIVE_NAME) {
+			resultTagName += '.';
+			resultTagName += structuredDocumentRegion.getText(region);
+		}
+		return resultTagName;
+	}
+
+	protected boolean isNestedTagClose(String regionType) {
+		boolean result = regionType == DOMJSPRegionContexts.JSP_CLOSE || regionType == DOMJSPRegionContexts.JSP_DIRECTIVE_CLOSE;
+		return result;
+	}
+
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/domdocument/TextImplForJSP.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/domdocument/TextImplForJSP.java
new file mode 100644
index 0000000..1f67f53
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/domdocument/TextImplForJSP.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+
+package org.eclipse.jst.jsp.core.internal.domdocument;
+
+import org.eclipse.jst.jsp.core.internal.regions.DOMJSPRegionContexts;
+import org.eclipse.wst.xml.core.internal.document.TextImpl;
+import org.w3c.dom.Document;
+
+public class TextImplForJSP extends TextImpl {
+	protected boolean isNotNestedContent(String regionType) {
+		boolean result = regionType != DOMJSPRegionContexts.JSP_CONTENT;
+		return result;
+	}
+	protected void setOwnerDocument(Document ownerDocument) {
+		super.setOwnerDocument(ownerDocument);
+	}
+
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/encoding/IJSPHeadContentDetector.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/encoding/IJSPHeadContentDetector.java
new file mode 100644
index 0000000..291c547
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/encoding/IJSPHeadContentDetector.java
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.encoding;
+
+import java.io.IOException;
+
+import org.eclipse.wst.sse.core.internal.document.IDocumentCharsetDetector;
+
+public interface IJSPHeadContentDetector extends IDocumentCharsetDetector {
+	String getContentType() throws IOException;
+
+	String getLanguage() throws IOException;
+
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/encoding/JSPDocumentHeadContentDetector.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/encoding/JSPDocumentHeadContentDetector.java
new file mode 100644
index 0000000..84c5e7e
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/encoding/JSPDocumentHeadContentDetector.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.encoding;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jst.jsp.core.internal.contenttype.JSPResourceEncodingDetector;
+import org.eclipse.wst.sse.core.internal.document.DocumentReader;
+
+/**
+ * This class parses beginning portion of JSP file to get attributes in page
+ * directiive
+ *  
+ */
+public class JSPDocumentHeadContentDetector extends JSPResourceEncodingDetector implements IJSPHeadContentDetector {
+
+	public JSPDocumentHeadContentDetector() {
+		super();
+	}
+
+	public void set(IDocument document) {
+		set(new DocumentReader(document, 0));
+
+	}
+
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/encoding/JSPDocumentLoader.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/encoding/JSPDocumentLoader.java
new file mode 100644
index 0000000..9b21526
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/encoding/JSPDocumentLoader.java
@@ -0,0 +1,311 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.encoding;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.io.UnsupportedEncodingException;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jface.text.IDocumentPartitioner;
+import org.eclipse.jst.jsp.core.internal.Assert;
+import org.eclipse.jst.jsp.core.internal.JSPCoreMessages;
+import org.eclipse.jst.jsp.core.internal.document.PageDirectiveWatcherFactory;
+import org.eclipse.jst.jsp.core.internal.parser.JSPReParser;
+import org.eclipse.jst.jsp.core.internal.parser.JSPSourceParser;
+import org.eclipse.jst.jsp.core.internal.provisional.JSP11Namespace;
+import org.eclipse.jst.jsp.core.internal.provisional.contenttype.ContentTypeIdForJSP;
+import org.eclipse.jst.jsp.core.internal.text.StructuredTextPartitionerForJSP;
+import org.eclipse.wst.sse.core.internal.PropagatingAdapter;
+import org.eclipse.wst.sse.core.internal.document.AbstractDocumentLoader;
+import org.eclipse.wst.sse.core.internal.document.IDocumentCharsetDetector;
+import org.eclipse.wst.sse.core.internal.document.IDocumentLoader;
+import org.eclipse.wst.sse.core.internal.document.StructuredDocumentFactory;
+import org.eclipse.wst.sse.core.internal.encoding.CodedIO;
+import org.eclipse.wst.sse.core.internal.encoding.CodedReaderCreator;
+import org.eclipse.wst.sse.core.internal.encoding.ContentTypeEncodingPreferences;
+import org.eclipse.wst.sse.core.internal.encoding.util.BufferedLimitedReader;
+import org.eclipse.wst.sse.core.internal.ltk.modelhandler.EmbeddedTypeHandler;
+import org.eclipse.wst.sse.core.internal.ltk.parser.RegionParser;
+import org.eclipse.wst.sse.core.internal.ltk.parser.TagMarker;
+import org.eclipse.wst.sse.core.internal.modelhandler.EmbeddedTypeRegistry;
+import org.eclipse.wst.sse.core.internal.modelhandler.EmbeddedTypeRegistryImpl;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.provisional.document.IEncodedDocument;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+import org.eclipse.wst.sse.core.internal.text.BasicStructuredDocument;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
+import org.eclipse.wst.xml.core.internal.ssemodelquery.ModelQueryAdapter;
+import org.w3c.dom.Document;
+
+public class JSPDocumentLoader extends AbstractDocumentLoader {
+	private final static String DEFAULT_MIME_TYPE = "text/html"; //$NON-NLS-1$
+	private final static String SPEC_DEFAULT_ENCODING = "ISO-8859-1"; //$NON-NLS-1$
+
+	protected static IFile getFileFor(IStructuredModel model) {
+		if (model == null)
+			return null;
+		String path = model.getBaseLocation();
+		if (path == null || path.length() == 0) {
+			Object id = model.getId();
+			if (id == null)
+				return null;
+			path = id.toString();
+		}
+		// TODO needs rework for linked resources
+		IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+		IFile file = root.getFileForLocation(new Path(path));
+		return file;
+	}
+
+	private EmbeddedTypeRegistry fEmbeddedContentTypeRegistry;
+
+	public JSPDocumentLoader() {
+		super();
+	}
+
+	protected void addNestablePrefix(JSPSourceParser parser, String tagName) {
+		TagMarker bm = new TagMarker(tagName);
+		parser.addNestablePrefix(bm);
+	}
+
+	synchronized public IEncodedDocument createNewStructuredDocument(IFile iFile) throws IOException, CoreException {
+		IStructuredDocument structuredDocument = null;
+		try {
+			structuredDocument = createCodedDocument(iFile);
+
+			EmbeddedTypeHandler embeddedType = getEmbeddedType(iFile);
+			if (embeddedType != null)
+				embeddedType.initializeParser(structuredDocument.getParser());
+
+			fFullPreparedReader.reset();
+			setDocumentContentsFromReader(structuredDocument, fFullPreparedReader);
+
+		}
+		finally {
+			if (fFullPreparedReader != null) {
+				fFullPreparedReader.close();
+			}
+		}
+		return structuredDocument;
+	}
+
+	private IStructuredDocument createCodedDocument(IFile iFile) throws CoreException, UnsupportedEncodingException, IOException {
+		IStructuredDocument structuredDocument = (IStructuredDocument) createNewStructuredDocument();
+
+		getCodedReaderCreator().set(iFile);
+
+		fFullPreparedReader = getCodedReaderCreator().getCodedReader();
+		fEncodingMemento = getCodedReaderCreator().getEncodingMemento();
+
+		structuredDocument.setEncodingMemento(getCodedReaderCreator().getEncodingMemento());
+
+		return structuredDocument;
+	}
+
+	public IEncodedDocument createNewStructuredDocument(String filename, InputStream inputStream) throws UnsupportedEncodingException, IOException {
+		if (filename == null && inputStream == null) {
+			throw new IllegalArgumentException("can not have both null filename and inputstream"); //$NON-NLS-1$
+		}
+		IEncodedDocument structuredDocument = createNewStructuredDocument();
+		CodedReaderCreator codedReaderCreator = new CodedReaderCreator();
+		try {
+			codedReaderCreator.set(filename, inputStream);
+			fFullPreparedReader = codedReaderCreator.getCodedReader();
+			fEncodingMemento = codedReaderCreator.getEncodingMemento();
+			structuredDocument.setEncodingMemento(fEncodingMemento);
+			// the fact that file is null means this method/code path is no
+			// good for JSP fragments
+			EmbeddedTypeHandler embeddedType = getEmbeddedType((IFile) null);
+			fFullPreparedReader.reset();
+			if (embeddedType != null)
+				embeddedType.initializeParser(((IStructuredDocument) structuredDocument).getParser());
+			setDocumentContentsFromReader(structuredDocument, fFullPreparedReader);
+		}
+		catch (CoreException e) {
+			// impossible in this context
+			throw new Error(e);
+		}
+		finally {
+			if (fFullPreparedReader != null) {
+				fFullPreparedReader.close();
+			}
+		}
+		return structuredDocument;
+
+	}
+
+	/**
+	 * Method getDefaultDocumentPartitioner.
+	 * 
+	 * @return IDocumentPartitioner
+	 */
+	public IDocumentPartitioner getDefaultDocumentPartitioner() {
+		return new StructuredTextPartitionerForJSP();
+	}
+
+	/**
+	 * Method getDefaultMimeType.
+	 * 
+	 * @return String
+	 */
+	private String getDefaultMimeType() {
+		return DEFAULT_MIME_TYPE;
+	}
+
+
+	public IDocumentCharsetDetector getDocumentEncodingDetector() {
+		if (fDocumentEncodingDetector == null) {
+			fDocumentEncodingDetector = new JSPDocumentHeadContentDetector();
+		}
+		return fDocumentEncodingDetector;
+	}
+
+	/**
+	 * Gets the embeddedContentTypeRegistry.
+	 * 
+	 * @return Returns a EmbeddedContentTypeRegistry
+	 */
+	private EmbeddedTypeRegistry getEmbeddedContentTypeRegistry() {
+		if (fEmbeddedContentTypeRegistry == null) {
+			fEmbeddedContentTypeRegistry = EmbeddedTypeRegistryImpl.getInstance();
+		}
+		return fEmbeddedContentTypeRegistry;
+	}
+
+	/**
+	 * Determine the MIME content type specified in a page directive. This
+	 * should appear "as early as possible in the JSP page" according to the
+	 * JSP v1.2 specification.
+	 */
+	private EmbeddedTypeHandler getEmbeddedType(IFile file) throws UnsupportedEncodingException, CoreException, IOException {
+		EmbeddedTypeHandler handler = null;
+		if (fFullPreparedReader == null) {
+			handler = getJSPDefaultEmbeddedType();
+		}
+		else {
+			String mimeType = null;
+
+			IDocumentCharsetDetector jspProvider = getDocumentEncodingDetector();
+			Reader fullPreparedReader = getFullPreparedReader();
+			BufferedLimitedReader limitedReader = new BufferedLimitedReader(fullPreparedReader, CodedIO.MAX_BUF_SIZE);
+			jspProvider.set(limitedReader);
+			if (jspProvider instanceof IJSPHeadContentDetector) {
+				mimeType = ((IJSPHeadContentDetector) jspProvider).getContentType();
+				fullPreparedReader.reset();
+			}
+
+			EmbeddedTypeRegistry reg = getEmbeddedContentTypeRegistry();
+			if (mimeType == null || mimeType.length() == 0) {
+				handler = getJSPDefaultEmbeddedType();
+			}
+			else {
+				handler = reg.getTypeFor(mimeType);
+			}
+		}
+		return handler;
+	}
+
+	/**
+	 * For JSP files, text/html is the default content type. This may want
+	 * this different for types like jsv (jsp for voice xml) For now, hard
+	 * code to new instance. In future, should get instance from registry.
+	 * Specification cites HTML as the default contentType.
+	 */
+	private EmbeddedTypeHandler getJSPDefaultEmbeddedType() {
+		EmbeddedTypeRegistry reg = getEmbeddedContentTypeRegistry();
+		return reg.getTypeFor(getDefaultMimeType());
+	}
+
+	public RegionParser getParser() {
+		// remember, the Loader
+		// will need to finish initialization of parser
+		// based on "embedded content"
+		JSPSourceParser parser = new JSPSourceParser();
+		// add default nestable tag list
+		addNestablePrefix(parser, JSP11Namespace.JSP_TAG_PREFIX);
+		return parser;
+	}
+
+	protected String getPreferredNewLineDelimiter(IFile file) {
+		String delimiter = ContentTypeEncodingPreferences.getPreferredNewLineDelimiter(ContentTypeIdForJSP.ContentTypeID_JSP);
+		if (delimiter == null)
+			delimiter = super.getPreferredNewLineDelimiter(file);
+		return delimiter;
+	}
+
+	/**
+	 * Specification cites ISO-8859-1/Latin-1 as the default charset.
+	 */
+	protected String getSpecDefaultEncoding() {
+		return SPEC_DEFAULT_ENCODING;
+	}
+
+	/**
+	 * This method must return a new instance of IStructuredDocument, that has
+	 * been initialized with appropriate parser. For many loaders, the
+	 * (default) parser used is known for any input. For others, the correct
+	 * parser (and its initialization) is normall dependent on the content of
+	 * the file. This no-argument method should assume "empty input" and would
+	 * therefore return the default parser for the default contentType. If the
+	 * parser is to handle tag libraries, it must have a TaglibSupport object
+	 * with a valid URIResolver and this IStructuredDocument attached to it
+	 * before the contents are set on the IStructuredDocument.
+	 */
+	protected IEncodedDocument newEncodedDocument() {
+		IStructuredDocument structuredDocument = StructuredDocumentFactory.getNewStructuredDocumentInstance(getParser());
+		((BasicStructuredDocument) structuredDocument).setReParser(new JSPReParser());
+		// structuredDocument.setDocumentPartitioner(new
+		// JSPJavaDocumentPartioner());
+		// even though this is an "empty model" ... we want it to have at
+		// least
+		// the
+		// default embeddeded content type handler
+		EmbeddedTypeHandler embeddedType = getJSPDefaultEmbeddedType();
+		embeddedType.initializeParser(structuredDocument.getParser());
+		return structuredDocument;
+	}
+
+	public IDocumentLoader newInstance() {
+		return new JSPDocumentLoader();
+	}
+
+	protected void preLoadAdapt(IStructuredModel structuredModel) {
+		IDOMModel domModel = (IDOMModel) structuredModel;
+		//
+		// document must have already been set for this to
+		// work.
+		Document document = domModel.getDocument();
+		Assert.isNotNull(document, JSPCoreMessages.JSPDocumentLoader_1);
+		// if there is a model in the adapter, this will adapt it to
+		// first node. After that the PropagatingAdater spreads over the
+		// children being
+		// created. Each time that happends, a side effect is to
+		// also "spread" sprecific registered adapters,
+		// they two can propigate is needed.
+		// This 'get' causes first to be be attached.
+		PropagatingAdapter propagatingAdapter = (PropagatingAdapter) ((INodeNotifier) document).getAdapterFor(PropagatingAdapter.class);
+		// may make this easier to use in futue
+		propagatingAdapter.addAdaptOnCreateFactory(new PageDirectiveWatcherFactory());
+		// For JSPs, the ModelQueryAdapter must be "attached" to the document
+		// before content is set in the model, so taglib initization can
+		// take place.
+		((INodeNotifier) document).getAdapterFor(ModelQueryAdapter.class);
+
+	}
+
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/ArrayMap.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/ArrayMap.java
new file mode 100644
index 0000000..507ec77
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/ArrayMap.java
@@ -0,0 +1,103 @@
+/*******************************************************************************
+ * Copyright (c) 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.java;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Hashtable;
+import java.util.Iterator;
+
+/**
+ * This implementation of a hashtable maps keys to arrays
+ * to support multiple values being associated with a single
+ * key. To remove a specific entry, a key and inserted value must
+ * be provided. Removing just based on the key name will remove all
+ * values stored under that key
+ * 
+ */
+public class ArrayMap extends Hashtable {
+
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = 1L;
+	
+	public ArrayMap(int size) {
+		super(size);
+	}
+	
+	public synchronized Object put(Object key, Object value) {
+		Object[] values = (Object[]) super.get(key);
+		Object[] newValues = null;
+		
+		if (values == null || values.length == 0)
+			newValues = new Object[1];
+		else {
+			newValues = new Object[values.length + 1];
+			System.arraycopy(values, 0, newValues, 0, values.length);
+		}
+
+		newValues[newValues.length - 1] = value;
+		return super.put(key, newValues);
+	}
+	
+	/**
+	 * Removes the first occurrence of <code>value</code> from the list 
+	 * of values associated with <code>key</code>
+	 * 
+	 * @param key the key that has <code>value</code>
+	 * @param value the specific value to remove from the key
+	 * @return The item removed from the list of values
+	 */
+	public synchronized Object remove(Object key, Object value) {
+		Object[] values = (Object[]) super.get(key);
+		Object removed = null;
+		Object[] result = null;
+		if (values != null && value != null) {
+			for (int i = 0; i < values.length; i++) {
+				if (value.equals(values[i])) {
+					removed = values[i];
+					result = new Object[values.length - 1];
+					
+					if (result.length > 0) {
+						// Copy left of value
+						System.arraycopy(values, 0, result, 0, i);
+						// Copy right of value
+						if (i < (values.length - 1))
+							System.arraycopy(values, i+1, result, i, result.length - i);
+					}
+					else
+						super.remove(key);
+					
+					break;
+				}
+			}
+		}
+		
+		if(result != null && result.length > 0)
+			super.put(key, result);
+		
+		return removed;
+	}
+	
+	public Collection values() {
+		Collection valuemaps = super.values();
+		Collection values = new ArrayList();
+		
+		for(Iterator i = valuemaps.iterator(); i.hasNext();)
+			values.addAll(Arrays.asList((Object[]) i.next()));
+		
+		return values;
+	}
+
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/CompilationUnitHelper.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/CompilationUnitHelper.java
new file mode 100644
index 0000000..7ace8d4
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/CompilationUnitHelper.java
@@ -0,0 +1,56 @@
+package org.eclipse.jst.jsp.core.internal.java;
+
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IProblemRequestor;
+import org.eclipse.jdt.core.WorkingCopyOwner;
+
+/**
+ * To ensure there is only one instance of ProblemRequestor and WorkingCopyOwner
+ * for JSP plugins.  These were removed from JSPTranslation to ensure that the
+ * JSPTranslation was not held in memory by any type of JDT lists (caching
+ * search results, etc...)
+ * 
+ * @author pavery
+ */
+public class CompilationUnitHelper {
+
+    private JSPProblemRequestor fProblemRequestor = null;
+    private WorkingCopyOwner fWorkingCopyOwner = null;
+    private static CompilationUnitHelper instance;
+
+    private CompilationUnitHelper() {
+        // force use of instance
+    }
+
+    public synchronized static final CompilationUnitHelper getInstance() {
+
+        if (instance == null)
+            instance = new CompilationUnitHelper();
+        return instance;
+    }
+
+    public JSPProblemRequestor getProblemRequestor() {
+
+        if (fProblemRequestor == null)
+            fProblemRequestor = new JSPProblemRequestor();
+        return fProblemRequestor;
+    }
+
+    public WorkingCopyOwner getWorkingCopyOwner() {
+
+        if (fWorkingCopyOwner == null) {
+            fWorkingCopyOwner = new WorkingCopyOwner() {
+            	/* (non-Javadoc)
+            	 * @see org.eclipse.jdt.core.WorkingCopyOwner#getProblemRequestor(org.eclipse.jdt.core.ICompilationUnit)
+            	 */
+            	public IProblemRequestor getProblemRequestor(ICompilationUnit workingCopy) {
+            		return CompilationUnitHelper.this.getProblemRequestor();
+            	}
+                public String toString() {
+                    return "JSP Working copy owner"; //$NON-NLS-1$
+                }
+            };
+        }
+        return fWorkingCopyOwner;
+    }
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/EscapedTextUtil.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/EscapedTextUtil.java
new file mode 100644
index 0000000..2d65350
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/EscapedTextUtil.java
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.java;
+
+
+
+import java.util.Properties;
+import com.ibm.icu.util.StringTokenizer;
+
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+
+/**
+ * class to handle chunks of text/regions
+ * with escaped character data
+ * @author pavery
+ */
+public class EscapedTextUtil {
+
+	public static Properties fXMLtoJavaLookup = null;
+
+	/**
+	 * @return unescaped full text of that region, "" if there is no text
+	 */
+	public static String getUnescapedText(IStructuredDocumentRegion parent, ITextRegion r) {
+		String test = (parent != r) ? parent.getFullText(r) : parent.getFullText();
+		return getUnescapedText(test);
+	}
+
+	public static String getUnescapedText(String test) {
+		initLookup();
+		StringBuffer buffer = new StringBuffer();
+		if (test != null) {
+			StringTokenizer st = new StringTokenizer(test, "&;", true); //$NON-NLS-1$
+			String tok1, tok2, tok3, transString;
+			while (st.hasMoreTokens()) {
+				tok1 = tok2 = tok3 = transString = ""; //$NON-NLS-1$
+				tok1 = st.nextToken();
+				if (tok1.equals("&") && st.hasMoreTokens()) //$NON-NLS-1$
+				{
+					tok2 = st.nextToken();
+					if (st.hasMoreTokens()) {
+						tok3 = st.nextToken();
+					}
+				}
+				if (!(transString = fXMLtoJavaLookup.getProperty(tok1 + tok2 + tok3, "")).equals("")) //$NON-NLS-2$ //$NON-NLS-1$
+				{
+					buffer.append(transString);
+				}
+				else {
+					buffer.append(tok1 + tok2 + tok3);
+				}
+			}
+			return buffer.toString();
+		}
+		return ""; //$NON-NLS-1$
+	}
+
+	/**
+	 * initialize lookup tables
+	 */
+	private static void initLookup() {
+		fXMLtoJavaLookup = new Properties();
+		fXMLtoJavaLookup.setProperty("&apos;", "'"); //$NON-NLS-2$ //$NON-NLS-1$
+		fXMLtoJavaLookup.setProperty("&quot;", "\""); //$NON-NLS-2$ //$NON-NLS-1$
+		fXMLtoJavaLookup.setProperty("&amp;", "&"); //$NON-NLS-2$ //$NON-NLS-1$
+		fXMLtoJavaLookup.setProperty("&lt;", "<"); //$NON-NLS-2$ //$NON-NLS-1$
+		fXMLtoJavaLookup.setProperty("&gt;", ">"); //$NON-NLS-2$ //$NON-NLS-1$
+		fXMLtoJavaLookup.setProperty("&nbsp;", " "); //$NON-NLS-2$ //$NON-NLS-1$
+	}
+
+	/**
+	 * Get the String representation of an entity reference.
+	 */
+	public static String translateEntityReference(String entity) {
+		return fXMLtoJavaLookup.getProperty(entity, entity);
+	}
+}
+
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/IJSPProblem.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/IJSPProblem.java
new file mode 100644
index 0000000..8270cd8
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/IJSPProblem.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.java;
+
+import org.eclipse.jdt.core.compiler.IProblem;
+
+public interface IJSPProblem extends IProblem {
+
+	int F_PROBLEM_ID_LITERAL = 0xA0000000;
+	
+	int TEIClassNotFound = F_PROBLEM_ID_LITERAL + 1;
+	int TEIValidationMessage = F_PROBLEM_ID_LITERAL + 2;
+	int TEIClassNotInstantiated = F_PROBLEM_ID_LITERAL + 3;
+	int TEIClassMisc = F_PROBLEM_ID_LITERAL + 4;	
+	int TagClassNotFound = F_PROBLEM_ID_LITERAL + 5;
+	int UseBeanInvalidID = F_PROBLEM_ID_LITERAL + 6;
+	int UseBeanMissingTypeInfo = F_PROBLEM_ID_LITERAL + 7;
+	int UseBeanAmbiguousType  = F_PROBLEM_ID_LITERAL + 8;
+	int StartCustomTagMissing  = F_PROBLEM_ID_LITERAL + 9;
+	int EndCustomTagMissing  = F_PROBLEM_ID_LITERAL + 10;
+	int UseBeanStartTagMissing  = F_PROBLEM_ID_LITERAL + 11;
+	int UseBeanEndTagMissing  = F_PROBLEM_ID_LITERAL + 12;
+	int ELProblem = F_PROBLEM_ID_LITERAL + 13;
+
+	/**
+	 * @return the ID of this JSP problem
+	 */
+	int getEID();
+
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/IJSPTranslation.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/IJSPTranslation.java
new file mode 100644
index 0000000..17f641f
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/IJSPTranslation.java
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.java;
+
+import java.util.List;
+
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IJavaElement;
+
+/**
+ * An object that holds a translated JSP String along with
+ * position mapping from Java to JSP, and JSP to Java.
+ * 
+ * @author pavery
+ * 
+ */
+public interface IJSPTranslation {
+
+	/**
+	 * The string contents of the translated document.
+	 * @return  the string contents of the translated document.
+	 */
+	public String getJavaText();
+
+	/**
+	 * The corresponding java offset in the translated document for a given jsp offset.
+	 * @param jspPosition
+	 * @return the java offset that maps to jspOffset, -1 if the position has no mapping.
+	 */
+	public int getJavaOffset(int jspOffset);
+
+	/**
+	 * The corresponding jsp offset in the source document for a given jsp offset in the translated document.
+	 * @param javaPosition
+	 * @return the jsp offset that maps to javaOffset, -1 if the position has no mapping.
+	 */
+	public int getJspOffset(int javaOffset);
+
+	/**
+	 * The corresponding CompilationUnit for the translated JSP document
+	 * @return an ICompilationUnit of the translation
+	 */
+	public ICompilationUnit getCompilationUnit();
+
+	/**
+	 * Returns the IJavaElements corresponding to the JSP range in the JSP StructuredDocument
+	 * 
+	 * @param jspStart staring offset in the JSP document
+	 * @param jspEnd ending offset in the JSP document
+	 * @return IJavaElements corresponding to the JSP selection
+	 */
+	public IJavaElement[] getElementsFromJspRange(int jspStart, int jspEnd);
+
+	/**
+	 * @param javaOffset
+	 * @return whether the given offset within the translated Java source maps
+	 *         directly to a scripting region in the original JSP
+	 */
+	public boolean isIndirect(int javaOffset);
+	
+	/**
+	 * Must be set true in order for problems to be collected during reconcile.
+	 * If set false, problems will be ignored during reconcile.
+	 * @param collect
+	 */
+	public void setProblemCollectingActive(boolean collect);
+
+	/**
+	 * Reconciles the compilation unit for this JSPTranslation
+	 */
+	public void reconcileCompilationUnit();
+
+	/**
+	 * @return the List of problems collected during reconcile of the compilation unit
+	 */
+	public List getProblems();
+	
+	// add these API once finalized
+	// getJspEdits(TextEdit javaEdit)
+	// getJavaRanges()
+    // getJavaDocument()
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/JSP2ServletNameUtil.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/JSP2ServletNameUtil.java
new file mode 100644
index 0000000..e9c6bd9
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/JSP2ServletNameUtil.java
@@ -0,0 +1,134 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.java;
+
+import java.io.File;
+
+/**
+ * @author pavery
+ */
+public class JSP2ServletNameUtil {
+	
+	/**
+	 * WAS mangles Tom&Jerry as: _Tom_26_Jerry; this takes in the mangled name
+	 * and returns the original name.
+	 * 
+	 * Unmangles the qualified type name.  If an underscore is found
+	 * it is assumed to be a mangled representation of a non-alpha, 
+	 * non-digit character of the form _NN_, where NN are hex digits
+	 * representing the encoded character.  This routine converts it
+	 * back to the original character.
+	 */
+	public final static String unmangle(String qualifiedTypeName) {
+		if(qualifiedTypeName.charAt(0) != '_')
+			return qualifiedTypeName;
+		
+		StringBuffer buf = new StringBuffer();
+		String possible = ""; //$NON-NLS-1$
+	
+		// remove the .java extension if there is one
+		if(qualifiedTypeName.endsWith(".java"))//$NON-NLS-1$
+			qualifiedTypeName = qualifiedTypeName.substring(0, qualifiedTypeName.length() - 5);
+		
+		for(int i = 1; i < qualifiedTypeName.length(); i++) {  // start at index 1 b/c 1st char is always '_'
+			char c = qualifiedTypeName.charAt(i);
+			if(c == '_') {
+				int endIndex = qualifiedTypeName.indexOf('_', i+1);
+				if(endIndex == -1)
+					buf.append(c);
+				else {
+					char unmangled;
+					try {
+						possible = qualifiedTypeName.substring(i+1, endIndex); 
+					    if(isValid(possible)) {
+							unmangled = (char)Integer.decode("0x" + possible).intValue();//$NON-NLS-1$
+							i = endIndex;
+					    }
+					    else { 
+					        unmangled = c;
+					    }
+						
+					} catch(NumberFormatException e) {
+						unmangled = c;
+					}
+					buf.append(unmangled);
+				}
+			} else {
+				buf.append(c);
+			}
+		}
+		return buf.toString();
+	}
+
+	/**
+	 * Determine if given string is a valid Hex representation of an ASCII character (eg. 2F -> /)
+	 * @param possible
+	 * @return
+	 */
+	private static boolean isValid(String possible) {
+	    boolean result = false;
+	    if(possible.length() == 2){	    
+	        char c1 = possible.charAt(0);
+	        char c2 = possible.charAt(1);
+	        // 1st character must be a digit
+	        if(Character.isDigit(c1)) {
+	            // 2nd character must be digit or upper case letter A-F
+	            if(Character.isDigit(c2)) {
+	                result = true;
+	            }
+	            else if(Character.isUpperCase(c2) && (c2 == 'A' || c2 == 'B' || c2 ==  'C'|| c2 ==  'D'|| c2 ==  'E'|| c2 == 'F')) {
+	                result = true;
+	            }
+	        }
+	    }
+        return result;
+	}
+	
+	/**
+	 * Mangle string to WAS-like specifications
+	 *
+	 */
+	public final static String mangle(String name) {	  
+	  StringBuffer modifiedName = new StringBuffer();
+	  
+	  // extension (.jsp, .jspf, .jspx, etc...) should already be encoded in name
+	  
+	  int length = name.length();
+	  // in case name is forbidden (a number, class, for, etc...)
+	  modifiedName.append('_');
+	
+	  // ensure rest of characters are valid	
+	  for (int i=0; i< length; i++) {
+		  char currentChar = name.charAt(i);
+		  // [290769] Mangle _ since mangling inserts _ as a delimiter
+		  if (currentChar == '_' || !Character.isJavaIdentifierPart(currentChar))
+			  modifiedName.append(mangleChar(currentChar));
+		  else
+			  modifiedName.append(currentChar);
+	  }
+	  return modifiedName.toString();
+	  
+	}
+
+	/**
+	 * take a character and return its hex equivalent
+	 */
+	private final static String mangleChar(char ch) {
+	  if ( ch == File.separatorChar ) {
+		  ch = '/';
+	  }
+	
+	  if ( Character.isLetterOrDigit(ch) == true ) {
+		  return "" + ch; //$NON-NLS-1$
+	  }
+	  return "_" + Integer.toHexString(ch).toUpperCase() + "_"; //$NON-NLS-1$ //$NON-NLS-2$
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/JSPIncludeRegionHelper.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/JSPIncludeRegionHelper.java
new file mode 100644
index 0000000..a9b5be3
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/JSPIncludeRegionHelper.java
@@ -0,0 +1,98 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.java;
+
+import org.eclipse.jst.jsp.core.internal.regions.DOMJSPRegionContexts;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+
+
+/**
+ * Extension of XMLJSPRegionHelper intended to parse entire included JSP files.
+ * Basically it expands the rules for what tags are parsed as JSP.
+ * 
+ * @author pavery
+ */
+class JSPIncludeRegionHelper extends XMLJSPRegionHelper {
+	/**
+	 * @param JSPTranslator
+	 */
+	public JSPIncludeRegionHelper(JSPTranslator translator, boolean appendAsIndirectSource) {
+		super(translator, appendAsIndirectSource);
+	}
+
+	// these methods determine what content gets added to the local scriplet, expression, declaration buffers
+	/*
+	 * return true for elements whose contents we might want to add to the java file we are building
+	 */
+	protected boolean isJSPStartRegion(IStructuredDocumentRegion sdRegion) {
+		String type = sdRegion.getFirstRegion().getType();
+		return type == DOMRegionContext.XML_TAG_OPEN || type == DOMJSPRegionContexts.JSP_DECLARATION_OPEN || type == DOMJSPRegionContexts.JSP_EXPRESSION_OPEN || type == DOMJSPRegionContexts.JSP_SCRIPTLET_OPEN || type == DOMJSPRegionContexts.JSP_DIRECTIVE_OPEN || type == DOMJSPRegionContexts.JSP_DIRECTIVE_NAME;
+	}
+
+	protected boolean isDeclaration(String tagName) {
+		return tagName.equalsIgnoreCase("jsp:declaration") //$NON-NLS-1$		
+					|| tagName.equalsIgnoreCase("<%!"); //$NON-NLS-1$		
+	}
+
+	protected boolean isExpression(String tagName) {
+		return tagName.equalsIgnoreCase("jsp:expression") //$NON-NLS-1$		
+					|| tagName.equalsIgnoreCase("<%="); //$NON-NLS-1$
+	}
+
+	protected boolean isScriptlet(String tagName) {
+		return tagName.equalsIgnoreCase("jsp:scriptlet") //$NON-NLS-1$		
+					|| tagName.equalsIgnoreCase("<%"); //$NON-NLS-1$
+	}
+
+	protected boolean isIncludeDirective(String tagName) {
+		return tagName.equalsIgnoreCase("jsp:directive.include") || //$NON-NLS-1$
+					tagName.equalsIgnoreCase("include"); //$NON-NLS-1$
+	}
+
+	protected boolean isTaglibDirective(String tagName) {
+		return tagName.equalsIgnoreCase("jsp:directive.taglib") //$NON-NLS-1$
+					|| tagName.equalsIgnoreCase("taglib"); //$NON-NLS-1$
+	}
+
+	protected boolean isPageDirective(String tagName) {
+		return tagName.equalsIgnoreCase("jsp:directive.page") //$NON-NLS-1$
+					|| tagName.equalsIgnoreCase("page"); //$NON-NLS-1$
+	}
+
+	// different btwn XML-JSP and JSP tags		
+	protected String getRegionName(IStructuredDocumentRegion sdRegion) {
+		ITextRegion nameRegion = null;
+		String nameStr = ""; //$NON-NLS-1$
+		int size = sdRegion.getRegions().size();
+		if (size > 1) {
+			// presumably XML-JSP <jsp:scriptlet> | <jsp:expression> | <jsp:declaration>
+			nameRegion = sdRegion.getRegions().get(1);
+		}
+		else if (size == 1) {
+			// presumably JSP open <% | <%= | <%!
+			nameRegion = sdRegion.getRegions().get(0);
+		}
+		if (nameRegion != null)
+			nameStr = fTextToParse.substring(sdRegion.getStartOffset(nameRegion), sdRegion.getTextEndOffset(nameRegion));
+		return nameStr.trim();
+	}
+
+	protected void processOtherRegions(IStructuredDocumentRegion sdRegion) {
+		processIncludeDirective(sdRegion);
+		processPageDirective(sdRegion);
+	}
+
+	protected void prepareText(IStructuredDocumentRegion sdRegion) {
+		fStrippedText = fTextBefore = fTextToParse.substring(sdRegion.getStartOffset(), sdRegion.getEndOffset());
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/JSPProblemRequestor.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/JSPProblemRequestor.java
new file mode 100644
index 0000000..cf47682
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/JSPProblemRequestor.java
@@ -0,0 +1,88 @@
+package org.eclipse.jst.jsp.core.internal.java;
+
+/**
+ * @author pavery
+ */
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jdt.core.IProblemRequestor;
+import org.eclipse.jdt.core.compiler.IProblem;
+
+class JSPProblemRequestor implements IProblemRequestor {
+
+    private boolean fIsActive = false;
+
+    private boolean fIsRunning = false;
+
+    private List fCollectedProblems;
+
+    public void beginReporting() {
+
+        fIsRunning = true;
+        fCollectedProblems = new ArrayList();
+    }
+
+    public void acceptProblem(IProblem problem) {
+
+        if (isActive())
+            fCollectedProblems.add(problem);
+    }
+
+    public void endReporting() {
+
+        fIsRunning = false;
+    }
+
+    public boolean isActive() {
+
+        return fIsActive && fCollectedProblems != null;
+    }
+
+    /**
+     * Sets the active state of this problem requestor.
+     * 
+     * @param isActive
+     *            the state of this problem requestor
+     */
+    public void setIsActive(boolean isActive) {
+
+        if (fIsActive != isActive) {
+            fIsActive = isActive;
+            if (fIsActive)
+                startCollectingProblems();
+            else
+                stopCollectingProblems();
+        }
+    }
+
+    /**
+     * Tells this annotation model to collect temporary problems from now on.
+     */
+    private void startCollectingProblems() {
+
+        fCollectedProblems = new ArrayList();
+    }
+
+    /**
+     * Tells this annotation model to no longer collect temporary problems.
+     */
+    private void stopCollectingProblems() {
+
+        // do nothing
+    }
+
+    /**
+     * @return the list of collected problems
+     */
+    public List getCollectedProblems() {
+
+        return fCollectedProblems;
+    }
+
+    public boolean isRunning() {
+
+        return fIsRunning;
+    }
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/JSPTranslation.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/JSPTranslation.java
new file mode 100644
index 0000000..e91499f
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/JSPTranslation.java
@@ -0,0 +1,641 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.java;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.resources.WorkspaceJob;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jdt.core.IBuffer;
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IPackageFragment;
+import org.eclipse.jdt.core.IPackageFragmentRoot;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.WorkingCopyOwner;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jst.jsp.core.internal.Logger;
+
+
+/**
+ * <p>
+ * An implementation of IJSPTranslation.  
+ * <br>
+ * This object that holds the java translation of 
+ * a JSP file as well as a mapping of ranges from the translated Java to the JSP source, 
+ * and mapping from JSP source back to the translated Java.
+ * </p>
+ * 
+ * <p>
+ * You may also use JSPTranslation to do CompilationUnit-esque things such as:
+ * <ul>
+ * 	<li>code select (get java elements for jsp selection)</li>
+ *  <li>reconcile</li>
+ *  <li>get java regions for jsp selection</li>
+ *  <li>get a JSP text edit based on a Java text edit</li>
+ *  <li>determine if a java offset falls within a jsp:useBean range</li>
+ *  <li>determine if a java offset falls within a jsp import statment</li>
+ * </ul>
+ * </p>
+ * 
+ * @author pavery
+ */
+public class JSPTranslation implements IJSPTranslation {
+	
+	// for debugging
+	private static final boolean DEBUG;
+	static {
+		String value= Platform.getDebugOption("org.eclipse.jst.jsp.core/debug/jsptranslation"); //$NON-NLS-1$
+		DEBUG= value != null && value.equalsIgnoreCase("true"); //$NON-NLS-1$
+	}
+
+	/** the name of the class (w/out extension) **/
+	private String fClassname = ""; //$NON-NLS-1$
+	private IJavaProject fJavaProject = null;
+	private HashMap fJava2JspMap = null;
+	private HashMap fJsp2JavaMap = null;
+	private HashMap fJava2JspImportsMap = null;
+	private HashMap fJava2JspUseBeanMap = null;
+	private HashMap fJava2JspIndirectMap = null;
+	
+	// don't want to hold onto model (via translator)
+	// all relevant info is extracted in the constructor.
+	//private JSPTranslator fTranslator = null;
+	private String fJavaText = ""; //$NON-NLS-1$
+	private String fJspText = ""; //$NON-NLS-1$
+	
+	private ICompilationUnit fCompilationUnit = null;
+	private IProgressMonitor fProgressMonitor = null;
+	/** lock to synchronize access to the compilation unit **/
+	private byte[] fLock = null;
+	private String fMangledName;
+	private String fJspName;
+	private List fTranslationProblems;
+	private Collection fIncludedPaths;
+	
+	/** the {@link JSPTranslator} used by this {@link JSPTranslator} */
+	private JSPTranslator fTranslator;
+
+	public JSPTranslation(IJavaProject javaProj, JSPTranslator translator) {
+
+		fLock = new byte[0];
+		fJavaProject = javaProj;
+		fTranslator = translator;
+		
+		// can be null if it's an empty document (w/ NullJSPTranslation)
+		initialize();
+	}
+
+	private void initialize() {
+		if(fTranslator != null) {
+			fJavaText = fTranslator.getTranslation().toString();
+			fJspText = fTranslator.getJspText();
+			fClassname = fTranslator.getClassname();
+			fJava2JspMap = fTranslator.getJava2JspRanges();
+			fJsp2JavaMap = fTranslator.getJsp2JavaRanges();
+			fJava2JspImportsMap = fTranslator.getJava2JspImportRanges();
+			fJava2JspUseBeanMap = fTranslator.getJava2JspUseBeanRanges();
+			fJava2JspIndirectMap = fTranslator.getJava2JspIndirectRanges();
+			fTranslationProblems = fTranslator.getTranslationProblems();
+			fIncludedPaths = fTranslator.getIncludedPaths();
+		}
+	}
+
+	/**
+	 * @return {@link JSPTranslator} used by this {@link JSPTranslation}
+	 */
+	protected JSPTranslator getTranslator() {
+		return this.fTranslator;
+	}
+	
+	public IJavaProject getJavaProject() {
+		return fJavaProject;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jst.jsp.core.internal.java.IJSPTranslation#getJavaText()
+	 */
+	public String getJavaText() {
+		//return (fTranslator != null) ? fTranslator.getTranslation().toString() : "";  //$NON-NLS-1$ 
+		return fJavaText;
+	}
+	
+	public String getJspText() {
+		//return (fTranslator != null) ? fTranslator.getJspText() : "";  //$NON-NLS-1$
+		return fJspText;
+	}
+	
+	public String getJavaPath() {
+		// create if necessary
+		ICompilationUnit cu = getCompilationUnit();
+		return (cu != null) ? cu.getPath().toString() : ""; //$NON-NLS-1$
+	}
+	
+	/**
+	 * 
+	 * @return the corresponding Java offset for a give JSP offset
+	 */
+	public int getJavaOffset(int jspOffset) {
+		int result = -1;
+		int offsetInRange = 0;
+		Position jspPos, javaPos = null;
+
+		// iterate all mapped jsp ranges
+		Iterator it = fJsp2JavaMap.keySet().iterator();
+		while (it.hasNext()) {
+			jspPos = (Position) it.next();
+			// need to count the last position as included
+			if (!jspPos.includes(jspOffset) && !(jspPos.offset+jspPos.length == jspOffset))
+				continue;
+
+			offsetInRange = jspOffset - jspPos.offset;
+			javaPos = (Position) fJsp2JavaMap.get(jspPos);
+			if(javaPos != null)
+				result = javaPos.offset + offsetInRange;
+			else  {
+
+				Logger.log(Logger.ERROR, "JavaPosition was null!" + jspOffset); //$NON-NLS-1$
+			}
+			break;
+		}
+		return result;
+	}
+
+	/**
+	 * 
+	 * @return the corresponding JSP offset for a give Java offset
+	 */
+	public int getJspOffset(int javaOffset) {
+		int result = -1;
+		int offsetInRange = 0;
+		Position jspPos, javaPos = null;
+
+		// iterate all mapped java ranges
+		Iterator it = fJava2JspMap.keySet().iterator();
+		while (it.hasNext()) {
+			javaPos = (Position) it.next();
+			// need to count the last position as included
+			if (!javaPos.includes(javaOffset) && !(javaPos.offset+javaPos.length == javaOffset))
+				continue;
+
+			offsetInRange = javaOffset - javaPos.offset;
+			jspPos = (Position) fJava2JspMap.get(javaPos);
+			
+			if(jspPos != null)
+				result = jspPos.offset + offsetInRange;
+			else  {
+				Logger.log(Logger.ERROR, "jspPosition was null!" + javaOffset); //$NON-NLS-1$
+			}
+			break;
+		}
+
+		return result;
+	}
+		
+	public Collection getIncludedPaths() {
+		return fIncludedPaths;
+	}
+
+	/**
+	 * 
+	 * @return a map of Positions in the Java document to corresponding Positions in the JSP document
+	 */
+	public HashMap getJava2JspMap() {
+		return fJava2JspMap;
+	}
+
+	/**
+	 * 
+	 * @return a map of Positions in the JSP document to corresponding Positions in the Java document
+	 */
+	public HashMap getJsp2JavaMap() {
+		return fJsp2JavaMap;
+	}
+
+	/**
+	 * Checks if the specified java range covers more than one partition in the JSP file.
+	 * 
+	 * <p>
+	 * ex.
+	 * <code>
+	 * <%
+	 * 	if(submit)
+	 *  {
+	 * %>
+	 *    <p> print this...</p>
+	 * 
+	 * <%
+	 *  }
+	 *  else
+	 *  {
+	 * %>
+	 * 	   <p> print that...</p>
+	 * <%
+	 *  }
+	 * %>
+	 * </code>
+	 * </p>
+	 * 
+	 * the if else statement above spans 3 JSP partitions, so it would return true.
+	 * @param offset
+	 * @param length
+	 * @return <code>true</code> if the java code spans multiple JSP partitions, otherwise false.
+	 */
+	public boolean javaSpansMultipleJspPartitions(int javaOffset, int javaLength) {
+		HashMap java2jsp = getJava2JspMap();
+		int count = 0;
+		Iterator it = java2jsp.keySet().iterator();
+		Position javaRange = null;
+		while(it.hasNext()) {
+			javaRange = (Position)it.next();
+			if(javaRange.overlapsWith(javaOffset, javaLength))
+				count++;
+			if(count > 1)
+				return true;
+		}
+		return false;
+	}
+	
+	/**
+	 * Returns the Java positions for the given range in the Java document.
+	 * 
+	 * @param offset
+	 * @param length
+	 * @return
+	 */
+	public Position[] getJavaRanges(int offset, int length) {
+
+		List results = new ArrayList();
+		Iterator it = getJava2JspMap().keySet().iterator();
+		Position p = null;
+		while(it.hasNext()) {
+			p = (Position)it.next();
+			if(p.overlapsWith(offset, length))
+				results.add(p);
+		}
+		return (Position[])results.toArray(new Position[results.size()]);
+	}
+	
+	/**
+	 * Indicates if the java Offset falls within the user import ranges
+	 * @param javaOffset
+	 * @return true if the java Offset falls within the user import ranges, otherwise false
+	 */
+	public boolean isImport(int javaOffset) {
+		return isInRanges(javaOffset, fJava2JspImportsMap);
+	}
+
+	/**
+	 * Indicates if the java offset falls within the use bean ranges
+	 * @param javaOffset
+	 * @return true if the java offset falls within the user import ranges, otherwise false
+	 */
+	public boolean isUseBean(int javaOffset) {
+		return isInRanges(javaOffset, fJava2JspUseBeanMap);
+	}
+	
+	/**
+	 * @param javaPos
+	 * @return
+	 */
+	public boolean isIndirect(int javaOffset) {
+		return isInRanges(javaOffset, fJava2JspIndirectMap, false);
+	}
+	
+	private boolean isInRanges(int javaOffset, HashMap ranges) {
+		return isInRanges(javaOffset, ranges, true);
+	}
+	/**
+	 * Tells you if the given offset is included in any of the ranges (Positions) passed in.
+	 * includeEndOffset tells whether or not to include the end offset of each range in the test.
+	 * 
+	 * @param javaOffset
+	 * @param ranges
+	 * @param includeEndOffset
+	 * @return
+	 */
+	private boolean isInRanges(int javaOffset, HashMap ranges, boolean includeEndOffset) {
+		
+		Iterator it = ranges.keySet().iterator();
+		while(it.hasNext()) {
+			Position javaPos = (Position)it.next();
+			// also include the start and end offset (only if requested)
+			// https://bugs.eclipse.org/bugs/show_bug.cgi?id=81687
+			if(javaPos.includes(javaOffset) || (includeEndOffset && javaPos.offset+javaPos.length == javaOffset)) 
+				return true;
+		}
+		return false;
+	}
+
+	/**
+	 * Return the Java CompilationUnit associated with this JSPTranslation (this particular model)
+	 * When using methods on the CU, it's reccomended to synchronize on the CU for reliable
+	 * results.
+	 * 
+	 * The method is synchronized to ensure that <code>createComplilationUnit</code> doesn't
+	 * get entered 2 or more times simultaneously.  A side effect of that is 2 compilation units
+	 * can be created in the JavaModelManager, but we only hold one reference to it in 
+	 * fCompilationUnit.  This would lead to a leak since only one instance of the CU is
+	 * discarded in the <code>release()</code> method.
+	 * 
+	 * @return a CompilationUnit representation of this JSPTranslation
+	 */
+	public ICompilationUnit getCompilationUnit() {
+		synchronized(fLock) {
+			try {
+				if (fCompilationUnit == null) {
+					fCompilationUnit = createCompilationUnit();
+				}
+			}
+			catch (JavaModelException jme) {
+				if(DEBUG)
+					Logger.logException("error creating JSP working copy... ", jme); //$NON-NLS-1$
+			}
+		}
+		return fCompilationUnit;
+	}
+
+	private String getMangledName() {
+		return fMangledName;
+	}
+	private void setMangledName(String mangledName) {
+		fMangledName = mangledName;
+	}
+	private String getJspName() {
+		return fJspName;
+	}
+
+	private void setJspName(String jspName) {
+		fJspName = jspName;
+	}
+
+	/**
+	 * Replaces mangled (servlet) name with jsp file name.
+	 * 
+	 * @param displayString
+	 * @return
+	 */
+	public String fixupMangledName(String displayString) {
+		
+		if(displayString == null)
+			return null;
+		
+		if(getJspName() == null || getMangledName() == null) {
+			// names not set yet
+			initJspAndServletNames();
+		}
+		return displayString.replaceAll(getMangledName(), getJspName());
+	}
+
+	private void initJspAndServletNames() {
+		ICompilationUnit cu = getCompilationUnit();
+		if(cu != null) {
+			String cuName = null;
+			synchronized(cu) {
+				// set some names for fixing up mangled name in proposals
+				// set mangled (servlet) name
+				 cuName = cu.getPath().lastSegment();
+			}
+			if(cuName != null) {
+				setMangledName(cuName.substring(0, cuName.lastIndexOf('.')));
+				// set name of jsp file
+				String unmangled = JSP2ServletNameUtil.unmangle(cuName);
+				setJspName(unmangled.substring(unmangled.lastIndexOf('/') + 1, unmangled.lastIndexOf('.')));
+			}
+		}
+	}
+
+	
+	/**
+	 * Originally from ReconcileStepForJava.  Creates an ICompilationUnit from the contents of the JSP document.
+	 * 
+	 * @return an ICompilationUnit from the contents of the JSP document
+	 */
+	private ICompilationUnit createCompilationUnit() throws JavaModelException {
+		
+		IJavaProject je = getJavaProject();
+
+		if (je == null || !je.exists())
+			return null;
+		
+		final String name = getClassname() + ".java";
+		IPackageFragmentRoot packageFragmentRoot = null;
+		IPackageFragmentRoot[] packageFragmentRoots = je.getPackageFragmentRoots();
+		for (int i = 0; i < packageFragmentRoots.length; i++) {
+			if (!packageFragmentRoots[i].isArchive() && !packageFragmentRoots[i].isExternal()) {
+				packageFragmentRoot = packageFragmentRoots[i];
+				break;
+			}
+		}
+		if (packageFragmentRoot == null) {
+			if(DEBUG) {
+				System.out.println("** Abort create working copy: cannot create working copy: JSP is not in a Java project with source package fragment root"); //$NON-NLS-1$
+			}
+			return null;
+		}
+		final IPackageFragment fragment = packageFragmentRoot.getPackageFragment(IPackageFragmentRoot.DEFAULT_PACKAGEROOT_PATH);
+		ICompilationUnit cu = fragment.getCompilationUnit(name).getWorkingCopy(getWorkingCopyOwner(), getProgressMonitor());
+		setContents(cu);
+
+		if(DEBUG) {
+			System.out.println("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"); //$NON-NLS-1$
+			System.out.println("(+) JSPTranslation ["+ this + "] finished creating CompilationUnit: " + cu); //$NON-NLS-1$ //$NON-NLS-2$
+			System.out.println("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"); //$NON-NLS-1$
+		}
+		
+		return cu;
+	}
+
+	/**
+	 * 
+	 * @return the problem requestor for the CompilationUnit in this JSPTranslation
+	 */
+	private JSPProblemRequestor getProblemRequestor() {
+	    return CompilationUnitHelper.getInstance().getProblemRequestor();
+	}
+
+	/**
+	 * 
+	 * @return the IWorkingCopyOwner for this CompilationUnit in this JSPTranslation
+	 */
+	public WorkingCopyOwner getWorkingCopyOwner() {
+	    return CompilationUnitHelper.getInstance().getWorkingCopyOwner();
+	}
+
+	/**
+	 * 
+	 * @return the progress monitor used in long operations (reconcile, creating the CompilationUnit...) in this JSPTranslation
+	 */
+	private IProgressMonitor getProgressMonitor() {
+		if (fProgressMonitor == null)
+			fProgressMonitor = new NullProgressMonitor();
+		return fProgressMonitor;
+	}
+
+	/**
+	 * 
+	 * @return the List of problems collected during reconcile of the compilation unit
+	 */
+	public List getProblems() {
+		List problems = getProblemRequestor().getCollectedProblems();
+		if (problems != null) {
+			if (fTranslationProblems.isEmpty()) {
+				return problems;
+			}
+			List combinedProblems = new ArrayList(problems);
+			combinedProblems.addAll(fTranslationProblems);
+			return combinedProblems;
+		}
+		return fTranslationProblems;
+	}
+
+	/**
+	 * Must be set true in order for problems to be collected during reconcile.
+	 * If set false, problems will be ignored during reconcile.
+	 * @param collect
+	 */
+	public void setProblemCollectingActive(boolean collect) {
+		ICompilationUnit cu = getCompilationUnit();
+		if(cu != null) {	
+			getProblemRequestor().setIsActive(collect);
+		}
+	}
+
+	public void retranslate(JSPTranslator translator) {
+		fTranslator = translator;
+		initialize();
+
+		synchronized (fLock) {
+			setContents(getCompilationUnit());
+		}
+	}
+
+	/**
+	 * Reconciles the compilation unit for this JSPTranslation
+	 */
+	public void reconcileCompilationUnit() {
+		ICompilationUnit cu = getCompilationUnit();
+		if (cu != null) {
+			try {
+				synchronized(cu) {
+					cu.makeConsistent(getProgressMonitor());
+					cu.reconcile(ICompilationUnit.NO_AST, false, getWorkingCopyOwner(), getProgressMonitor());
+				}
+			}
+			catch (JavaModelException e) {
+				Logger.logException(e);
+			}
+		}
+	}
+
+	/**
+	 * Set contents of the compilation unit to the translated jsp text.
+	 * @param the ICompilationUnit on which to set the buffer contents
+	 */
+	private void setContents(ICompilationUnit cu) {
+		if (cu == null)
+			return;
+		
+		synchronized (cu) {
+			IBuffer buffer;
+			try {
+				
+				buffer = cu.getBuffer();
+			}
+			catch (JavaModelException e) {
+				e.printStackTrace();
+				buffer = null;
+			}
+	
+			if (buffer != null)
+				buffer.setContents(getJavaText());
+		}
+	}
+
+	/**
+	 * Returns the IJavaElements corresponding to the JSP range in the JSP StructuredDocument
+	 * 
+	 * @param jspStart staring offset in the JSP document
+	 * @param jspEnd ending offset in the JSP document
+	 * @return IJavaElements corresponding to the JSP selection
+	 */
+	public IJavaElement[] getElementsFromJspRange(int jspStart, int jspEnd) {
+
+		int javaPositionStart = getJavaOffset(jspStart);
+		int javaPositionEnd = getJavaOffset(jspEnd);
+
+		IJavaElement[] EMTPY_RESULT_SET = new IJavaElement[0];
+		IJavaElement[] result = EMTPY_RESULT_SET;
+		try {
+			ICompilationUnit cu = getCompilationUnit();
+			if (cu != null) {
+				synchronized (cu) {
+					int cuDocLength = cu.getBuffer().getLength();
+					int javaLength = javaPositionEnd - javaPositionStart;
+					if (cuDocLength > 0 && javaPositionStart >= 0 && javaLength >= 0 && javaPositionEnd < cuDocLength) {
+						result = cu.codeSelect(javaPositionStart, javaLength);
+					}
+				}
+			}
+
+			if (result == null || result.length == 0)
+				return EMTPY_RESULT_SET;
+		}
+		catch (JavaModelException x) {
+			Logger.logException(x);
+		}
+
+		return result;
+	}
+
+	public String getClassname() {
+		return fClassname;
+	}
+
+	/**
+	 * Must discard compilation unit, or else they can leak in the JavaModelManager
+	 */
+	public void release() {
+		
+		synchronized (fLock) {
+			if (fCompilationUnit != null) {
+				Job discarder = new WorkspaceJob(fClassname) {
+					public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException {
+						try {
+							if (DEBUG) {
+								System.out.println("------------------------------------------------------------------"); //$NON-NLS-1$
+								System.out.println("(-) JSPTranslation [" + this + "] discarding CompilationUnit: " + fCompilationUnit); //$NON-NLS-1$ //$NON-NLS-2$
+								System.out.println("------------------------------------------------------------------"); //$NON-NLS-1$
+							}
+							fCompilationUnit.discardWorkingCopy();
+						}
+						catch (JavaModelException e) {
+							// we're done w/ it anyway
+						}
+						return Status.OK_STATUS;
+					}
+				};
+				discarder.schedule();
+			}
+		}
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/JSPTranslationAdapter.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/JSPTranslationAdapter.java
new file mode 100644
index 0000000..365fc1d
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/JSPTranslationAdapter.java
@@ -0,0 +1,269 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.java;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jface.text.Document;
+import org.eclipse.jface.text.DocumentEvent;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentListener;
+import org.eclipse.jst.jsp.core.internal.Logger;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapter;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+
+/**
+ * An adapter for getting a JSPTranslation of the document.
+ * 
+ * @author pavery
+ */
+public class JSPTranslationAdapter implements INodeAdapter, IDocumentListener {
+
+	// for debugging
+	private static final boolean DEBUG = "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.jst.jsp.core/debug/jsptranslation")); //$NON-NLS-1$  //$NON-NLS-2$
+
+	private IDocument fJspDocument = null;
+	private IDocument fJavaDocument = null;
+	private JSPTranslationExtension fJSPTranslation = null;
+	private boolean fDocumentIsDirty = true;
+	private IDOMModel fXMLModel;
+	private JSPTranslator fTranslator = null;
+	private NullProgressMonitor fTranslationMonitor = null;
+
+	/**
+	 * <p>Constructs a {@link JSPTranslationAdapter} that will create a new {@link JSPTranslator}<p>
+	 * 
+	 * @param xmlModel {@link IDOMModel} this {@link JSPTranslationAdapter} is for
+	 */
+	public JSPTranslationAdapter(IDOMModel xmlModel) {
+		setXMLModel(xmlModel);
+		initializeJavaPlugins();
+	}
+	
+	/**
+	 * <p>Constructs a {@link JSPTranslationAdapter} using an existing {@link JSPTranslator}</p>
+	 * 
+	 * @param xmlModel {@link IDOMModel} this {@link JSPTranslationAdapter} is for
+	 * @param translator existing {@link JSPTranslator} this {@link JSPTranslationAdapter} will use
+	 */
+	public JSPTranslationAdapter(IDOMModel xmlModel, JSPTranslator translator) {
+		this(xmlModel);
+		this.fTranslator = translator;
+		this.fJavaDocument = new Document(translator.getTranslation().toString());
+		this.fJSPTranslation = new JSPTranslationExtension(getXMLModel().getStructuredDocument(), fJavaDocument, getJavaProject(), this.fTranslator);
+		this.fDocumentIsDirty = false;
+	}
+
+	/**
+	 * Initialize the required Java Plugins
+	 */
+	protected void initializeJavaPlugins() {
+		JavaCore.getPlugin();
+	}
+
+	public boolean isAdapterForType(Object type) {
+		return type.equals(IJSPTranslation.class);
+	}
+
+	public void notifyChanged(INodeNotifier notifier, int eventType, Object changedFeature, Object oldValue, Object newValue, int pos) {
+		// nothing to do
+	}
+
+	/**
+	 * Automatically set through the setXMLModel(XMLModel)
+	 * 
+	 * @param doc
+	 */
+	private void setDocument(IDocument doc) {
+		if (fJspDocument != null)
+			fJspDocument.removeDocumentListener(this);
+		if (doc != null) {
+			doc.addDocumentListener(this);
+			fJspDocument = doc;
+		}
+	}
+
+	/**
+	 * @see org.eclipse.jface.text.IDocumentListener#documentAboutToBeChanged(org.eclipse.jface.text.DocumentEvent)
+	 */
+	public void documentAboutToBeChanged(DocumentEvent event) {
+		// do nothing
+	}
+
+	/**
+	 * @see org.eclipse.jface.text.IDocumentListener#documentChanged(org.eclipse.jface.text.DocumentEvent)
+	 */
+	public void documentChanged(DocumentEvent event) {
+		// mark translation for rebuilding
+		fDocumentIsDirty = true;
+	}
+
+	public void release() {
+
+		if (fJspDocument != null)
+			fJspDocument.removeDocumentListener(this);
+
+		if (fTranslationMonitor != null)
+			fTranslationMonitor.setCanceled(true);
+
+		if (fJSPTranslation != null) {
+
+			if (DEBUG)
+				System.out.println("JSPTranslationAdapter releasing:" + fJSPTranslation); //$NON-NLS-1$
+
+			fJSPTranslation.release();
+		}
+	}
+
+	/**
+	 * <p>Returns the JSPTranslation for this adapter.</p>
+	 * 
+	 * <p><b>IMPORTANT: </b><i>This will force translation of the
+	 * document if it has not already been called.  To avoid
+	 * accidental translation before calling this method call
+	 * {@link #hasTranslation()} to verify a translation
+	 * has already been forced by this adapter.</i></p>
+	 * 
+	 * @return a JSPTranslationExtension
+	 */
+	public synchronized JSPTranslationExtension getJSPTranslation() {
+
+		if (fJSPTranslation == null || fDocumentIsDirty) {
+			JSPTranslator translator = null;
+			if (getXMLModel() != null && getXMLModel().getIndexedRegion(0) != null) {
+				translator = getTranslator((IDOMNode) getXMLModel().getIndexedRegion(0));
+				translator.translate();
+				StringBuffer javaContents = translator.getTranslation();
+				fJavaDocument = new Document(javaContents.toString());
+			}
+			else {
+				// empty document case
+				translator = createTranslator();
+				StringBuffer emptyContents = translator.getEmptyTranslation();
+				fJavaDocument = new Document(emptyContents.toString());
+			}
+			// Just a dirty translation, re-translate
+			if (fJSPTranslation != null) {
+				if (DEBUG)
+					System.out.println("JSPTranslationAdapter retranslating:" + fJSPTranslation); //$NON-NLS-1$
+				fJSPTranslation.retranslate(fJavaDocument, translator);
+				fDocumentIsDirty = false;
+				return fJSPTranslation;
+			}
+			fJSPTranslation = new JSPTranslationExtension(getXMLModel().getStructuredDocument(), fJavaDocument, getJavaProject(), translator);
+			fDocumentIsDirty = false;
+		}
+		return fJSPTranslation;
+	}
+	
+	/**
+	 * <p>Knowing weather the translation has already been retrieved
+	 * from this adapter is important if you do not wan't to force
+	 * the translation of a document that has not yet been translated</p>
+	 * 
+	 * @return <code>true</code> if {@link #getJSPTranslation()} has
+	 * been called on this adapter already, <code>false</code> otherwise
+	 */
+	public boolean hasTranslation() {
+		return fJSPTranslation != null;
+	}
+
+	JSPTranslator createTranslator() {
+		return new JSPTranslator();
+	}
+
+	/**
+	 * Returns the JSPTranslator for this adapter. If it's null, a new
+	 * translator is created with the xmlNode. Otherwise the
+	 * translator.reset(xmlNode) is called to reset the current local
+	 * translator.
+	 * 
+	 * @param xmlNode
+	 *            the first node of the JSP document to be translated
+	 * @return the JSPTranslator for this adapter (creates if null)
+	 */
+	private JSPTranslator getTranslator(IDOMNode xmlNode) {
+		if (fTranslator == null) {
+			fTranslationMonitor = new NullProgressMonitor();
+			fTranslator = createTranslator();
+			fTranslator.reset(xmlNode, fTranslationMonitor);
+		}
+		else
+			fTranslator.reset(xmlNode, fTranslationMonitor);
+		return fTranslator;
+	}
+
+	/**
+	 * set the XMLModel for this adapter. Must be called.
+	 * 
+	 * @param xmlModel
+	 */
+	public void setXMLModel(IDOMModel xmlModel) {
+		fXMLModel = xmlModel;
+		setDocument(fXMLModel.getStructuredDocument());
+	}
+
+	/**
+	 * @return the XMLModel for this adapter.
+	 */
+	private IDOMModel getXMLModel() {
+		return fXMLModel;
+	}
+
+	/**
+	 * Gets (or creates via JavaCore) a JavaProject based on the location of
+	 * this adapter's XMLModel. Returns null for non IFile based models.
+	 * 
+	 * @return the java project where
+	 */
+	public IJavaProject getJavaProject() {
+
+		IJavaProject javaProject = null;
+		try {
+			String baseLocation = getXMLModel().getBaseLocation();
+			// 20041129 (pa) the base location changed for XML model
+			// because of FileBuffers, so this code had to be updated
+			// https://bugs.eclipse.org/bugs/show_bug.cgi?id=79686
+			IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+			IPath filePath = new Path(baseLocation);
+			IProject project = null;
+			if (filePath.segmentCount() > 0) {
+				project = root.getProject(filePath.segment(0));
+			}
+//			IFile[] files = ResourcesPlugin.getWorkspace().getRoot().findFilesForLocation(new Path(baseLocation));
+//			for (int i = 0; project == null && i < files.length; i++) {
+//				if (files[i].getType() != IResource.PROJECT) {
+//					project = files[i].getProject();
+//					break;
+//				}
+//			}
+			if (project != null) {
+				javaProject = JavaCore.create(project);
+			}
+		}
+		catch (Exception ex) {
+			if (getXMLModel() != null)
+				Logger.logException("(JSPTranslationAdapter) problem getting java project from the XMLModel's baseLocation > " + getXMLModel().getBaseLocation(), ex); //$NON-NLS-1$
+			else
+				Logger.logException("(JSPTranslationAdapter) problem getting java project", ex); //$NON-NLS-1$
+		}
+		return javaProject;
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/JSPTranslationAdapterFactory.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/JSPTranslationAdapterFactory.java
new file mode 100644
index 0000000..52cac51
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/JSPTranslationAdapterFactory.java
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.java;
+
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.wst.sse.core.internal.provisional.AbstractAdapterFactory;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapter;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+
+/**
+ * Factory for JSPTranslationAdapters.
+ * 
+ * @author pavery
+ *  
+ */
+public class JSPTranslationAdapterFactory extends AbstractAdapterFactory {
+
+	/** the adapter associated with this factory */
+	private JSPTranslationAdapter fAdapter = null;
+
+	// for debugging
+	static final boolean DEBUG = Boolean.valueOf(Platform.getDebugOption("org.eclipse.jst.jsp.core/debug/jsptranslation")).booleanValue(); //$NON-NLS-1$;
+	
+	public JSPTranslationAdapterFactory() {
+		super(IJSPTranslation.class, true);
+	}
+
+
+	protected INodeAdapter createAdapter(INodeNotifier target) {
+		if (target instanceof IDOMNode && fAdapter == null) {
+			/* attempt to load externalized translator and create adapter from it
+			 * else create new adapter */
+			IDOMModel model = ((IDOMNode) target).getModel();
+			
+			JSPTranslator translator = JSPTranslatorPersister.getPersistedTranslator(model);
+			if(translator != null) {
+				fAdapter = new JSPTranslationAdapter(model, translator);
+			} else {
+				fAdapter= new JSPTranslationAdapter(model);
+			}
+
+			if(DEBUG) {
+				System.out.println("(+) JSPTranslationAdapterFactory [" + this + "] created adapter: " + fAdapter); //$NON-NLS-1$ //$NON-NLS-2$
+			}
+		}
+		return fAdapter;
+	}
+
+
+	public void release() {
+		if(fAdapter != null) {
+			if(DEBUG) {
+				System.out.println("(-) JSPTranslationAdapterFactory [" + this + "] releasing adapter: " + fAdapter); //$NON-NLS-1$ //$NON-NLS-2$
+			}
+			fAdapter.release();
+		}
+	
+		super.release();
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/JSPTranslationExtension.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/JSPTranslationExtension.java
new file mode 100644
index 0000000..9184076
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/JSPTranslationExtension.java
@@ -0,0 +1,472 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.java;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.ToolFactory;
+import org.eclipse.jdt.core.formatter.CodeFormatter;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.TextUtilities;
+import org.eclipse.jst.jsp.core.internal.Logger;
+import org.eclipse.jst.jsp.core.internal.regions.DOMJSPRegionContexts;
+import org.eclipse.text.edits.DeleteEdit;
+import org.eclipse.text.edits.InsertEdit;
+import org.eclipse.text.edits.MalformedTreeException;
+import org.eclipse.text.edits.MultiTextEdit;
+import org.eclipse.text.edits.ReplaceEdit;
+import org.eclipse.text.edits.TextEdit;
+import org.eclipse.text.edits.UndoEdit;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+
+import com.ibm.icu.util.StringTokenizer;
+
+
+/**
+ * Adds the notion of IDocuments (jsp Document and java Document) Used for
+ * TextEdit translation
+ * 
+ * @author pavery
+ */
+public class JSPTranslationExtension extends JSPTranslation {
+
+	// for debugging
+	private static final boolean DEBUG;
+	static {
+		String value = Platform.getDebugOption("org.eclipse.jst.jsp.core/debug/jsptranslation"); //$NON-NLS-1$
+		DEBUG = value != null && value.equalsIgnoreCase("true"); //$NON-NLS-1$
+	}
+
+	// just a convenience data structure
+	// to keep track of java position deltas
+	private class PositionDelta {
+
+		public boolean isDeleted = false;
+		public int preOffset = 0;
+		public int preLength = 0;
+		public int postOffset = 0;
+		public int postLength = 0;
+
+		public PositionDelta(int preOffset, int preLength) {
+			this.preOffset = preOffset;
+			this.preLength = preLength;
+		}
+
+		public void setPostEditData(int postOffset, int postLength, boolean isDeleted) {
+			this.postOffset = postOffset;
+			this.postLength = postLength;
+			this.isDeleted = isDeleted;
+		}
+	}
+
+	private IDocument fJspDocument = null;
+	private IDocument fJavaDocument = null;
+	private CodeFormatter fCodeFormatter = null;
+
+	public JSPTranslationExtension(IDocument jspDocument, IDocument javaDocument, IJavaProject javaProj, JSPTranslator translator) {
+		super(javaProj, translator);
+		fJspDocument = jspDocument;
+		fJavaDocument = javaDocument;
+
+		// make sure positions are added to Java and JSP documents
+		// this is necessary for text edits
+		addPositionsToDocuments();
+	}
+
+	public void retranslate(IDocument javaDocument, JSPTranslator translator) {
+		fJavaDocument = javaDocument;
+		retranslate(translator);
+
+		addPositionsToDocuments();
+	}
+
+	public IDocument getJspDocument() {
+		return fJspDocument;
+	}
+
+	public IDocument getJavaDocument() {
+		return fJavaDocument;
+	}
+
+	public String getJavaText() {
+		return getJavaDocument() != null ? getJavaDocument().get() : ""; //$NON-NLS-1$
+	}
+
+	/**
+	 * Returns a corresponding TextEdit for the JSP file given a TextEdit for
+	 * a Java file.
+	 * 
+	 * @param javaEdit
+	 * @return the corresponding JSP edits (not applied to the document yet)
+	 */
+	public TextEdit getJspEdit(TextEdit javaEdit) {
+
+		if (javaEdit == null)
+			return null;
+
+		List jspEdits = new ArrayList();
+
+		int offset = javaEdit.getOffset();
+		int length = javaEdit.getLength();
+
+		if (javaEdit instanceof MultiTextEdit && javaEdit.getChildren().length > 0) {
+
+			IRegion r = TextEdit.getCoverage(getAllEdits(javaEdit));
+			offset = r.getOffset();
+			length = r.getLength();
+		}
+
+		// get java ranges that will be affected by the edit
+		Position[] javaPositions = getJavaRanges(offset, length);
+
+		// record position data before the change
+		Position[] jspPositions = new Position[javaPositions.length];
+		PositionDelta[] deltas = new PositionDelta[javaPositions.length];
+		for (int i = 0; i < javaPositions.length; i++) {
+			deltas[i] = new PositionDelta(javaPositions[i].offset, javaPositions[i].length);
+			// isIndirect means the position doesn't actually exist as exact
+			// text
+			// mapping from java <-> jsp (eg. an import statement)
+			if (!isIndirect(javaPositions[i].offset))
+				jspPositions[i] = (Position) getJava2JspMap().get(javaPositions[i]);
+		}
+
+		if (DEBUG) {
+			System.out.println("================================================"); //$NON-NLS-1$
+			System.out.println("deltas:"); //$NON-NLS-1$
+			String javaText = getJavaText();
+			for (int i = 0; i < deltas.length; i++)
+				System.out.println("pos[" + deltas[i].preOffset + ":" + deltas[i].preLength + "]" + javaText.substring(deltas[i].preOffset, deltas[i].preOffset + deltas[i].preLength)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+			System.out.println("==============================================="); //$NON-NLS-1$
+		}
+		UndoEdit undo = null;
+		// apply the edit to the java document
+		try {
+			undo = javaEdit.apply(getJavaDocument());
+		}
+		catch (MalformedTreeException e) {
+			Logger.logException(e);
+		}
+		catch (BadLocationException e) {
+			Logger.logException(e);
+		}
+		// now at this point Java positions are unreliable since they were
+		// updated after applying java edit.
+
+		String newJavaText = getJavaDocument().get();
+		if (DEBUG)
+			System.out.println("java post format text:\n" + newJavaText); //$NON-NLS-1$
+
+		// record post edit data
+		for (int i = 0; i < javaPositions.length; i++)
+			deltas[i].setPostEditData(javaPositions[i].offset, javaPositions[i].length, javaPositions[i].isDeleted);
+
+		// create appropriate text edits for deltas
+		Position jspPos = null;
+		String replaceText = ""; //$NON-NLS-1$
+		for (int i = 0; i < deltas.length; i++) {
+			jspPos = jspPositions[i];
+			// can be null if it's an indirect mapping position
+			// or if something was added into java that was not originally in
+			// JSP (like a new import...)
+
+			if (jspPos != null) {
+				if (deltas[i].isDeleted) {
+					jspEdits.add(new DeleteEdit(jspPos.offset, jspPos.length));
+				}
+				else {
+					replaceText = newJavaText.substring(deltas[i].postOffset, deltas[i].postOffset + deltas[i].postLength);
+
+					// get rid of pre and post white space or fine tuned
+					// adjustment later.
+					// fix text here...
+					replaceText = fixJspReplaceText(replaceText, jspPos.offset);
+
+					jspEdits.add(new ReplaceEdit(jspPos.offset, jspPos.length, replaceText));
+				}
+				if (DEBUG)
+					debugReplace(deltas, jspPos, replaceText, i);
+			}
+			else {
+				// the new Java text has no corresponding JSP position
+				// possible new import?
+				if (isImport(javaPositions[i].getOffset()) && replaceText.lastIndexOf("import ") != -1) { //$NON-NLS-1$
+					replaceText = newJavaText.substring(deltas[i].postOffset, deltas[i].postOffset + deltas[i].postLength);
+					String importText = replaceText.substring(replaceText.lastIndexOf("import "), replaceText.indexOf(";")); //$NON-NLS-1$ //$NON-NLS-2$
+					// evenutally need to check if it's XML-JSP
+					importText = "<%@page import=\"" + importText + "\" %>\n"; //$NON-NLS-1$ //$NON-NLS-2$
+					jspEdits.add(new InsertEdit(0, importText));
+				}
+			}
+		}
+		TextEdit allJspEdits = createMultiTextEdit((TextEdit[]) jspEdits.toArray(new TextEdit[jspEdits.size()]));
+
+		// https://bugs.eclipse.org/bugs/show_bug.cgi?id=105632
+		// undo the java edit
+		// (so the underlying Java document still represents what's in the
+		// editor)
+		if (undo != null) {
+			try {
+				undo.apply(getJavaDocument());
+			}
+			catch (MalformedTreeException e) {
+				Logger.logException(e);
+			}
+			catch (BadLocationException e) {
+				Logger.logException(e);
+			}
+		}
+
+		return allJspEdits;
+	}
+
+	private String fixJspReplaceText(String replaceText, int jspOffset) {
+
+		// result is the text inbetween the delimiters
+		// eg.
+		// 
+		// <% result
+		// %>
+		String result = replaceText.trim();
+		String preDelimiterWhitespace = ""; //$NON-NLS-1$
+
+		IDocument jspDoc = getJspDocument();
+		if (jspDoc instanceof IStructuredDocument) {
+			IStructuredDocument sDoc = (IStructuredDocument) jspDoc;
+			IStructuredDocumentRegion[] regions = sDoc.getStructuredDocumentRegions(0, jspOffset);
+			IStructuredDocumentRegion lastRegion = regions[regions.length - 1];
+
+			// only specifically modify scriptlets
+			if (lastRegion != null && lastRegion.getType() == DOMJSPRegionContexts.JSP_SCRIPTLET_OPEN) {
+				for (int i = regions.length - 1; i >= 0; i--) {
+					IStructuredDocumentRegion region = regions[i];
+
+					// is there a better way to check whitespace?
+					if (region.getType() == DOMRegionContext.XML_CONTENT && region.getFullText().trim().equals("")) { //$NON-NLS-1$
+
+						preDelimiterWhitespace = region.getFullText();
+						preDelimiterWhitespace = preDelimiterWhitespace.replaceAll("\r", ""); //$NON-NLS-1$ //$NON-NLS-2$
+						preDelimiterWhitespace = preDelimiterWhitespace.replaceAll("\n", ""); //$NON-NLS-1$ //$NON-NLS-2$
+
+						// need to determine indent for that first line...
+						String initialIndent = getInitialIndent(result);
+
+						// fix the first line of java code
+						result = TextUtilities.getDefaultLineDelimiter(sDoc) + initialIndent + result;
+
+						result = adjustIndent(result, preDelimiterWhitespace, TextUtilities.getDefaultLineDelimiter(sDoc));
+
+						// add whitespace before last delimiter to match
+						// it w/ the opening delimiter
+						result = result + TextUtilities.getDefaultLineDelimiter(sDoc) + preDelimiterWhitespace;
+						break;
+					}
+				}
+			}
+		}
+		return result;
+	}
+
+	private String adjustIndent(String textBefore, String indent, String delim) {
+
+		// first replace multiple indent with single indent
+		// the triple indent occurs because the scriptlet code
+		// actually occurs under:
+		// 
+		// class
+		// method
+		// code
+		// 
+		// in the translated java document
+		// BUG188636 - just get indent info from code formatter
+		String level1 = getCodeFormatter().createIndentationString(1);
+		String level3 = getCodeFormatter().createIndentationString(3);
+		String theOld = "\n" + level3; //$NON-NLS-1$
+		String theNew = "\n" + level1; //$NON-NLS-1$
+		textBefore = textBefore.replaceAll(theOld, theNew);
+
+		// get indent after 2nd line break
+		StringBuffer textAfter = new StringBuffer();
+		// will this work on mac?
+		textBefore = textBefore.replaceAll("\r", ""); //$NON-NLS-1$ //$NON-NLS-2$
+		StringTokenizer st = new StringTokenizer(textBefore, "\n", true); //$NON-NLS-1$
+		while (st.hasMoreTokens()) {
+			String tok = st.nextToken();
+			if (tok.equals("\n")) { //$NON-NLS-1$
+				textAfter.append(delim);
+			}
+			else {
+				// prepend each line w/ specified indent
+				textAfter.append(indent);
+				textAfter.append(tok);
+			}
+		}
+		return textAfter.toString();
+
+	}
+
+	private String getInitialIndent(String result) {
+		// BUG188636 - just get initial indent from code formatter
+		String indent = getCodeFormatter().createIndentationString(1);
+		// // get indent after 2nd line break
+		// String indent = ""; //$NON-NLS-1$
+		// StringTokenizer st = new StringTokenizer(result, "\r\n", false);
+		// //$NON-NLS-1$
+		// if (st.countTokens() > 1) {
+		// String tok = st.nextToken();
+		// tok = st.nextToken();
+		// int index = 0;
+		// if (tok != null) {
+		// while (tok.charAt(index) == ' ' || tok.charAt(index) == '\t') {
+		// indent += tok.charAt(index);
+		// index++;
+		// }
+		// }
+		// }
+		return indent;
+	}
+
+	private CodeFormatter getCodeFormatter() {
+		if (fCodeFormatter == null)
+			fCodeFormatter = ToolFactory.createCodeFormatter(null);
+		return fCodeFormatter;
+	}
+
+
+	/**
+	 * Combines an array of edits into one MultiTextEdit (with the appropriate
+	 * coverage region)
+	 * 
+	 * @param edits
+	 * @return
+	 */
+	private TextEdit createMultiTextEdit(TextEdit[] edits) {
+
+		if (edits.length == 0)
+			return new MultiTextEdit();
+
+		/* should not specify a limited region because other edits outside
+		 * these original edits might be added later.
+		 */
+		MultiTextEdit multiEdit = new MultiTextEdit();
+		for (int i = 0; i < edits.length; i++) {
+			addToMultiEdit(edits[i], multiEdit);
+		}
+		return multiEdit;
+	}
+
+
+	private void addToMultiEdit(TextEdit edit, MultiTextEdit multiEdit) {
+
+		// check for overlap here
+		// discard overlapping edits..
+		// possible exponential performance hit... need a better way...
+		TextEdit[] children = multiEdit.getChildren();
+		for (int i = 0; i < children.length; i++) {
+			if (children[i].covers(edit))
+				// don't add
+				return;
+		}
+		multiEdit.addChild(edit);
+	}
+
+
+	/**
+	 * @param translation
+	 */
+	private void addPositionsToDocuments() {
+
+		// can be null if it's a NullJSPTranslation
+		if (getJavaDocument() != null && getJspDocument() != null) {
+
+			HashMap java2jsp = getJava2JspMap();
+			Iterator it = java2jsp.keySet().iterator();
+			Position javaPos = null;
+			while (it.hasNext()) {
+				javaPos = (Position) it.next();
+				try {
+
+					fJavaDocument.addPosition(javaPos);
+
+				}
+				catch (BadLocationException e) {
+					if (DEBUG) {
+						System.out.println("tyring to add Java Position:[" + javaPos.offset + ":" + javaPos.length + "] to " + getJavaPath()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$					
+						// System.out.println("substring :[" +
+						// fJavaDocument.get().substring(javaPos.offset) +
+						// "]"); //$NON-NLS-1$ //$NON-NLS-2$
+						Logger.logException(e);
+					}
+				}
+
+				try {
+
+					fJspDocument.addPosition((Position) java2jsp.get(javaPos));
+
+				}
+				catch (BadLocationException e) {
+					if (DEBUG) {
+						System.out.println("tyring to add JSP Position:[" + ((Position) java2jsp.get(javaPos)).offset + ":" + ((Position) java2jsp.get(javaPos)).length + "] to " + getJavaPath()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+						Logger.logException(e);
+					}
+				}
+			}
+		}
+	}
+
+	/**
+	 * Recursively gets all child edits
+	 * 
+	 * @param javaEdit
+	 * @return all child edits
+	 */
+	private TextEdit[] getAllEdits(TextEdit javaEdit) {
+
+		List result = new ArrayList();
+		if (javaEdit instanceof MultiTextEdit) {
+			TextEdit[] children = javaEdit.getChildren();
+			for (int i = 0; i < children.length; i++)
+				result.addAll(Arrays.asList(getAllEdits(children[i])));
+		}
+		else
+			result.add(javaEdit);
+		return (TextEdit[]) result.toArray(new TextEdit[result.size()]);
+	}
+
+	/**
+	 * @param deltas
+	 * @param jspPos
+	 * @param replaceText
+	 * @param jspText
+	 * @param i
+	 */
+	private void debugReplace(PositionDelta[] deltas, Position jspPos, String replaceText, int i) {
+		String jspChunk;
+		jspChunk = getJspDocument().get().substring(jspPos.offset, jspPos.offset + jspPos.length);
+		if (!deltas[i].isDeleted) {
+			System.out.println("replacing:"); //$NON-NLS-1$
+			System.out.println("jsp:[" + jspChunk + "]"); //$NON-NLS-1$ //$NON-NLS-2$
+			System.out.println("w/ :[" + replaceText + "]"); //$NON-NLS-1$ //$NON-NLS-2$
+			System.out.println("--------------------------------"); //$NON-NLS-1$
+		}
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/JSPTranslationUtil.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/JSPTranslationUtil.java
new file mode 100644
index 0000000..2d72c36
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/JSPTranslationUtil.java
@@ -0,0 +1,125 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.java;
+
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jst.jsp.core.internal.modelhandler.ModelHandlerForJSP;
+import org.eclipse.text.edits.CopySourceEdit;
+import org.eclipse.text.edits.CopyTargetEdit;
+import org.eclipse.text.edits.DeleteEdit;
+import org.eclipse.text.edits.InsertEdit;
+import org.eclipse.text.edits.MoveSourceEdit;
+import org.eclipse.text.edits.MoveTargetEdit;
+import org.eclipse.text.edits.MultiTextEdit;
+import org.eclipse.text.edits.ReplaceEdit;
+import org.eclipse.text.edits.TextEdit;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.IModelManager;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
+
+public class JSPTranslationUtil {
+	protected IDocument fDocument = null;
+	protected JSPTranslationExtension fTranslation = null;
+
+	public JSPTranslationUtil(IDocument document) {
+		fDocument = document;
+	}
+
+	public TextEdit translateTextEdit(TextEdit textEdit) {
+		TextEdit translatedTextEdit = null;
+
+		int javaOffset = textEdit.getOffset();
+		int jspOffset = getTranslation().getJspOffset(textEdit.getOffset());
+		int length = textEdit.getLength();
+
+		if (textEdit instanceof MultiTextEdit) {
+			translatedTextEdit = new MultiTextEdit();
+			TextEdit[] children = ((MultiTextEdit) textEdit).getChildren();
+			for (int i = 0; i < children.length; i++) {
+				TextEdit translatedChildTextEdit = translateTextEdit(children[i]);
+				if (translatedChildTextEdit != null)
+					((MultiTextEdit) translatedTextEdit).addChild(translatedChildTextEdit);
+			}
+		}
+		else if (textEdit instanceof ReplaceEdit) {
+			if (jspOffset == -1)
+				return null;
+
+			if (!getTranslation().javaSpansMultipleJspPartitions(javaOffset, length))
+				translatedTextEdit = new ReplaceEdit(jspOffset, length, ((ReplaceEdit) textEdit).getText());
+		}
+		else if (textEdit instanceof InsertEdit) {
+			translatedTextEdit = new InsertEdit(jspOffset, ((InsertEdit) textEdit).getText());
+		}
+		else if (textEdit instanceof DeleteEdit) {
+			translatedTextEdit = new DeleteEdit(jspOffset, length);
+			TextEdit[] children = ((DeleteEdit) textEdit).getChildren();
+			for (int i = 0; i < children.length; i++) {
+				TextEdit translatedChildTextEdit = translateTextEdit(children[i]);
+				if (translatedChildTextEdit != null)
+					((DeleteEdit) translatedTextEdit).addChild(translatedChildTextEdit);
+			}
+		}
+		else if (textEdit instanceof CopySourceEdit) {
+			translatedTextEdit = new CopySourceEdit(jspOffset, length);
+			((CopySourceEdit) translatedTextEdit).setTargetEdit(((CopySourceEdit) textEdit).getTargetEdit());
+			((CopySourceEdit) translatedTextEdit).setSourceModifier(((CopySourceEdit) textEdit).getSourceModifier());
+		}
+		else if (textEdit instanceof CopyTargetEdit) {
+			translatedTextEdit = new CopyTargetEdit(jspOffset);
+			((CopyTargetEdit) textEdit).getSourceEdit().setTargetEdit((CopyTargetEdit) translatedTextEdit);
+		}
+		else if (textEdit instanceof MoveSourceEdit) {
+			translatedTextEdit = new MoveSourceEdit(jspOffset, length);
+			((MoveSourceEdit) translatedTextEdit).setTargetEdit(((MoveSourceEdit) textEdit).getTargetEdit());
+		}
+		else if (textEdit instanceof MoveTargetEdit) {
+			translatedTextEdit = new MoveTargetEdit(jspOffset);
+			((MoveTargetEdit) textEdit).getSourceEdit().setTargetEdit((MoveTargetEdit) translatedTextEdit);
+		}
+		else {
+			System.out.println("Need to translate " + textEdit); //$NON-NLS-1$
+		}
+
+		return translatedTextEdit;
+	}
+
+	public JSPTranslationExtension getTranslation() {
+		if (fTranslation == null) {
+			IDOMModel xmlModel = (IDOMModel) getModelManager().getExistingModelForRead(fDocument);
+			ModelHandlerForJSP.ensureTranslationAdapterFactory(xmlModel);
+			try {
+				IDOMDocument xmlDoc = xmlModel.getDocument();
+
+				JSPTranslationAdapter translationAdapter = (JSPTranslationAdapter) xmlDoc.getAdapterFor(IJSPTranslation.class);
+				if (translationAdapter != null)
+					fTranslation = translationAdapter.getJSPTranslation();
+			}
+			finally {
+				if (xmlModel != null) {
+					xmlModel.releaseFromRead();
+				}
+			}
+		}
+
+		return fTranslation;
+	}
+
+	public ICompilationUnit getCompilationUnit() {
+		return getTranslation().getCompilationUnit();
+	}
+
+	protected IModelManager getModelManager() {
+		return StructuredModelManager.getModelManager();
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/JSPTranslator.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/JSPTranslator.java
new file mode 100644
index 0000000..cb4f04d
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/JSPTranslator.java
@@ -0,0 +1,3603 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2011 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 = 2L;
+	
+	/** 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); //$NON-NLS-1$
+		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); //$NON-NLS-1$
+			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); //$NON-NLS-1$
+
+		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); //$NON-NLS-1$
+			/* 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_VBL_CONTENT.equals(type) || DOMJSPRegionContexts.JSP_EL_DQUOTE.equals(type) || DOMJSPRegionContexts.JSP_VBL_DQUOTE.equals(type) || DOMJSPRegionContexts.JSP_EL_QUOTED_CONTENT.equals(type) || DOMJSPRegionContexts.JSP_VBL_QUOTED_CONTENT.equals(type) || DOMJSPRegionContexts.JSP_EL_SQUOTE.equals(type) || DOMJSPRegionContexts.JSP_VBL_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(container,regions);
+				}
+			}
+		}
+	}
+
+	/**
+	 * translates embedded containers for ALL attribute values
+	 * 
+	 * @param regions
+	 */
+	private void checkAllAttributeValueContainers(ITextRegionCollection container, Iterator regions) {
+		// tag name is not jsp
+		// handle embedded jsp attributes...
+		ITextRegion embedded = null;
+		// Iterator attrRegions = null;
+		// ITextRegion attrChunk = null;
+		ITextRegion prevRegion = null;
+		while (regions.hasNext()) {
+			embedded = (ITextRegion) regions.next();
+			if (embedded.getType() == DOMRegionContext.XML_TAG_NAME || embedded.getType() == DOMJSPRegionContexts.JSP_DIRECTIVE_NAME)
+
+			{
+				String fullTagName = container.getText(embedded);
+				if (fullTagName.indexOf(':') > -1 && !fullTagName.startsWith(JSP_PREFIX)) {
+					if (prevRegion != null)
+					addCustomTaglibVariables(fullTagName, container,prevRegion,-1); // it may be a custom tag
+				}
+			}
+				else 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;
+				// }
+				// }
+			}
+			prevRegion = embedded;
+		}
+	}
+
+	/**
+	 * 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)) { //$NON-NLS-1$
+				// 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('[')); //$NON-NLS-1$
+					}
+					// 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;
+		IStructuredDocument structuredDocument = getStructuredDocument();
+		if (structuredDocument != null) {
+			ITextFileBuffer buffer = FileBufferModelManager.getInstance().getBuffer(structuredDocument);
+			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.writeChars(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();
+		char charArray[] = new char[length];
+		for(int i=0; i < length;i++){
+			charArray[i] = in.readChar();
+		}
+		return new String(charArray);
+	}
+	
+	/**
+	 * <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;
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/JSPTranslatorPersister.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/JSPTranslatorPersister.java
new file mode 100644
index 0000000..d41723b
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/JSPTranslatorPersister.java
@@ -0,0 +1,279 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.java;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InvalidClassException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.zip.CRC32;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jst.jsp.core.internal.JSPCorePlugin;
+import org.eclipse.jst.jsp.core.internal.Logger;
+import org.eclipse.jst.jsp.core.internal.java.search.JSPIndexManager;
+import org.eclipse.jst.jsp.core.internal.modelhandler.ModelHandlerForJSP;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.FileBufferModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
+
+/**
+ * <p>This is a static class used to persist JSP translations and retrieve the persisted
+ * translations.</p>
+ * 
+ * <p>It is not actually in charge of finding files to persist, rather it provides API
+ * for some other mechanism that tracks JSP files to call into to persist the translations.</p>
+ * 
+ * <p>This class can be deactivated through the <code>persistJSPTranslations</code> system property,
+ * a value of <code>true</code> means the persister is activated (which is the default), value of
+ * <code>false</code> means the persister is not activated.</p>
+ * 
+ * @see JSPIndexManager
+ */
+public class JSPTranslatorPersister{
+	/**
+	 * <code>true</code> if the persister is activated, <code>false</code>
+	 * otherwise.  This is determined by checking the system property
+	 * <code>persistJSPTranslations</code>, if no value supplied then
+	 * default is <code>true</code>
+	 */
+	public static final boolean ACTIVATED =
+		Boolean.valueOf(System.getProperty("persistJSPTranslations", "true")).booleanValue(); //$NON-NLS-1$ //$NON-NLS-2$
+	
+	/** the location where {@link JSPTranslator}s are externalized too for persistence purposes */
+	private static final IPath PERSIST_LOCATION = JSPCorePlugin.getDefault().getStateLocation().append("translators"); //$NON-NLS-1$
+	
+	/** used to calculate persisted translator file names */
+	private static final CRC32 CHECKSUM_CALC = new CRC32();
+	
+	/** lock to use while using the checksum */
+	private static final Object CHECKSUM_CALC_LOCK = new Object();
+	
+	/**
+	 * <p>Private constructor to prevent creating an instance of this class</p>
+	 */
+	private JSPTranslatorPersister() {
+	}
+	
+	/**
+	 * <p>Given the {@link IStructuredModel} of a JSP file attempts to retrieve the persisted
+	 * {@link JSPTranslator} for that model.</p>
+	 * <p><b>NOTE: </b><i>It is possible for there not to be a persisted translator</i></p>
+	 * 
+	 * @param model {@link IStructuredModel} to get the persisted {@link JSPTranslator} for
+	 * @return the persisted {@link JSPTranslator} for the given <code>model</code>, or
+	 * <code>null</code> if none could be found or an existing one could not be read
+	 */
+	public static JSPTranslator getPersistedTranslator(IStructuredModel model) {
+		String persistedTranslatorFilePath = getPersistedTranslatorFilePath(model.getBaseLocation());
+		File persistedTranslatorFile = new File(persistedTranslatorFilePath);
+		
+		//attempt to read in the externalized translator
+		JSPTranslator translator = null;
+		ObjectInputStream in = null;
+		try {
+			//get the persisted translator file if one exists
+			if(persistedTranslatorFile.exists()) {
+				long persistedTranslatorFileTimestamp = persistedTranslatorFile.lastModified();
+				long jspFileTimestamp = FileBufferModelManager.getInstance().getBuffer(
+						model.getStructuredDocument()).getModificationStamp();
+				
+				/* if the persisted translator timestamp is newer then the jsp file timestamp
+				 * then the translation has not become stale, otherwise it has so delete
+				 * it and don't use it */
+				if(persistedTranslatorFileTimestamp > jspFileTimestamp) {
+					FileInputStream fis = new FileInputStream(persistedTranslatorFile);
+					in = new ObjectInputStream(fis);
+					translator = (JSPTranslator)in.readObject();
+					
+					//do post read external setup
+					if(translator != null) {
+						translator.postReadExternalSetup(model);
+					}
+				} else {
+					persistedTranslatorFile.delete();
+				}
+			}
+		} catch(InvalidClassException e) {
+			/* this means that the externalized translator is for an older version
+			 * of the JSPTranslator, so delete it */
+			persistedTranslatorFile.delete();
+		}catch (IOException e) {
+			Logger.logException("Could not read externalized JSPTranslator at " + persistedTranslatorFilePath, e); //$NON-NLS-1$
+		} catch (ClassNotFoundException e) {
+			Logger.logException("Class of a serialized JSPTranslator cannot be found", e); //$NON-NLS-1$
+		} finally {
+			if(in != null) {
+				try {
+					in.close();
+				} catch (IOException e) {
+					Logger.logException("Could not close externalized JSPTranslator that was just read", e); //$NON-NLS-1$
+				}
+			}
+		}
+		
+		return translator;
+	}
+	
+	/**
+	 * @param resource JSP resource who's translation should be persisted
+	 */
+	public static void persistTranslation(IResource resource) {
+		if(ACTIVATED) {
+			IPath path = resource.getFullPath();
+			String filePath = getPersistedTranslatorFilePath(path.toString());
+			IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(path);
+	
+			JSPTranslator translator = getJSPTranslator(file);
+			if(translator != null) {
+				persistTranslator(translator, filePath);
+			}
+		}
+	}
+	
+	/**
+	 * @param resource JSP resource who's translation should no longer be persisted
+	 */
+	public static void removePersistedTranslation(IResource resource) {
+		if(ACTIVATED) {
+			File file = getPersistedFile(resource.getFullPath());
+			file.delete();
+		}
+	}
+	
+	/**
+	 * @param resource JSP resource that has moved and thus its persisted translation should be updated
+	 * @param fromPath Path the JSP resource moved from
+	 */
+	public static void movePersistedTranslation(IResource resource, IPath fromPath) {
+		if(ACTIVATED) {
+			File from = getPersistedFile(fromPath);
+			File to = getPersistedFile(resource.getFullPath());
+	
+			from.renameTo(to);
+		}
+	}
+	
+	/**
+	 * <p>Given the path to a JSP file determines the path to its persisted {@link JSPTranslator}</p>
+	 * 
+	 * @param jspFilePath {@link IPath} to JSP file for which the path to its persisted {@link JSPTranslator}
+	 * should be determined
+	 * 
+	 * @return OS file path to the persisted {@link JSPTranslator} associated with the JSP file at
+	 * <code>jspFilePath</code>
+	 */
+	private static String getPersistedTranslatorFilePath(String jspFilePath) {
+		String persistedTranslatorFileName = "error.translator"; //$NON-NLS-1$
+		synchronized(CHECKSUM_CALC_LOCK){
+			try {
+				CHECKSUM_CALC.reset();
+				CHECKSUM_CALC.update(jspFilePath.getBytes("utf16")); //$NON-NLS-1$
+				persistedTranslatorFileName = Long.toString(CHECKSUM_CALC.getValue()) + ".translator"; //$NON-NLS-1$
+			} catch (UnsupportedEncodingException e) {
+				Logger.logException("Could not get utf16 encoded bytes to create checksum to store persisted file.", e); //$NON-NLS-1$
+			}
+		}
+		
+		IPath location = PERSIST_LOCATION;
+		
+		// ensure the folder exists on disk
+        File folder = new File(location.toOSString());
+		if (!folder.isDirectory()) {
+			try {
+				folder.mkdir();
+			}
+			catch (SecurityException e) {
+			}
+		}
+		
+		location = location.addTrailingSeparator();
+		location = location.append(persistedTranslatorFileName);
+		return location.toOSString();
+	}
+	
+	/**
+	 * <p>Gets the associated {@link JSPTranslator} for a specific JSP file.</p>
+	 * <p><b>NOTE: </b><i>This does not get the persisted translator but rather the
+	 * associated translator in memory</i></p>
+	 * 
+	 * @param jspFile {@link IFile} to the JSP file that the associated {@link JSPTranslator}
+	 * is needed for
+	 * @return {@link JSPTranslator} associated with the given <code>jspFilePath</code>, or
+	 * <code>null</code> if none can be found.
+	 */
+	private static JSPTranslator getJSPTranslator(IFile jspFile) {
+		IStructuredModel model = null;
+		JSPTranslator translator = null;
+		try {
+			model = StructuredModelManager.getModelManager().getModelForRead(jspFile);
+			if(model instanceof IDOMModel) {
+				IDOMDocument doc = ((IDOMModel)model).getDocument();
+				ModelHandlerForJSP.ensureTranslationAdapterFactory(model);
+				JSPTranslationAdapter adapter = (JSPTranslationAdapter)doc.getAdapterFor(IJSPTranslation.class);
+				
+				//don't want to persist a translator that has not already been requested
+				if(adapter != null && adapter.hasTranslation()) {
+					translator = adapter.getJSPTranslation().getTranslator();
+				}
+			}
+		} catch (IOException e) {
+			Logger.logException("Could not get translator for " + jspFile.getName() + //$NON-NLS-1$
+					" because could not read model for same.", e); //$NON-NLS-1$
+		} catch (CoreException e) {
+			Logger.logException("Could not get translator for " + jspFile.getName() + //$NON-NLS-1$
+					" because could not read model for same.", e); //$NON-NLS-1$
+		} finally {
+			if(model != null) {
+				model.releaseFromRead();
+			}
+		}
+		
+		return translator;
+	}
+	
+	/**
+	 * <p>Persists a {@link JSPTranslator} to disk for a specific JSP file</p>
+	 * 
+	 * @param translator {@link JSPTranslator} to persist to disk
+	 * @param jspFilePath {@link IPath} to the JSP file the given <code>translator</code> is for
+	 */
+	private static void persistTranslator(JSPTranslator translator, String filePath) {
+		try {
+			FileOutputStream fos = new FileOutputStream(filePath);
+			ObjectOutputStream out = new ObjectOutputStream(fos);
+			out.writeObject(translator);
+			out.close();
+		} catch (IOException e) {
+			Logger.logException("Was unable to externalize JSPTranslator " + translator + //$NON-NLS-1$
+					" to " + filePath, e); //$NON-NLS-1$
+		}
+	}
+
+	/**
+	 * @param path {@link IPath} to the JSP file that the persisted translator is needed for
+	 * @return The persisted translator {@link File} for the JSP file at the given path
+	 * or <code>null</code> if no persisted translator exists for the JSP file at the given path
+	 */
+	private static File getPersistedFile(IPath path) {
+		return new File(getPersistedTranslatorFilePath(path.toString()));
+	}
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/StackMap.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/StackMap.java
new file mode 100644
index 0000000..2412687
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/StackMap.java
@@ -0,0 +1,158 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.java;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Stack;
+
+/**
+ * @author nitin
+ * 
+ */
+class StackMap {
+
+	private Map fInternalMap = null;
+
+	public StackMap() {
+		fInternalMap = new HashMap();
+	}
+
+	/**
+	 * Removes all mappings from this StackMap
+	 */
+	public void clear() {
+		fInternalMap.clear();
+	}
+
+	/**
+	 * Returns the most recently pushed value to which this map maps the
+	 * specified key. Returns <tt>null</tt> if the map contains no mapping
+	 * for this key.
+	 * 
+	 * @param key
+	 *            key whose associated value is to be returned.
+	 * @return the most recently put value to which this map maps the
+	 *         specified key, or <tt>null</tt> if the map contains no
+	 *         mapping for this key.
+	 */
+	public Object peek(Object key) {
+		Stack stack = (Stack) fInternalMap.get(key);
+		if (stack != null) {
+			Object o = stack.peek();
+			if (stack.isEmpty()) {
+				fInternalMap.remove(key);
+			}
+			return o;
+		}
+		return null;
+	}
+
+	/**
+	 * Associates the specified value with the specified key in this map. If
+	 * the map previously contained a mapping for this key, the old value is
+	 * pushed onto the top of this key's private stack.
+	 * 
+	 * @param key
+	 *            key with which the specified value is to be associated.
+	 * @param value
+	 *            value to be associated with the specified key.
+	 * @return newest value associated with specified key
+	 * 
+	 * @throws UnsupportedOperationException
+	 *             if the <tt>put</tt> operation is not supported by this
+	 *             StackMap.
+	 * @throws ClassCastException
+	 *             if the class of the specified key or value prevents it from
+	 *             being stored in this StackMap.
+	 * @throws IllegalArgumentException
+	 *             if some aspect of this key or value prevents it from being
+	 *             stored in this StackMap.
+	 * @throws NullPointerException,
+	 *             as this map does not permit <tt>null</tt> keys or values
+	 */
+	public Object push(Object key, Object value) {
+		Stack stack = (Stack) fInternalMap.get(key);
+		if (stack == null) {
+			stack = new Stack();
+			fInternalMap.put(key, stack);
+		}
+		Object o = stack.push(value);
+		return o;
+	}
+
+	/**
+	 * Removes the most-recent mapping for this key from this StackMap if it
+	 * is present.
+	 * 
+	 * <p>
+	 * Returns the value to which the map previously associated the key, or
+	 * <tt>null</tt> if the map contained no mapping for this key. The map
+	 * will not contain a mapping for the specified key once the call returns.
+	 * 
+	 * @param key
+	 *            key whose stack is to be popped
+	 * @return most-recently pushed value associated with specified key, or
+	 *         <tt>null</tt> if there was no mapping for key.
+	 * 
+	 * @throws ClassCastException
+	 *             if the key is of an inappropriate type for this map.
+	 * @throws NullPointerException
+	 *             if the key is <tt>null</tt> as this class does not permit
+	 *             <tt>null</tt> keys
+	 */
+	public Object pop(Object key) {
+		Stack stack = (Stack) fInternalMap.get(key);
+		if (stack != null) {
+			Object o = stack.pop();
+			if (stack.isEmpty()) {
+				fInternalMap.remove(key);
+			}
+			return o;
+		}
+		return null;
+	}
+
+    /**
+	 * Returns the number of entries in this StackMap, the sum of the sizes of
+	 * every remembered stack.
+	 * 
+	 * @return the number of entries in this map.
+	 */
+	int size() {
+		int size = 0;
+		Iterator i = fInternalMap.values().iterator();
+		while (i.hasNext()) {
+			Collection c = (Collection) i.next();
+			size += c.size();
+		}
+		return size;
+	}
+
+	/**
+	 * Returns all of the values of this StackMap.
+	 * 
+	 * @return the values of every Stack within this StackMap.
+	 */
+	Collection values() {
+		Collection values = new LinkedList();
+		Iterator i = fInternalMap.values().iterator();
+		while (i.hasNext()) {
+			Collection c = (Collection) i.next();
+			values.addAll(c);
+		}
+		return values;
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/TagTranslationAdapter.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/TagTranslationAdapter.java
new file mode 100644
index 0000000..0125fcd
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/TagTranslationAdapter.java
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.java;
+
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
+
+class TagTranslationAdapter extends JSPTranslationAdapter {
+	TagTranslationAdapter(IDOMModel xmlModel) {
+		super(xmlModel);
+	}
+
+	JSPTranslator createTranslator() {
+		return new TagTranslator();
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/TagTranslationAdapterFactory.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/TagTranslationAdapterFactory.java
new file mode 100644
index 0000000..4807976
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/TagTranslationAdapterFactory.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 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
+ *     
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.java;
+
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.wst.sse.core.internal.provisional.AbstractAdapterFactory;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapter;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapterFactory;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+
+public class TagTranslationAdapterFactory extends AbstractAdapterFactory {
+
+	// for debugging
+	static final boolean DEBUG = Boolean.valueOf(Platform.getDebugOption("org.eclipse.jst.jsp.core/debug/jsptranslation")).booleanValue(); //$NON-NLS-1$;
+	
+	private TagTranslationAdapter fAdapter = null;
+
+	public TagTranslationAdapterFactory() {
+		super(IJSPTranslation.class, true);
+	}
+
+	public INodeAdapterFactory copy() {
+		return new TagTranslationAdapterFactory();
+	}
+
+	protected INodeAdapter createAdapter(INodeNotifier target) {
+		if (target instanceof IDOMNode && fAdapter == null) {
+			fAdapter = new TagTranslationAdapter(((IDOMNode) target).getModel());
+			if (DEBUG) {
+				System.out.println("(+) TagTranslationAdapterFactory [" + this + "] created adapter: " + fAdapter); //$NON-NLS-1$ //$NON-NLS-2$
+			}
+		}
+		return fAdapter;
+	}
+
+	public void release() {
+		if (fAdapter != null) {
+			if (DEBUG) {
+				System.out.println("(-) TagTranslationAdapterFactory [" + this + "] releasing adapter: " + fAdapter); //$NON-NLS-1$ //$NON-NLS-2$
+			}
+			fAdapter.release();
+		}
+		super.release();
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/TagTranslator.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/TagTranslator.java
new file mode 100644
index 0000000..2d7c17d
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/TagTranslator.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.java;
+
+class TagTranslator extends JSPTranslator {
+
+	public TagTranslator() {
+		super();
+	}
+	
+	protected void init() {
+		fClassHeader = "public class _TagHandler extends "; //$NON-NLS-1$
+		fClassname = "_TagHandler"; //$NON-NLS-1$
+
+		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 doTag() throws JspException, java.io.IOException, IllegalStateException, SkipPageException {" + //$NON-NLS-1$
+					"javax.servlet.http.HttpServletResponse response = null;" + ENDL + //$NON-NLS-1$
+					"javax.servlet.http.HttpServletRequest request = null;" + ENDL + //$NON-NLS-1$
+					"JspContext jspContext = null;" + ENDL + //$NON-NLS-1$
+					"javax.servlet.ServletContext application = null;" + ENDL + //$NON-NLS-1$
+					"javax.servlet.jsp.JspWriter out = null;" + ENDL + //$NON-NLS-1$
+					"javax.servlet.ServletConfig config = null;" + ENDL; //$NON-NLS-1$ 
+
+		fSuperclass = "javax.servlet.jsp.tagext.SimpleTagSupport"; //$NON-NLS-1$
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/XMLJSPRegionHelper.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/XMLJSPRegionHelper.java
new file mode 100644
index 0000000..d281590
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/XMLJSPRegionHelper.java
@@ -0,0 +1,550 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.java;
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jst.jsp.core.internal.Logger;
+import org.eclipse.jst.jsp.core.internal.contentmodel.tld.TLDCMDocumentManager;
+import org.eclipse.jst.jsp.core.internal.encoding.JSPDocumentLoader;
+import org.eclipse.jst.jsp.core.internal.parser.JSPSourceParser;
+import org.eclipse.jst.jsp.core.internal.provisional.JSP11Namespace;
+import org.eclipse.jst.jsp.core.internal.provisional.contenttype.ContentTypeIdForJSP;
+import org.eclipse.jst.jsp.core.internal.regions.DOMJSPRegionContexts;
+import org.eclipse.jst.jsp.core.internal.util.FileContentCache;
+import org.eclipse.wst.sse.core.internal.ltk.modelhandler.IModelHandler;
+import org.eclipse.wst.sse.core.internal.ltk.parser.BlockMarker;
+import org.eclipse.wst.sse.core.internal.ltk.parser.StructuredDocumentRegionHandler;
+import org.eclipse.wst.sse.core.internal.modelhandler.ModelHandlerRegistry;
+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.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.regions.DOMRegionContext;
+
+
+/**
+ * Parser/helper class for JSPTranslator. Used for parsing XML-JSP regions (in
+ * a script block) A lot of logic borrowed from TLDCMDocumentManager. There
+ * should be only one XMLJSPRegionHelper per text file
+ * 
+ * @author pavery
+ */
+class XMLJSPRegionHelper implements StructuredDocumentRegionHandler {
+	private final JSPTranslator fTranslator;
+	protected JSPSourceParser fLocalParser = null;
+	protected String fTextToParse = null;
+	// need this if not at the start of the document (eg. parsing just a
+	// script block)
+	protected int fStartOfTextToParse = 0;
+	// name of the open tag that was last handled (if we are interested in it)
+	protected String fTagname = null;
+	protected String fTextBefore = ""; //$NON-NLS-1$
+	protected String fUnescapedText = ""; //$NON-NLS-1$
+	protected String fStrippedText = ""; //$NON-NLS-1$
+	// for reconciling cursor position later
+	int fPossibleOwner = JSPTranslator.SCRIPTLET;
+	/**
+	 * Determines whether translated source appends are indicated as
+	 * "indirect", affecting how offsets are mapped.
+	 */
+	boolean fAppendAsIndirectSource;
+
+	public XMLJSPRegionHelper(JSPTranslator translator, boolean appendAsIndirectSource) {
+		getLocalParser().addStructuredDocumentRegionHandler(this);
+		this.fTranslator = translator;
+		fAppendAsIndirectSource = appendAsIndirectSource;
+	}
+
+	protected JSPSourceParser getLocalParser() {
+		if (fLocalParser == null)
+			fLocalParser = new JSPSourceParser();
+		return fLocalParser;
+	}
+
+	public void addBlockMarker(BlockMarker marker) {
+		fLocalParser.addBlockMarker(marker);
+	}
+
+	public void reset(String textToParse) {
+		reset(textToParse, 0);
+	}
+
+	public void reset(String textToParse, int start) {
+		fStartOfTextToParse = start;
+		fTextToParse = textToParse;
+	}
+
+	public void forceParse() {
+		String contents = fTextToParse;
+
+		IStructuredDocument document = (IStructuredDocument) new JSPDocumentLoader().createNewStructuredDocument();
+		if(contents != null && document != null) {		
+			// from outer class
+			List blockMarkers = this.fTranslator.getBlockMarkers();
+			// this adds the current markers from the outer class list
+			// to this parser so parsing works correctly
+			for (int i = 0; i < blockMarkers.size(); i++) {
+				addBlockMarker((BlockMarker) blockMarkers.get(i));
+			}
+			reset(contents);
+	
+			document.set(contents);
+			IStructuredDocumentRegion cursor = document.getFirstStructuredDocumentRegion();
+			while(cursor != null) {
+				nodeParsed(cursor);
+				cursor = cursor.getNext();
+			}
+		}
+	}
+
+	/*
+	 * parse an entire file
+	 * 
+	 * @param filename @return
+	 */
+	public boolean parse(String filePathString) {
+		boolean parsed = false;
+		IStructuredDocument document = null;
+		String contents = null;
+
+		IPath filePath = new Path(filePathString);
+		IFile f = ResourcesPlugin.getWorkspace().getRoot().getFile(filePath);
+		if (f == null || !f.isAccessible()) {
+			f = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(filePath);
+		}
+		if (f != null && f.isAccessible()) {
+			/*
+			 * using a real document allows us to pull out text in the
+			 * translator for dealing with TEI variables
+			 */
+			try {
+				IModelHandler handler = ModelHandlerRegistry.getInstance().getHandlerFor(f, false);
+				if (handler == null)
+					handler = ModelHandlerRegistry.getInstance().getHandlerForContentTypeId(ContentTypeIdForJSP.ContentTypeID_JSPFRAGMENT);
+				document = (IStructuredDocument) handler.getDocumentLoader().createNewStructuredDocument();
+				contents = FileContentCache.getInstance().getContents(f.getFullPath());
+			}
+			catch (CoreException e) {
+				Logger.logException(e);
+			}
+		}
+		if (contents != null && document != null) {
+			// from outer class
+			List blockMarkers = this.fTranslator.getBlockMarkers();
+			// this adds the current markers from the outer class list
+			// to this parser so parsing works correctly
+			for (int i = 0; i < blockMarkers.size(); i++) {
+				addBlockMarker((BlockMarker) blockMarkers.get(i));
+			}
+			reset(contents);
+			// forces parse
+			document.set(contents);
+			IStructuredDocumentRegion cursor = document.getFirstStructuredDocumentRegion();
+			while (cursor != null) {
+				nodeParsed(cursor);
+				cursor = cursor.getNext();
+			}
+			parsed = true;
+		}
+		return parsed;
+	}
+
+
+	/*
+	 * listens to parser node parsed events adds to local scriplet,
+	 * expression, declaration buffers determines which type of region the
+	 * cursor is in, and adjusts cursor offset accordingly
+	 */
+	public void nodeParsed(IStructuredDocumentRegion sdRegion) {
+
+		try {
+			if (isJSPEndRegion(sdRegion)) {
+				String nameStr = getRegionName(sdRegion);
+				if (isPossibleCustomTag(nameStr)) {
+					// this custom tag may define variables
+					this.fTranslator.addTaglibVariables(nameStr, sdRegion);
+				}
+				fTagname = null;
+			}
+			else if (isJSPStartRegion(sdRegion)) {
+				int illegalContent = hasIllegalContent(sdRegion);
+				if (illegalContent >= 0)
+					decodeRemainingRegions(sdRegion, illegalContent);
+				String nameStr = getRegionName(sdRegion);
+				if (sdRegion.getFirstRegion().getType() == DOMRegionContext.XML_TAG_OPEN) {
+					if (isPossibleCustomTag(nameStr)) {
+						// this custom tag may define variables
+						this.fTranslator.addTaglibVariables(nameStr, sdRegion);
+					}
+				}
+				if (isJSPRegion(nameStr))
+					fTagname = nameStr;
+				else
+					fTagname = null;
+
+
+				// this section assumes important content (to translate)
+				// IS the opening tag
+
+				// handle include and directive
+				if (fTagname != null) {
+					processOtherRegions(sdRegion);
+				}
+
+
+				// handle jsp:useBean
+				if (fTagname != null && fTagname.equals(JSP11Namespace.ElementName.USEBEAN)) {
+					processUseBean(sdRegion);
+				}
+			}
+			else if (sdRegion.getFirstRegion().getType() == DOMJSPRegionContexts.JSP_CONTENT || sdRegion.getFirstRegion().getType() == DOMRegionContext.XML_CONTENT) {
+				// this section assumes important content (to translate)
+				// is AFTER the opening tag
+				if (fTagname != null) {
+					// assign contents to one of the tables
+					if (isScriptlet(fTagname)) {
+						processScriptlet(sdRegion);
+					}
+					else if (isExpression(fTagname)) {
+						processExpression(sdRegion);
+					}
+					else if (isDeclaration(fTagname)) {
+						processDeclaration(sdRegion);
+					}
+				}
+			}
+			else {
+				fTagname = null;
+				/*
+				 * We may have been asked to decode a script block with an XML
+				 * comment in it (a common provision for browsers not
+				 * supporting client scripting). While
+				 * scriptlets/expressions/declarations will be identified as
+				 * part of the normal parsing process, the temporary document
+				 * used here will be parsed differently, respecting the
+				 * comment since it's not in a tag block region any more, and
+				 * the custom tags in the comment will not be found. Run those
+				 * comment text pieces through the translator on their own.
+				 */
+				ITextRegion first = sdRegion.getFirstRegion();
+				ITextRegion last = sdRegion.getLastRegion();
+
+				/* Decode everything between the comment delimiters at once */
+				if (DOMRegionContext.XML_COMMENT_OPEN.equals(first.getType()) && DOMRegionContext.XML_COMMENT_CLOSE.equals(last.getType())) {
+					fTranslator.decodeScriptBlock(sdRegion.getFullText().substring(first.getEnd(), last.getStart()), 0);
+				}
+			}
+			// this updates cursor position
+			checkCursorInRegion(sdRegion);
+		}
+		catch (NullPointerException e) {
+			// logging this exception that I've seen a couple of times...
+			// seems to happen during shutdown of unit tests, at which
+			// point Logger has already been unloaded
+			try {
+				Logger.logException("XMLJSPRegionHelper: exception in node parsing", e); //$NON-NLS-1$
+			}
+			catch (NoClassDefFoundError ex) {
+				// do nothing, since we're just ending
+			}
+		}
+	}
+
+	private void decodeRemainingRegions(IStructuredDocumentRegion sdRegion, int start) {
+		ITextRegionList regionList = sdRegion.getRegions();
+		if(regionList != null) {
+			ITextRegion region = regionList.get(start);
+			String text = sdRegion.getFullText();
+			if (text != null && region != null && region.getStart() <= text.length())
+				fTranslator.decodeScriptBlock(text.substring(region.getStart(), text.length()), 0);
+		}
+	}
+
+	private int hasIllegalContent(IStructuredDocumentRegion sdRegion) {
+		ITextRegionList list = sdRegion.getRegions();
+		for (int i = 0; i < list.size(); i++) {
+			ITextRegion region = list.get(i);
+			String type = region.getType();
+			if (type == DOMRegionContext.UNDEFINED)
+				return i;
+			if (type == DOMRegionContext.XML_END_TAG_OPEN || type == DOMRegionContext.XML_EMPTY_TAG_CLOSE || type == DOMJSPRegionContexts.JSP_DIRECTIVE_CLOSE)
+				return -1;
+		}
+		return -1;
+	}
+
+	public void resetNodes() {
+		// do nothing
+	}
+
+	private void checkCursorInRegion(IStructuredDocumentRegion sdRegion) {
+		// if cursor is in this region...
+		if (this.fTranslator.getSourcePosition() >= fStartOfTextToParse + sdRegion.getStartOffset() && this.fTranslator.getSourcePosition() <= fStartOfTextToParse + sdRegion.getEndOffset()) {
+			int endOfNameTag = sdRegion.getStartOffset();
+			int offset = fTextBefore.length() - fStrippedText.length();
+			// offset in addtion to what's already in the buffer
+			this.fTranslator.setRelativeOffset(this.fTranslator.getSourcePosition() - (fStartOfTextToParse + endOfNameTag) - offset);
+			// outer class method
+			this.fTranslator.setCursorOwner(fPossibleOwner);
+			// add length of what's already in the buffer
+			this.fTranslator.setRelativeOffset(this.fTranslator.getRelativeOffset() + this.fTranslator.getCursorOwner().length());
+			if (fPossibleOwner == JSPTranslator.EXPRESSION) {
+				// add length of expression prefix if necessary...
+				this.fTranslator.setRelativeOffset(this.fTranslator.getRelativeOffset() + JSPTranslator.EXPRESSION_PREFIX.length());
+			}
+		}
+	}
+
+	protected void processDeclaration(IStructuredDocumentRegion sdRegion) {
+		prepareText(sdRegion);
+		IStructuredDocumentRegion currentNode = fTranslator.getCurrentNode();
+		this.fTranslator.translateDeclarationString(fStrippedText, currentNode, currentNode.getStartOffset(), currentNode.getLength(), fAppendAsIndirectSource);
+		fPossibleOwner = JSPTranslator.DECLARATION;
+	}
+
+	protected void processExpression(IStructuredDocumentRegion sdRegion) {
+		prepareText(sdRegion);
+		IStructuredDocumentRegion currentNode = fTranslator.getCurrentNode();
+		this.fTranslator.translateExpressionString(fStrippedText, currentNode, currentNode.getStartOffset(), currentNode.getLength(), fAppendAsIndirectSource);
+		fPossibleOwner = JSPTranslator.EXPRESSION;
+	}
+
+	protected void processScriptlet(IStructuredDocumentRegion sdRegion) {
+		prepareText(sdRegion);
+		IStructuredDocumentRegion currentNode = fTranslator.getCurrentNode();
+		this.fTranslator.translateScriptletString(fStrippedText, currentNode, currentNode.getStartOffset(), currentNode.getLength(), fAppendAsIndirectSource);
+		fPossibleOwner = JSPTranslator.SCRIPTLET;
+	}
+
+	/*
+	 * Substitutes values for entity references, strips CDATA tags, and keeps
+	 * track of string length(s) for cursor position calculation later. @param
+	 * sdRegion
+	 */
+	protected void prepareText(IStructuredDocumentRegion sdRegion) {
+		fTextBefore = fTextToParse.substring(sdRegion.getStartOffset(), sdRegion.getEndOffset());
+		fUnescapedText = EscapedTextUtil.getUnescapedText(fTextBefore);
+		fStrippedText = this.fTranslator.stripCDATA(fUnescapedText);
+	}
+
+	protected void processUseBean(IStructuredDocumentRegion sdRegion) {
+		if (fTagname != null && isUseBean(fTagname)) {
+
+			String beanClass, beanType, beanId, beanDecl = ""; //$NON-NLS-1$
+			beanClass = getAttributeValue("class", sdRegion); //$NON-NLS-1$
+			beanType = getAttributeValue("type", sdRegion); //$NON-NLS-1$
+			beanId = getAttributeValue("id", sdRegion); //$NON-NLS-1$
+
+			if (beanId != null && (beanType != null || beanClass != null)) {
+				String prefix = null;
+				if (beanType.length() != 0) {
+					/* a type was specified */
+					prefix = beanType + " " + beanId + " = "; //$NON-NLS-1$ //$NON-NLS-2$
+				}
+				else {
+					/* no type was specified, use the concrete class value */
+					prefix = beanClass + " " + beanId + " = "; //$NON-NLS-1$ //$NON-NLS-2$
+				}
+				/*
+				 * Define as null by default. If a concrete class was
+				 * specified, supply a default constructor invocation instead.
+				 */
+				String suffix = "null;\n"; //$NON-NLS-1$
+				// 186771 - JSP Validator problem with included useBean
+				if (beanClass.length() > 0) {
+					suffix = "new " + beanClass + "();\n"; //$NON-NLS-1$ //$NON-NLS-2$
+				}
+				beanDecl = prefix + suffix;
+			}
+
+			IStructuredDocumentRegion currentNode = fTranslator.getCurrentNode();
+			this.fTranslator.translateScriptletString(beanDecl, currentNode, currentNode.getStartOffset(), currentNode.getLength(), fAppendAsIndirectSource);
+			fPossibleOwner = JSPTranslator.SCRIPTLET;
+		}
+	}
+
+	protected void processOtherRegions(IStructuredDocumentRegion sdRegion) {
+		processIncludeDirective(sdRegion);
+		processPageDirective(sdRegion);
+	}
+
+	protected void processIncludeDirective(IStructuredDocumentRegion sdRegion) {
+		if (isIncludeDirective(fTagname)) {
+			// the directive name region itself contains the attrs...
+			if (sdRegion.getRegions().get(0).getType() == DOMRegionContext.XML_CONTENT)
+				sdRegion = sdRegion.getPrevious();
+			String fileLocation = getAttributeValue("file", sdRegion); //$NON-NLS-1$
+			this.fTranslator.handleIncludeFile(fileLocation);
+		}
+		else if (isTaglibDirective(fTagname)) {
+			// also add the ones created here to the parent document
+			String prefix = getAttributeValue("prefix", sdRegion); //$NON-NLS-1$
+			TLDCMDocumentManager documentManager = this.fTranslator.getTLDCMDocumentManager();
+			if (documentManager != null) {
+				List docs = documentManager.getCMDocumentTrackers(prefix, this.fTranslator.getCurrentNode().getStartOffset());
+				Iterator it = docs.iterator();
+				Iterator elements = null;
+				CMNode node = null;
+				CMDocument doc = null;
+				BlockMarker marker = null;
+				while (it.hasNext()) {
+					doc = (CMDocument) it.next();
+					elements = doc.getElements().iterator();
+					while (elements.hasNext()) {
+						node = (CMNode) elements.next();
+						marker = new BlockMarker(node.getNodeName(), null, DOMJSPRegionContexts.JSP_CONTENT, true);
+						// global scope is OK because we have encountered this
+						// <@taglib> directive
+						// so it all markers from it should will be in scope
+						// add to this local parser
+						addBlockMarker(marker);
+						// add to outer class marker list, for
+						this.fTranslator.getBlockMarkers().add(marker);
+					}
+				}
+			}
+		}
+	}
+
+	protected void processPageDirective(IStructuredDocumentRegion sdRegion) {
+		if (isPageDirective(fTagname)) {
+			this.fTranslator.translatePageDirectiveAttributes(sdRegion.getRegions().iterator(), sdRegion);
+		}
+	}
+
+	/*
+	 * convenience method to get an attribute value from attribute name
+	 */
+	protected String getAttributeValue(String attrName, IStructuredDocumentRegion sdRegion) {
+		String sdRegionText = fTextToParse.substring(sdRegion.getStartOffset(), sdRegion.getEndOffset());
+		String textRegionText, attrValue = ""; //$NON-NLS-1$
+		Iterator it = sdRegion.getRegions().iterator();
+		ITextRegion nameRegion, valueRegion = null;
+		while (it.hasNext()) {
+			nameRegion = (ITextRegion) it.next();
+			if (nameRegion.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) {
+				textRegionText = sdRegionText.substring(nameRegion.getStart(), nameRegion.getTextEnd());
+				if (textRegionText.equalsIgnoreCase(attrName)) {
+					while (it.hasNext()) {
+						valueRegion = (ITextRegion) it.next();
+						if (valueRegion.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
+							attrValue = sdRegionText.substring(valueRegion.getStart(), valueRegion.getEnd());
+							break; // inner
+						}
+					}
+					break; // outer
+				}
+			}
+		}
+		return StringUtils.stripQuotes(attrValue);
+	}
+
+	// these methods determine what content gets added to the local scriplet,
+	// expression, declaration buffers
+	/*
+	 * return true for elements whose contents we might want to add to the
+	 * java file we are building
+	 */
+	protected boolean isJSPStartRegion(IStructuredDocumentRegion sdRegion) {
+		return (sdRegion.getFirstRegion().getType() == DOMRegionContext.XML_TAG_OPEN || sdRegion.getFirstRegion().getType() == DOMJSPRegionContexts.JSP_DIRECTIVE_OPEN);
+	}
+
+	private boolean isJSPEndRegion(IStructuredDocumentRegion sdRegion) {
+		return (sdRegion.getFirstRegion().getType() == DOMRegionContext.XML_END_TAG_OPEN);
+	}
+
+	protected boolean isJSPRegion(String tagName) {
+		return isDeclaration(tagName) || isExpression(tagName) || isScriptlet(tagName) || isUseBean(tagName) || isIncludeDirective(tagName) || isPossibleCustomTag(tagName) || isTaglibDirective(tagName) || isPageDirective(tagName);
+	}
+
+	protected boolean isDeclaration(String tagName) {
+		return tagName.equalsIgnoreCase("jsp:declaration"); //$NON-NLS-1$		
+	}
+
+	protected boolean isExpression(String tagName) {
+		return tagName.equalsIgnoreCase("jsp:expression"); //$NON-NLS-1$		
+	}
+
+	protected boolean isScriptlet(String tagName) {
+		return tagName.equalsIgnoreCase("jsp:scriptlet"); //$NON-NLS-1$
+	}
+
+	protected boolean isUseBean(String tagName) {
+		return tagName.equalsIgnoreCase("jsp:useBean"); //$NON-NLS-1$
+	}
+
+	protected boolean isIncludeDirective(String tagName) {
+		return tagName.equalsIgnoreCase("jsp:directive.include"); //$NON-NLS-1$
+	}
+
+	protected boolean isPossibleCustomTag(String tagName) {
+//		int colonIndex = tagName.indexOf(":");
+//		if (colonIndex > 0) {
+//			String prefix = tagName.substring(0, colonIndex);
+//			if (prefix.equals("jsp")) { //$NON-NLS-1$
+//				return false;
+//			}
+//			if (prefix.length() > 0) {
+//				TagMarker[] prefixes = (TagMarker[]) fLocalParser.getNestablePrefixes().toArray(new TagMarker[0]);
+//				for (int i = 0; i < prefixes.length; i++) {
+//					if (prefix.equals(prefixes[i].getTagName())) {
+//						return true;
+//					}
+//				}
+//			}
+//		}
+//		return false;
+		return tagName.indexOf(':') > -1 && !tagName.startsWith(JSPTranslator.JSP_PREFIX);
+	}
+
+	protected boolean isTaglibDirective(String tagName) {
+		return tagName.equalsIgnoreCase("jsp:directive.taglib"); //$NON-NLS-1$
+	}
+
+	protected boolean isPageDirective(String tagName) {
+		return tagName.equalsIgnoreCase("jsp:directive.page"); //$NON-NLS-1$
+	}
+
+	protected String getRegionName(IStructuredDocumentRegion sdRegion) {
+
+		String nameStr = ""; //$NON-NLS-1$
+		ITextRegionList regions = sdRegion.getRegions();
+		for (int i = 0; i < regions.size(); i++) {
+			ITextRegion r = regions.get(i);
+			if (r.getType() == DOMRegionContext.XML_TAG_NAME) {
+				nameStr = fTextToParse.substring(sdRegion.getStartOffset(r), sdRegion.getTextEndOffset(r));
+				break;
+			}
+		}
+		return nameStr.trim();
+	}
+
+	/**
+	 * get the contents of a file as a String
+	 * 
+	 * @param filePath - the path to the file
+	 * @return the contents, null if the file could not be found
+	 */
+	protected String getContents(String filePath) {
+		IPath path = new Path(filePath);
+		return FileContentCache.getInstance().getContents(path.makeAbsolute());
+	}
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ASTAddExpress.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ASTAddExpress.java
new file mode 100644
index 0000000..a3c6a6e
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ASTAddExpress.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2005 BEA Systems 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:
+ *     BEA Systems - initial implementation
+ *     
+ *******************************************************************************/
+/* Generated By:JJTree: Do not edit this line. ASTAddExpress.java */
+
+package org.eclipse.jst.jsp.core.internal.java.jspel;
+
+public class ASTAddExpress extends SimpleNode {
+  public ASTAddExpress(int id) {
+    super(id);
+  }
+
+  public ASTAddExpress(JSPELParser p, int id) {
+    super(p, id);
+  }
+
+
+  /** Accept the visitor. **/
+  public Object jjtAccept(JSPELParserVisitor visitor, Object data) {
+    return visitor.visit(this, data);
+  }
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ASTAddExpression.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ASTAddExpression.java
new file mode 100644
index 0000000..c3b6eac
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ASTAddExpression.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2005 BEA Systems 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:
+ *     BEA Systems - initial implementation
+ *     
+ *******************************************************************************/
+/* Generated By:JJTree: Do not edit this line. ASTAddExpression.java */
+
+package org.eclipse.jst.jsp.core.internal.java.jspel;
+
+public class ASTAddExpression extends ASTOperatorExpression {
+  public ASTAddExpression(int id) {
+    super(id);
+  }
+
+  public ASTAddExpression(JSPELParser p, int id) {
+    super(p, id);
+  }
+
+
+  /** Accept the visitor. **/
+  public Object jjtAccept(JSPELParserVisitor visitor, Object data) {
+    return visitor.visit(this, data);
+  }
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ASTAndExpression.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ASTAndExpression.java
new file mode 100644
index 0000000..befe402
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ASTAndExpression.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2005 BEA Systems 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:
+ *     BEA Systems - initial implementation
+ *     
+ *******************************************************************************/
+/* Generated By:JJTree: Do not edit this line. ASTAndExpression.java */
+
+package org.eclipse.jst.jsp.core.internal.java.jspel;
+
+public class ASTAndExpression extends ASTOperatorExpression {
+  public ASTAndExpression(int id) {
+    super(id);
+  }
+
+  public ASTAndExpression(JSPELParser p, int id) {
+    super(p, id);
+  }
+
+
+  /** Accept the visitor. **/
+  public Object jjtAccept(JSPELParserVisitor visitor, Object data) {
+    return visitor.visit(this, data);
+  }
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ASTChoiceExpression.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ASTChoiceExpression.java
new file mode 100644
index 0000000..779079e
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ASTChoiceExpression.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2005 BEA Systems 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:
+ *     BEA Systems - initial implementation
+ *     
+ *******************************************************************************/
+/* Generated By:JJTree: Do not edit this line. ASTChoiceExpression.java */
+
+package org.eclipse.jst.jsp.core.internal.java.jspel;
+
+public class ASTChoiceExpression extends SimpleNode {
+  public ASTChoiceExpression(int id) {
+    super(id);
+  }
+
+  public ASTChoiceExpression(JSPELParser p, int id) {
+    super(p, id);
+  }
+
+
+  /** Accept the visitor. **/
+  public Object jjtAccept(JSPELParserVisitor visitor, Object data) {
+    return visitor.visit(this, data);
+  }
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ASTEqualityExpression.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ASTEqualityExpression.java
new file mode 100644
index 0000000..4a06113
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ASTEqualityExpression.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2005 BEA Systems 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:
+ *     BEA Systems - initial implementation
+ *     
+ *******************************************************************************/
+/* Generated By:JJTree: Do not edit this line. ASTEqualityExpression.java */
+
+package org.eclipse.jst.jsp.core.internal.java.jspel;
+
+public class ASTEqualityExpression extends ASTOperatorExpression {
+  public ASTEqualityExpression(int id) {
+    super(id);
+  }
+
+  public ASTEqualityExpression(JSPELParser p, int id) {
+    super(p, id);
+  }
+
+
+  /** Accept the visitor. **/
+  public Object jjtAccept(JSPELParserVisitor visitor, Object data) {
+    return visitor.visit(this, data);
+  }
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ASTExpression.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ASTExpression.java
new file mode 100644
index 0000000..9d93f38
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ASTExpression.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2005 BEA Systems 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:
+ *     BEA Systems - initial implementation
+ *     
+ *******************************************************************************/
+/* Generated By:JJTree: Do not edit this line. ASTExpression.java */
+
+package org.eclipse.jst.jsp.core.internal.java.jspel;
+
+public class ASTExpression extends SimpleNode {
+  public ASTExpression(int id) {
+    super(id);
+  }
+
+  public ASTExpression(JSPELParser p, int id) {
+    super(p, id);
+  }
+
+
+  /** Accept the visitor. **/
+  public Object jjtAccept(JSPELParserVisitor visitor, Object data) {
+    return visitor.visit(this, data);
+  }
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ASTFunctionInvocation.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ASTFunctionInvocation.java
new file mode 100644
index 0000000..a0cad90
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ASTFunctionInvocation.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2005 BEA Systems 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:
+ *     BEA Systems - initial implementation
+ *     
+ *******************************************************************************/
+/* Generated By:JJTree: Do not edit this line. ASTFunctionInvocation.java */
+
+package org.eclipse.jst.jsp.core.internal.java.jspel;
+
+public class ASTFunctionInvocation extends SimpleNode {
+  String fullFunctionName; 
+  
+  public ASTFunctionInvocation(int id) {
+    super(id);
+  }
+
+  public ASTFunctionInvocation(JSPELParser p, int id) {
+    super(p, id);
+  }
+
+
+  /** Accept the visitor. **/
+  public Object jjtAccept(JSPELParserVisitor visitor, Object data) {
+    return visitor.visit(this, data);
+  }
+
+public String getFullFunctionName() {
+	return fullFunctionName;
+}
+
+public void setFullFunctionName(String fullFunctionName) {
+	this.fullFunctionName = fullFunctionName;
+}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ASTGTNode.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ASTGTNode.java
new file mode 100644
index 0000000..d40005b
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ASTGTNode.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2005 BEA Systems 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:
+ *     BEA Systems - initial implementation
+ *     
+ *******************************************************************************/
+/* Generated By:JJTree: Do not edit this line. ASTGTNode.java */
+
+package org.eclipse.jst.jsp.core.internal.java.jspel;
+
+public class ASTGTNode extends SimpleNode {
+  public ASTGTNode(int id) {
+    super(id);
+  }
+
+  public ASTGTNode(JSPELParser p, int id) {
+    super(p, id);
+  }
+
+
+  /** Accept the visitor. **/
+  public Object jjtAccept(JSPELParserVisitor visitor, Object data) {
+    return visitor.visit(this, data);
+  }
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ASTImplicitObject.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ASTImplicitObject.java
new file mode 100644
index 0000000..1049ad5
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ASTImplicitObject.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2005 BEA Systems 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:
+ *     BEA Systems - initial implementation
+ *     
+ *******************************************************************************/
+/* Generated By:JJTree: Do not edit this line. ASTImplicitObject.java */
+
+package org.eclipse.jst.jsp.core.internal.java.jspel;
+
+public class ASTImplicitObject extends SimpleNode {
+  public ASTImplicitObject(int id) {
+    super(id);
+  }
+
+  public ASTImplicitObject(JSPELParser p, int id) {
+    super(p, id);
+  }
+
+
+  /** Accept the visitor. **/
+  public Object jjtAccept(JSPELParserVisitor visitor, Object data) {
+    return visitor.visit(this, data);
+  }
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ASTLiteral.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ASTLiteral.java
new file mode 100644
index 0000000..fb334f4
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ASTLiteral.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2005 BEA Systems 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:
+ *     BEA Systems - initial implementation
+ *     
+ *******************************************************************************/
+/* Generated By:JJTree: Do not edit this line. ASTLiteral.java */
+
+package org.eclipse.jst.jsp.core.internal.java.jspel;
+
+public class ASTLiteral extends SimpleNode {
+  public ASTLiteral(int id) {
+    super(id);
+  }
+
+  public ASTLiteral(JSPELParser p, int id) {
+    super(p, id);
+  }
+
+
+  /** Accept the visitor. **/
+  public Object jjtAccept(JSPELParserVisitor visitor, Object data) {
+    return visitor.visit(this, data);
+  }
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ASTMultiplyExpression.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ASTMultiplyExpression.java
new file mode 100644
index 0000000..3d8f600
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ASTMultiplyExpression.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2005 BEA Systems 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:
+ *     BEA Systems - initial implementation
+ *     
+ *******************************************************************************/
+/* Generated By:JJTree: Do not edit this line. ASTMultiplyExpression.java */
+
+package org.eclipse.jst.jsp.core.internal.java.jspel;
+
+public class ASTMultiplyExpression extends ASTOperatorExpression {
+  public ASTMultiplyExpression(int id) {
+    super(id);
+  }
+
+  public ASTMultiplyExpression(JSPELParser p, int id) {
+    super(p, id);
+  }
+
+
+  /** Accept the visitor. **/
+  public Object jjtAccept(JSPELParserVisitor visitor, Object data) {
+    return visitor.visit(this, data);
+  }
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ASTOperatorExpression.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ASTOperatorExpression.java
new file mode 100644
index 0000000..3da6b77
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ASTOperatorExpression.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2005 BEA Systems 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:
+ *     BEA Systems - initial implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.java.jspel;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ASTOperatorExpression extends SimpleNode {
+	protected ArrayList operatorTokens = new ArrayList();
+
+	public ASTOperatorExpression(int i) {
+		super(i);
+	}
+	
+	public ASTOperatorExpression(JSPELParser p, int i) {
+		this(i);
+		parser = p;
+	}
+
+	public void addOperatorToken(Token opToken) {
+		operatorTokens.add(opToken);
+	}
+	
+	public List getOperatorTokens() {
+		return operatorTokens;
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ASTOrExpression.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ASTOrExpression.java
new file mode 100644
index 0000000..f3bb76c
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ASTOrExpression.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2005 BEA Systems 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:
+ *     BEA Systems - initial implementation
+ *     
+ *******************************************************************************/
+/* Generated By:JJTree: Do not edit this line. ASTOrExpression.java */
+
+package org.eclipse.jst.jsp.core.internal.java.jspel;
+
+public class ASTOrExpression extends ASTOperatorExpression {
+  public ASTOrExpression(int id) {
+    super(id);
+  }
+
+  public ASTOrExpression(JSPELParser p, int id) {
+    super(p, id);
+  }
+
+
+  /** Accept the visitor. **/
+  public Object jjtAccept(JSPELParserVisitor visitor, Object data) {
+    return visitor.visit(this, data);
+  }
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ASTRelationalExpression.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ASTRelationalExpression.java
new file mode 100644
index 0000000..3023846
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ASTRelationalExpression.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2005 BEA Systems 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:
+ *     BEA Systems - initial implementation
+ *     
+ *******************************************************************************/
+/* Generated By:JJTree: Do not edit this line. ASTRelationalExpression.java */
+
+package org.eclipse.jst.jsp.core.internal.java.jspel;
+
+public class ASTRelationalExpression extends ASTOperatorExpression {
+  public ASTRelationalExpression(int id) {
+    super(id);
+  }
+
+  public ASTRelationalExpression(JSPELParser p, int id) {
+    super(p, id);
+  }
+
+
+  /** Accept the visitor. **/
+  public Object jjtAccept(JSPELParserVisitor visitor, Object data) {
+    return visitor.visit(this, data);
+  }
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ASTStart.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ASTStart.java
new file mode 100644
index 0000000..2fe1e50
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ASTStart.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 BEA Systems 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:
+ *     BEA Systems - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jst.jsp.core.internal.java.jspel;
+
+public class ASTStart extends SimpleNode {
+  public ASTStart(int id) {
+    super(id);
+  }
+
+  public ASTStart(JSPELParser p, int id) {
+    super(p, id);
+  }
+
+
+  /** Accept the visitor. **/
+  public Object jjtAccept(JSPELParserVisitor visitor, Object data) {
+    return visitor.visit(this, data);
+  }
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ASTUnaryExpression.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ASTUnaryExpression.java
new file mode 100644
index 0000000..86870a3
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ASTUnaryExpression.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2005 BEA Systems 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:
+ *     BEA Systems - initial implementation
+ *     
+ *******************************************************************************/
+/* Generated By:JJTree: Do not edit this line. ASTUnaryExpression.java */
+
+package org.eclipse.jst.jsp.core.internal.java.jspel;
+
+public class ASTUnaryExpression extends SimpleNode {
+  public ASTUnaryExpression(int id) {
+    super(id);
+  }
+
+  public ASTUnaryExpression(JSPELParser p, int id) {
+    super(p, id);
+  }
+
+
+  /** Accept the visitor. **/
+  public Object jjtAccept(JSPELParserVisitor visitor, Object data) {
+    return visitor.visit(this, data);
+  }
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ASTValue.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ASTValue.java
new file mode 100644
index 0000000..fd6a36c
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ASTValue.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2005 BEA Systems 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:
+ *     BEA Systems - initial implementation
+ *     
+ *******************************************************************************/
+/* Generated By:JJTree: Do not edit this line. ASTValue.java */
+
+package org.eclipse.jst.jsp.core.internal.java.jspel;
+
+public class ASTValue extends SimpleNode {
+  public ASTValue(int id) {
+    super(id);
+  }
+
+  public ASTValue(JSPELParser p, int id) {
+    super(p, id);
+  }
+
+
+  /** Accept the visitor. **/
+  public Object jjtAccept(JSPELParserVisitor visitor, Object data) {
+    return visitor.visit(this, data);
+  }
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ASTValuePrefix.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ASTValuePrefix.java
new file mode 100644
index 0000000..1f2bf03
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ASTValuePrefix.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2005 BEA Systems 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:
+ *     BEA Systems - initial implementation
+ *     
+ *******************************************************************************/
+/* Generated By:JJTree: Do not edit this line. ASTValuePrefix.java */
+
+package org.eclipse.jst.jsp.core.internal.java.jspel;
+
+public class ASTValuePrefix extends SimpleNode {
+  public ASTValuePrefix(int id) {
+    super(id);
+  }
+
+  public ASTValuePrefix(JSPELParser p, int id) {
+    super(p, id);
+  }
+
+
+  /** Accept the visitor. **/
+  public Object jjtAccept(JSPELParserVisitor visitor, Object data) {
+    return visitor.visit(this, data);
+  }
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ASTValueSuffix.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ASTValueSuffix.java
new file mode 100644
index 0000000..2317267
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ASTValueSuffix.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2005 BEA Systems 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:
+ *     BEA Systems - initial implementation
+ *     
+ *******************************************************************************/
+/* Generated By:JJTree: Do not edit this line. ASTValueSuffix.java */
+
+package org.eclipse.jst.jsp.core.internal.java.jspel;
+
+public class ASTValueSuffix extends SimpleNode {
+	
+  protected Token propertyNameToken;
+  
+  public ASTValueSuffix(int id) {
+    super(id);
+  }
+
+  public ASTValueSuffix(JSPELParser p, int id) {
+    super(p, id);
+  }
+
+
+  /** Accept the visitor. **/
+  public Object jjtAccept(JSPELParserVisitor visitor, Object data) {
+    return visitor.visit(this, data);
+  }
+
+public Token getPropertyNameToken() {
+	return propertyNameToken;
+}
+
+public void setPropertyNameToken(Token propertyNameToken) {
+	this.propertyNameToken = propertyNameToken;
+}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ELGenerator.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ELGenerator.java
new file mode 100644
index 0000000..99a7bf9
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ELGenerator.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2010 BEA Systems 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:
+ *     BEA Systems - initial implementation
+ *     
+ *******************************************************************************/
+
+package org.eclipse.jst.jsp.core.internal.java.jspel;
+
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.jst.jsp.core.jspel.ELProblem;
+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.ITextRegionCollection;
+
+/**
+ * The code checker for the jsf/jsp EL.
+ */
+public final class ELGenerator {
+	/**
+     * Constructor.
+     *
+     * @param locator A valid ELLocator instance, may not be null.
+     */
+    public ELGenerator() {
+    } // constructor
+	
+    /**
+     * Check the netuiel AST and set diagnostics as necessary.
+     * 
+     * @param root
+     * @param currentNode
+     * @param result
+     * @param codeMap
+     * @param document
+     * @param jspReferenceRegion
+     * @param contentStart
+     * @param contentLength
+     * @return a {@link List} of {@link ELProblem}s reported by the {@link ELGeneratorVisitor} this {@link ELGenerator} uses
+     */
+    public List generate(ASTExpression root, IStructuredDocumentRegion currentNode, StringBuffer result, Map codeMap, IStructuredDocument document, ITextRegionCollection jspReferenceRegion, int contentStart, int contentLength) {
+		ELGeneratorVisitor visitor = new ELGeneratorVisitor(result, currentNode, codeMap, document, jspReferenceRegion, contentStart);
+		visitor.startFunctionDefinition(root.getFirstToken().beginColumn - 1);
+		root.jjtAccept(visitor, null);
+		visitor.endFunctionDefinition(root.getLastToken().endColumn - 1);
+		
+		return visitor.getELProblems();
+    }
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ELGeneratorVisitor.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ELGeneratorVisitor.java
new file mode 100644
index 0000000..f6ea3da
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ELGeneratorVisitor.java
@@ -0,0 +1,661 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2010 BEA Systems 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:
+ *     BEA Systems - initial implementation
+ *     
+ *     Bug 154474 EL: 'and', 'or', ... operator
+ *     https://bugs.eclipse.org/bugs/show_bug.cgi?id=154474
+ *     Bernhard Huemer <bernhard.huemer@gmail.com>
+ *     
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.java.jspel;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jst.jsp.core.internal.JSPCoreMessages;
+import org.eclipse.jst.jsp.core.internal.contentmodel.TaglibController;
+import org.eclipse.jst.jsp.core.internal.contentmodel.tld.CMDocumentImpl;
+import org.eclipse.jst.jsp.core.internal.contentmodel.tld.TLDCMDocumentManager;
+import org.eclipse.jst.jsp.core.internal.contentmodel.tld.TaglibTracker;
+import org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.TLDFunction;
+import org.eclipse.jst.jsp.core.jspel.ELProblem;
+import org.eclipse.osgi.util.NLS;
+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.ITextRegionCollection;
+
+public class ELGeneratorVisitor implements JSPELParserVisitor {
+	
+	private static final String ENDL = "\n"; //$NON-NLS-1$
+	
+	private static final String fExpressionHeader1 = "public String _elExpression"; //$NON-NLS-1$
+	private static final String fExpressionHeader2 = "()" + ENDL + //$NON-NLS-1$
+	"\t\tthrows java.io.IOException, javax.servlet.ServletException, javax.servlet.jsp.JspException {" + ENDL + //$NON-NLS-1$
+	"javax.servlet.jsp.PageContext pageContext = null;" + ENDL + //$NON-NLS-1$
+	"java.util.Map param = null;" + ENDL + //$NON-NLS-1$
+	"java.util.Map paramValues = null;" + ENDL + //$NON-NLS-1$
+	"java.util.Map header = null;" + ENDL + //$NON-NLS-1$ 
+	"java.util.Map headerValues = null;" + ENDL + //$NON-NLS-1$
+	"java.util.Map cookie = null;" + ENDL + //$NON-NLS-1$ 
+	"java.util.Map initParam = null;" + ENDL + //$NON-NLS-1$
+	"java.util.Map pageScope = null;" + ENDL + //$NON-NLS-1$
+	"java.util.Map requestScope = null;" + ENDL + //$NON-NLS-1$
+	"java.util.Map sessionScope = null;" + ENDL + //$NON-NLS-1$
+	"java.util.Map applicationScope = null;" + ENDL + //$NON-NLS-1$
+	"return \"\"+( "; //$NON-NLS-1$
+
+	private static final String fExpressionHeader2_param = "()" + ENDL + //$NON-NLS-1$
+	"\t\tthrows java.io.IOException, javax.servlet.ServletException, javax.servlet.jsp.JspException {" + ENDL + //$NON-NLS-1$
+	"javax.servlet.jsp.PageContext pageContext = null;" + ENDL + //$NON-NLS-1$
+	"java.util.Map<String, String> param = null;" + ENDL + //$NON-NLS-1$
+	"java.util.Map<String, String[]> paramValues = null;" + ENDL + //$NON-NLS-1$
+	"java.util.Map<String, String> header = null;" + ENDL + //$NON-NLS-1$ 
+	"java.util.Map<String, String[]> headerValues = null;" + ENDL + //$NON-NLS-1$
+	"java.util.Map<String, javax.servlet.http.Cookie> cookie = null;" + ENDL + //$NON-NLS-1$ 
+	"java.util.Map<String, String> initParam = null;" + ENDL + //$NON-NLS-1$
+	"java.util.Map<String, Object> pageScope = null;" + ENDL + //$NON-NLS-1$
+	"java.util.Map<String, Object> requestScope = null;" + ENDL + //$NON-NLS-1$
+	"java.util.Map<String, Object> sessionScope = null;" + ENDL + //$NON-NLS-1$
+	"java.util.Map<String, Object> applicationScope = null;" + ENDL + //$NON-NLS-1$
+	"return \"\"+( "; //$NON-NLS-1$
+	
+	private static final String fJspImplicitObjects[] = { "pageContext" }; //$NON-NLS-1$
+	
+	private static final String fJspImplicitMaps[] = { 	"param", "paramValues", "header", "headerValues", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+														"cookie", "initParam", "pageScope", "requestScope", "sessionScope",  //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
+														"applicationScope" }; //$NON-NLS-1$
+	
+	private static final HashMap fJSPImplicitObjectMap = new HashMap(fJspImplicitObjects.length);
+	static {
+		for(int i = 0; i < fJspImplicitObjects.length; i++) {
+			fJSPImplicitObjectMap.put(fJspImplicitObjects[i], new Boolean(true));
+		}
+		
+		for(int i = 0; i < fJspImplicitMaps.length; i++) {
+			fJSPImplicitObjectMap.put(fJspImplicitMaps[i], new Boolean(false));
+		}
+	}
+	
+	private static final String fFooter = " );" + ENDL + "}" + ENDL; //$NON-NLS-1$ //$NON-NLS-2$
+
+	private StringBuffer fResult;
+	private Map fCodeMap;
+	private int fOffsetInUserCode;
+	private static int methodCounter = 0;
+	private IStructuredDocument fDocument = null;
+	private int fContentStart;
+	private static Map fOperatorMap;
+	// start of the generated function definition, if any:
+	private int fGeneratedFunctionStart;
+
+	// this flag lets us know if we were unable to generate for some reason.  One possible reason is that the expression 
+	// contains a reference to a variable for which information is only available at runtime.
+	private boolean fCanGenerate = true;
+
+	private IStructuredDocumentRegion fCurrentNode;
+
+	private boolean fUseParameterizedTypes;
+
+	private List fELProblems;
+
+	/**
+	 * Tranlsation of XML-style operators to java
+	 */
+	static {
+		fOperatorMap = new HashMap();
+		fOperatorMap.put("gt", ">"); //$NON-NLS-1$ //$NON-NLS-2$
+		fOperatorMap.put("lt", "<"); //$NON-NLS-1$ //$NON-NLS-2$
+		fOperatorMap.put("ge", ">="); //$NON-NLS-1$ //$NON-NLS-2$
+		fOperatorMap.put("le", "<="); //$NON-NLS-1$ //$NON-NLS-2$
+		fOperatorMap.put("mod", "%"); //$NON-NLS-1$ //$NON-NLS-2$
+		fOperatorMap.put("eq", "=="); //$NON-NLS-1$ //$NON-NLS-2$
+		fOperatorMap.put("and", "&&"); //$NON-NLS-1$ //$NON-NLS-2$
+		fOperatorMap.put("or", "||"); //$NON-NLS-1$ //$NON-NLS-2$
+		fOperatorMap.put("not", "!"); //$NON-NLS-1$ //$NON-NLS-2$
+	}
+	
+	/**
+	 * The constructor squirrels away a few things we'll need later
+	 * 
+	 * @param result
+	 * @param codeMap
+	 * @param translator
+	 * @param jspReferenceRegion
+	 * @param contentStart
+	 */
+	public ELGeneratorVisitor(StringBuffer result, IStructuredDocumentRegion currentNode, Map codeMap, IStructuredDocument document, ITextRegionCollection jspReferenceRegion, int contentStart)
+	{
+		fResult = result;
+		fCodeMap = codeMap;
+		fOffsetInUserCode = result.length();
+		fContentStart = contentStart;
+		fDocument = document;
+		fCurrentNode = currentNode;
+		fGeneratedFunctionStart = -1; //set when generating function definition
+		fUseParameterizedTypes = compilerSupportsParameterizedTypes();
+		fELProblems = new ArrayList();
+	}
+
+	/**
+	 * Append a token to the output stream.  Automatically calculating mapping.
+	 * 
+	 * @param token
+	 */
+	private void append(Token token)
+	{
+		append(token.image, token.beginColumn - 1, token.endColumn);
+	}
+	
+	/**
+	 * Append a translation for the corresponding input token.
+	 * 
+	 * @param translated
+	 * @param token
+	 */
+	private void append(String translated, Token token)
+	{
+		append(translated, token.beginColumn - 1, token.endColumn);
+	}
+
+	/**
+	 * Append a string explicitly giving the input mapping.
+	 * 
+	 * @param newText
+	 * @param jspPositionStart
+	 * @param jspPositionEnd
+	 */
+	private void append(String newText, int jspPositionStart, int jspPositionEnd)
+	{
+		fResult.append(newText);
+		Position javaRange = new Position(fOffsetInUserCode, newText.length());
+		Position jspRange = new Position(fContentStart + jspPositionStart, jspPositionEnd - jspPositionStart);
+
+		fCodeMap.put(javaRange, jspRange);
+		fOffsetInUserCode += newText.length();
+	}
+	
+	/**
+	 * Append text that will be unmapped and therefore will not be available for completion.
+	 * 
+	 * @param newText
+	 */
+	private void append(String newText)
+	{
+		fResult.append(newText);
+		fOffsetInUserCode += newText.length();
+	}
+	
+	/**
+	 * Generate a function invocation.
+	 * 
+	 * @param fullFunctionName
+	 * @return
+	 */
+	protected String genFunction(String fullFunctionName) {
+		TLDCMDocumentManager docMgr = TaglibController.getTLDCMDocumentManager(fDocument);
+		int colonIndex = fullFunctionName.indexOf(':');
+		String prefix = fullFunctionName.substring(0, colonIndex);
+		String functionName = fullFunctionName.substring(colonIndex + 1);
+		if (docMgr == null)
+			return null;
+		
+		Iterator taglibs = docMgr.getCMDocumentTrackers(fCurrentNode.getStartOffset()).iterator();
+		while (taglibs.hasNext()) {
+			TaglibTracker tracker = (TaglibTracker)taglibs.next();
+			if(tracker.getPrefix().equals(prefix)) {
+				CMDocumentImpl doc = (CMDocumentImpl)tracker.getDocument();
+				
+				List functions = doc.getFunctions();
+				for(Iterator it = functions.iterator(); it.hasNext(); ) {
+					TLDFunction function = (TLDFunction)it.next();
+					if(function.getName().equals(functionName)) {
+						String javaFuncName = getFunctionNameFromSignature(function.getSignature());
+						if (javaFuncName == null)
+							javaFuncName = functionName;
+						return function.getClassName() + "." + javaFuncName; //$NON-NLS-1$
+					}
+				}
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * Handle a simple node -- fallback
+	 */
+	public Object visit(SimpleNode node, Object data) {
+		return(node.childrenAccept(this, data));
+	}
+
+	static synchronized int getMethodCounter() {
+		return methodCounter++;
+	}
+	
+	/**
+	 * Handle top-level expression
+	 */
+	public Object visit(ASTExpression node, Object data) {
+		return node.childrenAccept(this, data);
+	}
+
+	public void startFunctionDefinition(int start) {
+		fGeneratedFunctionStart = fResult.length();
+		append(fExpressionHeader1, start, start);
+		append(Integer.toString(getMethodCounter()), start, start);
+		if (fUseParameterizedTypes)
+			append(fExpressionHeader2_param, start, start);
+		else
+			append(fExpressionHeader2, start, start);
+	}
+
+	public void endFunctionDefinition(int end) {
+		if (fGeneratedFunctionStart < 0) {
+			throw new IllegalStateException("Cannot end function definition because none has been started."); //$NON-NLS-1$
+		}
+		append(fFooter, end, end);
+
+		// something is preventing good code generation so empty out the result
+		// and the map.
+		if (!fCanGenerate) {
+			fResult.delete(fGeneratedFunctionStart, fResult.length());
+			fOffsetInUserCode = fResult.length();
+			// remove all fCodeMap entries for the removed code:
+			for (Iterator it = fCodeMap.entrySet().iterator(); it.hasNext();) {
+				Map.Entry entry = (Entry) it.next();
+				if (entry.getKey() instanceof Position) {
+					Position pos = (Position) entry.getKey();
+					if (pos.getOffset() >= fGeneratedFunctionStart) {
+						it.remove();
+					}
+				}
+			}
+		}
+		fGeneratedFunctionStart = -1;
+	}
+
+
+	private boolean compilerSupportsParameterizedTypes() {
+		if (fDocument != null) {
+			IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+			IPath location = TaglibController.getLocation(fDocument);
+			if (location != null && location.segmentCount() > 0) {
+				IJavaProject project = JavaCore.create(root.getProject(location.segment(0)));
+				String compliance = project.getOption(JavaCore.COMPILER_SOURCE, true);
+				try {
+					return Float.parseFloat(compliance) >= 1.5;
+				}
+				catch (NumberFormatException e) {
+					return false;
+				}
+			}
+		}
+		return false;
+	}
+	
+	/**
+	 * Generically generate an operator node.
+	 * 
+	 * @param node
+	 * @param data
+	 */
+	private void generateOperatorNode(ASTOperatorExpression node, Object data) {
+		for(int i = 0; i < node.children.length; i++) {
+			node.children[i].jjtAccept(this, data);
+			if( node.children.length - i > 1) {
+				appendOperator((Token)node.getOperatorTokens().get(i));
+			}
+		}
+	}
+	
+	/**
+	 * Append an operator to the output stream after translation (if any)
+	 * 
+	 * @param token
+	 * @return
+	 */
+	private String appendOperator(Token token) {
+		String tokenImage = token.image.trim();
+		String translated = (String)fOperatorMap.get(tokenImage);
+		if(null != translated) {
+			append(translated, token);
+		} else {
+			append(token);
+		}
+		return(translated);
+	}
+
+	/**
+	 * Handle or Expression
+	 */
+	public Object visit(ASTOrExpression node, Object data) {
+		generateOperatorNode(node, data);
+		return(null);
+	}
+
+
+	/**
+	 * Handle and expression 
+	 */
+	public Object visit(ASTAndExpression node, Object data) {
+		generateOperatorNode(node, data);
+		return(null);
+	}
+
+
+	/**
+	 * Handle equality
+	 */
+	public Object visit(ASTEqualityExpression node, Object data) {
+		generateOperatorNode(node, data);
+		return(null);
+	}
+
+
+	/**
+	 * Handle Relational
+	 */
+	public Object visit(ASTRelationalExpression node, Object data) {
+		generateOperatorNode(node, data);
+		return(null);
+	}
+
+
+	/**
+	 * Handle addition
+	 */
+	public Object visit(ASTAddExpression node, Object data) {
+		generateOperatorNode(node, data);
+		return(null);
+	}
+
+
+	/**
+	 * Handle multiply
+	 */
+	public Object visit(ASTMultiplyExpression node, Object data) {
+		generateOperatorNode(node, data);
+		return(null);
+	}
+
+
+	/** 
+	 * Choice Expression (ternary operator)
+	 */
+	public Object visit(ASTChoiceExpression node, Object data) {
+		node.children[0].jjtAccept(this, data);
+		append("?"); //$NON-NLS-1$
+		node.children[1].jjtAccept(this, data);
+		append(":"); //$NON-NLS-1$
+		node.children[2].jjtAccept(this,data);
+		return null;
+	}
+
+
+	/**
+	 * Handle unary
+	 */
+	public Object visit(ASTUnaryExpression node, Object data) {
+		if(JSPELParserConstants.EMPTY == node.firstToken.kind) {
+			append("((null == "); //$NON-NLS-1$
+			node.childrenAccept(this, data);
+			append(") || ("); //$NON-NLS-1$
+			node.childrenAccept(this, data);
+			append(").isEmpty())"); //$NON-NLS-1$
+		} else if(JSPELParserConstants.NOT1 == node.firstToken.kind || JSPELParserConstants.NOT2 == node.firstToken.kind) {
+			append("(!"); //$NON-NLS-1$
+			node.childrenAccept(this, data);
+			append(")"); //$NON-NLS-1$
+		} else if(JSPELParserConstants.MINUS == node.firstToken.kind) {
+			append("(-"); //$NON-NLS-1$
+			node.childrenAccept(this, data);
+			append(")"); //$NON-NLS-1$
+		} else {
+			node.childrenAccept(this, data);
+		}
+		return null;
+	}
+
+
+	/**
+	 * Value node
+	 */
+	public Object visit(ASTValue node, Object data) {
+		if(node.jjtGetNumChildren() >= 2) {
+			if(node.jjtGetChild(0) instanceof ASTValuePrefix && node.jjtGetChild(1) instanceof ASTValueSuffix) {
+				ASTValuePrefix prefix = (ASTValuePrefix) node.jjtGetChild(0);
+				ASTValueSuffix suffix = (ASTValueSuffix) node.jjtGetChild(1);
+				//content assist can cause a null pointer here without the extra null check
+				if(prefix.firstToken.image.equals("pageContext") && suffix.getPropertyNameToken() != null && suffix.getPropertyNameToken().image.equals("request")) {
+					append("((HttpServletRequest)");
+				}
+			}
+		}
+		return node.childrenAccept(this, data);	
+	}
+
+
+	/**
+	 * Value Prefix
+	 */
+	public Object visit(ASTValuePrefix node, Object data) {
+		// this is a raw identifier.  May sure it's an implicit object.
+		// This is the primary place where modification is needed to 
+		// support JSF backing beans.
+		if(null == node.children) {
+			if(isCompletingObject(node.firstToken.image)) {
+				append(node.firstToken);
+			} else {
+				fCanGenerate = false;
+			}
+			return(null);
+		}
+		return node.childrenAccept(this, data);
+	}
+
+
+	/**
+	 * Function for testing implicit objects.
+	 * 
+	 * @param image
+	 * @return
+	 */
+	private boolean isCompletingObject(String image) {
+		Boolean value = (Boolean)fJSPImplicitObjectMap.get(image);
+		return null == value ? false : value.booleanValue();
+	}
+
+	/**
+	 * Value suffix
+	 */
+	public Object visit(ASTValueSuffix node, Object data) {
+		if(JSPELParserConstants.LBRACKET == node.firstToken.kind) {
+			fCanGenerate = false;
+		} else if(null != node.getPropertyNameToken()) {
+			Token suffix = node.getPropertyNameToken();
+			String ucaseName = suffix.image.substring(0, 1).toUpperCase() + suffix.image.substring(1, suffix.image.length()); 
+
+			// This is a special case.  Note that the type system, no matter how much type information
+			// we would have wouldn't give us the correct result.  We're looking for "pageContext.request" 
+			// here and will add a downcast to (HTTPServletRequest)
+			
+			append(node.firstToken);
+			append("get" + ucaseName + "()", suffix); //$NON-NLS-1$ //$NON-NLS-2$
+			
+			SimpleNode parent = (SimpleNode) node.jjtGetParent();
+			if(suffix.image.equals("request") && parent instanceof ASTValue && //$NON-NLS-1$
+					parent.jjtGetParent() instanceof ASTUnaryExpression && parent.firstToken.image.equals("pageContext")) { //$NON-NLS-1$
+				append(")");
+			} 
+
+		} else if(node.getLastToken().image.equals(".") && node.getLastToken().next.image.equals("")) { //$NON-NLS-1$ //$NON-NLS-2$
+			//this allows for content assist in the case of something along the lines of "pageContext." and then ctl-space
+			append(node.firstToken);
+			append("get()", node.getLastToken().beginColumn, node.getLastToken().beginColumn); //$NON-NLS-1$
+		} else {
+			append(node.firstToken);
+		}
+		return null;
+	}
+
+
+	/**
+	 * Function invocation
+	 */
+	public Object visit(ASTFunctionInvocation node, Object data) {
+		String functionTranslation = genFunction(node.getFullFunctionName());
+		if(null != functionTranslation) {
+
+			//find the token representing the function name
+			Token jspFuncNameToken = getJSPFuncNameToken(node);
+			
+			/* if there is a dot in the function name then separate out the class path
+			 * from the function name and append.
+			 * else just append
+			 * in both cases use the jsp function name token as the mapped token
+			 */
+			int indexOfDot = functionTranslation.lastIndexOf('.');
+			if(indexOfDot != -1) {
+				String funcClass = functionTranslation.substring(0,indexOfDot+1);
+				String funcName = functionTranslation.substring(indexOfDot+1);
+				append(funcClass, jspFuncNameToken);
+				append(funcName, jspFuncNameToken);
+			} else {
+				append(functionTranslation, jspFuncNameToken);
+			}
+			
+			//append any parameters
+			append("(");
+			if(node.children != null) {
+				for(int i = 0; i < node.children.length; i++) {
+					node.children[i].jjtAccept(this, data);
+					if( node.children.length - i > 1){
+						append(","); //$NON-NLS-1$
+					}
+				}
+			}
+			append(")"); //$NON-NLS-1$
+		}
+		else {
+			//column offsets are 1 based not 0 based, thus subtract one
+			final int problemOffset = fContentStart + node.getFirstToken().beginColumn - 1;
+			final int problemLength = node.getLastToken().endColumn - 1;
+
+			//could not find function translation so report error
+			fELProblems.add(new ELProblem(new Position(problemOffset, problemLength), NLS.bind(JSPCoreMessages.JSPELTranslator_0, node.getFullFunctionName())));
+			
+			//error message to be injected into translation purely for debugging purposes
+			String errorMsg = "\"Could not find function translation for: " + node.getFullFunctionName() + "\""; //$NON-NLS-1$ //$NON-NLS-2$
+			append(errorMsg);
+ 		}
+		return null;
+	}
+
+	/**
+	 * @return the {@link ELProblem}s found by this visitor
+	 */
+	public List getELProblems() {
+		return fELProblems;
+	}
+
+	/**
+	 * Literal
+	 */
+	public Object visit(ASTLiteral node, Object data) {
+		if (isSingleQuotedStringLiteral(node)) {
+			//replace the single quotes with double quotes quotes
+			//so java compiler will be happy
+			//(see: https://bugs.eclipse.org/bugs/show_bug.cgi?id=104943)
+			String image = node.firstToken.image;
+			image = "\"" + image.substring(1, image.length()-1) + "\""; //$NON-NLS-1$ //$NON-NLS-2$
+			node.firstToken.image = image;
+		}
+		
+		append(node.firstToken);
+		return null;
+	}
+	
+	/**
+	 * Indicates whether the given ASTLiteral is a single quoted string literal,
+	 * As opposed to a double quoted ASTLiteral
+	 * 
+	 * @param node the ASTLiteral to check to see if it is single quoted
+	 * 
+	 * @return true, if the given token is a single quoted string literal,
+	 * false otherwise
+	 */
+	private static boolean isSingleQuotedStringLiteral(ASTLiteral node) {
+		String content = node.firstToken.image;
+		return content.length() > 1 && content.startsWith("'") && content.endsWith("'"); //$NON-NLS-1$ // $NON-NLS-2$
+	}
+
+	/**
+	 * <p>Given a method signature parse out the method name and return it.
+	 * The method name in the signature is found by finding a word with
+	 * whitespace before it and a '<code>(</code>' after it.</p>
+	 * 
+	 * @param methodSignature the signature of the method to get the method name out of.
+	 * @return the method name from the given signature, or <code>null</code> if it
+	 * can not be found.
+	 */
+	private static String getFunctionNameFromSignature (String methodSignature) {
+		int length = methodSignature.length();
+		char c = 0;
+		int identifierStart = -1;
+		int whitespaceStart = -1;
+		// keep track of the index of the last identifier before the (
+		for (int i = 0; i < length; i++) {
+			c = methodSignature.charAt(i);
+			if (Character.isJavaIdentifierPart(c) && whitespaceStart >= identifierStart)
+				identifierStart = i;
+			else if (Character.isWhitespace(c))
+				whitespaceStart = i;
+			else if (c == '(') {
+				if (identifierStart >= 0) {
+					return methodSignature.substring(identifierStart, i).trim();
+				}
+			}
+		}
+		return null;
+	}
+	
+	/**
+	 * Returns the {@link Token} the represents the function name in
+	 * the {@link ASTFunctionInvocation}. This is designated as the
+	 * first token after the {@link Token} whose image is ":".
+	 * If such a token can not be found then the first token of the
+	 * {@link ASTFunctionInvocation} is returned.
+	 * 
+	 * @param funcInvo the {@link ASTFunctionInvocation} to find the function name {@link Token} in
+	 * @return the {@link Token} in the given {@link ASTFunctionInvocation} that represents the
+	 * function name, or if that can't be found the first {@link Token} in the {@link ASTFunctionInvocation}.
+	 */
+	private Token getJSPFuncNameToken(ASTFunctionInvocation funcInvo) {
+		Token funcNameToken = funcInvo.getFirstToken();
+		
+		Token temp = funcInvo.getFirstToken();
+		do {
+			if(temp.image.equals(":")) {
+				funcNameToken = temp.next;
+			}
+		} while(temp.next != null && funcNameToken == null);
+			
+		
+		return funcNameToken;
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/FindFunctionInvocationVisitor.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/FindFunctionInvocationVisitor.java
new file mode 100644
index 0000000..e05c562
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/FindFunctionInvocationVisitor.java
@@ -0,0 +1,100 @@
+/*******************************************************************************
+ * Copyright (c) 2005 BEA Systems 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:
+ *     BEA Systems - initial implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.java.jspel;
+
+public class FindFunctionInvocationVisitor implements JSPELParserVisitor {
+	protected int fCursorPosition;
+	
+	public FindFunctionInvocationVisitor(int cursorPosition)
+	{
+		fCursorPosition = cursorPosition;
+	}
+	
+	protected boolean isEnclosing(SimpleNode node) {
+		return(node.firstToken.beginColumn < fCursorPosition && node.lastToken.endColumn >= fCursorPosition);
+	}
+
+	
+	protected Object visitEnclosingChild(SimpleNode node, Object data)	{
+		if(null == node.children)
+			return null;
+		
+		for(int i = 0; i < node.children.length; i++) {
+			if(isEnclosing(node)) 
+				return node.children[i].jjtAccept(this, data);
+		}
+		return null;
+	}
+
+	public Object visit(SimpleNode node, Object data) {
+		return visitEnclosingChild(node, data);
+	}
+
+	public Object visit(ASTExpression node, Object data) {
+		return visitEnclosingChild(node, data);
+	}
+
+	public Object visit(ASTOrExpression node, Object data) {
+		return visitEnclosingChild(node, data);
+	}
+
+	public Object visit(ASTAndExpression node, Object data) {
+		return visitEnclosingChild(node, data);
+	}
+
+	public Object visit(ASTEqualityExpression node, Object data) {
+		return visitEnclosingChild(node, data);
+	}
+
+	public Object visit(ASTRelationalExpression node, Object data) {
+		return visitEnclosingChild(node, data);
+	}
+
+	public Object visit(ASTAddExpression node, Object data) {
+		return visitEnclosingChild(node, data);
+	}
+
+	public Object visit(ASTMultiplyExpression node, Object data) {
+		return visitEnclosingChild(node, data);
+	}
+
+	public Object visit(ASTChoiceExpression node, Object data) {
+		return visitEnclosingChild(node, data);
+	}
+
+	public Object visit(ASTUnaryExpression node, Object data) {
+		return visitEnclosingChild(node, data);
+	}
+
+	public Object visit(ASTValue node, Object data) {
+		return visitEnclosingChild(node, data);
+	}
+
+	public Object visit(ASTValuePrefix node, Object data) {
+		return visitEnclosingChild(node, data);
+	}
+
+	public Object visit(ASTValueSuffix node, Object data) {
+		return visitEnclosingChild(node, data);
+	}
+
+	public Object visit(ASTFunctionInvocation node, Object data) {
+		Object nestedInvocation = visitEnclosingChild(node, data);
+		if(null != nestedInvocation)
+			return nestedInvocation;
+		return node;
+	}
+
+	public Object visit(ASTLiteral node, Object data) {
+		return visitEnclosingChild(node, data);
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/JJTJSPELParserState.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/JJTJSPELParserState.java
new file mode 100644
index 0000000..951a84b
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/JJTJSPELParserState.java
@@ -0,0 +1,135 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2010 BEA Systems 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:
+ *     BEA Systems - initial implementation
+ *     IBM Corporation - Bug 318281 - EL validation error for quote escaping
+ *
+ *******************************************************************************/
+/* Generated By:JavaCC: Do not edit this line. JJTJSPELParserState.java Version 4.2 */
+package org.eclipse.jst.jsp.core.internal.java.jspel;
+
+public class JJTJSPELParserState {
+  private java.util.List nodes;
+  private java.util.List marks;
+
+  private int sp;        // number of nodes on stack
+  private int mk;        // current mark
+  private boolean node_created;
+
+  public JJTJSPELParserState() {
+    nodes = new java.util.ArrayList();
+    marks = new java.util.ArrayList();
+    sp = 0;
+    mk = 0;
+  }
+
+  /* Determines whether the current node was actually closed and
+     pushed.  This should only be called in the final user action of a
+     node scope.  */
+  public boolean nodeCreated() {
+    return node_created;
+  }
+
+  /* Call this to reinitialize the node stack.  It is called
+     automatically by the parser's ReInit() method. */
+  public void reset() {
+    nodes.clear();
+    marks.clear();
+    sp = 0;
+    mk = 0;
+  }
+
+  /* Returns the root node of the AST.  It only makes sense to call
+     this after a successful parse. */
+  public Node rootNode() {
+    return (Node)nodes.get(0);
+  }
+
+  /* Pushes a node on to the stack. */
+  public void pushNode(Node n) {
+    nodes.add(n);
+    ++sp;
+  }
+
+  /* Returns the node on the top of the stack, and remove it from the
+     stack.  */
+  public Node popNode() {
+    if (--sp < mk) {
+      mk = ((Integer)marks.remove(marks.size()-1)).intValue();
+    }
+    return (Node)nodes.remove(nodes.size()-1);
+  }
+
+  /* Returns the node currently on the top of the stack. */
+  public Node peekNode() {
+    return (Node)nodes.get(nodes.size()-1);
+  }
+
+  /* Returns the number of children on the stack in the current node
+     scope. */
+  public int nodeArity() {
+    return sp - mk;
+  }
+
+
+  public void clearNodeScope(Node n) {
+    while (sp > mk) {
+      popNode();
+    }
+    mk = ((Integer)marks.remove(marks.size()-1)).intValue();
+  }
+
+
+  public void openNodeScope(Node n) {
+    marks.add(new Integer(mk));
+    mk = sp;
+    n.jjtOpen();
+  }
+
+
+  /* A definite node is constructed from a specified number of
+     children.  That number of nodes are popped from the stack and
+     made the children of the definite node.  Then the definite node
+     is pushed on to the stack. */
+  public void closeNodeScope(Node n, int num) {
+    mk = ((Integer)marks.remove(marks.size()-1)).intValue();
+    while (num-- > 0) {
+      Node c = popNode();
+      c.jjtSetParent(n);
+      n.jjtAddChild(c, num);
+    }
+    n.jjtClose();
+    pushNode(n);
+    node_created = true;
+  }
+
+
+  /* A conditional node is constructed if its condition is true.  All
+     the nodes that have been pushed since the node was opened are
+     made children of the conditional node, which is then pushed
+     on to the stack.  If the condition is false the node is not
+     constructed and they are left on the stack. */
+  public void closeNodeScope(Node n, boolean condition) {
+    if (condition) {
+      int a = nodeArity();
+      mk = ((Integer)marks.remove(marks.size()-1)).intValue();
+      while (a-- > 0) {
+        Node c = popNode();
+        c.jjtSetParent(n);
+        n.jjtAddChild(c, a);
+      }
+      n.jjtClose();
+      pushNode(n);
+      node_created = true;
+    } else {
+      mk = ((Integer)marks.remove(marks.size()-1)).intValue();
+      node_created = false;
+    }
+  }
+}
+/* JavaCC - OriginalChecksum=cf01a3e21044e1fa20cdfdc7a552e885 (do not edit this line) */
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/JSPEL.jj b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/JSPEL.jj
new file mode 100644
index 0000000..499e8c6
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/JSPEL.jj
@@ -0,0 +1,676 @@
+/*@bgen(jjtree) Generated By:JJTree: Do not edit this line. JSPEL.jj */

+/*@egen*//*******************************************************************************

+ * Copyright (c) 2005, 2010 BEA Systems 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:

+ *     BEA Systems - initial implementation

+ *     IBM Corporation - Bug 318281 - EL validation error for quote escaping

+ *

+ *******************************************************************************/

+/* I know that having some of these options on one line is rude but 

+ * if we don't do that the line number reported from javacc are off

+ * which, trust me, is far more annoying.  --tcarroll@bea.com

+ */

+options {

+  JAVA_UNICODE_ESCAPE = false;

+  UNICODE_INPUT = true;

+  STATIC = false;

+  OPTIMIZE_TOKEN_MANAGER = true;                                                                                                                     

+}

+

+PARSER_BEGIN(JSPELParser)

+

+package org.eclipse.jst.jsp.core.internal.java.jspel;

+

+public class JSPELParser/*@bgen(jjtree)*/implements JSPELParserTreeConstants/*@egen*/ {/*@bgen(jjtree)*/

+  protected JJTJSPELParserState jjtree = new JJTJSPELParserState();

+

+/*@egen*/

+  

+  void jjtreeOpenNodeScope(Node n)

+  {

+          ((SimpleNode)n).setFirstToken(getToken(1));

+  }

+

+  void jjtreeCloseNodeScope(Node n)

+  {

+    ((SimpleNode)n).setLastToken(getToken(0));

+  }

+  

+  public static JSPELParser createParser(java.lang.String input) {

+          java.io.StringReader reader = new java.io.StringReader(input);

+          return new JSPELParser(reader);

+  }

+  

+  public void ReInit(java.lang.String input) {

+           java.io.StringReader reader = new java.io.StringReader(input);

+           ReInit(reader);

+  }

+  

+}

+

+PARSER_END(JSPELParser)

+

+SKIP :

+{

+  " "

+| "\t"

+| "\n"

+| "\r"

+}

+

+TOKEN :

+{

+/* Literals */

+  < INTEGER_LITERAL: ["0"-"9"] (["0"-"9"])* >

+|

+  < FLOATING_POINT_LITERAL:

+        (["0"-"9"])+ "." (["0"-"9"])* (<EXPONENT>)?

+      | "." (["0"-"9"])+ (<EXPONENT>)?

+      | (["0"-"9"])+ <EXPONENT>

+  >

+|

+  < #EXPONENT: ["e","E"] (["+","-"])? (["0"-"9"])+ >

+|

+  < STRING_LITERAL:

+      ("\"" ((~["\"","\\"]) | ("\\" ( ["\\","\"","\'"] )))* "\"") |

+      ("\'" ((~["\'","\\"]) | ("\\" ( ["\\","\'","\""] )))* "\'")

+  >

+|

+  < BADLY_ESCAPED_STRING_LITERAL:

+      ("\"" (~["\"","\\"])* ("\\" ( ~["\\","\""] ))) |

+      ("\'" (~["\'","\\"])* ("\\" ( ~["\\","\'"] )))

+  >

+

+/* Reserved Words and Symbols */

+| < TRUE: "true" >

+| < FALSE: "false" >

+| < NULL: "null" >

+| < DOT: "." >

+| < GT1: ">" >

+| < GT2: "gt" >

+| < LT1: "<" >

+| < LT2: "lt" >

+| < EQ1: "==" >

+| < EQ2: "eq" >

+| < LE1: "<=" >

+| < LE2: "le" >

+| < GE1: ">=" >

+| < GE2: "ge" >

+| < NEQ1: "!=" >

+| < NEQ2: "ne" >

+| < LPAREN: "(" >

+| < RPAREN: ")" >

+| < COMMA: "," >

+| < COLON: ":" >

+| < LBRACKET: "[" >

+| < RBRACKET: "]" >

+| < PLUS: "+" >

+| < MINUS: "-" >

+| < MULTIPLY: "*" >

+| < DIVIDE1: "/" >

+| < DIVIDE2: "div" >

+| < MODULUS1: "%" >

+| < MODULUS2: "mod" >

+| < NOT1: "not" >

+| < NOT2: "!" >

+| < AND1: "and" >

+| < AND2: "&&" >

+| < OR1: "or" >

+| < OR2: "||" >

+| < EMPTY: "empty" >

+| < COND: "?" >

+

+/* Identifiers */

+

+| < IDENTIFIER: (<LETTER>|<IMPL_OBJ_START>) (<LETTER>|<DIGIT>)* >

+| < #IMPL_OBJ_START: "#" >

+|

+  < #LETTER:

+      [

+       "$",

+       "A"-"Z",

+       "_",

+       "a"-"z",

+       "\u00c0"-"\u00d6",

+       "\u00d8"-"\u00f6",

+       "\u00f8"-"\u00ff",

+       "\u0100"-"\u1fff",

+       "\u3040"-"\u318f",

+       "\u3300"-"\u337f",

+       "\u3400"-"\u3d2d",

+       "\u4e00"-"\u9fff",

+       "\uf900"-"\ufaff"

+      ]

+  >

+|

+  < #DIGIT:

+      [

+       "0"-"9",

+       "\u0660"-"\u0669",

+       "\u06f0"-"\u06f9",

+       "\u0966"-"\u096f",

+       "\u09e6"-"\u09ef",

+       "\u0a66"-"\u0a6f",

+       "\u0ae6"-"\u0aef",

+       "\u0b66"-"\u0b6f",

+       "\u0be7"-"\u0bef",

+       "\u0c66"-"\u0c6f",

+       "\u0ce6"-"\u0cef",

+       "\u0d66"-"\u0d6f",

+       "\u0e50"-"\u0e59",

+       "\u0ed0"-"\u0ed9",

+       "\u1040"-"\u1049"

+      ]

+  >

+}

+

+ASTExpression Expression() : {/*@bgen(jjtree) Expression */

+  ASTExpression jjtn000 = new ASTExpression(JJTEXPRESSION);

+  boolean jjtc000 = true;

+  jjtree.openNodeScope(jjtn000);

+  jjtreeOpenNodeScope(jjtn000);

+/*@egen*/}

+{/*@bgen(jjtree) Expression */

+        try {

+/*@egen*/

+        (LOOKAHEAD(ChoiceExpression()) ChoiceExpression() | OrExpression())/*@bgen(jjtree)*/

+                                                                            {

+                                                                              jjtree.closeNodeScope(jjtn000, true);

+                                                                              jjtc000 = false;

+                                                                              jjtreeCloseNodeScope(jjtn000);

+                                                                            }

+/*@egen*/ { return jjtn000; }/*@bgen(jjtree)*/

+        } catch (Throwable jjte000) {

+          if (jjtc000) {

+            jjtree.clearNodeScope(jjtn000);

+            jjtc000 = false;

+          } else {

+            jjtree.popNode();

+          }

+          if (jjte000 instanceof RuntimeException) {

+            throw (RuntimeException)jjte000;

+          }

+          if (jjte000 instanceof ParseException) {

+            throw (ParseException)jjte000;

+          }

+          throw (Error)jjte000;

+        } finally {

+          if (jjtc000) {

+            jjtree.closeNodeScope(jjtn000, true);

+            jjtreeCloseNodeScope(jjtn000);

+          }

+        }

+/*@egen*/

+}

+

+void OrExpression()                   : 

+{/*@bgen(jjtree) #OrExpression(> 1) */

+        ASTOrExpression jjtn000 = new ASTOrExpression(JJTOREXPRESSION);

+        boolean jjtc000 = true;

+        jjtree.openNodeScope(jjtn000);

+        jjtreeOpenNodeScope(jjtn000);

+/*@egen*/

+        Token t;

+}

+{/*@bgen(jjtree) #OrExpression(> 1) */

+        try {

+/*@egen*/

+        AndExpression() ((t = <OR1> | t = <OR2>) { jjtn000.addOperatorToken(t); }

+        AndExpression())*/*@bgen(jjtree)*/

+        } catch (Throwable jjte000) {

+          if (jjtc000) {

+            jjtree.clearNodeScope(jjtn000);

+            jjtc000 = false;

+          } else {

+            jjtree.popNode();

+          }

+          if (jjte000 instanceof RuntimeException) {

+            throw (RuntimeException)jjte000;

+          }

+          if (jjte000 instanceof ParseException) {

+            throw (ParseException)jjte000;

+          }

+          throw (Error)jjte000;

+        } finally {

+          if (jjtc000) {

+            jjtree.closeNodeScope(jjtn000, jjtree.nodeArity() > 1);

+            jjtreeCloseNodeScope(jjtn000);

+          }

+        }

+/*@egen*/

+}

+

+void AndExpression()                    : 

+{/*@bgen(jjtree) #AndExpression(> 1) */

+        ASTAndExpression jjtn000 = new ASTAndExpression(JJTANDEXPRESSION);

+        boolean jjtc000 = true;

+        jjtree.openNodeScope(jjtn000);

+        jjtreeOpenNodeScope(jjtn000);

+/*@egen*/

+        Token t;

+}

+{/*@bgen(jjtree) #AndExpression(> 1) */

+        try {

+/*@egen*/

+        EqualityExpression() ((t = <AND1> | t = <AND2>) { jjtn000.addOperatorToken(t); }

+        EqualityExpression())*/*@bgen(jjtree)*/

+        } catch (Throwable jjte000) {

+          if (jjtc000) {

+            jjtree.clearNodeScope(jjtn000);

+            jjtc000 = false;

+          } else {

+            jjtree.popNode();

+          }

+          if (jjte000 instanceof RuntimeException) {

+            throw (RuntimeException)jjte000;

+          }

+          if (jjte000 instanceof ParseException) {

+            throw (ParseException)jjte000;

+          }

+          throw (Error)jjte000;

+        } finally {

+          if (jjtc000) {

+            jjtree.closeNodeScope(jjtn000, jjtree.nodeArity() > 1);

+            jjtreeCloseNodeScope(jjtn000);

+          }

+        }

+/*@egen*/        

+}

+

+void EqualityExpression()                         : 

+{/*@bgen(jjtree) #EqualityExpression(> 1) */

+        ASTEqualityExpression jjtn000 = new ASTEqualityExpression(JJTEQUALITYEXPRESSION);

+        boolean jjtc000 = true;

+        jjtree.openNodeScope(jjtn000);

+        jjtreeOpenNodeScope(jjtn000);

+/*@egen*/

+        Token t;

+}

+{/*@bgen(jjtree) #EqualityExpression(> 1) */

+        try {

+/*@egen*/

+        RelationalExpression() 

+        ((t = <EQ1> | t = <EQ2> | t = <NEQ1> | t = <NEQ2>) { jjtn000.addOperatorToken(t); }

+        RelationalExpression())*/*@bgen(jjtree)*/

+        } catch (Throwable jjte000) {

+          if (jjtc000) {

+            jjtree.clearNodeScope(jjtn000);

+            jjtc000 = false;

+          } else {

+            jjtree.popNode();

+          }

+          if (jjte000 instanceof RuntimeException) {

+            throw (RuntimeException)jjte000;

+          }

+          if (jjte000 instanceof ParseException) {

+            throw (ParseException)jjte000;

+          }

+          throw (Error)jjte000;

+        } finally {

+          if (jjtc000) {

+            jjtree.closeNodeScope(jjtn000, jjtree.nodeArity() > 1);

+            jjtreeCloseNodeScope(jjtn000);

+          }

+        }

+/*@egen*/

+}

+

+void RelationalExpression()                           :

+{/*@bgen(jjtree) #RelationalExpression(> 1) */

+        ASTRelationalExpression jjtn000 = new ASTRelationalExpression(JJTRELATIONALEXPRESSION);

+        boolean jjtc000 = true;

+        jjtree.openNodeScope(jjtn000);

+        jjtreeOpenNodeScope(jjtn000);

+/*@egen*/

+        Token t;

+}

+{/*@bgen(jjtree) #RelationalExpression(> 1) */

+        try {

+/*@egen*/

+        AddExpression() 

+        (

+                (t = <LT1> | t = <LT2> | t = <GT1> | t = <GT2> | t = <GE1> | t = <GE2> | t = <LE1> | t = <LE2>)  { jjtn000.addOperatorToken(t); }

+                AddExpression()

+        )*/*@bgen(jjtree)*/

+        } catch (Throwable jjte000) {

+          if (jjtc000) {

+            jjtree.clearNodeScope(jjtn000);

+            jjtc000 = false;

+          } else {

+            jjtree.popNode();

+          }

+          if (jjte000 instanceof RuntimeException) {

+            throw (RuntimeException)jjte000;

+          }

+          if (jjte000 instanceof ParseException) {

+            throw (ParseException)jjte000;

+          }

+          throw (Error)jjte000;

+        } finally {

+          if (jjtc000) {

+            jjtree.closeNodeScope(jjtn000, jjtree.nodeArity() > 1);

+            jjtreeCloseNodeScope(jjtn000);

+          }

+        }

+/*@egen*/

+}

+

+void AddExpression()                    : 

+{/*@bgen(jjtree) #AddExpression(> 1) */

+        ASTAddExpression jjtn000 = new ASTAddExpression(JJTADDEXPRESSION);

+        boolean jjtc000 = true;

+        jjtree.openNodeScope(jjtn000);

+        jjtreeOpenNodeScope(jjtn000);

+/*@egen*/

+        Token t;

+}

+{/*@bgen(jjtree) #AddExpression(> 1) */

+        try {

+/*@egen*/

+        MultiplyExpression() ((t = <PLUS> | t = <MINUS>) { jjtn000.addOperatorToken(t); }

+        MultiplyExpression())*/*@bgen(jjtree)*/

+        } catch (Throwable jjte000) {

+          if (jjtc000) {

+            jjtree.clearNodeScope(jjtn000);

+            jjtc000 = false;

+          } else {

+            jjtree.popNode();

+          }

+          if (jjte000 instanceof RuntimeException) {

+            throw (RuntimeException)jjte000;

+          }

+          if (jjte000 instanceof ParseException) {

+            throw (ParseException)jjte000;

+          }

+          throw (Error)jjte000;

+        } finally {

+          if (jjtc000) {

+            jjtree.closeNodeScope(jjtn000, jjtree.nodeArity() > 1);

+            jjtreeCloseNodeScope(jjtn000);

+          }

+        }

+/*@egen*/

+}

+

+void MultiplyExpression()                         : 

+{/*@bgen(jjtree) #MultiplyExpression(> 1) */

+        ASTMultiplyExpression jjtn000 = new ASTMultiplyExpression(JJTMULTIPLYEXPRESSION);

+        boolean jjtc000 = true;

+        jjtree.openNodeScope(jjtn000);

+        jjtreeOpenNodeScope(jjtn000);

+/*@egen*/

+        Token t;

+}

+{/*@bgen(jjtree) #MultiplyExpression(> 1) */

+        try {

+/*@egen*/

+        UnaryExpression() (

+                ( t = <MULTIPLY> | t = <DIVIDE1> | t = <DIVIDE2> | t = <MODULUS1> | t = <MODULUS2>) { jjtn000.addOperatorToken(t); }

+                UnaryExpression()        

+        )*/*@bgen(jjtree)*/

+        } catch (Throwable jjte000) {

+          if (jjtc000) {

+            jjtree.clearNodeScope(jjtn000);

+            jjtc000 = false;

+          } else {

+            jjtree.popNode();

+          }

+          if (jjte000 instanceof RuntimeException) {

+            throw (RuntimeException)jjte000;

+          }

+          if (jjte000 instanceof ParseException) {

+            throw (ParseException)jjte000;

+          }

+          throw (Error)jjte000;

+        } finally {

+          if (jjtc000) {

+            jjtree.closeNodeScope(jjtn000, jjtree.nodeArity() > 1);

+            jjtreeCloseNodeScope(jjtn000);

+          }

+        }

+/*@egen*/

+}

+

+void ChoiceExpression() : {/*@bgen(jjtree) ChoiceExpression */

+  ASTChoiceExpression jjtn000 = new ASTChoiceExpression(JJTCHOICEEXPRESSION);

+  boolean jjtc000 = true;

+  jjtree.openNodeScope(jjtn000);

+  jjtreeOpenNodeScope(jjtn000);

+/*@egen*/}

+{/*@bgen(jjtree) ChoiceExpression */

+        try {

+/*@egen*/

+        OrExpression() <COND> OrExpression() <COLON> OrExpression()/*@bgen(jjtree)*/

+        } catch (Throwable jjte000) {

+          if (jjtc000) {

+            jjtree.clearNodeScope(jjtn000);

+            jjtc000 = false;

+          } else {

+            jjtree.popNode();

+          }

+          if (jjte000 instanceof RuntimeException) {

+            throw (RuntimeException)jjte000;

+          }

+          if (jjte000 instanceof ParseException) {

+            throw (ParseException)jjte000;

+          }

+          throw (Error)jjte000;

+        } finally {

+          if (jjtc000) {

+            jjtree.closeNodeScope(jjtn000, true);

+            jjtreeCloseNodeScope(jjtn000);

+          }

+        }

+/*@egen*/

+}

+

+void UnaryExpression() : {/*@bgen(jjtree) UnaryExpression */

+  ASTUnaryExpression jjtn000 = new ASTUnaryExpression(JJTUNARYEXPRESSION);

+  boolean jjtc000 = true;

+  jjtree.openNodeScope(jjtn000);

+  jjtreeOpenNodeScope(jjtn000);

+/*@egen*/}

+{/*@bgen(jjtree) UnaryExpression */

+        try {

+/*@egen*/

+        ((<NOT1> | <NOT2> | <MINUS> | <EMPTY>) UnaryExpression())

+        | Value()/*@bgen(jjtree)*/

+        } catch (Throwable jjte000) {

+          if (jjtc000) {

+            jjtree.clearNodeScope(jjtn000);

+            jjtc000 = false;

+          } else {

+            jjtree.popNode();

+          }

+          if (jjte000 instanceof RuntimeException) {

+            throw (RuntimeException)jjte000;

+          }

+          if (jjte000 instanceof ParseException) {

+            throw (ParseException)jjte000;

+          }

+          throw (Error)jjte000;

+        } finally {

+          if (jjtc000) {

+            jjtree.closeNodeScope(jjtn000, true);

+            jjtreeCloseNodeScope(jjtn000);

+          }

+        }

+/*@egen*/

+        

+}

+

+void Value() : {/*@bgen(jjtree) Value */

+  ASTValue jjtn000 = new ASTValue(JJTVALUE);

+  boolean jjtc000 = true;

+  jjtree.openNodeScope(jjtn000);

+  jjtreeOpenNodeScope(jjtn000);

+/*@egen*/}

+{/*@bgen(jjtree) Value */

+        try {

+/*@egen*/

+        ValuePrefix() (ValueSuffix())*/*@bgen(jjtree)*/

+        } catch (Throwable jjte000) {

+          if (jjtc000) {

+            jjtree.clearNodeScope(jjtn000);

+            jjtc000 = false;

+          } else {

+            jjtree.popNode();

+          }

+          if (jjte000 instanceof RuntimeException) {

+            throw (RuntimeException)jjte000;

+          }

+          if (jjte000 instanceof ParseException) {

+            throw (ParseException)jjte000;

+          }

+          throw (Error)jjte000;

+        } finally {

+          if (jjtc000) {

+            jjtree.closeNodeScope(jjtn000, true);

+            jjtreeCloseNodeScope(jjtn000);

+          }

+        }

+/*@egen*/

+}

+

+void ValuePrefix() : {/*@bgen(jjtree) ValuePrefix */

+  ASTValuePrefix jjtn000 = new ASTValuePrefix(JJTVALUEPREFIX);

+  boolean jjtc000 = true;

+  jjtree.openNodeScope(jjtn000);

+  jjtreeOpenNodeScope(jjtn000);

+/*@egen*/}

+{/*@bgen(jjtree) ValuePrefix */

+    try {

+/*@egen*/

+    Literal() | (<LPAREN> (Expression())? <RPAREN>) | LOOKAHEAD(3) FunctionInvocation() | <IDENTIFIER>/*@bgen(jjtree)*/

+    } catch (Throwable jjte000) {

+      if (jjtc000) {

+        jjtree.clearNodeScope(jjtn000);

+        jjtc000 = false;

+      } else {

+        jjtree.popNode();

+      }

+      if (jjte000 instanceof RuntimeException) {

+        throw (RuntimeException)jjte000;

+      }

+      if (jjte000 instanceof ParseException) {

+        throw (ParseException)jjte000;

+      }

+      throw (Error)jjte000;

+    } finally {

+      if (jjtc000) {

+        jjtree.closeNodeScope(jjtn000, true);

+        jjtreeCloseNodeScope(jjtn000);

+      }

+    }

+/*@egen*/ 

+}

+

+void ValueSuffix() : 

+{/*@bgen(jjtree) ValueSuffix */

+        ASTValueSuffix jjtn000 = new ASTValueSuffix(JJTVALUESUFFIX);

+        boolean jjtc000 = true;

+        jjtree.openNodeScope(jjtn000);

+        jjtreeOpenNodeScope(jjtn000);

+/*@egen*/

+        Token t = null;

+}

+{/*@bgen(jjtree) ValueSuffix */

+        try {

+/*@egen*/

+        (<DOT> (t = <IDENTIFIER>)?)/*@bgen(jjtree)*/

+                                    {

+                                      jjtree.closeNodeScope(jjtn000, true);

+                                      jjtc000 = false;

+                                      jjtreeCloseNodeScope(jjtn000);

+                                    }

+/*@egen*/ { jjtn000.setPropertyNameToken(t); }

+        | (<LBRACKET> Expression() <RBRACKET>)/*@bgen(jjtree)*/

+        } catch (Throwable jjte000) {

+          if (jjtc000) {

+            jjtree.clearNodeScope(jjtn000);

+            jjtc000 = false;

+          } else {

+            jjtree.popNode();

+          }

+          if (jjte000 instanceof RuntimeException) {

+            throw (RuntimeException)jjte000;

+          }

+          if (jjte000 instanceof ParseException) {

+            throw (ParseException)jjte000;

+          }

+          throw (Error)jjte000;

+        } finally {

+          if (jjtc000) {

+            jjtree.closeNodeScope(jjtn000, true);

+            jjtreeCloseNodeScope(jjtn000);

+          }

+        }

+/*@egen*/

+}

+

+void FunctionInvocation() : 

+{/*@bgen(jjtree) FunctionInvocation */

+        ASTFunctionInvocation jjtn000 = new ASTFunctionInvocation(JJTFUNCTIONINVOCATION);

+        boolean jjtc000 = true;

+        jjtree.openNodeScope(jjtn000);

+        jjtreeOpenNodeScope(jjtn000);

+/*@egen*/

+        Token prefix = null, name = null;

+}

+{/*@bgen(jjtree) FunctionInvocation */

+    try {

+/*@egen*/

+    (prefix = <IDENTIFIER> <COLON>) { jjtn000.setFullFunctionName(prefix.image + ":"); }

+        (name = <IDENTIFIER>)? {

+            if(null != prefix && null != name)

+                    jjtn000.setFullFunctionName(prefix.image + ":" + (null == name ? "" : name.image));

+            else if(null != name)

+                    jjtn000.setFullFunctionName(name.image);

+        }

+        (<LPAREN> (Expression())? (<COMMA> Expression())* try  { (<RPAREN>) } catch (Exception e) {} )?/*@bgen(jjtree)*/

+    } catch (Throwable jjte000) {

+      if (jjtc000) {

+        jjtree.clearNodeScope(jjtn000);

+        jjtc000 = false;

+      } else {

+        jjtree.popNode();

+      }

+      if (jjte000 instanceof RuntimeException) {

+        throw (RuntimeException)jjte000;

+      }

+      if (jjte000 instanceof ParseException) {

+        throw (ParseException)jjte000;

+      }

+      throw (Error)jjte000;

+    } finally {

+      if (jjtc000) {

+        jjtree.closeNodeScope(jjtn000, true);

+        jjtreeCloseNodeScope(jjtn000);

+      }

+    }

+/*@egen*/

+}

+

+void Literal() : {/*@bgen(jjtree) Literal */

+  ASTLiteral jjtn000 = new ASTLiteral(JJTLITERAL);

+  boolean jjtc000 = true;

+  jjtree.openNodeScope(jjtn000);

+  jjtreeOpenNodeScope(jjtn000);

+/*@egen*/}

+{/*@bgen(jjtree) Literal */

+        try {

+/*@egen*/

+        <TRUE> | <FALSE> | <INTEGER_LITERAL> | <FLOATING_POINT_LITERAL> | <STRING_LITERAL> | <NULL>/*@bgen(jjtree)*/

+        } finally {

+          if (jjtc000) {

+            jjtree.closeNodeScope(jjtn000, true);

+            jjtreeCloseNodeScope(jjtn000);

+          }

+        }

+/*@egen*/

+}

diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/JSPEL.jjt b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/JSPEL.jjt
new file mode 100644
index 0000000..66d2c79
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/JSPEL.jjt
@@ -0,0 +1,282 @@
+/*******************************************************************************

+ * Copyright (c) 2005, 2010 BEA Systems 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:

+ *     BEA Systems - initial implementation

+ *     IBM Corporation - Bug 318281 - EL validation error for quote escaping

+ *

+ *******************************************************************************/

+/* I know that having some of these options on one line is rude but 

+ * if we don't do that the line number reported from javacc are off

+ * which, trust me, is far more annoying.  --tcarroll@bea.com

+ */

+options {

+  JAVA_UNICODE_ESCAPE = false;

+  UNICODE_INPUT = true;

+  STATIC = false;

+  OPTIMIZE_TOKEN_MANAGER = true; MULTI = true; VISITOR = true; NODE_PACKAGE = "org.eclipse.jst.jsp.core.internal.java.jspel"; NODE_SCOPE_HOOK = true;

+}

+

+PARSER_BEGIN(JSPELParser)

+

+package org.eclipse.jst.jsp.core.internal.java.jspel;

+

+public class JSPELParser {

+  

+  void jjtreeOpenNodeScope(Node n)

+  {

+          ((SimpleNode)n).setFirstToken(getToken(1));

+  }

+

+  void jjtreeCloseNodeScope(Node n)

+  {

+    ((SimpleNode)n).setLastToken(getToken(0));

+  }

+  

+  public static JSPELParser createParser(java.lang.String input) {

+          java.io.StringReader reader = new java.io.StringReader(input);

+          return new JSPELParser(reader);

+  }

+  

+  public void ReInit(java.lang.String input) {

+           java.io.StringReader reader = new java.io.StringReader(input);

+           ReInit(reader);

+  }

+  

+}

+

+PARSER_END(JSPELParser)

+

+SKIP :

+{

+  " "

+| "\t"

+| "\n"

+| "\r"

+}

+

+TOKEN :

+{

+/* Literals */

+  < INTEGER_LITERAL: ["0"-"9"] (["0"-"9"])* >

+|

+  < FLOATING_POINT_LITERAL:

+        (["0"-"9"])+ "." (["0"-"9"])* (<EXPONENT>)?

+      | "." (["0"-"9"])+ (<EXPONENT>)?

+      | (["0"-"9"])+ <EXPONENT>

+  >

+|

+  < #EXPONENT: ["e","E"] (["+","-"])? (["0"-"9"])+ >

+|

+  < STRING_LITERAL:

+      ("\"" ((~["\"","\\"]) | ("\\" ( ["\\","\"","\'"] )))* "\"") |

+      ("\'" ((~["\'","\\"]) | ("\\" ( ["\\","\'","\""] )))* "\'")

+  >

+|

+  < BADLY_ESCAPED_STRING_LITERAL:

+      ("\"" (~["\"","\\"])* ("\\" ( ~["\\","\""] ))) |

+      ("\'" (~["\'","\\"])* ("\\" ( ~["\\","\'"] )))

+  >

+

+/* Reserved Words and Symbols */

+| < TRUE: "true" >

+| < FALSE: "false" >

+| < NULL: "null" >

+| < DOT: "." >

+| < GT1: ">" >

+| < GT2: "gt" >

+| < LT1: "<" >

+| < LT2: "lt" >

+| < EQ1: "==" >

+| < EQ2: "eq" >

+| < LE1: "<=" >

+| < LE2: "le" >

+| < GE1: ">=" >

+| < GE2: "ge" >

+| < NEQ1: "!=" >

+| < NEQ2: "ne" >

+| < LPAREN: "(" >

+| < RPAREN: ")" >

+| < COMMA: "," >

+| < COLON: ":" >

+| < LBRACKET: "[" >

+| < RBRACKET: "]" >

+| < PLUS: "+" >

+| < MINUS: "-" >

+| < MULTIPLY: "*" >

+| < DIVIDE1: "/" >

+| < DIVIDE2: "div" >

+| < MODULUS1: "%" >

+| < MODULUS2: "mod" >

+| < NOT1: "not" >

+| < NOT2: "!" >

+| < AND1: "and" >

+| < AND2: "&&" >

+| < OR1: "or" >

+| < OR2: "||" >

+| < EMPTY: "empty" >

+| < COND: "?" >

+

+/* Identifiers */

+

+| < IDENTIFIER: (<LETTER>|<IMPL_OBJ_START>) (<LETTER>|<DIGIT>)* >

+| < #IMPL_OBJ_START: "#" >

+|

+  < #LETTER:

+      [

+       "\u0024",

+       "\u0041"-"\u005a",

+       "\u005f",

+       "\u0061"-"\u007a",

+       "\u00c0"-"\u00d6",

+       "\u00d8"-"\u00f6",

+       "\u00f8"-"\u00ff",

+       "\u0100"-"\u1fff",

+       "\u3040"-"\u318f",

+       "\u3300"-"\u337f",

+       "\u3400"-"\u3d2d",

+       "\u4e00"-"\u9fff",

+       "\uf900"-"\ufaff"

+      ]

+  >

+|

+  < #DIGIT:

+      [

+       "\u0030"-"\u0039",

+       "\u0660"-"\u0669",

+       "\u06f0"-"\u06f9",

+       "\u0966"-"\u096f",

+       "\u09e6"-"\u09ef",

+       "\u0a66"-"\u0a6f",

+       "\u0ae6"-"\u0aef",

+       "\u0b66"-"\u0b6f",

+       "\u0be7"-"\u0bef",

+       "\u0c66"-"\u0c6f",

+       "\u0ce6"-"\u0cef",

+       "\u0d66"-"\u0d6f",

+       "\u0e50"-"\u0e59",

+       "\u0ed0"-"\u0ed9",

+       "\u1040"-"\u1049"

+      ]

+  >

+}

+

+ASTExpression Expression() : {}

+{

+        (LOOKAHEAD(ChoiceExpression()) ChoiceExpression() | OrExpression()) { return jjtThis; }

+}

+

+void OrExpression() #OrExpression(>1) : 

+{

+        Token t;

+}

+{

+        AndExpression() ((t = <OR1> | t = <OR2>) { jjtThis.addOperatorToken(t); }

+        AndExpression())*

+}

+

+void AndExpression() #AndExpression(>1) : 

+{

+        Token t;

+}

+{

+        EqualityExpression() ((t = <AND1> | t = <AND2>) { jjtThis.addOperatorToken(t); }

+        EqualityExpression())*        

+}

+

+void EqualityExpression() #EqualityExpression(>1) : 

+{

+        Token t;

+}

+{

+        RelationalExpression() 

+        ((t = <EQ1> | t = <EQ2> | t = <NEQ1> | t = <NEQ2>) { jjtThis.addOperatorToken(t); }

+        RelationalExpression())*

+}

+

+void RelationalExpression() #RelationalExpression(>1) :

+{

+        Token t;

+}

+{

+        AddExpression() 

+        (

+                (t = <LT1> | t = <LT2> | t = <GT1> | t = <GT2> | t = <GE1> | t = <GE2> | t = <LE1> | t = <LE2>)  { jjtThis.addOperatorToken(t); }

+                AddExpression()

+        )*

+}

+

+void AddExpression() #AddExpression(>1) : 

+{

+        Token t;

+}

+{

+        MultiplyExpression() ((t = <PLUS> | t = <MINUS>) { jjtThis.addOperatorToken(t); }

+        MultiplyExpression())*

+}

+

+void MultiplyExpression() #MultiplyExpression(>1) : 

+{

+        Token t;

+}

+{

+        UnaryExpression() (

+                ( t = <MULTIPLY> | t = <DIVIDE1> | t = <DIVIDE2> | t = <MODULUS1> | t = <MODULUS2>) { jjtThis.addOperatorToken(t); }

+                UnaryExpression()        

+        )*

+}

+

+void ChoiceExpression() : {}

+{

+        OrExpression() <COND> OrExpression() <COLON> OrExpression()

+}

+

+void UnaryExpression() : {}

+{

+        ((<NOT1> | <NOT2> | <MINUS> | <EMPTY>) UnaryExpression())

+        | Value()

+        

+}

+

+void Value() : {}

+{

+        ValuePrefix() (ValueSuffix())*

+}

+

+void ValuePrefix() : {}

+{

+    Literal() | (<LPAREN> (Expression())? <RPAREN>) | LOOKAHEAD(3) FunctionInvocation() | <IDENTIFIER> 

+}

+

+void ValueSuffix() : 

+{

+        Token t = null;

+}

+{

+        (<DOT> (t = <IDENTIFIER>)?) { jjtThis.setPropertyNameToken(t); }

+        | (<LBRACKET> Expression() <RBRACKET>)

+}

+

+void FunctionInvocation() : 

+{

+        Token prefix = null, name = null;

+}

+{

+    (prefix = <IDENTIFIER> <COLON>) { jjtThis.setFullFunctionName(prefix.image + ":"); }

+        (name = <IDENTIFIER>)? {

+            if(null != prefix && null != name)

+                    jjtThis.setFullFunctionName(prefix.image + ":" + (null == name ? "" : name.image));

+            else if(null != name)

+                    jjtThis.setFullFunctionName(name.image);

+        }

+        (<LPAREN> (Expression())? (<COMMA> Expression())* try  { (<RPAREN>) } catch (Exception e) {} )?

+}

+

+void Literal() : {}

+{

+        <TRUE> | <FALSE> | <INTEGER_LITERAL> | <FLOATING_POINT_LITERAL> | <STRING_LITERAL> | <NULL>

+}

diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/JSPELParser.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/JSPELParser.java
new file mode 100644
index 0000000..9e3c2e7
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/JSPELParser.java
@@ -0,0 +1,1536 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2010 BEA Systems 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:
+ *     BEA Systems - initial implementation
+ *     IBM Corporation - Bug 318281 - EL validation error for quote escaping
+ *
+ *******************************************************************************/
+/* Generated By:JJTree&JavaCC: Do not edit this line. JSPELParser.java */
+package org.eclipse.jst.jsp.core.internal.java.jspel;
+
+public class JSPELParser/*@bgen(jjtree)*/implements JSPELParserTreeConstants, JSPELParserConstants {/*@bgen(jjtree)*/
+  protected JJTJSPELParserState jjtree = new JJTJSPELParserState();
+  void jjtreeOpenNodeScope(Node n)
+  {
+          ((SimpleNode)n).setFirstToken(getToken(1));
+  }
+
+  void jjtreeCloseNodeScope(Node n)
+  {
+    ((SimpleNode)n).setLastToken(getToken(0));
+  }
+
+  public static JSPELParser createParser(java.lang.String input) {
+          java.io.StringReader reader = new java.io.StringReader(input);
+          return new JSPELParser(reader);
+  }
+
+  public void ReInit(java.lang.String input) {
+           java.io.StringReader reader = new java.io.StringReader(input);
+           ReInit(reader);
+  }
+
+  final public ASTExpression Expression() throws ParseException {
+                              /*@bgen(jjtree) Expression */
+  ASTExpression jjtn000 = new ASTExpression(JJTEXPRESSION);
+  boolean jjtc000 = true;
+  jjtree.openNodeScope(jjtn000);
+  jjtreeOpenNodeScope(jjtn000);
+    try {
+      if (jj_2_1(2147483647)) {
+        ChoiceExpression();
+      } else {
+        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+        case INTEGER_LITERAL:
+        case FLOATING_POINT_LITERAL:
+        case STRING_LITERAL:
+        case TRUE:
+        case FALSE:
+        case NULL:
+        case LPAREN:
+        case MINUS:
+        case NOT1:
+        case NOT2:
+        case EMPTY:
+        case IDENTIFIER:
+          OrExpression();
+          break;
+        default:
+          jj_la1[0] = jj_gen;
+          jj_consume_token(-1);
+          throw new ParseException();
+        }
+      }
+                                                                              jjtree.closeNodeScope(jjtn000, true);
+                                                                              jjtc000 = false;
+                                                                              jjtreeCloseNodeScope(jjtn000);
+                                                                              {if (true) return jjtn000;}
+    } catch (Throwable jjte000) {
+          if (jjtc000) {
+            jjtree.clearNodeScope(jjtn000);
+            jjtc000 = false;
+          } else {
+            jjtree.popNode();
+          }
+          if (jjte000 instanceof RuntimeException) {
+            {if (true) throw (RuntimeException)jjte000;}
+          }
+          if (jjte000 instanceof ParseException) {
+            {if (true) throw (ParseException)jjte000;}
+          }
+          {if (true) throw (Error)jjte000;}
+    } finally {
+          if (jjtc000) {
+            jjtree.closeNodeScope(jjtn000, true);
+            jjtreeCloseNodeScope(jjtn000);
+          }
+    }
+    throw new Error("Missing return statement in function");
+  }
+
+  final public void OrExpression() throws ParseException {
+ /*@bgen(jjtree) #OrExpression(> 1) */
+        ASTOrExpression jjtn000 = new ASTOrExpression(JJTOREXPRESSION);
+        boolean jjtc000 = true;
+        jjtree.openNodeScope(jjtn000);
+        jjtreeOpenNodeScope(jjtn000);Token t;
+    try {
+      AndExpression();
+      label_1:
+      while (true) {
+        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+        case OR1:
+        case OR2:
+          break;
+        default:
+          jj_la1[1] = jj_gen;
+          break label_1;
+        }
+        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+        case OR1:
+          t = jj_consume_token(OR1);
+          break;
+        case OR2:
+          t = jj_consume_token(OR2);
+          break;
+        default:
+          jj_la1[2] = jj_gen;
+          jj_consume_token(-1);
+          throw new ParseException();
+        }
+                                                   jjtn000.addOperatorToken(t);
+        AndExpression();
+      }
+    } catch (Throwable jjte000) {
+          if (jjtc000) {
+            jjtree.clearNodeScope(jjtn000);
+            jjtc000 = false;
+          } else {
+            jjtree.popNode();
+          }
+          if (jjte000 instanceof RuntimeException) {
+            {if (true) throw (RuntimeException)jjte000;}
+          }
+          if (jjte000 instanceof ParseException) {
+            {if (true) throw (ParseException)jjte000;}
+          }
+          {if (true) throw (Error)jjte000;}
+    } finally {
+          if (jjtc000) {
+            jjtree.closeNodeScope(jjtn000, jjtree.nodeArity() > 1);
+            jjtreeCloseNodeScope(jjtn000);
+          }
+    }
+  }
+
+  final public void AndExpression() throws ParseException {
+ /*@bgen(jjtree) #AndExpression(> 1) */
+        ASTAndExpression jjtn000 = new ASTAndExpression(JJTANDEXPRESSION);
+        boolean jjtc000 = true;
+        jjtree.openNodeScope(jjtn000);
+        jjtreeOpenNodeScope(jjtn000);Token t;
+    try {
+      EqualityExpression();
+      label_2:
+      while (true) {
+        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+        case AND1:
+        case AND2:
+          break;
+        default:
+          jj_la1[3] = jj_gen;
+          break label_2;
+        }
+        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+        case AND1:
+          t = jj_consume_token(AND1);
+          break;
+        case AND2:
+          t = jj_consume_token(AND2);
+          break;
+        default:
+          jj_la1[4] = jj_gen;
+          jj_consume_token(-1);
+          throw new ParseException();
+        }
+                                                          jjtn000.addOperatorToken(t);
+        EqualityExpression();
+      }
+    } catch (Throwable jjte000) {
+          if (jjtc000) {
+            jjtree.clearNodeScope(jjtn000);
+            jjtc000 = false;
+          } else {
+            jjtree.popNode();
+          }
+          if (jjte000 instanceof RuntimeException) {
+            {if (true) throw (RuntimeException)jjte000;}
+          }
+          if (jjte000 instanceof ParseException) {
+            {if (true) throw (ParseException)jjte000;}
+          }
+          {if (true) throw (Error)jjte000;}
+    } finally {
+          if (jjtc000) {
+            jjtree.closeNodeScope(jjtn000, jjtree.nodeArity() > 1);
+            jjtreeCloseNodeScope(jjtn000);
+          }
+    }
+  }
+
+  final public void EqualityExpression() throws ParseException {
+ /*@bgen(jjtree) #EqualityExpression(> 1) */
+        ASTEqualityExpression jjtn000 = new ASTEqualityExpression(JJTEQUALITYEXPRESSION);
+        boolean jjtc000 = true;
+        jjtree.openNodeScope(jjtn000);
+        jjtreeOpenNodeScope(jjtn000);Token t;
+    try {
+      RelationalExpression();
+      label_3:
+      while (true) {
+        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+        case EQ1:
+        case EQ2:
+        case NEQ1:
+        case NEQ2:
+          break;
+        default:
+          jj_la1[5] = jj_gen;
+          break label_3;
+        }
+        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+        case EQ1:
+          t = jj_consume_token(EQ1);
+          break;
+        case EQ2:
+          t = jj_consume_token(EQ2);
+          break;
+        case NEQ1:
+          t = jj_consume_token(NEQ1);
+          break;
+        case NEQ2:
+          t = jj_consume_token(NEQ2);
+          break;
+        default:
+          jj_la1[6] = jj_gen;
+          jj_consume_token(-1);
+          throw new ParseException();
+        }
+                                                             jjtn000.addOperatorToken(t);
+        RelationalExpression();
+      }
+    } catch (Throwable jjte000) {
+          if (jjtc000) {
+            jjtree.clearNodeScope(jjtn000);
+            jjtc000 = false;
+          } else {
+            jjtree.popNode();
+          }
+          if (jjte000 instanceof RuntimeException) {
+            {if (true) throw (RuntimeException)jjte000;}
+          }
+          if (jjte000 instanceof ParseException) {
+            {if (true) throw (ParseException)jjte000;}
+          }
+          {if (true) throw (Error)jjte000;}
+    } finally {
+          if (jjtc000) {
+            jjtree.closeNodeScope(jjtn000, jjtree.nodeArity() > 1);
+            jjtreeCloseNodeScope(jjtn000);
+          }
+    }
+  }
+
+  final public void RelationalExpression() throws ParseException {
+ /*@bgen(jjtree) #RelationalExpression(> 1) */
+        ASTRelationalExpression jjtn000 = new ASTRelationalExpression(JJTRELATIONALEXPRESSION);
+        boolean jjtc000 = true;
+        jjtree.openNodeScope(jjtn000);
+        jjtreeOpenNodeScope(jjtn000);Token t;
+    try {
+      AddExpression();
+      label_4:
+      while (true) {
+        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+        case GT1:
+        case GT2:
+        case LT1:
+        case LT2:
+        case LE1:
+        case LE2:
+        case GE1:
+        case GE2:
+          break;
+        default:
+          jj_la1[7] = jj_gen;
+          break label_4;
+        }
+        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+        case LT1:
+          t = jj_consume_token(LT1);
+          break;
+        case LT2:
+          t = jj_consume_token(LT2);
+          break;
+        case GT1:
+          t = jj_consume_token(GT1);
+          break;
+        case GT2:
+          t = jj_consume_token(GT2);
+          break;
+        case GE1:
+          t = jj_consume_token(GE1);
+          break;
+        case GE2:
+          t = jj_consume_token(GE2);
+          break;
+        case LE1:
+          t = jj_consume_token(LE1);
+          break;
+        case LE2:
+          t = jj_consume_token(LE2);
+          break;
+        default:
+          jj_la1[8] = jj_gen;
+          jj_consume_token(-1);
+          throw new ParseException();
+        }
+                                                                                                                   jjtn000.addOperatorToken(t);
+        AddExpression();
+      }
+    } catch (Throwable jjte000) {
+          if (jjtc000) {
+            jjtree.clearNodeScope(jjtn000);
+            jjtc000 = false;
+          } else {
+            jjtree.popNode();
+          }
+          if (jjte000 instanceof RuntimeException) {
+            {if (true) throw (RuntimeException)jjte000;}
+          }
+          if (jjte000 instanceof ParseException) {
+            {if (true) throw (ParseException)jjte000;}
+          }
+          {if (true) throw (Error)jjte000;}
+    } finally {
+          if (jjtc000) {
+            jjtree.closeNodeScope(jjtn000, jjtree.nodeArity() > 1);
+            jjtreeCloseNodeScope(jjtn000);
+          }
+    }
+  }
+
+  final public void AddExpression() throws ParseException {
+ /*@bgen(jjtree) #AddExpression(> 1) */
+        ASTAddExpression jjtn000 = new ASTAddExpression(JJTADDEXPRESSION);
+        boolean jjtc000 = true;
+        jjtree.openNodeScope(jjtn000);
+        jjtreeOpenNodeScope(jjtn000);Token t;
+    try {
+      MultiplyExpression();
+      label_5:
+      while (true) {
+        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+        case PLUS:
+        case MINUS:
+          break;
+        default:
+          jj_la1[9] = jj_gen;
+          break label_5;
+        }
+        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+        case PLUS:
+          t = jj_consume_token(PLUS);
+          break;
+        case MINUS:
+          t = jj_consume_token(MINUS);
+          break;
+        default:
+          jj_la1[10] = jj_gen;
+          jj_consume_token(-1);
+          throw new ParseException();
+        }
+                                                           jjtn000.addOperatorToken(t);
+        MultiplyExpression();
+      }
+    } catch (Throwable jjte000) {
+          if (jjtc000) {
+            jjtree.clearNodeScope(jjtn000);
+            jjtc000 = false;
+          } else {
+            jjtree.popNode();
+          }
+          if (jjte000 instanceof RuntimeException) {
+            {if (true) throw (RuntimeException)jjte000;}
+          }
+          if (jjte000 instanceof ParseException) {
+            {if (true) throw (ParseException)jjte000;}
+          }
+          {if (true) throw (Error)jjte000;}
+    } finally {
+          if (jjtc000) {
+            jjtree.closeNodeScope(jjtn000, jjtree.nodeArity() > 1);
+            jjtreeCloseNodeScope(jjtn000);
+          }
+    }
+  }
+
+  final public void MultiplyExpression() throws ParseException {
+ /*@bgen(jjtree) #MultiplyExpression(> 1) */
+        ASTMultiplyExpression jjtn000 = new ASTMultiplyExpression(JJTMULTIPLYEXPRESSION);
+        boolean jjtc000 = true;
+        jjtree.openNodeScope(jjtn000);
+        jjtreeOpenNodeScope(jjtn000);Token t;
+    try {
+      UnaryExpression();
+      label_6:
+      while (true) {
+        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+        case MULTIPLY:
+        case DIVIDE1:
+        case DIVIDE2:
+        case MODULUS1:
+        case MODULUS2:
+          break;
+        default:
+          jj_la1[11] = jj_gen;
+          break label_6;
+        }
+        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+        case MULTIPLY:
+          t = jj_consume_token(MULTIPLY);
+          break;
+        case DIVIDE1:
+          t = jj_consume_token(DIVIDE1);
+          break;
+        case DIVIDE2:
+          t = jj_consume_token(DIVIDE2);
+          break;
+        case MODULUS1:
+          t = jj_consume_token(MODULUS1);
+          break;
+        case MODULUS2:
+          t = jj_consume_token(MODULUS2);
+          break;
+        default:
+          jj_la1[12] = jj_gen;
+          jj_consume_token(-1);
+          throw new ParseException();
+        }
+                                                                                                      jjtn000.addOperatorToken(t);
+        UnaryExpression();
+      }
+    } catch (Throwable jjte000) {
+          if (jjtc000) {
+            jjtree.clearNodeScope(jjtn000);
+            jjtc000 = false;
+          } else {
+            jjtree.popNode();
+          }
+          if (jjte000 instanceof RuntimeException) {
+            {if (true) throw (RuntimeException)jjte000;}
+          }
+          if (jjte000 instanceof ParseException) {
+            {if (true) throw (ParseException)jjte000;}
+          }
+          {if (true) throw (Error)jjte000;}
+    } finally {
+          if (jjtc000) {
+            jjtree.closeNodeScope(jjtn000, jjtree.nodeArity() > 1);
+            jjtreeCloseNodeScope(jjtn000);
+          }
+    }
+  }
+
+  final public void ChoiceExpression() throws ParseException {
+                           /*@bgen(jjtree) ChoiceExpression */
+  ASTChoiceExpression jjtn000 = new ASTChoiceExpression(JJTCHOICEEXPRESSION);
+  boolean jjtc000 = true;
+  jjtree.openNodeScope(jjtn000);
+  jjtreeOpenNodeScope(jjtn000);
+    try {
+      OrExpression();
+      jj_consume_token(COND);
+      OrExpression();
+      jj_consume_token(COLON);
+      OrExpression();
+    } catch (Throwable jjte000) {
+          if (jjtc000) {
+            jjtree.clearNodeScope(jjtn000);
+            jjtc000 = false;
+          } else {
+            jjtree.popNode();
+          }
+          if (jjte000 instanceof RuntimeException) {
+            {if (true) throw (RuntimeException)jjte000;}
+          }
+          if (jjte000 instanceof ParseException) {
+            {if (true) throw (ParseException)jjte000;}
+          }
+          {if (true) throw (Error)jjte000;}
+    } finally {
+          if (jjtc000) {
+            jjtree.closeNodeScope(jjtn000, true);
+            jjtreeCloseNodeScope(jjtn000);
+          }
+    }
+  }
+
+  final public void UnaryExpression() throws ParseException {
+                          /*@bgen(jjtree) UnaryExpression */
+  ASTUnaryExpression jjtn000 = new ASTUnaryExpression(JJTUNARYEXPRESSION);
+  boolean jjtc000 = true;
+  jjtree.openNodeScope(jjtn000);
+  jjtreeOpenNodeScope(jjtn000);
+    try {
+      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+      case MINUS:
+      case NOT1:
+      case NOT2:
+      case EMPTY:
+        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+        case NOT1:
+          jj_consume_token(NOT1);
+          break;
+        case NOT2:
+          jj_consume_token(NOT2);
+          break;
+        case MINUS:
+          jj_consume_token(MINUS);
+          break;
+        case EMPTY:
+          jj_consume_token(EMPTY);
+          break;
+        default:
+          jj_la1[13] = jj_gen;
+          jj_consume_token(-1);
+          throw new ParseException();
+        }
+        UnaryExpression();
+        break;
+      case INTEGER_LITERAL:
+      case FLOATING_POINT_LITERAL:
+      case STRING_LITERAL:
+      case TRUE:
+      case FALSE:
+      case NULL:
+      case LPAREN:
+      case IDENTIFIER:
+        Value();
+        break;
+      default:
+        jj_la1[14] = jj_gen;
+        jj_consume_token(-1);
+        throw new ParseException();
+      }
+    } catch (Throwable jjte000) {
+          if (jjtc000) {
+            jjtree.clearNodeScope(jjtn000);
+            jjtc000 = false;
+          } else {
+            jjtree.popNode();
+          }
+          if (jjte000 instanceof RuntimeException) {
+            {if (true) throw (RuntimeException)jjte000;}
+          }
+          if (jjte000 instanceof ParseException) {
+            {if (true) throw (ParseException)jjte000;}
+          }
+          {if (true) throw (Error)jjte000;}
+    } finally {
+          if (jjtc000) {
+            jjtree.closeNodeScope(jjtn000, true);
+            jjtreeCloseNodeScope(jjtn000);
+          }
+    }
+  }
+
+  final public void Value() throws ParseException {
+                /*@bgen(jjtree) Value */
+  ASTValue jjtn000 = new ASTValue(JJTVALUE);
+  boolean jjtc000 = true;
+  jjtree.openNodeScope(jjtn000);
+  jjtreeOpenNodeScope(jjtn000);
+    try {
+      ValuePrefix();
+      label_7:
+      while (true) {
+        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+        case DOT:
+        case LBRACKET:
+          break;
+        default:
+          jj_la1[15] = jj_gen;
+          break label_7;
+        }
+        ValueSuffix();
+      }
+    } catch (Throwable jjte000) {
+          if (jjtc000) {
+            jjtree.clearNodeScope(jjtn000);
+            jjtc000 = false;
+          } else {
+            jjtree.popNode();
+          }
+          if (jjte000 instanceof RuntimeException) {
+            {if (true) throw (RuntimeException)jjte000;}
+          }
+          if (jjte000 instanceof ParseException) {
+            {if (true) throw (ParseException)jjte000;}
+          }
+          {if (true) throw (Error)jjte000;}
+    } finally {
+          if (jjtc000) {
+            jjtree.closeNodeScope(jjtn000, true);
+            jjtreeCloseNodeScope(jjtn000);
+          }
+    }
+  }
+
+  final public void ValuePrefix() throws ParseException {
+                      /*@bgen(jjtree) ValuePrefix */
+  ASTValuePrefix jjtn000 = new ASTValuePrefix(JJTVALUEPREFIX);
+  boolean jjtc000 = true;
+  jjtree.openNodeScope(jjtn000);
+  jjtreeOpenNodeScope(jjtn000);
+    try {
+      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+      case INTEGER_LITERAL:
+      case FLOATING_POINT_LITERAL:
+      case STRING_LITERAL:
+      case TRUE:
+      case FALSE:
+      case NULL:
+        Literal();
+        break;
+      case LPAREN:
+        jj_consume_token(LPAREN);
+        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+        case INTEGER_LITERAL:
+        case FLOATING_POINT_LITERAL:
+        case STRING_LITERAL:
+        case TRUE:
+        case FALSE:
+        case NULL:
+        case LPAREN:
+        case MINUS:
+        case NOT1:
+        case NOT2:
+        case EMPTY:
+        case IDENTIFIER:
+          Expression();
+          break;
+        default:
+          jj_la1[16] = jj_gen;
+        }
+        jj_consume_token(RPAREN);
+        break;
+      default:
+        jj_la1[17] = jj_gen;
+        if (jj_2_2(3)) {
+          FunctionInvocation();
+        } else {
+          switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+          case IDENTIFIER:
+            jj_consume_token(IDENTIFIER);
+            break;
+          default:
+            jj_la1[18] = jj_gen;
+            jj_consume_token(-1);
+            throw new ParseException();
+          }
+        }
+      }
+    } catch (Throwable jjte000) {
+      if (jjtc000) {
+        jjtree.clearNodeScope(jjtn000);
+        jjtc000 = false;
+      } else {
+        jjtree.popNode();
+      }
+      if (jjte000 instanceof RuntimeException) {
+        {if (true) throw (RuntimeException)jjte000;}
+      }
+      if (jjte000 instanceof ParseException) {
+        {if (true) throw (ParseException)jjte000;}
+      }
+      {if (true) throw (Error)jjte000;}
+    } finally {
+      if (jjtc000) {
+        jjtree.closeNodeScope(jjtn000, true);
+        jjtreeCloseNodeScope(jjtn000);
+      }
+    }
+  }
+
+  final public void ValueSuffix() throws ParseException {
+ /*@bgen(jjtree) ValueSuffix */
+        ASTValueSuffix jjtn000 = new ASTValueSuffix(JJTVALUESUFFIX);
+        boolean jjtc000 = true;
+        jjtree.openNodeScope(jjtn000);
+        jjtreeOpenNodeScope(jjtn000);Token t = null;
+    try {
+      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+      case DOT:
+        jj_consume_token(DOT);
+        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+        case IDENTIFIER:
+          t = jj_consume_token(IDENTIFIER);
+          break;
+        default:
+          jj_la1[19] = jj_gen;
+        }
+                                      jjtree.closeNodeScope(jjtn000, true);
+                                      jjtc000 = false;
+                                      jjtreeCloseNodeScope(jjtn000);
+                                      jjtn000.setPropertyNameToken(t);
+        break;
+      case LBRACKET:
+        jj_consume_token(LBRACKET);
+        Expression();
+        jj_consume_token(RBRACKET);
+        break;
+      default:
+        jj_la1[20] = jj_gen;
+        jj_consume_token(-1);
+        throw new ParseException();
+      }
+    } catch (Throwable jjte000) {
+          if (jjtc000) {
+            jjtree.clearNodeScope(jjtn000);
+            jjtc000 = false;
+          } else {
+            jjtree.popNode();
+          }
+          if (jjte000 instanceof RuntimeException) {
+            {if (true) throw (RuntimeException)jjte000;}
+          }
+          if (jjte000 instanceof ParseException) {
+            {if (true) throw (ParseException)jjte000;}
+          }
+          {if (true) throw (Error)jjte000;}
+    } finally {
+          if (jjtc000) {
+            jjtree.closeNodeScope(jjtn000, true);
+            jjtreeCloseNodeScope(jjtn000);
+          }
+    }
+  }
+
+  final public void FunctionInvocation() throws ParseException {
+ /*@bgen(jjtree) FunctionInvocation */
+        ASTFunctionInvocation jjtn000 = new ASTFunctionInvocation(JJTFUNCTIONINVOCATION);
+        boolean jjtc000 = true;
+        jjtree.openNodeScope(jjtn000);
+        jjtreeOpenNodeScope(jjtn000);Token prefix = null, name = null;
+    try {
+      prefix = jj_consume_token(IDENTIFIER);
+      jj_consume_token(COLON);
+                                      jjtn000.setFullFunctionName(prefix.image + ":");
+      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+      case IDENTIFIER:
+        name = jj_consume_token(IDENTIFIER);
+        break;
+      default:
+        jj_la1[21] = jj_gen;
+      }
+            if(null != prefix && null != name)
+                    jjtn000.setFullFunctionName(prefix.image + ":" + (null == name ? "" : name.image));
+            else if(null != name)
+                    jjtn000.setFullFunctionName(name.image);
+      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+      case LPAREN:
+        jj_consume_token(LPAREN);
+        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+        case INTEGER_LITERAL:
+        case FLOATING_POINT_LITERAL:
+        case STRING_LITERAL:
+        case TRUE:
+        case FALSE:
+        case NULL:
+        case LPAREN:
+        case MINUS:
+        case NOT1:
+        case NOT2:
+        case EMPTY:
+        case IDENTIFIER:
+          Expression();
+          break;
+        default:
+          jj_la1[22] = jj_gen;
+        }
+        label_8:
+        while (true) {
+          switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+          case COMMA:
+            break;
+          default:
+            jj_la1[23] = jj_gen;
+            break label_8;
+          }
+          jj_consume_token(COMMA);
+          Expression();
+        }
+        try {
+          jj_consume_token(RPAREN);
+        } catch (Exception e) {
+
+        }
+        break;
+      default:
+        jj_la1[24] = jj_gen;
+      }
+    } catch (Throwable jjte000) {
+      if (jjtc000) {
+        jjtree.clearNodeScope(jjtn000);
+        jjtc000 = false;
+      } else {
+        jjtree.popNode();
+      }
+      if (jjte000 instanceof RuntimeException) {
+        {if (true) throw (RuntimeException)jjte000;}
+      }
+      if (jjte000 instanceof ParseException) {
+        {if (true) throw (ParseException)jjte000;}
+      }
+      {if (true) throw (Error)jjte000;}
+    } finally {
+      if (jjtc000) {
+        jjtree.closeNodeScope(jjtn000, true);
+        jjtreeCloseNodeScope(jjtn000);
+      }
+    }
+  }
+
+  final public void Literal() throws ParseException {
+                  /*@bgen(jjtree) Literal */
+  ASTLiteral jjtn000 = new ASTLiteral(JJTLITERAL);
+  boolean jjtc000 = true;
+  jjtree.openNodeScope(jjtn000);
+  jjtreeOpenNodeScope(jjtn000);
+    try {
+      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+      case TRUE:
+        jj_consume_token(TRUE);
+        break;
+      case FALSE:
+        jj_consume_token(FALSE);
+        break;
+      case INTEGER_LITERAL:
+        jj_consume_token(INTEGER_LITERAL);
+        break;
+      case FLOATING_POINT_LITERAL:
+        jj_consume_token(FLOATING_POINT_LITERAL);
+        break;
+      case STRING_LITERAL:
+        jj_consume_token(STRING_LITERAL);
+        break;
+      case NULL:
+        jj_consume_token(NULL);
+        break;
+      default:
+        jj_la1[25] = jj_gen;
+        jj_consume_token(-1);
+        throw new ParseException();
+      }
+    } finally {
+          if (jjtc000) {
+            jjtree.closeNodeScope(jjtn000, true);
+            jjtreeCloseNodeScope(jjtn000);
+          }
+    }
+  }
+
+  final private boolean jj_2_1(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_1(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(0, xla); }
+  }
+
+  final private boolean jj_2_2(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_2(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(1, xla); }
+  }
+
+  final private boolean jj_3_1() {
+    if (jj_3R_9()) return true;
+    return false;
+  }
+
+  final private boolean jj_3R_11() {
+    if (jj_3R_13()) return true;
+    Token xsp;
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_3R_14()) { jj_scanpos = xsp; break; }
+    }
+    return false;
+  }
+
+  final private boolean jj_3R_34() {
+    if (jj_3R_37()) return true;
+    return false;
+  }
+
+  final private boolean jj_3R_38() {
+    if (jj_3R_9()) return true;
+    return false;
+  }
+
+  final private boolean jj_3R_37() {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_38()) {
+    jj_scanpos = xsp;
+    if (jj_3R_39()) return true;
+    }
+    return false;
+  }
+
+  final private boolean jj_3R_10() {
+    if (jj_scan_token(IDENTIFIER)) return true;
+    if (jj_scan_token(COLON)) return true;
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_scan_token(47)) jj_scanpos = xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_12()) jj_scanpos = xsp;
+    return false;
+  }
+
+  final private boolean jj_3R_36() {
+    if (jj_scan_token(LBRACKET)) return true;
+    if (jj_3R_37()) return true;
+    if (jj_scan_token(RBRACKET)) return true;
+    return false;
+  }
+
+  final private boolean jj_3R_29() {
+    if (jj_3R_32()) return true;
+    return false;
+  }
+
+  final private boolean jj_3R_31() {
+    if (jj_scan_token(LPAREN)) return true;
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_34()) jj_scanpos = xsp;
+    if (jj_scan_token(RPAREN)) return true;
+    return false;
+  }
+
+  final private boolean jj_3R_32() {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_35()) {
+    jj_scanpos = xsp;
+    if (jj_3R_36()) return true;
+    }
+    return false;
+  }
+
+  final private boolean jj_3R_35() {
+    if (jj_scan_token(DOT)) return true;
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_scan_token(47)) jj_scanpos = xsp;
+    return false;
+  }
+
+  final private boolean jj_3R_28() {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_30()) {
+    jj_scanpos = xsp;
+    if (jj_3R_31()) {
+    jj_scanpos = xsp;
+    if (jj_3_2()) {
+    jj_scanpos = xsp;
+    if (jj_scan_token(47)) return true;
+    }
+    }
+    }
+    return false;
+  }
+
+  final private boolean jj_3R_30() {
+    if (jj_3R_33()) return true;
+    return false;
+  }
+
+  final private boolean jj_3R_27() {
+    if (jj_3R_28()) return true;
+    Token xsp;
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_3R_29()) { jj_scanpos = xsp; break; }
+    }
+    return false;
+  }
+
+  final private boolean jj_3R_26() {
+    if (jj_3R_27()) return true;
+    return false;
+  }
+
+  final private boolean jj_3R_23() {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_25()) {
+    jj_scanpos = xsp;
+    if (jj_3R_26()) return true;
+    }
+    return false;
+  }
+
+  final private boolean jj_3R_22() {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_scan_token(32)) {
+    jj_scanpos = xsp;
+    if (jj_scan_token(33)) return true;
+    }
+    if (jj_3R_21()) return true;
+    return false;
+  }
+
+  final private boolean jj_3R_25() {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_scan_token(39)) {
+    jj_scanpos = xsp;
+    if (jj_scan_token(40)) {
+    jj_scanpos = xsp;
+    if (jj_scan_token(33)) {
+    jj_scanpos = xsp;
+    if (jj_scan_token(45)) return true;
+    }
+    }
+    }
+    if (jj_3R_23()) return true;
+    return false;
+  }
+
+  final private boolean jj_3R_24() {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_scan_token(34)) {
+    jj_scanpos = xsp;
+    if (jj_scan_token(35)) {
+    jj_scanpos = xsp;
+    if (jj_scan_token(36)) {
+    jj_scanpos = xsp;
+    if (jj_scan_token(37)) {
+    jj_scanpos = xsp;
+    if (jj_scan_token(38)) return true;
+    }
+    }
+    }
+    }
+    if (jj_3R_23()) return true;
+    return false;
+  }
+
+  final private boolean jj_3R_9() {
+    if (jj_3R_11()) return true;
+    if (jj_scan_token(COND)) return true;
+    if (jj_3R_11()) return true;
+    if (jj_scan_token(COLON)) return true;
+    if (jj_3R_11()) return true;
+    return false;
+  }
+
+  final private boolean jj_3R_21() {
+    if (jj_3R_23()) return true;
+    Token xsp;
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_3R_24()) { jj_scanpos = xsp; break; }
+    }
+    return false;
+  }
+
+  final private boolean jj_3R_39() {
+    if (jj_3R_11()) return true;
+    return false;
+  }
+
+  final private boolean jj_3R_19() {
+    if (jj_3R_21()) return true;
+    Token xsp;
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_3R_22()) { jj_scanpos = xsp; break; }
+    }
+    return false;
+  }
+
+  final private boolean jj_3R_20() {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_scan_token(16)) {
+    jj_scanpos = xsp;
+    if (jj_scan_token(17)) {
+    jj_scanpos = xsp;
+    if (jj_scan_token(14)) {
+    jj_scanpos = xsp;
+    if (jj_scan_token(15)) {
+    jj_scanpos = xsp;
+    if (jj_scan_token(22)) {
+    jj_scanpos = xsp;
+    if (jj_scan_token(23)) {
+    jj_scanpos = xsp;
+    if (jj_scan_token(20)) {
+    jj_scanpos = xsp;
+    if (jj_scan_token(21)) return true;
+    }
+    }
+    }
+    }
+    }
+    }
+    }
+    if (jj_3R_19()) return true;
+    return false;
+  }
+
+  final private boolean jj_3R_16() {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_scan_token(41)) {
+    jj_scanpos = xsp;
+    if (jj_scan_token(42)) return true;
+    }
+    if (jj_3R_15()) return true;
+    return false;
+  }
+
+  final private boolean jj_3R_41() {
+    if (jj_scan_token(COMMA)) return true;
+    if (jj_3R_37()) return true;
+    return false;
+  }
+
+  final private boolean jj_3R_17() {
+    if (jj_3R_19()) return true;
+    Token xsp;
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_3R_20()) { jj_scanpos = xsp; break; }
+    }
+    return false;
+  }
+
+  final private boolean jj_3_2() {
+    if (jj_3R_10()) return true;
+    return false;
+  }
+
+  final private boolean jj_3R_18() {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_scan_token(18)) {
+    jj_scanpos = xsp;
+    if (jj_scan_token(19)) {
+    jj_scanpos = xsp;
+    if (jj_scan_token(24)) {
+    jj_scanpos = xsp;
+    if (jj_scan_token(25)) return true;
+    }
+    }
+    }
+    if (jj_3R_17()) return true;
+    return false;
+  }
+
+  final private boolean jj_3R_15() {
+    if (jj_3R_17()) return true;
+    Token xsp;
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_3R_18()) { jj_scanpos = xsp; break; }
+    }
+    return false;
+  }
+
+  final private boolean jj_3R_14() {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_scan_token(43)) {
+    jj_scanpos = xsp;
+    if (jj_scan_token(44)) return true;
+    }
+    if (jj_3R_13()) return true;
+    return false;
+  }
+
+  final private boolean jj_3R_40() {
+    if (jj_3R_37()) return true;
+    return false;
+  }
+
+  final private boolean jj_3R_13() {
+    if (jj_3R_15()) return true;
+    Token xsp;
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_3R_16()) { jj_scanpos = xsp; break; }
+    }
+    return false;
+  }
+
+  final private boolean jj_3R_33() {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_scan_token(10)) {
+    jj_scanpos = xsp;
+    if (jj_scan_token(11)) {
+    jj_scanpos = xsp;
+    if (jj_scan_token(5)) {
+    jj_scanpos = xsp;
+    if (jj_scan_token(6)) {
+    jj_scanpos = xsp;
+    if (jj_scan_token(8)) {
+    jj_scanpos = xsp;
+    if (jj_scan_token(12)) return true;
+    }
+    }
+    }
+    }
+    }
+    return false;
+  }
+
+  final private boolean jj_3R_12() {
+    if (jj_scan_token(LPAREN)) return true;
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_40()) jj_scanpos = xsp;
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_3R_41()) { jj_scanpos = xsp; break; }
+    }
+    if (jj_scan_token(RPAREN)) return true;
+    return false;
+  }
+
+  /** Generated Token Manager. */
+  public JSPELParserTokenManager token_source;
+  SimpleCharStream jj_input_stream;
+  /** Current token. */
+  public Token token;
+  /** Next token. */
+  public Token jj_nt;
+  private int jj_ntk;
+  private Token jj_scanpos, jj_lastpos;
+  private int jj_la;
+  private int jj_gen;
+  final private int[] jj_la1 = new int[26];
+  static private int[] jj_la1_0;
+  static private int[] jj_la1_1;
+  static {
+      jj_la1_init_0();
+      jj_la1_init_1();
+   }
+   private static void jj_la1_init_0() {
+      jj_la1_0 = new int[] {0x4001d60,0x0,0x0,0x0,0x0,0x30c0000,0x30c0000,0xf3c000,0xf3c000,0x0,0x0,0x0,0x0,0x0,0x4001d60,0x40002000,0x4001d60,0x4001d60,0x0,0x0,0x40002000,0x0,0x4001d60,0x10000000,0x4000000,0x1d60,};
+   }
+   private static void jj_la1_init_1() {
+      jj_la1_1 = new int[] {0xa182,0x1800,0x1800,0x600,0x600,0x0,0x0,0x0,0x0,0x3,0x3,0x7c,0x7c,0x2182,0xa182,0x0,0xa182,0x0,0x8000,0x8000,0x0,0x8000,0xa182,0x0,0x0,0x0,};
+   }
+  final private JJCalls[] jj_2_rtns = new JJCalls[2];
+  private boolean jj_rescan = false;
+  private int jj_gc = 0;
+
+  /** Constructor with InputStream. */
+  public JSPELParser(java.io.InputStream stream) {
+     this(stream, null);
+  }
+  /** Constructor with InputStream and supplied encoding */
+  public JSPELParser(java.io.InputStream stream, String encoding) {
+    try { jj_input_stream = new SimpleCharStream(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); }
+    token_source = new JSPELParserTokenManager(jj_input_stream);
+    token = new Token();
+    jj_ntk = -1;
+    jj_gen = 0;
+    for (int i = 0; i < 26; i++) jj_la1[i] = -1;
+    for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
+  }
+
+  /** Reinitialise. */
+  public void ReInit(java.io.InputStream stream) {
+     ReInit(stream, null);
+  }
+  /** Reinitialise. */
+  public void ReInit(java.io.InputStream stream, String encoding) {
+    try { jj_input_stream.ReInit(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); }
+    token_source.ReInit(jj_input_stream);
+    token = new Token();
+    jj_ntk = -1;
+    jjtree.reset();
+    jj_gen = 0;
+    for (int i = 0; i < 26; i++) jj_la1[i] = -1;
+    for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
+  }
+
+  /** Constructor. */
+  public JSPELParser(java.io.Reader stream) {
+    jj_input_stream = new SimpleCharStream(stream, 1, 1);
+    token_source = new JSPELParserTokenManager(jj_input_stream);
+    token = new Token();
+    jj_ntk = -1;
+    jj_gen = 0;
+    for (int i = 0; i < 26; i++) jj_la1[i] = -1;
+    for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
+  }
+
+  /** Reinitialise. */
+  public void ReInit(java.io.Reader stream) {
+    jj_input_stream.ReInit(stream, 1, 1);
+    token_source.ReInit(jj_input_stream);
+    token = new Token();
+    jj_ntk = -1;
+    jjtree.reset();
+    jj_gen = 0;
+    for (int i = 0; i < 26; i++) jj_la1[i] = -1;
+    for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
+  }
+
+  /** Constructor with generated Token Manager. */
+  public JSPELParser(JSPELParserTokenManager tm) {
+    token_source = tm;
+    token = new Token();
+    jj_ntk = -1;
+    jj_gen = 0;
+    for (int i = 0; i < 26; i++) jj_la1[i] = -1;
+    for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
+  }
+
+  /** Reinitialise. */
+  public void ReInit(JSPELParserTokenManager tm) {
+    token_source = tm;
+    token = new Token();
+    jj_ntk = -1;
+    jjtree.reset();
+    jj_gen = 0;
+    for (int i = 0; i < 26; i++) jj_la1[i] = -1;
+    for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
+  }
+
+  final private Token jj_consume_token(int kind) throws ParseException {
+    Token oldToken;
+    if ((oldToken = token).next != null) token = token.next;
+    else token = token.next = token_source.getNextToken();
+    jj_ntk = -1;
+    if (token.kind == kind) {
+      jj_gen++;
+      if (++jj_gc > 100) {
+        jj_gc = 0;
+        for (int i = 0; i < jj_2_rtns.length; i++) {
+          JJCalls c = jj_2_rtns[i];
+          while (c != null) {
+            if (c.gen < jj_gen) c.first = null;
+            c = c.next;
+          }
+        }
+      }
+      return token;
+    }
+    token = oldToken;
+    jj_kind = kind;
+    throw generateParseException();
+  }
+
+  static private final class LookaheadSuccess extends java.lang.Error { 
+    private static final long serialVersionUID = 1L; 
+  }
+  final private LookaheadSuccess jj_ls = new LookaheadSuccess();
+  final private boolean jj_scan_token(int kind) {
+    if (jj_scanpos == jj_lastpos) {
+      jj_la--;
+      if (jj_scanpos.next == null) {
+        jj_lastpos = jj_scanpos = jj_scanpos.next = token_source.getNextToken();
+      } else {
+        jj_lastpos = jj_scanpos = jj_scanpos.next;
+      }
+    } else {
+      jj_scanpos = jj_scanpos.next;
+    }
+    if (jj_rescan) {
+      int i = 0; Token tok = token;
+      while (tok != null && tok != jj_scanpos) { i++; tok = tok.next; }
+      if (tok != null) jj_add_error_token(kind, i);
+    }
+    if (jj_scanpos.kind != kind) return true;
+    if (jj_la == 0 && jj_scanpos == jj_lastpos) throw jj_ls;
+    return false;
+  }
+
+
+/** Get the next Token. */
+  final public Token getNextToken() {
+    if (token.next != null) token = token.next;
+    else token = token.next = token_source.getNextToken();
+    jj_ntk = -1;
+    jj_gen++;
+    return token;
+  }
+
+/** Get the specific Token. */
+  final public Token getToken(int index) {
+    Token t = token;
+    for (int i = 0; i < index; i++) {
+      if (t.next != null) t = t.next;
+      else t = t.next = token_source.getNextToken();
+    }
+    return t;
+  }
+
+  final private int jj_ntk() {
+    if ((jj_nt=token.next) == null)
+      return (jj_ntk = (token.next=token_source.getNextToken()).kind);
+    else
+      return (jj_ntk = jj_nt.kind);
+  }
+
+  private java.util.List jj_expentries = new java.util.ArrayList();
+  private int[] jj_expentry;
+  private int jj_kind = -1;
+  private int[] jj_lasttokens = new int[100];
+  private int jj_endpos;
+
+  private void jj_add_error_token(int kind, int pos) {
+    if (pos >= 100) return;
+    if (pos == jj_endpos + 1) {
+      jj_lasttokens[jj_endpos++] = kind;
+    } else if (jj_endpos != 0) {
+      jj_expentry = new int[jj_endpos];
+      for (int i = 0; i < jj_endpos; i++) {
+        jj_expentry[i] = jj_lasttokens[i];
+      }
+      jj_entries_loop: for (java.util.Iterator it = jj_expentries.iterator(); it.hasNext();) {
+        int[] oldentry = (int[])(it.next());
+        if (oldentry.length == jj_expentry.length) {
+          for (int i = 0; i < jj_expentry.length; i++) {
+            if (oldentry[i] != jj_expentry[i]) {
+              continue jj_entries_loop;
+            }
+          }
+          jj_expentries.add(jj_expentry);
+          break jj_entries_loop;
+        }
+      }
+      if (pos != 0) jj_lasttokens[(jj_endpos = pos) - 1] = kind;
+    }
+  }
+
+  /** Generate ParseException. */
+  public ParseException generateParseException() {
+    jj_expentries.clear();
+    boolean[] la1tokens = new boolean[51];
+    if (jj_kind >= 0) {
+      la1tokens[jj_kind] = true;
+      jj_kind = -1;
+    }
+    for (int i = 0; i < 26; i++) {
+      if (jj_la1[i] == jj_gen) {
+        for (int j = 0; j < 32; j++) {
+          if ((jj_la1_0[i] & (1<<j)) != 0) {
+            la1tokens[j] = true;
+          }
+          if ((jj_la1_1[i] & (1<<j)) != 0) {
+            la1tokens[32+j] = true;
+          }
+        }
+      }
+    }
+    for (int i = 0; i < 51; i++) {
+      if (la1tokens[i]) {
+        jj_expentry = new int[1];
+        jj_expentry[0] = i;
+        jj_expentries.add(jj_expentry);
+      }
+    }
+    jj_endpos = 0;
+    jj_rescan_token();
+    jj_add_error_token(0, 0);
+    int[][] exptokseq = new int[jj_expentries.size()][];
+    for (int i = 0; i < jj_expentries.size(); i++) {
+      exptokseq[i] = (int[])jj_expentries.get(i);
+    }
+    return new ParseException(token, exptokseq, tokenImage);
+  }
+
+  /** Enable tracing. */
+  final public void enable_tracing() {
+  }
+
+  /** Disable tracing. */
+  final public void disable_tracing() {
+  }
+
+  final private void jj_rescan_token() {
+    jj_rescan = true;
+    for (int i = 0; i < 2; i++) {
+    try {
+      JJCalls p = jj_2_rtns[i];
+      do {
+        if (p.gen > jj_gen) {
+          jj_la = p.arg; jj_lastpos = jj_scanpos = p.first;
+          switch (i) {
+            case 0: jj_3_1(); break;
+            case 1: jj_3_2(); break;
+          }
+        }
+        p = p.next;
+      } while (p != null);
+      } catch(LookaheadSuccess ls) { }
+    }
+    jj_rescan = false;
+  }
+
+  final private void jj_save(int index, int xla) {
+    JJCalls p = jj_2_rtns[index];
+    while (p.gen > jj_gen) {
+      if (p.next == null) { p = p.next = new JJCalls(); break; }
+      p = p.next;
+    }
+    p.gen = jj_gen + xla - jj_la; p.first = token; p.arg = xla;
+  }
+
+  static final class JJCalls {
+    int gen;
+    Token first;
+    int arg;
+    JJCalls next;
+  }
+
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/JSPELParserConstants.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/JSPELParserConstants.java
new file mode 100644
index 0000000..1f4e3ad
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/JSPELParserConstants.java
@@ -0,0 +1,121 @@
+/*******************************************************************************
+ * Copyright (c) 2005 BEA Systems 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:
+ *     BEA Systems - initial implementation
+ *     
+ *******************************************************************************/
+/* Generated By:JJTree&JavaCC: Do not edit this line. JSPELParserConstants.java */
+package org.eclipse.jst.jsp.core.internal.java.jspel;
+
+public interface JSPELParserConstants {
+
+  int EOF = 0;
+  int INTEGER_LITERAL = 5;
+  int FLOATING_POINT_LITERAL = 6;
+  int EXPONENT = 7;
+  int STRING_LITERAL = 8;
+  int BADLY_ESCAPED_STRING_LITERAL = 9;
+  int TRUE = 10;
+  int FALSE = 11;
+  int NULL = 12;
+  int DOT = 13;
+  int GT1 = 14;
+  int GT2 = 15;
+  int LT1 = 16;
+  int LT2 = 17;
+  int EQ1 = 18;
+  int EQ2 = 19;
+  int LE1 = 20;
+  int LE2 = 21;
+  int GE1 = 22;
+  int GE2 = 23;
+  int NEQ1 = 24;
+  int NEQ2 = 25;
+  int LPAREN = 26;
+  int RPAREN = 27;
+  int COMMA = 28;
+  int COLON = 29;
+  int LBRACKET = 30;
+  int RBRACKET = 31;
+  int PLUS = 32;
+  int MINUS = 33;
+  int MULTIPLY = 34;
+  int DIVIDE1 = 35;
+  int DIVIDE2 = 36;
+  int MODULUS1 = 37;
+  int MODULUS2 = 38;
+  int NOT1 = 39;
+  int NOT2 = 40;
+  int AND1 = 41;
+  int AND2 = 42;
+  int OR1 = 43;
+  int OR2 = 44;
+  int EMPTY = 45;
+  int COND = 46;
+  int IDENTIFIER = 47;
+  int IMPL_OBJ_START = 48;
+  int LETTER = 49;
+  int DIGIT = 50;
+
+  int DEFAULT = 0;
+
+  String[] tokenImage = {
+    "<EOF>",
+    "\" \"",
+    "\"\\t\"",
+    "\"\\n\"",
+    "\"\\r\"",
+    "<INTEGER_LITERAL>",
+    "<FLOATING_POINT_LITERAL>",
+    "<EXPONENT>",
+    "<STRING_LITERAL>",
+    "<BADLY_ESCAPED_STRING_LITERAL>",
+    "\"true\"",
+    "\"false\"",
+    "\"null\"",
+    "\".\"",
+    "\">\"",
+    "\"gt\"",
+    "\"<\"",
+    "\"lt\"",
+    "\"==\"",
+    "\"eq\"",
+    "\"<=\"",
+    "\"le\"",
+    "\">=\"",
+    "\"ge\"",
+    "\"!=\"",
+    "\"ne\"",
+    "\"(\"",
+    "\")\"",
+    "\",\"",
+    "\":\"",
+    "\"[\"",
+    "\"]\"",
+    "\"+\"",
+    "\"-\"",
+    "\"*\"",
+    "\"/\"",
+    "\"div\"",
+    "\"%\"",
+    "\"mod\"",
+    "\"not\"",
+    "\"!\"",
+    "\"and\"",
+    "\"&&\"",
+    "\"or\"",
+    "\"||\"",
+    "\"empty\"",
+    "\"?\"",
+    "<IDENTIFIER>",
+    "\"#\"",
+    "<LETTER>",
+    "<DIGIT>",
+  };
+
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/JSPELParserTokenManager.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/JSPELParserTokenManager.java
new file mode 100644
index 0000000..4c727ea
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/JSPELParserTokenManager.java
@@ -0,0 +1,877 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2010 BEA Systems 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:
+ *     BEA Systems - initial implementation
+ *     IBM Corporation - Bug 318281 - EL validation error for quote escaping
+ *
+ *******************************************************************************/
+/* Generated By:JJTree&JavaCC: Do not edit this line. JSPELParserTokenManager.java */
+package org.eclipse.jst.jsp.core.internal.java.jspel;
+
+/** Token Manager. */
+public class JSPELParserTokenManager implements JSPELParserConstants
+{
+
+  /** Debug output. */
+  public  java.io.PrintStream debugStream = System.out;
+  /** Set debug output. */
+  public  void setDebugStream(java.io.PrintStream ds) { debugStream = ds; }
+private final int jjStopStringLiteralDfa_0(int pos, long active0)
+{
+   switch (pos)
+   {
+      case 0:
+         if ((active0 & 0x2ad002aa9c00L) != 0L)
+         {
+            jjmatchedKind = 47;
+            return 6;
+         }
+         if ((active0 & 0x2000L) != 0L)
+            return 1;
+         return -1;
+      case 1:
+         if ((active0 & 0x22d000001c00L) != 0L)
+         {
+            jjmatchedKind = 47;
+            jjmatchedPos = 1;
+            return 6;
+         }
+         if ((active0 & 0x80002aa8000L) != 0L)
+            return 6;
+         return -1;
+      case 2:
+         if ((active0 & 0x200000001c00L) != 0L)
+         {
+            jjmatchedKind = 47;
+            jjmatchedPos = 2;
+            return 6;
+         }
+         if ((active0 & 0x2d000000000L) != 0L)
+            return 6;
+         return -1;
+      case 3:
+         if ((active0 & 0x200000000800L) != 0L)
+         {
+            jjmatchedKind = 47;
+            jjmatchedPos = 3;
+            return 6;
+         }
+         if ((active0 & 0x1400L) != 0L)
+            return 6;
+         return -1;
+      default :
+         return -1;
+   }
+}
+private final int jjStartNfa_0(int pos, long active0)
+{
+   return jjMoveNfa_0(jjStopStringLiteralDfa_0(pos, active0), pos + 1);
+}
+private int jjStopAtPos(int pos, int kind)
+{
+   jjmatchedKind = kind;
+   jjmatchedPos = pos;
+   return pos + 1;
+}
+private int jjMoveStringLiteralDfa0_0()
+{
+   switch(curChar)
+   {
+      case 33:
+         jjmatchedKind = 40;
+         return jjMoveStringLiteralDfa1_0(0x1000000L);
+      case 37:
+         return jjStopAtPos(0, 37);
+      case 38:
+         return jjMoveStringLiteralDfa1_0(0x40000000000L);
+      case 40:
+         return jjStopAtPos(0, 26);
+      case 41:
+         return jjStopAtPos(0, 27);
+      case 42:
+         return jjStopAtPos(0, 34);
+      case 43:
+         return jjStopAtPos(0, 32);
+      case 44:
+         return jjStopAtPos(0, 28);
+      case 45:
+         return jjStopAtPos(0, 33);
+      case 46:
+         return jjStartNfaWithStates_0(0, 13, 1);
+      case 47:
+         return jjStopAtPos(0, 35);
+      case 58:
+         return jjStopAtPos(0, 29);
+      case 60:
+         jjmatchedKind = 16;
+         return jjMoveStringLiteralDfa1_0(0x100000L);
+      case 61:
+         return jjMoveStringLiteralDfa1_0(0x40000L);
+      case 62:
+         jjmatchedKind = 14;
+         return jjMoveStringLiteralDfa1_0(0x400000L);
+      case 63:
+         return jjStopAtPos(0, 46);
+      case 91:
+         return jjStopAtPos(0, 30);
+      case 93:
+         return jjStopAtPos(0, 31);
+      case 97:
+         return jjMoveStringLiteralDfa1_0(0x20000000000L);
+      case 100:
+         return jjMoveStringLiteralDfa1_0(0x1000000000L);
+      case 101:
+         return jjMoveStringLiteralDfa1_0(0x200000080000L);
+      case 102:
+         return jjMoveStringLiteralDfa1_0(0x800L);
+      case 103:
+         return jjMoveStringLiteralDfa1_0(0x808000L);
+      case 108:
+         return jjMoveStringLiteralDfa1_0(0x220000L);
+      case 109:
+         return jjMoveStringLiteralDfa1_0(0x4000000000L);
+      case 110:
+         return jjMoveStringLiteralDfa1_0(0x8002001000L);
+      case 111:
+         return jjMoveStringLiteralDfa1_0(0x80000000000L);
+      case 116:
+         return jjMoveStringLiteralDfa1_0(0x400L);
+      case 124:
+         return jjMoveStringLiteralDfa1_0(0x100000000000L);
+      default :
+         return jjMoveNfa_0(0, 0);
+   }
+}
+private int jjMoveStringLiteralDfa1_0(long active0)
+{
+   try { curChar = input_stream.readChar(); }
+   catch(java.io.IOException e) {
+      jjStopStringLiteralDfa_0(0, active0);
+      return 1;
+   }
+   switch(curChar)
+   {
+      case 38:
+         if ((active0 & 0x40000000000L) != 0L)
+            return jjStopAtPos(1, 42);
+         break;
+      case 61:
+         if ((active0 & 0x40000L) != 0L)
+            return jjStopAtPos(1, 18);
+         else if ((active0 & 0x100000L) != 0L)
+            return jjStopAtPos(1, 20);
+         else if ((active0 & 0x400000L) != 0L)
+            return jjStopAtPos(1, 22);
+         else if ((active0 & 0x1000000L) != 0L)
+            return jjStopAtPos(1, 24);
+         break;
+      case 97:
+         return jjMoveStringLiteralDfa2_0(active0, 0x800L);
+      case 101:
+         if ((active0 & 0x200000L) != 0L)
+            return jjStartNfaWithStates_0(1, 21, 6);
+         else if ((active0 & 0x800000L) != 0L)
+            return jjStartNfaWithStates_0(1, 23, 6);
+         else if ((active0 & 0x2000000L) != 0L)
+            return jjStartNfaWithStates_0(1, 25, 6);
+         break;
+      case 105:
+         return jjMoveStringLiteralDfa2_0(active0, 0x1000000000L);
+      case 109:
+         return jjMoveStringLiteralDfa2_0(active0, 0x200000000000L);
+      case 110:
+         return jjMoveStringLiteralDfa2_0(active0, 0x20000000000L);
+      case 111:
+         return jjMoveStringLiteralDfa2_0(active0, 0xc000000000L);
+      case 113:
+         if ((active0 & 0x80000L) != 0L)
+            return jjStartNfaWithStates_0(1, 19, 6);
+         break;
+      case 114:
+         if ((active0 & 0x80000000000L) != 0L)
+            return jjStartNfaWithStates_0(1, 43, 6);
+         return jjMoveStringLiteralDfa2_0(active0, 0x400L);
+      case 116:
+         if ((active0 & 0x8000L) != 0L)
+            return jjStartNfaWithStates_0(1, 15, 6);
+         else if ((active0 & 0x20000L) != 0L)
+            return jjStartNfaWithStates_0(1, 17, 6);
+         break;
+      case 117:
+         return jjMoveStringLiteralDfa2_0(active0, 0x1000L);
+      case 124:
+         if ((active0 & 0x100000000000L) != 0L)
+            return jjStopAtPos(1, 44);
+         break;
+      default :
+         break;
+   }
+   return jjStartNfa_0(0, active0);
+}
+private int jjMoveStringLiteralDfa2_0(long old0, long active0)
+{
+   if (((active0 &= old0)) == 0L)
+      return jjStartNfa_0(0, old0);
+   try { curChar = input_stream.readChar(); }
+   catch(java.io.IOException e) {
+      jjStopStringLiteralDfa_0(1, active0);
+      return 2;
+   }
+   switch(curChar)
+   {
+      case 100:
+         if ((active0 & 0x4000000000L) != 0L)
+            return jjStartNfaWithStates_0(2, 38, 6);
+         else if ((active0 & 0x20000000000L) != 0L)
+            return jjStartNfaWithStates_0(2, 41, 6);
+         break;
+      case 108:
+         return jjMoveStringLiteralDfa3_0(active0, 0x1800L);
+      case 112:
+         return jjMoveStringLiteralDfa3_0(active0, 0x200000000000L);
+      case 116:
+         if ((active0 & 0x8000000000L) != 0L)
+            return jjStartNfaWithStates_0(2, 39, 6);
+         break;
+      case 117:
+         return jjMoveStringLiteralDfa3_0(active0, 0x400L);
+      case 118:
+         if ((active0 & 0x1000000000L) != 0L)
+            return jjStartNfaWithStates_0(2, 36, 6);
+         break;
+      default :
+         break;
+   }
+   return jjStartNfa_0(1, active0);
+}
+private int jjMoveStringLiteralDfa3_0(long old0, long active0)
+{
+   if (((active0 &= old0)) == 0L)
+      return jjStartNfa_0(1, old0);
+   try { curChar = input_stream.readChar(); }
+   catch(java.io.IOException e) {
+      jjStopStringLiteralDfa_0(2, active0);
+      return 3;
+   }
+   switch(curChar)
+   {
+      case 101:
+         if ((active0 & 0x400L) != 0L)
+            return jjStartNfaWithStates_0(3, 10, 6);
+         break;
+      case 108:
+         if ((active0 & 0x1000L) != 0L)
+            return jjStartNfaWithStates_0(3, 12, 6);
+         break;
+      case 115:
+         return jjMoveStringLiteralDfa4_0(active0, 0x800L);
+      case 116:
+         return jjMoveStringLiteralDfa4_0(active0, 0x200000000000L);
+      default :
+         break;
+   }
+   return jjStartNfa_0(2, active0);
+}
+private int jjMoveStringLiteralDfa4_0(long old0, long active0)
+{
+   if (((active0 &= old0)) == 0L)
+      return jjStartNfa_0(2, old0);
+   try { curChar = input_stream.readChar(); }
+   catch(java.io.IOException e) {
+      jjStopStringLiteralDfa_0(3, active0);
+      return 4;
+   }
+   switch(curChar)
+   {
+      case 101:
+         if ((active0 & 0x800L) != 0L)
+            return jjStartNfaWithStates_0(4, 11, 6);
+         break;
+      case 121:
+         if ((active0 & 0x200000000000L) != 0L)
+            return jjStartNfaWithStates_0(4, 45, 6);
+         break;
+      default :
+         break;
+   }
+   return jjStartNfa_0(3, active0);
+}
+private int jjStartNfaWithStates_0(int pos, int kind, int state)
+{
+   jjmatchedKind = kind;
+   jjmatchedPos = pos;
+   try { curChar = input_stream.readChar(); }
+   catch(java.io.IOException e) { return pos + 1; }
+   return jjMoveNfa_0(state, pos + 1);
+}
+static final long[] jjbitVec0 = {
+   0x1ff00000fffffffeL, 0xffffffffffffc000L, 0xffffffffL, 0x600000000000000L
+};
+static final long[] jjbitVec2 = {
+   0x0L, 0x0L, 0x0L, 0xff7fffffff7fffffL
+};
+static final long[] jjbitVec3 = {
+   0x0L, 0xffffffffffffffffL, 0xffffffffffffffffL, 0xffffffffffffffffL
+};
+static final long[] jjbitVec4 = {
+   0xffffffffffffffffL, 0xffffffffffffffffL, 0xffffL, 0x0L
+};
+static final long[] jjbitVec5 = {
+   0xffffffffffffffffL, 0xffffffffffffffffL, 0x0L, 0x0L
+};
+static final long[] jjbitVec6 = {
+   0x3fffffffffffL, 0x0L, 0x0L, 0x0L
+};
+static final long[] jjbitVec7 = {
+   0xfffffffffffffffeL, 0xffffffffffffffffL, 0xffffffffffffffffL, 0xffffffffffffffffL
+};
+static final long[] jjbitVec8 = {
+   0x0L, 0x0L, 0xffffffffffffffffL, 0xffffffffffffffffL
+};
+private int jjMoveNfa_0(int startState, int curPos)
+{
+   int startsAt = 0;
+   jjnewStateCnt = 35;
+   int i = 1;
+   jjstateSet[0] = startState;
+   int kind = 0x7fffffff;
+   for (;;)
+   {
+      if (++jjround == 0x7fffffff)
+         ReInitRounds();
+      if (curChar < 64)
+      {
+         long l = 1L << curChar;
+         do
+         {
+            switch(jjstateSet[--i])
+            {
+               case 0:
+                  if ((0x3ff000000000000L & l) != 0L)
+                  {
+                     if (kind > 5)
+                        kind = 5;
+                     jjCheckNAddStates(0, 4);
+                  }
+                  else if ((0x1800000000L & l) != 0L)
+                  {
+                     if (kind > 47)
+                        kind = 47;
+                     jjCheckNAdd(6);
+                  }
+                  else if (curChar == 39)
+                     jjCheckNAddStates(5, 9);
+                  else if (curChar == 34)
+                     jjCheckNAddStates(10, 14);
+                  else if (curChar == 46)
+                     jjCheckNAdd(1);
+                  break;
+               case 1:
+                  if ((0x3ff000000000000L & l) == 0L)
+                     break;
+                  if (kind > 6)
+                     kind = 6;
+                  jjCheckNAddTwoStates(1, 2);
+                  break;
+               case 3:
+                  if ((0x280000000000L & l) != 0L)
+                     jjCheckNAdd(4);
+                  break;
+               case 4:
+                  if ((0x3ff000000000000L & l) == 0L)
+                     break;
+                  if (kind > 6)
+                     kind = 6;
+                  jjCheckNAdd(4);
+                  break;
+               case 5:
+                  if ((0x1800000000L & l) == 0L)
+                     break;
+                  if (kind > 47)
+                     kind = 47;
+                  jjCheckNAdd(6);
+                  break;
+               case 6:
+                  if ((0x3ff001000000000L & l) == 0L)
+                     break;
+                  if (kind > 47)
+                     kind = 47;
+                  jjCheckNAdd(6);
+                  break;
+               case 7:
+                  if ((0x3ff000000000000L & l) == 0L)
+                     break;
+                  if (kind > 5)
+                     kind = 5;
+                  jjCheckNAddStates(0, 4);
+                  break;
+               case 8:
+                  if ((0x3ff000000000000L & l) == 0L)
+                     break;
+                  if (kind > 5)
+                     kind = 5;
+                  jjCheckNAdd(8);
+                  break;
+               case 9:
+                  if ((0x3ff000000000000L & l) != 0L)
+                     jjCheckNAddTwoStates(9, 10);
+                  break;
+               case 10:
+                  if (curChar != 46)
+                     break;
+                  if (kind > 6)
+                     kind = 6;
+                  jjCheckNAddTwoStates(11, 12);
+                  break;
+               case 11:
+                  if ((0x3ff000000000000L & l) == 0L)
+                     break;
+                  if (kind > 6)
+                     kind = 6;
+                  jjCheckNAddTwoStates(11, 12);
+                  break;
+               case 13:
+                  if ((0x280000000000L & l) != 0L)
+                     jjCheckNAdd(14);
+                  break;
+               case 14:
+                  if ((0x3ff000000000000L & l) == 0L)
+                     break;
+                  if (kind > 6)
+                     kind = 6;
+                  jjCheckNAdd(14);
+                  break;
+               case 15:
+                  if ((0x3ff000000000000L & l) != 0L)
+                     jjCheckNAddTwoStates(15, 16);
+                  break;
+               case 17:
+                  if ((0x280000000000L & l) != 0L)
+                     jjCheckNAdd(18);
+                  break;
+               case 18:
+                  if ((0x3ff000000000000L & l) == 0L)
+                     break;
+                  if (kind > 6)
+                     kind = 6;
+                  jjCheckNAdd(18);
+                  break;
+               case 19:
+                  if (curChar == 34)
+                     jjCheckNAddStates(10, 14);
+                  break;
+               case 20:
+                  if ((0xfffffffbffffffffL & l) != 0L)
+                     jjCheckNAddStates(15, 17);
+                  break;
+               case 22:
+                  if ((0x8400000000L & l) != 0L)
+                     jjCheckNAddStates(15, 17);
+                  break;
+               case 23:
+                  if (curChar == 34 && kind > 8)
+                     kind = 8;
+                  break;
+               case 24:
+                  if ((0xfffffffbffffffffL & l) != 0L)
+                     jjCheckNAddTwoStates(24, 25);
+                  break;
+               case 26:
+                  if ((0xfffffffbffffffffL & l) != 0L && kind > 9)
+                     kind = 9;
+                  break;
+               case 27:
+                  if (curChar == 39)
+                     jjCheckNAddStates(5, 9);
+                  break;
+               case 28:
+                  if ((0xffffff7fffffffffL & l) != 0L)
+                     jjCheckNAddStates(18, 20);
+                  break;
+               case 30:
+                  if ((0x8400000000L & l) != 0L)
+                     jjCheckNAddStates(18, 20);
+                  break;
+               case 31:
+                  if (curChar == 39 && kind > 8)
+                     kind = 8;
+                  break;
+               case 32:
+                  if ((0xffffff7fffffffffL & l) != 0L)
+                     jjCheckNAddTwoStates(32, 33);
+                  break;
+               case 34:
+                  if ((0xffffff7fffffffffL & l) != 0L && kind > 9)
+                     kind = 9;
+                  break;
+               default : break;
+            }
+         } while(i != startsAt);
+      }
+      else if (curChar < 128)
+      {
+         long l = 1L << (curChar & 077);
+         do
+         {
+            switch(jjstateSet[--i])
+            {
+               case 0:
+               case 6:
+                  if ((0x7fffffe87fffffeL & l) == 0L)
+                     break;
+                  if (kind > 47)
+                     kind = 47;
+                  jjCheckNAdd(6);
+                  break;
+               case 2:
+                  if ((0x2000000020L & l) != 0L)
+                     jjAddStates(21, 22);
+                  break;
+               case 12:
+                  if ((0x2000000020L & l) != 0L)
+                     jjAddStates(23, 24);
+                  break;
+               case 16:
+                  if ((0x2000000020L & l) != 0L)
+                     jjAddStates(25, 26);
+                  break;
+               case 20:
+                  if ((0xffffffffefffffffL & l) != 0L)
+                     jjCheckNAddStates(15, 17);
+                  break;
+               case 21:
+                  if (curChar == 92)
+                     jjstateSet[jjnewStateCnt++] = 22;
+                  break;
+               case 22:
+                  if (curChar == 92)
+                     jjCheckNAddStates(15, 17);
+                  break;
+               case 24:
+                  if ((0xffffffffefffffffL & l) != 0L)
+                     jjAddStates(27, 28);
+                  break;
+               case 25:
+                  if (curChar == 92)
+                     jjstateSet[jjnewStateCnt++] = 26;
+                  break;
+               case 26:
+               case 34:
+                  if ((0xffffffffefffffffL & l) != 0L && kind > 9)
+                     kind = 9;
+                  break;
+               case 28:
+                  if ((0xffffffffefffffffL & l) != 0L)
+                     jjCheckNAddStates(18, 20);
+                  break;
+               case 29:
+                  if (curChar == 92)
+                     jjstateSet[jjnewStateCnt++] = 30;
+                  break;
+               case 30:
+                  if (curChar == 92)
+                     jjCheckNAddStates(18, 20);
+                  break;
+               case 32:
+                  if ((0xffffffffefffffffL & l) != 0L)
+                     jjAddStates(29, 30);
+                  break;
+               case 33:
+                  if (curChar == 92)
+                     jjstateSet[jjnewStateCnt++] = 34;
+                  break;
+               default : break;
+            }
+         } while(i != startsAt);
+      }
+      else
+      {
+         int hiByte = curChar >> 8;
+         int i1 = hiByte >> 6;
+         long l1 = 1L << (hiByte & 077);
+         int i2 = (curChar & 0xff) >> 6;
+         long l2 = 1L << (curChar & 077);
+         do
+         {
+            switch(jjstateSet[--i])
+            {
+               case 0:
+               case 6:
+                  if (!jjCanMove_0(hiByte, i1, i2, l1, l2))
+                     break;
+                  if (kind > 47)
+                     kind = 47;
+                  jjCheckNAdd(6);
+                  break;
+               case 20:
+                  if (jjCanMove_1(hiByte, i1, i2, l1, l2))
+                     jjAddStates(15, 17);
+                  break;
+               case 24:
+                  if (jjCanMove_1(hiByte, i1, i2, l1, l2))
+                     jjAddStates(27, 28);
+                  break;
+               case 26:
+               case 34:
+                  if (jjCanMove_1(hiByte, i1, i2, l1, l2) && kind > 9)
+                     kind = 9;
+                  break;
+               case 28:
+                  if (jjCanMove_1(hiByte, i1, i2, l1, l2))
+                     jjAddStates(18, 20);
+                  break;
+               case 32:
+                  if (jjCanMove_1(hiByte, i1, i2, l1, l2))
+                     jjAddStates(29, 30);
+                  break;
+               default : break;
+            }
+         } while(i != startsAt);
+      }
+      if (kind != 0x7fffffff)
+      {
+         jjmatchedKind = kind;
+         jjmatchedPos = curPos;
+         kind = 0x7fffffff;
+      }
+      ++curPos;
+      if ((i = jjnewStateCnt) == (startsAt = 35 - (jjnewStateCnt = startsAt)))
+         return curPos;
+      try { curChar = input_stream.readChar(); }
+      catch(java.io.IOException e) { return curPos; }
+   }
+}
+static final int[] jjnextStates = {
+   8, 9, 10, 15, 16, 28, 29, 31, 32, 33, 20, 21, 23, 24, 25, 20, 
+   21, 23, 28, 29, 31, 3, 4, 13, 14, 17, 18, 24, 25, 32, 33, 
+};
+private static final boolean jjCanMove_0(int hiByte, int i1, int i2, long l1, long l2)
+{
+   switch(hiByte)
+   {
+      case 0:
+         return ((jjbitVec2[i2] & l2) != 0L);
+      case 48:
+         return ((jjbitVec3[i2] & l2) != 0L);
+      case 49:
+         return ((jjbitVec4[i2] & l2) != 0L);
+      case 51:
+         return ((jjbitVec5[i2] & l2) != 0L);
+      case 61:
+         return ((jjbitVec6[i2] & l2) != 0L);
+      default :
+         if ((jjbitVec0[i1] & l1) != 0L)
+            return true;
+         return false;
+   }
+}
+private static final boolean jjCanMove_1(int hiByte, int i1, int i2, long l1, long l2)
+{
+   switch(hiByte)
+   {
+      case 0:
+         return ((jjbitVec8[i2] & l2) != 0L);
+      default :
+         if ((jjbitVec7[i1] & l1) != 0L)
+            return true;
+         return false;
+   }
+}
+
+/** Token literal values. */
+public static final String[] jjstrLiteralImages = {
+"", null, null, null, null, null, null, null, null, null, "\164\162\165\145", 
+"\146\141\154\163\145", "\156\165\154\154", "\56", "\76", "\147\164", "\74", "\154\164", "\75\75", 
+"\145\161", "\74\75", "\154\145", "\76\75", "\147\145", "\41\75", "\156\145", "\50", 
+"\51", "\54", "\72", "\133", "\135", "\53", "\55", "\52", "\57", "\144\151\166", 
+"\45", "\155\157\144", "\156\157\164", "\41", "\141\156\144", "\46\46", "\157\162", 
+"\174\174", "\145\155\160\164\171", "\77", null, null, null, null, };
+
+/** Lexer state names. */
+public static final String[] lexStateNames = {
+   "DEFAULT",
+};
+static final long[] jjtoToken = {
+   0xffffffffff61L, 
+};
+static final long[] jjtoSkip = {
+   0x1eL, 
+};
+protected SimpleCharStream input_stream;
+private final int[] jjrounds = new int[35];
+private final int[] jjstateSet = new int[70];
+protected char curChar;
+/** Constructor. */
+public JSPELParserTokenManager(SimpleCharStream stream){
+   if (SimpleCharStream.staticFlag)
+      throw new Error("ERROR: Cannot use a static CharStream class with a non-static lexical analyzer.");
+   input_stream = stream;
+}
+
+/** Constructor. */
+public JSPELParserTokenManager(SimpleCharStream stream, int lexState){
+   this(stream);
+   SwitchTo(lexState);
+}
+
+/** Reinitialise parser. */
+public void ReInit(SimpleCharStream stream)
+{
+   jjmatchedPos = jjnewStateCnt = 0;
+   curLexState = defaultLexState;
+   input_stream = stream;
+   ReInitRounds();
+}
+private void ReInitRounds()
+{
+   int i;
+   jjround = 0x80000001;
+   for (i = 35; i-- > 0;)
+      jjrounds[i] = 0x80000000;
+}
+
+/** Reinitialise parser. */
+public void ReInit(SimpleCharStream stream, int lexState)
+{
+   ReInit(stream);
+   SwitchTo(lexState);
+}
+
+/** Switch to specified lex state. */
+public void SwitchTo(int lexState)
+{
+   if (lexState >= 1 || lexState < 0)
+      throw new TokenMgrError("Error: Ignoring invalid lexical state : " + lexState + ". State unchanged.", TokenMgrError.INVALID_LEXICAL_STATE);
+   else
+      curLexState = lexState;
+}
+
+protected Token jjFillToken()
+{
+   final Token t;
+   final String curTokenImage;
+   final int beginLine;
+   final int endLine;
+   final int beginColumn;
+   final int endColumn;
+   String im = jjstrLiteralImages[jjmatchedKind];
+   curTokenImage = (im == null) ? input_stream.GetImage() : im;
+   beginLine = input_stream.getBeginLine();
+   beginColumn = input_stream.getBeginColumn();
+   endLine = input_stream.getEndLine();
+   endColumn = input_stream.getEndColumn();
+   t = Token.newToken(jjmatchedKind, curTokenImage);
+
+   t.beginLine = beginLine;
+   t.endLine = endLine;
+   t.beginColumn = beginColumn;
+   t.endColumn = endColumn;
+
+   return t;
+}
+
+int curLexState = 0;
+int defaultLexState = 0;
+int jjnewStateCnt;
+int jjround;
+int jjmatchedPos;
+int jjmatchedKind;
+
+/** Get the next Token. */
+public Token getNextToken() 
+{
+  Token matchedToken;
+  int curPos = 0;
+
+  EOFLoop :
+  for (;;)
+  {
+   try
+   {
+      curChar = input_stream.BeginToken();
+   }
+   catch(java.io.IOException e)
+   {
+      jjmatchedKind = 0;
+      matchedToken = jjFillToken();
+      return matchedToken;
+   }
+
+   try { input_stream.backup(0);
+      while (curChar <= 32 && (0x100002600L & (1L << curChar)) != 0L)
+         curChar = input_stream.BeginToken();
+   }
+   catch (java.io.IOException e1) { continue EOFLoop; }
+   jjmatchedKind = 0x7fffffff;
+   jjmatchedPos = 0;
+   curPos = jjMoveStringLiteralDfa0_0();
+   if (jjmatchedKind != 0x7fffffff)
+   {
+      if (jjmatchedPos + 1 < curPos)
+         input_stream.backup(curPos - jjmatchedPos - 1);
+      if ((jjtoToken[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L)
+      {
+         matchedToken = jjFillToken();
+         return matchedToken;
+      }
+      else
+      {
+         continue EOFLoop;
+      }
+   }
+   int error_line = input_stream.getEndLine();
+   int error_column = input_stream.getEndColumn();
+   String error_after = null;
+   boolean EOFSeen = false;
+   try { input_stream.readChar(); input_stream.backup(1); }
+   catch (java.io.IOException e1) {
+      EOFSeen = true;
+      error_after = curPos <= 1 ? "" : input_stream.GetImage();
+      if (curChar == '\n' || curChar == '\r') {
+         error_line++;
+         error_column = 0;
+      }
+      else
+         error_column++;
+   }
+   if (!EOFSeen) {
+      input_stream.backup(1);
+      error_after = curPos <= 1 ? "" : input_stream.GetImage();
+   }
+   throw new TokenMgrError(EOFSeen, curLexState, error_line, error_column, error_after, curChar, TokenMgrError.LEXICAL_ERROR);
+  }
+}
+
+private void jjCheckNAdd(int state)
+{
+   if (jjrounds[state] != jjround)
+   {
+      jjstateSet[jjnewStateCnt++] = state;
+      jjrounds[state] = jjround;
+   }
+}
+private void jjAddStates(int start, int end)
+{
+   do {
+      jjstateSet[jjnewStateCnt++] = jjnextStates[start];
+   } while (start++ != end);
+}
+private void jjCheckNAddTwoStates(int state1, int state2)
+{
+   jjCheckNAdd(state1);
+   jjCheckNAdd(state2);
+}
+
+private void jjCheckNAddStates(int start, int end)
+{
+   do {
+      jjCheckNAdd(jjnextStates[start]);
+   } while (start++ != end);
+}
+
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/JSPELParserTreeConstants.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/JSPELParserTreeConstants.java
new file mode 100644
index 0000000..55a6e47
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/JSPELParserTreeConstants.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2005 BEA Systems 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:
+ *     BEA Systems - initial implementation
+ *     
+ *******************************************************************************/
+/* Generated By:JJTree: Do not edit this line. JSPELParserTreeConstants.java */
+
+package org.eclipse.jst.jsp.core.internal.java.jspel;
+
+public interface JSPELParserTreeConstants
+{
+  public int JJTEXPRESSION = 0;
+  public int JJTOREXPRESSION = 1;
+  public int JJTANDEXPRESSION = 2;
+  public int JJTEQUALITYEXPRESSION = 3;
+  public int JJTRELATIONALEXPRESSION = 4;
+  public int JJTADDEXPRESSION = 5;
+  public int JJTMULTIPLYEXPRESSION = 6;
+  public int JJTCHOICEEXPRESSION = 7;
+  public int JJTUNARYEXPRESSION = 8;
+  public int JJTVALUE = 9;
+  public int JJTVALUEPREFIX = 10;
+  public int JJTVALUESUFFIX = 11;
+  public int JJTFUNCTIONINVOCATION = 12;
+  public int JJTLITERAL = 13;
+
+
+  public String[] jjtNodeName = {
+    "Expression",
+    "OrExpression",
+    "AndExpression",
+    "EqualityExpression",
+    "RelationalExpression",
+    "AddExpression",
+    "MultiplyExpression",
+    "ChoiceExpression",
+    "UnaryExpression",
+    "Value",
+    "ValuePrefix",
+    "ValueSuffix",
+    "FunctionInvocation",
+    "Literal",
+  };
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/JSPELParserVisitor.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/JSPELParserVisitor.java
new file mode 100644
index 0000000..ffcf494
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/JSPELParserVisitor.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2005 BEA Systems 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:
+ *     BEA Systems - initial implementation
+ *     
+ *******************************************************************************/
+/* Generated By:JJTree: Do not edit this line. JSPELParserVisitor.java */
+
+package org.eclipse.jst.jsp.core.internal.java.jspel;
+
+public interface JSPELParserVisitor
+{
+  public Object visit(SimpleNode node, Object data);
+  public Object visit(ASTExpression node, Object data);
+  public Object visit(ASTOrExpression node, Object data);
+  public Object visit(ASTAndExpression node, Object data);
+  public Object visit(ASTEqualityExpression node, Object data);
+  public Object visit(ASTRelationalExpression node, Object data);
+  public Object visit(ASTAddExpression node, Object data);
+  public Object visit(ASTMultiplyExpression node, Object data);
+  public Object visit(ASTChoiceExpression node, Object data);
+  public Object visit(ASTUnaryExpression node, Object data);
+  public Object visit(ASTValue node, Object data);
+  public Object visit(ASTValuePrefix node, Object data);
+  public Object visit(ASTValueSuffix node, Object data);
+  public Object visit(ASTFunctionInvocation node, Object data);
+  public Object visit(ASTLiteral node, Object data);
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/JSPELTranslator.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/JSPELTranslator.java
new file mode 100644
index 0000000..c995a1a
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/JSPELTranslator.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 BEA Systems 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:
+ *     BEA Systems - initial implementation
+ *     
+ *******************************************************************************/
+
+package org.eclipse.jst.jsp.core.internal.java.jspel;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import org.eclipse.jface.text.Position;
+import org.eclipse.jst.jsp.core.internal.JSPCoreMessages;
+import org.eclipse.jst.jsp.core.jspel.ELProblem;
+import org.eclipse.jst.jsp.core.jspel.IJSPELTranslator;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+
+	
+public class JSPELTranslator implements IJSPELTranslator {
+	/**
+	 * JSP Expression Language Parser.
+	 */
+	private JSPELParser elParser = null;
+	
+	public List translateEL(String elText, String delim,
+			IStructuredDocumentRegion currentNode, int contentStart,
+			int contentLength, StringBuffer fUserELExpressions,
+			HashMap fUserELRanges, IStructuredDocument document) {
+		
+		ArrayList elProblems = new ArrayList();
+		
+		try {
+			synchronized(this) {
+				if(null == elParser) {
+					elParser = JSPELParser.createParser(elText);
+				} else {
+					elParser.ReInit(elText);
+				}
+			
+				ASTExpression expression = elParser.Expression();
+				ELGenerator gen = new ELGenerator();
+				List generatorELProblems = gen.generate(expression, currentNode, fUserELExpressions, fUserELRanges, document, currentNode, contentStart, contentLength);
+				elProblems.addAll(generatorELProblems);
+			}
+		} catch (ParseException e) {
+			Token curTok = e.currentToken;
+			int problemStartOffset;
+			int problemEndOffset;
+			Position pos = null;
+			problemStartOffset =  contentStart + curTok.beginColumn;
+			problemEndOffset = contentStart + curTok.endColumn;
+			
+			pos = new Position(problemStartOffset, problemEndOffset - problemStartOffset + 1);
+			elProblems.add(new ELProblem(pos, e.getLocalizedMessage()));
+		} catch (TokenMgrError te) {
+			Position pos = new Position(contentStart, contentLength);
+			elProblems.add(new ELProblem(pos, JSPCoreMessages.JSPEL_Token));
+		}
+		return elProblems;
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/Node.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/Node.java
new file mode 100644
index 0000000..b8a186e
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/Node.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2005 BEA Systems 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:
+ *     BEA Systems - initial implementation
+ *     
+ *******************************************************************************/
+/* Generated By:JJTree: Do not edit this line. Node.java */
+
+package org.eclipse.jst.jsp.core.internal.java.jspel;
+
+/* All AST nodes must implement this interface.  It provides basic
+   machinery for constructing the parent and child relationships
+   between nodes. */
+
+public interface Node {
+
+  /** This method is called after the node has been made the current
+    node.  It indicates that child nodes can now be added to it. */
+  public void jjtOpen();
+
+  /** This method is called after all the child nodes have been
+    added. */
+  public void jjtClose();
+
+  /** This pair of methods are used to inform the node of its
+    parent. */
+  public void jjtSetParent(Node n);
+  public Node jjtGetParent();
+
+  /** This method tells the node to add its argument to the node's
+    list of children.  */
+  public void jjtAddChild(Node n, int i);
+
+  /** This method returns a child node.  The children are numbered
+     from zero, left to right. */
+  public Node jjtGetChild(int i);
+
+  /** Return the number of children the node has. */
+  public int jjtGetNumChildren();
+
+  /** Accept the visitor. **/
+  public Object jjtAccept(JSPELParserVisitor visitor, Object data);
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ParseException.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ParseException.java
new file mode 100644
index 0000000..fbaa061
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/ParseException.java
@@ -0,0 +1,199 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2010 BEA Systems 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:
+ *     BEA Systems - initial implementation
+ *     IBM Corporation - Bug 318281 - EL validation error for quote escaping
+ *
+ *******************************************************************************/
+/* Generated By:JavaCC: Do not edit this line. ParseException.java Version 4.1 */
+/* JavaCCOptions:KEEP_LINE_COL=null */
+package org.eclipse.jst.jsp.core.internal.java.jspel;
+
+/**
+ * This exception is thrown when parse errors are encountered.
+ * You can explicitly create objects of this exception type by
+ * calling the method generateParseException in the generated
+ * parser.
+ *
+ * You can modify this class to customize your error reporting
+ * mechanisms so long as you retain the public fields.
+ */
+public class ParseException extends Exception {
+
+  /**
+   * The version identifier for this Serializable class.
+   * Increment only if the <i>serialized</i> form of the
+   * class changes.
+   */
+  private static final long serialVersionUID = 1L;
+
+  /**
+   * This constructor is used by the method "generateParseException"
+   * in the generated parser.  Calling this constructor generates
+   * a new object of this type with the fields "currentToken",
+   * "expectedTokenSequences", and "tokenImage" set.
+   */
+  public ParseException(Token currentTokenVal,
+                        int[][] expectedTokenSequencesVal,
+                        String[] tokenImageVal
+                       )
+  {
+    super(initialise(currentTokenVal, expectedTokenSequencesVal, tokenImageVal));
+    currentToken = currentTokenVal;
+    expectedTokenSequences = expectedTokenSequencesVal;
+    tokenImage = tokenImageVal;
+  }
+
+  /**
+   * The following constructors are for use by you for whatever
+   * purpose you can think of.  Constructing the exception in this
+   * manner makes the exception behave in the normal way - i.e., as
+   * documented in the class "Throwable".  The fields "errorToken",
+   * "expectedTokenSequences", and "tokenImage" do not contain
+   * relevant information.  The JavaCC generated code does not use
+   * these constructors.
+   */
+
+  public ParseException() {
+    super();
+  }
+
+  /** Constructor with message. */
+  public ParseException(String message) {
+    super(message);
+  }
+
+
+  /**
+   * This is the last token that has been consumed successfully.  If
+   * this object has been created due to a parse error, the token
+   * followng this token will (therefore) be the first error token.
+   */
+  public Token currentToken;
+
+  /**
+   * Each entry in this array is an array of integers.  Each array
+   * of integers represents a sequence of tokens (by their ordinal
+   * values) that is expected at this point of the parse.
+   */
+  public int[][] expectedTokenSequences;
+
+  /**
+   * This is a reference to the "tokenImage" array of the generated
+   * parser within which the parse error occurred.  This array is
+   * defined in the generated ...Constants interface.
+   */
+  public String[] tokenImage;
+
+  /**
+   * It uses "currentToken" and "expectedTokenSequences" to generate a parse
+   * error message and returns it.  If this object has been created
+   * due to a parse error, and you do not catch it (it gets thrown
+   * from the parser) the correct error message
+   * gets displayed.
+   */
+  private static String initialise(Token currentToken,
+                           int[][] expectedTokenSequences,
+                           String[] tokenImage) {
+    String eol = System.getProperty("line.separator", "\n");
+    StringBuffer expected = new StringBuffer();
+    int maxSize = 0;
+    for (int i = 0; i < expectedTokenSequences.length; i++) {
+      if (maxSize < expectedTokenSequences[i].length) {
+        maxSize = expectedTokenSequences[i].length;
+      }
+      for (int j = 0; j < expectedTokenSequences[i].length; j++) {
+        expected.append(tokenImage[expectedTokenSequences[i][j]]).append(' ');
+      }
+      if (expectedTokenSequences[i][expectedTokenSequences[i].length - 1] != 0) {
+        expected.append("...");
+      }
+      expected.append(eol).append("    ");
+    }
+    String retval = "Encountered \"";
+    Token tok = currentToken.next;
+    for (int i = 0; i < maxSize; i++) {
+      if (i != 0) retval += " ";
+      if (tok.kind == 0) {
+        retval += tokenImage[0];
+        break;
+      }
+      retval += " " + tokenImage[tok.kind];
+      retval += " \"";
+      retval += add_escapes(tok.image);
+      retval += " \"";
+      tok = tok.next;
+    }
+    retval += "\" at line " + currentToken.next.beginLine + ", column " + currentToken.next.beginColumn;
+    retval += "." + eol;
+    if (expectedTokenSequences.length == 1) {
+      retval += "Was expecting:" + eol + "    ";
+    } else {
+      retval += "Was expecting one of:" + eol + "    ";
+    }
+    retval += expected.toString();
+    return retval;
+  }
+
+  /**
+   * The end of line string for this machine.
+   */
+  protected String eol = System.getProperty("line.separator", "\n");
+
+  /**
+   * Used to convert raw characters to their escaped version
+   * when these raw version cannot be used as part of an ASCII
+   * string literal.
+   */
+  static String add_escapes(String str) {
+      StringBuffer retval = new StringBuffer();
+      char ch;
+      for (int i = 0; i < str.length(); i++) {
+        switch (str.charAt(i))
+        {
+           case 0 :
+              continue;
+           case '\b':
+              retval.append("\\b");
+              continue;
+           case '\t':
+              retval.append("\\t");
+              continue;
+           case '\n':
+              retval.append("\\n");
+              continue;
+           case '\f':
+              retval.append("\\f");
+              continue;
+           case '\r':
+              retval.append("\\r");
+              continue;
+           case '\"':
+              retval.append("\\\"");
+              continue;
+           case '\'':
+              retval.append("\\\'");
+              continue;
+           case '\\':
+              retval.append("\\\\");
+              continue;
+           default:
+              if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) {
+                 String s = "0000" + Integer.toString(ch, 16);
+                 retval.append("\\u" + s.substring(s.length() - 4, s.length()));
+              } else {
+                 retval.append(ch);
+              }
+              continue;
+        }
+      }
+      return retval.toString();
+   }
+
+}
+/* JavaCC - OriginalChecksum=2450ea96e71c048c1be00d6aa17c7b52 (do not edit this line) */
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/SimpleCharStream.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/SimpleCharStream.java
new file mode 100644
index 0000000..657c505
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/SimpleCharStream.java
@@ -0,0 +1,481 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2010 BEA Systems 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:
+ *     BEA Systems - initial implementation
+ *     IBM Corporation - Bug 318281 - EL validation error for quote escaping
+ *
+ *******************************************************************************/
+/* Generated By:JavaCC: Do not edit this line. SimpleCharStream.java Version 4.1 */
+/* JavaCCOptions:STATIC=false,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */
+package org.eclipse.jst.jsp.core.internal.java.jspel;
+
+/**
+ * An implementation of interface CharStream, where the stream is assumed to
+ * contain only ASCII characters (without unicode processing).
+ */
+
+public class SimpleCharStream
+{
+/** Whether parser is static. */
+  public static final boolean staticFlag = false;
+  int bufsize;
+  int available;
+  int tokenBegin;
+/** Position in buffer. */
+  public int bufpos = -1;
+  protected int bufline[];
+  protected int bufcolumn[];
+
+  protected int column = 0;
+  protected int line = 1;
+
+  protected boolean prevCharIsCR = false;
+  protected boolean prevCharIsLF = false;
+
+  protected java.io.Reader inputStream;
+
+  protected char[] buffer;
+  protected int maxNextCharInd = 0;
+  protected int inBuf = 0;
+  protected int tabSize = 8;
+
+  protected void setTabSize(int i) { tabSize = i; }
+  protected int getTabSize(int i) { return tabSize; }
+
+
+  protected void ExpandBuff(boolean wrapAround)
+  {
+    char[] newbuffer = new char[bufsize + 2048];
+    int newbufline[] = new int[bufsize + 2048];
+    int newbufcolumn[] = new int[bufsize + 2048];
+
+    try
+    {
+      if (wrapAround)
+      {
+        System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
+        System.arraycopy(buffer, 0, newbuffer, bufsize - tokenBegin, bufpos);
+        buffer = newbuffer;
+
+        System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
+        System.arraycopy(bufline, 0, newbufline, bufsize - tokenBegin, bufpos);
+        bufline = newbufline;
+
+        System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
+        System.arraycopy(bufcolumn, 0, newbufcolumn, bufsize - tokenBegin, bufpos);
+        bufcolumn = newbufcolumn;
+
+        maxNextCharInd = (bufpos += (bufsize - tokenBegin));
+      }
+      else
+      {
+        System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
+        buffer = newbuffer;
+
+        System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
+        bufline = newbufline;
+
+        System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
+        bufcolumn = newbufcolumn;
+
+        maxNextCharInd = (bufpos -= tokenBegin);
+      }
+    }
+    catch (Throwable t)
+    {
+      throw new Error(t.getMessage());
+    }
+
+
+    bufsize += 2048;
+    available = bufsize;
+    tokenBegin = 0;
+  }
+
+  protected void FillBuff() throws java.io.IOException
+  {
+    if (maxNextCharInd == available)
+    {
+      if (available == bufsize)
+      {
+        if (tokenBegin > 2048)
+        {
+          bufpos = maxNextCharInd = 0;
+          available = tokenBegin;
+        }
+        else if (tokenBegin < 0)
+          bufpos = maxNextCharInd = 0;
+        else
+          ExpandBuff(false);
+      }
+      else if (available > tokenBegin)
+        available = bufsize;
+      else if ((tokenBegin - available) < 2048)
+        ExpandBuff(true);
+      else
+        available = tokenBegin;
+    }
+
+    int i;
+    try {
+      if ((i = inputStream.read(buffer, maxNextCharInd, available - maxNextCharInd)) == -1)
+      {
+        inputStream.close();
+        throw new java.io.IOException();
+      }
+      else
+        maxNextCharInd += i;
+      return;
+    }
+    catch(java.io.IOException e) {
+      --bufpos;
+      backup(0);
+      if (tokenBegin == -1)
+        tokenBegin = bufpos;
+      throw e;
+    }
+  }
+
+/** Start. */
+  public char BeginToken() throws java.io.IOException
+  {
+    tokenBegin = -1;
+    char c = readChar();
+    tokenBegin = bufpos;
+
+    return c;
+  }
+
+  protected void UpdateLineColumn(char c)
+  {
+    column++;
+
+    if (prevCharIsLF)
+    {
+      prevCharIsLF = false;
+      line += (column = 1);
+    }
+    else if (prevCharIsCR)
+    {
+      prevCharIsCR = false;
+      if (c == '\n')
+      {
+        prevCharIsLF = true;
+      }
+      else
+        line += (column = 1);
+    }
+
+    switch (c)
+    {
+      case '\r' :
+        prevCharIsCR = true;
+        break;
+      case '\n' :
+        prevCharIsLF = true;
+        break;
+      case '\t' :
+        column--;
+        column += (tabSize - (column % tabSize));
+        break;
+      default :
+        break;
+    }
+
+    bufline[bufpos] = line;
+    bufcolumn[bufpos] = column;
+  }
+
+/** Read a character. */
+  public char readChar() throws java.io.IOException
+  {
+    if (inBuf > 0)
+    {
+      --inBuf;
+
+      if (++bufpos == bufsize)
+        bufpos = 0;
+
+      return buffer[bufpos];
+    }
+
+    if (++bufpos >= maxNextCharInd)
+      FillBuff();
+
+    char c = buffer[bufpos];
+
+    UpdateLineColumn(c);
+    return c;
+  }
+
+  /**
+   * @deprecated
+   * @see #getEndColumn
+   */
+
+  public int getColumn() {
+    return bufcolumn[bufpos];
+  }
+
+  /**
+   * @deprecated
+   * @see #getEndLine
+   */
+
+  public int getLine() {
+    return bufline[bufpos];
+  }
+
+  /** Get token end column number. */
+  public int getEndColumn() {
+    return bufcolumn[bufpos];
+  }
+
+  /** Get token end line number. */
+  public int getEndLine() {
+     return bufline[bufpos];
+  }
+
+  /** Get token beginning column number. */
+  public int getBeginColumn() {
+    return bufcolumn[tokenBegin];
+  }
+
+  /** Get token beginning line number. */
+  public int getBeginLine() {
+    return bufline[tokenBegin];
+  }
+
+/** Backup a number of characters. */
+  public void backup(int amount) {
+
+    inBuf += amount;
+    if ((bufpos -= amount) < 0)
+      bufpos += bufsize;
+  }
+
+  /** Constructor. */
+  public SimpleCharStream(java.io.Reader dstream, int startline,
+  int startcolumn, int buffersize)
+  {
+    inputStream = dstream;
+    line = startline;
+    column = startcolumn - 1;
+
+    available = bufsize = buffersize;
+    buffer = new char[buffersize];
+    bufline = new int[buffersize];
+    bufcolumn = new int[buffersize];
+  }
+
+  /** Constructor. */
+  public SimpleCharStream(java.io.Reader dstream, int startline,
+                          int startcolumn)
+  {
+    this(dstream, startline, startcolumn, 4096);
+  }
+
+  /** Constructor. */
+  public SimpleCharStream(java.io.Reader dstream)
+  {
+    this(dstream, 1, 1, 4096);
+  }
+
+  /** Reinitialise. */
+  public void ReInit(java.io.Reader dstream, int startline,
+  int startcolumn, int buffersize)
+  {
+    inputStream = dstream;
+    line = startline;
+    column = startcolumn - 1;
+
+    if (buffer == null || buffersize != buffer.length)
+    {
+      available = bufsize = buffersize;
+      buffer = new char[buffersize];
+      bufline = new int[buffersize];
+      bufcolumn = new int[buffersize];
+    }
+    prevCharIsLF = prevCharIsCR = false;
+    tokenBegin = inBuf = maxNextCharInd = 0;
+    bufpos = -1;
+  }
+
+  /** Reinitialise. */
+  public void ReInit(java.io.Reader dstream, int startline,
+                     int startcolumn)
+  {
+    ReInit(dstream, startline, startcolumn, 4096);
+  }
+
+  /** Reinitialise. */
+  public void ReInit(java.io.Reader dstream)
+  {
+    ReInit(dstream, 1, 1, 4096);
+  }
+  /** Constructor. */
+  public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline,
+  int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException
+  {
+    this(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize);
+  }
+
+  /** Constructor. */
+  public SimpleCharStream(java.io.InputStream dstream, int startline,
+  int startcolumn, int buffersize)
+  {
+    this(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize);
+  }
+
+  /** Constructor. */
+  public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline,
+                          int startcolumn) throws java.io.UnsupportedEncodingException
+  {
+    this(dstream, encoding, startline, startcolumn, 4096);
+  }
+
+  /** Constructor. */
+  public SimpleCharStream(java.io.InputStream dstream, int startline,
+                          int startcolumn)
+  {
+    this(dstream, startline, startcolumn, 4096);
+  }
+
+  /** Constructor. */
+  public SimpleCharStream(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException
+  {
+    this(dstream, encoding, 1, 1, 4096);
+  }
+
+  /** Constructor. */
+  public SimpleCharStream(java.io.InputStream dstream)
+  {
+    this(dstream, 1, 1, 4096);
+  }
+
+  /** Reinitialise. */
+  public void ReInit(java.io.InputStream dstream, String encoding, int startline,
+                          int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException
+  {
+    ReInit(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize);
+  }
+
+  /** Reinitialise. */
+  public void ReInit(java.io.InputStream dstream, int startline,
+                          int startcolumn, int buffersize)
+  {
+    ReInit(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize);
+  }
+
+  /** Reinitialise. */
+  public void ReInit(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException
+  {
+    ReInit(dstream, encoding, 1, 1, 4096);
+  }
+
+  /** Reinitialise. */
+  public void ReInit(java.io.InputStream dstream)
+  {
+    ReInit(dstream, 1, 1, 4096);
+  }
+  /** Reinitialise. */
+  public void ReInit(java.io.InputStream dstream, String encoding, int startline,
+                     int startcolumn) throws java.io.UnsupportedEncodingException
+  {
+    ReInit(dstream, encoding, startline, startcolumn, 4096);
+  }
+  /** Reinitialise. */
+  public void ReInit(java.io.InputStream dstream, int startline,
+                     int startcolumn)
+  {
+    ReInit(dstream, startline, startcolumn, 4096);
+  }
+  /** Get token literal value. */
+  public String GetImage()
+  {
+    if (bufpos >= tokenBegin)
+      return new String(buffer, tokenBegin, bufpos - tokenBegin + 1);
+    else
+      return new String(buffer, tokenBegin, bufsize - tokenBegin) +
+                            new String(buffer, 0, bufpos + 1);
+  }
+
+  /** Get the suffix. */
+  public char[] GetSuffix(int len)
+  {
+    char[] ret = new char[len];
+
+    if ((bufpos + 1) >= len)
+      System.arraycopy(buffer, bufpos - len + 1, ret, 0, len);
+    else
+    {
+      System.arraycopy(buffer, bufsize - (len - bufpos - 1), ret, 0,
+                                                        len - bufpos - 1);
+      System.arraycopy(buffer, 0, ret, len - bufpos - 1, bufpos + 1);
+    }
+
+    return ret;
+  }
+
+  /** Reset buffer when finished. */
+  public void Done()
+  {
+    buffer = null;
+    bufline = null;
+    bufcolumn = null;
+  }
+
+  /**
+   * Method to adjust line and column numbers for the start of a token.
+   */
+  public void adjustBeginLineColumn(int newLine, int newCol)
+  {
+    int start = tokenBegin;
+    int len;
+
+    if (bufpos >= tokenBegin)
+    {
+      len = bufpos - tokenBegin + inBuf + 1;
+    }
+    else
+    {
+      len = bufsize - tokenBegin + bufpos + 1 + inBuf;
+    }
+
+    int i = 0, j = 0, k = 0;
+    int nextColDiff = 0, columnDiff = 0;
+
+    while (i < len && bufline[j = start % bufsize] == bufline[k = ++start % bufsize])
+    {
+      bufline[j] = newLine;
+      nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j];
+      bufcolumn[j] = newCol + columnDiff;
+      columnDiff = nextColDiff;
+      i++;
+    }
+
+    if (i < len)
+    {
+      bufline[j] = newLine++;
+      bufcolumn[j] = newCol + columnDiff;
+
+      while (i++ < len)
+      {
+        if (bufline[j = start % bufsize] != bufline[++start % bufsize])
+          bufline[j] = newLine++;
+        else
+          bufline[j] = newLine;
+      }
+    }
+
+    line = bufline[j];
+    column = bufcolumn[j];
+  }
+
+}
+/* JavaCC - OriginalChecksum=f319cd62855f4b29d5c4e9550c8852eb (do not edit this line) */
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/SimpleNode.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/SimpleNode.java
new file mode 100644
index 0000000..aac473f
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/SimpleNode.java
@@ -0,0 +1,116 @@
+/*******************************************************************************
+ * Copyright (c) 2005 BEA Systems 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:
+ *     BEA Systems - initial implementation
+ *     
+ *******************************************************************************/
+/* Generated By:JJTree: Do not edit this line. SimpleNode.java */
+
+package org.eclipse.jst.jsp.core.internal.java.jspel;
+
+public class SimpleNode implements Node {
+  protected Node parent;
+  protected Node[] children;
+  protected int id;
+  protected JSPELParser parser;
+  protected Token firstToken;
+  protected Token lastToken;
+
+  public SimpleNode(int i) {
+    id = i;
+  }
+
+  public SimpleNode(JSPELParser p, int i) {
+    this(i);
+    parser = p;
+  }
+
+  public void jjtOpen() {
+  }
+
+  public void jjtClose() {
+  }
+  
+  public void jjtSetParent(Node n) { parent = n; }
+  public Node jjtGetParent() { return parent; }
+
+  public void jjtAddChild(Node n, int i) {
+    if (children == null) {
+      children = new Node[i + 1];
+    } else if (i >= children.length) {
+      Node c[] = new Node[i + 1];
+      System.arraycopy(children, 0, c, 0, children.length);
+      children = c;
+    }
+    children[i] = n;
+  }
+
+  public Node jjtGetChild(int i) {
+    return children[i];
+  }
+
+  public int jjtGetNumChildren() {
+    return (children == null) ? 0 : children.length;
+  }
+
+  /** Accept the visitor. **/
+  public Object jjtAccept(JSPELParserVisitor visitor, Object data) {
+    return visitor.visit(this, data);
+  }
+
+  /** Accept the visitor. **/
+  public Object childrenAccept(JSPELParserVisitor visitor, Object data) {
+    if (children != null) {
+      for (int i = 0; i < children.length; ++i) {
+        children[i].jjtAccept(visitor, data);
+      }
+    }
+    return data;
+  }
+
+  /* You can override these two methods in subclasses of SimpleNode to
+     customize the way the node appears when the tree is dumped.  If
+     your output uses more than one line you should override
+     toString(String), otherwise overriding toString() is probably all
+     you need to do. */
+
+  public String toString() { return JSPELParserTreeConstants.jjtNodeName[id]; }
+  public String toString(String prefix) { return prefix + toString(); }
+
+  /* Override this method if you want to customize how the node dumps
+     out its children. */
+
+  public void dump(String prefix) {
+    System.out.println(toString(prefix));
+    if (children != null) {
+      for (int i = 0; i < children.length; ++i) {
+	SimpleNode n = (SimpleNode)children[i];
+	if (n != null) {
+	  n.dump(prefix + " ");
+	}
+      }
+    }
+  }
+
+  public Token getFirstToken() {
+    return firstToken;
+  }
+
+  public void setFirstToken(Token firstToken) {
+    this.firstToken = firstToken;
+  }
+
+  public Token getLastToken() {
+    return lastToken;
+  }
+
+  public void setLastToken(Token lastToken) {
+    this.lastToken = lastToken;
+  }
+}
+
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/Token.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/Token.java
new file mode 100644
index 0000000..6bad947
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/Token.java
@@ -0,0 +1,143 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2010 BEA Systems 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:
+ *     BEA Systems - initial implementation
+ *     IBM Corporation - Bug 318281 - EL validation error for quote escaping
+ *
+ *******************************************************************************/
+/* Generated By:JavaCC: Do not edit this line. Token.java Version 4.1 */
+/* JavaCCOptions:TOKEN_EXTENDS=,KEEP_LINE_COL=null,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */
+package org.eclipse.jst.jsp.core.internal.java.jspel;
+
+/**
+ * Describes the input token stream.
+ */
+
+public class Token implements java.io.Serializable {
+
+  /**
+   * The version identifier for this Serializable class.
+   * Increment only if the <i>serialized</i> form of the
+   * class changes.
+   */
+  private static final long serialVersionUID = 1L;
+
+  /**
+   * An integer that describes the kind of this token.  This numbering
+   * system is determined by JavaCCParser, and a table of these numbers is
+   * stored in the file ...Constants.java.
+   */
+  public int kind;
+
+  /** The line number of the first character of this Token. */
+  public int beginLine;
+  /** The column number of the first character of this Token. */
+  public int beginColumn;
+  /** The line number of the last character of this Token. */
+  public int endLine;
+  /** The column number of the last character of this Token. */
+  public int endColumn;
+
+  /**
+   * The string image of the token.
+   */
+  public String image;
+
+  /**
+   * A reference to the next regular (non-special) token from the input
+   * stream.  If this is the last token from the input stream, or if the
+   * token manager has not read tokens beyond this one, this field is
+   * set to null.  This is true only if this token is also a regular
+   * token.  Otherwise, see below for a description of the contents of
+   * this field.
+   */
+  public Token next;
+
+  /**
+   * This field is used to access special tokens that occur prior to this
+   * token, but after the immediately preceding regular (non-special) token.
+   * If there are no such special tokens, this field is set to null.
+   * When there are more than one such special token, this field refers
+   * to the last of these special tokens, which in turn refers to the next
+   * previous special token through its specialToken field, and so on
+   * until the first special token (whose specialToken field is null).
+   * The next fields of special tokens refer to other special tokens that
+   * immediately follow it (without an intervening regular token).  If there
+   * is no such token, this field is null.
+   */
+  public Token specialToken;
+
+  /**
+   * An optional attribute value of the Token.
+   * Tokens which are not used as syntactic sugar will often contain
+   * meaningful values that will be used later on by the compiler or
+   * interpreter. This attribute value is often different from the image.
+   * Any subclass of Token that actually wants to return a non-null value can
+   * override this method as appropriate.
+   */
+  public Object getValue() {
+    return null;
+  }
+
+  /**
+   * No-argument constructor
+   */
+  public Token() {}
+
+  /**
+   * Constructs a new token for the specified Image.
+   */
+  public Token(int kind)
+  {
+    this(kind, null);
+  }
+
+  /**
+   * Constructs a new token for the specified Image and Kind.
+   */
+  public Token(int kind, String image)
+  {
+    this.kind = kind;
+    this.image = image;
+  }
+
+  /**
+   * Returns the image.
+   */
+  public String toString()
+  {
+    return image;
+  }
+
+  /**
+   * Returns a new Token object, by default. However, if you want, you
+   * can create and return subclass objects based on the value of ofKind.
+   * Simply add the cases to the switch for all those special cases.
+   * For example, if you have a subclass of Token called IDToken that
+   * you want to create if ofKind is ID, simply add something like :
+   *
+   *    case MyParserConstants.ID : return new IDToken(ofKind, image);
+   *
+   * to the following switch statement. Then you can cast matchedToken
+   * variable to the appropriate type and use sit in your lexical actions.
+   */
+  public static Token newToken(int ofKind, String image)
+  {
+    switch(ofKind)
+    {
+      default : return new Token(ofKind, image);
+    }
+  }
+
+  public static Token newToken(int ofKind)
+  {
+    return newToken(ofKind, null);
+  }
+
+}
+/* JavaCC - OriginalChecksum=688686a2181e010445ea99e501e9cd07 (do not edit this line) */
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/TokenMgrError.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/TokenMgrError.java
new file mode 100644
index 0000000..1a53dc2
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/TokenMgrError.java
@@ -0,0 +1,149 @@
+/*******************************************************************************
+ * Copyright (c) 2005 BEA Systems 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:
+ *     BEA Systems - initial implementation
+ *     
+ *******************************************************************************/
+/* Generated By:JavaCC: Do not edit this line. TokenMgrError.java Version 3.0 */
+package org.eclipse.jst.jsp.core.internal.java.jspel;
+
+public class TokenMgrError extends Error
+{
+   /*
+    * Ordinals for various reasons why an Error of this type can be thrown.
+    */
+
+   /**
+	 * Default <code>serialVersionUID</code>
+	 */
+	private static final long serialVersionUID = 1L;
+
+/**
+    * Lexical error occured.
+    */
+   static final int LEXICAL_ERROR = 0;
+
+   /**
+    * An attempt wass made to create a second instance of a static token manager.
+    */
+   static final int STATIC_LEXER_ERROR = 1;
+
+   /**
+    * Tried to change to an invalid lexical state.
+    */
+   static final int INVALID_LEXICAL_STATE = 2;
+
+   /**
+    * Detected (and bailed out of) an infinite loop in the token manager.
+    */
+   static final int LOOP_DETECTED = 3;
+
+   /**
+    * Indicates the reason why the exception is thrown. It will have
+    * one of the above 4 values.
+    */
+   int errorCode;
+
+   /**
+    * Replaces unprintable characters by their espaced (or unicode escaped)
+    * equivalents in the given string
+    */
+   protected static final String addEscapes(String str) {
+      StringBuffer retval = new StringBuffer();
+      char ch;
+      for (int i = 0; i < str.length(); i++) {
+        switch (str.charAt(i))
+        {
+           case 0 :
+              continue;
+           case '\b':
+              retval.append("\\b");
+              continue;
+           case '\t':
+              retval.append("\\t");
+              continue;
+           case '\n':
+              retval.append("\\n");
+              continue;
+           case '\f':
+              retval.append("\\f");
+              continue;
+           case '\r':
+              retval.append("\\r");
+              continue;
+           case '\"':
+              retval.append("\\\"");
+              continue;
+           case '\'':
+              retval.append("\\\'");
+              continue;
+           case '\\':
+              retval.append("\\\\");
+              continue;
+           default:
+              if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) {
+                 String s = "0000" + Integer.toString(ch, 16);
+                 retval.append("\\u" + s.substring(s.length() - 4, s.length()));
+              } else {
+                 retval.append(ch);
+              }
+              continue;
+        }
+      }
+      return retval.toString();
+   }
+
+   /**
+    * Returns a detailed message for the Error when it is thrown by the
+    * token manager to indicate a lexical error.
+    * Parameters : 
+    *    EOFSeen     : indicates if EOF caused the lexicl error
+    *    curLexState : lexical state in which this error occured
+    *    errorLine   : line number when the error occured
+    *    errorColumn : column number when the error occured
+    *    errorAfter  : prefix that was seen before this error occured
+    *    curchar     : the offending character
+    * Note: You can customize the lexical error message by modifying this method.
+    */
+   protected static String LexicalError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar) {
+      return("Lexical error at line " +
+           errorLine + ", column " +
+           errorColumn + ".  Encountered: " +
+           (EOFSeen ? "<EOF> " : ("\"" + addEscapes(String.valueOf(curChar)) + "\"") + " (" + (int)curChar + "), ") +
+           "after : \"" + addEscapes(errorAfter) + "\"");
+   }
+
+   /**
+    * You can also modify the body of this method to customize your error messages.
+    * For example, cases like LOOP_DETECTED and INVALID_LEXICAL_STATE are not
+    * of end-users concern, so you can return something like : 
+    *
+    *     "Internal Error : Please file a bug report .... "
+    *
+    * from this method for such cases in the release version of your parser.
+    */
+   public String getMessage() {
+      return super.getMessage();
+   }
+
+   /*
+    * Constructors of various flavors follow.
+    */
+
+   public TokenMgrError() {
+   }
+
+   public TokenMgrError(String message, int reason) {
+      super(message);
+      errorCode = reason;
+   }
+
+   public TokenMgrError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar, int reason) {
+      this(LexicalError(EOFSeen, lexState, errorLine, errorColumn, errorAfter, curChar), reason);
+   }
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/fixparser.sed b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/fixparser.sed
new file mode 100644
index 0000000..1aa5e62
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/fixparser.sed
@@ -0,0 +1,18 @@
+#!/usr/bin/sed

+

+#

+# The SSE generally uses compiler setting to turn  most warnings into errors.  

+# This is a little problematic for JavaCC generated files.  We don't want 

+# to distribute a customized version of JavaCC nor is there any "template" 

+# mechanism.  So, this simple sed script goes through the generated token

+# manager and fixes a few things.  If JavaCC changes the generated code, 

+# it's likely that this script will no longer do the right thing.  Ditto with

+# any version of JavaCC besides 3.2. Also, there's no guarantee that this 

+# script will even work with an arbitrary JavaCC grammar.  It's only been tested

+# with the current JSP EL grammar.

+#

+# Author: Ted A. Carroll (tcarroll@bea.com)

+#

+

+s/static private final class LookaheadSuccess extends java.lang.Error { }/static private final class LookaheadSuccess extends java.lang.Error { \n    private static final long serialVersionUID = 1L; \n  }/g

+

diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/fixtm.sed b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/fixtm.sed
new file mode 100644
index 0000000..5c1dea4
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/fixtm.sed
@@ -0,0 +1,27 @@
+#!/usr/bin/sed

+

+#

+# The SSE generally uses compiler setting to turn  most warnings into errors.  

+# This is a little problematic for JavaCC generated files.  We don't want 

+# to distribute a customized version of JavaCC nor is there any "template" 

+# mechanism.  So, this simple sed script goes through the generated token

+# manager and fixes a few things.  If JavaCC changes the generated code, 

+# it's likely that this script will no longer do the right thing.  Ditto with

+# any version of JavaCC besides 3.2. Also, there's no guarantee that this 

+# script will even work with an arbitrary JavaCC grammar.  It's only been tested

+# with the current JSP EL grammar.

+#

+# Author: Ted A. Carroll (tcarroll@bea.com)

+#

+

+s/(int)(curChar >> 8)/curChar >> 8/g

+

+/^public Token getNextToken()/, /EOFLoop/{

+	/int kind;/ {d}

+	/Token specialToken = null;/{d}

+}

+

+/^private final int jjMoveNfa_0(int startState, int curPos)/, /for(;;)/{

+	s/int j, kind = 0x7fffffff;/int kind = 0x7fffffff;/g

+	/int\[\] nextStates;/{d}

+}

diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/go.sh b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/go.sh
new file mode 100644
index 0000000..b3d5aaa
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/jspel/go.sh
@@ -0,0 +1,9 @@
+#!/usr/bin/sh

+

+# Set JAVACC_HOME to the installation directory of javacc 3.2

+$JAVACC_HOME/bin/jjtree.bat JSPEL.jjt

+$JAVACC_HOME/bin/javacc.bat JSPEL.jj

+sed -f fixtm.sed -i.bak JSPELParserTokenManager.java

+diff -w JSPELParserTokenManager.java JSPELParserTokenManager.java.bak

+sed -f fixparser.sed -i.bak JSPELParser.java

+diff -w JSPELParser.java JSPELParser.java.bak

diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/search/IndexWorkspaceJob.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/search/IndexWorkspaceJob.java
new file mode 100644
index 0000000..5313b20
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/search/IndexWorkspaceJob.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.java.search;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jst.jsp.core.internal.JSPCoreMessages;
+
+/**
+ * @deprecated - no longer used
+ */
+public class IndexWorkspaceJob extends Job {
+
+	// for debugging
+	static final boolean DEBUG;
+	static {
+		String value= Platform.getDebugOption("org.eclipse.jst.jsp.core/debug/jspindexmanager"); //$NON-NLS-1$
+		DEBUG= value != null && value.equalsIgnoreCase("true"); //$NON-NLS-1$
+	}
+	
+	public IndexWorkspaceJob() {
+		// pa_TODO may want to say something like "Rebuilding JSP Index" to be more
+		// descriptive instead of "Updating JSP Index" since they are 2 different things
+		super(JSPCoreMessages.JSPIndexManager_0);
+		setPriority(Job.LONG);
+		setSystem(true);
+	}
+
+	/**
+	 * @see org eclipse.core.internal.jobs.InternalJob#run(org.eclipse.core.runtime.IProgressMonitor) 
+	 * for similar method
+	 */
+	protected IStatus run(IProgressMonitor monitor) {
+		return Status.OK_STATUS;
+	}
+	
+	void setCanceledState() {}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/search/JSPIndexManager.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/search/JSPIndexManager.java
new file mode 100644
index 0000000..be734a4
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/search/JSPIndexManager.java
@@ -0,0 +1,164 @@
+/*******************************************************************************
+ * 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
+ *     
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.java.search;
+
+import java.io.File;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.content.IContentType;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jst.jsp.core.internal.JSPCoreMessages;
+import org.eclipse.jst.jsp.core.internal.JSPCorePlugin;
+import org.eclipse.jst.jsp.core.internal.Logger;
+import org.eclipse.jst.jsp.core.internal.java.JSPTranslatorPersister;
+import org.eclipse.jst.jsp.core.internal.provisional.contenttype.ContentTypeIdForJSP;
+import org.eclipse.wst.sse.core.indexing.AbstractIndexManager;
+
+/**
+ * <p>Index manger used to update the JDT index with the Java translations
+ * of JSPs.</p>
+ * 
+ * <p>Also keeps JSP persistence up to date</p>
+ * 
+ * <p>Any action that needs the JDT index to have all of the latest JSP changes processed
+ * should wait for this manger to report that it is consistent,
+ * {@link #waitForConsistent(org.eclipse.core.runtime.IProgressMonitor)}.  Such actions
+ * include but are not limited to searching and refactoring JSPs.</p>
+ */
+public class JSPIndexManager extends AbstractIndexManager {
+	/** the singleton instance of the {@link JSPIndexManager} */
+	private static JSPIndexManager INSTANCE;
+	
+	/** the JSP {@link IContentType} */
+	private static final IContentType JSP_CONTENT_TYPE =
+		Platform.getContentTypeManager().getContentType(ContentTypeIdForJSP.ContentTypeID_JSP);
+	
+	/** the location to store state */
+	private IPath fWorkingLocation;
+	
+	/**
+	 * <p>Private singleton constructor</p>
+	 */
+	private JSPIndexManager() {
+		super(JSPCoreMessages.JSPIndexManager_0, JSPCoreMessages.JSPIndexManager_0,
+				JSPCoreMessages.Initializing, JSPCoreMessages.JSPIndexManager_2);
+	}
+	
+	/**
+	 * @return the singleton instance of the {@link JSPIndexManager}
+	 */
+	public static JSPIndexManager getDefault() {
+		return INSTANCE != null ? INSTANCE : (INSTANCE = new JSPIndexManager());
+	}
+	
+	/**
+	 * @deprecated - use {@link #getDefault()} 
+	 **/
+	public synchronized static JSPIndexManager getInstance() {
+		return getDefault();
+		
+	}
+	/**
+	 * @see indexer.internal.indexing.AbstractIndexManager#isResourceToIndex(int, java.lang.String)
+	 */
+	protected boolean isResourceToIndex(int type, IPath path) {
+		String name = path.lastSegment();
+		return 
+			type == IResource.PROJECT || 
+			(type == IResource.FOLDER && !name.equals("bin") && !name.startsWith(".")) || //$NON-NLS-1$ //$NON-NLS-2$
+			JSP_CONTENT_TYPE.isAssociatedWith(path.lastSegment());
+	}
+
+	/**
+	 * @see indexer.internal.indexing.AbstractIndexManager#getWorkingLocation()
+	 */
+	protected IPath getWorkingLocation() {
+		if(this.fWorkingLocation == null) {
+			//create path to working area
+    		IPath workingLocation =
+    			JSPCorePlugin.getDefault().getStateLocation().append("jspsearch"); //$NON-NLS-1$
+
+            // ensure that it exists on disk
+            File folder = new File(workingLocation.toOSString());
+    		if (!folder.isDirectory()) {
+    			try {
+    				folder.mkdir();
+    			}
+    			catch (SecurityException e) {
+    				Logger.logException(this.getName() +
+    						": Error while creating state location: " + folder + //$NON-NLS-1$
+    						" This renders the index manager irrevocably broken for this workspace session", //$NON-NLS-1$
+    						e);
+    			}
+    		}
+    		
+    		this.fWorkingLocation = workingLocation;
+    	}
+    	
+        return this.fWorkingLocation;
+	}
+
+	/**
+	 * @see indexer.internal.indexing.AbstractIndexManager#performAction(byte, byte, org.eclipse.core.resources.IResource, org.eclipse.core.runtime.IPath)
+	 */
+	protected void performAction(byte source, byte action, IResource resource,
+			IPath movePath) {
+		
+		//inform the persister of the action unless it come from a full workspace scan
+		if(JSPTranslatorPersister.ACTIVATED && source != AbstractIndexManager.SOURCE_WORKSPACE_SCAN) {
+			switch(action) {
+				case AbstractIndexManager.ACTION_ADD: {
+					JSPTranslatorPersister.persistTranslation(resource);
+					break;
+				}
+				case AbstractIndexManager.ACTION_REMOVE: {
+					JSPTranslatorPersister.removePersistedTranslation(resource);
+					break;
+				}
+				case AbstractIndexManager.ACTION_ADD_MOVE_FROM: {
+					JSPTranslatorPersister.movePersistedTranslation(resource, movePath);
+					break;
+				}
+				case AbstractIndexManager.ACTION_REMOVE_MOVE_TO: {
+					//do nothing, taken care of by AbstractIndexManager.ACTION_ADD_MOVE_FROM
+					break;
+				}
+			}
+		}
+		
+		//add any new JSP files to the JDT index using the JSPSearchSupport
+		if(action == AbstractIndexManager.ACTION_ADD ||
+				action == AbstractIndexManager.ACTION_ADD_MOVE_FROM) {
+		
+			IFile file = (IFile)resource; //this assumption can be made because of #isResourceToIndex
+			JSPSearchSupport ss = JSPSearchSupport.getInstance();
+			try {
+				IProject project = file.getProject();
+				if (project != null) {
+					IJavaProject jproject = JavaCore.create(project);
+					if (jproject.exists()) {
+						ss.addJspFile(file);
+					}
+				}
+			}
+			catch (Exception e) {
+				String filename = file != null ? file.getFullPath().toString() : ""; //$NON-NLS-1$
+				Logger.logException("JPSIndexManger: problem indexing:" + filename, e); //$NON-NLS-1$
+			}
+		}
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/search/JSPPathIndexer.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/search/JSPPathIndexer.java
new file mode 100644
index 0000000..9afdda9
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/search/JSPPathIndexer.java
@@ -0,0 +1,109 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.java.search;
+
+import java.util.HashMap;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceProxy;
+import org.eclipse.core.resources.IResourceProxyVisitor;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.content.IContentDescription;
+import org.eclipse.core.runtime.content.IContentType;
+import org.eclipse.jdt.core.search.IJavaSearchScope;
+import org.eclipse.jdt.core.search.SearchPattern;
+import org.eclipse.jst.jsp.core.internal.provisional.contenttype.ContentTypeIdForJSP;
+
+/**
+ * pa_TODO Still need to take into consideration:
+ * 	- focus in workspace
+ *  - search pattern
+ * 
+ * @author pavery
+ */
+public class JSPPathIndexer {
+
+	// for debugging
+	static final boolean DEBUG;
+	static {
+		String value= Platform.getDebugOption("org.eclipse.jst.jsp.core/debug/jspsearch"); //$NON-NLS-1$
+		DEBUG= value != null && value.equalsIgnoreCase("true"); //$NON-NLS-1$
+	}
+	
+	// visitor that retrieves jsp project paths for all jsp files in the workspace
+	class JSPFileVisitor implements IResourceProxyVisitor {
+		// hash map forces only one of each file
+		private HashMap fPaths = new HashMap();
+		IJavaSearchScope fScope = null;
+		SearchPattern fPattern = null;
+
+		public JSPFileVisitor(SearchPattern pattern, IJavaSearchScope scope) {
+			this.fPattern = pattern;
+			this.fScope = scope;
+		}
+
+		public boolean visit(IResourceProxy proxy) throws CoreException {
+			
+			if(JSPSearchSupport.getInstance().isCanceled())
+				return false;
+			
+			if (proxy.getType() == IResource.FILE) {
+
+				IContentType contentTypeJSP = Platform.getContentTypeManager().getContentType(ContentTypeIdForJSP.ContentTypeID_JSP);
+				// https://w3.opensource.ibm.com/bugzilla/show_bug.cgi?id=3553
+				// check this before description
+				// check name before actually getting the file (less work)
+				if(contentTypeJSP.isAssociatedWith(proxy.getName())) {
+					
+					IFile file = (IFile)proxy.requestResource();
+					IContentDescription contentDescription = file.getContentDescription();
+					String ctId = null;
+					if (contentDescription != null) {
+						ctId = contentDescription.getContentType().getId();
+					}
+					if (ContentTypeIdForJSP.ContentTypeID_JSP.equals(ctId)) {
+						if (this.fScope.encloses(proxy.requestFullPath().toString())) {
+	
+							if (DEBUG)
+								System.out.println("adding selected index path:" + file.getParent().getFullPath()); //$NON-NLS-1$
+
+							fPaths.put(file.getParent().getFullPath(), JSPSearchSupport.getInstance().computeIndexLocation(file.getParent().getFullPath()));
+						}
+					}
+				}
+				// don't search deeper for files
+				return false;
+			}
+			return true;
+		}
+
+		public IPath[] getPaths() {
+			return (IPath[]) fPaths.values().toArray(new IPath[fPaths.size()]);
+		}
+	}
+
+	public IPath[] getVisibleJspPaths(SearchPattern pattern, IJavaSearchScope scope) {
+
+		JSPFileVisitor jspFileVisitor = new JSPFileVisitor(pattern, scope);
+		try {
+			ResourcesPlugin.getWorkspace().getRoot().accept(jspFileVisitor, 0);
+		}
+		catch (CoreException e) {
+			e.printStackTrace();
+		}
+		return jspFileVisitor.getPaths();
+	}
+}
+
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/search/JSPSearchDocument.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/search/JSPSearchDocument.java
new file mode 100644
index 0000000..b78944f
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/search/JSPSearchDocument.java
@@ -0,0 +1,254 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.java.search;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import org.eclipse.core.resources.IFile;
+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.IPath;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jdt.core.search.SearchParticipant;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jst.jsp.core.internal.Logger;
+import org.eclipse.jst.jsp.core.internal.java.IJSPTranslation;
+import org.eclipse.jst.jsp.core.internal.java.JSPTranslation;
+import org.eclipse.jst.jsp.core.internal.java.JSPTranslationAdapter;
+import org.eclipse.jst.jsp.core.internal.java.JSPTranslationExtension;
+import org.eclipse.jst.jsp.core.internal.modelhandler.ModelHandlerForJSP;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.exceptions.UnsupportedCharsetExceptionWithDetail;
+import org.eclipse.wst.sse.core.internal.provisional.IModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
+
+
+/**
+ * Created with a .jsp file, but should appear to be a .java file for indexing
+ * and searching purposes. There are purposely few fields in this class, and
+ * those fields are lightweight since it's possible for many JSP search
+ * documents to exist in memory at one time (eg. after importing a project
+ * with a large number of JSP files)
+ */
+public class JSPSearchDocument {
+
+	private String fJSPPathString = null;
+	private String fCUPath = null;
+	private SearchParticipant fParticipant = null;
+	private long fLastModifiedStamp;
+	private char[] fCachedCharContents;
+	
+	/**
+	 * @param file
+	 * @param participant
+	 * @throws CoreException
+	 */
+	public JSPSearchDocument(String filePath, SearchParticipant participant) {
+		//Assert.isNotNull(filePath, "Search support for JSP requires file paths"); //$NON-NLS-1$ 
+		this.fJSPPathString = filePath;
+		this.fParticipant = participant;
+	}
+
+	public SearchParticipant getParticipant() {
+		return this.fParticipant;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.core.search.SearchDocument#getCharContents()
+	 */
+	public char[] getCharContents() {
+		
+		if(fCachedCharContents == null || isDirty()) {
+		    JSPTranslation trans = getJSPTranslation();    
+		    fCachedCharContents = trans != null ? trans.getJavaText().toCharArray() : new char[0];
+		    fCUPath = trans.getJavaPath();
+		}
+		return fCachedCharContents;
+	}
+
+	public String getJavaText() {
+		return new String(getCharContents());
+	}
+
+	private IModelManager getModelManager() {
+		return StructuredModelManager.getModelManager();
+	}
+
+	/**
+	 * It's not recommended for clients to hold on to this JSPTranslation
+	 * since it's kind of large. If possible, hold on to the
+	 * JSPSearchDocument, which is more of a lightweight proxy.
+	 * 
+	 * @return the JSPTranslation for the jsp file, or null if it's an
+	 *         unsupported file.
+	 */
+	public final JSPTranslationExtension getJSPTranslation() {
+		JSPTranslationExtension translation = null;
+		IFile jspFile = getFile();
+		if (!JSPSearchSupport.isJsp(jspFile))
+			return translation;
+
+		IStructuredModel model = null;
+		try {
+			// get existing model for read, then get document from it
+			IModelManager modelManager = getModelManager();
+			if (modelManager != null) {
+				jspFile.refreshLocal(IResource.DEPTH_ZERO, new NullProgressMonitor());
+				model = modelManager.getModelForRead(jspFile);
+			}
+			// handle unsupported
+			if (model instanceof IDOMModel) {
+				IDOMModel xmlModel = (IDOMModel)model;
+				setupAdapterFactory(xmlModel);
+				IDOMDocument doc = xmlModel.getDocument();
+				JSPTranslationAdapter adapter = (JSPTranslationAdapter) doc.getAdapterFor(IJSPTranslation.class);
+				translation = adapter.getJSPTranslation();
+			}
+		}
+		catch (IOException e) {
+			Logger.logException(e);
+		}
+		catch (CoreException e) {
+			Logger.logException(e);
+		}
+		catch (UnsupportedCharsetExceptionWithDetail e) {
+			// no need to log this. Just consider it an invalid file for our
+			// purposes.
+			// Logger.logException(e);
+		}
+		finally {
+			if (model != null)
+				model.releaseFromRead();
+		}
+		return translation;
+	}
+
+	/**
+	 * add the factory for JSPTranslationAdapter here
+	 * 
+	 * @param sm
+	 */
+	private void setupAdapterFactory(IStructuredModel sm) {
+		ModelHandlerForJSP.ensureTranslationAdapterFactory(sm);
+	}
+
+	/**
+	 * the path to the Java compilation unit
+	 * 
+	 * @see org.eclipse.jdt.core.search.SearchDocument#getPath()
+	 */
+	public String getPath() {
+	    // caching the path since it's expensive to get translation
+		// important that isDirty() check is second to cache modification stamp
+	    if(this.fCUPath == null || isDirty()) {
+	        JSPTranslation trans = getJSPTranslation();
+	        if(trans != null) {
+	            this.fCUPath = trans.getJavaPath();
+	            // save since it's expensive to calculate again later
+	            fCachedCharContents = trans.getJavaText().toCharArray();
+	        }
+	    }
+		return fCUPath;
+	}
+
+	public int getJspOffset(int javaOffset) {
+		// copied from JSPTranslation
+		int result = -1;
+		int offsetInRange = 0;
+		Position jspPos, javaPos = null;
+		JSPTranslation trans = getJSPTranslation();
+		if (trans != null) {
+			HashMap java2jspMap = trans.getJava2JspMap();
+
+			// iterate all mapped java ranges
+			Iterator it = java2jspMap.keySet().iterator();
+			while (it.hasNext()) {
+				javaPos = (Position) it.next();
+				// need to count the last position as included
+				if (!javaPos.includes(javaOffset) && !(javaPos.offset + javaPos.length == javaOffset))
+					continue;
+
+				offsetInRange = javaOffset - javaPos.offset;
+				jspPos = (Position) java2jspMap.get(javaPos);
+
+				if (jspPos != null)
+					result = jspPos.offset + offsetInRange;
+				else {
+					Logger.log(Logger.ERROR, "jspPosition was null!" + javaOffset); //$NON-NLS-1$
+				}
+				break;
+			}
+		}
+		return result;
+	}
+
+	public IFile getFile() {
+		IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+		IPath jspPath = new Path(this.fJSPPathString);
+		IFile jspFile = root.getFile(jspPath);
+		if (!jspFile.exists()) {
+			// possibly outside workspace
+			jspFile = root.getFileForLocation(jspPath);
+		}
+		return jspFile;
+	}
+
+	
+	private boolean isDirty() {
+		boolean modified = false;
+		IFile f = getFile();
+		if(f != null) {
+			long currentStamp = f.getModificationStamp();
+			if(currentStamp != fLastModifiedStamp)
+				modified = true;
+			fLastModifiedStamp = currentStamp;
+		}
+		return modified;
+	}
+	
+	public void release() {
+		// nothing to do now since JSPTranslation is created on the fly
+	}
+
+	/**
+	 * for debugging
+	 */
+	public String toString() {
+		return "[JSPSearchDocument:" + this.fJSPPathString + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jdt.core.search.SearchDocument#getEncoding()
+	 */
+	public String getEncoding() {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jdt.core.search.SearchDocument#getByteContents()
+	 */
+	public byte[] getByteContents() {
+		// TODO Auto-generated method stub
+		return null;
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/search/JSPSearchParticipant.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/search/JSPSearchParticipant.java
new file mode 100644
index 0000000..6e84b2b
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/search/JSPSearchParticipant.java
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.java.search;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jdt.core.search.IJavaSearchScope;
+import org.eclipse.jdt.core.search.SearchDocument;
+import org.eclipse.jdt.core.search.SearchEngine;
+import org.eclipse.jdt.core.search.SearchParticipant;
+import org.eclipse.jdt.core.search.SearchPattern;
+import org.eclipse.jdt.core.search.SearchRequestor;
+
+/**
+ * Integration of JSP w/ java search.
+ * 
+ * @author pavery
+ */
+public class JSPSearchParticipant extends SearchParticipant {
+
+	// for debugging
+	private static final boolean DEBUG = calculateValue();
+
+	private static boolean calculateValue() {
+		String value = Platform.getDebugOption("org.eclipse.jst.jsp.core/debug/jspsearch"); //$NON-NLS-1$
+		boolean debug = value != null && value.equalsIgnoreCase("true"); //$NON-NLS-1$
+		return debug;
+	}
+
+	/**
+	 * Important to never return null here or else Java search participation
+	 * will break.
+	 */
+	public SearchDocument getDocument(String documentPath) {
+		SearchDocument sDoc = JSPSearchSupport.getInstance().getSearchDocument(documentPath);
+
+		if (sDoc == null) {
+			// return a dummy doc here so search participation doesn't break
+			return new NullSearchDocument(documentPath);
+		}
+		return sDoc;
+	}
+
+	public String getDescription() {
+		return "JSP"; //$NON-NLS-1$
+	}
+
+	public IPath[] selectIndexes(SearchPattern pattern, IJavaSearchScope scope) {
+		JSPPathIndexer indexer = new JSPPathIndexer();
+		return indexer.getVisibleJspPaths(pattern, scope);
+	}
+
+	public void indexDocument(SearchDocument document, IPath indexPath) {
+		if (!(document instanceof JavaSearchDocumentDelegate))
+			return;
+
+		// use Java search indexing
+		SearchEngine.getDefaultSearchParticipant().indexDocument(document, indexPath);
+	}
+
+	public void locateMatches(SearchDocument[] indexMatches, SearchPattern pattern, IJavaSearchScope scope, SearchRequestor requestor, IProgressMonitor monitor) throws CoreException {
+
+		if (monitor != null && monitor.isCanceled())
+			return;
+
+		// filter out null matches
+		List filtered = new ArrayList();
+		SearchDocument match = null;
+		for (int i = 0; i < indexMatches.length; i++) {
+			if (DEBUG)
+				System.out.println("found possible matching JavaSearchDocumentDelegate: " + indexMatches[i]); //$NON-NLS-1$
+			match = indexMatches[i];
+			if (match != null) {
+				// some matches may be null, or if the index is out of date,
+				// the file may not even exist
+				if (match instanceof JavaSearchDocumentDelegate && ((JavaSearchDocumentDelegate) match).getFile().exists())
+					filtered.add(match);
+			}
+		}
+
+		indexMatches = (SearchDocument[]) filtered.toArray(new SearchDocument[filtered.size()]);
+		SearchEngine.getDefaultSearchParticipant().locateMatches(indexMatches, pattern, scope, requestor, monitor);
+	}
+
+	/**
+	 * @see org.eclipse.jdt.core.search.SearchParticipant#getDocument(org.eclipse.core.resources.IFile)
+	 */
+	public SearchDocument getDocument(IFile file) {
+		// never gets called?
+		return null;
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/search/JSPSearchScope.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/search/JSPSearchScope.java
new file mode 100644
index 0000000..9e5cd4f
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/search/JSPSearchScope.java
@@ -0,0 +1,125 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.java.search;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.core.resources.IResourceProxy;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.search.IJavaSearchScope;
+
+/**
+ * Used to constrain JSP/java search to certain paths and elements.
+ * @author pavery
+ */
+public class JSPSearchScope implements IJavaSearchScope {
+
+	private boolean fEnclosesAll = false;
+	private List fResourcePaths = null;
+	private List fJavaElements = null;
+
+	public JSPSearchScope() {
+		// empty constructor just returns true for everything
+		// everything is in scope
+		this.fEnclosesAll = true;
+		init();
+	}
+
+	public JSPSearchScope(String[] resourceStringPath) {
+		init();
+		fResourcePaths.addAll(Arrays.asList(resourceStringPath));
+	}
+
+	public JSPSearchScope(IJavaElement[] javaElement) {
+		init();
+		fJavaElements.addAll(Arrays.asList(javaElement));
+	}
+
+	private void init() {
+		this.fResourcePaths = new ArrayList();
+		this.fJavaElements = new ArrayList();
+	}
+
+	public boolean encloses(String resourcePathString) {
+
+		if (this.fEnclosesAll)
+			return true;
+		else if (enclosesPath(resourcePathString))
+			return true;
+
+		return false;
+	}
+
+	public boolean encloses(IJavaElement element) {
+
+		// pa_TOD implement
+		if (this.fEnclosesAll)
+			return true;
+
+		return true;
+	}
+
+	public boolean encloses(IResourceProxy element) {
+
+		if (this.fEnclosesAll)
+			return true;
+		else if (enclosesPath(element.requestFullPath().toOSString()))
+			return true;
+
+		return true;
+	}
+
+	public void addPath(String path) {
+		this.fResourcePaths.add(path);
+	}
+
+	public void addElement(IJavaElement element) {
+		this.fJavaElements.add(element);
+	}
+
+	private boolean enclosesPath(String possible) {
+
+		String[] paths = (String[]) fResourcePaths.toArray(new String[fResourcePaths.size()]);
+		for (int i = 0; i < paths.length; i++) {
+			if (possible.equals(paths[i]))
+				return true;
+		}
+		return false;
+	}
+
+	public String getDescription() {
+
+		return "JSPSearchScope"; //$NON-NLS-1$
+	}
+
+	public IPath[] enclosingProjectsAndJars() {
+		return (IPath[]) fResourcePaths.toArray(new IPath[fResourcePaths.size()]);
+	}
+
+	public boolean includesBinaries() {
+		return false;
+	}
+
+	public boolean includesClasspaths() {
+		return false;
+	}
+
+	public void setIncludesBinaries(boolean includesBinaries) {
+		// do nothing
+	}
+
+	public void setIncludesClasspaths(boolean includesClasspaths) {
+		// do nothing
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/search/JSPSearchSupport.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/search/JSPSearchSupport.java
new file mode 100644
index 0000000..7d1ed20
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/search/JSPSearchSupport.java
@@ -0,0 +1,595 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.java.search;
+
+import java.io.File;
+import java.util.zip.CRC32;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IWorkspaceRunnable;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.content.IContentType;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.search.IJavaSearchConstants;
+import org.eclipse.jdt.core.search.IJavaSearchScope;
+import org.eclipse.jdt.core.search.SearchDocument;
+import org.eclipse.jdt.core.search.SearchEngine;
+import org.eclipse.jdt.core.search.SearchPattern;
+import org.eclipse.jdt.core.search.SearchRequestor;
+import org.eclipse.jst.jsp.core.internal.JSPCoreMessages;
+import org.eclipse.jst.jsp.core.internal.JSPCorePlugin;
+import org.eclipse.jst.jsp.core.internal.Logger;
+import org.eclipse.jst.jsp.core.internal.java.JSP2ServletNameUtil;
+import org.eclipse.jst.jsp.core.internal.provisional.contenttype.ContentTypeIdForJSP;
+
+/**
+ * Central access to java indexing and search. All contact between JDT indexing
+ * and Searching should be done through here.
+ * 
+ * Clients should access the methods of this class via the single instance via
+ * <code>getInstance()</code>.
+ * 
+ * @author pavery
+ */
+public class JSPSearchSupport {
+
+    // for debugging
+    static final boolean DEBUG;
+    static {
+        String value = Platform.getDebugOption("org.eclipse.jst.jsp.core/debug/jspsearch"); //$NON-NLS-1$
+        DEBUG = value != null && value.equalsIgnoreCase("true"); //$NON-NLS-1$
+    }
+
+    private static JSPSearchSupport singleton = null;
+
+    private JSPSearchParticipant fParticipant = null;
+
+    private IPath fJspPluginLocation = null;
+
+    // pa_TODO may be slow (esp for indexing entire workspace)
+    private final CRC32 fChecksumCalculator = new CRC32();
+
+    /** main cancel montior for all search support */
+    private final IProgressMonitor fMonitor = new NullProgressMonitor();
+
+    private JSPSearchSupport() {
+        // force use of single instance
+    }
+
+    /**
+     * This operation ensures that the live resource's search markers show up in
+     * the open editor. It also allows the ability to pass in a ProgressMonitor
+     */
+    private class SearchJob extends Job implements IJavaSearchConstants {
+
+        String fSearchText = ""; //$NON-NLS-1$
+
+        IJavaSearchScope fScope = null;
+
+        int fSearchFor = FIELD;
+
+        int fLimitTo = ALL_OCCURRENCES;
+
+        int fMatchMode = SearchPattern.R_PATTERN_MATCH;
+
+        SearchRequestor fRequestor = null;
+
+        IJavaElement fElement = null;
+
+        // constructor w/ java element
+        public SearchJob(IJavaElement element, IJavaSearchScope scope, SearchRequestor requestor) {
+
+            super(JSPCoreMessages.JSP_Search + element.getElementName());
+            this.fElement = element;
+            this.fScope = scope;
+            this.fRequestor = requestor;
+        }
+
+        // constructor w/ search text
+        public SearchJob(String searchText, IJavaSearchScope scope, int searchFor, int limitTo, int matchMode, boolean isCaseSensitive, SearchRequestor requestor) {
+
+            super(JSPCoreMessages.JSP_Search + searchText);
+            this.fSearchText = searchText;
+            this.fScope = scope;
+            this.fSearchFor = searchFor;
+            this.fLimitTo = limitTo;
+            this.fMatchMode = matchMode;
+            this.fRequestor = requestor;
+        }
+
+        public IStatus run(IProgressMonitor jobMonitor) {
+
+            if (jobMonitor != null && jobMonitor.isCanceled())
+                return Status.CANCEL_STATUS;
+            if (JSPSearchSupport.getInstance().isCanceled())
+                return Status.CANCEL_STATUS;
+
+            SearchPattern javaSearchPattern = null;
+            // if an element is available, use that to create search pattern
+            // (eg. LocalVariable)
+            // otherwise use the text and other paramters
+            if (this.fElement != null)
+                javaSearchPattern = SearchPattern.createPattern(this.fElement, this.fLimitTo);
+            else
+                javaSearchPattern = SearchPattern.createPattern(this.fSearchText, this.fSearchFor, this.fLimitTo, this.fMatchMode);
+
+            if (javaSearchPattern != null) {
+                JSPSearchParticipant[] participants = { getSearchParticipant() };
+                SearchEngine engine = new SearchEngine();
+                try {
+                    if (jobMonitor != null)
+                        jobMonitor.beginTask("", IProgressMonitor.UNKNOWN); //$NON-NLS-1$
+                    engine.search(javaSearchPattern, participants, this.fScope, this.fRequestor, jobMonitor);
+                } catch (CoreException e) {
+                    if (DEBUG)
+                        Logger.logException(e);
+                }
+                // non-CoreExceptions will permanently stall the Worker thread
+                catch (Exception e) {
+                    if (DEBUG)
+                        Logger.logException(e);
+                } finally {
+                    if (jobMonitor != null)
+                        jobMonitor.done();
+                }
+            }
+            return Status.OK_STATUS;
+        }
+    }
+
+    // end SearchJob
+    /**
+     * Runnable forces caller to wait until finished (as opposed to using a Job)
+     */
+    private class SearchRunnable implements IWorkspaceRunnable, IJavaSearchConstants {
+
+        String fSearchText = ""; //$NON-NLS-1$
+
+        IJavaSearchScope fScope = null;
+
+        int fSearchFor = FIELD;
+
+        int fLimitTo = ALL_OCCURRENCES;
+
+        int fMatchMode = SearchPattern.R_PATTERN_MATCH;
+
+        SearchRequestor fRequestor = null;
+
+        IJavaElement fElement = null;
+
+        // constructor w/ java element
+        public SearchRunnable(IJavaElement element, IJavaSearchScope scope, SearchRequestor requestor) {
+
+            this.fElement = element;
+            this.fScope = scope;
+            this.fRequestor = requestor;
+        }
+
+        public void run(IProgressMonitor monitor) throws CoreException {
+
+            if (monitor != null && monitor.isCanceled())
+                return;
+            if (JSPSearchSupport.getInstance().isCanceled())
+                return;
+
+            SearchPattern javaSearchPattern = null;
+            // if an element is available, use that to create search pattern
+            // (eg. LocalVariable)
+            // otherwise use the text and other paramters
+            if (this.fElement != null)
+                javaSearchPattern = SearchPattern.createPattern(this.fElement, fLimitTo);
+            else
+                javaSearchPattern = SearchPattern.createPattern(fSearchText, fSearchFor, fLimitTo, fMatchMode);
+
+            if (javaSearchPattern != null) {
+                JSPSearchParticipant[] participants = { getSearchParticipant() };
+                SearchEngine engine = new SearchEngine();
+                try {
+                    if (monitor != null)
+                        monitor.beginTask("", 0); //$NON-NLS-1$
+                    engine.search(javaSearchPattern, participants, fScope, fRequestor, monitor);
+                } catch (CoreException e) {
+                    Logger.logException(e);
+                    //throw e;
+                }
+                // non-CoreExceptions will permanently stall the Worker thread
+                catch (Exception e) {
+                    Logger.logException(e);
+                } finally {
+                    if (monitor != null)
+                        monitor.done();
+                }
+            }
+        }
+    }
+
+    // end SearchRunnable
+
+    /**
+     * Clients should access the methods of this class via the single instance
+     * via getInstance()
+     * 
+     * @return
+     */
+    public synchronized static JSPSearchSupport getInstance() {
+
+        if (singleton == null)
+            singleton = new JSPSearchSupport();
+        return singleton;
+    }
+
+    /**
+     * Utility method to check if a file is a jsp file (since this is done
+     * frequently)
+     */
+    public static boolean isJsp(IFile file) {
+    	// (pa) 20051025 removing deep content type check
+    	// because this method is called frequently
+    	// and IO is expensive
+        boolean isJsp = false;
+
+        if (file != null && file.exists()) {
+        	
+            IContentType contentTypeJSP = Platform.getContentTypeManager().getContentType(ContentTypeIdForJSP.ContentTypeID_JSP);
+            // check this before description, it's less expensive
+            if (contentTypeJSP.isAssociatedWith(file.getName())) {
+            	isJsp = true;
+            }
+        }
+
+        return isJsp;
+    }
+
+    /**
+     * schedules a search document representing this JSP file for indexing (by
+     * the java indexer)
+     * 
+     * @param file
+     *            the JSP file
+     * @return true if indexing was successful, false otherwise
+     * @throws CoreException
+     */
+    public SearchDocument addJspFile(IFile file) {
+        if (JSPSearchSupport.getInstance().isCanceled() || !file.isAccessible()) {
+            return null;
+        }
+
+        if (DEBUG)
+            System.out.println("adding JSP file:" + file.getFullPath()); //$NON-NLS-1$
+
+        // create
+        SearchDocument delegate = createSearchDocument(file);
+        // null if not a jsp file
+        if (delegate != null) {
+            try {
+                getSearchParticipant().scheduleDocumentIndexing(delegate, computeIndexLocation(file.getParent().getFullPath()));
+            } catch (Exception e) {
+                // ensure that failure here doesn't keep other documents from
+                // being indexed
+                // if peformed in a batch call (like JSPIndexManager)
+                if (DEBUG)
+                    e.printStackTrace();
+            }
+        }
+
+        if (DEBUG)
+            System.out.println("scheduled" + delegate + "for indexing"); //$NON-NLS-1$ //$NON-NLS-2$
+
+        return delegate;
+    }
+    
+    /**
+     * Perform a java search w/ the given parameters. Runs in a background Job
+     * (results may still come in after this method call)
+     * 
+     * @param searchText
+     *            the string of text to search on
+     * @param searchFor
+     *            IJavaSearchConstants.TYPE, METHOD, FIELD, PACKAGE, etc...
+     * @param limitTo
+     *            IJavaSearchConstants.DECLARATIONS,
+     *            IJavaSearchConstants.REFERENCES,
+     *            IJavaSearchConstants.IMPLEMENTORS, or
+     *            IJavaSearchConstants.ALL_OCCURRENCES
+     * @param matchMode
+     *            allow * wildcards or not
+     * @param isCaseSensitive
+     * @param requestor
+     *            passed in to accept search matches (and do "something" with
+     *            them)
+     * 
+     * @deprecated use {@link #search(String, IJavaSearchScope, int, int, int, boolean, SearchRequestor, IProgressMonitor)}
+     */
+    public void search(String searchText, IJavaSearchScope scope, int searchFor, int limitTo, int matchMode, boolean isCaseSensitive, SearchRequestor requestor) {
+    	this.search(searchText, scope, searchFor, limitTo, matchMode, isCaseSensitive,
+    			requestor, new NullProgressMonitor());
+    }
+
+    /**
+     * Search for an IJavaElement, constrained by the given parameters. Runs in
+     * a background Job (results may still come in after this method call)
+     * 
+     * @param element
+     * @param scope
+     * @param requestor
+     * 
+     * @deprecated use {@link #search(IJavaElement, IJavaSearchScope, SearchRequestor, IProgressMonitor)}
+     */
+    public void search(IJavaElement element, IJavaSearchScope scope, SearchRequestor requestor) {
+    	this.search(element, scope, requestor, new NullProgressMonitor());
+    }
+
+    /**
+     * Search for an IJavaElement, constrained by the given parameters. Runs in
+     * an IWorkspace runnable (results will be reported by the end of this
+     * method)
+     * 
+     * @param element
+     * @param scope
+     * @param requestor
+     * 
+     * @deprecated should use {@link #search(IJavaElement, IJavaSearchScope, SearchRequestor, IProgressMonitor)}
+     * so that operation can be canceled
+     */
+    public void searchRunnable(IJavaElement element, IJavaSearchScope scope, SearchRequestor requestor) {
+    	this.searchRunnable(element, scope, requestor, new NullProgressMonitor());
+    }
+    
+    /**
+     * Perform a java search w/ the given parameters. Runs in a background Job
+     * (results may still come in after this method call)
+     * 
+     * @param searchText
+     *            the string of text to search on
+     * @param searchFor
+     *            IJavaSearchConstants.TYPE, METHOD, FIELD, PACKAGE, etc...
+     * @param limitTo
+     *            IJavaSearchConstants.DECLARATIONS,
+     *            IJavaSearchConstants.REFERENCES,
+     *            IJavaSearchConstants.IMPLEMENTORS, or
+     *            IJavaSearchConstants.ALL_OCCURRENCES
+     * @param matchMode
+     *            allow * wildcards or not
+     * @param isCaseSensitive
+     * @param requestor
+     *            passed in to accept search matches (and do "something" with
+     *            them)
+     */
+    public void search(String searchText, IJavaSearchScope scope, int searchFor, int
+    		limitTo, int matchMode, boolean isCaseSensitive, SearchRequestor requestor,
+    		IProgressMonitor monitor) {
+
+    	//wait for the index
+		JSPIndexManager.getDefault().waitForConsistent(monitor);
+
+        SearchJob job = new SearchJob(searchText, scope, searchFor, limitTo, matchMode, isCaseSensitive, requestor);
+        setCanceled(false);
+        job.setUser(true);
+        // https://w3.opensource.ibm.com/bugzilla/show_bug.cgi?id=5032
+        // pops up user operation blocked dialog if you perform a long search,
+        // then open a file because it locks the workspace
+        //job.setRule(ResourcesPlugin.getWorkspace().getRoot());
+        job.schedule();
+    }
+
+    /**
+     * Search for an IJavaElement, constrained by the given parameters. Runs in
+     * a background Job (results may still come in after this method call)
+     * 
+     * @param element
+     * @param scope
+     * @param requestor
+     */
+    public void search(IJavaElement element, IJavaSearchScope scope, SearchRequestor requestor,
+    		IProgressMonitor monitor) {
+
+    	//wait for the index
+		JSPIndexManager.getDefault().waitForConsistent(monitor);
+    	
+        SearchJob job = new SearchJob(element, scope, requestor);
+        setCanceled(false);
+        job.setUser(true);
+        // https://w3.opensource.ibm.com/bugzilla/show_bug.cgi?id=5032
+        //job.setRule(ResourcesPlugin.getWorkspace().getRoot());
+        job.schedule();
+    }
+
+    /**
+     * Search for an IJavaElement, constrained by the given parameters. Runs in
+     * an IWorkspace runnable (results will be reported by the end of this
+     * method)
+     * 
+     * @param element
+     * @param scope
+     * @param requestor
+     */
+    public void searchRunnable(IJavaElement element, IJavaSearchScope scope,
+    		SearchRequestor requestor, IProgressMonitor monitor) {
+    	
+    	//wait for the index
+		JSPIndexManager.getDefault().waitForConsistent(monitor);
+
+        SearchRunnable searchRunnable = new SearchRunnable(element, scope, requestor);
+        try {
+            setCanceled(false);
+            ResourcesPlugin.getWorkspace().run(searchRunnable, JSPSearchSupport.getInstance().getProgressMonitor());
+        } catch (CoreException e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * @param jspFile
+     * @return SearchDocument if the file is not null, exists, and is a JSP
+     *         file, otherwise null.
+     */
+    private SearchDocument createSearchDocument(IFile jspFile) {
+
+        JavaSearchDocumentDelegate delegate = null;
+        if (jspFile != null && jspFile.exists() && isJsp(jspFile)) {
+
+            delegate = new JavaSearchDocumentDelegate(new JSPSearchDocument(jspFile.getFullPath().toString(), getSearchParticipant()));
+        }
+        return delegate;
+
+    }
+
+    /**
+     * Centralized place to access JSPSearchDocuments (used by
+     * JSPSearchParticipant and JSPSearchRequestor)
+     * 
+     * @param searchDocPath
+     * @param doc
+     * @return the JSPSearchDocument or null if one is not found
+     */
+    public SearchDocument getSearchDocument(String searchDocPath) {
+         
+        SearchDocument delegate = null;
+        IFile f = fileForCUPath(searchDocPath);
+        if (f != null) {
+            delegate = createSearchDocument(f);
+        } else {
+            // handle failure case... (file deleted maybe?)
+        }
+        return delegate;
+    }
+
+    /**
+     * Unmangles the searchDocPath and returns the corresponding JSP file.
+     * 
+     * @param searchDocPath
+     */
+    private IFile fileForCUPath(String searchDocPath) {
+    
+        String[] split = searchDocPath.split("/"); //$NON-NLS-1$
+        String classname = split[split.length - 1];
+
+        // ignore anything but .java matches (like .class binary matches)
+        if(!searchDocPath.endsWith(".java")) { //$NON-NLS-1$
+            return null;
+        }
+
+        String filePath = JSP2ServletNameUtil.unmangle(classname);
+       
+        // try absolute path
+        IFile f = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(new Path(filePath));
+        // workspace relative then
+        if(f == null) {
+            // https://bugs.eclipse.org/bugs/show_bug.cgi?id=86009
+            // must have a project name as well
+            // which would mean >= 2 path segments
+            IPath path = new Path(filePath);
+            if(path.segmentCount() >= 2) {
+                f = ResourcesPlugin.getWorkspace().getRoot().getFile(path);
+            }
+        }
+        return f;
+    }
+
+    JSPSearchParticipant getSearchParticipant() {
+
+        if (this.fParticipant == null)
+            this.fParticipant = new JSPSearchParticipant();
+        return this.fParticipant;
+    }
+
+    // This is called from JSPPathIndexer
+    // pa_TODO
+    //how can we make sure participant indexLocations are updated at startup?
+    public final IPath computeIndexLocation(IPath containerPath) {
+
+        IPath indexLocation = null;
+        // we don't want to inadvertently use a JDT Index
+        // we want to be sure to use the Index from the JSP location
+        //Object obj = indexLocations.get(containerPath);
+        //if (obj != null) {
+        //    indexLocation = (String) obj;
+        //} else {
+            // create index entry
+            String pathString = containerPath.toOSString();
+            this.fChecksumCalculator.reset();
+            this.fChecksumCalculator.update(pathString.getBytes());
+            String fileName = Long.toString(this.fChecksumCalculator.getValue()) + ".index"; //$NON-NLS-1$
+            // this is the only difference from
+            // IndexManager#computeIndexLocation(...)
+            indexLocation = getModelJspPluginWorkingLocation().append(fileName);
+        //}
+        return indexLocation;
+    }
+
+    // copied from JDT IndexManager
+    public IPath getModelJspPluginWorkingLocation() {
+
+        if (this.fJspPluginLocation != null)
+            return this.fJspPluginLocation;
+
+        // Append the folder name "jspsearch" to keep the state location area cleaner
+        IPath stateLocation = JSPCorePlugin.getDefault().getStateLocation().append("jspsearch"); //$NON-NLS-1$
+
+        // pa_TODO workaround for
+        // https://bugs.eclipse.org/bugs/show_bug.cgi?id=62267
+        // copied from IndexManager
+        String device = stateLocation.getDevice();
+        if (device != null && device.charAt(0) == '/')
+            stateLocation = stateLocation.setDevice(device.substring(1));
+
+        // ensure that it exists on disk
+        File folder = new File(stateLocation.toOSString());
+		if (!folder.isDirectory()) {
+			try {
+				folder.mkdir();
+			}
+			catch (SecurityException e) {
+			}
+		}
+
+        return this.fJspPluginLocation = stateLocation;
+    }
+
+    /**
+     * JSP Indexing and Search jobs check this
+     * 
+     * @return
+     */
+    public synchronized final void setCanceled(boolean cancel) {
+    	//System.out.println("search support monitor" + fMonitor);
+        fMonitor.setCanceled(cancel);
+    }
+
+    /**
+     * JSP Indexing and Search jobs check this
+     * 
+     * @return
+     */
+    public synchronized final boolean isCanceled() {
+
+        return fMonitor.isCanceled();
+    }
+
+    /**
+     * JSP Indexing and Search jobs check this
+     * 
+     * @return
+     */
+    public final IProgressMonitor getProgressMonitor() {
+
+        return this.fMonitor;
+    }
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/search/JavaSearchDocumentDelegate.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/search/JavaSearchDocumentDelegate.java
new file mode 100644
index 0000000..2e07148
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/search/JavaSearchDocumentDelegate.java
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.java.search;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.jdt.core.search.SearchDocument;
+import org.eclipse.jst.jsp.core.internal.java.JSPTranslationExtension;
+
+
+/**
+ * Wrapper method to set getPath() path to be the path of the compilation unit 
+ * for the jsp file. (since it's a final method, it needs to be set via constructor)
+ * 
+ * @author pavery
+ */
+public class JavaSearchDocumentDelegate extends SearchDocument {
+	
+	private JSPSearchDocument fJSPSearchDoc = null;
+	
+	public JavaSearchDocumentDelegate(JSPSearchDocument jspSearchDoc) {
+		
+		super(jspSearchDoc.getPath(), jspSearchDoc.getParticipant());
+		this.fJSPSearchDoc = jspSearchDoc;
+	}
+
+	public byte[] getByteContents() {
+		
+		return this.fJSPSearchDoc.getByteContents();
+	}
+
+	public char[] getCharContents() {
+		
+		return this.fJSPSearchDoc.getCharContents();
+	}
+	
+	public String getJavaText() {
+		return this.fJSPSearchDoc.getJavaText();
+	}
+
+	public String getEncoding() {
+		
+		return this.fJSPSearchDoc.getEncoding();
+	}
+	
+	public IFile getFile() {
+		
+		return this.fJSPSearchDoc.getFile();
+	}
+	
+	public JSPTranslationExtension getJspTranslation() {
+		
+		return this.fJSPSearchDoc.getJSPTranslation();
+	}
+	
+	public int getJspOffset(int javaOffset) {
+		
+		return this.fJSPSearchDoc.getJspOffset(javaOffset);
+	}
+	
+	public void release() {
+		this.fJSPSearchDoc.release();
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/search/NullSearchDocument.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/search/NullSearchDocument.java
new file mode 100644
index 0000000..ad99a10
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/search/NullSearchDocument.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.java.search;
+
+import org.eclipse.jdt.core.search.SearchDocument;
+import org.eclipse.jst.jsp.core.internal.java.JSPTranslator;
+
+
+
+/**
+ * An empty servlet, safe for Java search participation
+ * 
+ * @author pavery
+ */
+public class NullSearchDocument extends SearchDocument {
+	
+	StringBuffer fEmptyServletBuffer = null;
+	
+	public NullSearchDocument(String documentPath) {
+		super(documentPath, new JSPSearchParticipant()); //$NON-NLS-1$
+		this.fEmptyServletBuffer = new JSPTranslator().getEmptyTranslation();
+	}
+	
+	public byte[] getByteContents() {
+		return this.fEmptyServletBuffer.toString().getBytes();
+	}
+	
+	public char[] getCharContents() {
+		return this.fEmptyServletBuffer.toString().toCharArray();
+	}
+	
+	public String getEncoding() {
+		return null;
+	}
+
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelhandler/EmbeddedTypeStateData.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelhandler/EmbeddedTypeStateData.java
new file mode 100644
index 0000000..9ee8a41
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelhandler/EmbeddedTypeStateData.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.modelhandler;
+
+
+
+import org.eclipse.wst.sse.core.internal.ltk.modelhandler.EmbeddedTypeHandler;
+
+/**
+ * This class is only for remembering old and new embedded handlers, 
+ * in the event a re-init is needed.
+ */
+public class EmbeddedTypeStateData {
+
+
+	EmbeddedTypeHandler oldHandler;
+	EmbeddedTypeHandler newHandler;
+
+	public EmbeddedTypeStateData(EmbeddedTypeHandler oldHandler, EmbeddedTypeHandler newHandler) {
+		this.oldHandler = oldHandler;
+		this.newHandler = newHandler;
+	}
+
+	public EmbeddedTypeHandler getNewHandler() {
+		return newHandler;
+	}
+
+	public EmbeddedTypeHandler getOldHandler() {
+		return oldHandler;
+	}
+
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelhandler/JSPModelLoader.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelhandler/JSPModelLoader.java
new file mode 100644
index 0000000..23b90ab
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelhandler/JSPModelLoader.java
@@ -0,0 +1,647 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.modelhandler;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.content.IContentDescription;
+import org.eclipse.core.runtime.content.IContentType;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentPartitioner;
+import org.eclipse.jst.jsp.core.internal.Logger;
+import org.eclipse.jst.jsp.core.internal.contentproperties.JSPFContentProperties;
+import org.eclipse.jst.jsp.core.internal.document.PageDirectiveAdapter;
+import org.eclipse.jst.jsp.core.internal.document.PageDirectiveAdapterFactory;
+import org.eclipse.jst.jsp.core.internal.document.PageDirectiveWatcherFactory;
+import org.eclipse.jst.jsp.core.internal.domdocument.DOMModelForJSP;
+import org.eclipse.jst.jsp.core.internal.encoding.IJSPHeadContentDetector;
+import org.eclipse.jst.jsp.core.internal.encoding.JSPDocumentHeadContentDetector;
+import org.eclipse.jst.jsp.core.internal.encoding.JSPDocumentLoader;
+import org.eclipse.jst.jsp.core.internal.modelquery.JSPModelQueryAdapterImpl;
+import org.eclipse.jst.jsp.core.internal.modelquery.ModelQueryAdapterFactoryForJSP;
+import org.eclipse.jst.jsp.core.internal.parser.JSPReParser;
+import org.eclipse.jst.jsp.core.internal.parser.JSPSourceParser;
+import org.eclipse.jst.jsp.core.internal.provisional.contenttype.ContentTypeIdForJSP;
+import org.eclipse.jst.jsp.core.internal.provisional.contenttype.IContentDescriptionForJSP;
+import org.eclipse.jst.jsp.core.internal.text.StructuredTextPartitionerForJSP;
+import org.eclipse.wst.html.core.internal.provisional.contenttype.ContentTypeFamilyForHTML;
+import org.eclipse.wst.html.core.internal.provisional.contenttype.ContentTypeIdForHTML;
+import org.eclipse.wst.html.core.internal.text.StructuredTextPartitionerForHTML;
+import org.eclipse.wst.sse.core.internal.PropagatingAdapter;
+import org.eclipse.wst.sse.core.internal.document.DocumentReader;
+import org.eclipse.wst.sse.core.internal.document.IDocumentLoader;
+import org.eclipse.wst.sse.core.internal.document.StructuredDocumentFactory;
+import org.eclipse.wst.sse.core.internal.ltk.modelhandler.EmbeddedTypeHandler;
+import org.eclipse.wst.sse.core.internal.ltk.parser.RegionParser;
+import org.eclipse.wst.sse.core.internal.model.AbstractModelLoader;
+import org.eclipse.wst.sse.core.internal.modelhandler.EmbeddedTypeRegistry;
+import org.eclipse.wst.sse.core.internal.modelhandler.EmbeddedTypeRegistryImpl;
+import org.eclipse.wst.sse.core.internal.provisional.IModelLoader;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapterFactory;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+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.text.BasicStructuredDocument;
+import org.eclipse.wst.sse.core.internal.util.Assert;
+import org.eclipse.wst.sse.core.internal.util.Debug;
+import org.eclipse.wst.xml.core.internal.DebugAdapterFactory;
+import org.eclipse.wst.xml.core.internal.document.DOMModelImpl;
+import org.eclipse.wst.xml.core.internal.propagate.PropagatingAdapterFactoryImpl;
+import org.eclipse.wst.xml.core.internal.provisional.contenttype.ContentTypeIdForXML;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
+import org.eclipse.wst.xml.core.internal.ssemodelquery.ModelQueryAdapter;
+import org.eclipse.wst.xml.core.internal.text.rules.StructuredTextPartitionerForXML;
+import org.w3c.dom.Document;
+
+public class JSPModelLoader extends AbstractModelLoader {
+	protected final int MAX_BUFFERED_SIZE_FOR_RESET_MARK = 200000;
+
+	/**
+	 * DMW - Note: I think the embeddedTypeRegistry in IModelManager can be
+	 * removed
+	 */
+	private EmbeddedTypeRegistry embeddedContentTypeRegistry;
+	private final static String DEFAULT_MIME_TYPE = "text/html"; //$NON-NLS-1$
+	private final static String DEFAULT_LANGUAGE = "java"; //$NON-NLS-1$
+
+	public JSPModelLoader() {
+		super();
+	}
+
+	/**
+	 * Gets the embeddedContentTypeRegistry.
+	 * 
+	 * @return Returns a EmbeddedContentTypeRegistry
+	 */
+	private EmbeddedTypeRegistry getEmbeddedContentTypeRegistry() {
+		if (embeddedContentTypeRegistry == null) {
+			embeddedContentTypeRegistry = EmbeddedTypeRegistryImpl.getInstance();
+		}
+		return embeddedContentTypeRegistry;
+	}
+
+	public IStructuredModel newModel() {
+		DOMModelForJSP model = new DOMModelForJSP();
+		return model;
+	}
+
+	/**
+	 * For JSP files, text/html is the default content type. This may want
+	 * this different for types like jsv (jsp for voice xml) For now, hard
+	 * code to new instance. In future, should get instance from registry.
+	 * 
+	 * Specification cites HTML as the default contentType.
+	 */
+	private EmbeddedTypeHandler getJSPDefaultEmbeddedType(IStructuredModel model) {
+		EmbeddedTypeRegistry reg = getEmbeddedContentTypeRegistry();
+
+		String mimeType = null;
+		// default embedded type for fragments
+		if (model != null) {
+			IFile file = getFile(model);
+			if (file != null) {
+				mimeType = JSPFContentProperties.getProperty(JSPFContentProperties.JSPCONTENTTYPE, file, true);
+			}
+		}
+		mimeType = mimeType == null ? getDefaultMimeType() : mimeType;
+		return reg.getTypeFor(mimeType);
+	}
+
+	/**
+	 * Method getDefaultMimeType.
+	 * 
+	 * @return String
+	 */
+	private String getDefaultMimeType() {
+		return DEFAULT_MIME_TYPE;
+	}
+
+	/**
+	 * This method must return a new instance of IStructuredDocument, that has
+	 * been initialized with appropriate parser. For many loaders, the
+	 * (default) parser used is known for any input. For others, the correct
+	 * parser (and its initialization) is normall dependent on the content of
+	 * the file. This no-argument method should assume "empty input" and would
+	 * therefore return the default parser for the default contentType.
+	 * 
+	 * If the parser is to handle tag libraries, it must have a TaglibSupport
+	 * object with a valid URIResolver and this IStructuredDocument attached
+	 * to it before the contents are set on the IStructuredDocument.
+	 */
+	public IStructuredDocument newStructuredDocument() {
+		IStructuredDocument structuredDocument = StructuredDocumentFactory.getNewStructuredDocumentInstance(getParser());
+		((BasicStructuredDocument) structuredDocument).setReParser(new JSPReParser());
+		// structuredDocument.setDocumentPartitioner(new
+		// JSPJavaDocumentPartioner());
+		// even though this is an "empty model" ... we want it to have at
+		// least the
+		// default embeddeded content type handler
+		EmbeddedTypeHandler embeddedType = getJSPDefaultEmbeddedType(null);
+		embeddedType.initializeParser(structuredDocument.getParser());
+		return structuredDocument;
+	}
+
+	public RegionParser getParser() {
+		// remember, the Loader
+		// will need to finish initialization of parser
+		// based on "embedded content"
+		return new JSPSourceParser();
+	}
+
+	protected void preLoadAdapt(IStructuredModel structuredModel) {
+		super.preLoadAdapt(structuredModel);
+		IDOMModel domModel = (IDOMModel) structuredModel;
+		//
+		// document must have already been set for this to
+		// work.
+		Document document = domModel.getDocument();
+		Assert.isNotNull(document);
+		// if there is a model in the adapter, this will adapt it to
+		// first node. After that the PropagatingAdater spreads over the
+		// children being
+		// created. Each time that happends, a side effect is to
+		// also "spread" sprecific registered adapters,
+		// they two can propigate is needed.
+		// This 'get' causes first to be be attached.
+		PropagatingAdapter propagatingAdapter = (PropagatingAdapter) ((INodeNotifier) document).getAdapterFor(PropagatingAdapter.class);
+		// may make this easier to use in futue
+		propagatingAdapter.addAdaptOnCreateFactory(new PageDirectiveWatcherFactory());
+		if (Debug.debugNotificationAndEvents) {
+			propagatingAdapter.addAdaptOnCreateFactory(new DebugAdapterFactory());
+		}
+		// For JSPs, the ModelQueryAdapter must be "attached" to the document
+		// before content is set in the model, so taglib initization can
+		// take place.
+		((INodeNotifier) document).getAdapterFor(ModelQueryAdapter.class);
+		//
+
+	}
+
+	/**
+	 * This method must return those factories which must be attached to the
+	 * structuredModel before content is applied.
+	 */
+	public List getAdapterFactories() {
+		List result = new ArrayList();
+		INodeAdapterFactory factory = null;
+		//
+		factory = new ModelQueryAdapterFactoryForJSP();
+		result.add(factory);
+		factory = new PropagatingAdapterFactoryImpl();
+		result.add(factory);
+		factory = new PageDirectiveAdapterFactory();
+		result.add(factory);
+
+		return result;
+	}
+
+
+	public IJSPHeadContentDetector getHeadParser() {
+		return new JSPDocumentHeadContentDetector();
+	}
+
+	private IContentDescription getContentDescription(IDocument doc) {
+		if (doc == null)
+			return null;
+		DocumentReader reader = new DocumentReader(doc);
+		return getContentDescription(reader);
+	}
+
+	/**
+	 * Returns content description for an input stream Assumes it's JSP
+	 * content. Closes the input stream when finished.
+	 * 
+	 * @param reader
+	 * @return the IContentDescription for in, or null if in is null
+	 */
+	private IContentDescription getContentDescription(Reader reader) {
+
+		if (reader == null)
+			return null;
+
+		IContentDescription desc = null;
+		try {
+
+			IContentType contentTypeJSP = Platform.getContentTypeManager().getContentType(ContentTypeIdForJSP.ContentTypeID_JSP);
+			desc = contentTypeJSP.getDescriptionFor(reader, IContentDescription.ALL);
+		}
+		catch (IOException e) {
+			Logger.logException(e);
+		}
+		finally {
+			if (reader != null) {
+				try {
+					reader.close();
+				}
+				catch (IOException e) {
+					Logger.logException(e);
+				}
+			}
+		}
+		return desc;
+	}
+
+	private IFile getFile(IStructuredModel model) {
+		if (model != null) {
+			String location = model.getBaseLocation();
+			if (location != null) {
+				IPath path = new Path(location);
+				if (!path.toFile().exists() && path.segmentCount() > 1) {
+					return ResourcesPlugin.getWorkspace().getRoot().getFile(path);
+				}
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * Method getLanguage.
+	 * 
+	 * @param model
+	 * @return String
+	 */
+	private String getLanguage(IStructuredModel model) {
+		String result = null;
+		// first check the model (document itself) to see if contains
+		result = getLanguageFromStructuredDocument(model.getStructuredDocument());
+		// Note: if model contains an unsupported
+		// language, we'll even return it,
+		// since who knows what future holds.
+
+		// get default language specified in properties page
+		IFile file = getFile(model);
+		result = JSPFContentProperties.getProperty(JSPFContentProperties.JSPLANGUAGE, file, true);
+
+		// always return something
+		if (result == null) {
+			result = DEFAULT_LANGUAGE;
+		}
+		return result;
+	}
+
+	/**
+	 * Method getLanguageFromStructuredDocument.
+	 * 
+	 * @param structuredDocument
+	 * @return String
+	 */
+	private String getLanguageFromStructuredDocument(IStructuredDocument structuredDocument) {
+		if (structuredDocument == null)
+			return null;
+		String result = null;
+		// bascially same algorithm as get encoding or
+		// get content type from structuredDocument.
+		IJSPHeadContentDetector localHeadParser = getHeadParser();
+		// we can be assured that its already been
+		// parsed. If not call parseHeaderForPageDirective()
+		// before calling getLanguage;
+		localHeadParser.set(structuredDocument);
+		try {
+			result = localHeadParser.getLanguage();
+		}
+		catch (IOException e) {
+			// impossible
+			// TODO need to reconsider design to avoid
+			throw new Error(e);
+		}
+		return result;
+	}
+
+	/**
+	 * This is "reinitialize" since there should always be at least the
+	 * default one assigned, before we start checking the stream
+	 */
+	private void reInitializeEmbeddedType(IStructuredModel model, EmbeddedTypeHandler oldEmbeddedContentType, EmbeddedTypeHandler newEmbeddedContentType) {
+		// check program logic
+		Assert.isNotNull(oldEmbeddedContentType, "Program error: invalid call during model initialization"); //$NON-NLS-1$
+		// once we know the embedded content type, we need to set it in the
+		// PageDirectiveAdapter ... the order of initialization is
+		// critical here, the doc must have been created, but its contents not
+		// set yet,
+		// and all factories must have been set up also.
+		IDOMModel domModel = (IDOMModel) model;
+		IStructuredDocument structuredDocument = model.getStructuredDocument();
+		IDOMDocument document = domModel.getDocument();
+		PageDirectiveAdapter pageDirectiveAdapter = (PageDirectiveAdapter) document.getExistingAdapter(PageDirectiveAdapter.class);
+		// ==> // PropagatingAdapter propagatingAdapter = (PropagatingAdapter)
+		// ((INodeNotifier)
+		// document).getExistingAdapter(PropagatingAdapter.class);
+		// ==> // ModelQueryAdapter modelQueryAdapter = (ModelQueryAdapter)
+		// ((INodeNotifier)
+		// document).getExistingAdapter(ModelQueryAdapter.class);
+		oldEmbeddedContentType.uninitializeFactoryRegistry(model.getFactoryRegistry());
+		oldEmbeddedContentType.uninitializeParser(structuredDocument.getParser());
+		// since 'document' is not recreated in this
+		// reinit path, we need to remove all adapters,
+		// except for the propagated adapters (including page
+		// directive adapter, and model query adapter).
+		// to accomplish this, we'll just remove all, then
+		// add back with a call to pre-load adapt.
+		// let clients decide to unload adapters from document
+		// Collection oldAdapters = document.getAdapters();
+		// Iterator oldAdaptersIterator = oldAdapters.iterator();
+		// while (oldAdaptersIterator.hasNext()) {
+		// INodeAdapter oldAdapter = (INodeAdapter)
+		// oldAdaptersIterator.next();
+		// if (oldAdapter != pageDirectiveAdapter && oldAdapter !=
+		// propagatingAdapter && oldAdapter != modelQueryAdapter) {
+		// // DO NOT remove directly!
+		// // can change contents while in notifity loop!
+		// //oldAdaptersIterator.remove();
+		// document.removeAdapter(oldAdapter);
+		// }
+		// }
+		// DMW: I believe something like the following is needed,
+		// since releases cached adapters
+		// if (document instanceof DocumentImpl) {
+		// ((DocumentImpl) document).releaseDocumentType();
+		// ((DocumentImpl) document).releaseStyleSheets();
+		// }
+		// remember, embedded type factories are automatically cleared when
+		// embededType changed
+		pageDirectiveAdapter.setEmbeddedType(newEmbeddedContentType);
+		// // but still need to clear the page directive watchers, and let
+		// them be rediscovered (with new, accurate node as target)
+		// pageDirectiveAdapter.clearPageWatchers();
+		if (newEmbeddedContentType != null) {
+
+			// need to null out or else ModelParserAdapter
+			// won't get reinitialized
+			((DOMModelImpl) model).setModelParser(null);
+
+			newEmbeddedContentType.initializeFactoryRegistry(model.getFactoryRegistry());
+			newEmbeddedContentType.initializeParser(structuredDocument.getParser());
+
+			// partitioner setup is the responsibility of this loader
+			IDocumentPartitioner documentPartitioner = structuredDocument.getDocumentPartitioner();
+			// ISSUE: this logic is flawed, not sure of original intent, but
+			// added null/type checks for safety.
+			if (documentPartitioner != null && documentPartitioner instanceof StructuredTextPartitionerForJSP) {
+				if (newEmbeddedContentType.getFamilyId().equals(ContentTypeIdForXML.ContentTypeID_XML)) {
+					((StructuredTextPartitionerForJSP) documentPartitioner).setEmbeddedPartitioner(new StructuredTextPartitionerForXML());
+				}
+				else if (newEmbeddedContentType.getFamilyId().equals(ContentTypeIdForHTML.ContentTypeID_HTML)) {
+					((StructuredTextPartitionerForJSP) documentPartitioner).setEmbeddedPartitioner(new StructuredTextPartitionerForHTML());
+				}
+			}
+		}
+		// adding language here, in this convienent central
+		// location, but some obvious renaming or refactoring
+		// wouldn't hurt, in future.
+		// I needed to add this language setting for JSP Fragment support
+		// Note: this is the one that counts, since at this point,
+		// the model has an ID, so we can look up IFile, etc.
+		String language = getLanguage(model);
+		if (language != null && language.length() > 0) {
+			pageDirectiveAdapter.setLanguage(language);
+		}
+	}
+
+	/**
+	 * This is "reinitialize" since there should always be at least the
+	 * default one assigned, before we start checking the stream
+	 */
+	private void initCloneOfEmbeddedType(IStructuredModel model, EmbeddedTypeHandler oldEmbeddedContentType, EmbeddedTypeHandler newEmbeddedContentType) {
+		// check program logic
+		Assert.isNotNull(oldEmbeddedContentType, "Program error: invalid call during model initialization"); //$NON-NLS-1$
+		// once we know the embedded content type, we need to set it in the
+		// PageDirectiveAdapter ... the order of initialization is
+		// critical here, the doc must have been created, but its contents not
+		// set yet,
+		// and all factories must have been set up also.
+		IDOMModel domModel = (IDOMModel) model;
+		IStructuredDocument structuredDocument = model.getStructuredDocument();
+		IDOMDocument document = domModel.getDocument();
+		PageDirectiveAdapter pageDirectiveAdapter = (PageDirectiveAdapter) document.getAdapterFor(PageDirectiveAdapter.class);
+		// ==> // PropagatingAdapter propagatingAdapter = (PropagatingAdapter)
+		// ((INodeNotifier) document).getAdapterFor(PropagatingAdapter.class);
+		// ==> // ModelQueryAdapter modelQueryAdapter = (ModelQueryAdapter)
+		// ((INodeNotifier) document).getAdapterFor(ModelQueryAdapter.class);
+		// because, even in the clone case, the model has been paritally
+		// intialized with
+		// the old embedded type (during createModel), we need to unitialize
+		// parts of it, based on the old (or default) ones
+		oldEmbeddedContentType.uninitializeFactoryRegistry(model.getFactoryRegistry());
+		oldEmbeddedContentType.uninitializeParser(structuredDocument.getParser());
+		// remember, embedded type factories are automatically cleared when
+		// embededType changed
+		pageDirectiveAdapter.setEmbeddedType(newEmbeddedContentType);
+		if (newEmbeddedContentType != null) {
+			newEmbeddedContentType.initializeFactoryRegistry(model.getFactoryRegistry());
+			newEmbeddedContentType.initializeParser(structuredDocument.getParser());
+		}
+		// adding language here, in this convienent central
+		// location, but some obvious renaming or refactoring
+		// wouldn't hurt, in future.
+		// I needed to add this language setting for JSP Fragment support
+		// Note: this is the one that counts, since at this point,
+		// the model has an ID, so we can look up IFile, etc.
+		String language = getLanguage(model);
+		if (language != null && language.length() > 0) {
+			pageDirectiveAdapter.setLanguage(language);
+		}
+	}
+
+	private EmbeddedTypeHandler getEmbeddedType(IStructuredModel model) {
+		Document doc = ((IDOMModel) model).getDocument();
+		PageDirectiveAdapter pageDirectiveAdapter = (PageDirectiveAdapter) ((INodeNotifier) doc).getAdapterFor(PageDirectiveAdapter.class);
+		EmbeddedTypeHandler embeddedHandler = pageDirectiveAdapter.getEmbeddedType();
+		return embeddedHandler;
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.sse.core.internal.model.AbstractModelLoader#initEmbeddedTypePre(org.eclipse.wst.sse.core.internal.provisional.IStructuredModel)
+	 */
+	protected void initEmbeddedTypePre(IStructuredModel model) {
+		JSPModelLoader.this.initEmbeddedTypePre(model, model.getStructuredDocument());
+	}
+
+	protected void initEmbeddedTypePre(IStructuredModel model, IStructuredDocument structuredDocument) {
+
+		// note: this will currently only work for models backed by files
+		EmbeddedTypeHandler embeddedContentType = null;
+		IDOMModel domModel = (IDOMModel) model;
+
+		if (embeddedContentType == null) {
+			IContentDescription desc = getContentDescription(structuredDocument);
+			if (desc != null) {
+				Object prop = null;
+
+				prop = desc.getProperty(IContentDescriptionForJSP.CONTENT_FAMILY_ATTRIBUTE);
+				if (prop != null) {
+					if (ContentTypeFamilyForHTML.HTML_FAMILY.equals(prop)) {
+						embeddedContentType = EmbeddedTypeRegistryImpl.getInstance().getTypeFor("text/html");
+					}
+				}
+
+				if (embeddedContentType == null) {
+
+					prop = desc.getProperty(IContentDescriptionForJSP.CONTENT_TYPE_ATTRIBUTE);
+					if (prop != null) {
+						embeddedContentType = EmbeddedTypeRegistryImpl.getInstance().getTypeFor((String) prop);
+					}
+				}
+			}
+		}
+
+		IDOMDocument document = domModel.getDocument();
+		PageDirectiveAdapter pageDirectiveAdapter = (PageDirectiveAdapter) document.getAdapterFor(PageDirectiveAdapter.class);
+
+		if (embeddedContentType != null) {
+			pageDirectiveAdapter.setEmbeddedType(embeddedContentType);
+			embeddedContentType.initializeFactoryRegistry(model.getFactoryRegistry());
+		}
+		else {
+			// use default embeddedType if it couldn't determine one
+			embeddedContentType = getJSPDefaultEmbeddedType(model);
+			pageDirectiveAdapter.setEmbeddedType(embeddedContentType);
+			embeddedContentType.initializeFactoryRegistry(model.getFactoryRegistry());
+		}
+	}
+
+	protected void initEmbeddedTypePost(IStructuredModel model) {
+		// should already be initialized (from initEmbeddedTypePre)
+		// via IContentDescription
+		setLanguageInPageDirective(model);
+	}
+
+	/**
+	 * As part of the model cloning process, ensure that the new model has the
+	 * same embedded content type handler as the old model, and that it is
+	 * properly initialized
+	 */
+	protected void initEmbeddedType(IStructuredModel oldModel, IStructuredModel newModel) {
+		EmbeddedTypeHandler existingEmbeddedType = getEmbeddedType(oldModel);
+		if (existingEmbeddedType == null) {
+			initEmbeddedTypePre(newModel, newModel.getStructuredDocument());
+			initEmbeddedTypePost(newModel);
+		}
+		else {
+			EmbeddedTypeHandler newEmbeddedContentType = existingEmbeddedType.newInstance();
+			// initEmbeddedType(newModel);
+			initCloneOfEmbeddedType(newModel, existingEmbeddedType, newEmbeddedContentType);
+			setLanguageInPageDirective(newModel);
+		}
+	}
+
+	protected void setLanguageInPageDirective(IStructuredModel newModel) {
+		if (newModel instanceof IDOMModel) {
+			IDOMDocument document = ((IDOMModel) newModel).getDocument();
+			PageDirectiveAdapter pageDirectiveAdapter = (PageDirectiveAdapter) document.getAdapterFor(PageDirectiveAdapter.class);
+			String language = getLanguage(newModel);
+			pageDirectiveAdapter.setLanguage(language);
+		}
+	}
+
+	public IStructuredModel reinitialize(IStructuredModel model) {
+		EmbeddedTypeHandler oldHandler = null;
+		EmbeddedTypeHandler newHandler = null;
+		Object reinitStateData = model.getReinitializeStateData();
+		if (reinitStateData instanceof EmbeddedTypeStateData) {
+			EmbeddedTypeStateData oldStateData = (EmbeddedTypeStateData) reinitStateData;
+			oldHandler = oldStateData.getOldHandler();
+			newHandler = oldStateData.getNewHandler();
+			// note. We should already have the new handler in the model's
+			// (documents) adapters,
+			// so need need to use the old one to undo the old state data
+			reInitializeEmbeddedType(model, oldHandler, newHandler);
+		}
+		else {
+			// for language ... we someday MIGHT have to do something
+			// here, but for now, we don't have any model-side language
+			// sensitive adapters.
+		}
+		return super.reinitialize(model);
+	}
+
+	public IModelLoader newInstance() {
+		return new JSPModelLoader();
+	}
+
+	public IDocumentLoader getDocumentLoader() {
+		if (documentLoaderInstance == null) {
+			documentLoaderInstance = new JSPDocumentLoader();
+		}
+		return documentLoaderInstance;
+	}
+
+	/**
+	 * Ensures that an InputStream has mark/reset support.
+	 */
+	public static InputStream getMarkSupportedStream(InputStream original) {
+		if (original == null)
+			return null;
+		if (original.markSupported())
+			return original;
+		return new BufferedInputStream(original);
+	}
+
+	protected byte[] getBytes(InputStream inputStream, int max) throws IOException {
+		byte[] smallBuffer = new byte[max];
+		byte[] returnBuffer = null;
+		int nRead = inputStream.read(smallBuffer, 0, max);
+		if (nRead < max) {
+			// empty file will return -1;
+			if (nRead < 0)
+				nRead = 0;
+			byte[] smallerBuffer = new byte[nRead];
+			System.arraycopy(smallBuffer, 0, smallerBuffer, 0, nRead);
+			returnBuffer = smallerBuffer;
+		}
+		else {
+			returnBuffer = smallBuffer;
+		}
+		return returnBuffer;
+	}
+
+	public IStructuredModel createModel(IStructuredModel oldModel) {
+		IStructuredModel model = super.createModel(oldModel);
+		// For JSPs, the ModelQueryAdapter must be "attached" to the document
+		// before content is set in the model, so taglib initialization can
+		// take place.
+		// In this "clone model" case, we create a ModelQuery adapter
+		// create a new instance from the old data. Note: I think this
+		// "forced fit" only works here since the implementation of
+		// ModelQueryAdapter does not
+		// have to be released.
+
+		ModelQueryAdapter modelQueryAdapter = getModelQueryAdapter(model);
+		if (modelQueryAdapter == null) {
+			modelQueryAdapter = getModelQueryAdapter(oldModel);
+			IDOMDocument document = ((IDOMModel) model).getDocument();
+			document.addAdapter(new JSPModelQueryAdapterImpl(modelQueryAdapter.getCMDocumentCache(), modelQueryAdapter.getModelQuery(), modelQueryAdapter.getIdResolver()));
+
+		}
+
+
+
+		return model;
+	}
+
+	private ModelQueryAdapter getModelQueryAdapter(IStructuredModel model) {
+		IDOMDocument document = ((IDOMModel) model).getDocument();
+
+		ModelQueryAdapter modelQueryAdapter = (ModelQueryAdapter) ((INodeNotifier) document).getAdapterFor(ModelQueryAdapter.class);
+		return modelQueryAdapter;
+	}
+
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelhandler/ModelHandlerForJSP.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelhandler/ModelHandlerForJSP.java
new file mode 100644
index 0000000..aa74637
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelhandler/ModelHandlerForJSP.java
@@ -0,0 +1,113 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.modelhandler;
+
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.core.runtime.content.IContentType;
+import org.eclipse.jst.jsp.core.internal.JSPCorePlugin;
+import org.eclipse.jst.jsp.core.internal.encoding.JSPDocumentHeadContentDetector;
+import org.eclipse.jst.jsp.core.internal.encoding.JSPDocumentLoader;
+import org.eclipse.jst.jsp.core.internal.java.IJSPTranslation;
+import org.eclipse.jst.jsp.core.internal.java.JSPTranslationAdapterFactory;
+import org.eclipse.jst.jsp.core.internal.java.TagTranslationAdapterFactory;
+import org.eclipse.jst.jsp.core.internal.parser.JSPSourceParser;
+import org.eclipse.jst.jsp.core.internal.provisional.contenttype.ContentTypeIdForJSP;
+import org.eclipse.jst.jsp.core.internal.regions.DOMJSPRegionContexts;
+import org.eclipse.wst.sse.core.internal.document.IDocumentCharsetDetector;
+import org.eclipse.wst.sse.core.internal.document.IDocumentLoader;
+import org.eclipse.wst.sse.core.internal.ltk.modelhandler.AbstractModelHandler;
+import org.eclipse.wst.sse.core.internal.ltk.parser.BlockMarker;
+import org.eclipse.wst.sse.core.internal.provisional.IModelLoader;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapterFactory;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+
+public class ModelHandlerForJSP extends AbstractModelHandler {
+
+	/**
+	 * Needs to match what's in plugin registry. In fact, can be overwritten
+	 * at run time with what's in registry! (so should never be 'final')
+	 */
+	static String AssociatedContentTypeID = "org.eclipse.jst.jsp.core.jspsource"; //$NON-NLS-1$
+	/**
+	 * Needs to match what's in plugin registry. In fact, can be overwritten
+	 * at run time with what's in registry! (so should never be 'final')
+	 */
+	private static String ModelHandlerID = "org.eclipse.jst.jsp.core.modelhandler"; //$NON-NLS-1$
+
+
+	public ModelHandlerForJSP() {
+		super();
+		setId(ModelHandlerID);
+		setAssociatedContentTypeId(AssociatedContentTypeID);
+	}
+
+	protected void addJSPTagName(JSPSourceParser parser, String tagname) {
+		BlockMarker bm = new BlockMarker(tagname, null, DOMJSPRegionContexts.JSP_CONTENT, true);
+		parser.addBlockMarker(bm);
+	}
+
+	public IModelLoader getModelLoader() {
+		return new JSPModelLoader();
+	}
+
+	public Preferences getPreferences() {
+		return JSPCorePlugin.getDefault().getPluginPreferences();
+	}
+
+	public IDocumentCharsetDetector getEncodingDetector() {
+		return new JSPDocumentHeadContentDetector();
+	}
+
+	public IDocumentLoader getDocumentLoader() {
+		return new JSPDocumentLoader();
+	}
+
+	public static void ensureTranslationAdapterFactory(IStructuredModel sm) {
+		if (sm.getFactoryRegistry().getFactoryFor(IJSPTranslation.class) == null) {
+			/*
+			 * Check for tag/tagx files, otherwise add the JSP translation
+			 * factory for better compatibility with other possible subtypes
+			 * of JSP.
+			 */
+			IContentType thisContentType = Platform.getContentTypeManager().getContentType(sm.getContentTypeIdentifier());
+			IContentType tagContentType = Platform.getContentTypeManager().getContentType(ContentTypeIdForJSP.ContentTypeID_JSPTAG);
+			if (thisContentType.isKindOf(tagContentType)) {
+				INodeAdapterFactory factory = new TagTranslationAdapterFactory();
+				sm.getFactoryRegistry().addFactory(factory);
+			}
+			else {
+				INodeAdapterFactory factory = null;
+//				if (false) {
+//					IContentType textContentType = Platform.getContentTypeManager().getContentType(IContentTypeManager.CT_TEXT);
+//					IContentType jspContentType = Platform.getContentTypeManager().getContentType(ContentTypeIdForJSP.ContentTypeID_JSP);
+//					/*
+//					 * This IAdapterManager call is temporary placeholder code
+//					 * that should not be relied upon in any way!
+//					 */
+//					if (thisContentType.isKindOf(jspContentType)) {
+//						IContentType testContentType = thisContentType;
+//						INodeAdapterFactory holdFactory = null;
+//						while (!testContentType.equals(textContentType) && holdFactory == null) {
+//							holdFactory = (INodeAdapterFactory) Platform.getAdapterManager().getAdapter(testContentType.getId(), IJSPTranslation.class.getName());
+//							testContentType = testContentType.getBaseType();
+//						}
+//					}
+//				}
+				if (factory == null) {
+					factory = new JSPTranslationAdapterFactory();
+				}
+
+				sm.getFactoryRegistry().addFactory(factory);
+			}
+		}
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelhandler/ModelHandlerForTag.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelhandler/ModelHandlerForTag.java
new file mode 100644
index 0000000..1cb5f63
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelhandler/ModelHandlerForTag.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.modelhandler;
+
+import org.eclipse.wst.sse.core.internal.provisional.IModelLoader;
+
+public class ModelHandlerForTag extends ModelHandlerForJSP {
+
+	/**
+	 * Needs to match what's in plugin registry. In fact, can be overwritten
+	 * at run time with what's in registry! (so should never be 'final')
+	 */
+	static String AssociatedContentTypeID = "org.eclipse.jst.jsp.core.tagsource"; //$NON-NLS-1$
+	/**
+	 * Needs to match what's in plugin registry. In fact, can be overwritten
+	 * at run time with what's in registry! (so should never be 'final')
+	 */
+	private static String ModelHandlerID = "org.eclipse.jst.jsp.core.modelhandler.tag"; //$NON-NLS-1$
+
+
+	public ModelHandlerForTag() {
+		super();
+		setId(ModelHandlerID);
+		setAssociatedContentTypeId(AssociatedContentTypeID);
+	}
+
+	public IModelLoader getModelLoader() {
+		return new TagModelLoader();
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelhandler/TagModelLoader.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelhandler/TagModelLoader.java
new file mode 100644
index 0000000..b13da79
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelhandler/TagModelLoader.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.modelhandler;
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.jst.jsp.core.internal.modelquery.ModelQueryAdapterFactoryForTag;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapterFactory;
+import org.eclipse.wst.xml.core.internal.ssemodelquery.ModelQueryAdapter;
+
+public class TagModelLoader extends JSPModelLoader {
+
+	public TagModelLoader() {
+	}
+
+	public List getAdapterFactories() {
+		List factories = super.getAdapterFactories();
+		/*
+		 * Replace the default JSP model query by using our own factory
+		 */
+
+		Iterator i = factories.iterator();
+		while (i.hasNext()) {
+			if (((INodeAdapterFactory) i.next()).isFactoryForType(ModelQueryAdapter.class)) {
+				i.remove();
+			}
+		}
+
+		factories.add(new ModelQueryAdapterFactoryForTag());
+		return factories;
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelquery/JSPModelQueryAdapterImpl.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelquery/JSPModelQueryAdapterImpl.java
new file mode 100644
index 0000000..6350e54
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelquery/JSPModelQueryAdapterImpl.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.modelquery;
+
+
+
+import org.eclipse.wst.common.uriresolver.internal.provisional.URIResolver;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.CMDocumentCache;
+import org.eclipse.wst.xml.core.internal.ssemodelquery.ModelQueryAdapterImpl;
+
+
+public class JSPModelQueryAdapterImpl extends ModelQueryAdapterImpl {
+	public JSPModelQueryAdapterImpl(CMDocumentCache cmDocumentCache, ModelQuery modelQuery, URIResolver idResolver) {
+		super(cmDocumentCache, modelQuery, idResolver);
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelquery/JSPModelQueryAssociationProvider.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelquery/JSPModelQueryAssociationProvider.java
new file mode 100644
index 0000000..c689f5c
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelquery/JSPModelQueryAssociationProvider.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.modelquery;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.modelqueryimpl.SimpleAssociationProvider;
+
+/**
+ * @deprecated
+ */
+public class JSPModelQueryAssociationProvider extends SimpleAssociationProvider {
+
+	/**
+	 * @param modelQueryCMProvider
+	 *            org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQueryCMProvider
+	 */
+	public JSPModelQueryAssociationProvider() {
+		super(new JSPModelQueryCMProvider());
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelquery/JSPModelQueryCMProvider.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelquery/JSPModelQueryCMProvider.java
new file mode 100644
index 0000000..5b77a58
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelquery/JSPModelQueryCMProvider.java
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.modelquery;
+
+import java.util.List;
+
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jst.jsp.core.internal.contentmodel.JSPCMDocumentFactory;
+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.contenttype.DeploymentDescriptorPropertyCache;
+import org.eclipse.wst.sse.core.internal.provisional.IModelManager;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQueryCMProvider;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.w3c.dom.Node;
+
+/**
+ * CMDocument provider for HTML and JSP documents.
+ */
+public class JSPModelQueryCMProvider implements ModelQueryCMProvider {
+
+	protected JSPModelQueryCMProvider() {
+		super();
+	}
+
+	/**
+	 * Returns the CMDocument that corresponds to the DOM Node. or null if no
+	 * CMDocument is appropriate for the DOM Node.
+	 */
+	public CMDocument getCorrespondingCMDocument(Node node) {
+		CMDocument jcmdoc = null;
+		if (node instanceof IDOMNode) {
+			IDOMModel model = ((IDOMNode) node).getModel();
+			String modelPath = model.getBaseLocation();
+			if (modelPath != null && !IModelManager.UNMANAGED_MODEL.equals(modelPath)) {
+				float version = DeploymentDescriptorPropertyCache.getInstance().getJSPVersion(new Path(modelPath));
+				jcmdoc = JSPCMDocumentFactory.getCMDocument(version);
+			}
+		}
+		if (jcmdoc == null) {
+			jcmdoc = JSPCMDocumentFactory.getCMDocument();
+		}
+		
+		CMDocument result = null;
+		try {
+			if (node.getNodeType() == Node.ELEMENT_NODE) {
+				String elementName = node.getNodeName();
+
+				// test to see if this node belongs to JSP's CMDocument (case
+				// sensitive)
+				CMElementDeclaration dec = (CMElementDeclaration) jcmdoc.getElements().getNamedItem(elementName);
+				if (dec != null) {
+					result = jcmdoc;
+				}
+			}
+
+			String prefix = node.getPrefix();
+
+			if (result == null && prefix != null && prefix.length() > 0 && node instanceof IDOMNode) {
+				// check position dependent
+				IDOMNode xmlNode = (IDOMNode) node;
+				TLDCMDocumentManager tldmgr = TaglibController.getTLDCMDocumentManager(xmlNode.getStructuredDocument());
+				if (tldmgr != null) {
+					List documents = tldmgr.getCMDocumentTrackers(node.getPrefix(), xmlNode.getStartOffset());
+					// there shouldn't be more than one cmdocument returned
+					if (documents != null && documents.size() > 0)
+						result = (CMDocument) documents.get(0);
+				}
+			}
+		}
+		catch (Exception e) {
+			e.printStackTrace();
+		}
+		return result;
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelquery/JSPModelQueryExtension.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelquery/JSPModelQueryExtension.java
new file mode 100644
index 0000000..0b00471
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelquery/JSPModelQueryExtension.java
@@ -0,0 +1,203 @@
+/*******************************************************************************
+ * Copyright (c) 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.modelquery;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jst.jsp.core.internal.contentmodel.JSPCMDocumentFactory;
+import org.eclipse.jst.jsp.core.internal.contenttype.DeploymentDescriptorPropertyCache;
+import org.eclipse.jst.jsp.core.internal.provisional.JSP12Namespace;
+import org.eclipse.jst.jsp.core.internal.provisional.JSP20Namespace;
+import org.eclipse.jst.jsp.core.internal.provisional.contenttype.ContentTypeIdForJSP;
+import org.eclipse.wst.html.core.internal.contentmodel.JSPCMDocument;
+import org.eclipse.wst.sse.core.internal.provisional.IModelManager;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.extension.ModelQueryExtension;
+import org.eclipse.wst.xml.core.internal.provisional.contentmodel.CMDocType;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.eclipse.wst.xml.core.internal.ssemodelquery.ModelQueryAdapter;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+/**
+ * An implementation of {@link ModelQueryExtension} for JSP tags in JSP documents
+ */
+public class JSPModelQueryExtension extends ModelQueryExtension {
+	
+	private static final String TAG_JSP_ROOT = "jsp:root";
+
+	/**
+	 * Originally taken from JSPContentAssistProcessor
+	 * 
+	 * @see org.eclipse.wst.xml.core.internal.contentmodel.modelquery.extension.ModelQueryExtension#getAvailableElementContent(org.w3c.dom.Element, java.lang.String, int)
+	 */
+	public CMNode[] getAvailableElementContent(Element parentElement,
+			String namespace, int includeOptions) {
+		
+		CMNode[] nodes = EMPTY_CMNODE_ARRAY;
+		ArrayList nodeList = new ArrayList();
+		
+		//only returns anything if looking for child nodes
+		if(((includeOptions & ModelQuery.INCLUDE_CHILD_NODES) != 0) && parentElement instanceof IDOMNode) {
+			IDOMNode node = (IDOMNode)parentElement;
+			// get position dependent CMDocuments and insert their tags as
+			// proposals
+			ModelQueryAdapter mqAdapter = null;
+			if (node.getNodeType() == Node.DOCUMENT_NODE) {
+				mqAdapter = (ModelQueryAdapter) node.getAdapterFor(ModelQueryAdapter.class);
+			} else {
+				mqAdapter = (ModelQueryAdapter) ((IDOMNode) node.getOwnerDocument()).getAdapterFor(ModelQueryAdapter.class);
+			}
+
+			if (mqAdapter != null) {
+				CMDocument doc = mqAdapter.getModelQuery().getCorrespondingCMDocument(node);
+				if (doc != null) {
+					CMDocument jcmdoc = getDefaultJSPCMDocument(node);
+					CMNamedNodeMap jspelements = jcmdoc.getElements();
+
+					/* For a built-in JSP action the content model is properly
+					 * set up, so don't just blindly add the rest--unless this
+					 * will be a direct child of the document
+					 */
+					if (jspelements != null && (!(doc instanceof JSPCMDocument) || node.getNodeType() == Node.DOCUMENT_NODE)) {
+						List rejectElements = new ArrayList();
+
+						// determine if the document is in XML form
+						Document domDoc = null;
+						if (node.getNodeType() == Node.DOCUMENT_NODE) {
+							domDoc = (Document) node;
+						} else {
+							domDoc = node.getOwnerDocument();
+						}
+
+						// Show XML tag forms of JSP markers if jsp:root is
+						// the document element OR it's HTML but
+						// isn't really in the text.
+						// If the document isn't strictly XML, pull out the
+						// XML tag forms it is xml format
+						rejectElements.add(JSP12Namespace.ElementName.SCRIPTLET);
+						rejectElements.add(JSP12Namespace.ElementName.EXPRESSION);
+						rejectElements.add(JSP12Namespace.ElementName.DECLARATION);
+						rejectElements.add(JSP12Namespace.ElementName.DIRECTIVE_INCLUDE);
+						rejectElements.add(JSP12Namespace.ElementName.DIRECTIVE_PAGE);
+						rejectElements.add(JSP12Namespace.ElementName.TEXT);
+						rejectElements.add(JSP12Namespace.ElementName.DIRECTIVE_TAGLIB);
+						rejectElements.add(JSP20Namespace.ElementName.DIRECTIVE_TAG);
+						rejectElements.add(JSP20Namespace.ElementName.DIRECTIVE_ATTRIBUTE);
+						rejectElements.add(JSP20Namespace.ElementName.DIRECTIVE_VARIABLE);
+						if (isXMLFormat(domDoc)) {
+							// jsp actions
+							rejectElements.add(JSP12Namespace.ElementName.FALLBACK);
+							rejectElements.add(JSP12Namespace.ElementName.USEBEAN);
+							rejectElements.add(JSP12Namespace.ElementName.GETPROPERTY);
+							rejectElements.add(JSP12Namespace.ElementName.SETPROPERTY);
+							rejectElements.add(JSP12Namespace.ElementName.INCLUDE);
+							rejectElements.add(JSP12Namespace.ElementName.FORWARD);
+							rejectElements.add(JSP12Namespace.ElementName.PLUGIN);
+							rejectElements.add(JSP12Namespace.ElementName.FALLBACK);
+							rejectElements.add(JSP12Namespace.ElementName.PARAM);
+							rejectElements.add(JSP12Namespace.ElementName.PARAMS);
+						}
+
+
+						// don't show jsp:root if a document element already
+						// exists
+						Element docElement = domDoc.getDocumentElement();
+						if (docElement != null &&((docElement.getNodeName().equals(TAG_JSP_ROOT)) ||
+								((((IDOMNode) docElement).getStartStructuredDocumentRegion() != null ||
+										((IDOMNode) docElement).getEndStructuredDocumentRegion() != null)))) {
+							
+							rejectElements.add(JSP12Namespace.ElementName.ROOT);
+						}
+
+						for (int j = 0; j < jspelements.getLength(); j++) {
+							CMElementDeclaration ed = (CMElementDeclaration) jspelements.item(j);
+							if (!rejectElements.contains(ed.getNodeName())) {
+								nodeList.add(ed);
+							}
+						}
+
+					}
+				}
+				// No cm document (such as for the Document (a non-Element) node itself)
+				else {
+					CMNamedNodeMap jspElements = getDefaultJSPCMDocument(node).getElements();
+					int length = jspElements.getLength();
+					for (int i = 0; i < length; i++) {
+						nodeList.add(jspElements.item(i));
+					}
+				}
+			}
+			
+			nodes = (CMNode[])nodeList.toArray(new CMNode[nodeList.size()]);
+		}
+		
+		return nodes;
+	}
+	
+	/**
+	 * <p>For JSP files and segments, this is just the JSP
+	 *         document, but when editing tag files and their fragments, it
+	 *         should be the tag document.</p>
+	 * 
+	 * <p>It may also vary based on the model being edited in the future.</p>
+	 * 
+	 * <p><b>NOTE:</b>Copied from JSPContentAssistProcessor</p>
+	 *
+	 * @return the default non-embedded CMDocument for the document being
+	 *         edited. 
+	 */
+	private CMDocument getDefaultJSPCMDocument(IDOMNode node) {
+		CMDocument jcmdoc = null; 
+		
+		// handle tag files here
+		String contentType = node.getModel().getContentTypeIdentifier();
+		if (ContentTypeIdForJSP.ContentTypeID_JSPTAG.equals(contentType)) {
+			jcmdoc =  JSPCMDocumentFactory.getCMDocument(CMDocType.TAG20_DOC_TYPE);
+		} else {
+			String modelPath = node.getModel().getBaseLocation();
+			if (modelPath != null && !IModelManager.UNMANAGED_MODEL.equals(modelPath)) {
+				float version = DeploymentDescriptorPropertyCache.getInstance().getJSPVersion(new Path(modelPath));
+				jcmdoc = JSPCMDocumentFactory.getCMDocument(version);
+			}
+			if (jcmdoc == null) {
+				jcmdoc = JSPCMDocumentFactory.getCMDocument();
+			}
+		}
+
+		return jcmdoc;
+	}
+	
+	/**
+	 * <p><b>NOTE:</b>Copied from JSPContentAssistProcessor</p>
+	 *
+	 * @param doc determine if this {@link Document} is in an XML format
+	 * @return is the given document in an XML format
+	 */
+	private boolean isXMLFormat(Document doc) {
+		boolean result = false;
+		if (doc != null) {
+			Element docElement = doc.getDocumentElement();
+			result = docElement != null &&
+				((docElement.getNodeName().equals(TAG_JSP_ROOT)) ||
+						((((IDOMNode) docElement).getStartStructuredDocumentRegion() == null &&
+								((IDOMNode) docElement).getEndStructuredDocumentRegion() == null)));
+		}
+		return result;
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelquery/JSPModelQueryImpl.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelquery/JSPModelQueryImpl.java
new file mode 100644
index 0000000..18ee575
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelquery/JSPModelQueryImpl.java
@@ -0,0 +1,163 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.modelquery;
+
+
+import java.util.HashMap;
+import java.util.List;
+
+import org.eclipse.jst.jsp.core.internal.document.PageDirectiveAdapter;
+import org.eclipse.wst.common.uriresolver.internal.provisional.URIResolver;
+import org.eclipse.wst.html.core.internal.provisional.contenttype.ContentTypeFamilyForHTML;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelqueryimpl.ModelQueryImpl;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelqueryimpl.SimpleAssociationProvider;
+import org.eclipse.wst.xml.core.internal.ssemodelquery.ModelQueryAdapter;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+public class JSPModelQueryImpl extends ModelQueryImpl {
+
+	// ISSUE: jspModel doesn't seem used?
+	protected IStructuredModel jspModel = null;
+	private HashMap embeddedModelQueries = new HashMap();
+
+	public JSPModelQueryImpl(IStructuredModel model, URIResolver resolver) {
+		super(new SimpleAssociationProvider(new JSPModelQueryCMProvider()));
+		jspModel = model;
+	}
+
+	/*
+	 * @see ModelQuery#getCMElementDeclaration(Element)
+	 */
+	public CMElementDeclaration getCMElementDeclaration(Element element) {
+		CMElementDeclaration result = super.getCMElementDeclaration(element);
+		if (result == null) {
+			ModelQuery query = getEmbeddedModelQuery(element);
+			if (query != null) {
+				result = query.getCMElementDeclaration(element);
+			}
+		}
+		return result;
+	}
+
+	/*
+	 * @see ModelQuery#getCorrespondingCMDocument(Node)
+	 */
+	public CMDocument getCorrespondingCMDocument(Node node) {
+		CMDocument doc = super.getCorrespondingCMDocument(node);
+		if (doc == null) {
+			ModelQuery query = getEmbeddedModelQuery(node);
+			if (query != null) {
+				doc = query.getCorrespondingCMDocument(node);
+			}
+		}
+		return doc;
+	}
+
+	/*
+	 * @see ModelQuery#getCMNode(Node)
+	 */
+	public CMNode getCMNode(Node node) {
+		CMNode result = super.getCMNode(node);
+		if (result == null) {
+			ModelQuery query = getEmbeddedModelQuery(node);
+			if (query != null) {
+				result = query.getCMNode(node);
+			}
+		}
+		return result;
+	}
+
+	public List getAvailableContent(Element element, CMElementDeclaration ed, int includeOptions) {
+		ModelQuery emq = getEmbeddedModelQuery(element);
+		if (emq != null)
+			return emq.getAvailableContent(element, ed, includeOptions);
+		else
+			return super.getAvailableContent(element, ed, includeOptions);
+	}
+
+	// ISSUE: shouldn't this be private?
+	protected ModelQuery getEmbeddedModelQuery(Node node) {
+		ModelQuery embeddedModelQuery = null;
+
+		if (node instanceof INodeNotifier) { 
+			Node ownerNode = node.getOwnerDocument();
+			if (ownerNode == null) {
+				// then must be the document itself
+				ownerNode = node; 
+			}
+			PageDirectiveAdapter pageDirectiveAdapter = (PageDirectiveAdapter) ((INodeNotifier) ownerNode).getAdapterFor(PageDirectiveAdapter.class);
+			if (pageDirectiveAdapter != null) {
+
+				String effectiveContentType = null;
+				ModelQuery potentialModelQueryObject = null;
+
+				String familyId = pageDirectiveAdapter.getEmbeddedType().getFamilyId();
+				if (ContentTypeFamilyForHTML.HTML_FAMILY.equals(familyId)) {
+					effectiveContentType = "text/html";
+				}
+				else {
+					effectiveContentType = pageDirectiveAdapter.getContentType();
+				}
+				
+				potentialModelQueryObject = (ModelQuery) embeddedModelQueries.get(effectiveContentType);
+				
+				if (potentialModelQueryObject == null) {
+					ModelQueryAdapter embeddedAdapter = (ModelQueryAdapter) pageDirectiveAdapter.adapt((INodeNotifier) node, ModelQueryAdapter.class);
+					if (embeddedAdapter != null) {
+						// we will cache one model query per content type
+						embeddedModelQuery = embeddedAdapter.getModelQuery();
+						embeddedModelQueries.put(effectiveContentType, embeddedModelQuery);
+					}
+				}
+				else {
+					embeddedModelQuery = potentialModelQueryObject;
+				}
+			}
+		}
+		return embeddedModelQuery;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery#getCMAttributeDeclaration(org.w3c.dom.Attr)
+	 */
+	public CMAttributeDeclaration getCMAttributeDeclaration(Attr attr) {
+		CMAttributeDeclaration result = super.getCMAttributeDeclaration(attr);
+		if (result == null) {
+			ModelQuery query = getEmbeddedModelQuery(attr);
+			if (query != null) {
+				result = query.getCMAttributeDeclaration(attr);
+			}
+		}
+		return result;
+	}
+	
+	/**
+	 * NOT API -- this is provided, and is public, only to make some JUnit testing 
+	 * more straightforward. It will be changed in future, and from release to release.
+	 * 
+	 * @param node
+	 * @return
+	 */
+	public ModelQuery internalTestOnly_getEmbeddedModelQuery(Node node) {
+		return getEmbeddedModelQuery(node);
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelquery/ModelQueryAdapterFactoryForJSP.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelquery/ModelQueryAdapterFactoryForJSP.java
new file mode 100644
index 0000000..7d5c14c
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelquery/ModelQueryAdapterFactoryForJSP.java
@@ -0,0 +1,217 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.modelquery;
+
+import java.io.File;
+import java.net.URI;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.wst.common.uriresolver.internal.provisional.URIResolver;
+import org.eclipse.wst.sse.core.internal.provisional.AbstractAdapterFactory;
+import org.eclipse.wst.sse.core.internal.provisional.IModelStateListener;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapter;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapterFactory;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.util.Debug;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.CMDocumentCache;
+import org.eclipse.wst.xml.core.internal.modelquery.XMLCatalogIdResolver;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.eclipse.wst.xml.core.internal.ssemodelquery.ModelQueryAdapter;
+
+public class ModelQueryAdapterFactoryForJSP extends AbstractAdapterFactory implements IModelStateListener {
+
+	protected JSPModelQueryAdapterImpl modelQueryAdapterImpl;
+
+	protected IStructuredModel stateNotifier = null;
+
+	public ModelQueryAdapterFactoryForJSP() {
+		this(ModelQueryAdapter.class, true);
+	}
+
+	/**
+	 * ModelQueryAdapterFactoryForJSP constructor comment.
+	 * 
+	 * @param adapterKey
+	 *            java.lang.Object
+	 * @param registerAdapters
+	 *            boolean
+	 */
+	public ModelQueryAdapterFactoryForJSP(Object key, boolean registerAdapters) {
+		super(key, registerAdapters);
+	}
+
+	public INodeAdapterFactory copy() {
+		return new ModelQueryAdapterFactoryForJSP(getAdapterKey(), isShouldRegisterAdapter());
+	}
+
+	/**
+	 * createAdapter method comment.
+	 */
+	protected INodeAdapter createAdapter(INodeNotifier target) {
+		if (Debug.displayInfo)
+			System.out.println("-----------------------ModelQueryAdapterFactoryForJSP.createAdapter" + target); //$NON-NLS-1$
+		if (modelQueryAdapterImpl == null) {
+			if (target instanceof IDOMNode) {
+				IDOMNode xmlNode = (IDOMNode) target;
+				IStructuredModel model = stateNotifier = xmlNode.getModel();
+				if (model.getBaseLocation() != null) {
+					stateNotifier.addModelStateListener(this);
+				}
+
+				org.eclipse.wst.sse.core.internal.util.URIResolver resolver = model.getResolver();
+				if (Debug.displayInfo)
+					System.out.println("----------------ModelQueryAdapterFactoryForJSP... baseLocation : " + resolver.getFileBaseLocation()); //$NON-NLS-1$
+
+				/**
+				 * XMLCatalogIdResolver currently requires a filesystem
+				 * location string. Customarily this will be what is in the
+				 * deprecated SSE URIResolver and required by the Common URI
+				 * Resolver.
+				 */
+				URIResolver idResolver = null;
+				if (resolver != null) {
+					idResolver = new XMLCatalogIdResolver(resolver.getFileBaseLocation(), resolver);
+				}
+				else {
+					/*
+					 * 203649 - this block may be necessary due to ordering of
+					 * setting the resolver into the model
+					 */
+					String baseLocation = null;
+					String modelsBaseLocation = model.getBaseLocation();
+					if (modelsBaseLocation != null) {
+						File file = new Path(modelsBaseLocation).toFile();
+						if (file.exists()) {
+							baseLocation = file.getAbsolutePath();
+						}
+						else {
+							IPath basePath = new Path(model.getBaseLocation());
+							IResource derivedResource = null;
+							if (basePath.segmentCount() > 1)
+								derivedResource = ResourcesPlugin.getWorkspace().getRoot().getFile(basePath);
+							else
+								derivedResource = ResourcesPlugin.getWorkspace().getRoot().getProject(basePath.segment(0));
+							IPath derivedPath = derivedResource.getLocation();
+							if (derivedPath != null) {
+								baseLocation = derivedPath.toString();
+							}
+							else {
+								URI uri = derivedResource.getLocationURI();
+								if (uri != null) {
+									baseLocation = uri.toString();
+								}
+							}
+						}
+						if(baseLocation == null) {
+							baseLocation = modelsBaseLocation;
+						}
+					}
+					idResolver = new XMLCatalogIdResolver(baseLocation, null);
+				}
+
+				ModelQuery modelQuery = createModelQuery(model, idResolver);
+				modelQuery.setEditMode(ModelQuery.EDIT_MODE_UNCONSTRAINED);
+				modelQueryAdapterImpl = new JSPModelQueryAdapterImpl(new CMDocumentCache(), modelQuery, idResolver);
+			}
+		}
+		return modelQueryAdapterImpl;
+	}
+
+	protected ModelQuery createModelQuery(IStructuredModel model, URIResolver resolver) {
+		return new JSPModelQueryImpl(model, resolver);
+	}
+
+	/**
+	 * @see IModelStateListener#modelAboutToBeChanged(IStructuredModel)
+	 */
+	public void modelAboutToBeChanged(IStructuredModel model) {
+	}
+
+	/**
+	 * @see IModelStateListener#modelChanged(IStructuredModel)
+	 */
+	public void modelChanged(IStructuredModel model) {
+	}
+
+	/**
+	 * @see IModelStateListener#modelDirtyStateChanged(IStructuredModel,
+	 *      boolean)
+	 */
+	public void modelDirtyStateChanged(IStructuredModel model, boolean isDirty) {
+	}
+
+	/**
+	 * @see IModelStateListener#modelResourceDeleted(IStructuredModel)
+	 */
+	public void modelResourceDeleted(IStructuredModel model) {
+	}
+
+	/**
+	 * @see IModelStateListener#modelResourceMoved(IStructuredModel,
+	 *      IStructuredModel)
+	 */
+	public void modelResourceMoved(IStructuredModel oldModel, IStructuredModel newModel) {
+		// if oldModel != newModel, bad things might happen with the adapter
+		stateNotifier.removeModelStateListener(this);
+		stateNotifier = newModel;
+		updateResolver(stateNotifier);
+		stateNotifier.addModelStateListener(this);
+	}
+
+
+	public void release() {
+		super.release();
+		if (stateNotifier != null) {
+			stateNotifier.removeModelStateListener(this);
+		}
+		stateNotifier = null;
+		if (modelQueryAdapterImpl != null) {
+			modelQueryAdapterImpl.release();
+		}
+	}
+
+	protected void updateResolver(IStructuredModel model) {
+		String baseLocation = model.getBaseLocation();
+		IFile baseFile = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(model.getBaseLocation()));
+		if (baseFile != null) {
+			if (baseFile.getLocation() != null) {
+				baseLocation = baseFile.getLocation().toString();
+			}
+			if (baseLocation == null && baseFile.getLocationURI() != null) {
+				baseLocation = baseFile.getLocationURI().toString();
+			}
+			if (baseLocation == null) {
+				baseLocation = baseFile.getFullPath().toString();
+			}
+		}
+		else {
+			baseLocation = model.getBaseLocation();
+		}
+		modelQueryAdapterImpl.setIdResolver(new XMLCatalogIdResolver(baseLocation, model.getResolver()));
+	}
+
+	public void modelAboutToBeReinitialized(IStructuredModel structuredModel) {
+		// TODO Auto-generated method stub
+
+	}
+
+	public void modelReinitialized(IStructuredModel structuredModel) {
+		updateResolver(structuredModel);
+
+	}
+
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelquery/ModelQueryAdapterFactoryForTag.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelquery/ModelQueryAdapterFactoryForTag.java
new file mode 100644
index 0000000..ec9abb7
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelquery/ModelQueryAdapterFactoryForTag.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.modelquery;
+
+import org.eclipse.wst.common.uriresolver.internal.provisional.URIResolver;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapterFactory;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelqueryimpl.SimpleAssociationProvider;
+
+public class ModelQueryAdapterFactoryForTag extends ModelQueryAdapterFactoryForJSP {
+
+	public ModelQueryAdapterFactoryForTag() {
+	}
+
+	public ModelQueryAdapterFactoryForTag(Object key, boolean registerAdapters) {
+		super(key, registerAdapters);
+	}
+
+	public INodeAdapterFactory copy() {
+		return new ModelQueryAdapterFactoryForTag(getAdapterKey(), isShouldRegisterAdapter());
+	}
+
+	protected ModelQuery createModelQuery(IStructuredModel model, URIResolver resolver) {
+		return new TagModelQuery(new SimpleAssociationProvider(new TagModelQueryCMProvider()));
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelquery/TagModelQuery.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelquery/TagModelQuery.java
new file mode 100644
index 0000000..73ef1cc
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelquery/TagModelQuery.java
@@ -0,0 +1,155 @@
+/*******************************************************************************

+ * Copyright (c) 2009 IBM Corporation and others.

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ * 

+ * Contributors:

+ *     IBM Corporation - initial API and implementation

+ *******************************************************************************/

+

+package org.eclipse.jst.jsp.core.internal.modelquery;

+

+import java.util.List;

+

+import org.eclipse.core.resources.IProject;

+import org.eclipse.core.resources.ProjectScope;

+import org.eclipse.core.resources.ResourcesPlugin;

+import org.eclipse.core.runtime.IPath;

+import org.eclipse.core.runtime.Path;

+import org.eclipse.core.runtime.preferences.IEclipsePreferences;

+import org.eclipse.jst.jsp.core.internal.JSPCorePlugin;

+import org.eclipse.wst.common.uriresolver.internal.provisional.URIResolver;

+import org.eclipse.wst.sse.core.internal.ltk.modelhandler.EmbeddedTypeHandler;

+import org.eclipse.wst.sse.core.internal.modelhandler.ModelHandlerUtility;

+import org.eclipse.wst.sse.core.internal.provisional.IModelManager;

+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapter;

+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapterFactory;

+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;

+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;

+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;

+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;

+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;

+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQueryAssociationProvider;

+import org.eclipse.wst.xml.core.internal.contentmodel.modelqueryimpl.ModelQueryImpl;

+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;

+import org.eclipse.wst.xml.core.internal.ssemodelquery.ModelQueryAdapter;

+import org.eclipse.wst.xml.core.internal.ssemodelquery.MovableModelQuery;

+import org.w3c.dom.Element;

+import org.w3c.dom.Node;

+

+/**

+ * ModelQuery for JSP Tag files. Prioritizes the Tag content model and any

+ * loaded tag libraries in the model before falling back to the embedded model

+ * query, if one is found.

+ */

+public class TagModelQuery extends ModelQueryImpl implements ModelQuery, MovableModelQuery {

+	/**

+	 * The default mime-type for the embedded ModelQuery

+	 */

+	public static final String DEFAULT_MIMETYPE = "text/html";

+

+

+	/**

+	 * The prefix used with ProjectScope to find the (possibly user-set)

+	 * embedded mime-type on a .tag file.

+	 */

+	private static final String PREFERENCE_PREFIX = "embeddedMimeType/";

+

+	public static String createPreferenceKey(IPath fullPath) {

+		return PREFERENCE_PREFIX + fullPath.removeFirstSegments(1).toString();

+	}

+

+	private ModelQuery fEmbeddedModelQuery;

+

+	/**

+	 * @param modelQueryAssociationProvider

+	 */

+	public TagModelQuery(ModelQueryAssociationProvider modelQueryAssociationProvider) {

+		super(modelQueryAssociationProvider);

+	}

+

+	/*

+	 * (non-Javadoc)

+	 * 

+	 * @see org.eclipse.wst.xml.core.internal.contentmodel.modelqueryimpl.

+	 * ModelQueryImpl#getCMElementDeclaration(org.w3c.dom.Element)

+	 */

+	public CMElementDeclaration getCMElementDeclaration(Element element) {

+		CMElementDeclaration cmElementDeclaration = super.getCMElementDeclaration(element);

+		if (cmElementDeclaration == null) {

+			ModelQuery embeddedModelQuery = getEmbeddedModelQuery(element);

+			if (embeddedModelQuery != null) {

+				return embeddedModelQuery.getCMElementDeclaration(element);

+			}

+		}

+		return cmElementDeclaration;

+	}

+

+	/*

+	 * (non-Javadoc)

+	 * 

+	 * @see org.eclipse.wst.xml.core.internal.contentmodel.modelqueryimpl.

+	 * ModelQueryImpl#getCorrespondingCMDocument(org.w3c.dom.Node)

+	 */

+	public CMDocument getCorrespondingCMDocument(Node node) {

+		CMDocument document = super.getCorrespondingCMDocument(node);

+		if (document == null) {

+			ModelQuery embeddedModelQuery = getEmbeddedModelQuery(node);

+			if (embeddedModelQuery != null) {

+				return embeddedModelQuery.getCorrespondingCMDocument(node);

+			}

+		}

+		return document;

+	}

+

+	private String getEmbeddedMimeType(Node node) {

+		String type = DEFAULT_MIMETYPE;

+		if (node instanceof IDOMNode) {

+			IStructuredModel model = ((IDOMNode) node).getModel();

+			String baseLocation = model.getBaseLocation();

+			if (!baseLocation.equals(IModelManager.UNMANAGED_MODEL)) {

+				IPath path = new Path(baseLocation);

+				if (path.segmentCount() > 1) {

+					IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(path.segment(0));

+					if (project.isAccessible()) {

+						String key = createPreferenceKey(path);

+						IEclipsePreferences preferences = new ProjectScope(project).getNode(JSPCorePlugin.getDefault().getBundle().getSymbolicName());

+						type = preferences.get(key, DEFAULT_MIMETYPE);

+					}

+				}

+			}

+		}

+		return type;

+	}

+

+	private ModelQuery getEmbeddedModelQuery(Node node) {

+		if (fEmbeddedModelQuery == null) {

+			String embeddedMimeType = getEmbeddedMimeType(node);

+			if (embeddedMimeType != null) {

+				EmbeddedTypeHandler embeddedContentTypeHandler = ModelHandlerUtility.getEmbeddedContentTypeFor(embeddedMimeType);

+				if (embeddedContentTypeHandler != null) {

+					List adapterFactories = embeddedContentTypeHandler.getAdapterFactories();

+					for (int i = 0; i < adapterFactories.size(); i++) {

+						INodeAdapterFactory factory = (INodeAdapterFactory) adapterFactories.get(i);

+						if (factory.isFactoryForType(ModelQueryAdapter.class)) {

+							INodeAdapter adapter = factory.adapt((INodeNotifier) node.getOwnerDocument());

+							if (adapter instanceof ModelQueryAdapter) {

+								fEmbeddedModelQuery = ((ModelQueryAdapter) adapter).getModelQuery();

+							}

+						}

+					}

+				}

+			}

+		}

+		return fEmbeddedModelQuery;

+	}

+

+	/* (non-Javadoc)

+	 * @see org.eclipse.wst.xml.core.internal.ssemodelquery.MovableModelQuery#setIdResolver(org.eclipse.wst.common.uriresolver.internal.provisional.URIResolver)

+	 */

+	public void setIdResolver(URIResolver newURIResolver) {

+		fEmbeddedModelQuery = null;

+	}

+}

diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelquery/TagModelQueryCMProvider.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelquery/TagModelQueryCMProvider.java
new file mode 100644
index 0000000..8620e8a
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelquery/TagModelQueryCMProvider.java
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.modelquery;
+
+
+
+import java.util.List;
+
+import org.eclipse.jst.jsp.core.internal.contentmodel.TaglibController;
+import org.eclipse.jst.jsp.core.internal.contentmodel.tld.TLDCMDocumentManager;
+import org.eclipse.wst.html.core.internal.contentmodel.HTMLCMDocumentFactory;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQueryCMProvider;
+import org.eclipse.wst.xml.core.internal.provisional.contentmodel.CMDocType;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.w3c.dom.Node;
+
+/**
+ * CMDocument provider for HTML and JSP documents.
+ */
+public class TagModelQueryCMProvider implements ModelQueryCMProvider {
+
+	protected TagModelQueryCMProvider() {
+		super();
+	}
+
+	/**
+	 * Returns the CMDocument that corresponds to the DOM Node. or null if no
+	 * CMDocument is appropriate for the DOM Node.
+	 */
+	public CMDocument getCorrespondingCMDocument(Node node) {
+		CMDocument tagdoc = HTMLCMDocumentFactory.getCMDocument(CMDocType.TAG20_DOC_TYPE);
+
+		CMDocument result = null;
+		try {
+			if (node.getNodeType() == Node.ELEMENT_NODE) {
+				String elementName = node.getNodeName();
+
+				// test to see if this node belongs to JSP's CMDocument (case
+				// sensitive)
+				CMElementDeclaration dec = (CMElementDeclaration) tagdoc.getElements().getNamedItem(elementName);
+				if (dec != null) {
+					result = tagdoc;
+				}
+			}
+
+			String prefix = node.getPrefix();
+
+			if (result == null && prefix != null && prefix.length() > 0 && node instanceof IDOMNode) {
+				// check position dependent
+				IDOMNode xmlNode = (IDOMNode) node;
+				TLDCMDocumentManager tldmgr = TaglibController.getTLDCMDocumentManager(xmlNode.getStructuredDocument());
+				if (tldmgr != null) {
+					List documents = tldmgr.getCMDocumentTrackers(node.getPrefix(), xmlNode.getStartOffset());
+					// there shouldn't be more than one cmdocument returned
+					if (documents != null && !documents.isEmpty())
+						result = (CMDocument) documents.get(0);
+				}
+			}
+		}
+		catch (Exception e) {
+			e.printStackTrace();
+		}
+// 204990 - JSP/Web Page Editors: tag files do not support content assist on html element attributes
+//		if (result == null) {
+//			result = tagdoc;
+//		}
+		return result;
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelquery/TaglibModelQueryExtension.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelquery/TaglibModelQueryExtension.java
new file mode 100644
index 0000000..33e8c1d
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelquery/TaglibModelQueryExtension.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.modelquery;
+
+import java.util.ArrayList;
+import java.util.List;
+
+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.TaglibTracker;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.extension.ModelQueryExtension;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
+import org.w3c.dom.Element;
+
+/**
+ * An implementation of {@link ModelQueryExtension} for tag libraries in JSP documents
+ */
+public class TaglibModelQueryExtension extends ModelQueryExtension {
+	
+	/**
+	 * @see org.eclipse.wst.xml.core.internal.contentmodel.modelquery.extension.ModelQueryExtension#getAvailableElementContent(org.w3c.dom.Element, java.lang.String, int)
+	 */
+	public CMNode[] getAvailableElementContent(Element parentElement,
+			String namespace, int includeOptions) {
+		
+		CMNode[] nodes = EMPTY_CMNODE_ARRAY;
+		ArrayList nodeList = new ArrayList();
+		
+		//only returns anything if looking for child nodes
+		if(((includeOptions & ModelQuery.INCLUDE_CHILD_NODES) != 0) && parentElement instanceof IDOMElement) {
+			//get the trackers
+			IDOMElement elem = (IDOMElement)parentElement;
+			IStructuredDocument structDoc = elem.getModel().getStructuredDocument();
+			TLDCMDocumentManager manager = TaglibController.getTLDCMDocumentManager(structDoc);
+
+			if(manager != null) {
+				List trackers = new ArrayList(manager.getTaglibTrackers());
+				
+				//for each tracker add each of its elements to the node list
+				for(int trackerIndex = 0; trackerIndex < trackers.size(); ++trackerIndex) {
+					CMNamedNodeMap elements = ((TaglibTracker)trackers.get(trackerIndex)).getElements();
+					for(int elementIndex = 0; elementIndex < elements.getLength(); ++elementIndex) {
+						nodeList.add(elements.item(elementIndex));
+					}
+				}
+				
+				nodes = (CMNode[])nodeList.toArray(new CMNode[nodeList.size()]);
+			}
+		}
+		
+		return nodes;
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/parser/JSPDirectiveStructuredDocumentRegion.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/parser/JSPDirectiveStructuredDocumentRegion.java
new file mode 100644
index 0000000..963a70d
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/parser/JSPDirectiveStructuredDocumentRegion.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.parser;
+
+import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentEvent;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.xml.core.internal.text.XMLStructuredDocumentRegion;
+
+public class JSPDirectiveStructuredDocumentRegion extends XMLStructuredDocumentRegion {
+	/**
+	 * JSPDirectiveStructuredDocumentRegion constructor comment.
+	 */
+	public JSPDirectiveStructuredDocumentRegion() {
+		super();
+	}
+
+	protected StructuredDocumentEvent reparse(Object requester, String changes, int requestStart, int lengthToReplace) {
+		return null;
+	}
+
+	// This is a language specific method (e.g. HTML, Java, Prolog, etc.) so
+	// could/should be made configurable.
+	public StructuredDocumentEvent updateModel(Object requester, String changes, int requestStart, int lengthToReplace, IStructuredDocumentRegion flatnode) {
+		return null;
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/parser/JSPReParser.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/parser/JSPReParser.java
new file mode 100644
index 0000000..7c04388
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/parser/JSPReParser.java
@@ -0,0 +1,379 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.parser;
+
+
+import java.util.Iterator;
+
+import org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.JSP11TLDNames;
+import org.eclipse.jst.jsp.core.internal.provisional.JSP12Namespace;
+import org.eclipse.jst.jsp.core.internal.regions.DOMJSPRegionContexts;
+import org.eclipse.wst.sse.core.internal.ltk.parser.RegionParser;
+import org.eclipse.wst.sse.core.internal.ltk.parser.StructuredDocumentRegionParser;
+import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentEvent;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegionList;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredTextReParser;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+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.internal.text.CoreNodeList;
+import org.eclipse.wst.sse.core.internal.util.Debug;
+import org.eclipse.wst.xml.core.internal.parser.XMLStructuredDocumentReParser;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+
+public class JSPReParser extends XMLStructuredDocumentReParser {
+
+	/**
+	 * Allow a reparser to check for extra syntactic cases that require
+	 * parsing beyond the flatNode boundary.
+	 * 
+	 * This implementation adds JSP language markers (comments are handled
+	 * elsewhere).
+	 */
+	protected StructuredDocumentEvent checkForCrossStructuredDocumentRegionSyntax() {
+		StructuredDocumentEvent result = super.checkForCrossStructuredDocumentRegionSyntax();
+		// None of the superclass' cases were valid, so check for JSP cases
+		if (result == null) {
+			result = checkForJSP();
+			if (result == null)
+				result = checkForJSPEL();
+		}
+		return result;
+	}
+	
+	private StructuredDocumentEvent checkForJSPEL() {
+		StructuredDocumentEvent result = null;
+		result = checkForCriticalKey("${"); //$NON-NLS-1$
+		if (result == null) 
+			result = checkForCriticalKey("}"); //$NON-NLS-1$
+		return result;
+	}
+
+	/**
+	 * A change to a JSP tag can result in all being reparsed.
+	 */
+	private StructuredDocumentEvent checkForJSP() {
+		StructuredDocumentEvent result = null;
+		result = checkForCriticalKey("<%"); //$NON-NLS-1$
+		if (result == null)
+			result = checkForCriticalKey("<%="); //$NON-NLS-1$
+		if (result == null)
+			result = checkForCriticalKey("<%!"); //$NON-NLS-1$
+		if (result == null)
+			result = checkForCriticalKey("%>"); //$NON-NLS-1$
+
+		return result;
+	}
+
+	/**
+	 * If a comment start or end tag is being added or deleted, we'll rescan
+	 * the whole document. The reason is that content that is revealed or
+	 * commented out can effect the interpretation of the rest of the
+	 * document. Note: for now this is very XML/JSP specific, can
+	 * refactor/improve later.
+	 */
+	protected StructuredDocumentEvent checkForComments() {
+
+		StructuredDocumentEvent result = super.checkForComments();
+
+		if (result == null)
+			result = checkForCriticalKey("<%--"); //$NON-NLS-1$
+		if (result == null)
+			result = checkForCriticalKey("--%>"); //$NON-NLS-1$
+		// we'll also check for these degenerate cases
+		if (result == null)
+			result = checkForCriticalKey("<%---%>"); //$NON-NLS-1$
+
+		return result;
+	}
+
+	/**
+	 * The core reparsing method ... after the dirty start and dirty end have
+	 * been calculated elsewhere. - this method overrides, does not extend
+	 * super's method. changes/fixes to super may have to be made here as
+	 * well.
+	 */
+	protected StructuredDocumentEvent reparse(IStructuredDocumentRegion dirtyStart, IStructuredDocumentRegion dirtyEnd) {
+		StructuredDocumentEvent result = null;
+		int rescanStart = -1;
+		int rescanEnd = -1;
+		boolean firstTime = false;
+		boolean detectedBreakingChange = false;
+
+		//
+		// "save" the oldNodes (that may be replaced) in a list
+		CoreNodeList oldNodes = formOldNodes(dirtyStart, dirtyEnd);
+
+		if (containsBreakingChange(oldNodes) || isBreakingWithNestedTag(dirtyStart, dirtyEnd)) {
+			if (Debug.debugTaglibs)
+				System.out.println("reparse: is taglib or include"); //$NON-NLS-1$
+			detectedBreakingChange = true;
+			rescanStart = 0;
+			rescanEnd = fStructuredDocument.getLength() + fLengthDifference;
+			oldNodes = formOldNodes(fStructuredDocument.getFirstStructuredDocumentRegion(), fStructuredDocument.getLastStructuredDocumentRegion());
+			clearTaglibInfo();
+		}
+		else if (dirtyStart == null || dirtyEnd == null) {
+			// dirtyStart or dirty end are null, then that means we didn't
+			// have a
+			// cached node, which means we have an empty document, so we
+			// just need to rescan the changes
+			rescanStart = 0;
+			rescanEnd = fChanges.length();
+			firstTime = true;
+		}
+		else {
+			// set the start of the text to rescan
+			rescanStart = dirtyStart.getStart();
+			//
+			// set the end of the text to rescan
+			// notice we use the same rationale as for the rescanStart,
+			// with the added caveat that length has to be added to it,
+			// to compensate for the new text which has been added or deleted.
+			// If changes has zero length, then "length" will be negative,
+			// since
+			// we are deleting text. Otherwise, use the difference between
+			// what's selected to be replaced and the length of the new text.
+			rescanEnd = dirtyEnd.getEnd() + fLengthDifference;
+		}
+
+		// now that we have the old stuff "saved" away, update the document
+		// with the changes.
+		fStructuredDocument.updateDocumentData(fStart, fLengthToReplace, fChanges);
+		// ------------------ now the real work
+		result = core_reparse(rescanStart, rescanEnd, oldNodes, firstTime);
+		//
+
+		// if we did not detect a breaking type of change at the beginning,
+		// but
+		// do now, then reparse all! If we did detect them, then we may or may
+		// not detect again, but presumably we've already set up to re-parsed
+		// everthing, so no need to do again.
+		if ((!detectedBreakingChange) && (containsBreakingChange(oldNodes))) {
+			clearTaglibInfo();
+			// reparse all
+			oldNodes = formOldNodes(fStructuredDocument.getFirstStructuredDocumentRegion(), fStructuredDocument.getLastStructuredDocumentRegion());
+			result = core_reparse(0, fStructuredDocument.getLength(), oldNodes, firstTime);
+		}
+
+		// event is returned to the caller, incase there is
+		// some optimization they can do
+		return result;
+	}
+
+	/**
+	 * Verifies that the regions given, representing the contents of a
+	 * IStructuredDocumentRegion, contain regions that could alter the
+	 * behavior of the parser or the parsing of areas outside of the regions
+	 * given.
+	 */
+	private boolean isBreakingChange(IStructuredDocumentRegion node, ITextRegionList regions) {
+		return isTaglibOrInclude(node, regions) || isJspRoot(regions);
+	}
+
+	/**
+	 * Verifies that the regions given, representing the regions touched by a
+	 * text change have: 1) ...an insertion at the textEndOffset of an
+	 * XML_TAG_OPEN that's in it's own IStructuredDocumentRegion and preceded
+	 * by an unended IStructuredDocumentRegion 2) ...a deletion happening in
+	 * an XML_EMPTY_TAG_CLOSE that ends a ITextRegionContainer 3) ...an
+	 * insertion happening with a ' <' character somewhere in an XML attribute
+	 * name or value 4) ...a deletion of a normal XML_TAG_CLOSE since
+	 * subsequent tags become attribute values
+	 */
+
+	private boolean isBreakingWithNestedTag(boolean changesIncludeA_lt, boolean delsIncludeA_gt, IStructuredDocumentRegion parent, ITextRegion region) {
+		boolean result = false;
+
+		IStructuredDocumentRegion previous = parent.getPrevious();
+		// case 1 test
+		if (parent.getRegions().size() == 1 && region.getType() == DOMRegionContext.XML_TAG_OPEN && (previous == null || (!previous.isEnded() || previous.getType() == DOMRegionContext.XML_CONTENT))) {
+			result = true;
+		}
+		// case 2 test
+		if (region instanceof ITextRegionContainer) {
+			ITextRegionContainer container = (ITextRegionContainer) region;
+			ITextRegion internal = container.getRegions().get(container.getRegions().size() - 1);
+			if (internal.getType() == DOMRegionContext.WHITE_SPACE && container.getRegions().size() >= 2)
+				internal = container.getRegions().get(container.getRegions().size() - 2);
+			if (internal.getType() == DOMRegionContext.XML_EMPTY_TAG_CLOSE) {
+				result = true;
+			}
+		}
+		// case 3 test
+		if (changesIncludeA_lt && (region.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME || region.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE)) {
+			result = true;
+		}
+		// case 4 test
+		if (delsIncludeA_gt && region.getType() == DOMRegionContext.XML_TAG_CLOSE) {
+			result = true;
+		}
+		return result;
+	}
+
+	/**
+	 * Verifies that the regions given, representing the contents of a
+	 * IStructuredDocumentRegion, includes a jsp:root tag
+	 */
+	private boolean isJspRoot(ITextRegionList regions) {
+		return regions.size() > 1 && regions.get(0).getType() == DOMRegionContext.XML_TAG_OPEN && regions.get(1).getType() == DOMJSPRegionContexts.JSP_ROOT_TAG_NAME;
+	}
+
+	/**
+	 * Verifies that the regions given, representing the contents of a
+	 * IStructuredDocumentRegion, includes a valid taglib directive or include
+	 * directive
+	 */
+	private boolean isTaglibOrInclude(IStructuredDocumentRegion node, ITextRegionList regions) {
+		boolean sizeAndTypesMatch = (regions.size() > 1) && (regions.get(1).getType() == DOMJSPRegionContexts.JSP_DIRECTIVE_NAME) && (regions.get(0).getType() == DOMJSPRegionContexts.JSP_DIRECTIVE_OPEN || regions.get(0).getType() == DOMRegionContext.XML_TAG_OPEN);
+		if (!sizeAndTypesMatch)
+			return false;
+		ITextRegion region = regions.get(1);
+		String directiveName = node.getText(region);
+		return sizeAndTypesMatch && (directiveName.equals(JSP11TLDNames.TAGLIB) || directiveName.equals(JSP11TLDNames.INCLUDE) || directiveName.equals(JSP12Namespace.ElementName.DIRECTIVE_TAGLIB) || directiveName.equals(JSP12Namespace.ElementName.DIRECTIVE_INCLUDE));
+	}
+
+	private void clearTaglibInfo() {
+		if (Debug.debugTaglibs)
+			System.out.println("clearing taglib info"); //$NON-NLS-1$
+		RegionParser parser = fStructuredDocument.getParser();
+		if (parser instanceof StructuredDocumentRegionParser)
+			((StructuredDocumentRegionParser) parser).resetHandlers();
+	}
+
+	private boolean containsBreakingChange(IStructuredDocumentRegionList list) {
+		boolean contains = false;
+		for (int i = 0; i < list.getLength(); i++) {
+			IStructuredDocumentRegion node = list.item(i);
+			if (isBreakingChange(node, node.getRegions())) {
+				contains = true;
+				break;
+			}
+		}
+		return contains;
+	}
+
+	protected IStructuredDocumentRegion findDirtyEnd(int end) {
+
+		IStructuredDocumentRegion result = super.findDirtyEnd(end);
+
+		// if not well formed, get one past, if its not null
+
+		// now, if any of to-be-scanned flatnodes are the start of a jsp
+		// region, we'll
+		// reparse all the way to the end, to be sure we detect embedded
+		// regions (or not-embedded regions) correctly.
+		// notice we don't need to do if we're only processing one node.
+		// notice too we have a strong assumption here that dirtyStart has
+		// already been found!
+		//
+		// note that dirtyEnd is not checked in the do-block below, so we'll
+		// check it first.
+		if (isJSPEmbeddedStartOrEnd(result)) {
+			result = fStructuredDocument.getLastStructuredDocumentRegion();
+		}
+		else {
+			// when end node and start node are the same, we only need the
+			// above
+			// check, otherwise, there's a few cases that we'll search the
+			// rest of the
+			// flatnodes needlessly.
+			if (result != dirtyStart) {
+				IStructuredDocumentRegion searchNode = dirtyStart;
+				do {
+					if (isJSPEmbeddedStartOrEnd(searchNode)) {
+						result = fStructuredDocument.getLastStructuredDocumentRegion();
+						break;
+					}
+					else {
+						searchNode = searchNode.getNext();
+					}
+					// if we get to the current dirty end, or end of
+					// flatnodes, without finding JSP region then we
+					// don't need to check further
+				}
+				while ((searchNode != result) && (searchNode != null));
+			}
+		}
+		// result should never be null, but cachedNode needs to be protected
+		// from being changed to null
+		if (result != null)
+			fStructuredDocument.setCachedDocumentRegion(result);
+		dirtyEnd = result;
+		return dirtyEnd;
+	}
+
+	private boolean isBreakingWithNestedTag(IStructuredDocumentRegion start, IStructuredDocumentRegion end) {
+		boolean result = false;
+		boolean changesIncludeA_lt = fChanges != null && fChanges.indexOf('<') >= 0;
+		boolean delsIncludeA_gt = fDeletedText != null && fDeletedText.indexOf('>') >= 0;
+
+		// List regions = new ArrayList();
+		IStructuredDocumentRegion node = start;
+		int endReplace = fStart + fLengthToReplace;
+		while (end != null && node != end.getNext()) {
+			Iterator i = node.getRegions().iterator();
+			while (i.hasNext()) {
+				ITextRegion region = (ITextRegion) i.next();
+				if (intersects(node, region, fStart, endReplace)) {
+
+					result = isBreakingWithNestedTag(changesIncludeA_lt, delsIncludeA_gt, node, region);
+
+					if (result)
+						break;
+				}
+			}
+			node = node.getNext();
+			if (result)
+				break;
+		}
+		return result;
+	}
+
+	private boolean intersects(IStructuredDocumentRegion node, ITextRegion region, int low, int high) {
+		int start = node.getStartOffset(region);
+		int end = node.getEndOffset(region);
+		return (end >= low && start <= high) || (start <= low && end >= low) || (start <= high && end >= high);
+	}
+
+	/**
+	 * Returns true if potentially could be a jsp embedded region. Things like
+	 * JSP Declaration can't be embedded.
+	 */
+	private boolean isJSPEmbeddedStartOrEnd(IStructuredDocumentRegion flatNode) {
+		boolean result = false;
+		String type = flatNode.getType();
+		result = ((type == DOMJSPRegionContexts.JSP_SCRIPTLET_OPEN) || (type == DOMJSPRegionContexts.JSP_EXPRESSION_OPEN) || (type == DOMJSPRegionContexts.JSP_DECLARATION_OPEN));
+		return result;
+	}
+
+	/**
+	 * extends super class behavior
+	 */
+	protected boolean isPartOfBlockRegion(IStructuredDocumentRegion flatNode) {
+		boolean result = false;
+		String type = flatNode.getType();
+		result = ((type == DOMJSPRegionContexts.JSP_CLOSE) || (type == DOMJSPRegionContexts.JSP_CONTENT) || super.isPartOfBlockRegion(flatNode));
+		return result;
+	}
+
+	public IStructuredTextReParser newInstance() {
+		return new JSPReParser();
+	}
+
+	public StructuredDocumentEvent quickCheck() {
+		if (containsBreakingChange(new CoreNodeList(dirtyStart, dirtyEnd)))
+			return null;
+		return super.quickCheck();
+	}
+
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/parser/JSPSourceParser.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/parser/JSPSourceParser.java
new file mode 100644
index 0000000..44af4f7
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/parser/JSPSourceParser.java
@@ -0,0 +1,427 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.parser;
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.JSP12TLDNames;
+import org.eclipse.jst.jsp.core.internal.parser.internal.JSPTokenizer;
+import org.eclipse.jst.jsp.core.internal.provisional.JSP12Namespace;
+import org.eclipse.jst.jsp.core.internal.regions.DOMJSPRegionContexts;
+import org.eclipse.wst.sse.core.internal.ltk.parser.BlockTokenizer;
+import org.eclipse.wst.sse.core.internal.ltk.parser.JSPCapableParser;
+import org.eclipse.wst.sse.core.internal.ltk.parser.RegionParser;
+import org.eclipse.wst.sse.core.internal.ltk.parser.StructuredDocumentRegionHandler;
+import org.eclipse.wst.sse.core.internal.ltk.parser.StructuredDocumentRegionHandlerExtension;
+import org.eclipse.wst.sse.core.internal.ltk.parser.StructuredDocumentRegionParser;
+import org.eclipse.wst.sse.core.internal.ltk.parser.TagMarker;
+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.ITextRegionContainer;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList;
+import org.eclipse.wst.sse.core.internal.text.IRegionComparible;
+import org.eclipse.wst.sse.core.internal.util.Debug;
+import org.eclipse.wst.sse.core.utils.StringUtils;
+import org.eclipse.wst.xml.core.internal.parser.XMLSourceParser;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+
+/**
+ * Takes input from the JSPTokenizer and creates a tag list
+ */
+
+public class JSPSourceParser extends XMLSourceParser implements JSPCapableParser {
+	protected class NestablePrefixHandler implements StructuredDocumentRegionHandler, StructuredDocumentRegionHandlerExtension {
+
+		private static final String XMLNS = "xmlns:"; //$NON-NLS-1$
+
+		/**
+		 * Enables a TLD owning the given prefix loaded from the given URI at
+		 * the anchorFlatNode. The list of additionalCMDocuments will claim to
+		 * not know any of its tags at positions earlier than that
+		 * IStructuredDocumentRegion's position.
+		 * 
+		 * For taglib directives, the taglib is the anchor while taglibs
+		 * registered through include directives use the primary include
+		 * directive as their anchor.
+		 */
+		protected void enableForTaglib(String prefix, IStructuredDocumentRegion anchorFlatNode) {
+			if (prefix == null)
+				return;
+			List tagmarkers = ((JSPTokenizer) getTokenizer()).getNestablePrefixes();
+			for (int i = 0; i < tagmarkers.size(); i++) {
+				if (((TagMarker) tagmarkers.get(i)).getTagName().equals(prefix))
+					return;
+			}
+			((JSPTokenizer) getTokenizer()).getNestablePrefixes().add(new TagMarker(prefix, anchorFlatNode));
+		}
+
+		public void nodeParsed(IStructuredDocumentRegion aCoreFlatNode) {
+			// could test > 1, but since we only care if there are 8 (<%@,
+			// taglib, uri, =, where, prefix, =, what) [or 4 for includes]
+			if (aCoreFlatNode.getNumberOfRegions() > 4 && aCoreFlatNode.getRegions().get(1).getType() == DOMJSPRegionContexts.JSP_DIRECTIVE_NAME) {
+				ITextRegion name = aCoreFlatNode.getRegions().get(1);
+				try {
+					int offset = aCoreFlatNode.getStartOffset(name);
+					int length = name.getTextLength();
+					boolean taglibdetected = false;
+					boolean taglibdirectivedetected = false;
+					if (fCharSequenceSource instanceof IRegionComparible) {
+						taglibdetected = ((IRegionComparible) fCharSequenceSource).regionMatches(offset, length, JSP12TLDNames.TAGLIB);
+						taglibdirectivedetected = ((IRegionComparible) fCharSequenceSource).regionMatches(offset, length, JSP12Namespace.ElementName.DIRECTIVE_TAGLIB);
+					}
+					else {
+						// old fashioned way
+						String directiveName = getText(offset, length);
+						taglibdetected = directiveName.equals(JSP12TLDNames.TAGLIB);
+						taglibdirectivedetected = directiveName.equals(JSP12Namespace.ElementName.DIRECTIVE_TAGLIB);
+					}
+					boolean processDirectiveName = taglibdetected || taglibdirectivedetected;
+					if (processDirectiveName) {
+						processTaglib(aCoreFlatNode);
+					}
+				}
+				catch (StringIndexOutOfBoundsException sioobExc) {
+					// do nothing
+				}
+			}
+			// could test > 1, but since we only care if there are 5 (<,
+			// jsp:root, xmlns:prefix, =, where)
+			else if (aCoreFlatNode.getNumberOfRegions() > 4 && (aCoreFlatNode.getRegions().get(1)).getType() == DOMJSPRegionContexts.JSP_ROOT_TAG_NAME) {
+				processJSPRoot(aCoreFlatNode);
+			}
+		}
+
+		protected void processJSPRoot(IStructuredDocumentRegion taglibFlatNode) {
+			ITextRegionList regions = taglibFlatNode.getRegions();
+			String prefix = null;
+			boolean taglib = false;
+			try {
+				for (int i = 0; i < regions.size(); i++) {
+					ITextRegion region = regions.get(i);
+					if (region.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) {
+						int offset = taglibFlatNode.getStartOffset(region);
+						int length = region.getTextLength();
+
+						String name = getText(offset, length);
+						if (name.startsWith(XMLNS) && name.length() > XMLNS.length()) { //$NON-NLS-1$
+							prefix = name.substring(6);
+							taglib = true;
+						}
+						else {
+							prefix = null;
+							taglib = false;
+						}
+					}
+					else if (taglib && region.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
+						prefix = StringUtils.strip(prefix);
+						if (prefix != null && prefix.length() > 0) {
+							enableForTaglib(prefix, taglibFlatNode);
+							prefix = null;
+						}
+					}
+				}
+			}
+			catch (StringIndexOutOfBoundsException sioobExc) {
+				// nothing to be done
+				prefix = null;
+			}
+		}
+
+		/**
+		 * Pulls the prefix from the given taglib directive
+		 * IStructuredDocumentRegion and makes sure the prefix is nestable.
+		 */
+		protected void processTaglib(IStructuredDocumentRegion taglibFlatNode) {
+			ITextRegionList regions = taglibFlatNode.getRegions();
+			String prefix = null;
+			boolean prefixname = false;
+			try {
+				for (int i = 0; i < regions.size(); i++) {
+					ITextRegion region = regions.get(i);
+					if (region.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) {
+						if (fCharSequenceSource != null && fCharSequenceSource instanceof IRegionComparible) {
+							int offset = taglibFlatNode.getStartOffset(region);
+							int length = region.getTextLength();
+							prefixname = ((IRegionComparible) fCharSequenceSource).regionMatches(offset, length, JSP12TLDNames.PREFIX);
+						}
+						else {
+							// old fashioned way
+							prefixname = (getText(taglibFlatNode.getStartOffset(region), region.getTextLength()).equals(JSP12TLDNames.PREFIX));
+						}
+					}
+					else if (prefixname && region.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
+						prefix = getText(taglibFlatNode.getStartOffset(region), region.getTextLength());
+					}
+				}
+			}
+			catch (StringIndexOutOfBoundsException sioobExc) {
+				// nothing to be done
+				prefix = null;
+			}
+			prefix = StringUtils.strip(prefix);
+			if (prefix != null && prefix.length() > 0) {
+				enableForTaglib(prefix, taglibFlatNode);
+			}
+		}
+
+		public void resetNodes() {
+			Iterator tagmarkers = ((JSPTokenizer) getTokenizer()).getNestablePrefixes().iterator();
+			while (tagmarkers.hasNext()) {
+				if (!((TagMarker) tagmarkers.next()).isGlobal())
+					tagmarkers.remove();
+			}
+		}
+
+		public void setStructuredDocument(IStructuredDocument newDocument) {
+			resetNodes();
+			getStructuredDocumentRegionHandlers().remove(this);
+			if (newDocument != null && newDocument.getParser() instanceof StructuredDocumentRegionParser) {
+				((StructuredDocumentRegionParser) newDocument.getParser()).addStructuredDocumentRegionHandler(this);
+			}
+		}
+	}
+
+	/**
+	 * JSPSourceParser constructor comment.
+	 */
+	public JSPSourceParser() {
+		super();
+	}
+
+	public void addNestablePrefix(TagMarker marker) {
+		((JSPTokenizer) getTokenizer()).addNestablePrefix(marker);
+	}
+
+	public List getNestablePrefixes() {
+		return ((JSPTokenizer) getTokenizer()).getNestablePrefixes();
+	}
+
+	protected BlockTokenizer getTokenizer() {
+		if (fTokenizer == null) {
+			fTokenizer = new JSPTokenizer();
+			getStructuredDocumentRegionHandlers().add(new NestablePrefixHandler());
+		}
+		return fTokenizer;
+	}
+
+
+	public RegionParser newInstance() {
+		JSPSourceParser newInstance = new JSPSourceParser();
+		newInstance.setTokenizer(getTokenizer().newInstance());
+		return newInstance;
+	}
+
+	protected IStructuredDocumentRegion parseNodes() {
+		// regions are initially reported as complete offsets within the
+		// scanned input
+		// they are adjusted here to be indexes from the currentNode's start
+		// offset
+		IStructuredDocumentRegion headNode = null;
+		IStructuredDocumentRegion lastNode = null;
+		ITextRegion region = null;
+		// DMW: 2/12/03. Made current node local variable, since
+		// we changed class to not require state
+		IStructuredDocumentRegion currentNode = null;
+		String type = null;
+
+		while ((region = getNextRegion()) != null) {
+			type = region.getType();
+			// these types (might) demand a IStructuredDocumentRegion for each
+			// of them
+			if (type == DOMRegionContext.BLOCK_TEXT) {
+				if (currentNode != null && currentNode.getLastRegion().getType() == DOMRegionContext.BLOCK_TEXT) {
+					// multiple block texts indicated embedded containers; no
+					// new IStructuredDocumentRegion
+					currentNode.addRegion(region);
+					currentNode.setLength(region.getStart() + region.getLength() - currentNode.getStart());
+					region.adjustStart(-currentNode.getStart());
+					// DW, 4/16/2003 token regions no longer have parents
+					// region.setParent(currentNode);
+					if (region instanceof ITextRegionContainer) {
+						((ITextRegionContainer) region).setParent(currentNode);
+					}
+				}
+				else {
+					// not continuing a IStructuredDocumentRegion
+					if (currentNode != null) {
+						// ensure that any existing node is at least
+						// terminated
+						if (!currentNode.isEnded()) {
+							currentNode.setLength(region.getStart() - currentNode.getStart());
+							// fCurrentNode.setTextLength(region.getStart() -
+							// fCurrentNode.getStart());
+						}
+						lastNode = currentNode;
+					}
+					fireNodeParsed(currentNode);
+					currentNode = createStructuredDocumentRegion(type);
+					if (lastNode != null) {
+						lastNode.setNext(currentNode);
+					}
+					currentNode.setPrevious(lastNode);
+					currentNode.setStart(region.getStart());
+					currentNode.setLength(region.getStart() + region.getLength() - currentNode.getStart());
+					currentNode.setEnded(true);
+					region.adjustStart(-currentNode.getStart());
+					currentNode.addRegion(region);
+					// DW, 4/16/2003 token regions no longer have parents
+					// region.setParent(currentNode);
+					if (region instanceof ITextRegionContainer) {
+						((ITextRegionContainer) region).setParent(currentNode);
+					}
+
+				}
+			}
+			// the following contexts OPEN new StructuredDocumentRegions
+			else if ((currentNode != null && currentNode.isEnded()) || (type == DOMRegionContext.XML_CONTENT) || (type == DOMRegionContext.XML_CHAR_REFERENCE) || (type == DOMRegionContext.XML_ENTITY_REFERENCE) || (type == DOMRegionContext.XML_PI_OPEN) || (type == DOMRegionContext.XML_TAG_OPEN) || (type == DOMRegionContext.XML_END_TAG_OPEN) || (type == DOMRegionContext.XML_COMMENT_OPEN) || (type == DOMRegionContext.XML_CDATA_OPEN) || (type == DOMRegionContext.XML_DECLARATION_OPEN) || (type == DOMJSPRegionContexts.JSP_COMMENT_OPEN) || (type == DOMJSPRegionContexts.JSP_DECLARATION_OPEN) || (type == DOMJSPRegionContexts.JSP_DIRECTIVE_OPEN) || (type == DOMJSPRegionContexts.JSP_EXPRESSION_OPEN) || (type == DOMJSPRegionContexts.JSP_SCRIPTLET_OPEN) || (type == DOMJSPRegionContexts.JSP_CLOSE) || type == DOMJSPRegionContexts.JSP_EL_OPEN) {
+				if (currentNode != null) {
+					// ensure that any existing node is at least terminated
+					if (!currentNode.isEnded()) {
+						currentNode.setLength(region.getStart() - currentNode.getStart());
+						// fCurrentNode.setTextLength(region.getStart() -
+						// fCurrentNode.getStart());
+					}
+					lastNode = currentNode;
+				}
+				fireNodeParsed(currentNode);
+				currentNode = createStructuredDocumentRegion(type);
+				if (lastNode != null) {
+					lastNode.setNext(currentNode);
+				}
+				currentNode.setPrevious(lastNode);
+				currentNode.setStart(region.getStart());
+				currentNode.addRegion(region);
+				currentNode.setLength(region.getStart() + region.getLength() - currentNode.getStart());
+				region.adjustStart(-currentNode.getStart());
+				// DW, 4/16/2003 token regions no longer have parents
+				// region.setParent(currentNode);
+				if (region instanceof ITextRegionContainer) {
+					((ITextRegionContainer) region).setParent(currentNode);
+				}
+
+			}
+			// the following contexts NEITHER open nor close
+			// StructuredDocumentRegions; just add to them
+			else if ((type == DOMRegionContext.XML_TAG_NAME) || (type == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) || (type == DOMRegionContext.XML_TAG_ATTRIBUTE_EQUALS) || (type == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) || (type == DOMRegionContext.XML_COMMENT_TEXT) || (type == DOMRegionContext.XML_PI_CONTENT) || (type == DOMRegionContext.XML_DOCTYPE_INTERNAL_SUBSET) || (type == DOMJSPRegionContexts.JSP_COMMENT_TEXT) || (type == DOMJSPRegionContexts.JSP_ROOT_TAG_NAME) || (type == DOMJSPRegionContexts.JSP_DIRECTIVE_NAME) || type == DOMJSPRegionContexts.JSP_EL_CONTENT) {
+				currentNode.addRegion(region);
+				currentNode.setLength(region.getStart() + region.getLength() - currentNode.getStart());
+				region.adjustStart(-currentNode.getStart());
+				// DW, 4/16/2003 token regions no longer have parents
+				// region.setParent(currentNode);
+				if (region instanceof ITextRegionContainer) {
+					((ITextRegionContainer) region).setParent(currentNode);
+				}
+			}
+			// the following contexts close off StructuredDocumentRegions
+			// cleanly
+			else if ((type == DOMRegionContext.XML_PI_CLOSE) || (type == DOMRegionContext.XML_TAG_CLOSE) || (type == DOMRegionContext.XML_EMPTY_TAG_CLOSE) || (type == DOMRegionContext.XML_COMMENT_CLOSE) || (type == DOMRegionContext.XML_CDATA_CLOSE) || (type == DOMJSPRegionContexts.JSP_CLOSE) || (type == DOMJSPRegionContexts.JSP_COMMENT_CLOSE) || (type == DOMJSPRegionContexts.JSP_DIRECTIVE_CLOSE) || (type == DOMRegionContext.XML_DECLARATION_CLOSE) || type == DOMJSPRegionContexts.JSP_EL_CLOSE) {
+				currentNode.setEnded(true);
+				currentNode.setLength(region.getStart() + region.getLength() - currentNode.getStart());
+				currentNode.addRegion(region);
+				region.adjustStart(-currentNode.getStart());
+				// DW, 4/16/2003 token regions no longer have parents
+				// region.setParent(currentNode);
+				if (region instanceof ITextRegionContainer) {
+					((ITextRegionContainer) region).setParent(currentNode);
+				}
+			}
+			// this is extremely rare, but valid
+			else if (type == DOMRegionContext.WHITE_SPACE) {
+				ITextRegion lastRegion = currentNode.getLastRegion();
+				// pack the embedded container with this region
+				if (lastRegion instanceof ITextRegionContainer) {
+					ITextRegionContainer container = (ITextRegionContainer) lastRegion;
+					container.getRegions().add(region);
+					// DW, 4/16/2003 container regions have parent. Probably a
+					// better place to set,
+					// but for now, will (re)set each time through
+					container.setParent(currentNode);
+					// DW, 4/16/2003 token regions no longer have parents
+					// region.setParent(container);
+					region.adjustStart(container.getLength() - region.getStart());
+				}
+				currentNode.getLastRegion().adjustLength(region.getLength());
+				currentNode.adjustLength(region.getLength());
+			}
+			else if (type == DOMRegionContext.UNDEFINED && currentNode != null) {
+				// skip on a very-first region situation as the default
+				// behavior is good enough
+				// combine with previous if also undefined
+				if (currentNode.getLastRegion() != null && currentNode.getLastRegion().getType() == DOMRegionContext.UNDEFINED) {
+					currentNode.getLastRegion().adjustLength(region.getLength());
+					currentNode.adjustLength(region.getLength());
+
+					//if adding this region to a previous container then need to add this
+					//region to the container and update its start location
+					if(currentNode.getLastRegion() instanceof ITextRegionContainer) {
+						region.adjustStart(-currentNode.getLastRegion().getStart() - currentNode.getStart());
+						((ITextRegionContainer)currentNode.getLastRegion()).getRegions().add(region);
+					}
+				}
+				// previous wasn't undefined
+				else {
+					currentNode.addRegion(region);
+					currentNode.setLength(region.getStart() + region.getLength() - currentNode.getStart());
+					region.adjustStart(-currentNode.getStart());
+				}
+				if (region instanceof ITextRegionContainer) {
+					((ITextRegionContainer) region).setParent(currentNode);
+				}
+			}
+			else {
+				// if an unknown type is the first region in the document,
+				// ensure that a node exists
+				if (currentNode == null) {
+					currentNode = createStructuredDocumentRegion(type);
+					currentNode.setStart(region.getStart());
+				}
+				currentNode.addRegion(region);
+				currentNode.setLength(region.getStart() + region.getLength() - currentNode.getStart());
+				region.adjustStart(-currentNode.getStart());
+				// DW, 4/16/2003 token regions no longer have parents
+				// region.setParent(currentNode);
+				if (region instanceof ITextRegionContainer) {
+					((ITextRegionContainer) region).setParent(currentNode);
+				}
+
+				if (Debug.debugTokenizer)
+					System.out.println(getClass().getName() + " found region of not specifically handled type " + region.getType() + " @ " + region.getStart() + "[" + region.getLength() + "]");//$NON-NLS-4$//$NON-NLS-3$//$NON-NLS-2$//$NON-NLS-1$
+
+			}
+
+			// these regions also get their own node, so close them cleanly
+			// NOTE: these regions have new StructuredDocumentRegions created
+			// for them above; it may
+			// be more readable if that is handled here as well, but the
+			// current layout
+			// ensures that they open StructuredDocumentRegions the same way
+			if ((type == DOMRegionContext.XML_CONTENT) || (type == DOMRegionContext.XML_CHAR_REFERENCE) || (type == DOMRegionContext.XML_ENTITY_REFERENCE) || (type == DOMJSPRegionContexts.JSP_DECLARATION_OPEN) || (type == DOMJSPRegionContexts.JSP_EXPRESSION_OPEN) || (type == DOMJSPRegionContexts.JSP_SCRIPTLET_OPEN) || (type == DOMJSPRegionContexts.JSP_CONTENT) || (type == DOMJSPRegionContexts.JSP_CLOSE)) {
+				currentNode.setEnded(true);
+			}
+			if (headNode == null && currentNode != null) {
+				headNode = currentNode;
+			}
+		}
+		if (currentNode != null) {
+			fireNodeParsed(currentNode);
+			currentNode.setPrevious(lastNode);
+		}
+		primReset();
+		return headNode;
+	}
+
+	public void removeNestablePrefix(String tagName) {
+		((JSPTokenizer) getTokenizer()).removeNestablePrefix(tagName);
+	}
+
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/parser/internal/JSPParserRegionFactory.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/parser/internal/JSPParserRegionFactory.java
new file mode 100644
index 0000000..0d36dae
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/parser/internal/JSPParserRegionFactory.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.parser.internal;
+
+import org.eclipse.jst.jsp.core.internal.regions.DOMJSPRegionContexts;
+import org.eclipse.wst.sse.core.internal.parser.ForeignRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+import org.eclipse.wst.xml.core.internal.parser.regions.XMLParserRegionFactory;
+
+/**
+ * 
+ * This region factory is very specific to the parser output, and the specific
+ * implementation classes for various regions.
+ */
+public class JSPParserRegionFactory extends XMLParserRegionFactory {
+	public JSPParserRegionFactory() {
+		super();
+	}
+
+	public ITextRegion createToken(String context, int start, int textLength, int length, String lang, String surroundingTag) {
+		ITextRegion newRegion = null;
+		if (context == DOMJSPRegionContexts.JSP_CONTENT) {
+			newRegion = new ForeignRegion(context, start, textLength, length);
+		}
+		else
+			newRegion = super.createToken(context, start, textLength, length, lang, surroundingTag);
+		return newRegion;
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/parser/internal/JSPStructuredRegionFactory.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/parser/internal/JSPStructuredRegionFactory.java
new file mode 100644
index 0000000..498ed94
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/parser/internal/JSPStructuredRegionFactory.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.parser.internal;
+
+import org.eclipse.jst.jsp.core.internal.parser.JSPDirectiveStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.xml.core.internal.parser.XMLStructuredRegionFactory;
+
+/**
+ * A simple class to generate instances of StructuredRegions. 
+ */
+public class JSPStructuredRegionFactory extends XMLStructuredRegionFactory {
+
+	public static IStructuredDocumentRegion createRegion(int type) {
+		IStructuredDocumentRegion instance = null;
+		switch (type) {
+			case JSP_DIRECTIVE :
+				instance = new JSPDirectiveStructuredDocumentRegion();
+				break;
+			default :
+				instance = XMLStructuredRegionFactory.createRegion(type);
+		}
+		return instance;
+	}
+
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/parser/internal/JSPTokenizer.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/parser/internal/JSPTokenizer.java
new file mode 100644
index 0000000..917fe31
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/parser/internal/JSPTokenizer.java
@@ -0,0 +1,4029 @@
+/* The following code was generated by JFlex 1.2.2 on 5/2/11 2:19 PM */
+
+/*******************************************************************************
+ * Copyright (c) 2004, 2011 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.parser.internal;
+
+import java.io.CharArrayReader;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.jst.jsp.core.internal.Logger;
+import org.eclipse.jst.jsp.core.internal.regions.DOMJSPRegionContexts;
+import org.eclipse.wst.sse.core.internal.ltk.parser.BlockMarker;
+import org.eclipse.wst.sse.core.internal.ltk.parser.BlockTokenizer;
+import org.eclipse.wst.sse.core.internal.ltk.parser.TagMarker;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList;
+import org.eclipse.wst.sse.core.internal.util.Debug;
+import org.eclipse.wst.sse.core.utils.StringUtils;
+import org.eclipse.wst.xml.core.internal.parser.ContextRegionContainer;
+import org.eclipse.wst.xml.core.internal.parser.IntStack;
+
+
+/**
+ * This class is a scanner generated by 
+ * <a href="http://www.informatik.tu-muenchen.de/~kleing/jflex/">JFlex</a> 1.2.2
+ * on 5/2/11 2:19 PM from the specification file
+ * <tt>file:/C:/dev/workspaces/helios/org.eclipse.wst.sse.core/DevTimeSupport/SedModel/HTMLTokenizer/devel/JSPTokenizer.jflex</tt>
+ */
+public class JSPTokenizer implements BlockTokenizer, DOMJSPRegionContexts {
+
+  /** this character denotes the end of file */
+  final public static int YYEOF = -1;
+
+  /** lexical states */
+  final public static int ST_JSP_VBL_DQUOTES = 52;
+  final public static int ST_JSP_VBL_SQUOTES = 51;
+  final public static int ST_JSP_VBL_SQUOTES_END = 53;
+  final public static int ST_XML_COMMENT_END = 4;
+  final public static int ST_JSP_DIRECTIVE_ATTRIBUTE_VALUE = 21;
+  final public static int ST_JSP_EL_SQUOTES_END = 46;
+  final public static int ST_JSP_EL_DQUOTES = 45;
+  final public static int ST_JSP_EL = 43;
+  final public static int ST_BLOCK_TAG_SCAN = 36;
+  final public static int ST_JSP_EL_SQUOTES = 44;
+  final public static int ST_DHTML_ATTRIBUTE_VALUE = 14;
+  final public static int ST_XML_PI_ATTRIBUTE_NAME = 8;
+  final public static int ST_DHTML_TAG_CLOSE = 15;
+  final public static int ST_XML_ATTRIBUTE_VALUE_DQUOTED = 42;
+  final public static int ST_DHTML_EQUALS = 13;
+  final public static int ST_XML_PI_ATTRIBUTE_VALUE = 10;
+  final public static int ST_XML_ATTRIBUTE_VALUE = 25;
+  final public static int ST_JSP_VBL = 50;
+  final public static int ST_JSP_SQUOTED_VBL = 56;
+  final public static int ST_XML_ATTRIBUTE_VALUE_SQUOTED = 41;
+  final public static int ST_XML_ATTRIBUTE_NAME = 23;
+  final public static int ST_XML_EQUALS = 24;
+  final public static int YYINITIAL = 0;
+  final public static int ST_JSP_DIRECTIVE_ATTRIBUTE_NAME = 19;
+  final public static int ST_JSP_CONTENT = 16;
+  final public static int ST_XML_DOCTYPE_ID_SYSTEM = 31;
+  final public static int ST_XML_ELEMENT_DECLARATION = 32;
+  final public static int ST_XML_DECLARATION_CLOSE = 27;
+  final public static int ST_JSP_DIRECTIVE_EQUALS = 20;
+  final public static int ST_JSP_VBL_DQUOTES_END = 54;
+  final public static int ST_JSP_DQUOTED_EL = 48;
+  final public static int ST_XML_DOCTYPE_DECLARATION = 28;
+  final public static int ST_CDATA_END = 2;
+  final public static int ST_PI_WS = 6;
+  final public static int ST_CDATA_TEXT = 1;
+  final public static int ST_JSP_DIRECTIVE_NAME_WHITESPACE = 18;
+  final public static int ST_XML_ELEMENT_DECLARATION_CONTENT = 33;
+  final public static int ST_XML_ATTLIST_DECLARATION = 34;
+  final public static int ST_JSP_EL_DQUOTES_END = 47;
+  final public static int ST_JSP_SQUOTED_EL = 49;
+  final public static int ST_JSP_COMMENT_END = 39;
+  final public static int ST_XML_PI_EQUALS = 9;
+  final public static int ST_XML_ATTLIST_DECLARATION_CONTENT = 35;
+  final public static int ST_XML_DOCTYPE_ID_PUBLIC = 30;
+  final public static int ST_JSP_DQUOTED_VBL = 55;
+  final public static int ST_DHTML_ATTRIBUTE_NAME = 12;
+  final public static int ST_ABORT_EMBEDDED = 37;
+  final public static int ST_XML_DOCTYPE_EXTERNAL_ID = 29;
+  final public static int ST_JSP_COMMENT = 38;
+  final public static int ST_PI_CONTENT = 7;
+  final public static int ST_BLOCK_TAG_INTERNAL_SCAN = 37;
+  final public static int ST_PI = 5;
+  final public static int ST_XML_DECLARATION = 26;
+  final public static int ST_JSP_DIRECTIVE_NAME = 17;
+  final public static int ST_XML_TAG_NAME = 22;
+  final public static int ST_XML_PI_TAG_CLOSE = 11;
+  final public static int ST_XML_COMMENT = 3;
+  final public static int ST_JSP_ATTRIBUTE_VALUE = 40;
+
+  /** 
+   * Translates characters to character classes
+   */
+  final private static String yycmap_packed = 
+    "\11\0\1\5\1\27\2\0\1\20\22\0\1\20\1\26\1\12\1\66"+
+    "\1\15\1\23\1\13\1\14\1\25\1\25\1\25\1\25\1\25\1\7"+
+    "\1\6\1\3\12\21\1\11\1\73\1\1\1\52\1\2\1\4\1\22"+
+    "\1\41\1\74\1\37\1\40\1\56\1\71\1\63\1\63\1\64\1\63"+
+    "\1\63\1\34\1\32\1\65\1\53\1\55\1\63\1\70\1\67\1\42"+
+    "\1\72\2\63\1\30\1\54\1\63\1\36\1\17\1\24\1\0\1\10"+
+    "\1\0\1\60\1\104\1\75\1\61\1\44\1\71\1\76\1\106\1\47"+
+    "\1\101\1\63\1\35\1\33\1\51\1\50\1\102\1\63\1\45\1\46"+
+    "\1\57\1\103\1\43\1\63\1\31\1\62\1\63\1\16\1\0\1\105"+
+    "\71\0\1\100\10\0\27\77\1\0\37\77\1\0\72\77\2\0\13\77"+
+    "\2\0\10\77\1\0\65\77\1\0\104\77\11\0\44\77\3\0\2\77"+
+    "\4\0\36\77\70\0\131\77\22\0\7\77\16\0\2\100\56\0\106\100"+
+    "\32\0\2\100\44\0\1\77\1\100\3\77\1\0\1\77\1\0\24\77"+
+    "\1\0\54\77\1\0\7\77\3\0\1\77\1\0\1\77\1\0\1\77"+
+    "\1\0\1\77\1\0\22\77\15\0\14\77\1\0\102\77\1\0\14\77"+
+    "\1\0\44\77\1\0\4\100\11\0\65\77\2\0\2\77\2\0\2\77"+
+    "\3\0\34\77\2\0\10\77\2\0\2\77\67\0\46\77\2\0\1\77"+
+    "\7\0\46\77\12\0\21\100\1\0\27\100\1\0\3\100\1\0\1\100"+
+    "\1\0\2\100\1\0\1\100\13\0\33\77\5\0\3\77\56\0\32\77"+
+    "\5\0\1\100\12\77\10\100\15\0\12\100\6\0\1\100\107\77\2\0"+
+    "\5\77\1\0\17\77\1\0\4\77\1\0\1\77\17\100\2\77\2\100"+
+    "\1\0\4\100\2\0\12\100\u0207\0\3\100\1\0\65\77\2\0\1\100"+
+    "\1\77\20\100\3\0\4\100\3\0\12\77\2\100\2\0\12\100\21\0"+
+    "\3\100\1\0\10\77\2\0\2\77\2\0\26\77\1\0\7\77\1\0"+
+    "\1\77\3\0\4\77\2\0\1\100\1\0\7\100\2\0\2\100\2\0"+
+    "\3\100\11\0\1\100\4\0\2\77\1\0\3\77\2\100\2\0\12\100"+
+    "\2\77\20\0\1\100\2\0\6\77\4\0\2\77\2\0\26\77\1\0"+
+    "\7\77\1\0\2\77\1\0\2\77\1\0\2\77\2\0\1\100\1\0"+
+    "\5\100\4\0\2\100\2\0\3\100\13\0\4\77\1\0\1\77\7\0"+
+    "\12\100\2\100\3\77\14\0\3\100\1\0\7\77\1\0\1\77\1\0"+
+    "\3\77\1\0\26\77\1\0\7\77\1\0\2\77\1\0\5\77\2\0"+
+    "\1\100\1\77\10\100\1\0\3\100\1\0\3\100\22\0\1\77\5\0"+
+    "\12\100\21\0\3\100\1\0\10\77\2\0\2\77\2\0\26\77\1\0"+
+    "\7\77\1\0\2\77\2\0\4\77\2\0\1\100\1\77\6\100\3\0"+
+    "\2\100\2\0\3\100\10\0\2\100\4\0\2\77\1\0\3\77\4\0"+
+    "\12\100\22\0\2\100\1\0\6\77\3\0\3\77\1\0\4\77\3\0"+
+    "\2\77\1\0\1\77\1\0\2\77\3\0\2\77\3\0\3\77\3\0"+
+    "\10\77\1\0\3\77\4\0\5\100\3\0\3\100\1\0\4\100\11\0"+
+    "\1\100\17\0\11\100\21\0\3\100\1\0\10\77\1\0\3\77\1\0"+
+    "\27\77\1\0\12\77\1\0\5\77\4\0\7\100\1\0\3\100\1\0"+
+    "\4\100\7\0\2\100\11\0\2\77\4\0\12\100\22\0\2\100\1\0"+
+    "\10\77\1\0\3\77\1\0\27\77\1\0\12\77\1\0\5\77\4\0"+
+    "\7\100\1\0\3\100\1\0\4\100\7\0\2\100\7\0\1\77\1\0"+
+    "\2\77\4\0\12\100\22\0\2\100\1\0\10\77\1\0\3\77\1\0"+
+    "\27\77\1\0\20\77\4\0\6\100\2\0\3\100\1\0\4\100\11\0"+
+    "\1\100\10\0\2\77\4\0\12\100\221\0\56\77\1\0\1\77\1\100"+
+    "\2\77\7\100\5\0\6\77\1\100\10\100\1\0\12\100\47\0\2\77"+
+    "\1\0\1\77\2\0\2\77\1\0\1\77\2\0\1\77\6\0\4\77"+
+    "\1\0\7\77\1\0\3\77\1\0\1\77\1\0\1\77\2\0\2\77"+
+    "\1\0\2\77\1\0\1\77\1\100\2\77\6\100\1\0\2\100\1\77"+
+    "\2\0\5\77\1\0\1\100\1\0\6\100\2\0\12\100\76\0\2\100"+
+    "\6\0\12\100\13\0\1\100\1\0\1\100\1\0\1\100\4\0\2\100"+
+    "\10\77\1\0\41\77\7\0\24\100\1\0\6\100\4\0\6\100\1\0"+
+    "\1\100\1\0\25\100\3\0\7\100\1\0\1\100\346\0\46\77\12\0"+
+    "\47\77\11\0\1\77\1\0\2\77\1\0\3\77\1\0\1\77\1\0"+
+    "\2\77\1\0\5\77\51\0\1\77\1\0\1\77\1\0\1\77\13\0"+
+    "\1\77\1\0\1\77\1\0\1\77\3\0\2\77\3\0\1\77\5\0"+
+    "\3\77\1\0\1\77\1\0\1\77\1\0\1\77\1\0\1\77\3\0"+
+    "\2\77\3\0\2\77\1\0\1\77\50\0\1\77\11\0\1\77\2\0"+
+    "\1\77\2\0\2\77\7\0\2\77\1\0\1\77\1\0\7\77\50\0"+
+    "\1\77\4\0\1\77\10\0\1\77\u0c06\0\234\77\4\0\132\77\6\0"+
+    "\26\77\2\0\6\77\2\0\46\77\2\0\6\77\2\0\10\77\1\0"+
+    "\1\77\1\0\1\77\1\0\1\77\1\0\37\77\2\0\65\77\1\0"+
+    "\7\77\1\0\1\77\3\0\3\77\1\0\7\77\3\0\4\77\2\0"+
+    "\6\77\4\0\15\77\5\0\3\77\1\0\7\77\323\0\15\100\4\0"+
+    "\1\100\104\0\1\77\3\0\2\77\2\0\1\77\121\0\3\77\u0e82\0"+
+    "\1\100\1\0\1\77\31\0\11\77\6\100\1\0\5\100\13\0\124\77"+
+    "\4\0\2\100\2\0\2\100\2\0\132\77\1\0\3\100\6\0\50\77"+
+    "\u1cd3\0\u51a6\77\u0c5a\0\u2ba4\77\134\0\u0800\0\u1ffe\0\2\0";
+
+  /** 
+   * Translates characters to character classes
+   */
+  final private static char [] yycmap = yy_unpack_cmap(yycmap_packed);
+
+  /** 
+   * Translates a state to a row index in the transition table
+   */
+  final private static int yy_rowMap [] = { 
+        0,    71,   142,   213,   284,   355,   426,   497,   568,   639, 
+      710,   781,   852,   923,   994,  1065,  1136,  1207,  1278,  1349, 
+     1420,  1491,  1562,  1633,  1704,  1775,  1846,  1917,  1988,  2059, 
+     2130,  2201,  2272,  2343,  2414,  2485,  2556,  2627,  2698,  2769, 
+     2840,  2911,  2982,  3053,  3124,  3195,  3266,  3337,  3408,  3479, 
+     3550,  3621,  3692,  3763,  3834,  3905,  3976,  4047,  4118,  4189, 
+     4260,  4331,  4402,  4473,  4544,  4615,  4544,  4615,  4686,  4544, 
+     4544,  4615,  4757,  4828,  4899,  4970,  5041,  5112,  5183,  5254, 
+     4544,  4615,  5325,  5396,  5467,  4544,  5538,  5538,  5609,  5680, 
+     5751,  5325,  4544,  5822,  5893,  4544,  5964,  6035,  6106,  6177, 
+     4544,  4615,  6248,  6319,  6390,  6461,  6532,  6603,  4544,  6674, 
+     6674,  6745,  6816,  6887,  6958,  7029,  4544,  7100,  7171,  7242, 
+     7313,  7384,  7455,  4544,  7526,  7597,  7668,  7739,  7810,  7881, 
+     7952,  8023,  4544,  8094,  8165,  8236,  8307,  8378,  8449,  8520, 
+     8591,  8591,  8662,  8733,  8804,  8875,  8875,  8946,  9017,  9088, 
+     9159,  9159,  9230,  9301,  9372,  9443,  4544,  9514,  9514,  9585, 
+     9656,  9727,  9798,  4544,  4544,  4615,  4544,  4615,  9869,  9940, 
+     7597, 10011, 10082, 10153, 10224, 10295, 10366, 10437, 10508,  4544, 
+    10579, 10650, 10721, 10792,  4544, 10863, 10934, 11005, 11076,  4544, 
+     4544, 11147,  4544, 11218, 11289,  4544, 11218, 11360, 11431,  4544, 
+    11360, 11502, 11573,  4544, 11644,  4544, 11715, 11786, 11857, 11928, 
+    11999,  4544,  4544, 12070,  4544, 12141, 12212,  4544, 12141, 12283, 
+    12354,  4544, 12283, 12425, 12496, 12567,  4544, 12638, 12709, 12780, 
+     4544,  4544, 12851, 12922, 12993, 13064, 13135, 13206, 13277, 13348, 
+    13419, 13490, 13561, 13632, 13703, 13774,  4544, 13845, 13916, 13987, 
+     4544,  4544,  5538,  5680,  4544, 14058, 14129,  5751, 14200, 14271, 
+     5822,  5964,  6035, 14342,  6106,  4544, 14413, 14484, 14555,  6177, 
+    14626, 14697,  4544, 12922,  4544,  6674,  6745,  4544, 14768, 14839, 
+     6816, 14910, 14981,  4544, 15052, 15123,  7526, 15194,  7739,  4544, 
+    15265, 15336,  7810, 15407, 15478, 15549, 15620, 15691, 15762, 15833, 
+     8307,  4544, 15904, 15975,  8591,  8662,  4544, 16046, 16117, 16188, 
+    16259, 16330, 16401, 16472,  8804,  8591,  8875,  8946,  4544,  9017, 
+     9088,  8875,  9159,  9230,  4544, 16543, 16614, 16685, 16756, 16827, 
+    16898, 16969, 17040, 17111,  9514,  9585,  4544, 17182, 17253, 17324, 
+    17395, 17466, 17537, 17608, 17679, 17750, 17821,  9940, 10082,  4544, 
+    17892, 17963, 10153, 18034, 18105, 18176, 18247,  4544, 18318,  4544, 
+     4544,  4544,  4544, 18389, 18460, 18531, 18602, 11218,  4544, 18673, 
+    18744, 11360,  4544, 18815, 18886, 18957, 19028, 19099, 19170, 19241, 
+    19312, 19383, 11928, 12141,  4544, 19454, 19525, 12283,  4544, 19596, 
+    19667, 19738, 19809, 19880, 19951, 20022, 20093, 20164,  4544,  4544, 
+     4544, 20235, 20306, 20377, 20448, 20519,  4544, 20590, 20661, 20732, 
+     4544,  4544,  4544,  4544, 20803,  4544,  4544,  4970, 20874, 20945, 
+    21016, 21087, 21158, 21229, 21300, 21371, 21442, 21513, 21584, 21655, 
+    21726, 21797, 21868, 21939, 22010, 21939, 22081, 22152, 22081, 22223, 
+    22294, 22365, 22436, 22507, 22578, 22649, 22720, 22720, 22791, 22862, 
+    22933, 23004, 23004, 23075, 23146,  9372,  9372,  9372, 23217, 23288, 
+    23359, 23430, 23430, 23501, 23572,  9727,  9727,  9727, 23643, 23714, 
+    10082, 23785, 10153, 23856, 23927, 23927, 23998, 23998, 18531, 24069, 
+    11005, 11005, 11005, 24140, 24211, 11218, 11218, 11218, 24282, 24353, 
+    11360, 11360, 11360, 24424, 24495, 11502, 11502, 11502, 19099, 24566, 
+    24637, 11715, 11715, 11715, 19312, 24708, 24779, 11928, 11928, 11928, 
+    24850, 12141, 12141, 12141, 24921, 24992, 12283, 12283, 12283, 25063, 
+    25134, 12425, 12425, 12425, 19880, 25205, 25276, 12638, 12638, 12638, 
+    20093, 25347,  4544,  4544, 25418, 25489,  4544, 25560, 25631, 25702, 
+    25773, 25844, 25915,  7526,  4544,  4544, 25986, 26057, 26128, 26199, 
+    26270, 16330, 16827,  9372, 26341, 17466,  9727, 26412,  4544,  9940, 
+    11005, 11218, 26483, 11360, 26554, 11502, 26625,  4544, 11715, 26696, 
+    11928, 12141, 26767, 12283, 26838, 12425, 26909,  4544, 12638, 26980, 
+    27051, 27122, 27193, 27264, 27335, 27406, 27477, 27548, 27619, 27690, 
+    27761, 27832, 27903, 27974, 28045, 28116, 28187, 28258, 28329, 28400, 
+    28471, 28542,  4970, 28613, 28684, 28755, 28826, 28897,  4544,  4544, 
+    28968, 29039, 29110, 29181, 19099, 19312, 29252, 29323, 19880, 20093, 
+    29394, 29465, 29536, 29607,  4544,  4544,  4544, 29678, 29749, 29820, 
+    29891, 29962, 30033, 30104, 30175,  7242, 30246, 30317, 30388, 30459, 
+    30530, 30601, 30672,  4544, 30743, 30814,  9372,  9727, 11218, 11360, 
+    12141, 12283, 30885, 30956, 31027, 31098, 31169, 31240, 31311, 31382, 
+     4970, 31453, 31524, 31595, 31666, 31737, 31808, 31879, 31950, 32021, 
+    32092, 32163, 32234, 32305, 32376, 32447, 32518, 32589, 32660, 32731, 
+    32802, 32873, 32944, 33015, 33086, 33157, 33228, 33299, 33370, 33441, 
+    33512, 33583, 33654, 33725, 33796, 33867, 33938,  4544, 34009, 34080, 
+    34151, 34222,  7242, 34293, 34364, 34435, 34506, 34577, 34648, 34719, 
+    34790, 34861, 34932, 35003, 35074, 35145, 35216
+  };
+
+  /** 
+   * The packed transition table of the DFA
+   */
+  final private static String yy_packed = 
+    "\1\72\1\73\11\72\1\74\1\72\1\75\1\72\1\76"+
+    "\3\72\1\77\42\72\1\100\20\72\1\101\1\102\105\101"+
+    "\1\103\1\104\22\103\1\105\2\103\1\106\57\103\1\107"+
+    "\1\110\105\107\1\103\1\104\5\103\1\111\17\103\1\106"+
+    "\60\103\1\104\2\103\1\112\1\113\2\103\2\114\6\103"+
+    "\1\113\6\103\1\113\1\115\1\116\4\114\1\103\10\114"+
+    "\1\117\2\114\1\103\11\114\1\117\1\114\1\103\4\114"+
+    "\1\103\4\114\1\103\4\114\1\103\1\114\1\103\1\104"+
+    "\2\103\1\112\1\120\12\103\1\120\6\103\1\120\57\103"+
+    "\1\121\1\122\2\121\1\123\22\121\1\106\57\121\1\103"+
+    "\1\104\2\103\1\124\1\113\2\103\2\125\6\103\1\113"+
+    "\6\103\1\113\6\125\1\103\13\125\1\103\13\125\1\103"+
+    "\4\125\1\103\4\125\1\103\4\125\1\103\1\125\1\103"+
+    "\1\104\2\103\1\124\1\113\2\103\2\125\6\103\1\113"+
+    "\6\103\1\113\6\125\1\103\13\125\1\126\13\125\1\103"+
+    "\4\125\1\103\4\125\1\103\4\125\1\103\1\125\1\127"+
+    "\1\104\1\103\1\130\1\131\1\113\4\127\1\132\1\127"+
+    "\1\133\3\127\1\113\6\127\1\113\57\127\1\103\1\104"+
+    "\2\103\1\134\22\103\1\106\60\103\1\104\1\135\1\136"+
+    "\1\103\1\113\2\103\2\137\6\103\1\113\6\103\1\113"+
+    "\6\137\1\103\13\137\1\103\13\137\1\103\4\137\1\103"+
+    "\4\137\1\103\4\137\1\103\1\137\1\103\1\104\1\135"+
+    "\1\136\1\103\1\113\2\103\2\137\6\103\1\113\6\103"+
+    "\1\113\6\137\1\103\13\137\1\140\13\137\1\103\4\137"+
+    "\1\103\4\137\1\103\4\137\1\103\1\137\1\141\1\104"+
+    "\1\135\1\142\1\141\1\113\4\141\1\143\1\141\1\144"+
+    "\3\141\1\113\6\141\1\113\57\141\1\103\1\104\3\103"+
+    "\1\113\12\103\1\113\6\103\1\113\57\103\1\145\1\146"+
+    "\21\145\1\147\63\145\1\103\1\150\3\103\1\113\2\103"+
+    "\2\151\6\103\1\113\2\103\1\152\3\103\1\113\6\151"+
+    "\1\103\13\151\1\103\13\151\1\103\4\151\1\103\4\151"+
+    "\1\103\4\151\1\103\1\151\1\103\1\150\3\103\1\153"+
+    "\12\103\1\153\2\103\1\152\3\103\1\153\60\103\1\150"+
+    "\3\103\1\113\2\103\2\154\6\103\1\113\2\103\1\152"+
+    "\3\103\1\113\6\154\1\103\13\154\1\103\13\154\1\103"+
+    "\4\154\1\103\4\154\1\103\4\154\1\103\1\154\1\103"+
+    "\1\150\3\103\1\113\2\103\2\154\6\103\1\113\2\103"+
+    "\1\152\3\103\1\113\6\154\1\103\13\154\1\155\13\154"+
+    "\1\103\4\154\1\103\4\154\1\103\4\154\1\103\1\154"+
+    "\1\156\1\150\1\103\1\157\1\156\1\113\4\156\1\160"+
+    "\1\156\1\161\3\156\1\113\2\156\1\162\3\156\1\113"+
+    "\57\156\1\163\1\164\1\165\1\166\4\163\2\167\16\163"+
+    "\6\170\1\163\13\170\1\163\13\170\1\163\4\170\1\163"+
+    "\4\170\1\163\1\171\3\170\1\163\1\170\1\103\1\172"+
+    "\1\165\1\166\1\103\1\113\2\103\2\173\6\103\1\113"+
+    "\6\103\1\113\6\173\1\103\13\173\1\103\13\173\1\103"+
+    "\4\173\1\103\4\173\1\103\4\173\1\103\1\173\1\103"+
+    "\1\172\1\165\1\166\1\103\1\113\2\103\2\173\6\103"+
+    "\1\113\6\103\1\113\6\173\1\103\13\173\1\174\13\173"+
+    "\1\103\4\173\1\103\4\173\1\103\4\173\1\103\1\173"+
+    "\1\175\1\176\1\165\1\177\1\175\1\113\4\175\1\200"+
+    "\1\175\1\201\1\202\2\175\1\113\6\175\1\113\36\175"+
+    "\1\203\20\175\1\103\1\204\1\205\2\103\1\113\12\103"+
+    "\1\113\6\103\1\113\10\103\1\206\1\207\2\103\1\210"+
+    "\11\103\1\210\1\103\1\207\1\206\26\103\1\104\1\205"+
+    "\2\103\1\113\12\103\1\113\6\103\1\113\6\103\1\211"+
+    "\51\103\1\104\1\205\2\103\1\113\2\103\2\212\6\103"+
+    "\1\113\6\103\1\113\6\212\1\211\13\212\1\103\13\212"+
+    "\1\103\4\212\1\103\4\212\1\103\4\212\1\103\1\212"+
+    "\1\103\1\104\1\205\2\103\1\113\12\103\1\113\6\103"+
+    "\1\113\6\103\1\211\7\103\1\213\6\103\1\214\11\103"+
+    "\1\213\12\103\1\214\4\103\1\215\1\104\1\205\1\216"+
+    "\1\215\1\113\4\215\1\217\1\215\1\220\3\215\1\113"+
+    "\6\215\1\113\6\215\1\221\50\215\1\222\1\104\1\205"+
+    "\1\223\1\222\1\113\4\222\1\224\1\222\1\225\3\222"+
+    "\1\113\6\222\1\113\6\222\1\226\50\222\1\227\1\104"+
+    "\1\205\1\230\1\227\1\113\4\227\1\231\1\227\1\232"+
+    "\3\227\1\113\6\227\1\113\57\227\1\233\1\234\1\235"+
+    "\104\233\1\236\1\104\1\205\1\237\1\236\1\113\4\236"+
+    "\1\240\1\236\1\241\3\236\1\113\6\236\1\113\57\236"+
+    "\1\242\1\243\1\244\104\242\1\245\1\246\105\245\1\103"+
+    "\1\104\25\103\1\106\57\103\1\247\1\250\105\247\1\103"+
+    "\1\104\5\103\1\251\17\103\1\106\57\103\1\252\1\253"+
+    "\1\165\1\254\1\252\1\113\4\252\1\255\1\252\1\256"+
+    "\1\257\2\252\1\113\6\252\1\113\36\252\1\260\20\252"+
+    "\1\261\1\262\3\261\1\263\6\261\1\264\1\265\2\261"+
+    "\1\263\6\261\1\263\36\261\1\266\20\261\1\267\1\262"+
+    "\3\267\1\270\4\267\1\271\2\267\1\272\2\267\1\270"+
+    "\6\267\1\270\36\267\1\273\20\267\1\274\1\275\10\274"+
+    "\1\276\1\274\1\277\1\300\67\274\1\301\1\274\1\302"+
+    "\1\303\12\302\1\304\12\302\1\305\57\302\1\306\1\307"+
+    "\10\306\1\310\14\306\1\311\57\306\1\103\1\104\12\103"+
+    "\1\304\12\103\1\106\60\103\1\104\10\103\1\310\14\103"+
+    "\1\106\57\103\1\312\1\313\10\312\1\314\4\312\1\315"+
+    "\65\312\1\316\1\312\1\317\1\320\12\317\1\264\2\317"+
+    "\1\321\65\317\1\316\1\317\1\322\1\323\10\322\1\324"+
+    "\1\322\1\325\51\322\1\326\16\322\1\327\1\322\1\330"+
+    "\1\331\12\330\1\332\12\330\1\333\57\330\1\334\1\335"+
+    "\10\334\1\336\14\334\1\337\57\334\1\103\1\104\12\103"+
+    "\1\332\12\103\1\106\60\103\1\104\10\103\1\336\14\103"+
+    "\1\106\57\103\1\340\1\341\10\340\1\314\4\340\1\342"+
+    "\65\340\1\343\1\340\1\344\1\345\12\344\1\264\2\344"+
+    "\1\346\65\344\1\343\1\344\1\72\1\0\11\72\1\0"+
+    "\1\72\1\0\5\72\1\0\42\72\1\0\20\72\3\0"+
+    "\1\347\1\350\16\0\1\351\2\0\1\352\65\0\1\353"+
+    "\2\0\2\354\6\0\1\353\6\0\1\353\6\354\1\0"+
+    "\13\354\1\0\13\354\1\355\4\354\1\0\4\354\1\0"+
+    "\4\354\1\0\1\354\1\72\1\0\11\72\1\0\1\72"+
+    "\1\356\1\357\4\72\1\0\64\72\1\0\11\72\1\0"+
+    "\1\72\1\360\5\72\1\0\42\72\1\360\20\72\5\0"+
+    "\1\353\2\0\2\361\6\0\1\353\6\0\1\353\6\361"+
+    "\1\0\13\361\1\0\13\361\1\0\4\361\1\0\4\361"+
+    "\1\0\4\361\1\0\1\361\1\72\1\0\11\72\1\0"+
+    "\2\72\1\362\4\72\1\0\42\72\1\363\20\72\132\0"+
+    "\1\351\2\0\1\364\104\0\1\365\71\0\1\366\101\0"+
+    "\1\367\111\0\1\113\12\0\1\113\6\0\1\113\65\0"+
+    "\4\114\7\0\1\114\6\0\6\114\1\0\13\114\1\0"+
+    "\13\114\1\0\4\114\1\0\11\114\1\0\1\114\6\0"+
+    "\4\114\7\0\1\114\6\0\2\114\2\370\2\114\1\0"+
+    "\13\114\1\0\13\114\1\0\4\114\1\0\11\114\1\0"+
+    "\1\114\6\0\4\114\7\0\1\114\6\0\2\114\1\370"+
+    "\1\371\2\114\1\0\13\114\1\0\13\114\1\0\4\114"+
+    "\1\0\11\114\1\0\1\114\6\0\4\114\7\0\1\114"+
+    "\6\0\2\114\2\372\2\114\1\0\13\114\1\0\13\114"+
+    "\1\0\4\114\1\0\11\114\1\0\1\114\5\0\1\120"+
+    "\12\0\1\120\6\0\1\120\61\0\1\373\106\0\1\374"+
+    "\112\0\4\125\7\0\1\125\6\0\6\125\1\0\13\125"+
+    "\1\0\13\125\1\0\4\125\1\0\11\125\1\0\1\125"+
+    "\1\127\2\0\1\375\1\127\1\0\4\127\1\0\1\127"+
+    "\1\0\3\127\1\0\6\127\1\0\60\127\1\0\1\374"+
+    "\1\375\1\127\1\0\4\127\1\0\1\127\1\0\3\127"+
+    "\1\0\6\127\1\0\57\127\1\376\1\0\10\376\1\377"+
+    "\2\376\1\u0100\1\376\1\u0101\46\376\1\u0100\20\376\1\u0102"+
+    "\1\0\12\u0102\1\377\1\u0103\1\u0102\1\u0104\46\u0102\1\u0103"+
+    "\20\u0102\2\0\1\135\1\u0105\111\0\4\137\7\0\1\137"+
+    "\6\0\6\137\1\0\13\137\1\0\13\137\1\0\4\137"+
+    "\1\0\11\137\1\0\1\137\1\141\2\0\1\u0106\1\141"+
+    "\1\0\4\141\1\0\1\141\1\0\3\141\1\0\6\141"+
+    "\1\0\60\141\1\0\1\135\1\u0107\1\141\1\0\4\141"+
+    "\1\0\1\141\1\0\3\141\1\0\6\141\1\0\57\141"+
+    "\1\143\1\0\1\u0108\1\u0109\1\143\1\u0108\4\143\1\u010a"+
+    "\1\143\1\u0108\1\u010b\1\143\1\u010c\1\u0108\6\143\1\u0108"+
+    "\36\143\1\u010b\20\143\1\144\1\0\1\u010d\1\u010e\1\144"+
+    "\1\u010d\4\144\1\u010d\1\144\1\u010a\1\u010f\1\144\1\u0110"+
+    "\1\u010d\6\144\1\u010d\36\144\1\u010f\20\144\2\0\1\u0111"+
+    "\127\0\1\351\2\0\1\u0112\66\0\4\151\7\0\1\151"+
+    "\6\0\6\151\1\0\13\151\1\0\13\151\1\0\4\151"+
+    "\1\0\11\151\1\0\1\151\2\0\1\u0113\111\0\1\153"+
+    "\12\0\1\153\6\0\1\153\65\0\4\154\7\0\1\154"+
+    "\6\0\6\154\1\0\13\154\1\0\13\154\1\0\4\154"+
+    "\1\0\11\154\1\0\1\154\1\156\2\0\1\u0114\1\156"+
+    "\1\0\4\156\1\0\1\156\1\0\3\156\1\0\6\156"+
+    "\1\0\57\156\1\u0115\1\0\10\u0115\1\u0116\2\u0115\1\u0117"+
+    "\1\u0115\1\u0118\46\u0115\1\u0117\20\u0115\1\u0119\1\0\12\u0119"+
+    "\1\u0116\1\u011a\1\u0119\1\u011b\46\u0119\1\u011a\20\u0119\1\156"+
+    "\1\0\1\u0113\1\u0114\1\156\1\0\4\156\1\0\1\156"+
+    "\1\0\3\156\1\0\6\156\1\0\57\156\1\163\3\0"+
+    "\24\163\6\0\1\163\13\0\1\163\13\0\1\163\4\0"+
+    "\1\163\4\0\1\163\4\0\1\163\4\0\1\347\17\0"+
+    "\1\351\2\0\1\352\62\0\1\u011c\104\0\1\163\3\0"+
+    "\2\163\4\167\7\163\1\167\6\163\6\170\1\163\13\170"+
+    "\1\163\13\170\1\163\4\170\1\163\4\170\1\167\4\170"+
+    "\1\163\1\170\6\0\4\170\7\0\1\170\6\0\6\170"+
+    "\1\0\13\170\1\0\13\170\1\0\4\170\1\0\11\170"+
+    "\1\0\1\170\6\0\4\170\7\0\1\170\6\0\6\170"+
+    "\1\0\7\170\1\u011d\3\170\1\0\13\170\1\0\4\170"+
+    "\1\0\11\170\1\0\1\170\3\0\1\347\4\0\2\u011e"+
+    "\11\0\1\351\2\0\1\352\1\0\6\u011e\1\0\13\u011e"+
+    "\1\0\13\u011e\1\0\4\u011e\1\0\4\u011e\1\0\4\u011e"+
+    "\1\0\1\u011e\6\0\4\173\7\0\1\173\6\0\6\173"+
+    "\1\0\13\173\1\0\13\173\1\0\4\173\1\0\11\173"+
+    "\1\0\1\173\1\175\2\0\1\u011f\1\175\1\0\4\175"+
+    "\1\0\1\175\1\0\3\175\1\0\6\175\1\0\57\175"+
+    "\3\0\1\347\4\0\2\u0120\11\0\1\351\2\0\1\352"+
+    "\1\0\6\u0120\1\0\13\u0120\1\0\13\u0120\1\0\4\u0120"+
+    "\1\0\4\u0120\1\0\4\u0120\1\0\1\u0120\1\175\1\0"+
+    "\1\u011c\1\u011f\1\175\1\0\4\175\1\0\1\175\1\0"+
+    "\3\175\1\0\6\175\1\0\57\175\1\u0121\1\0\10\u0121"+
+    "\1\u0122\2\u0121\1\u0123\1\u0121\1\u0124\46\u0121\1\u0123\20\u0121"+
+    "\1\u0125\1\0\12\u0125\1\u0122\1\u0126\1\u0125\1\u0127\46\u0125"+
+    "\1\u0126\20\u0125\1\175\2\0\1\u011f\1\175\1\0\4\175"+
+    "\1\0\1\175\1\0\1\175\1\u0128\1\175\1\0\6\175"+
+    "\1\0\60\175\2\0\1\u011f\1\175\1\0\4\175\1\0"+
+    "\1\175\1\0\1\175\1\u0129\1\175\1\0\6\175\1\0"+
+    "\57\175\3\0\1\347\17\0\1\351\2\0\1\u0112\130\0"+
+    "\1\u012a\2\0\1\u012a\75\0\1\u012b\14\0\1\u012b\63\0"+
+    "\2\u012c\51\0\24\u012d\1\u012e\62\u012d\6\0\4\212\7\0"+
+    "\1\212\6\0\6\212\1\0\13\212\1\0\13\212\1\0"+
+    "\4\212\1\0\11\212\1\0\1\212\54\0\1\u012f\5\0"+
+    "\1\u012f\116\0\1\u0130\10\0\1\u0130\3\0\1\215\2\0"+
+    "\1\u0131\1\215\1\0\4\215\1\0\1\215\1\0\3\215"+
+    "\1\0\6\215\1\0\57\215\1\u0132\1\0\10\u0132\1\u0133"+
+    "\2\u0132\1\u0134\1\u0132\1\u0135\46\u0132\1\u0134\20\u0132\1\u0136"+
+    "\1\0\1\u0136\2\u0137\1\u0136\4\u0137\2\u0136\1\u0138\1\u0139"+
+    "\1\u0136\1\u013a\4\u0137\1\u0136\11\u0137\1\u0136\27\u0137\1\u0139"+
+    "\10\u0137\2\u0136\4\u0137\1\u0136\1\u0137\1\221\2\u012d\1\u013b"+
+    "\1\221\1\u012d\4\221\1\u012d\1\221\1\u012d\3\221\1\u012d"+
+    "\3\221\1\u013c\2\221\1\u012d\57\221\1\222\2\0\1\u013d"+
+    "\1\222\1\0\4\222\1\0\1\222\1\0\3\222\1\0"+
+    "\6\222\1\0\57\222\12\u013e\1\u013f\74\u013e\14\u0140\1\u013f"+
+    "\72\u0140\1\226\2\u012d\1\u0141\1\226\1\u012d\4\226\1\u012d"+
+    "\1\226\1\u012d\3\226\1\u012d\3\226\1\u0142\2\226\1\u012d"+
+    "\57\226\1\227\2\0\1\u0143\1\227\1\0\4\227\1\0"+
+    "\1\227\1\0\3\227\1\0\6\227\1\0\57\227\1\u0144"+
+    "\1\0\10\u0144\1\u0145\2\u0144\1\u0146\1\u0144\1\u0147\46\u0144"+
+    "\1\u0146\20\u0144\1\u0148\1\0\1\u0148\2\u0149\1\u0148\4\u0149"+
+    "\2\u0148\1\u014a\1\u014b\1\u0148\1\u014c\4\u0149\1\u0148\11\u0149"+
+    "\1\u0148\27\u0149\1\u014b\10\u0149\2\u0148\4\u0149\1\u0148\1\u0149"+
+    "\2\233\1\0\106\233\1\0\20\233\1\u014d\2\233\1\u014e"+
+    "\60\233\1\236\2\0\1\u014f\1\236\1\0\4\236\1\0"+
+    "\1\236\1\0\3\236\1\0\6\236\1\0\57\236\1\u0150"+
+    "\1\0\10\u0150\1\u0151\2\u0150\1\u0152\1\u0150\1\u0153\46\u0150"+
+    "\1\u0152\20\u0150\1\u0154\1\0\1\u0154\2\u0155\1\u0154\4\u0155"+
+    "\2\u0154\1\u0156\1\u0157\1\u0154\1\u0158\4\u0155\1\u0154\11\u0155"+
+    "\1\u0154\27\u0155\1\u0157\10\u0155\2\u0154\4\u0155\1\u0154\1\u0155"+
+    "\2\242\1\0\106\242\1\0\20\242\1\u0159\2\242\1\u015a"+
+    "\60\242\7\0\1\u015b\77\0\1\252\2\0\1\u015c\1\252"+
+    "\1\0\4\252\1\0\1\252\1\0\3\252\1\0\6\252"+
+    "\1\0\60\252\1\0\1\u011c\1\u015c\1\252\1\0\4\252"+
+    "\1\0\1\252\1\0\3\252\1\0\6\252\1\0\57\252"+
+    "\1\u015d\1\0\10\u015d\1\u015e\2\u015d\1\u015f\1\u015d\1\u0160"+
+    "\46\u015d\1\u015f\20\u015d\1\u0161\1\0\12\u0161\1\u015e\1\u0162"+
+    "\1\u0161\1\u0163\46\u0161\1\u0162\20\u0161\1\252\2\0\1\u015c"+
+    "\1\252\1\0\4\252\1\0\1\252\1\0\1\252\1\u0164"+
+    "\1\252\1\0\6\252\1\0\60\252\2\0\1\u015c\1\252"+
+    "\1\0\4\252\1\0\1\252\1\0\1\252\1\u0165\1\252"+
+    "\1\0\6\252\1\0\57\252\1\261\1\0\12\261\2\0"+
+    "\50\261\1\0\20\261\3\0\1\u0166\17\0\1\351\2\0"+
+    "\1\364\60\0\1\261\1\0\3\261\1\263\6\261\2\0"+
+    "\2\261\1\263\6\261\1\263\36\261\1\0\20\261\5\0"+
+    "\1\u0167\10\0\1\u0168\1\0\1\u0167\6\0\1\u0167\64\0"+
+    "\1\u0167\10\0\1\u0169\1\0\1\u0167\6\0\1\u0167\57\0"+
+    "\1\267\1\0\10\267\1\0\2\267\1\0\50\267\1\0"+
+    "\21\267\1\0\3\267\1\270\4\267\1\0\2\267\1\0"+
+    "\2\267\1\270\6\267\1\270\36\267\1\0\20\267\5\0"+
+    "\1\u0167\10\0\1\u016a\1\0\1\u0167\6\0\1\u0167\64\0"+
+    "\1\u0167\10\0\1\u016b\1\0\1\u0167\6\0\1\u0167\57\0"+
+    "\12\274\1\0\1\274\1\0\1\u016c\67\274\1\0\13\274"+
+    "\1\0\1\274\1\0\1\u016c\5\274\1\u016d\61\274\1\0"+
+    "\13\274\1\0\1\274\1\0\1\274\1\u016e\66\274\1\u016f"+
+    "\1\274\14\u0170\1\u0171\106\u0170\1\u0171\6\u0170\1\u0172\2\u0170"+
+    "\1\u0173\60\u0170\12\u0174\1\u0175\106\u0174\1\u0175\10\u0174\1\u0176"+
+    "\2\u0174\1\u0177\60\u0174\12\312\1\0\4\312\1\u0178\65\312"+
+    "\1\0\13\312\1\0\4\312\1\u0178\3\312\1\u0179\61\312"+
+    "\1\0\13\312\1\u017a\74\312\14\317\1\0\2\317\1\u017b"+
+    "\65\317\1\0\15\317\1\0\2\317\1\u017b\3\317\1\u017c"+
+    "\61\317\1\0\15\317\1\u017d\72\317\12\322\1\0\1\322"+
+    "\1\0\70\322\1\0\13\322\1\0\1\322\1\0\6\322"+
+    "\1\u017e\61\322\1\0\13\322\1\0\1\322\1\0\1\322"+
+    "\1\u017f\66\322\1\0\1\322\14\u0180\1\u0181\106\u0180\1\u0181"+
+    "\6\u0180\1\u0182\2\u0180\1\u0183\60\u0180\12\u0184\1\u0185\106\u0184"+
+    "\1\u0185\10\u0184\1\u0186\2\u0184\1\u0187\60\u0184\12\340\1\0"+
+    "\4\340\1\u0188\65\340\1\0\13\340\1\0\4\340\1\u0188"+
+    "\3\340\1\u0189\61\340\1\0\13\340\1\u018a\74\340\14\344"+
+    "\1\0\2\344\1\u018b\65\344\1\0\15\344\1\0\2\344"+
+    "\1\u018b\3\344\1\u018c\61\344\1\0\15\344\1\u018d\72\344"+
+    "\7\0\1\u018e\12\0\1\u018f\3\0\1\u0190\23\0\1\u0191"+
+    "\43\0\1\u0192\26\0\1\u0193\55\0\1\353\2\0\2\u0194"+
+    "\6\0\1\353\6\0\1\353\6\u0194\1\0\13\u0194\1\0"+
+    "\13\u0194\1\0\4\u0194\1\0\4\u0194\1\0\4\u0194\1\0"+
+    "\1\u0194\1\u0195\1\0\3\u0195\1\u0196\4\354\1\u0195\1\0"+
+    "\4\u0195\1\u0196\1\354\1\u0195\1\0\3\u0195\1\u0196\6\354"+
+    "\1\u0195\13\354\1\u0195\13\354\1\u0195\4\354\1\u0197\11\354"+
+    "\1\u0195\1\354\21\0\1\u0198\7\0\1\u0199\55\0\1\72"+
+    "\1\0\11\72\1\0\1\72\1\u019a\5\72\1\0\42\72"+
+    "\1\0\20\72\105\357\1\u019b\1\357\16\0\1\u019c\70\0"+
+    "\1\u0195\1\0\3\u0195\1\u0196\4\361\1\u0195\1\0\4\u0195"+
+    "\1\u0196\1\361\1\u0195\1\0\3\u0195\1\u0196\6\361\1\u0195"+
+    "\13\361\1\u0195\13\361\1\u0195\4\361\1\u019d\11\361\1\u0195"+
+    "\1\361\105\362\1\u019e\1\362\1\72\1\0\11\72\1\0"+
+    "\1\72\1\0\5\72\1\0\42\72\1\u019f\20\72\36\0"+
+    "\1\u0193\52\0\1\u01a0\106\0\1\u01a1\112\0\4\114\7\0"+
+    "\1\114\6\0\4\114\2\u01a2\1\0\13\114\1\0\13\114"+
+    "\1\0\4\114\1\0\11\114\1\0\1\114\6\0\4\114"+
+    "\7\0\1\114\6\0\4\114\1\u01a2\1\u01a3\1\0\13\114"+
+    "\1\0\13\114\1\0\4\114\1\0\11\114\1\0\1\114"+
+    "\6\0\4\114\7\0\1\114\6\0\6\114\1\0\13\114"+
+    "\1\0\2\114\1\u01a4\10\114\1\0\4\114\1\0\6\114"+
+    "\1\u01a4\2\114\1\0\1\114\12\376\1\377\3\376\1\0"+
+    "\71\376\1\0\10\376\1\377\2\376\1\u01a5\1\376\1\u0101"+
+    "\46\376\1\u01a5\20\376\14\u0102\1\377\1\u0102\1\0\71\u0102"+
+    "\1\0\12\u0102\1\377\1\u01a6\1\u0102\1\u0104\46\u0102\1\u01a6"+
+    "\20\u0102\1\u0108\1\0\10\u0108\1\u010a\2\u0108\1\u01a7\1\u0108"+
+    "\1\u01a8\46\u0108\1\u01a7\20\u0108\1\143\2\u0108\1\u0109\1\143"+
+    "\1\u0108\4\143\1\u010a\1\143\1\u0108\1\143\1\141\1\143"+
+    "\1\u0108\6\143\1\u0108\60\143\1\0\1\u0108\1\u0109\1\143"+
+    "\1\u0108\4\143\1\u010a\1\143\1\u0108\1\u01a9\1\143\1\u010c"+
+    "\1\u0108\6\143\1\u0108\36\143\1\u01a9\20\143\1\u010d\1\0"+
+    "\12\u010d\1\u010a\1\u01aa\1\u010d\1\u01ab\46\u010d\1\u01aa\20\u010d"+
+    "\1\144\2\u010d\1\u010e\1\144\1\u010d\4\144\1\u010d\1\144"+
+    "\1\u010a\1\144\1\141\1\144\1\u010d\6\144\1\u010d\60\144"+
+    "\1\0\1\u010d\1\u010e\1\144\1\u010d\4\144\1\u010d\1\144"+
+    "\1\u010a\1\u01ac\1\144\1\u0110\1\u010d\6\144\1\u010d\36\144"+
+    "\1\u01ac\20\144\12\u0115\1\u0116\3\u0115\1\0\71\u0115\1\0"+
+    "\10\u0115\1\u0116\2\u0115\1\u01ad\1\u0115\1\u0118\46\u0115\1\u01ad"+
+    "\20\u0115\14\u0119\1\u0116\1\u0119\1\0\71\u0119\1\0\12\u0119"+
+    "\1\u0116\1\u01ae\1\u0119\1\u011b\46\u0119\1\u01ae\20\u0119\6\0"+
+    "\4\170\7\0\1\170\6\0\6\170\1\0\13\170\1\0"+
+    "\13\170\1\0\4\170\1\0\6\170\1\u01af\2\170\1\0"+
+    "\1\170\6\0\4\u011e\7\0\1\u011e\6\0\6\u011e\1\0"+
+    "\13\u011e\1\0\13\u011e\1\0\4\u011e\1\0\11\u011e\1\0"+
+    "\1\u011e\6\0\4\u0120\7\0\1\u0120\6\0\6\u0120\1\0"+
+    "\13\u0120\1\0\13\u0120\1\0\4\u0120\1\0\11\u0120\1\0"+
+    "\1\u0120\12\u0121\1\u0122\3\u0121\1\0\71\u0121\1\0\10\u0121"+
+    "\1\u0122\2\u0121\1\u01b0\1\u0121\1\u0124\46\u0121\1\u01b0\20\u0121"+
+    "\14\u0125\1\u0122\1\u0125\1\0\71\u0125\1\0\12\u0125\1\u0122"+
+    "\1\u01b1\1\u0125\1\u0127\46\u0125\1\u01b1\20\u0125\1\u01b2\2\u01b3"+
+    "\1\u01b4\1\u01b2\1\u01b3\4\u01b2\1\u01b3\1\u01b2\1\u01b3\3\u01b2"+
+    "\1\u01b3\6\u01b2\1\u01b3\55\u01b2\1\175\1\u01b2\1\u01b5\2\u01b6"+
+    "\1\u01b7\1\u01b5\1\u01b6\4\u01b5\1\u01b6\1\u01b5\1\u01b6\3\u01b5"+
+    "\1\u01b6\6\u01b5\1\u01b6\55\u01b5\1\175\1\u01b5\37\0\1\u01b8"+
+    "\35\0\1\u01b8\53\0\1\u01b9\14\0\1\u01b9\73\0\1\u01ba"+
+    "\11\0\1\u01ba\76\0\1\u01bb\20\0\1\u01bb\113\0\1\u01bc"+
+    "\7\0\1\u01bc\2\0\12\u0132\1\u0133\3\u0132\1\0\71\u0132"+
+    "\1\0\10\u0132\1\u0133\2\u0132\1\u01bd\1\u0132\1\u0135\46\u0132"+
+    "\1\u01bd\20\u0132\1\u0136\1\0\12\u0136\1\u0133\1\u01be\1\u0136"+
+    "\1\u013a\46\u0136\1\u01be\21\u0136\1\0\12\u0136\1\u01bf\1\u01be"+
+    "\1\u0136\1\u013a\46\u0136\1\u01be\20\u0136\14\0\1\u01c0\72\0"+
+    "\14\u0136\1\u01bf\1\u0136\1\0\71\u0136\1\0\12\u0136\1\u0133"+
+    "\1\u01c1\1\u0136\1\u013a\46\u0136\1\u01c1\20\u0136\12\u0144\1\u0145"+
+    "\3\u0144\1\0\71\u0144\1\0\10\u0144\1\u0145\2\u0144\1\u01c2"+
+    "\1\u0144\1\u0147\46\u0144\1\u01c2\20\u0144\1\u0148\1\0\12\u0148"+
+    "\1\u0145\1\u01c3\1\u0148\1\u014c\46\u0148\1\u01c3\21\u0148\1\0"+
+    "\12\u0148\1\u01c4\1\u01c3\1\u0148\1\u014c\46\u0148\1\u01c3\20\u0148"+
+    "\14\0\1\u01c5\72\0\14\u0148\1\u01c4\1\u0148\1\0\71\u0148"+
+    "\1\0\12\u0148\1\u0145\1\u01c6\1\u0148\1\u014c\46\u0148\1\u01c6"+
+    "\20\u0148\2\233\1\0\4\233\1\u01c7\12\233\1\u01c8\3\233"+
+    "\1\u01c9\23\233\1\u01ca\36\233\1\0\33\233\1\u01cb\50\233"+
+    "\12\u0150\1\u0151\3\u0150\1\0\71\u0150\1\0\10\u0150\1\u0151"+
+    "\2\u0150\1\u01cc\1\u0150\1\u0153\46\u0150\1\u01cc\20\u0150\1\u0154"+
+    "\1\0\12\u0154\1\u0151\1\u01cd\1\u0154\1\u0158\46\u0154\1\u01cd"+
+    "\21\u0154\1\0\12\u0154\1\u01ce\1\u01cd\1\u0154\1\u0158\46\u0154"+
+    "\1\u01cd\20\u0154\14\0\1\u01cf\72\0\14\u0154\1\u01ce\1\u0154"+
+    "\1\0\71\u0154\1\0\12\u0154\1\u0151\1\u01d0\1\u0154\1\u0158"+
+    "\46\u0154\1\u01d0\20\u0154\2\242\1\0\4\242\1\u01d1\12\242"+
+    "\1\u01d2\3\242\1\u01d3\23\242\1\u01d4\36\242\1\0\33\242"+
+    "\1\u01d5\50\242\23\0\1\u01d6\63\0\12\u015d\1\u015e\3\u015d"+
+    "\1\0\71\u015d\1\0\10\u015d\1\u01d7\2\u015d\1\u01d8\1\u015d"+
+    "\1\u0160\46\u015d\1\u01d8\20\u015d\14\u0161\1\u015e\1\u0161\1\0"+
+    "\71\u0161\1\0\12\u0161\1\u01d9\1\u01da\1\u0161\1\u0163\46\u0161"+
+    "\1\u01da\20\u0161\1\u01db\2\u01b3\1\u01dc\1\u01db\1\u01b3\4\u01db"+
+    "\1\u01b3\1\u01db\1\u01b3\3\u01db\1\u01b3\6\u01db\1\u01b3\55\u01db"+
+    "\1\252\1\u01db\1\u01dd\2\u01b6\1\u01de\1\u01dd\1\u01b6\4\u01dd"+
+    "\1\u01b6\1\u01dd\1\u01b6\3\u01dd\1\u01b6\6\u01dd\1\u01b6\55\u01dd"+
+    "\1\252\1\u01dd\5\0\1\u0167\12\0\1\u0167\6\0\1\u0167"+
+    "\57\0\12\274\1\0\1\274\1\0\1\274\1\u01df\66\274"+
+    "\1\u016f\10\274\1\u01e0\2\274\1\0\1\274\1\0\1\u016c"+
+    "\4\274\1\u01e1\3\274\1\u01e2\23\274\1\u01e3\32\274\1\0"+
+    "\1\274\12\u01df\1\0\1\u01df\1\0\70\u01df\1\0\1\u01df"+
+    "\12\u016f\1\0\1\u016f\1\0\1\u01e4\67\u016f\1\0\1\u016f"+
+    "\7\u0170\1\u01e5\4\u0170\1\u0171\5\u0170\1\u01e6\3\u0170\1\u01e7"+
+    "\23\u0170\1\u01e8\50\u0170\1\u0171\21\u0170\1\u01e9\50\u0170\7\u0174"+
+    "\1\u01ea\2\u0174\1\u0175\7\u0174\1\u01eb\3\u0174\1\u01ec\23\u0174"+
+    "\1\u01ed\46\u0174\1\u0175\23\u0174\1\u01ee\50\u0174\12\312\1\0"+
+    "\103\312\1\u01ef\2\312\1\0\4\312\1\u0178\2\312\1\u01f0"+
+    "\3\312\1\u01f1\23\312\1\u01f2\32\312\1\0\1\312\17\u01f3"+
+    "\1\u01f4\67\u01f3\14\317\1\0\101\317\1\u01f5\4\317\1\0"+
+    "\2\317\1\u017b\2\317\1\u01f6\3\317\1\u01f7\23\317\1\u01f8"+
+    "\32\317\1\0\1\317\17\u01f9\1\u01fa\67\u01f9\7\322\1\u01fb"+
+    "\2\322\1\0\1\322\1\0\5\322\1\u01fc\3\322\1\u01fd"+
+    "\23\322\1\u01fe\32\322\1\0\1\322\7\u0180\1\u01ff\4\u0180"+
+    "\1\u0181\5\u0180\1\u0200\3\u0180\1\u0201\23\u0180\1\u0202\50\u0180"+
+    "\1\u0181\21\u0180\1\u0203\50\u0180\7\u0184\1\u0204\2\u0184\1\u0185"+
+    "\7\u0184\1\u0205\3\u0184\1\u0206\23\u0184\1\u0207\46\u0184\1\u0185"+
+    "\23\u0184\1\u0208\50\u0184\12\340\1\0\103\340\1\u0209\2\340"+
+    "\1\0\4\340\1\u0188\2\340\1\u020a\3\340\1\u020b\23\340"+
+    "\1\u020c\32\340\1\0\1\340\17\u020d\1\u020e\67\u020d\14\344"+
+    "\1\0\101\344\1\u020f\4\344\1\0\2\344\1\u018b\2\344"+
+    "\1\u0210\3\344\1\u0211\23\344\1\u0212\32\344\1\0\1\344"+
+    "\17\u0213\1\u0214\67\u0213\7\0\1\u0215\106\0\1\u0216\136\0"+
+    "\1\u0217\47\0\1\u0194\1\0\11\u0194\1\0\7\u0194\1\0"+
+    "\63\u0194\1\u0195\1\0\11\u0195\1\0\7\u0195\1\0\47\u0195"+
+    "\1\0\14\u0195\1\0\3\u0195\1\u0196\5\u0195\1\0\4\u0195"+
+    "\1\u0196\2\u0195\1\0\3\u0195\1\u0196\43\u0195\1\u0218\13\u0195"+
+    "\21\0\1\u0198\51\0\1\u0219\34\0\1\u021a\15\0\3\u021a"+
+    "\2\0\1\u021a\11\0\1\u021a\1\0\2\u021a\7\0\1\u021a"+
+    "\2\0\2\u021a\6\0\1\u021a\17\0\1\u019a\157\0\1\u019f"+
+    "\26\0\1\114\1\u021b\2\114\7\0\1\114\6\0\6\114"+
+    "\1\0\13\114\1\0\13\114\1\0\4\114\1\0\11\114"+
+    "\1\0\1\114\6\0\4\114\7\0\1\114\6\0\6\114"+
+    "\1\0\11\114\1\u021c\1\114\1\0\1\u021c\12\114\1\0"+
+    "\4\114\1\0\11\114\1\0\1\114\12\376\1\377\74\376"+
+    "\14\u0102\1\377\72\u0102\12\u0108\1\u010a\3\u0108\1\0\71\u0108"+
+    "\1\0\10\u0108\1\u010a\2\u0108\1\u021d\1\u0108\1\u01a8\46\u0108"+
+    "\1\u021d\20\u0108\1\143\2\u0108\1\u0109\1\143\1\u0108\4\143"+
+    "\1\u010a\1\143\1\u0108\3\143\1\u0108\6\143\1\u0108\57\143"+
+    "\14\u010d\1\u010a\1\u010d\1\0\71\u010d\1\0\12\u010d\1\u010a"+
+    "\1\u021e\1\u010d\1\u01ab\46\u010d\1\u021e\20\u010d\1\144\2\u010d"+
+    "\1\u010e\1\144\1\u010d\4\144\1\u010d\1\144\1\u010a\3\144"+
+    "\1\u010d\6\144\1\u010d\57\144\12\u0115\1\u0116\74\u0115\14\u0119"+
+    "\1\u0116\72\u0119\6\0\3\170\1\u021f\7\0\1\170\6\0"+
+    "\6\170\1\0\13\170\1\0\13\170\1\0\4\170\1\0"+
+    "\11\170\1\0\1\170\12\u0121\1\u0122\74\u0121\14\u0125\1\u0122"+
+    "\72\u0125\1\u01b2\2\u01b3\1\u01b4\1\u01b2\1\u01b3\4\u01b2\1\u01b3"+
+    "\1\u01b2\1\u01b3\3\u01b2\1\u01b3\6\u01b2\1\u01b3\55\u01b2\1\u0220"+
+    "\1\u01b2\105\u01b3\1\u0221\1\u01b3\1\u01b5\2\u01b6\1\u01b7\1\u01b5"+
+    "\1\u01b6\4\u01b5\1\u01b6\1\u01b5\1\u01b6\3\u01b5\1\u01b6\6\u01b5"+
+    "\1\u01b6\55\u01b5\1\u0220\1\u01b5\105\u01b6\1\u0222\1\u01b6\42\0"+
+    "\1\u0223\14\0\1\u0223\63\0\2\u0224\103\0\2\u0225\115\0"+
+    "\1\u0226\14\0\1\u0226\63\0\2\u0227\51\0\12\u0132\1\u0133"+
+    "\74\u0132\14\u0136\1\u0133\1\u0136\1\0\70\u0136\3\0\2\u0228"+
+    "\1\0\4\u0228\2\0\1\u0138\1\u0228\2\0\4\u0228\1\0"+
+    "\11\u0228\1\0\40\u0228\2\0\4\u0228\1\0\1\u0228\14\u0136"+
+    "\1\u0133\72\u0136\12\u0144\1\u0145\74\u0144\14\u0148\1\u0145\1\u0148"+
+    "\1\0\70\u0148\3\0\2\u0229\1\0\4\u0229\2\0\1\u014a"+
+    "\1\u0229\2\0\4\u0229\1\0\11\u0229\1\0\40\u0229\2\0"+
+    "\4\u0229\1\0\1\u0229\14\u0148\1\u0145\72\u0148\2\233\1\0"+
+    "\4\233\1\u022a\101\233\1\0\34\233\1\u022b\47\233\12\u0150"+
+    "\1\u0151\74\u0150\14\u0154\1\u0151\1\u0154\1\0\70\u0154\3\0"+
+    "\2\u022c\1\0\4\u022c\2\0\1\u0156\1\u022c\2\0\4\u022c"+
+    "\1\0\11\u022c\1\0\40\u022c\2\0\4\u022c\1\0\1\u022c"+
+    "\14\u0154\1\u0151\72\u0154\2\242\1\0\4\242\1\u022d\101\242"+
+    "\1\0\34\242\1\u022e\47\242\2\0\1\u022f\104\0\12\u015d"+
+    "\1\u015e\74\u015d\14\u0161\1\u015e\72\u0161\1\u01db\2\u01b3\1\u01dc"+
+    "\1\u01db\1\u01b3\4\u01db\1\u01b3\1\u01db\1\u01b3\3\u01db\1\u01b3"+
+    "\6\u01db\1\u01b3\55\u01db\1\u0230\1\u01db\1\u01dd\2\u01b6\1\u01de"+
+    "\1\u01dd\1\u01b6\4\u01dd\1\u01b6\1\u01dd\1\u01b6\3\u01dd\1\u01b6"+
+    "\6\u01dd\1\u01b6\55\u01dd\1\u0230\1\u01dd\7\274\1\u0231\2\274"+
+    "\1\0\1\274\1\0\1\u016c\67\274\1\0\1\274\12\u016f"+
+    "\1\0\1\u016f\1\0\1\u016f\1\0\70\u016f\7\u0170\1\u0232"+
+    "\4\u0170\1\u0171\106\u0170\1\u0171\22\u0170\1\u0233\47\u0170\7\u0174"+
+    "\1\u0234\2\u0174\1\u0175\106\u0174\1\u0175\24\u0174\1\u0235\47\u0174"+
+    "\7\312\1\u0236\2\312\1\0\4\312\1\u0178\65\312\1\0"+
+    "\1\312\12\u0237\1\u0238\72\u0237\1\0\1\u0237\7\317\1\u0239"+
+    "\4\317\1\0\2\317\1\u017b\65\317\1\0\1\317\14\u023a"+
+    "\1\u0238\70\u023a\1\0\1\u023a\7\322\1\u023b\2\322\1\0"+
+    "\1\322\1\0\70\322\1\0\1\322\7\u0180\1\u023c\4\u0180"+
+    "\1\u0181\106\u0180\1\u0181\22\u0180\1\u023d\47\u0180\7\u0184\1\u023e"+
+    "\2\u0184\1\u0185\106\u0184\1\u0185\24\u0184\1\u023f\47\u0184\7\340"+
+    "\1\u0240\2\340\1\0\4\340\1\u0188\65\340\1\0\1\340"+
+    "\12\u0241\1\u0242\72\u0241\1\0\1\u0241\7\344\1\u0243\4\344"+
+    "\1\0\2\344\1\u018b\65\344\1\0\1\344\14\u0244\1\u0242"+
+    "\70\u0244\1\0\1\u0244\40\0\1\u0245\141\0\1\u0218\34\0"+
+    "\1\u021a\15\0\3\u021a\2\0\1\u021a\11\0\1\u021a\1\0"+
+    "\2\u021a\7\0\1\u021a\1\0\1\u0219\2\u021a\6\0\1\u021a"+
+    "\10\0\4\114\7\0\1\114\6\0\6\114\1\0\7\114"+
+    "\1\u0246\3\114\1\0\13\114\1\0\4\114\1\0\11\114"+
+    "\1\0\1\114\6\0\4\114\7\0\1\114\6\0\6\114"+
+    "\1\0\6\114\1\u0247\4\114\1\0\13\114\1\0\1\114"+
+    "\1\u0247\2\114\1\0\11\114\1\0\1\114\12\u0108\1\u010a"+
+    "\74\u0108\14\u010d\1\u010a\72\u010d\6\0\4\170\7\0\1\170"+
+    "\6\0\6\170\1\0\6\170\1\u0248\4\170\1\0\6\170"+
+    "\1\u0249\4\170\1\0\4\170\1\0\11\170\1\0\1\170"+
+    "\54\0\1\u024a\5\0\1\u024a\73\0\1\u024b\14\0\1\u024b"+
+    "\66\0\1\u024c\11\0\1\u024c\74\0\1\u024d\11\0\1\u024d"+
+    "\77\0\1\u024e\14\0\1\u024e\22\0\2\233\1\0\35\233"+
+    "\1\u024f\46\233\2\242\1\0\35\242\1\u0250\46\242\14\u0170"+
+    "\1\u0171\23\u0170\1\u0251\46\u0170\12\u0174\1\u0175\25\u0174\1\u0252"+
+    "\46\u0174\12\u0237\1\u01f3\4\u0237\1\u0253\65\u0237\1\u01f3\1\u0237"+
+    "\14\u023a\1\u01f9\2\u023a\1\u0254\65\u023a\1\u01f9\1\u023a\14\u0180"+
+    "\1\u0181\23\u0180\1\u0255\46\u0180\12\u0184\1\u0185\25\u0184\1\u0256"+
+    "\46\u0184\12\u0241\1\u020d\4\u0241\1\u0257\65\u0241\1\u020d\1\u0241"+
+    "\14\u0244\1\u0213\2\u0244\1\u0258\65\u0244\1\u0213\1\u0244\41\0"+
+    "\1\u0259\53\0\4\114\7\0\1\114\6\0\6\114\1\0"+
+    "\13\114\1\0\4\114\1\u025a\6\114\1\0\4\114\1\0"+
+    "\11\114\1\0\1\114\6\0\4\114\7\0\1\114\6\0"+
+    "\6\114\1\0\3\114\1\u025b\7\114\1\0\4\114\1\u025b"+
+    "\6\114\1\0\4\114\1\0\11\114\1\0\1\114\6\0"+
+    "\4\170\7\0\1\170\6\0\6\170\1\0\11\170\1\u025c"+
+    "\1\170\1\0\13\170\1\0\4\170\1\0\11\170\1\0"+
+    "\1\170\6\0\4\170\7\0\1\170\6\0\6\170\1\0"+
+    "\10\170\1\u025d\2\170\1\0\13\170\1\0\4\170\1\0"+
+    "\11\170\1\0\1\170\55\0\1\u025e\24\0\1\u025e\52\0"+
+    "\1\u025f\20\0\1\u025f\70\0\1\u0260\13\0\1\u0260\53\0"+
+    "\2\u0261\112\0\1\u0262\35\0\1\u0262\11\0\2\233\1\0"+
+    "\36\233\1\u0263\45\233\2\242\1\0\36\242\1\u0264\45\242"+
+    "\14\u0170\1\u0171\24\u0170\1\u0265\45\u0170\12\u0174\1\u0175\26\u0174"+
+    "\1\u0266\45\u0174\12\u0237\1\u0267\4\u0237\1\u0253\65\u0237\1\u01f3"+
+    "\1\u0237\14\u023a\1\u0268\2\u023a\1\u0254\65\u023a\1\u01f9\1\u023a"+
+    "\14\u0180\1\u0181\24\u0180\1\u0269\45\u0180\12\u0184\1\u0185\26\u0184"+
+    "\1\u026a\45\u0184\12\u0241\1\u026b\4\u0241\1\u0257\65\u0241\1\u020d"+
+    "\1\u0241\14\u0244\1\u026c\2\u0244\1\u0258\65\u0244\1\u0213\1\u0244"+
+    "\42\0\1\u026d\52\0\4\114\7\0\1\114\6\0\6\114"+
+    "\1\0\13\114\1\0\7\114\1\u026e\3\114\1\0\4\114"+
+    "\1\0\11\114\1\0\1\114\6\0\4\170\7\0\1\170"+
+    "\6\0\6\170\1\0\11\170\1\u026f\1\170\1\0\13\170"+
+    "\1\0\4\170\1\0\11\170\1\0\1\170\6\0\4\170"+
+    "\7\0\1\170\6\0\6\170\1\0\6\170\1\u0270\4\170"+
+    "\1\0\13\170\1\0\4\170\1\0\11\170\1\0\1\170"+
+    "\44\0\1\u0271\11\0\1\u0271\72\0\1\u0272\14\0\1\u0272"+
+    "\71\0\1\u0273\14\0\1\u0273\27\0\2\233\1\0\37\233"+
+    "\1\u0274\44\233\2\242\1\0\37\242\1\u0275\44\242\14\u0170"+
+    "\1\u0171\25\u0170\1\u0276\44\u0170\12\u0174\1\u0175\27\u0174\1\u0277"+
+    "\44\u0174\14\u0180\1\u0181\25\u0180\1\u0278\44\u0180\12\u0184\1\u0185"+
+    "\27\u0184\1\u0279\44\u0184\41\0\1\u027a\53\0\4\114\7\0"+
+    "\1\114\6\0\5\114\1\u027b\1\0\13\114\1\0\13\114"+
+    "\1\0\4\114\1\0\11\114\1\0\1\114\6\0\4\170"+
+    "\7\0\1\170\6\0\6\170\1\0\13\170\1\0\4\170"+
+    "\1\u027c\6\170\1\0\4\170\1\0\11\170\1\0\1\170"+
+    "\6\0\4\170\7\0\1\170\6\0\6\170\1\0\5\170"+
+    "\1\u027d\5\170\1\0\13\170\1\0\4\170\1\0\11\170"+
+    "\1\0\1\170\2\233\1\0\36\233\1\u027e\45\233\2\242"+
+    "\1\0\36\242\1\u027f\45\242\14\u0170\1\u0171\24\u0170\1\u0280"+
+    "\45\u0170\12\u0174\1\u0175\26\u0174\1\u0281\45\u0174\14\u0180\1\u0181"+
+    "\24\u0180\1\u0282\45\u0180\12\u0184\1\u0185\26\u0184\1\u0283\45\u0184"+
+    "\36\0\1\u0284\56\0\4\114\7\0\1\114\6\0\6\114"+
+    "\1\0\5\114\1\u0285\5\114\1\0\13\114\1\0\4\114"+
+    "\1\0\11\114\1\0\1\114\6\0\4\170\7\0\1\170"+
+    "\6\0\6\170\1\0\13\170\1\0\13\170\1\0\4\170"+
+    "\1\0\1\170\1\u0286\7\170\1\0\1\170\2\233\1\0"+
+    "\33\233\1\u0287\50\233\2\242\1\0\33\242\1\u0288\50\242"+
+    "\14\u0170\1\u0171\21\u0170\1\u0289\50\u0170\12\u0174\1\u0175\23\u0174"+
+    "\1\u028a\50\u0174\14\u0180\1\u0181\21\u0180\1\u028b\50\u0180\12\u0184"+
+    "\1\u0185\23\u0184\1\u028c\50\u0184\6\0\4\114\7\0\1\114"+
+    "\6\0\6\114\1\0\7\114\1\u028d\3\114\1\0\13\114"+
+    "\1\0\4\114\1\0\11\114\1\0\1\114\6\0\4\170"+
+    "\7\0\1\170\6\0\6\170\1\0\13\170\1\0\4\170"+
+    "\1\u028e\6\170\1\0\4\170\1\0\11\170\1\0\1\170"+
+    "\6\0\4\114\7\0\1\114\6\0\6\114\1\0\13\114"+
+    "\1\0\13\114\1\0\4\114\1\0\11\114\1\0\1\u028f"+
+    "\6\0\4\170\7\0\1\170\6\0\6\170\1\0\10\170"+
+    "\1\u0290\2\170\1\0\13\170\1\0\4\170\1\0\11\170"+
+    "\1\0\1\170\6\0\4\114\7\0\1\114\6\0\6\114"+
+    "\1\0\5\114\1\u0291\5\114\1\0\13\114\1\0\4\114"+
+    "\1\0\11\114\1\0\1\114\6\0\4\170\7\0\1\170"+
+    "\6\0\6\170\1\0\4\170\1\u0292\6\170\1\0\13\170"+
+    "\1\0\4\170\1\0\11\170\1\0\1\170\6\0\4\114"+
+    "\7\0\1\114\6\0\6\114\1\0\5\114\1\u0293\5\114"+
+    "\1\0\13\114\1\0\4\114\1\0\11\114\1\0\1\114"+
+    "\6\0\4\170\7\0\1\170\6\0\6\170\1\0\5\170"+
+    "\1\u0294\5\170\1\0\13\170\1\0\4\170\1\0\11\170"+
+    "\1\0\1\170\6\0\4\114\7\0\1\114\6\0\6\114"+
+    "\1\0\13\114\1\0\4\114\1\u0295\6\114\1\0\4\114"+
+    "\1\0\11\114\1\0\1\114\6\u0296\4\u0297\7\u0296\1\u0297"+
+    "\5\u0296\1\0\6\u0297\1\u0296\13\u0297\1\u0296\13\u0297\1\u0296"+
+    "\4\u0297\1\u0296\11\u0297\1\u0296\1\u0297\43\0\1\u0298\3\0"+
+    "\1\u0299\7\0\1\u029a\1\u029b\21\0\1\u029c\12\0\4\170"+
+    "\7\0\1\170\6\0\6\170\1\0\4\170\1\u029d\3\170"+
+    "\1\u029e\2\170\1\0\4\170\1\u029f\1\u02a0\5\170\1\0"+
+    "\4\170\1\0\6\170\1\u02a1\2\170\1\0\1\170\60\0"+
+    "\1\u02a2\77\0\1\u02a3\115\0\1\u02a4\105\0\1\u02a5\107\0"+
+    "\1\u02a6\34\0\4\170\7\0\1\170\6\0\6\170\1\0"+
+    "\13\170\1\0\5\170\1\u02a7\5\170\1\0\4\170\1\0"+
+    "\11\170\1\0\1\170\6\0\4\170\7\0\1\170\6\0"+
+    "\6\170\1\0\12\170\1\u02a8\1\0\13\170\1\0\4\170"+
+    "\1\0\11\170\1\0\1\170\6\0\4\170\7\0\1\170"+
+    "\6\0\6\170\1\0\13\170\1\0\5\170\1\u02a9\5\170"+
+    "\1\0\4\170\1\0\11\170\1\0\1\170\6\0\4\170"+
+    "\7\0\1\170\6\0\6\170\1\0\13\170\1\0\4\170"+
+    "\1\u02aa\6\170\1\0\4\170\1\0\11\170\1\0\1\170"+
+    "\6\0\4\170\7\0\1\170\6\0\6\170\1\0\13\170"+
+    "\1\0\5\170\1\u02ab\5\170\1\0\4\170\1\0\11\170"+
+    "\1\0\1\170\45\0\1\u02ac\136\0\1\u02ad\107\0\1\u02ae"+
+    "\67\0\1\u02af\125\0\1\u02b0\16\0\4\170\7\0\1\170"+
+    "\6\0\6\170\1\0\6\170\1\u02b1\4\170\1\0\13\170"+
+    "\1\0\4\170\1\0\11\170\1\0\1\170\6\0\4\170"+
+    "\7\0\1\170\6\0\6\170\1\0\13\170\1\0\13\170"+
+    "\1\0\4\170\1\0\1\170\1\u02b2\7\170\1\0\1\170"+
+    "\6\0\4\170\7\0\1\170\6\0\6\170\1\0\13\170"+
+    "\1\0\13\170\1\0\4\170\1\0\2\170\1\u02b3\6\170"+
+    "\1\0\1\170\6\0\4\170\7\0\1\170\6\0\6\170"+
+    "\1\0\13\170\1\0\4\170\1\u02b4\6\170\1\0\4\170"+
+    "\1\0\11\170\1\0\1\170\6\0\4\170\7\0\1\170"+
+    "\6\0\6\170\1\0\13\170\1\0\13\170\1\0\4\170"+
+    "\1\0\2\170\1\u02b5\6\170\1\0\1\170\47\0\1\u02b6"+
+    "\74\0\1\u02b7\106\0\1\u02b8\116\0\1\u02b9\105\0\1\u02ba"+
+    "\50\0\4\170\7\0\1\170\6\0\6\170\1\0\10\170"+
+    "\1\u02bb\2\170\1\0\13\170\1\0\4\170\1\0\11\170"+
+    "\1\0\1\170\6\0\4\170\7\0\1\170\6\0\5\170"+
+    "\1\u02bc\1\0\13\170\1\0\13\170\1\0\4\170\1\0"+
+    "\11\170\1\0\1\170\6\0\4\170\7\0\1\170\6\0"+
+    "\5\170\1\u02bd\1\0\13\170\1\0\13\170\1\0\4\170"+
+    "\1\0\11\170\1\0\1\170\6\0\4\170\7\0\1\170"+
+    "\6\0\6\170\1\0\6\170\1\u02be\4\170\1\0\13\170"+
+    "\1\0\4\170\1\0\11\170\1\0\1\170\6\0\4\170"+
+    "\7\0\1\170\6\0\6\170\1\0\5\170\1\u02bf\5\170"+
+    "\1\0\13\170\1\0\4\170\1\0\11\170\1\0\1\170"+
+    "\60\0\1\u02c0\131\0\1\u02c1\52\0\1\u02c2\106\0\1\u02c3"+
+    "\45\0\4\170\7\0\1\170\6\0\6\170\1\0\13\170"+
+    "\1\0\5\170\1\u02c4\5\170\1\0\4\170\1\0\11\170"+
+    "\1\0\1\170\6\0\4\170\7\0\1\170\6\0\6\170"+
+    "\1\0\13\170\1\0\13\170\1\0\4\170\1\0\7\170"+
+    "\1\u02c5\1\170\1\0\1\170\6\0\4\170\7\0\1\170"+
+    "\6\0\6\170\1\0\10\170\1\u02c6\2\170\1\0\13\170"+
+    "\1\0\4\170\1\0\11\170\1\0\1\170\6\0\4\170"+
+    "\7\0\1\170\6\0\6\170\1\0\10\170\1\u02c7\2\170"+
+    "\1\0\13\170\1\0\4\170\1\0\11\170\1\0\1\170"+
+    "\104\0\1\u02c8\63\0\1\u02b0\131\0\1\u02ba\106\0\1\u02c9"+
+    "\10\0\4\170\7\0\1\170\6\0\6\170\1\0\13\170"+
+    "\1\0\13\170\1\0\4\170\1\0\10\170\1\u02ca\1\0"+
+    "\1\170\6\0\4\170\7\0\1\170\6\0\6\170\1\0"+
+    "\13\170\1\0\6\170\1\u02b5\4\170\1\0\4\170\1\0"+
+    "\11\170\1\0\1\170\6\0\4\170\7\0\1\170\6\0"+
+    "\6\170\1\0\13\170\1\0\13\170\1\0\4\170\1\0"+
+    "\10\170\1\u02bf\1\0\1\170\6\0\4\170\7\0\1\170"+
+    "\6\0\6\170\1\0\13\170\1\0\13\170\1\0\4\170"+
+    "\1\0\10\170\1\u02cb\1\0\1\170\35\0\1\u02b0\154\0"+
+    "\1\u02cc\11\0\4\170\7\0\1\170\6\0\5\170\1\u02b5"+
+    "\1\0\13\170\1\0\13\170\1\0\4\170\1\0\11\170"+
+    "\1\0\1\170\6\0\4\170\7\0\1\170\6\0\6\170"+
+    "\1\0\13\170\1\0\13\170\1\0\4\170\1\0\7\170"+
+    "\1\u02cd\1\170\1\0\1\170\57\0\1\u02b0\35\0\4\170"+
+    "\7\0\1\170\6\0\6\170\1\0\13\170\1\0\4\170"+
+    "\1\u02b5\6\170\1\0\4\170\1\0\11\170\1\0\1\170";
+
+  /** 
+   * The transition table of the DFA
+   */
+  final private static int yytrans [] = yy_unpack(yy_packed);
+
+
+  /* error codes */
+  final private static int YY_UNKNOWN_ERROR = 0;
+  // final private static int YY_ILLEGAL_STATE = 1;
+  final private static int YY_NO_MATCH = 2;
+  final private static int YY_PUSHBACK_2BIG = 3;
+
+  /* error messages for the codes above */
+  final private static String YY_ERROR_MSG[] = {
+    "Unkown internal scanner error",		//$NON-NLS-1$
+    "Internal error: unknown state",		//$NON-NLS-1$
+    "Error: could not match input",		//$NON-NLS-1$
+    "Error: pushback value was too large"	//$NON-NLS-1$
+  };
+
+  /**
+   * YY_ATTRIBUTE[aState] contains the attributes of state <code>aState</code>
+   */
+  private final static byte YY_ATTRIBUTE[] = {
+     1,  0,  0,  0,  0,  1,  0,  0,  1,  1,  1,  0,  1,  1,  1,  1, 
+     0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
+     1,  1,  1,  1,  0,  0,  0,  0,  1,  1,  1,  1,  0,  0,  0,  0, 
+     0,  0,  1,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1,  1,  1, 
+     9,  1,  9,  1,  1,  9,  9,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
+     9,  1,  1,  1,  1,  9,  1,  1,  1,  1,  1,  1,  9,  1,  1,  9, 
+     1,  1,  1,  1,  9,  1,  1,  1,  1,  1,  1,  1,  9,  1,  1,  1, 
+     1,  1,  1,  1,  9,  1,  1,  1,  1,  1,  1,  9,  1,  1,  1,  1, 
+     1,  1,  1,  1,  9,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
+     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  9,  1,  1,  1, 
+     1,  1,  1,  9,  9,  1,  9,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
+     1,  1,  1,  9,  1,  1,  1,  1,  9,  1,  1,  1,  1,  9,  9,  1, 
+     9,  3,  3,  9,  3,  3,  3,  9,  3,  1,  1,  9,  1,  9,  1,  1, 
+     1,  1,  1,  9,  9,  1,  9,  3,  3,  9,  3,  3,  3,  9,  3,  1, 
+     1,  1,  9,  1,  1,  1,  9,  9,  1,  1,  0,  1,  0,  1,  2,  0, 
+     1,  2,  1,  0,  0,  0,  9,  1,  1,  1,  9,  9,  0,  0,  9,  0, 
+     0,  0,  0,  0,  0,  0,  0,  0,  0,  9,  1,  1,  0,  0,  1,  1, 
+     9,  0,  9,  0,  0,  9,  0,  0,  0,  0,  0,  9,  1,  1,  0,  1, 
+     0,  9,  0,  0,  0,  0,  0,  1,  1,  0,  0,  0,  0,  9,  0,  0, 
+     0,  0,  9,  0,  0,  0,  0,  1,  0,  0,  0,  1,  0,  0,  9,  0, 
+     0,  1,  0,  0,  9,  0,  0,  0,  0,  1,  0,  0,  1,  1,  0,  0, 
+     9,  0,  0,  0,  0,  1,  0,  0,  1,  1,  0,  0,  0,  9,  0,  0, 
+     0,  0,  0,  1,  1,  9,  1,  9,  9,  9,  9,  1,  1,  1,  1,  2, 
+    13,  3,  2,  2, 13,  3,  2,  0,  1,  1,  0,  1,  1,  1,  1,  2, 
+    13,  3,  2,  2, 13,  3,  2,  0,  1,  1,  0,  1,  1,  0,  9,  9, 
+     9,  0,  0,  1,  1,  1,  9,  0,  0,  1, 13,  9,  9, 13,  1,  9, 
+     9,  1,  1,  1,  0,  0,  0,  0,  1,  0,  0,  1,  0,  0,  1,  0, 
+     0,  3,  2,  2,  3,  2,  2,  0,  0,  0,  0,  0,  0,  0,  1,  0, 
+     0,  0,  0,  1,  0,  0,  1,  1,  1,  1,  1,  0,  0,  1,  0,  0, 
+     1,  1,  1,  1,  1,  0,  1,  0,  1,  0,  3,  2,  3,  2,  1,  1, 
+     1,  1,  1,  0,  2,  3,  3,  3,  2,  2,  3,  3,  3,  2,  1,  1, 
+     1,  1,  0,  0,  1,  1,  1,  1,  0,  0,  1,  1,  1,  1,  2,  3, 
+     3,  3,  2,  2,  3,  3,  3,  2,  1,  1,  1,  1,  0,  0,  1,  1, 
+     1,  1,  0,  0,  9,  9,  0,  1,  9,  0,  1,  1,  0,  0,  1,  5, 
+    13, 13,  0,  0,  0,  0,  0,  0,  0,  1,  1,  0,  1,  1,  9,  5, 
+     1,  3,  2,  3,  2,  1,  0,  9,  1,  0,  1,  3,  2,  3,  2,  1, 
+     0,  9,  1,  0,  0,  1,  1,  1,  1,  0,  0,  0,  0,  0,  1,  1, 
+     2,  2,  0,  0,  2,  2,  0,  0,  0,  1,  1,  1,  1,  0,  0,  0, 
+     9,  9,  1,  1,  2,  2,  1,  1,  2,  2,  1,  1,  0,  1,  1,  1, 
+     9,  9,  9,  1,  1,  2,  2,  2,  2,  0,  1,  1,  1,  1,  1,  2, 
+     2,  2,  2,  9,  1,  1,  1,  1,  3,  3,  3,  3,  1,  1,  1,  1, 
+     1,  1,  1,  1,  1,  0,  1,  0,  0,  0,  0,  0,  1,  1,  1,  1, 
+     1,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1,  0,  0,  1,  0,  0, 
+     1,  1,  1,  1,  1,  0,  0,  0,  0,  9,  1,  1,  1,  1,  1,  0, 
+     0,  0,  0,  1,  1,  1,  1,  0,  0,  1,  1,  0,  1
+  };
+
+  /** the input device */
+  private java.io.Reader yy_reader;
+
+  /** the current state of the DFA */
+  private int yy_state;
+
+  /** the current lexical state */
+  private int yy_lexical_state = YYINITIAL;
+
+  /** this buffer contains the current text to be matched and is
+      the source of the yytext() string */
+  private char yy_buffer[] = new char[16384];
+
+  /** the textposition at the last accepting state */
+  private int yy_markedPos;
+
+  /** the textposition at the last state to be included in yytext */
+  private int yy_pushbackPos;
+
+  /** the current text position in the buffer */
+  private int yy_currentPos;
+
+  /** startRead marks the beginning of the yytext() string in the buffer */
+  private int yy_startRead;
+
+  /** endRead marks the last character in the buffer, that has been read
+      from input */
+  private int yy_endRead;
+
+  /** number of newlines encountered up to the start of the matched text */
+  // private int yyline;
+
+  /** the number of characters up to the start of the matched text */
+  private int yychar;
+
+  /**
+   * the number of characters from the last newline up to the start of the 
+   * matched text
+   */
+  // private int yycolumn; 
+
+  /** 
+   * yy_atBOL == true <=> the scanner is currently at the beginning of a line
+   */
+  // private boolean yy_atBOL;
+
+  /** yy_atEOF == true <=> the scanner has returned a value for EOF */
+  private boolean yy_atEOF;
+
+  /** denotes if the user-EOF-code has already been executed */
+  private boolean yy_eof_done;
+
+  /* user code: */
+	private int fTokenCount = 0;
+ 
+	// required holders for white-space compacting
+	private boolean fShouldLoadBuffered = false;
+	private String fBufferedContext = null;
+	private int fBufferedStart = 1;
+	private int fBufferedLength = 0;
+	private ITextRegion fBufferedEmbeddedContainer = null;
+	private ITextRegion fProxyUnknownRegion = null;
+	private String f_context = null;
+
+	// state stack for handling embedded regions
+	private IntStack fStateStack = new IntStack();
+	// a "hint" as to what an embedded region should be evaluated
+	private String fEmbeddedHint = UNDEFINED;
+	// a "hint" as to what state to enter once an embedded region has
+	//   been completed
+	private int fEmbeddedPostState = YYINITIAL;
+	
+	// the container used to create embedded regions
+	private ContextRegionContainer fEmbeddedContainer = null;
+	private static final String PROXY_CONTEXT = "PROXY_CONTEXT";
+	private static final String PROXY_UNKNOWN_CONTEXT = "PROXY_UNKNOWN_CONTEXT";
+
+	private String context = null;
+	private int start = 0;
+	private int textLength = 0;
+	private int length = 0;
+
+	// offset for tracking position specific block tags
+	private int fOffset = 0;
+	
+	// the name of the current tag being opened
+	private String fCurrentTagName = null;
+
+	// the name of the current tag inside of an embedded region
+	private String internalTagName = null;
+	private String internalContext = null;
+
+	// the list of tag name BlockMarkers
+	private List fBlockMarkers = new ArrayList(0);
+	private List fNestablePrefixes = new ArrayList(1);
+	
+	// where the last internal container block was found
+	private int fLastInternalBlockStart = -1;
+
+	// required to not seek text blocks on an end tag
+	private boolean fIsBlockingEnabled = false;
+	private boolean fIsCaseSensitiveBlocking = true;
+
+	private static final boolean fForbidJSP = false;
+	
+	private int fELlevel = 0;
+
+	private JSPParserRegionFactory fRegionFactory = new JSPParserRegionFactory();
+
+	// Is the embedded tag a JSP tag
+	private boolean fEmbeddedTag = false;
+	// Is the non-embedded tag a JSP tag
+	private boolean fContainerTag = false;
+	// Is the tokenizer in a non-embedded tag (between < and >)
+	private boolean fInTagContainer = false;
+	// Is the tokenizer in an embedded tag (between < and >)
+	private boolean fInTagEmbedded = false;
+
+	/**
+	 * user method 
+	 */
+	public final void addBlockMarker(BlockMarker marker) {
+		if(containsTagName(marker.getTagName()))
+			return;
+		fBlockMarkers.add(marker);
+	}
+	/**
+	 * user method
+	 */
+	public final void addNestablePrefix(TagMarker marker) {
+		fNestablePrefixes.add(marker);
+	}
+	/* user method */
+	public List getNestablePrefixes() {
+		return fNestablePrefixes;
+	}
+	/**
+	 * user method
+	 */
+	private boolean isNestable(String tagName) {
+		//Iterator blocks = fNestablePrefixes.iterator();
+		//while(blocks.hasNext()) {
+		//	TagMarker marker = (TagMarker)blocks.next();
+		//	String markerName = marker.getTagName();
+		//	if(tagName.length() > markerName.length() + 1 && tagName.startsWith(markerName) && tagName.charAt(markerName.length()) == ':') {
+		//		return marker.isGlobal() || getOffset() >= marker.getMarker().getStart();
+		//	}
+		//}
+		//return false;
+		return true;
+	}
+	/**
+	 * user method 
+	 */
+	public final void removeNestablePrefix(String name) {
+		if (fNestablePrefixes != null) {
+			Iterator nestables = fNestablePrefixes.iterator();
+			while (nestables.hasNext()) {
+				if (((TagMarker) nestables.next()).getTagName().equalsIgnoreCase(name))
+					nestables.remove();
+			}
+		}
+	}
+	/**
+	 * user method 
+	 */
+	public final void removeBlockMarker(BlockMarker marker) {
+		fBlockMarkers.remove(marker);
+	}
+	/**
+	 * user method 
+	 */
+	public final void removeBlockMarker(String tagname) {
+		if (fBlockMarkers != null) {
+			Iterator blocks = fBlockMarkers.iterator();
+			while (blocks.hasNext()) {
+				if (((BlockMarker) blocks.next()).getTagName().equals(tagname))
+					blocks.remove();
+			}
+		}
+	}
+	/* user method */
+	private final void assembleEmbeddedTagSequence(String startType, String endTagName) {
+		assembleEmbeddedContainer(startType, null, endTagName);
+	}
+	/* user method */
+	private final void assembleEmbeddedContainer(String startType, String[] endTypes) {
+		assembleEmbeddedContainer(startType, endTypes, null);
+	}
+	/* user method */
+	private final void assembleEmbeddedContainer(String startType, String endType) {
+		assembleEmbeddedContainer(startType, new String[]{endType}, null);
+	}
+	/**
+	 *  user method 
+	 * 
+	 * Assembles an embedded container beginning with the given startType as
+	 * the first ContextRegion within it and of the type fEmbeddedHint.  The
+	 * endTypes[] array contains the context types that will cause a successful
+	 * exit.  Use of the endTagName parameter alters this behavior to force an
+	 * exit on an XML_TAG_CLOSE after seeing an XML_TAG_NAME whose significant
+	 * text matches the endTagName String.  All contents in between are
+	 * insignificant, and yes, this means comments are allowed inside.
+	 **/
+	private final void assembleEmbeddedContainer(String startType, String[] endTypes, String endTagName) {
+		// the context of the region being added to the embedded container
+		internalContext = startType;
+		// keep track of where this container began; to provide relative indeces for the regions
+		int containerStart = yychar;
+		boolean notFinished = true;
+		// keep track of where we seem to be so that the endTagName can be checked
+		boolean isInEndTag = false;
+		boolean isInFirstTag = true;
+		// create the embedded container and setup its "type"
+		if (fEmbeddedContainer == null) {
+			fEmbeddedContainer = new ContextRegionContainer();
+			fEmbeddedContainer.setType(fEmbeddedHint);
+			fEmbeddedContainer.setStart(containerStart);
+			// TODO: parent region needs to be set .... but not sure where to get it from 
+			//		fEmbeddedContainer.setParent(parentRegion);
+		}
+		int initialLength = fEmbeddedContainer.getRegions().size();
+		containerStart = fEmbeddedContainer.getStart();
+		while (notFinished) {
+			// add the region to the container
+			if (internalContext != null && internalContext != PROXY_CONTEXT) {
+				ITextRegion newToken = fRegionFactory.createToken(internalContext, yychar - containerStart, yylength(), yylength());
+				fEmbeddedContainer.getRegions().add(newToken);
+				fEmbeddedContainer.setLength(fEmbeddedContainer.getLength() + yylength());
+				fEmbeddedContainer.setTextLength(fEmbeddedContainer.getTextLength() + yylength());
+				// DW, 4/16/2003 token regions no longer have parents
+				//newToken.setParent(fEmbeddedContainer);
+			}
+			try {
+				// longscan determines whether to attempt a blockTagScan within the embedded container
+				boolean longscan = false;
+				// save the tokenizer state in case of a block tag scan
+				int previousState = yystate();
+				String previousCurrentTagName = fCurrentTagName;
+				int previousPostState = fEmbeddedPostState;
+				String previousEmbeddedHint = fEmbeddedHint;
+				// determine if a block tag scan is necessary
+				if (internalContext == XML_TAG_NAME) {
+					internalTagName = yytext();
+					if (endTagName != null && endTagName.length() == 0){
+						endTagName = internalTagName;
+					}
+					if(!isNestable(internalTagName)) {
+						internalTagName = null;
+						// snagged a tag name we shouldn't have
+						fEmbeddedPostState = ST_ABORT_EMBEDDED;
+						notFinished = false;
+					}
+				}
+				else if (internalContext == XML_TAG_OPEN || internalContext == XML_END_TAG_OPEN) {
+					internalTagName = null;
+				}
+				// do upkeep for endTagName usage; must be here since the next token could be the close
+				if (internalContext == XML_END_TAG_OPEN) {
+					isInEndTag = true;
+				} else if (internalContext == XML_TAG_CLOSE) {
+					isInFirstTag = isInEndTag = false;
+				} else {
+				 	ITextRegionList embeddedRegions = fEmbeddedContainer.getRegions();
+					if (embeddedRegions.size() > 2 && (embeddedRegions.get(embeddedRegions.size()-1)).getType() == XML_TAG_CLOSE && (embeddedRegions.get(embeddedRegions.size() - 3)).getType() == XML_TAG_OPEN && internalTagName != null) {
+						if (containsTagName(internalTagName)) {
+							longscan = true;
+							yybegin(ST_BLOCK_TAG_SCAN);
+						}
+					}
+				}
+				if (longscan)
+					fCurrentTagName = internalTagName;
+				// read the next region and context
+				internalContext = primGetNextToken();
+				if (longscan) {
+					// Returning from a block tag scan requires restoring some state variables
+					// as well as handling the block region and setting up for normal scanning
+					// inside the embedded container
+					ITextRegion newToken = fRegionFactory.createToken(internalContext, yychar - containerStart, yylength(), yylength());
+					fEmbeddedContainer.getRegions().add(newToken);
+					fEmbeddedContainer.setLength(fEmbeddedContainer.getLength() + yylength());
+					fEmbeddedContainer.setTextLength(fEmbeddedContainer.getTextLength() + yylength());
+					// DW, 4/16/2003 token regions no longer have parents
+					// newToken.setParent(fEmbeddedContainer);
+					longscan = false;
+					fEmbeddedPostState = previousPostState;
+					fEmbeddedHint = previousEmbeddedHint;
+					fCurrentTagName = previousCurrentTagName;
+					yybegin(previousState);
+					internalContext = primGetNextToken();
+				}
+			} catch (IOException e) {
+				// primGetNextToken() calls may throw an IOException
+				// catch and do nothing since the isEOF check below
+				// will properly exit if the input was too short
+			} catch (Exception f) {
+				// some other exception happened; never should
+				Logger.logException(f);
+			}
+			boolean isEndingType = yystate() == ST_ABORT_EMBEDDED;
+			ITextRegionList embeddedList = fEmbeddedContainer.getRegions();
+			if(!isEndingType) {
+				// check for ending context
+				if (endTagName == null) {
+					for (int i = 0; i < endTypes.length; i++) {
+						isEndingType = isEndingType || (internalContext == endTypes[i]) || (embeddedList.size() - initialLength) >= 2 && (embeddedList.get(embeddedList.size()-1)).getType() == endTypes[i];
+					}
+				}
+				else {
+					isEndingType = ((isInEndTag && internalContext == XML_TAG_CLOSE) || (isInFirstTag && internalContext == XML_EMPTY_TAG_CLOSE)) && internalTagName != null && internalTagName.equals(endTagName);
+				}
+			}
+			notFinished = notFinished && ((!isEndingType) && !isEOF() && (endTagName != null || internalContext != UNDEFINED) && !(internalContext == PROXY_CONTEXT && (embeddedList.get(embeddedList.size()-1)).getType() == UNDEFINED));
+		}
+		// finish adding the last context
+		if (internalContext != null && internalContext != PROXY_CONTEXT) {
+			ITextRegion newToken = fRegionFactory.createToken(internalContext, yychar - containerStart, yylength(), yylength());
+			fEmbeddedContainer.getRegions().add(newToken);
+			// DW, 4/16/2003 token regions no longer have parents
+			//newToken.setParent(fEmbeddedContainer);
+			fEmbeddedContainer.setLength(yychar - containerStart + yylength());
+			fEmbeddedContainer.setTextLength(yychar - containerStart + yylength());
+		}
+		yybegin(fEmbeddedPostState);
+	}
+	/* user method */
+	public final boolean isCaseSensitiveBlocking() {
+		return fIsCaseSensitiveBlocking;
+	}
+	/* user method */
+	public final void setCaseSensitiveBlocking(boolean newValue) {
+		fIsCaseSensitiveBlocking = newValue;
+	}
+	/* user method */
+	public boolean getBlockMarkerAllowsJSP() {
+		return getBlockMarkerAllowsJSP(fCurrentTagName);
+	}
+	/* user method */
+	public boolean getBlockMarkerAllowsJSP(String name) {
+		Iterator iterator = fBlockMarkers.iterator();
+		while(iterator.hasNext()) {
+			BlockMarker marker = (BlockMarker)iterator.next();
+			boolean casesensitive = marker.isCaseSensitive();
+			if(casesensitive && marker.getTagName().equals(name))
+				return marker.allowsJSP();
+			else if(!casesensitive && marker.getTagName().equalsIgnoreCase(name))
+				return marker.allowsJSP();
+		}
+		return true;
+	}
+	/* user method */
+	public boolean getBlockMarkerCaseSensitivity() {
+		return getBlockMarkerCaseSensitivity(fCurrentTagName);
+	}
+	public boolean getBlockMarkerCaseSensitivity(String name) {
+		Iterator iterator = fBlockMarkers.iterator();
+		while(iterator.hasNext()) {
+			BlockMarker marker = (BlockMarker)iterator.next();
+			boolean casesensitive = marker.isCaseSensitive();
+			if(casesensitive && marker.getTagName().equals(name))
+				return casesensitive;
+			else if(!casesensitive && marker.getTagName().equalsIgnoreCase(name))
+				return casesensitive;
+		}
+		return true;
+	}
+	/* user method */
+	public String getBlockMarkerContext() {
+		return getBlockMarkerContext(fCurrentTagName);
+	}
+	/* user method */
+	public String getBlockMarkerContext(String name) {
+		Iterator iterator = fBlockMarkers.iterator();
+		while(iterator.hasNext()) {
+			BlockMarker marker = (BlockMarker)iterator.next();
+			if(marker.getTagName().equals(name))
+				return marker.getContext();
+		}
+		return BLOCK_TEXT;
+	}
+	/* user method */
+	public List getBlockMarkers() {
+		return fBlockMarkers;
+	}
+	/* user method */
+	public final int getOffset() {
+		return fOffset + yychar;
+	}
+	private final boolean isBlockMarker() {
+		return isBlockMarker(fCurrentTagName);
+	}
+	private final boolean isBlockMarker(String tagName) {
+		if (!fIsBlockingEnabled)
+			return false;
+		return containsTagName(tagName);
+	}
+	/**
+	 * user method
+	 */
+	public final void beginBlockTagScan(String newTagName) {
+		beginBlockMarkerScan(newTagName, BLOCK_TEXT);
+	}
+	/**
+	 * user method
+	 *
+	 * Special tokenizer setup.  Allows tokenization to be initiated at the
+	 * start of a text block within a "newTagName" tag.
+	 *
+	 * Example: 
+	 *	Tokenizer toker = new Tokenizer();
+	 *	toker.setCaseSensitiveBlocking(false);
+	 *	toker.reset(new java.io.StringReader("afiuhqwkejhtasihgalkwhtq</scripter></scr></script>asgdasga"));
+	 *	toker.beginBlockMarkerScan("script", BLOCK_TEXT);
+	 *	toker.getRegions(); 
+	 *
+	 * Returns:
+	 *	BLOCK_TEXT: 0-40
+	 *	XML_END_TAG_OPEN: 41-42
+	 *	XML_TAG_NAME: 43-48
+	 *	XML_TAG_CLOSE: 49-49
+	 *	XML_CONTENT: 50-57
+	 *
+	 */
+	public final void beginBlockMarkerScan(String newTagName, String blockcontext) {
+		yybegin(ST_BLOCK_TAG_SCAN);
+		fCurrentTagName = newTagName;
+	}
+
+/**
+ * Method doScan.
+ * 
+ * Returns a context region for all of the text from the current position upto the end of input or
+ * to right *before* the first occurence of searchString
+ * 
+ * @param searchString - target string to search for ex.: "-->", "</tagname"
+ * @param requireTailSeparator - whether the target must be immediately followed by whitespace or '>'
+ * @param allowJSP - check for and allow for JSP markup <%%>
+ * @param context - the context of the scanned region if non-zero length
+ * @param exitState - the state to go to if the region was of non-zero length
+ * @param abortState - the state to go to if the searchString was found immediately
+ * @return String - the context found: the desired context on a non-zero length match, the abortContext on immediate success
+ * @throws IOException
+ */
+private final String doScan(String searchString, boolean requireTailSeparator, boolean allowJSP, boolean allowCDATA, String searchContext, int exitState, int immediateFallbackState) throws IOException {
+	boolean stillSearching = true;
+	boolean wasBlockingEnabled = fIsBlockingEnabled;
+	try {
+		// Disable further block (probably)
+		fIsBlockingEnabled = false;
+		int searchStringLength = searchString.length();
+		int n = 0;
+		char lastCheckChar;
+		int i;
+		boolean same = false;
+		// Check for JSP starts ("<%") if the tag is global like SCRIPT or STYLE
+		boolean checkJSPs = allowJSP && !fForbidJSP;
+		boolean checkedForJSPsOnce = !checkJSPs;
+		boolean checkedJSPsAtStartOnce = false;
+		
+		while (stillSearching) {
+			n = 0;
+			// Ensure that enough data from the input exists to compare against the search String.
+			n = yy_advance();
+			while(n != YYEOF && yy_currentPos < searchStringLength)
+				n = yy_advance();
+	//		c = (char) n;
+			// If the input was too short or we've exhausted the input, stop immediately.
+			if (n == YYEOF && checkedForJSPsOnce) {
+				stillSearching = false;
+			}
+			else {
+				/**
+				 * Look for starting JSPs "<%"
+				 */
+				checkedForJSPsOnce = true;
+				// 1) yy_currentPos - searchStringLength : There's at least searchStringLength of input available; once that's read, check for JSPs
+				// ---
+				// Look for a JSP beginning at current-searchStringLength; if so, backup and switch scanner states to handle it.
+				// Ensure that we've not encountered a complete block (<%%>) that was *shorter* than the closeTagString and
+				// thus found twice at current-targetLength [since the first scan would have come out this far anyway].
+				if(checkJSPs && yy_currentPos > searchStringLength && yy_currentPos - searchStringLength != fLastInternalBlockStart && 
+					yy_buffer[yy_currentPos - searchStringLength] == '<' && yy_buffer[yy_currentPos - searchStringLength + 1] == '%') {
+					fLastInternalBlockStart = yy_markedPos = yy_currentPos - searchStringLength;
+					yy_currentPos = yy_markedPos + 1;
+					int resumeState = yystate();
+					yybegin(ST_BLOCK_TAG_INTERNAL_SCAN);
+					if(yy_markedPos == yy_startRead) {
+						String jspContext = primGetNextToken();
+						yybegin(resumeState);
+						return jspContext;
+					}
+					return searchContext;
+				}
+				// 2) yy_currentPos - jspstarter.length : There's not searchStringLength of input available; check for a JSP 2 spots back in what we could read
+				// ---
+				// Look for a JSP beginning at the current position; this case wouldn't be handled by the preceding section
+				// since it relies upon *having* closeTagStringLength amount of input to work as designed.  Must be sure we don't
+				// spill over the end of the buffer while checking.
+				else if(checkJSPs && yy_startRead != fLastInternalBlockStart && yy_currentPos > 0 && yy_currentPos < yy_buffer.length - 1 &&
+						yy_buffer[yy_currentPos - 1] == '<' && yy_buffer[yy_currentPos] == '%') {
+					fLastInternalBlockStart = yy_markedPos = yy_currentPos - 1;
+					yy_currentPos = yy_markedPos + 1;
+					int resumeState = yystate();
+					yybegin(ST_BLOCK_TAG_INTERNAL_SCAN);
+					if(yy_markedPos == yy_startRead) {
+						String jspContext = primGetNextToken();
+						yybegin(resumeState);
+						return jspContext;
+					}
+					return searchContext;
+				}
+				// 3) yy_currentPos..(yy_currentPos+jspStartlength-1) : Check at the start of the block one time
+				// ---
+				// Look for a JSP beginning immediately in the block area; this case wouldn't be handled by the preceding section
+				// since it relies upon yy_currentPos equaling exactly the previous end +1 to work as designed.
+				else if(checkJSPs && !checkedJSPsAtStartOnce && yy_startRead != fLastInternalBlockStart && yy_startRead > 0 &&
+						yy_startRead < yy_buffer.length - 1 && yy_buffer[yy_startRead] == '<' && yy_buffer[yy_startRead + 1] == '%') {
+					checkedJSPsAtStartOnce = true;
+					fLastInternalBlockStart = yy_markedPos = yy_startRead;
+					yy_currentPos = yy_markedPos + 1;
+					int resumeState = yystate();
+					yybegin(ST_BLOCK_TAG_INTERNAL_SCAN);
+					if(yy_markedPos == yy_startRead) {
+						String jspContext = primGetNextToken();
+						yybegin(resumeState);
+						return jspContext;
+					}
+					return searchContext;
+				}
+	
+	
+				/**
+				 * Look for starting CDATA "<![CDATA["
+				 */
+				// 1) yy_currentPos - searchStringLength: There's at least searchStringLength of input available; once that's read, check for CDATA
+				// ---
+				// Look for a CDATA beginning at current-searchStringLength; if so, backup and switch scanner states to handle it.
+				// Ensure that we've not encountered a complete block (<[!CDATA[]]>) that was *shorter* than the closeTagString and
+				// thus found twice at current-targetLength [since the first scan would have come out this far anyway].
+	/*			if(checkCDATA && yy_currentPos > searchStringLength && yy_currentPos + searchStringLength < yy_buffer.length && yy_currentPos - searchStringLength != fLastInternalBlockStart && 
+					charsMatch(cdataStarter, yy_buffer, 0, yy_currentPos - searchStringLength)) {
+					fLastInternalBlockStart = yy_markedPos = yy_currentPos - searchStringLength;
+					yy_currentPos = yy_markedPos + 1;
+					int resumeState = yystate();
+					// go to a state where CDATA can be found
+					if (fEmbeddedContainer == null) {
+						fEmbeddedContainer = new ContextRegionContainer();
+						fEmbeddedContainer.setType(searchContext);
+						fEmbeddedContainer.setStart(yychar);
+					}
+					ITextRegion newToken = fRegionFactory.createToken(searchContext, yychar, yylength(), yylength());
+					fEmbeddedContainer.getRegions().add(newToken);
+					fEmbeddedContainer.setLength(fEmbeddedContainer.getLength() + yylength());
+					fEmbeddedContainer.setTextLength(fEmbeddedContainer.getTextLength() + yylength());
+					yybegin(YYINITIAL);
+					String context = primGetNextToken();
+					if(context.equals(XMLRegionContexts.XML_CDATA_OPEN)) {
+						assembleEmbeddedContainer(XMLRegionContexts.XML_CDATA_OPEN, XMLRegionContexts.XML_CDATA_CLOSE);
+					}
+					yybegin(resumeState);
+					return searchContext;
+				}
+	*//*
+				// 2) yy_currentPos - cdataStarter.length: There's not searchStringLength of input available; check for a CDATA right here spots back in what we could read
+				// ---
+				// Look for a JSP beginning at the current position; this case wouldn't be handled by the preceding section
+				// since it relies upon *having* closeTagStringLength amount of input to work as designed.  Must be sure we don't
+				// spill over the end of the buffer while checking.
+				else if(checkCDATA && yy_startRead != fLastInternalBlockStart && yy_currentPos > 0 && yy_currentPos < yy_buffer.length - 1 &&
+						yy_buffer[yy_currentPos - 1] == '<' && yy_buffer[yy_currentPos] == '%') {
+					fLastInternalBlockStart = yy_markedPos = yy_currentPos - 1;
+					yy_currentPos = yy_markedPos + 1;
+					int resumeState = yystate();
+					yybegin(ST_BLOCK_TAG_INTERNAL_SCAN);
+					if(yy_markedPos == yy_startRead) {
+						String jspContext = primGetNextToken();
+						yybegin(resumeState);
+						return jspContext;
+					}
+					return searchContext;
+				}
+				// 3) yy_currentPos : Check at the start of the block one time
+				// ---
+				// Look for a JSP beginning immediately in the block area; this case wouldn't be handled by the preceding section
+				// since it relies upon yy_currentPos equaling exactly the previous end +1 to work as designed.
+				else if(checkCDATA && !checkedForCDATAOnce && yy_startRead != fLastInternalBlockStart && yy_startRead > 0 &&
+						yy_startRead < yy_buffer.length - 1 && yy_buffer[yy_startRead] == '<' && yy_buffer[yy_startRead + 1] == '%') {
+					checkedForCDATAOnce = true;
+					fLastInternalBlockStart = yy_markedPos = yy_startRead;
+					yy_currentPos = yy_markedPos + 1;
+					int resumeState = yystate();
+					yybegin(ST_BLOCK_TAG_INTERNAL_SCAN);
+					if(yy_markedPos == yy_startRead) {
+						String jspContext = primGetNextToken();
+						yybegin(resumeState);
+						return jspContext;
+					}
+					return searchContext;
+				}
+	*/
+				// Check the characters in the target versus the last targetLength characters read from the buffer
+				// and see if it matches
+				if (n == YYEOF) {
+					stillSearching = false;
+				}
+				else {
+					same = true;
+					// safety check for array accesses
+					if(yy_currentPos >= searchStringLength && yy_currentPos <= yy_buffer.length) {
+						for(i = 0; i < searchStringLength && same; i++) {
+							if(fIsCaseSensitiveBlocking)
+								same = yy_buffer[i + yy_currentPos - searchStringLength] == searchString.charAt(i);
+							else
+								same = Character.toLowerCase(yy_buffer[i + yy_currentPos - searchStringLength]) == Character.toLowerCase(searchString.charAt(i));
+						}
+					}
+					// safety check failed; no match is possible right now
+					else {
+						same = false;
+					}
+				}
+				if (same && requireTailSeparator && yy_currentPos < yy_buffer.length) {
+					// Additional check for close tags to ensure that targetString="</script" doesn't match
+					// "</scriptS"
+					lastCheckChar = yy_buffer[yy_currentPos];
+					// Succeed on "</script>" and "</script "
+					if(lastCheckChar == '>' || Character.isWhitespace(lastCheckChar))
+						stillSearching = false;
+				}
+				else {
+					stillSearching = !same || (yy_currentPos < yy_startRead + searchStringLength);
+				}
+			}
+		}
+		if (n != YYEOF || same) {
+			// We've stopped short of the end or definitely found a match
+			yy_markedPos = yy_currentPos - searchStringLength;
+			yy_currentPos = yy_markedPos + 1;
+			// If the searchString occurs at the very beginning of what would have
+			// been a Block, resume scanning normally immediately
+			if (yy_markedPos == yy_startRead) {
+				yybegin(immediateFallbackState);
+				return primGetNextToken();
+			}
+		}
+		else {
+			// We ran through the rest of the input
+			yy_markedPos = yy_currentPos;
+			yy_currentPos++;
+		}
+		yybegin(exitState);
+		// If the ending occurs at the very beginning of what would have
+		// been a Block, resume scanning normally immediately
+		if(yy_markedPos == yy_startRead)
+			return primGetNextToken();
+		return searchContext;
+	}
+	finally {
+		fIsBlockingEnabled = wasBlockingEnabled;
+	}
+}
+/**
+ * user method 
+ * does a lookahead for the current tag name
+ */
+private final String doBlockTagScan() throws IOException {
+	fIsCaseSensitiveBlocking = getBlockMarkerCaseSensitivity();
+	return doScan("</" + fCurrentTagName, true, getBlockMarkerAllowsJSP(), true, getBlockMarkerContext(fCurrentTagName), YYINITIAL, YYINITIAL);
+}
+	/**
+	 * user method
+	 *
+	 * Converts the raw context String returned by the primGetNextToken()
+	 * method into a full ITextRegion by pulling in values for the
+	 * current offset within the scanning text.
+	 *
+	 * Returns null when EOF is encountered and attaches intermittently
+	 * discovered whitespace onto the end of useful regions.
+	 *
+	 * Note that this algorithm caches the token following the one being returned
+	 * so that whitespace can be collapsed.
+	 */
+	public final ITextRegion getNextToken() throws IOException {
+		fEmbeddedContainer = null;
+		// load the starting non-whitespace token (assume that it is so)
+		if (fShouldLoadBuffered) {
+			if (fBufferedEmbeddedContainer != null) {
+				ITextRegion container = fBufferedEmbeddedContainer;
+				fBufferedEmbeddedContainer = null;
+				fShouldLoadBuffered = false;
+				return container;
+			}
+			context = fBufferedContext;
+			start = fBufferedStart;
+			textLength = length = fBufferedLength;
+			fShouldLoadBuffered = false;
+		} else {
+			context = primGetNextToken();
+			if (context == PROXY_CONTEXT) {
+				return fEmbeddedContainer;
+			} else if (context == XML_TAG_NAME || f_context == JSP_ROOT_TAG_NAME || f_context == JSP_DIRECTIVE_NAME) {
+				if(containsTagName(yy_buffer, yy_startRead, yy_markedPos-yy_startRead))
+					fCurrentTagName = yytext();
+				else
+					fCurrentTagName = null;
+			} else if (context == XML_TAG_OPEN) {
+				fIsBlockingEnabled = true;
+			} else if (context == XML_END_TAG_OPEN) {
+				fIsBlockingEnabled = false;
+			}
+			start = yychar;
+			textLength = length = yylength();
+			if (yy_atEOF) {
+				fTokenCount++;
+				return null;
+			}
+		}
+		// store the next token
+		f_context = primGetNextToken();
+		if (f_context == PROXY_CONTEXT) {
+			fBufferedEmbeddedContainer = fEmbeddedContainer;
+			fShouldLoadBuffered = true;
+		} else if (f_context == XML_TAG_NAME || f_context == JSP_ROOT_TAG_NAME || f_context == JSP_DIRECTIVE_NAME) {
+			if(containsTagName(yy_buffer, yy_startRead, yy_markedPos-yy_startRead))
+				fCurrentTagName = yytext();
+			else
+				fCurrentTagName = null;
+		} else if (f_context == XML_TAG_OPEN) {
+			fIsBlockingEnabled = true;
+		} else if (f_context == XML_END_TAG_OPEN) {
+			fIsBlockingEnabled = false;
+		} else if (f_context == PROXY_UNKNOWN_CONTEXT) {
+			fBufferedEmbeddedContainer = fProxyUnknownRegion;
+		}
+		fBufferedContext = f_context;
+		fBufferedStart = yychar;
+		fBufferedLength = yylength();
+		fShouldLoadBuffered = true;
+		if (fBufferedContext == WHITE_SPACE) {
+			fShouldLoadBuffered = false;
+			length += fBufferedLength;
+		}
+		if (context == null) {
+			// EOF
+			if (Debug.debugTokenizer) {
+				System.out.println(getClass().getName() + " discovered " + fTokenCount + " tokens."); //$NON-NLS-2$//$NON-NLS-1$
+			}
+			return null;
+		}
+		fTokenCount++;
+		return fRegionFactory.createToken(context, start, textLength, length, null, fCurrentTagName);
+	}
+	/* user method */
+	public JSPTokenizer(){
+		super();
+	}
+	/* user method */
+	public JSPTokenizer(char[] charArray){
+			this(new CharArrayReader(charArray));
+	}
+	/* user method */
+	public void reset(char[] charArray) {
+		reset(new CharArrayReader(charArray), 0);
+	}
+	/* user method */
+	public void reset(char[] charArray, int newOffset) {
+		reset(new CharArrayReader(charArray), newOffset);
+	}
+	/* user method */
+	public void reset(java.io.InputStream in) {
+		reset(new java.io.InputStreamReader(in), 0);
+	}
+	/* user method */
+	public void reset(java.io.InputStream in, int newOffset) {
+		reset(new java.io.InputStreamReader(in), newOffset);
+	}
+	/* user method */
+	public void reset(java.io.Reader in) {
+		reset(in, 0);
+	}
+	/**
+	 * user method *
+	 *
+	 * Reset internal counters and vars to "newly created" values, in the hopes
+	 * that resetting a pre-existing tokenizer is faster than creating a new one.
+	 *
+	 * This method contains code blocks that were essentially duplicated from the
+	 * <em>generated</em> output of this specification before this method was
+	 * added.  Those code blocks were under the above copyright.
+	 */
+	public void reset(java.io.Reader in, int newOffset) {
+		if (Debug.debugTokenizer) {
+			System.out.println("resetting tokenizer");//$NON-NLS-1$
+		}
+		fOffset = newOffset;
+	
+		/* the input device */
+		yy_reader = in;
+	
+		/* the current state of the DFA */
+		yy_state = 0;
+	
+		/* the current lexical state */
+		yy_lexical_state = YYINITIAL;
+	
+		/* this buffer contains the current text to be matched and is
+		the source of the yytext() string */
+		java.util.Arrays.fill(yy_buffer, (char)0);
+	
+		/* the textposition at the last accepting state */
+		yy_markedPos = 0;
+	
+		/* the textposition at the last state to be included in yytext */
+		yy_pushbackPos = 0;
+	
+		/* the current text position in the buffer */
+		yy_currentPos = 0;
+	
+		/* startRead marks the beginning of the yytext() string in the buffer */
+		yy_startRead = 0;
+	
+		/** 
+		 * endRead marks the last character in the buffer, that has been read
+		 * from input 
+		 */
+		yy_endRead = 0;
+	
+		/* number of newlines encountered up to the start of the matched text */
+		//yyline = 0;
+	
+		/* the number of characters up to the start of the matched text */
+		yychar = 0;
+	
+		/* yy_atEOF == true <=> the scanner has returned a value for EOF */
+		yy_atEOF = false;
+	
+		/* denotes if the user-EOF-code has already been executed */
+		yy_eof_done = false;
+	
+	
+		/* user vars: */
+		fTokenCount = 0;
+	 
+		fShouldLoadBuffered = false;
+		fBufferedContext = null;
+		fBufferedStart = 1;
+		fBufferedLength = 0;
+		fStateStack = new IntStack();
+	
+		fLastInternalBlockStart = -1;
+	
+		context = null;
+		start = 0;
+		textLength = 0;
+		length = 0;
+	
+		fEmbeddedContainer = null;
+		
+		fELlevel = 0;
+	}
+	/**
+	 * user method
+	 *
+	 */
+	public BlockTokenizer newInstance() {
+		JSPTokenizer newInstance = new JSPTokenizer();
+		// global tagmarkers can be shared; they have no state and 
+		// are never destroyed (e.g. 'release')
+		for(int i = 0; i < fBlockMarkers.size(); i++) {
+			BlockMarker blockMarker = (BlockMarker) fBlockMarkers.get(i);
+			if(blockMarker.isGlobal())
+				newInstance.addBlockMarker(blockMarker);
+		}
+		for(int i = 0; i < fNestablePrefixes.size(); i++) {
+			TagMarker marker = (TagMarker) fNestablePrefixes.get(i);
+			if(marker.isGlobal())
+				newInstance.addNestablePrefix(marker);
+		}
+		return newInstance;
+	}
+	/* user method */
+	private final String scanXMLCommentText() throws IOException {
+		// Scan for '-->' and return the text up to that point as
+		//   XML_COMMENT_TEXT unless the string occurs IMMEDIATELY, in which
+		//  case change to the ST_XML_COMMENT_END state and return the next
+		//  context as usual.
+		return doScan("-->", false, true, true, XML_COMMENT_TEXT, ST_XML_COMMENT_END, ST_XML_COMMENT_END);
+	}
+	/* user method */
+	private final String scanJSPCommentText() throws IOException {
+		// Scan for '--%>' and return the text up to that point as
+		//   JSP_COMMENT_TEXT unless the string occurs IMMEDIATELY, in which
+		//  case change to the ST_JSP_COMMENT_END state and return the next
+		//  context as usual.
+		return doScan("--%>", false, false, true, JSP_COMMENT_TEXT, ST_JSP_COMMENT_END, ST_JSP_COMMENT_END);
+	}
+	
+	/* user method */
+	private boolean isJspTag() {
+		return (fContainerTag && fEmbeddedContainer != null) || (fContainerTag && fInTagContainer) || (fEmbeddedTag && fInTagEmbedded);
+	}
+
+
+  /**
+   * Creates a new scanner
+   * There is also a java.io.InputStream version of this constructor.
+   *
+   * @param   in  the java.io.Reader to read input from.
+   */
+  public JSPTokenizer(java.io.Reader in) {
+    this.yy_reader = in;
+  }
+
+  /**
+   * Creates a new scanner.
+   * There is also java.io.Reader version of this constructor.
+   *
+   * @param   in  the java.io.Inputstream to read input from.
+   */
+  public JSPTokenizer(java.io.InputStream in) {
+    this(new java.io.InputStreamReader(in));
+  }
+
+  /** 
+   * Unpacks the compressed DFA transition table.
+   *
+   * @param packed   the packed transition table
+   * @return         the unpacked transition table
+   */
+  private static int [] yy_unpack(String packed) {
+    int [] trans = new int[35287];
+    int i = 0;  /* index in packed string  */
+    int j = 0;  /* index in unpacked array */
+    while (i < 9344) {
+      int count = packed.charAt(i++);
+      int value = packed.charAt(i++);
+      value--;
+      do trans[j++] = value; while (--count > 0);
+    }
+    return trans;
+  }
+
+  /** 
+   * Unpacks the compressed character translation table.
+   *
+   * @param packed   the packed character translation table
+   * @return         the unpacked character translation table
+   */
+  private static char [] yy_unpack_cmap(String packed) {
+    char [] map = new char[0x10000];
+    int i = 0;  /* index in packed string  */
+    int j = 0;  /* index in unpacked array */
+    while (i < 1376) {
+      int  count = packed.charAt(i++);
+      char value = packed.charAt(i++);
+      do map[j++] = value; while (--count > 0);
+    }
+    return map;
+  }
+
+
+  /**
+   * Gets the next input character.
+   *
+   * @return      the next character of the input stream, EOF if the
+   *              end of the stream is reached.
+   * @exception   IOException  if any I/O-Error occurs
+   */
+  private int yy_advance() throws java.io.IOException {
+
+    /* standard case */
+    if (yy_currentPos < yy_endRead) return yy_buffer[yy_currentPos++];
+
+    /* if the eof is reached, we don't need to work hard */ 
+    if (yy_atEOF) return YYEOF;
+
+    /* otherwise: need to refill the buffer */
+
+    /* first: make room (if you can) */
+    if (yy_startRead > 0) {
+      System.arraycopy(yy_buffer, yy_startRead, 
+                       yy_buffer, 0, 
+                       yy_endRead-yy_startRead);
+
+      /* translate stored positions */
+      yy_endRead-= yy_startRead;
+      yy_currentPos-= yy_startRead;
+      yy_markedPos-= yy_startRead;
+      yy_pushbackPos-= yy_startRead;
+      yy_startRead = 0;
+    }
+
+    /* is the buffer big enough? */
+    if (yy_currentPos >= yy_buffer.length) {
+      /* if not: blow it up */
+      char newBuffer[] = new char[yy_currentPos*2];
+      System.arraycopy(yy_buffer, 0, newBuffer, 0, yy_buffer.length);
+      yy_buffer = newBuffer;
+    }
+
+    /* finally: fill the buffer with new input */
+    int numRead = yy_reader.read(yy_buffer, yy_endRead, 
+                                            yy_buffer.length-yy_endRead);
+
+    if ( numRead == -1 ) return YYEOF;
+
+    yy_endRead+= numRead;
+
+    return yy_buffer[yy_currentPos++];
+  }
+
+    
+  /**
+   * Closes the input stream.
+   */
+  final public void yyclose() throws java.io.IOException {
+    yy_atEOF = true;            /* indicate end of file */
+    yy_endRead = yy_startRead;  /* invalidate buffer    */
+    yy_reader.close();
+  }
+
+
+  /**
+   * Returns the current lexical state.
+   */
+  final public int yystate() {
+    return yy_lexical_state;
+  }
+
+  /**
+   * Enters a new lexical state
+   *
+   * @param newState the new lexical state
+   */
+  final public void yybegin(int newState) {
+    yy_lexical_state = newState;
+  }
+
+
+  /**
+   * Returns the text matched by the current regular expression.
+   */
+  final public String yytext() {
+    return new String( yy_buffer, yy_startRead, yy_markedPos-yy_startRead );
+  }
+
+  /**
+   * Returns the length of the matched text region.
+   */
+  final public int yylength() {
+    return yy_markedPos-yy_startRead;
+  }
+
+
+  /**
+   * Reports an error that occured while scanning - from the SED JFlex skeleton
+   *
+   * @param   errorCode  the code of the errormessage to display
+   */
+  private void yy_ScanError(int errorCode) {
+    try {
+      Logger.log(Logger.ERROR, YY_ERROR_MSG[errorCode]);
+    }
+    catch (ArrayIndexOutOfBoundsException e) {
+      Logger.log(Logger.ERROR, YY_ERROR_MSG[YY_UNKNOWN_ERROR]);
+    }
+    // DO NOT EXIT the VM on an error
+    // System.exit(1);
+  } 
+
+
+  /**
+   * Pushes the specified amount of characters back into the input stream.
+   *
+   * They will be read again by then next call of the scanning method
+   *
+   * @param number  the number of characters to be read again.
+   *                This number must not be greater than yylength()!
+   */
+  void yypushback(int number) {
+    if ( number > yylength() )
+      yy_ScanError(YY_PUSHBACK_2BIG);
+
+    yy_markedPos -= number;
+  }
+
+	/**
+	 * user method - skeleton.sed
+	 */
+	protected final boolean containsTagName(char[] markerTagName, int offset, int tagnameLength) {
+		for(int j = 0; j < fBlockMarkers.size(); j++) {
+			BlockMarker marker = (BlockMarker)fBlockMarkers.get(j);
+			if(marker.getTagName().length() == tagnameLength) {
+				boolean matchesSoFar = true;
+				for(int i = 0; i < tagnameLength && matchesSoFar; i++) {
+					if(marker.isCaseSensitive()) {
+						if(marker.getTagName().charAt(i) != markerTagName[i + offset])
+							matchesSoFar = false;
+					}
+					else {
+						if(Character.toLowerCase(marker.getTagName().charAt(i)) != Character.toLowerCase(markerTagName[i + offset]))
+							matchesSoFar = false;
+					}
+				}
+				if(matchesSoFar)
+					return true;
+			}
+		}
+		return false;
+	}
+
+	/**
+	 * user method - skeleton.sed
+	 *
+	 * Return ALL of the regions scannable within the remaining text
+	 * Note: for verification use
+	 */
+	public final List getRegions() {
+		List tokens = new ArrayList();
+		ITextRegion region = null;
+		try {
+			region = getNextToken();
+			while(region != null) {
+				if (region != null) {
+					tokens.add(region);
+				}
+				region = getNextToken();
+			}
+		}
+		catch (StackOverflowError e) {
+			Logger.logException(getClass().getName()+": input could not be tokenized correctly at position " + getOffset(), e);//$NON-NLS-1$
+			throw e;
+		}
+		catch (Exception e) {
+			// Since this is convenience method and NOT the recommended 
+			// way of getting tokens, many errors are simply hidden
+			Logger.logException("Exception not handled retrieving regions: " + e.getLocalizedMessage(), e);//$NON-NLS-1$
+		}
+		return tokens;
+	}
+	/**
+	 * user method - skeleton.sed
+	 */
+	private final void dump(String s) {
+		if (Debug.debugTokenizer) {
+			System.out.println(s + " (" + yychar + "-" + //$NON-NLS-2$//$NON-NLS-1$
+				(yylength() + yychar) + "):\'" +//$NON-NLS-1$
+					StringUtils.escape(yytext()) + "\'");//$NON-NLS-1$
+		}
+	}
+	/* user method  - skeleton.sed */
+	public final boolean isEOF() {
+		return yy_atEOF;
+	}
+/* user method - skeleton.sed */
+protected final boolean containsTagName(String markerTagName) {
+	Iterator blocks = fBlockMarkers.iterator();
+	while(blocks.hasNext()) {
+		BlockMarker marker = (BlockMarker)blocks.next();
+		if(marker.isCaseSensitive()) {
+			if(marker.getTagName().equals(markerTagName))
+				return true;
+		}
+		else {
+			if(marker.getTagName().equalsIgnoreCase(markerTagName))
+				return true;
+		}
+	}
+	return false;
+}
+
+  /**
+   * Contains user EOF-code, which will be executed exactly once,
+   * when the end of file is reached
+   */
+  private void yy_do_eof() {
+    if (!yy_eof_done) {
+      yy_eof_done = true;
+    // do nothing, this is the downstream parser's job
+
+    }
+  }
+
+
+  /**
+   * Resumes scanning until the next regular expression is matched,
+   * the end of input is encountered or an I/O-Error occurs.
+   *
+   * @return      the next token
+   * @exception   IOException  if any I/O-Error occurs
+   */
+  public String primGetNextToken() throws java.io.IOException {
+    int yy_input;
+    int yy_action;
+
+    yy_pushbackPos = -1;
+    boolean yy_was_pushback;
+
+    while (true) {
+
+      yychar+= yylength();
+
+      yy_action = -1;
+
+      yy_currentPos = yy_startRead = yy_markedPos;
+
+      yy_state = yy_lexical_state;
+
+      yy_was_pushback = false;
+
+      yy_forAction: {
+        while (true) {
+    
+          yy_input = yy_advance();
+
+          if ( yy_input == YYEOF ) break yy_forAction;
+
+          int yy_next = yytrans[ yy_rowMap[yy_state] + yycmap[yy_input] ];
+          if (yy_next == -1) break yy_forAction;
+          yy_state = yy_next;
+
+          int yy_attributes = YY_ATTRIBUTE[yy_state];
+          if ( (yy_attributes & 2) > 0 )
+            yy_pushbackPos = yy_currentPos;
+
+          if ( (yy_attributes & 1) > 0 ) {
+            yy_was_pushback = (yy_attributes & 4) > 0;
+            yy_action = yy_state; 
+            yy_markedPos = yy_currentPos; 
+            if ( (yy_attributes & 8) > 0 ) break yy_forAction;
+          }
+
+        }
+      }
+
+      if (yy_was_pushback)
+        yy_markedPos = yy_pushbackPos;
+
+      switch (yy_action) {    
+
+        case 124: 
+        case 129: 
+        case 130: 
+        case 289: 
+        case 295: 
+        case 296: 
+        case 433: 
+        case 436: 
+        case 543: 
+          {  /* only allow for non-JSP tags for this does not obey JSP quoting rules */
+	if(Debug.debugTokenizer)
+		dump("attr value");//$NON-NLS-1$
+	fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;
+	fEmbeddedPostState = ST_XML_EQUALS;
+        yybegin(ST_XML_ATTRIBUTE_NAME);
+        return XML_TAG_ATTRIBUTE_VALUE;
+ }
+        case 718: break;
+        case 169: 
+        case 174: 
+        case 175: 
+        case 349: 
+        case 355: 
+        case 356: 
+        case 470: 
+        case 472: 
+        case 474: 
+        case 476: 
+        case 559: 
+          {  /* JSP attribute values have escape semantics */
+	if(Debug.debugTokenizer)
+		dump("jsp attr value");//$NON-NLS-1$
+	fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;
+	fEmbeddedPostState = ST_XML_EQUALS;
+	yybegin(ST_XML_ATTRIBUTE_NAME);
+	return XML_TAG_ATTRIBUTE_VALUE;
+ }
+        case 719: break;
+        case 685: 
+        case 690: 
+        case 697: 
+        case 702: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("jsp directive tag name");//$NON-NLS-1$
+	fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;
+	fEmbeddedPostState = ST_XML_EQUALS;
+        yybegin(ST_XML_ATTRIBUTE_NAME);
+        return JSP_DIRECTIVE_NAME;
+ }
+        case 720: break;
+        case 660: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("XSL processing instruction target");//$NON-NLS-1$
+	fEmbeddedPostState = ST_XML_EQUALS;
+        yybegin(ST_XML_PI_ATTRIBUTE_NAME);
+        return XML_TAG_NAME;
+ }
+        case 721: break;
+        case 643: 
+        case 646: 
+        case 647: 
+        case 648: 
+        case 649: 
+        case 650: 
+        case 651: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("\nCDATA start");//$NON-NLS-1$
+	fStateStack.push(yystate());
+	yybegin(ST_CDATA_TEXT);
+	return XML_CDATA_OPEN;
+ }
+        case 722: break;
+        case 635: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("jsp:root tag name");//$NON-NLS-1$
+	fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;
+	fEmbeddedPostState = ST_XML_EQUALS;
+        yybegin(ST_XML_ATTRIBUTE_NAME);
+        return JSP_ROOT_TAG_NAME;
+ }
+        case 723: break;
+        case 626: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("element");//$NON-NLS-1$
+	yybegin(ST_XML_ELEMENT_DECLARATION);
+	return XML_ELEMENT_DECLARATION;
+ }
+        case 724: break;
+        case 625: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("attlist");//$NON-NLS-1$
+	yybegin(ST_XML_ATTLIST_DECLARATION);
+	return XML_ATTLIST_DECLARATION;
+ }
+        case 725: break;
+        case 624: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("doctype");//$NON-NLS-1$
+	yybegin(ST_XML_DOCTYPE_DECLARATION);
+	return XML_DOCTYPE_DECLARATION;
+ }
+        case 726: break;
+        case 609: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("doctype external id");//$NON-NLS-1$
+	fEmbeddedHint = XML_DOCTYPE_EXTERNAL_ID_PUBREF;
+	yybegin(ST_XML_DOCTYPE_ID_PUBLIC);
+	return XML_DOCTYPE_EXTERNAL_ID_PUBLIC;
+ }
+        case 727: break;
+        case 608: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("doctype external id");//$NON-NLS-1$
+	fEmbeddedHint = XML_DOCTYPE_EXTERNAL_ID_SYSREF;
+	yybegin(ST_XML_DOCTYPE_ID_SYSTEM);
+	return XML_DOCTYPE_EXTERNAL_ID_SYSTEM;
+ }
+        case 728: break;
+        case 602: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("DHTML processing instruction target");//$NON-NLS-1$
+	fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;
+	fEmbeddedPostState = ST_XML_EQUALS;
+        yybegin(ST_DHTML_ATTRIBUTE_NAME);
+        return XML_TAG_NAME;
+ }
+        case 729: break;
+        case 577: 
+        case 618: 
+        case 619: 
+          { 
+	return JSP_VBL_QUOTED_CONTENT;
+ }
+        case 730: break;
+        case 567: 
+        case 614: 
+        case 615: 
+          { 
+	return JSP_EL_QUOTED_CONTENT;
+ }
+        case 731: break;
+        case 558: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("\nJSP comment close");//$NON-NLS-1$
+	yybegin(YYINITIAL);
+	return JSP_COMMENT_CLOSE;
+ }
+        case 732: break;
+        case 545: 
+          { 
+	if (Debug.debugTokenizer) {
+		System.out.println("begin embedded region: " + fEmbeddedHint+", el-unquoted");//$NON-NLS-1$
+	}
+	fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;
+	fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+	fStateStack.push(yystate());
+	if(yylength() > 2)
+		yypushback(yylength() -2);
+	if(Debug.debugTokenizer)
+		dump("VBL in attr value");//$NON-NLS-1$
+	yybegin(ST_JSP_VBL);
+	fELlevel++;
+	assembleEmbeddedContainer(JSP_VBL_OPEN, new String[]{JSP_VBL_CLOSE});
+	fStateStack.pop();
+	yybegin(ST_XML_ATTRIBUTE_NAME);
+	fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;
+	fEmbeddedPostState = ST_XML_EQUALS;
+	return PROXY_CONTEXT;
+ }
+        case 733: break;
+        case 544: 
+          { 
+	if (Debug.debugTokenizer) {
+		System.out.println("begin embedded region: " + fEmbeddedHint+", el-unquoted");//$NON-NLS-1$
+	}
+	fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;
+	fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+	fStateStack.push(yystate());
+	if(yylength() > 2)
+		yypushback(yylength() -2);
+	if(Debug.debugTokenizer)
+		dump("EL in attr value");//$NON-NLS-1$
+	yybegin(ST_JSP_EL);
+	fELlevel++;
+	assembleEmbeddedContainer(JSP_EL_OPEN, new String[]{JSP_EL_CLOSE});
+	fStateStack.pop();
+	yybegin(ST_XML_ATTRIBUTE_NAME);
+	fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;
+	fEmbeddedPostState = ST_XML_EQUALS;
+	return PROXY_CONTEXT;
+ }
+        case 734: break;
+        case 536: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("\nCharRef");//$NON-NLS-1$
+	return XML_CHAR_REFERENCE;
+ }
+        case 735: break;
+        case 533: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("\ncomment start");//$NON-NLS-1$
+	fEmbeddedHint = XML_COMMENT_TEXT;
+	fEmbeddedPostState = ST_XML_COMMENT;
+	yybegin(ST_XML_COMMENT);
+	return XML_COMMENT_OPEN;
+ }
+        case 736: break;
+        case 532: 
+        case 553: 
+        case 556: 
+        case 560: 
+        case 561: 
+        case 563: 
+        case 565: 
+        case 568: 
+        case 570: 
+        case 571: 
+        case 573: 
+        case 575: 
+        case 578: 
+          { 
+	/* JSP comment begun (anywhere)
+	 * A consequence of the start anywhere possibility is that the
+	 *  incoming state must be checked to see if it's erroneous
+	 *  due to the order of precedence generated
+	 */
+	// begin sanity checks
+	if(yystate() == ST_JSP_CONTENT) {
+		// at the beginning?!
+		yypushback(3);
+		return JSP_CONTENT;
+	}
+	else if(yystate() == ST_BLOCK_TAG_SCAN) {
+		yypushback(4);
+		return doBlockTagScan();
+	}
+	else if(yystate() == ST_XML_COMMENT) {
+		yypushback(4);
+		return scanXMLCommentText();
+	}
+	else if(yystate() == ST_JSP_COMMENT) {
+		yypushback(4);
+		return scanJSPCommentText();
+	}
+	else if(yystate() == ST_BLOCK_TAG_INTERNAL_SCAN)  {
+		yybegin(ST_JSP_COMMENT);
+		assembleEmbeddedContainer(JSP_COMMENT_OPEN, JSP_COMMENT_CLOSE);
+		if(yystate() == ST_BLOCK_TAG_INTERNAL_SCAN)
+			yybegin(ST_BLOCK_TAG_SCAN);
+		return PROXY_CONTEXT;
+	}
+	// finished sanity checks
+	if(yystate()==YYINITIAL) {
+		// the simple case, just a regular scriptlet out in content
+		if(Debug.debugTokenizer)
+			dump("\nJSP comment start");//$NON-NLS-1$
+		yybegin(ST_JSP_COMMENT);
+		return JSP_COMMENT_OPEN;
+	}
+	else {
+		if (Debug.debugTokenizer) {
+			System.out.println("begin embedded region: " + fEmbeddedHint+", jspCommentStart");//$NON-NLS-1$
+		}
+		if(Debug.debugTokenizer)
+			dump("JSP comment start");//$NON-NLS-1$
+		if(yystate() == ST_XML_ATTRIBUTE_VALUE_DQUOTED)
+			fEmbeddedPostState = ST_XML_ATTRIBUTE_VALUE_DQUOTED;
+		else if(yystate() == ST_XML_ATTRIBUTE_VALUE_SQUOTED)
+			fEmbeddedPostState = ST_XML_ATTRIBUTE_VALUE_SQUOTED;
+		else if(yystate() == ST_CDATA_TEXT) {
+			fEmbeddedPostState = ST_CDATA_TEXT;
+			fEmbeddedHint = XML_CDATA_TEXT;
+		}
+		yybegin(ST_JSP_COMMENT);
+		// the comment container itself will act as comment text
+		fEmbeddedHint = JSP_COMMENT_TEXT;
+		assembleEmbeddedContainer(JSP_COMMENT_OPEN, JSP_COMMENT_CLOSE);
+		if(yystate() == ST_BLOCK_TAG_INTERNAL_SCAN) {
+			yybegin(ST_BLOCK_TAG_SCAN);
+			return BLOCK_TEXT;
+		}
+		/*
+		 * required help for successive embedded regions; mark this one as a
+		 * comment so it will be otherwise ignored but preserved (which is why
+		 * we can't use white-space)
+		 */
+		if(yystate() == ST_XML_TAG_NAME) {
+			fEmbeddedHint = XML_TAG_NAME;
+			fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+		}
+		else if((yystate() == ST_XML_ATTRIBUTE_NAME || yystate() == ST_XML_EQUALS)) {
+			fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;
+			fEmbeddedPostState = ST_XML_EQUALS;
+		}
+		else if(yystate() == ST_XML_ATTRIBUTE_VALUE) {
+			fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;
+			fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+		}
+		else if(yystate() == ST_JSP_ATTRIBUTE_VALUE) {
+			fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;
+			fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+		}
+		return PROXY_CONTEXT;
+	}
+ }
+        case 737: break;
+        case 417: 
+        case 418: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("XML processing instruction target");//$NON-NLS-1$
+	fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;
+	fEmbeddedPostState = ST_XML_EQUALS;
+        yybegin(ST_XML_PI_ATTRIBUTE_NAME);
+        return XML_TAG_NAME;
+ }
+        case 738: break;
+        case 416: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("comment end");//$NON-NLS-1$
+	fEmbeddedHint = UNDEFINED;
+	yybegin(YYINITIAL);
+	return XML_COMMENT_CLOSE;
+ }
+        case 739: break;
+        case 415: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("CDATA end");//$NON-NLS-1$
+	yybegin(fStateStack.pop());
+	return XML_CDATA_CLOSE;
+ }
+        case 740: break;
+        case 413: 
+          { 
+	yybegin(ST_JSP_VBL);
+	if(yylength() > 2)
+		yypushback(yylength() - 2);
+	fELlevel++;
+	fEmbeddedHint = XML_CONTENT;
+	fEmbeddedPostState = YYINITIAL;
+	assembleEmbeddedContainer(JSP_VBL_OPEN, JSP_VBL_CLOSE);
+	fEmbeddedHint = XML_CONTENT;
+	yybegin(YYINITIAL);
+	return PROXY_CONTEXT;
+ }
+        case 741: break;
+        case 412: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("\nPEReference");//$NON-NLS-1$
+	return XML_PE_REFERENCE;
+ }
+        case 742: break;
+        case 410: 
+          { 
+	yybegin(ST_JSP_EL);
+	if(yylength() > 2)
+		yypushback(yylength() - 2);
+	fELlevel++;
+	fEmbeddedHint = XML_CONTENT;
+	fEmbeddedPostState = YYINITIAL;
+	assembleEmbeddedContainer(JSP_EL_OPEN, JSP_EL_CLOSE);
+	fEmbeddedHint = XML_CONTENT;
+	yybegin(YYINITIAL);
+	return PROXY_CONTEXT;
+ }
+        case 743: break;
+        case 406: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("\nEntityRef");//$NON-NLS-1$
+	return XML_ENTITY_REFERENCE;
+ }
+        case 744: break;
+        case 400: 
+        case 457: 
+        case 467: 
+        case 482: 
+        case 487: 
+        case 492: 
+        case 497: 
+        case 503: 
+        case 509: 
+        case 513: 
+        case 518: 
+        case 523: 
+        case 529: 
+          { 
+	/* JSP expression begun (anywhere)
+	 * A consequence of the start anywhere possibility is that the
+	 *  incoming state must be checked to see if it's erroneous
+	 *  due to the order of precedence generated
+	 */
+	// begin sanity checks
+	if(yystate() == ST_JSP_CONTENT) {
+		// at the beginning?!
+		yypushback(2);
+		return JSP_CONTENT;
+	}
+	else if(yystate() == ST_BLOCK_TAG_SCAN) {
+		yypushback(3);
+		return doBlockTagScan();
+	}
+	else if(yystate() == ST_XML_COMMENT) {
+		yypushback(3);
+		return scanXMLCommentText();
+	}
+	else if(yystate() == ST_JSP_COMMENT) {
+		yypushback(3);
+		return scanJSPCommentText();
+	}
+	// end sanity checks
+	fStateStack.push(yystate());
+	if(fStateStack.peek()==YYINITIAL) {
+		// the simple case, just an expression out in content
+		if(Debug.debugTokenizer)
+			dump("\nJSP expression start");//$NON-NLS-1$
+		yybegin(ST_JSP_CONTENT);
+		return JSP_EXPRESSION_OPEN;
+	}
+	else {
+		if (Debug.debugTokenizer) {
+			System.out.println("begin embedded region: " + fEmbeddedHint+", jspExpressionStart");//$NON-NLS-1$
+		}
+		if(Debug.debugTokenizer)
+			dump("JSP expression start");//$NON-NLS-1$
+		if(yystate() == ST_XML_ATTRIBUTE_VALUE_DQUOTED)
+			fEmbeddedPostState = ST_XML_ATTRIBUTE_VALUE_DQUOTED;
+		else if(yystate() == ST_XML_ATTRIBUTE_VALUE_SQUOTED)
+			fEmbeddedPostState = ST_XML_ATTRIBUTE_VALUE_SQUOTED;
+		else if(yystate() == ST_CDATA_TEXT) {
+			fEmbeddedPostState = ST_CDATA_TEXT;
+			fEmbeddedHint = XML_CDATA_TEXT;
+		}
+		yybegin(ST_JSP_CONTENT);
+		assembleEmbeddedContainer(JSP_EXPRESSION_OPEN, JSP_CLOSE);
+		if(yystate() == ST_BLOCK_TAG_INTERNAL_SCAN) {
+			yybegin(ST_BLOCK_TAG_SCAN);
+			return BLOCK_TEXT;
+		}
+		// required help for successive embedded regions
+		if(yystate() == ST_XML_TAG_NAME) {
+			fEmbeddedHint = XML_TAG_NAME;
+			fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+		}
+		else if((yystate() == ST_XML_ATTRIBUTE_NAME || yystate() == ST_XML_EQUALS)) {
+			fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;
+			fEmbeddedPostState = ST_XML_EQUALS;
+		}
+		else if(yystate() == ST_XML_ATTRIBUTE_VALUE) {
+			fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;
+			fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+		}
+		else if(yystate() == ST_JSP_ATTRIBUTE_VALUE) {
+			fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;
+			fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+		}
+		
+		return PROXY_CONTEXT;
+	}
+ }
+        case 745: break;
+        case 399: 
+        case 456: 
+        case 466: 
+        case 481: 
+        case 486: 
+        case 491: 
+        case 496: 
+        case 502: 
+        case 508: 
+        case 512: 
+        case 517: 
+        case 522: 
+        case 528: 
+          { 
+	/* JSP declaration begun (anywhere)
+	 * A consequence of the start anywhere possibility is that the
+	 *  incoming state must be checked to see if it's erroneous
+	 *  due to the order of precedence generated
+	 */
+	// begin sanity checks
+	if(yystate() == ST_JSP_CONTENT) {
+		// at the beginning?!
+		yypushback(2);
+		return JSP_CONTENT;
+	}
+	else if(yystate() == ST_BLOCK_TAG_SCAN) {
+		yypushback(3);
+		return doBlockTagScan();
+	}
+	else if(yystate() == ST_XML_COMMENT) {
+		yypushback(3);
+		return scanXMLCommentText();
+	}
+	else if(yystate() == ST_JSP_COMMENT) {
+		yypushback(3);
+		return scanJSPCommentText();
+	}
+	// end sanity checks
+	fStateStack.push(yystate());
+	if(fStateStack.peek()==YYINITIAL) {
+		// the simple case, just a declaration out in content
+		if(Debug.debugTokenizer)
+			dump("\nJSP declaration start");//$NON-NLS-1$
+		yybegin(ST_JSP_CONTENT);
+		return JSP_DECLARATION_OPEN;
+	}
+	else {
+		if (Debug.debugTokenizer) {
+			System.out.println("begin embedded region: " + fEmbeddedHint+", jspDeclarationStart");//$NON-NLS-1$
+		}
+		if(Debug.debugTokenizer)
+			dump("JSP declaration start");//$NON-NLS-1$
+		if(yystate() == ST_XML_ATTRIBUTE_VALUE_DQUOTED)
+			fEmbeddedPostState = ST_XML_ATTRIBUTE_VALUE_DQUOTED;
+		else if(yystate() == ST_XML_ATTRIBUTE_VALUE_SQUOTED)
+			fEmbeddedPostState = ST_XML_ATTRIBUTE_VALUE_SQUOTED;
+		else if(yystate() == ST_CDATA_TEXT) {
+			fEmbeddedPostState = ST_CDATA_TEXT;
+			fEmbeddedHint = XML_CDATA_TEXT;
+		}
+		yybegin(ST_JSP_CONTENT);
+		assembleEmbeddedContainer(JSP_DECLARATION_OPEN, JSP_CLOSE);
+		if(yystate() == ST_BLOCK_TAG_INTERNAL_SCAN) {
+			yybegin(ST_BLOCK_TAG_SCAN);
+			return BLOCK_TEXT;
+		}
+		// required help for successive embedded regions
+		if(yystate() == ST_XML_TAG_NAME) {
+			fEmbeddedHint = XML_TAG_NAME;
+			fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+		}
+		else if((yystate() == ST_XML_ATTRIBUTE_NAME || yystate() == ST_XML_EQUALS)) {
+			fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;
+			fEmbeddedPostState = ST_XML_EQUALS;
+		}
+		else if(yystate() == ST_XML_ATTRIBUTE_VALUE) {
+			fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;
+			fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+		}
+		else if(yystate() == ST_JSP_ATTRIBUTE_VALUE) {
+			fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;
+			fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+		}
+		return PROXY_CONTEXT;
+	}
+ }
+        case 746: break;
+        case 398: 
+        case 455: 
+        case 465: 
+        case 480: 
+        case 485: 
+        case 490: 
+        case 495: 
+        case 501: 
+        case 507: 
+        case 511: 
+        case 516: 
+        case 521: 
+        case 527: 
+          { 
+	/* JSP directive begun (anywhere)
+	 * A consequence of the start anywhere possibility is that the
+	 *  incoming state must be checked to see if it's erroneous
+	 *  due to the order of precedence generated
+	 */
+	// begin sanity checks
+	if(yystate() == ST_JSP_CONTENT) {
+		// at the beginning?!
+		yypushback(2);
+		return JSP_CONTENT;
+	}
+	else if(yystate() == ST_BLOCK_TAG_SCAN) {
+		yypushback(3);
+		return doBlockTagScan();
+	}
+	else if(yystate() == ST_XML_COMMENT) {
+		yypushback(3);
+		return scanXMLCommentText();
+	}
+	else if(yystate() == ST_JSP_COMMENT) {
+		yypushback(3);
+		return scanJSPCommentText();
+	}
+	// end sanity checks
+	fStateStack.push(yystate());
+	if(fStateStack.peek()==YYINITIAL) {
+		// the simple case, just a declaration out in content
+		if(Debug.debugTokenizer)
+			dump("\nJSP directive start");//$NON-NLS-1$
+		yybegin(ST_JSP_DIRECTIVE_NAME);
+		return JSP_DIRECTIVE_OPEN;
+	}
+	else {
+		if (Debug.debugTokenizer) {
+			System.out.println("begin embedded region: " + fEmbeddedHint+", jspDirectiveStart");//$NON-NLS-1$
+		}
+		if(Debug.debugTokenizer)
+			dump("JSP declaration start");//$NON-NLS-1$
+		if(yystate() == ST_XML_ATTRIBUTE_VALUE_DQUOTED)
+			fEmbeddedPostState = ST_XML_ATTRIBUTE_VALUE_DQUOTED;
+		else if(yystate() == ST_XML_ATTRIBUTE_VALUE_SQUOTED)
+			fEmbeddedPostState = ST_XML_ATTRIBUTE_VALUE_SQUOTED;
+		else if(yystate() == ST_CDATA_TEXT) {
+			fEmbeddedPostState = ST_CDATA_TEXT;
+			fEmbeddedHint = XML_CDATA_TEXT;
+		}
+		yybegin(ST_JSP_DIRECTIVE_NAME);
+		assembleEmbeddedContainer(JSP_DIRECTIVE_OPEN, new String[]{JSP_DIRECTIVE_CLOSE, JSP_CLOSE});
+		if(yystate() == ST_BLOCK_TAG_INTERNAL_SCAN) {
+			yybegin(ST_BLOCK_TAG_SCAN);
+			return BLOCK_TEXT;
+		}
+		// required help for successive embedded regions
+		if(yystate() == ST_XML_TAG_NAME) {
+			fEmbeddedHint = XML_TAG_NAME;
+			fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+		}
+		else if((yystate() == ST_XML_ATTRIBUTE_NAME || yystate() == ST_XML_EQUALS)) {
+			fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;
+			fEmbeddedPostState = ST_XML_EQUALS;
+		}
+		else if(yystate() == ST_XML_ATTRIBUTE_VALUE) {
+			fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;
+			fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+		}
+		return PROXY_CONTEXT;
+	}
+ }
+        case 747: break;
+        case 388: 
+          { 
+	yybegin(ST_JSP_VBL_DQUOTES_END);
+	return JSP_VBL_QUOTED_CONTENT;
+ }
+        case 748: break;
+        case 384: 
+          { 
+	yybegin(ST_JSP_VBL_SQUOTES_END);
+	return JSP_VBL_QUOTED_CONTENT;
+ }
+        case 749: break;
+        case 382: 
+          { 
+	fELlevel++;
+	if(fELlevel == 1) {
+		return JSP_VBL_OPEN;
+	}
+ }
+        case 750: break;
+        case 372: 
+          { 
+	yybegin(ST_JSP_EL_DQUOTES_END);
+	return JSP_EL_QUOTED_CONTENT;
+ }
+        case 751: break;
+        case 368: 
+          { 
+	yybegin(ST_JSP_EL_SQUOTES_END);
+	return JSP_EL_QUOTED_CONTENT;
+ }
+        case 752: break;
+        case 366: 
+          { 
+	//System.out.println(JSP_EL_CONTENT+ ":[" + yytext() + "]");
+	return JSP_EL_CONTENT;
+ }
+        case 753: break;
+        case 365: 
+          { 
+	fELlevel++;
+	if(fELlevel == 1) {
+		return JSP_EL_OPEN;
+	}
+ }
+        case 754: break;
+        case 362: 
+          { 
+	int enterState = yystate();
+	yybegin(ST_JSP_DQUOTED_VBL);
+	assembleEmbeddedContainer(JSP_VBL_OPEN, new String[]{JSP_VBL_CLOSE, XML_TAG_ATTRIBUTE_VALUE_DQUOTE, JSP_TAG_ATTRIBUTE_VALUE_DQUOTE});
+	// abort early when an unescaped double quote is found in the VBL
+	if(fEmbeddedContainer.getLastRegion().getType().equals(XML_TAG_ATTRIBUTE_VALUE_DQUOTE) || fEmbeddedContainer.getLastRegion().getType().equals(JSP_TAG_ATTRIBUTE_VALUE_DQUOTE)) {
+		yybegin(ST_ABORT_EMBEDDED);
+		fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+	}
+	else {
+		yybegin(enterState);
+	}
+	return PROXY_CONTEXT;
+ }
+        case 755: break;
+        case 361: 
+          { 
+	int enterState = yystate();
+	yybegin(ST_JSP_DQUOTED_EL);
+	assembleEmbeddedContainer(JSP_EL_OPEN, new String[]{JSP_EL_CLOSE, XML_TAG_ATTRIBUTE_VALUE_DQUOTE, JSP_TAG_ATTRIBUTE_VALUE_DQUOTE});
+	// abort early when an unescaped double quote is found in the EL
+	if(fEmbeddedContainer.getLastRegion().getType().equals(XML_TAG_ATTRIBUTE_VALUE_DQUOTE) || fEmbeddedContainer.getLastRegion().getType().equals(JSP_TAG_ATTRIBUTE_VALUE_DQUOTE)) {
+		yybegin(ST_ABORT_EMBEDDED);
+		fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+	}
+	else {
+		yybegin(enterState);
+	}
+	return PROXY_CONTEXT;
+ }
+        case 756: break;
+        case 360: 
+          { 
+	int enterState = yystate();
+	yybegin(ST_JSP_SQUOTED_VBL);
+	assembleEmbeddedContainer(JSP_VBL_OPEN, new String[]{JSP_VBL_CLOSE, XML_TAG_ATTRIBUTE_VALUE_SQUOTE, JSP_TAG_ATTRIBUTE_VALUE_SQUOTE});
+	// abort early when an unescaped single quote is found in the VBL
+	if(fEmbeddedContainer.getLastRegion().getType().equals(XML_TAG_ATTRIBUTE_VALUE_SQUOTE) || fEmbeddedContainer.getLastRegion().getType().equals(JSP_TAG_ATTRIBUTE_VALUE_SQUOTE)) {
+		yybegin(ST_ABORT_EMBEDDED);
+		fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+	}
+	else {
+		yybegin(enterState);
+	}
+	return PROXY_CONTEXT;
+ }
+        case 757: break;
+        case 359: 
+          { 
+	int enterState = yystate();
+	yybegin(ST_JSP_SQUOTED_EL);
+	assembleEmbeddedContainer(JSP_EL_OPEN, new String[]{JSP_EL_CLOSE, XML_TAG_ATTRIBUTE_VALUE_SQUOTE, JSP_TAG_ATTRIBUTE_VALUE_SQUOTE});
+	// abort early when an unescaped single quote is found in the EL
+	if(fEmbeddedContainer.getLastRegion().getType().equals(XML_TAG_ATTRIBUTE_VALUE_SQUOTE) || fEmbeddedContainer.getLastRegion().getType().equals(JSP_TAG_ATTRIBUTE_VALUE_SQUOTE)) {
+		yybegin(ST_ABORT_EMBEDDED);
+		fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+	}
+	else {
+		yybegin(enterState);
+	}
+	return PROXY_CONTEXT;
+ }
+        case 758: break;
+        case 357: 
+          { 
+	if (Debug.debugTokenizer) {
+		System.out.println("begin embedded region: " + fEmbeddedHint+", genericEndTagOpen");//$NON-NLS-1$
+	}
+	int incomingState = yystate();
+	fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;
+	fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+	if(Debug.debugTokenizer)
+		dump("JSP attribute value start - end tag");//$NON-NLS-1$
+	yybegin(ST_XML_TAG_NAME);
+	assembleEmbeddedContainer(XML_END_TAG_OPEN, new String[]{XML_TAG_CLOSE,XML_EMPTY_TAG_CLOSE});
+	if(yystate() != ST_ABORT_EMBEDDED)
+        yybegin(incomingState);
+	return PROXY_CONTEXT;
+ }
+        case 759: break;
+        case 301: 
+        case 315: 
+        case 321: 
+          { 
+	return XML_DOCTYPE_INTERNAL_SUBSET;
+ }
+        case 760: break;
+        case 287: 
+          { 
+	String tagName = yytext().substring(1);
+	// pushback to just after the opening bracket
+	yypushback(yylength() - 1);
+	/*
+	 * If this tag can not be nested or we're already searching for an
+	 * attribute name, equals, or value, return immediately.
+	 */
+	if (!isNestable(tagName) || (!fStateStack.empty() && (fStateStack.peek() == ST_XML_ATTRIBUTE_NAME || fStateStack.peek() == ST_XML_EQUALS || fStateStack.peek() == ST_XML_ATTRIBUTE_VALUE || fStateStack.peek() == ST_JSP_ATTRIBUTE_VALUE))) {
+		yybegin(ST_XML_TAG_NAME);
+		return XML_TAG_OPEN;
+	}
+	if(Debug.debugTokenizer)
+		dump("tag in place of attr value");//$NON-NLS-1$
+	fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;
+	fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+	fStateStack.push(yystate());
+	// embedded container should be looking for the name (again) next
+	yybegin(ST_XML_TAG_NAME);
+	assembleEmbeddedTagSequence(XML_TAG_OPEN, tagName); // ?
+	fStateStack.pop();
+	yybegin(ST_XML_ATTRIBUTE_NAME);
+	return PROXY_CONTEXT;
+ }
+        case 761: break;
+        case 285: 
+          { 
+	String tagName = yytext().substring(1);
+	// pushback to just after the opening bracket
+	yypushback(yylength() - 1);
+	/*
+	 * If this tag can not be nested or we're already searching for an
+	 * attribute name, equals, or value, return immediately.
+	 */
+	if (!isNestable(tagName) || (!fStateStack.empty() && (fStateStack.peek() == ST_XML_ATTRIBUTE_NAME || fStateStack.peek() == ST_XML_EQUALS || fStateStack.peek() == ST_XML_ATTRIBUTE_VALUE || fStateStack.peek() == ST_JSP_ATTRIBUTE_VALUE))) {
+		yybegin(ST_XML_TAG_NAME);
+		return XML_TAG_OPEN;
+	}
+	if(Debug.debugTokenizer)
+		dump("tag in place of attr name");//$NON-NLS-1$
+	fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;
+	fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+	fStateStack.push(yystate());
+	// embedded container should be looking for the name (again) next
+	yybegin(ST_XML_TAG_NAME);
+	assembleEmbeddedTagSequence(XML_TAG_OPEN, tagName); // ?
+	fStateStack.pop();
+	yybegin(ST_XML_EQUALS);
+	return PROXY_CONTEXT;
+ }
+        case 762: break;
+        case 283: 
+          { 
+        yybegin(YYINITIAL);
+	fEmbeddedHint = UNDEFINED;
+	if(Debug.debugTokenizer)
+		dump("empty tag close");//$NON-NLS-1$
+
+	if (fEmbeddedContainer != null)
+		fInTagEmbedded = false;
+	else
+		fInTagContainer = false;
+
+	return XML_EMPTY_TAG_CLOSE;
+ }
+        case 763: break;
+        case 274: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("JSP end");//$NON-NLS-1$
+	if (Debug.debugTokenizer) {
+		if(fStateStack.peek()!=YYINITIAL)
+			System.out.println("end embedded region");//$NON-NLS-1$
+	}
+	yybegin(fStateStack.pop());
+	return JSP_DIRECTIVE_CLOSE;
+ }
+        case 764: break;
+        case 272: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("JSP end");//$NON-NLS-1$
+	if (Debug.debugTokenizer) {
+		if(fStateStack.peek()!=YYINITIAL)
+			System.out.println("end embedded region");//$NON-NLS-1$
+	}
+	yybegin(fStateStack.pop());
+	return JSP_CLOSE;
+ }
+        case 765: break;
+        case 127: 
+        case 172: 
+          { 
+	String type = yy_lexical_state == ST_XML_ATTRIBUTE_VALUE ? XML_TAG_ATTRIBUTE_VALUE_DQUOTE : JSP_TAG_ATTRIBUTE_VALUE_DQUOTE;
+
+	if (Debug.debugTokenizer) {
+		System.out.println("begin embedded region: " + fEmbeddedHint+", "+type);//$NON-NLS-1$
+	}
+	fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;
+	fEmbeddedPostState = ST_XML_ATTRIBUTE_VALUE_DQUOTED;
+	yybegin(ST_XML_ATTRIBUTE_VALUE_DQUOTED);
+	fStateStack.push(yystate());
+	if(Debug.debugTokenizer)
+		dump("JSP attribute value start - complex double quoted");//$NON-NLS-1$
+	assembleEmbeddedContainer(type, type);
+	fStateStack.pop();
+	fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;
+	fEmbeddedPostState = ST_XML_EQUALS;
+	yybegin(ST_XML_ATTRIBUTE_NAME);
+	if (fEmbeddedContainer.getLastRegion().getType() == UNDEFINED) {
+		fProxyUnknownRegion = fRegionFactory.createToken(XML_TAG_ATTRIBUTE_VALUE, fEmbeddedContainer.getStart(), fEmbeddedContainer.getTextLength(), fEmbeddedContainer.getLength());
+		return PROXY_UNKNOWN_CONTEXT;
+	}
+	return PROXY_CONTEXT;
+ }
+        case 766: break;
+        case 125: 
+          { 
+	if (Debug.debugTokenizer) {
+		System.out.println("begin embedded region: " + fEmbeddedHint+", unquoted genericTagOpen");//$NON-NLS-1$
+	}
+	fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;
+	fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+	fStateStack.push(yystate());
+	if(Debug.debugTokenizer)
+		dump("JSP tag embedded name start - start tag");//$NON-NLS-1$
+	yybegin(ST_XML_TAG_NAME);
+	assembleEmbeddedContainer(XML_TAG_OPEN, new String[]{XML_TAG_CLOSE,XML_EMPTY_TAG_CLOSE});
+	fStateStack.pop();
+        yybegin(ST_XML_ATTRIBUTE_NAME);
+	fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;
+	fEmbeddedPostState = ST_XML_EQUALS;
+	return PROXY_CONTEXT;
+ }
+        case 767: break;
+        case 123: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("equals");//$NON-NLS-1$
+	fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;
+	fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+        yybegin(isJspTag() ? ST_JSP_ATTRIBUTE_VALUE : ST_XML_ATTRIBUTE_VALUE);
+        return XML_TAG_ATTRIBUTE_EQUALS;
+ }
+        case 768: break;
+        case 122: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("attr name");//$NON-NLS-1$
+	fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;
+	fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+        yybegin(ST_XML_EQUALS);
+        return XML_TAG_ATTRIBUTE_NAME;
+ }
+        case 769: break;
+        case 118: 
+        case 119: 
+        case 120: 
+        case 284: 
+        case 430: 
+        case 542: 
+        case 583: 
+        case 584: 
+        case 603: 
+        case 604: 
+        case 622: 
+        case 623: 
+        case 636: 
+        case 645: 
+        case 653: 
+        case 655: 
+        case 657: 
+        case 659: 
+        case 662: 
+        case 668: 
+        case 669: 
+        case 670: 
+        case 671: 
+        case 672: 
+        case 678: 
+        case 679: 
+        case 680: 
+        case 681: 
+        case 682: 
+        case 688: 
+        case 689: 
+        case 691: 
+        case 692: 
+        case 698: 
+        case 699: 
+        case 700: 
+        case 701: 
+        case 707: 
+        case 708: 
+        case 709: 
+        case 710: 
+        case 713: 
+        case 714: 
+        case 716: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("tag name");//$NON-NLS-1$
+    String tagname = yytext();
+    boolean jspTag = tagname.indexOf(':') != -1;
+	if (fEmbeddedContainer != null) {
+    	fEmbeddedTag = jspTag;
+		fInTagEmbedded = true;
+    }
+	else {
+		fContainerTag = jspTag;
+		fInTagContainer = true;
+	}
+	fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;
+	fEmbeddedPostState = ST_XML_EQUALS;
+        yybegin(ST_XML_ATTRIBUTE_NAME);
+        return XML_TAG_NAME;
+ }
+        case 770: break;
+        case 116: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("tag close");//$NON-NLS-1$
+	fEmbeddedHint = UNDEFINED;
+	if(isBlockMarker()) {
+		fEmbeddedHint = getBlockMarkerContext();
+		fEmbeddedPostState = ST_BLOCK_TAG_SCAN;
+        	yybegin(ST_BLOCK_TAG_SCAN);
+	}
+	else
+        	yybegin(YYINITIAL);
+
+	if (fEmbeddedContainer != null)
+		fInTagEmbedded = false;
+	else
+		fInTagContainer = false;
+
+	return XML_TAG_CLOSE;
+ }
+        case 771: break;
+        case 109: 
+        case 113: 
+        case 277: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("attr value");//$NON-NLS-1$
+        yybegin(ST_JSP_DIRECTIVE_ATTRIBUTE_NAME);
+        return XML_TAG_ATTRIBUTE_VALUE;
+ }
+        case 772: break;
+        case 108: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("equals");//$NON-NLS-1$
+        yybegin(ST_JSP_DIRECTIVE_ATTRIBUTE_VALUE);
+        return XML_TAG_ATTRIBUTE_EQUALS;
+ }
+        case 773: break;
+        case 107: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("attr name");//$NON-NLS-1$
+        yybegin(ST_JSP_DIRECTIVE_EQUALS);
+        return XML_TAG_ATTRIBUTE_NAME;
+ }
+        case 774: break;
+        case 104: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("JSP directive name");//$NON-NLS-1$
+	yybegin(ST_JSP_DIRECTIVE_NAME_WHITESPACE);
+	return JSP_DIRECTIVE_NAME;
+ }
+        case 775: break;
+        case 100: 
+        case 101: 
+        case 102: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("JSP code content");//$NON-NLS-1$
+	return doScan("%>", false, false, false, JSP_CONTENT, ST_JSP_CONTENT, ST_JSP_CONTENT);
+ }
+        case 776: break;
+        case 96: 
+        case 98: 
+        case 99: 
+        case 265: 
+        case 266: 
+        case 267: 
+        case 270: 
+        case 271: 
+        case 424: 
+        case 427: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("DHTML processing instruction attribute value");//$NON-NLS-1$
+	fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;
+	fEmbeddedPostState = ST_XML_EQUALS;
+        yybegin(ST_DHTML_ATTRIBUTE_NAME);
+        return XML_TAG_ATTRIBUTE_VALUE;
+ }
+        case 777: break;
+        case 95: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("DHTML processing instruction '='");//$NON-NLS-1$
+	fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;
+	fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+        yybegin(ST_DHTML_ATTRIBUTE_VALUE);
+        return XML_TAG_ATTRIBUTE_EQUALS;
+ }
+        case 778: break;
+        case 94: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("DHTML processing instruction attribute name");//$NON-NLS-1$
+        yybegin(ST_DHTML_EQUALS);
+        return XML_TAG_ATTRIBUTE_NAME;
+ }
+        case 779: break;
+        case 92: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("DHTML processing instruction end");//$NON-NLS-1$
+	fEmbeddedHint = UNDEFINED;
+        yybegin(YYINITIAL);
+        return XML_PI_CLOSE;
+ }
+        case 780: break;
+        case 86: 
+        case 88: 
+        case 254: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("XML processing instruction attribute value");//$NON-NLS-1$
+	fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;
+	fEmbeddedPostState = ST_XML_EQUALS;
+        yybegin(ST_XML_PI_ATTRIBUTE_NAME);
+        return XML_TAG_ATTRIBUTE_VALUE;
+ }
+        case 781: break;
+        case 85: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("XML processing instruction '='");//$NON-NLS-1$
+	fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;
+	fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+        yybegin(ST_XML_PI_ATTRIBUTE_VALUE);
+        return XML_TAG_ATTRIBUTE_EQUALS;
+ }
+        case 782: break;
+        case 50: 
+        case 209: 
+        case 210: 
+        case 213: 
+        case 223: 
+        case 224: 
+        case 227: 
+        case 228: 
+        case 393: 
+        case 396: 
+        case 506: 
+        case 520: 
+        case 526: 
+          { 
+	return JSP_VBL_CONTENT;
+ }
+        case 783: break;
+        case 43: 
+        case 187: 
+        case 188: 
+        case 191: 
+        case 201: 
+        case 202: 
+        case 206: 
+        case 207: 
+        case 363: 
+        case 377: 
+        case 380: 
+        case 478: 
+        case 479: 
+        case 494: 
+        case 500: 
+          { 
+	return JSP_EL_CONTENT;
+ }
+        case 784: break;
+        case 35: 
+        case 161: 
+        case 162: 
+        case 345: 
+        case 464: 
+        case 468: 
+        case 557: 
+        case 591: 
+        case 611: 
+        case 628: 
+        case 638: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("attlist contentspec");//$NON-NLS-1$
+	return XML_ATTLIST_DECL_CONTENT;
+ }
+        case 785: break;
+        case 33: 
+        case 154: 
+        case 155: 
+        case 333: 
+        case 454: 
+        case 458: 
+        case 554: 
+        case 590: 
+        case 610: 
+        case 627: 
+        case 637: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("elementdecl contentspec");//$NON-NLS-1$
+	return XML_ELEMENT_DECL_CONTENT;
+ }
+        case 786: break;
+        case 22: 
+        case 114: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("inappropriate tag name");//$NON-NLS-1$
+	if(!fStateStack.empty() && (fStateStack.peek()==ST_XML_ATTRIBUTE_VALUE_SQUOTED||fStateStack.peek()==ST_XML_ATTRIBUTE_VALUE_DQUOTED)) {
+		yybegin(ST_ABORT_EMBEDDED);
+		char c = yy_buffer[yy_markedPos - 1];
+		if (fStateStack.peek()==ST_XML_ATTRIBUTE_VALUE_DQUOTED && c == '\"') {
+			return isJspTag() ? JSP_TAG_ATTRIBUTE_VALUE_DQUOTE : XML_TAG_ATTRIBUTE_VALUE_DQUOTE;
+		}		
+		if (fStateStack.peek()==ST_XML_ATTRIBUTE_VALUE_SQUOTED && c == '\'') {
+			return isJspTag() ? JSP_TAG_ATTRIBUTE_VALUE_SQUOTE : XML_TAG_ATTRIBUTE_VALUE_SQUOTE;
+		}
+		yypushback(yylength()-1);
+		return XML_TAG_ATTRIBUTE_VALUE;
+	}
+	yybegin(YYINITIAL);
+        return XML_CONTENT;
+ }
+        case 787: break;
+        case 18: 
+        case 106: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("white space");//$NON-NLS-1$
+	yybegin(ST_JSP_DIRECTIVE_ATTRIBUTE_NAME);
+	return WHITE_SPACE;
+ }
+        case 788: break;
+        case 5: 
+        case 8: 
+        case 9: 
+        case 10: 
+        case 12: 
+        case 13: 
+        case 14: 
+        case 15: 
+        case 17: 
+        case 19: 
+        case 20: 
+        case 21: 
+        case 23: 
+        case 24: 
+        case 25: 
+        case 26: 
+        case 27: 
+        case 28: 
+        case 29: 
+        case 30: 
+        case 31: 
+        case 32: 
+        case 34: 
+        case 40: 
+        case 41: 
+        case 42: 
+        case 74: 
+        case 178: 
+        case 183: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("white space");//$NON-NLS-1$
+        return WHITE_SPACE;
+ }
+        case 789: break;
+        case 0: 
+        case 57: 
+        case 60: 
+        case 61: 
+        case 63: 
+        case 235: 
+        case 237: 
+        case 240: 
+        case 242: 
+        case 403: 
+        case 404: 
+        case 405: 
+        case 409: 
+        case 411: 
+        case 414: 
+        case 535: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("\nXML content");//$NON-NLS-1$
+	return XML_CONTENT;
+ }
+        case 790: break;
+        case 58: 
+        case 103: 
+        case 115: 
+        case 121: 
+        case 131: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("\nstart tag open");//$NON-NLS-1$
+	if (!fStateStack.empty() && fStateStack.peek()== ST_XML_COMMENT){
+		fStateStack.pop();
+		fEmbeddedHint = XML_COMMENT_TEXT;
+		yybegin(ST_XML_TAG_NAME);
+		String tagName = "";
+		assembleEmbeddedTagSequence(XML_TAG_OPEN, tagName); // ?
+		return PROXY_CONTEXT;
+	}
+	fEmbeddedHint = XML_TAG_NAME;
+	fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+        yybegin(ST_XML_TAG_NAME);
+        return XML_TAG_OPEN;
+ }
+        case 791: break;
+        case 59: 
+        case 62: 
+        case 66: 
+        case 67: 
+        case 68: 
+        case 72: 
+        case 73: 
+        case 83: 
+        case 87: 
+        case 89: 
+        case 90: 
+        case 91: 
+        case 93: 
+        case 97: 
+        case 105: 
+        case 110: 
+        case 111: 
+        case 112: 
+        case 117: 
+        case 126: 
+        case 133: 
+        case 134: 
+        case 135: 
+        case 136: 
+        case 138: 
+        case 139: 
+        case 141: 
+        case 142: 
+        case 143: 
+        case 146: 
+        case 147: 
+        case 148: 
+        case 151: 
+        case 152: 
+        case 153: 
+        case 158: 
+        case 159: 
+        case 160: 
+        case 168: 
+        case 170: 
+        case 171: 
+        case 193: 
+        case 194: 
+        case 197: 
+        case 198: 
+        case 204: 
+        case 208: 
+        case 215: 
+        case 216: 
+        case 219: 
+        case 220: 
+        case 225: 
+        case 229: 
+          { 
+	if (Debug.debugTokenizer)
+		System.out.println("!!!unexpected!!!: \"" + yytext() + "\":" + //$NON-NLS-2$//$NON-NLS-1$
+			yychar + "-" + (yychar + yylength()));//$NON-NLS-1$
+	return UNDEFINED;
+ }
+        case 792: break;
+        case 64: 
+        case 65: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("CDATA text");//$NON-NLS-1$
+	fEmbeddedPostState = ST_CDATA_TEXT;
+	fEmbeddedHint = XML_CDATA_TEXT;
+	String returnedContext = doScan("]]>", false, true, true, XML_CDATA_TEXT, ST_CDATA_END,  ST_CDATA_END);//$NON-NLS-1$
+	if(returnedContext == XML_CDATA_TEXT)
+		yybegin(ST_CDATA_END);
+	return returnedContext;
+ }
+        case 793: break;
+        case 69: 
+        case 196: 
+        case 200: 
+        case 218: 
+        case 222: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("LINE FEED");//$NON-NLS-1$
+	return WHITE_SPACE;
+ }
+        case 794: break;
+        case 70: 
+        case 71: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("comment content");//$NON-NLS-1$
+	return scanXMLCommentText();
+ }
+        case 795: break;
+        case 75: 
+        case 76: 
+        case 77: 
+        case 78: 
+        case 247: 
+        case 248: 
+        case 249: 
+        case 419: 
+        case 538: 
+        case 539: 
+        case 581: 
+        case 582: 
+        case 601: 
+        case 621: 
+        case 634: 
+        case 644: 
+        case 652: 
+        case 654: 
+        case 656: 
+        case 658: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("processing instruction target");//$NON-NLS-1$
+	fEmbeddedHint = XML_CONTENT;
+        yybegin(ST_PI_WS);
+        return XML_TAG_NAME;
+ }
+        case 796: break;
+        case 79: 
+          { 
+        yybegin(ST_PI_CONTENT);
+        return WHITE_SPACE;
+ }
+        case 797: break;
+        case 80: 
+        case 81: 
+        case 82: 
+          { 
+		// block scan until close is found
+	return doScan("?>", false, false, false, XML_PI_CONTENT, ST_XML_PI_TAG_CLOSE, ST_XML_PI_TAG_CLOSE);
+ }
+        case 798: break;
+        case 84: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("XML processing instruction attribute name");//$NON-NLS-1$
+        yybegin(ST_XML_PI_EQUALS);
+        return XML_TAG_ATTRIBUTE_NAME;
+ }
+        case 799: break;
+        case 128: 
+        case 173: 
+          { 
+	String type = yy_lexical_state == ST_XML_ATTRIBUTE_VALUE ? XML_TAG_ATTRIBUTE_VALUE_SQUOTE : JSP_TAG_ATTRIBUTE_VALUE_SQUOTE;
+	if (Debug.debugTokenizer) {
+		System.out.println("begin embedded region: " + fEmbeddedHint+", "+type);//$NON-NLS-1$
+	}
+	fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;
+	fEmbeddedPostState = ST_XML_ATTRIBUTE_VALUE_SQUOTED;
+	yybegin(ST_XML_ATTRIBUTE_VALUE_SQUOTED);
+	fStateStack.push(yystate());
+	if(Debug.debugTokenizer)
+		dump("JSP attribute value start - complex single quoted");//$NON-NLS-1$
+	assembleEmbeddedContainer(type, type);
+	fStateStack.pop();
+	fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;
+	fEmbeddedPostState = ST_XML_EQUALS;
+        yybegin(ST_XML_ATTRIBUTE_NAME);
+    if (fEmbeddedContainer.getLastRegion().getType() == UNDEFINED) {
+		fProxyUnknownRegion = fRegionFactory.createToken(XML_TAG_ATTRIBUTE_VALUE, fEmbeddedContainer.getStart(), fEmbeddedContainer.getTextLength(), fEmbeddedContainer.getLength());
+		return PROXY_UNKNOWN_CONTEXT;
+	}
+	return PROXY_CONTEXT;
+ }
+        case 800: break;
+        case 132: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("declaration end");//$NON-NLS-1$
+	if (Debug.debugTokenizer) {
+		if(fStateStack.peek()!=YYINITIAL)
+			System.out.println("end embedded region");//$NON-NLS-1$
+	}
+	yybegin(fStateStack.pop());
+	return XML_DECLARATION_CLOSE;
+ }
+        case 801: break;
+        case 137: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("doctype type");//$NON-NLS-1$
+	yybegin(ST_XML_DOCTYPE_EXTERNAL_ID);
+	return XML_DOCTYPE_NAME;
+ }
+        case 802: break;
+        case 140: 
+        case 144: 
+        case 306: 
+        case 311: 
+        case 446: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("doctype public reference");//$NON-NLS-1$
+	fEmbeddedHint = UNDEFINED;
+	fEmbeddedPostState = YYINITIAL;
+	yybegin(ST_XML_DOCTYPE_ID_SYSTEM);
+	return XML_DOCTYPE_EXTERNAL_ID_PUBREF;
+ }
+        case 803: break;
+        case 145: 
+        case 149: 
+        case 318: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("doctype system reference");//$NON-NLS-1$
+	fEmbeddedHint = UNDEFINED;
+	fEmbeddedPostState = YYINITIAL;
+	yybegin(ST_XML_DECLARATION_CLOSE);
+	return XML_DOCTYPE_EXTERNAL_ID_SYSREF;
+ }
+        case 804: break;
+        case 150: 
+        case 324: 
+        case 329: 
+        case 451: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("elementdecl name");//$NON-NLS-1$
+	fEmbeddedHint = UNDEFINED;
+	fEmbeddedPostState = YYINITIAL;
+	yybegin(ST_XML_ELEMENT_DECLARATION_CONTENT);
+	return XML_ELEMENT_DECL_NAME;
+ }
+        case 805: break;
+        case 156: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("elementdecl close");//$NON-NLS-1$
+	if (Debug.debugTokenizer) {
+		if(fStateStack.peek()!=YYINITIAL)
+			System.out.println("end embedded region");//$NON-NLS-1$
+	}
+	yybegin(fStateStack.pop());
+	return XML_DECLARATION_CLOSE;
+ }
+        case 806: break;
+        case 157: 
+        case 336: 
+        case 341: 
+        case 461: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("attlist name");//$NON-NLS-1$
+	fEmbeddedHint = UNDEFINED;
+	fEmbeddedPostState = YYINITIAL;
+	yybegin(ST_XML_ATTLIST_DECLARATION_CONTENT);
+	return XML_ATTLIST_DECL_NAME;
+ }
+        case 807: break;
+        case 163: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("attlist close");//$NON-NLS-1$
+	if (Debug.debugTokenizer) {
+		if(fStateStack.peek()!=YYINITIAL)
+			System.out.println("end embedded region");//$NON-NLS-1$
+	}
+	yybegin(fStateStack.pop());
+	return XML_DECLARATION_CLOSE;
+ }
+        case 808: break;
+        case 166: 
+        case 167: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("\nJSP comment text");//$NON-NLS-1$
+	return scanJSPCommentText();
+ }
+        case 809: break;
+        case 176: 
+        case 180: 
+        case 181: 
+        case 182: 
+        case 185: 
+        case 186: 
+        case 358: 
+          { 
+	return XML_TAG_ATTRIBUTE_VALUE;
+ }
+        case 810: break;
+        case 177: 
+          { 
+	if (Debug.debugTokenizer) {
+		System.out.println("begin embedded region: " + fEmbeddedHint+", genericTagOpen");//$NON-NLS-1$
+	}
+	int incomingState = yystate();
+	fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;
+	fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+	if(Debug.debugTokenizer)
+		dump("tag inside of JSP attribute value start");//$NON-NLS-1$
+	yybegin(ST_XML_TAG_NAME);
+	assembleEmbeddedContainer(XML_TAG_OPEN, new String[]{XML_TAG_CLOSE,XML_EMPTY_TAG_CLOSE});
+	if(yystate() != ST_ABORT_EMBEDDED)
+        yybegin(incomingState);
+	return PROXY_CONTEXT;
+ }
+        case 811: break;
+        case 179: 
+          { 
+	return isJspTag() ? JSP_TAG_ATTRIBUTE_VALUE_SQUOTE : XML_TAG_ATTRIBUTE_VALUE_SQUOTE;
+ }
+        case 812: break;
+        case 184: 
+          { 
+	return isJspTag()? JSP_TAG_ATTRIBUTE_VALUE_DQUOTE : XML_TAG_ATTRIBUTE_VALUE_DQUOTE;
+ }
+        case 813: break;
+        case 189: 
+          { 
+	yybegin(ST_JSP_EL_DQUOTES);
+	return JSP_EL_DQUOTE;
+ }
+        case 814: break;
+        case 190: 
+          { 
+	yybegin(ST_JSP_EL_SQUOTES);
+	return JSP_EL_SQUOTE;
+ }
+        case 815: break;
+        case 192: 
+          { 
+	fELlevel--;
+	if(fELlevel == 0) {
+		yybegin(YYINITIAL);
+		return JSP_EL_CLOSE;
+	}
+	return JSP_EL_CONTENT;
+ }
+        case 816: break;
+        case 195: 
+          { 
+	yybegin(ST_JSP_EL);
+	return JSP_EL_SQUOTE;
+ }
+        case 817: break;
+        case 199: 
+          { 
+	yybegin(ST_JSP_EL);
+	return JSP_EL_DQUOTE;
+ }
+        case 818: break;
+        case 203: 
+          { 
+	return isJspTag() ? JSP_TAG_ATTRIBUTE_VALUE_DQUOTE: XML_TAG_ATTRIBUTE_VALUE_DQUOTE;
+ }
+        case 819: break;
+        case 205: 
+          { 
+	return JSP_EL_CLOSE;
+ }
+        case 820: break;
+        case 211: 
+          { 
+	yybegin(ST_JSP_VBL_DQUOTES);
+	return JSP_VBL_DQUOTE;
+ }
+        case 821: break;
+        case 212: 
+          { 
+	yybegin(ST_JSP_VBL_SQUOTES);
+	return JSP_VBL_SQUOTE;
+ }
+        case 822: break;
+        case 214: 
+          { 
+	fELlevel--;
+	if(fELlevel == 0) {
+		yybegin(YYINITIAL);
+		return JSP_VBL_CLOSE;
+	}
+	return JSP_VBL_CONTENT;
+ }
+        case 823: break;
+        case 217: 
+          { 
+	yybegin(ST_JSP_VBL);
+	return JSP_VBL_SQUOTE;
+ }
+        case 824: break;
+        case 221: 
+          { 
+	yybegin(ST_JSP_VBL);
+	return JSP_VBL_DQUOTE;
+ }
+        case 825: break;
+        case 226: 
+          { 
+	return JSP_VBL_CLOSE;
+ }
+        case 826: break;
+        case 230: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("\nend tag open");//$NON-NLS-1$
+	fEmbeddedHint = XML_TAG_NAME;
+	fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+        yybegin(ST_XML_TAG_NAME);
+        return XML_END_TAG_OPEN;
+ }
+        case 827: break;
+        case 231: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("\nprocessing instruction start");//$NON-NLS-1$
+	yybegin(ST_PI);
+        return XML_PI_OPEN;
+ }
+        case 828: break;
+        case 232: 
+        case 332: 
+        case 344: 
+        case 364: 
+        case 369: 
+        case 373: 
+        case 376: 
+        case 379: 
+        case 381: 
+        case 385: 
+        case 389: 
+        case 392: 
+        case 395: 
+          { 
+	/* JSP scriptlet begun (anywhere)
+	 * A consequence of the start anywhere possibility is that the
+	 *  incoming state must be checked to see if it's erroneous
+	 *  due to the order of precedence generated
+	 */
+	// begin sanity checks
+	if(yystate() == ST_JSP_CONTENT) {
+		// at the beginning?!
+		yypushback(1);
+		return JSP_CONTENT;
+	}
+	else if(yystate() == ST_BLOCK_TAG_SCAN) {
+		yypushback(2);
+		return doBlockTagScan();
+	}
+	else if(yystate() == ST_XML_COMMENT) {
+		yypushback(2);
+		return scanXMLCommentText();
+	}
+	else if(yystate() == ST_JSP_COMMENT) {
+		yypushback(2);
+		return scanJSPCommentText();
+	}
+	// finished sanity checks
+	fStateStack.push(yystate());
+	if(fStateStack.peek()==YYINITIAL) {
+		// the simple case, just a regular scriptlet out in content
+		if(Debug.debugTokenizer)
+			dump("\nJSP scriptlet start");//$NON-NLS-1$
+		yybegin(ST_JSP_CONTENT);
+		return JSP_SCRIPTLET_OPEN;
+	}
+	else {
+		if (Debug.debugTokenizer) {
+			System.out.println("begin embedded region: " + fEmbeddedHint+", jspScriptletStart");//$NON-NLS-1$
+		}
+		if(Debug.debugTokenizer)
+			dump("JSP scriptlet start");//$NON-NLS-1$
+		if(yystate() == ST_XML_ATTRIBUTE_VALUE_DQUOTED)
+			fEmbeddedPostState = ST_XML_ATTRIBUTE_VALUE_DQUOTED;
+		else if(yystate() == ST_XML_ATTRIBUTE_VALUE_SQUOTED)
+			fEmbeddedPostState = ST_XML_ATTRIBUTE_VALUE_SQUOTED;
+		else if(yystate() == ST_CDATA_TEXT) {
+			fEmbeddedPostState = ST_CDATA_TEXT;
+			fEmbeddedHint = XML_CDATA_TEXT;
+		}
+		yybegin(ST_JSP_CONTENT);
+		assembleEmbeddedContainer(JSP_SCRIPTLET_OPEN, JSP_CLOSE);
+		if(yystate() == ST_BLOCK_TAG_INTERNAL_SCAN) {
+			yybegin(ST_BLOCK_TAG_SCAN);
+			return BLOCK_TEXT;
+		}
+		// required help for successive embedded regions
+		if(yystate() == ST_XML_TAG_NAME) {
+			fEmbeddedHint = XML_TAG_NAME;
+			fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+		}
+		else if((yystate() == ST_XML_ATTRIBUTE_NAME || yystate() == ST_XML_EQUALS)) {
+			fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;
+			fEmbeddedPostState = ST_XML_EQUALS;
+		}
+		else if(yystate() == ST_XML_ATTRIBUTE_VALUE) {
+			fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;
+			fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+		}
+        else if(yystate() == ST_JSP_ATTRIBUTE_VALUE) {
+            fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;
+            fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+        }
+		
+		return PROXY_CONTEXT;
+	}
+ }
+        case 829: break;
+        case 233: 
+          { 
+	fStateStack.push(yystate());
+	if(Debug.debugTokenizer)
+		dump("\ndeclaration start");//$NON-NLS-1$
+        yybegin(ST_XML_DECLARATION);
+	return XML_DECLARATION_OPEN;
+ }
+        case 830: break;
+        case 246: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("processing instruction end");//$NON-NLS-1$
+	fEmbeddedHint = UNDEFINED;
+        yybegin(YYINITIAL);
+        return XML_PI_CLOSE;
+ }
+        case 831: break;
+        case 250: 
+          { 
+		// ended with nothing inside
+		fEmbeddedHint = UNDEFINED;
+        yybegin(YYINITIAL);
+        return XML_PI_CLOSE;
+ }
+        case 832: break;
+        case 251: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("XML processing instruction end");//$NON-NLS-1$
+	fEmbeddedHint = UNDEFINED;
+        yybegin(YYINITIAL);
+        return XML_PI_CLOSE;
+ }
+        case 833: break;
+        case 164: 
+        case 165: 
+          { 
+		return doBlockTagScan();
+	 }
+        case 834: break;
+        default: 
+          if (yy_input == YYEOF && yy_startRead == yy_currentPos) {
+            yy_atEOF = true;
+            yy_do_eof();
+              return null;
+          } 
+          else {
+            yy_ScanError(YY_NO_MATCH);
+          }
+      }
+    }
+  }    
+
+
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/preferences/JSPCorePreferenceInitializer.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/preferences/JSPCorePreferenceInitializer.java
new file mode 100644
index 0000000..508773b
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/preferences/JSPCorePreferenceInitializer.java
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.preferences;
+
+import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer;
+import org.eclipse.core.runtime.preferences.DefaultScope;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences;
+import org.eclipse.jst.jsp.core.internal.JSPCorePlugin;
+import org.eclipse.wst.sse.core.internal.encoding.CommonCharsetNames;
+import org.eclipse.wst.sse.core.internal.encoding.CommonEncodingPreferenceNames;
+import org.eclipse.wst.sse.core.internal.validate.ValidationMessage;
+
+/**
+ * Sets default values for JSP Core preferences
+ */
+public class JSPCorePreferenceInitializer extends AbstractPreferenceInitializer {
+
+	public void initializeDefaultPreferences() {
+		IEclipsePreferences node = new DefaultScope().getNode(JSPCorePlugin.getDefault().getBundle().getSymbolicName());
+
+		// compiler/validation preferences
+		node.putBoolean(JSPCorePreferenceNames.VALIDATE_FRAGMENTS, true);
+
+		// code generation preferences
+		node.put(CommonEncodingPreferenceNames.INPUT_CODESET, ""); //$NON-NLS-1$
+		String defaultEnc = "ISO-8859-1";//$NON-NLS-1$
+		String systemEnc = System.getProperty("file.encoding"); //$NON-NLS-1$
+		if (systemEnc != null) {
+			defaultEnc = CommonCharsetNames.getPreferredDefaultIanaName(systemEnc, "ISO-8859-1");//$NON-NLS-1$
+		}
+		node.put(CommonEncodingPreferenceNames.OUTPUT_CODESET, defaultEnc);
+		node.put(CommonEncodingPreferenceNames.END_OF_LINE_CODE, ""); //$NON-NLS-1$
+
+		// this could be made smarter by actually looking up the content
+		// type's valid extensions
+		node.put(JSPCorePreferenceNames.DEFAULT_EXTENSION, "jsp"); //$NON-NLS-1$
+
+		node.putInt(JSPCorePreferenceNames.VALIDATION_DIRECTIVE_TAGLIB_DUPLICATE_PREFIXES_DIFFERENT_URIS, ValidationMessage.ERROR);
+		node.putInt(JSPCorePreferenceNames.VALIDATION_DIRECTIVE_TAGLIB_DUPLICATE_PREFIXES_SAME_URIS, ValidationMessage.IGNORE);
+		node.putInt(JSPCorePreferenceNames.VALIDATION_DIRECTIVE_TAGLIB_MISSING_PREFIX, ValidationMessage.ERROR);
+		node.putInt(JSPCorePreferenceNames.VALIDATION_DIRECTIVE_TAGLIB_MISSING_URI_OR_TAGDIR, ValidationMessage.ERROR);
+		node.putInt(JSPCorePreferenceNames.VALIDATION_DIRECTIVE_TAGLIB_UNRESOLVABLE_URI_OR_TAGDIR, ValidationMessage.ERROR);
+		node.putInt(JSPCorePreferenceNames.VALIDATION_DIRECTIVE_PAGE_SUPERCLASS_NOT_FOUND, ValidationMessage.ERROR);
+		node.putInt(JSPCorePreferenceNames.VALIDATION_DIRECTIVE_INCLUDE_NO_FILE_SPECIFIED, ValidationMessage.ERROR);
+		node.putInt(JSPCorePreferenceNames.VALIDATION_DIRECTIVE_INCLUDE_FILE_NOT_FOUND, ValidationMessage.ERROR);
+
+		node.putInt(JSPCorePreferenceNames.VALIDATION_JAVA_LOCAL_VARIABLE_NEVER_USED, ValidationMessage.IGNORE);
+		node.putInt(JSPCorePreferenceNames.VALIDATION_JAVA_ARGUMENT_IS_NEVER_USED, ValidationMessage.IGNORE);
+		node.putInt(JSPCorePreferenceNames.VALIDATION_JAVA_NULL_LOCAL_VARIABLE_REFERENCE, ValidationMessage.IGNORE);
+		node.putInt(JSPCorePreferenceNames.VALIDATION_JAVA_POTENTIAL_NULL_LOCAL_VARIABLE_REFERENCE, ValidationMessage.IGNORE);
+		node.putInt(JSPCorePreferenceNames.VALIDATION_JAVA_UNUSED_IMPORT, ValidationMessage.IGNORE);
+
+		node.putInt(JSPCorePreferenceNames.VALIDATION_EL_SYNTAX, ValidationMessage.ERROR);
+		node.putInt(JSPCorePreferenceNames.VALIDATION_EL_LEXER, ValidationMessage.IGNORE);
+
+		node.putInt(JSPCorePreferenceNames.VALIDATION_ACTIONS_SEVERITY_MISSING_REQUIRED_ATTRIBUTE, ValidationMessage.ERROR);
+		node.putInt(JSPCorePreferenceNames.VALIDATION_ACTIONS_SEVERITY_UNKNOWN_ATTRIBUTE, ValidationMessage.WARNING);
+		node.putInt(JSPCorePreferenceNames.VALIDATION_ACTIONS_SEVERITY_NON_EMPTY_INLINE_TAG, ValidationMessage.WARNING);
+		node.putInt(JSPCorePreferenceNames.VALIDATION_ACTIONS_SEVERITY_UNEXPECTED_RTEXPRVALUE, ValidationMessage.WARNING);
+
+		node.putInt(JSPCorePreferenceNames.VALIDATION_TRANSLATION_TEI_VALIDATION_MESSAGE, ValidationMessage.ERROR);
+		node.putInt(JSPCorePreferenceNames.VALIDATION_TRANSLATION_TEI_CLASS_NOT_FOUND, ValidationMessage.WARNING);
+		node.putInt(JSPCorePreferenceNames.VALIDATION_TRANSLATION_TEI_CLASS_NOT_INSTANTIATED, ValidationMessage.WARNING);
+		node.putInt(JSPCorePreferenceNames.VALIDATION_TRANSLATION_TEI_CLASS_RUNTIME_EXCEPTION, ValidationMessage.WARNING);
+		node.putInt(JSPCorePreferenceNames.VALIDATION_TRANSLATION_TAG_HANDLER_CLASS_NOT_FOUND, ValidationMessage.WARNING);
+		node.putInt(JSPCorePreferenceNames.VALIDATION_TRANSLATION_USEBEAN_INVALID_ID, ValidationMessage.ERROR);
+		node.putInt(JSPCorePreferenceNames.VALIDATION_TRANSLATION_USBEAN_MISSING_TYPE_INFO, ValidationMessage.ERROR);
+		node.putInt(JSPCorePreferenceNames.VALIDATION_TRANSLATION_USEBEAN_AMBIGUOUS_TYPE_INFO, ValidationMessage.WARNING);
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/preferences/JSPCorePreferenceNames.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/preferences/JSPCorePreferenceNames.java
new file mode 100644
index 0000000..1f8f2b0
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/preferences/JSPCorePreferenceNames.java
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.preferences;
+
+
+/**
+ * Common preference keys used by JSP core
+ */
+public class JSPCorePreferenceNames {
+	private JSPCorePreferenceNames() {
+		// empty private constructor so users cannot instantiate class
+	}
+
+	/**
+	 * The default extension to use when none is specified in the New JSP File
+	 * Wizard.
+	 * <p>
+	 * Value is of type <code>String</code>.
+	 * </p>
+	 */
+	public static final String DEFAULT_EXTENSION = "defaultExtension"; //$NON-NLS-1$
+
+	/**
+	 * Indicates if JSP fragments should be compiled/validated. JSP fragments
+	 * will be validated when true.
+	 * <p>
+	 * Value is of type <code>Boolean</code>.
+	 * </p>
+	 */
+	public static final String VALIDATE_FRAGMENTS = "validateFragments";//$NON-NLS-1$
+
+	/**
+	 * Indicates that JSP validation will use per-project preferences
+	 * <p>
+	 * Value is of type <code>Boolean</code>.
+	 * </p>
+	 */
+	public static final String VALIDATION_USE_PROJECT_SETTINGS = "validation.use-project-settings";
+
+	/**
+	 * Validation preference keys
+	 */
+	public static final String VALIDATION_DIRECTIVE_TAGLIB_DUPLICATE_PREFIXES_DIFFERENT_URIS="validation.directive-taglib-duplicate-prefixes-different-uris";//$NON-NLS-1$
+	public static final String VALIDATION_DIRECTIVE_TAGLIB_DUPLICATE_PREFIXES_SAME_URIS="validation.directive-taglib-duplicate-prefixes-same-uris";//$NON-NLS-1$
+	public static final String VALIDATION_DIRECTIVE_TAGLIB_MISSING_PREFIX="validation.directive-taglib-missing-prefix";//$NON-NLS-1$
+	public static final String VALIDATION_DIRECTIVE_TAGLIB_MISSING_URI_OR_TAGDIR="validation.directive-taglib-missing-uri-or-tagdir";//$NON-NLS-1$
+	public static final String VALIDATION_DIRECTIVE_TAGLIB_UNRESOLVABLE_URI_OR_TAGDIR="validation.directive-taglib-unresolvable-uri-or-tagdir";//$NON-NLS-1$
+	public static final String VALIDATION_DIRECTIVE_PAGE_SUPERCLASS_NOT_FOUND="validation.directive-page-superclass-not-found";//$NON-NLS-1$
+	public static final String VALIDATION_DIRECTIVE_INCLUDE_NO_FILE_SPECIFIED="validation.directive-include-fragment-file-not-specified";//$NON-NLS-1$
+	public static final String VALIDATION_DIRECTIVE_INCLUDE_FILE_NOT_FOUND="validation.directive-include-fragment-file-not-found";//$NON-NLS-1$
+	
+	public static final String VALIDATION_JAVA_LOCAL_VARIABLE_NEVER_USED ="validation.java-local-variable-is-never-used";
+	public static final String VALIDATION_JAVA_ARGUMENT_IS_NEVER_USED  ="validation.java-";
+	public static final String VALIDATION_JAVA_NULL_LOCAL_VARIABLE_REFERENCE  ="validation.java-null-local-variable-reference";
+	public static final String VALIDATION_JAVA_POTENTIAL_NULL_LOCAL_VARIABLE_REFERENCE  ="validation.java-potential-null-local-variable-reference";
+	public static final String VALIDATION_JAVA_UNUSED_IMPORT  ="validation.java-unused-import";
+	
+	public static final String VALIDATION_EL_SYNTAX  ="validation.el-general-syntax";
+	public static final String VALIDATION_EL_LEXER  ="validation.el-lexical-failure";
+
+	public static final String VALIDATION_ACTIONS_SEVERITY_MISSING_REQUIRED_ATTRIBUTE = "validation.actions-missing-required-attribute";
+	public static final String VALIDATION_ACTIONS_SEVERITY_UNKNOWN_ATTRIBUTE = "validation.actions-unknown-attribute";
+	public static final String VALIDATION_ACTIONS_SEVERITY_UNEXPECTED_RTEXPRVALUE = "validation.actions-unexpected-rtexprvalue";
+	public static final String VALIDATION_ACTIONS_SEVERITY_NON_EMPTY_INLINE_TAG = "validation.actions-non-empty-inline-tag";
+	
+	public static final String VALIDATION_TRANSLATION_TEI_VALIDATION_MESSAGE = "validation.translation-tei-message";
+	public static final String VALIDATION_TRANSLATION_TEI_CLASS_NOT_FOUND = "validation.translation-tei-class-not-found";
+	public static final String VALIDATION_TRANSLATION_TEI_CLASS_NOT_INSTANTIATED = "validation.translation-tei-class-not-instantiated";
+	public static final String VALIDATION_TRANSLATION_TEI_CLASS_RUNTIME_EXCEPTION = "validation.translation-tei-class-runtime-exception";	
+	public static final String VALIDATION_TRANSLATION_TAG_HANDLER_CLASS_NOT_FOUND = "validation.translation-tag-class-not-found";
+	public static final String VALIDATION_TRANSLATION_USEBEAN_INVALID_ID= "validation.translation-usebean-invalid-id";
+	public static final String VALIDATION_TRANSLATION_USBEAN_MISSING_TYPE_INFO= "validation.translation-usebean-missing-type-info";
+	public static final String VALIDATION_TRANSLATION_USEBEAN_AMBIGUOUS_TYPE_INFO = "validation.translation-usebean-ambiguous-type-info";
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/provisional/JSP11Namespace.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/provisional/JSP11Namespace.java
new file mode 100644
index 0000000..43d0f75
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/provisional/JSP11Namespace.java
@@ -0,0 +1,109 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.provisional;
+
+
+/**
+ * JSP 1.1 Namespace
+ */
+public interface JSP11Namespace {
+
+	public static interface ElementName {
+		// Element names
+		public static final String SCRIPTLET = "jsp:scriptlet"; //$NON-NLS-1$
+		public static final String EXPRESSION = "jsp:expression"; //$NON-NLS-1$
+		public static final String DECLARATION = "jsp:declaration"; //$NON-NLS-1$
+		public static final String DIRECTIVE_PAGE = "jsp:directive.page"; //$NON-NLS-1$
+		public static final String DIRECTIVE_INCLUDE = "jsp:directive.include"; //$NON-NLS-1$
+		public static final String DIRECTIVE_TAGLIB = "jsp:directive.taglib"; //$NON-NLS-1$
+		public static final String USEBEAN = "jsp:useBean"; //$NON-NLS-1$
+		public static final String SETPROPERTY = "jsp:setProperty"; //$NON-NLS-1$
+		public static final String GETPROPERTY = "jsp:getProperty"; //$NON-NLS-1$
+		public static final String INCLUDE = "jsp:include"; //$NON-NLS-1$
+		public static final String FORWARD = "jsp:forward"; //$NON-NLS-1$
+		public static final String PLUGIN = "jsp:plugin"; //$NON-NLS-1$
+		public static final String PARAMS = "jsp:params"; //$NON-NLS-1$
+		public static final String FALLBACK = "jsp:fallback"; //$NON-NLS-1$
+		public static final String PARAM = "jsp:param"; //$NON-NLS-1$
+		public static final String ROOT = "jsp:root"; //$NON-NLS-1$
+		public static final String TEXT = "jsp:text"; //$NON-NLS-1$
+	}
+
+	public static final String JSP11_URI = ""; //$NON-NLS-1$
+	public static final String JSP_TAG_PREFIX = "jsp"; //$NON-NLS-1$
+	// attribute names
+	//   directive.page
+	public static final String ATTR_NAME_LANGUAGE = "language"; //$NON-NLS-1$
+	public static final String ATTR_NAME_EXTENDS = "extends"; //$NON-NLS-1$
+	public static final String ATTR_NAME_CONTENT_TYPE = "contentType"; //$NON-NLS-1$
+	public static final String ATTR_NAME_IMPORT = "import"; //$NON-NLS-1$
+	public static final String ATTR_NAME_SESSION = "session"; //$NON-NLS-1$
+	public static final String ATTR_NAME_BUFFER = "buffer"; //$NON-NLS-1$
+	public static final String ATTR_NAME_AUTOFLUSH = "autoFlush"; //$NON-NLS-1$
+	public static final String ATTR_NAME_IS_THREAD_SAFE = "isThreadSafe"; //$NON-NLS-1$
+	public static final String ATTR_NAME_INFO = "info"; //$NON-NLS-1$
+	public static final String ATTR_NAME_ERROR_PAGE = "errorPage"; //$NON-NLS-1$
+	public static final String ATTR_NAME_IS_ERROR_PAGE = "isErrorPage"; //$NON-NLS-1$
+	public static final String ATTR_NAME_PAGE_ENCODING = "pageEncoding"; //$NON-NLS-1$
+	//   directive.include
+	public static final String ATTR_NAME_FILE = "file"; //$NON-NLS-1$
+	//   directive.taglib
+	public static final String ATTR_NAME_URI = "uri"; //$NON-NLS-1$
+	public static final String ATTR_NAME_PREFIX = "prefix"; //$NON-NLS-1$
+	//   useBean
+	public static final String ATTR_NAME_ID = "id"; //$NON-NLS-1$
+	public static final String ATTR_NAME_SCOPE = "scope"; //$NON-NLS-1$
+	public static final String ATTR_NAME_CLASS = "class"; //$NON-NLS-1$
+	public static final String ATTR_NAME_BEAN_NAME = "beanName"; //$NON-NLS-1$
+	public static final String ATTR_NAME_TYPE = "type"; //$NON-NLS-1$
+	//   setProperty
+	public static final String ATTR_NAME_NAME = "name"; //$NON-NLS-1$
+	public static final String ATTR_NAME_PROPERTY = "property"; //$NON-NLS-1$
+	public static final String ATTR_NAME_VALUE = "value"; //$NON-NLS-1$
+	public static final String ATTR_NAME_PARAM = "param"; //$NON-NLS-1$
+	//   include
+	public static final String ATTR_NAME_PAGE = "page"; //$NON-NLS-1$
+	public static final String ATTR_NAME_FLUSH = "flush"; //$NON-NLS-1$
+	//   plugin
+	public static final String ATTR_NAME_CODE = "code"; //$NON-NLS-1$
+	public static final String ATTR_NAME_CODEBASE = "codebase"; //$NON-NLS-1$
+	public static final String ATTR_NAME_ALIGN = "align"; //$NON-NLS-1$
+	public static final String ATTR_NAME_ARCHIVE = "archive"; //$NON-NLS-1$
+	public static final String ATTR_NAME_HEIGHT = "height"; //$NON-NLS-1$
+	public static final String ATTR_NAME_HSPACE = "hspace"; //$NON-NLS-1$
+	public static final String ATTR_NAME_JREVERSION = "jreversion"; //$NON-NLS-1$
+	public static final String ATTR_NAME_VSPACE = "vspace"; //$NON-NLS-1$
+	public static final String ATTR_NAME_WIDTH = "width"; //$NON-NLS-1$
+	public static final String ATTR_NAME_NSPLUGINURL = "nspluginurl"; //$NON-NLS-1$
+	public static final String ATTR_NAME_IEPLUGINURL = "iepluginurl"; //$NON-NLS-1$
+	//   root
+	public static final String ATTR_NAME_XMLNS_JSP = "xmlns:jsp"; //$NON-NLS-1$
+	public static final String ATTR_NAME_VERSION = "version"; //$NON-NLS-1$
+	// attribute values
+	public static final String ATTR_VALUE_TRUE = "true"; //$NON-NLS-1$
+	public static final String ATTR_VALUE_FALSE = "false"; //$NON-NLS-1$
+	public static final String ATTR_VALUE_JAVA = "java"; //$NON-NLS-1$
+	public static final String ATTR_VALUE_CT_DEFAULT = "text/html; charset=ISO-8859-1";//D195366 //$NON-NLS-1$
+	public static final String ATTR_VALUE_BUFSIZ_DEFAULT = "8kb"; //$NON-NLS-1$
+	public static final String ATTR_VALUE_PAGE = "page"; //$NON-NLS-1$
+	public static final String ATTR_VALUE_SESSION = "session"; //$NON-NLS-1$
+	public static final String ATTR_VALUE_REQUEST = "request"; //$NON-NLS-1$
+	public static final String ATTR_VALUE_APPLICATION = "application"; //$NON-NLS-1$
+	public static final String ATTR_VALUE_BEAN = "bean"; //$NON-NLS-1$
+	public static final String ATTR_VALUE_APPLET = "applet"; //$NON-NLS-1$
+	public static final String ATTR_VALUE_TOP = "top"; //$NON-NLS-1$
+	public static final String ATTR_VALUE_MIDDLE = "middle"; //$NON-NLS-1$
+	public static final String ATTR_VALUE_BOTTOM = "bottom"; //$NON-NLS-1$
+	public static final String ATTR_VALUE_LEFT = "left"; //$NON-NLS-1$
+	public static final String ATTR_VALUE_RIGHT = "right"; //$NON-NLS-1$
+	public static final String ATTR_VALUE_JVER11 = "1.1"; //$NON-NLS-1$
+	public static final String ATTR_VALUE_XMLNS_JSP = "http://java.sun.com/JSP/Page"; //$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/provisional/JSP12Namespace.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/provisional/JSP12Namespace.java
new file mode 100644
index 0000000..89f76e8
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/provisional/JSP12Namespace.java
@@ -0,0 +1,19 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.provisional;
+
+/**
+ * Names for JSP 1.2 spec.
+ * Currently, it is just the same as JSP11Namespace in org.eclipse.jst.jsp.core.
+ */
+public interface JSP12Namespace extends JSP11Namespace {
+
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/provisional/JSP20Namespace.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/provisional/JSP20Namespace.java
new file mode 100644
index 0000000..3e1fde3
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/provisional/JSP20Namespace.java
@@ -0,0 +1,18 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.provisional;
+
+/**
+ * New names for JSP 2.0 spec.
+ */
+
+public interface JSP20Namespace extends org.eclipse.wst.html.core.internal.contentmodel.JSP20Namespace {
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/provisional/JSP21Namespace.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/provisional/JSP21Namespace.java
new file mode 100644
index 0000000..bbb5d9d
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/provisional/JSP21Namespace.java
@@ -0,0 +1,14 @@
+/*******************************************************************************
+ * Copyright (c) 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.provisional;
+
+public interface JSP21Namespace extends org.eclipse.wst.html.core.internal.contentmodel.JSP21Namespace {
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/provisional/contenttype/ContentTypeIdForJSP.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/provisional/contenttype/ContentTypeIdForJSP.java
new file mode 100644
index 0000000..0f246bc
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/provisional/contenttype/ContentTypeIdForJSP.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+
+package org.eclipse.jst.jsp.core.internal.provisional.contenttype;
+
+/**
+ * This class, with its one field, is a convience to provide compile-time
+ * safety when refering to a contentType ID. The value of the contenttype id
+ * field must match what is specified in plugin.xml file.
+ */
+
+public class ContentTypeIdForJSP {
+	/**
+	 * The value of the contenttype id field must match what is specified in
+	 * plugin.xml file. Note: this value is intentially set with default
+	 * protected method so it will not be inlined.
+	 */
+	public final static String ContentTypeID_JSP = getConstantString();
+	/**
+	 * The value of the contenttype id field must match what is specified in
+	 * plugin.xml file. Note: this value is intentially set with default
+	 * protected method so it will not be inlined.
+	 */
+	public final static String ContentTypeID_JSPFRAGMENT = getFragmentConstantString();
+
+	/**
+	 * The value of the contenttype id field must match what is specified in
+	 * plugin.xml file. Note: this value is intentially set with default
+	 * protected method so it will not be inlined.
+	 */
+	public final static String ContentTypeID_JSPTAG = getTagConstantString();
+
+	/**
+	 * Don't allow instantiation.
+	 */
+	private ContentTypeIdForJSP() {
+		super();
+	}
+
+	static String getConstantString() {
+		return "org.eclipse.jst.jsp.core.jspsource"; //$NON-NLS-1$
+	}
+	
+	static String getFragmentConstantString() {
+		return "org.eclipse.jst.jsp.core.jspfragmentsource"; //$NON-NLS-1$
+	}
+	
+	static String getTagConstantString() {
+		return "org.eclipse.jst.jsp.core.tagsource"; //$NON-NLS-1$
+	}
+
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/provisional/contenttype/IContentDescriptionForJSP.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/provisional/contenttype/IContentDescriptionForJSP.java
new file mode 100644
index 0000000..393dd10
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/provisional/contenttype/IContentDescriptionForJSP.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.provisional.contenttype;
+
+import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.wst.sse.core.internal.encoding.ICodedResourcePlugin;
+
+
+public interface IContentDescriptionForJSP {
+	/**
+	 * Extra properties as part of ContentDescription, if the content is JSP.
+	 */
+	public final static QualifiedName CONTENT_TYPE_ATTRIBUTE = new QualifiedName(ICodedResourcePlugin.ID, "contentTypeAttribute"); //$NON-NLS-1$
+	public final static QualifiedName LANGUAGE_ATTRIBUTE = new QualifiedName(ICodedResourcePlugin.ID, "languageAttribute"); //$NON-NLS-1$
+	public final static QualifiedName CONTENT_FAMILY_ATTRIBUTE = new QualifiedName(ICodedResourcePlugin.ID, "contentFamilyAttribute"); //$NON-NLS-1$;
+
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/provisional/text/IJSPPartitionTypes.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/provisional/text/IJSPPartitionTypes.java
new file mode 100644
index 0000000..49cc31d
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/provisional/text/IJSPPartitionTypes.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.provisional.text;
+
+
+/**
+ * This interface is not intended to be implemented.
+ * It defines the partition types for JSP.
+ * Clients should reference the partition type Strings defined here directly.
+ * 
+ * @deprecated use org.eclipse.jst.jsp.core.internal.provisional.text.IJSPPartitions
+ */
+public interface IJSPPartitionTypes {
+
+	String JSP_DEFAULT = "org.eclipse.jst.jsp.DEFAULT_JSP"; //$NON-NLS-1$
+	String JSP_COMMENT = "org.eclipse.jst.jsp.JSP_COMMENT"; //$NON-NLS-1$
+	
+	String JSP_SCRIPT_PREFIX = "org.eclipse.jst.jsp.SCRIPT."; //$NON-NLS-1$
+	String JSP_CONTENT_DELIMITER = JSP_SCRIPT_PREFIX + "DELIMITER"; //$NON-NLS-1$
+	String JSP_CONTENT_JAVA = JSP_SCRIPT_PREFIX + "JAVA"; //$NON-NLS-1$
+	String JSP_CONTENT_JAVASCRIPT = JSP_SCRIPT_PREFIX + "JAVASCRIPT"; //$NON-NLS-1$
+	String JSP_DEFAULT_EL = JSP_SCRIPT_PREFIX + "JSP_EL"; //$NON-NLS-1$
+	String JSP_DEFAULT_EL2 = JSP_SCRIPT_PREFIX + "JSP_EL2"; //$NON-NLS-1$
+	
+	String JSP_DIRECTIVE = "org.eclipse.jst.jsp.JSP_DIRECTIVE"; //$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/regions/DOMJSPRegionContexts.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/regions/DOMJSPRegionContexts.java
new file mode 100644
index 0000000..3387e1f
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/regions/DOMJSPRegionContexts.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2009 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     Frits Jalvingh - contributions for bug 150794
+ *     
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.regions;
+
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+
+
+/**
+ *
+ */
+
+public interface DOMJSPRegionContexts extends DOMRegionContext {
+	public static final String JSP_CLOSE = "JSP_CLOSE"; //$NON-NLS-1$
+	public static final String JSP_COMMENT_CLOSE = "JSP_COMMENT_CLOSE"; //$NON-NLS-1$
+
+	public static final String JSP_COMMENT_OPEN = "JSP_COMMENT_OPEN"; //$NON-NLS-1$
+	public static final String JSP_COMMENT_TEXT = "JSP_COMMENT_TEXT"; //$NON-NLS-1$
+
+	public static final String JSP_CONTENT = "JSP_CONTENT"; //$NON-NLS-1$
+	public static final String JSP_DECLARATION_OPEN = "JSP_DECLARATION_OPEN"; //$NON-NLS-1$
+	public static final String JSP_DIRECTIVE_CLOSE = "JSP_DIRECTIVE_CLOSE"; //$NON-NLS-1$
+	public static final String JSP_DIRECTIVE_NAME = "JSP_DIRECTIVE_NAME"; //$NON-NLS-1$
+
+	public static final String JSP_DIRECTIVE_OPEN = "JSP_DIRECTIVE_OPEN"; //$NON-NLS-1$
+	public static final String JSP_EL_CLOSE = "JSP_EL_CLOSE"; //$NON-NLS-1$
+	public static final String JSP_EL_CONTENT = "JSP_EL_CONTENT"; //$NON-NLS-1$
+	public static final String JSP_EL_DQUOTE = "JSP_EL_DQUOTE"; //$NON-NLS-1$
+
+	public static final String JSP_EL_OPEN = "JSP_EL_OPEN"; //$NON-NLS-1$
+	public static final String JSP_EL_QUOTED_CONTENT = "JSP_EL_QUOTED_CONTENT"; //$NON-NLS-1$
+	public static final String JSP_EL_SQUOTE = "JSP_EL_SQUOTE"; //$NON-NLS-1$
+	public static final String JSP_EXPRESSION_OPEN = "JSP_EXPRESSION_OPEN"; //$NON-NLS-1$
+
+	public static final String JSP_ROOT_TAG_NAME = "JSP_ROOT_TAG_NAME"; //$NON-NLS-1$
+
+	public static final String JSP_SCRIPTLET_OPEN = "JSP_SCRIPTLET_OPEN"; //$NON-NLS-1$
+	public static final String JSP_VBL_CLOSE = "JSP_VBL_CLOSE"; //$NON-NLS-1$
+	public static final String JSP_VBL_CONTENT = "JSP_VBL_CONTENT"; //$NON-NLS-1$
+	public static final String JSP_VBL_DQUOTE = "JSP_VBL_DQUOTE"; //$NON-NLS-1$
+	public static final String JSP_VBL_OPEN = "JSP_VBL_OPEN"; //$NON-NLS-1$
+	public static final String JSP_VBL_QUOTED_CONTENT = "JSP_VBL_QUOTED_CONTENT"; //$NON-NLS-1$
+	public static final String JSP_VBL_SQUOTE = "JSP_VBL_SQUOTE"; //$NON-NLS-1$
+
+	/** Non-taglib XML tag, needing single escape unquoting for embedded expressions */
+	public static final String XML_TAG_ATTRIBUTE_VALUE_DQUOTE = "XML_TAG_ATTRIBUTE_VALUE_DQUOTE"; //$NON-NLS-1$
+	public static final String XML_TAG_ATTRIBUTE_VALUE_SQUOTE = "XML_TAG_ATTRIBUTE_VALUE_SQUOTE"; //$NON-NLS-1$
+
+	/** Taglib tag attribute with double quote, needing 'double escaping' */
+	public static final String JSP_TAG_ATTRIBUTE_VALUE_DQUOTE = "JSP_TAG_ATTRIBUTE_VALUE_DQUOTE"; //$NON-NLS-1$
+	/** Taglib tag attribute with single quote, needing 'double escaping' */
+	public static final String JSP_TAG_ATTRIBUTE_VALUE_SQUOTE = "JSP_TAG_ATTRIBUTE_VALUE_SQUOTE"; //$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/taglib/BuildPathClassLoader.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/taglib/BuildPathClassLoader.java
new file mode 100644
index 0000000..7b5443f
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/taglib/BuildPathClassLoader.java
@@ -0,0 +1,234 @@
+/*******************************************************************************
+ * Copyright (c) 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.taglib;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Platform;
+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.jst.jsp.core.internal.Logger;
+import org.eclipse.wst.sse.core.utils.StringUtils;
+
+/**
+ * Custom ClassLoader backed by a Java Project.
+ */
+public class BuildPathClassLoader extends ClassLoader {
+	private static final boolean DEBUG = Boolean.valueOf(Platform.getDebugOption("org.eclipse.jst.jsp.core/debug/taglibclassloader")).booleanValue(); //$NON-NLS-1$
+	private IJavaProject fProject;
+
+	public BuildPathClassLoader(ClassLoader parent, IJavaProject project) {
+		super(parent);
+		fProject = project;
+	}
+
+	/**
+	 * Closes the given file with "extreme prejudice".
+	 * 
+	 * @param file the zip file to be closed
+	 */
+	public void closeJarFile(ZipFile file) {
+		if (file == null)
+			return;
+		try {
+			file.close();
+		}
+		catch (IOException ioe) {
+			// no cleanup can be done
+			Logger.logException("JarUtilities: Could not close file " + file.getName(), ioe); //$NON-NLS-1$
+		}
+	}
+
+	/*
+	 * This may pose a runtime performance problem as it opens the containing
+	 * .jar file for each class, but this is countered by no longer leaving
+	 * file handles open nor having to directly interact the build path at
+	 * all. If it is a problem, the TaglibHelper should control some
+	 * "batching" whereby we leave the JarFiles open until directed to close
+	 * them at the end of TaglibHelper.addTEIVariables(...).
+	 * 
+	 * @see java.lang.ClassLoader#findClass(java.lang.String)
+	 */
+	protected Class findClass(String className) throws ClassNotFoundException {
+		if (DEBUG)
+			System.out.println("finding: [" + className + "]"); //$NON-NLS-1$ //$NON-NLS-2$
+		try {
+			IType type = fProject.findType(className);
+			int offset = -1;
+			if (type == null && (offset = className.indexOf('$')) != -1) {
+				// Internal classes from source files must be referenced by . instead of $
+				String cls = className.substring(0, offset) + className.substring(offset).replace('$', '.');
+				type = fProject.findType(cls);
+			}
+			if (type != null) {
+				IPath path = null;
+				IResource resource = type.getResource();
+
+				if (resource != null)
+					path = resource.getLocation();
+				if (path == null)
+					path = type.getPath();
+
+				// needs to be compiled before we can load it
+				if ("class".equalsIgnoreCase(path.getFileExtension())) {
+					IFile file = null;
+
+					if (resource != null && resource.getType() == IResource.FILE)
+						file = (IFile) resource;
+					else
+						file = ResourcesPlugin.getWorkspace().getRoot().getFile(path);
+
+					if (file != null && file.isAccessible()) {
+						byte[] bytes = loadBytes(file);
+						return defineClass(className, bytes, 0, bytes.length);
+					}
+				}
+				// Look up the class file based on the output location of the java project
+				else if ("java".equalsIgnoreCase(path.getFileExtension()) && resource != null) { //$NON-NLS-1$
+					if (resource.getProject() != null) {
+						IJavaProject jProject = JavaCore.create(resource.getProject());
+						String outputClass = StringUtils.replace(type.getFullyQualifiedName(), ".", "/").concat(".class"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+						IPath classPath = jProject.getOutputLocation().append(outputClass);
+						IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(classPath);
+						if (file != null && file.isAccessible()) {
+							byte[] bytes = loadBytes(file);
+							return defineClass(className, bytes, 0, bytes.length);
+						}
+					}
+				}
+				else if ("jar".equalsIgnoreCase(path.getFileExtension())) {
+					String expectedFileName = StringUtils.replace(className, ".", "/").concat(".class"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+					byte[] bytes = getCachedInputStream(path.toOSString(), expectedFileName);
+					return defineClass(className, bytes, 0, bytes.length);
+				}
+			}
+		}
+		catch (JavaModelException e) {
+			Logger.logException(e);
+		}
+		return super.findClass(className);
+	}
+
+	/**
+	 * Get the entry from the jarfile
+	 * @param jarFilename the string path of the jarfile
+	 * @param entryName the fully-qualified entry
+	 * @return the bytes for the entry within the jarfile or a byte array of size 0
+	 */
+	private byte[] getCachedInputStream(String jarFilename, String entryName) {
+		ByteArrayOutputStream buffer = null;
+
+		File testFile = new File(jarFilename);
+		if (!testFile.exists())
+			return null;
+
+		ZipFile jarfile = null;
+		try {
+			jarfile = new ZipFile(jarFilename);
+			
+			if (jarfile != null) {
+				ZipEntry zentry = jarfile.getEntry(entryName);
+				if (zentry != null) {
+					InputStream entryInputStream = null;
+					try {
+						entryInputStream = jarfile.getInputStream(zentry);
+					}
+					catch (IOException ioExc) {
+						Logger.logException("JarUtilities: " + jarFilename, ioExc); //$NON-NLS-1$
+					}
+
+					if (entryInputStream != null) {
+						int c;
+						if (zentry.getSize() > 0) {
+							buffer = new ByteArrayOutputStream((int) zentry.getSize());
+						}
+						else {
+							buffer = new ByteArrayOutputStream();
+						}
+						// array dim restriction?
+						byte bytes[] = new byte[2048];
+						try {
+							while ((c = entryInputStream.read(bytes)) >= 0) {
+								buffer.write(bytes, 0, c);
+							}
+						}
+						catch (IOException ioe) {
+							// no cleanup can be done
+						}
+						finally {
+							try {
+								entryInputStream.close();
+							}
+							catch (IOException e) {
+							}
+						}
+					}
+				}
+			}
+		}
+		catch (IOException ioExc) {
+			Logger.logException("JarUtilities: " + jarFilename, ioExc); //$NON-NLS-1$
+		}
+		finally {
+			closeJarFile(jarfile);
+		}
+
+		if (buffer != null) {
+			return buffer.toByteArray();
+		}
+		return new byte[0];
+	}
+
+	/**
+	 * @param file
+	 * @return
+	 */
+	private byte[] loadBytes(IFile file) {
+		ByteArrayOutputStream out = new ByteArrayOutputStream();
+		InputStream in = null;
+		try {
+			in = file.getContents();
+			byte[] buffer = new byte[4096];
+			int read = 0;
+			while ((read = in.read(buffer)) != -1) {
+				out.write(buffer, 0, read);
+			}
+		}
+		catch (CoreException e) {
+			Logger.logException(e);
+		}
+		catch (IOException e) {
+			Logger.logException(e);
+		}
+		finally {
+			try {
+				if (in != null)
+					in.close();
+			}
+			catch (IOException e) {
+			}
+		}
+		return out.toByteArray();
+	}
+
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/taglib/CustomTag.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/taglib/CustomTag.java
new file mode 100644
index 0000000..0186713
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/taglib/CustomTag.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright (c) 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.taglib;
+
+/**
+ * Contains information about a custom tag including the tag name (with prefix),
+ * the class that defines the functionality of the tag, TEI class, any scripting variables associated with the
+ * TEI class, and if the class is an iteration tag
+ *
+ */
+public class CustomTag {
+
+	private final String fTagName;
+	private final String fClassName;
+	private final String fTeiClassName;
+	private final boolean fIsIterationTag;
+	private final TaglibVariable[] fVariables;
+
+	public CustomTag(String tagName, String className, String teiClassName, TaglibVariable[] tagVariables, boolean isIterationTag) {
+		fTagName = tagName;
+		fClassName = className;
+		fTeiClassName = teiClassName;
+		fVariables = tagVariables;
+		fIsIterationTag = isIterationTag;
+	}
+
+	/**
+	 * Returns the name of the tag with its prefix
+	 * @return the tag name including prefix
+	 */
+	public String getTagName() {
+		return fTagName;
+	}
+
+	/**
+	 * Returns the name of the implementation class for the tag
+	 * @return the name of the implementation class for the tag
+	 */
+	public String getTagClassName() {
+		return fClassName;
+	}
+
+	/**
+	 * Returns the name of the TagExtraInfo class for the tag
+	 * @return the name of the TagExtraInfo class for the tag
+	 */
+	public String getTeiClassName() {
+		return fTeiClassName;
+	}
+
+	/**
+	 * Returns an array of scripting variables associated with the TagExtraInfo class
+	 * @return an array of scripting variables associated with the TagExtraInfo class
+	 */
+	public TaglibVariable[] getTagVariables() {
+		return fVariables;
+	}
+
+	/**
+	 * Identifies if the tag implements the IterationTag interface
+	 * @return true if the tag implements the IterationTag interface; false otherwise
+	 */
+	public boolean isIterationTag() {
+		return fIsIterationTag;
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/taglib/TaglibClassLoader.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/taglib/TaglibClassLoader.java
new file mode 100644
index 0000000..0dc3948
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/taglib/TaglibClassLoader.java
@@ -0,0 +1,91 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.taglib;
+
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jst.jsp.core.internal.Logger;
+
+/**
+ * Custom classloader which allows you to add source directories (folders
+ * containing .class files) and jars to the classpath.
+ */
+public class TaglibClassLoader extends URLClassLoader {
+	// for debugging
+	private static final boolean DEBUG = Boolean.valueOf(Platform.getDebugOption("org.eclipse.jst.jsp.core/debug/taglibclassloader")).booleanValue(); //$NON-NLS-1$
+
+	private static final String FILE = "file:/";
+	private static final String RESOURCE = "platform:/resource/";
+
+	public TaglibClassLoader(ClassLoader parentLoader) {
+		super(new URL[0], parentLoader);
+	}
+
+	public void addDirectory(String dirPath) {
+		addJavaFile(dirPath + "/"); //$NON-NLS-1$
+	}
+
+	public void addFile(IPath filePath) {
+		try {
+			URL url = new URL(RESOURCE + filePath.toString()); //$NON-NLS-1$
+			super.addURL(url);
+			if (DEBUG)
+				System.out.println("added: [" + url + "] to classpath"); //$NON-NLS-1$ //$NON-NLS-2$
+		}
+		catch (MalformedURLException e) {
+			Logger.logException(filePath.toString(), e);
+		}
+	}
+
+	public void addFolder(IPath folderPath) {
+		try {
+			URL url = new URL(RESOURCE + folderPath.toString() + "/"); //$NON-NLS-1$
+			super.addURL(url);
+			if (DEBUG)
+				System.out.println("added: [" + url + "] to classpath"); //$NON-NLS-1$ //$NON-NLS-2$
+		}
+		catch (MalformedURLException e) {
+			Logger.logException(folderPath.toString(), e);
+		}
+	}
+
+	public void addJar(String filename) {
+		addJavaFile(filename);
+	}
+
+	void addJavaFile(String filename) {
+		try {
+			URL url = new URL(FILE + filename);
+			super.addURL(url);
+			if (DEBUG)
+				System.out.println("added: [" + url + "] to classpath"); //$NON-NLS-1$ //$NON-NLS-2$
+		}
+		catch (MalformedURLException e) {
+			Logger.logException(filename, e);
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see java.net.URLClassLoader#findClass(java.lang.String)
+	 */
+	protected Class findClass(String className) throws ClassNotFoundException {
+		if (DEBUG)
+			System.out.println("finding: [" + className + "]"); //$NON-NLS-1$ //$NON-NLS-2$
+		return super.findClass(className);
+	}
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/taglib/TaglibHelper.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/taglib/TaglibHelper.java
new file mode 100644
index 0000000..d4eee32
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/taglib/TaglibHelper.java
@@ -0,0 +1,1017 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.taglib;
+
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.servlet.jsp.tagext.FunctionInfo;
+import javax.servlet.jsp.tagext.TagAttributeInfo;
+import javax.servlet.jsp.tagext.TagData;
+import javax.servlet.jsp.tagext.TagExtraInfo;
+import javax.servlet.jsp.tagext.TagFileInfo;
+import javax.servlet.jsp.tagext.TagInfo;
+import javax.servlet.jsp.tagext.TagLibraryInfo;
+import javax.servlet.jsp.tagext.ValidationMessage;
+import javax.servlet.jsp.tagext.VariableInfo;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Platform;
+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.Signature;
+import org.eclipse.jface.text.IDocument;
+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.TaglibTracker;
+import org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.TLDAttributeDeclaration;
+import org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.TLDDocument;
+import org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.TLDElementDeclaration;
+import org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.TLDVariable;
+import org.eclipse.jst.jsp.core.internal.java.IJSPProblem;
+import org.eclipse.jst.jsp.core.internal.regions.DOMJSPRegionContexts;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.NotImplementedException;
+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.ITextRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionCollection;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList;
+import org.eclipse.wst.sse.core.internal.util.AbstractMemoryListener;
+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.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.modelquery.ModelQueryUtil;
+import org.eclipse.wst.xml.core.internal.provisional.contentmodel.CMNodeWrapper;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+import org.osgi.service.event.Event;
+
+import com.ibm.icu.text.MessageFormat;
+
+/**
+ * This class helps find TaglibVariables in a JSP file.
+ */
+public class TaglibHelper {
+
+	private static final String ITERATION_QUALIFIER = "javax.servlet.jsp.tagext"; //$NON-NLS-1$
+	private static final String ITERATION_NAME = "IterationTag"; //$NON-NLS-1$
+	
+	// for debugging
+	private static final boolean DEBUG;
+	static {
+		String value = Platform.getDebugOption("org.eclipse.jst.jsp.core/debug/taglibvars"); //$NON-NLS-1$
+		DEBUG = value != null && value.equalsIgnoreCase("true"); //$NON-NLS-1$
+	}
+
+	private IProject fProject = null;
+	private ClassLoader fLoader = null;
+
+	private IJavaProject fJavaProject;
+	
+	/**
+	 * A cache of class names that the class loader could not find.
+	 * Because the TaglibHelper is destroyed and recreated whenever
+	 * the classpath changes this cache will not become stale
+	 */
+	private Set fNotFoundClasses = null;
+
+	private Map fClassMap = null;
+
+	/**
+	 * Used to keep the {@link #fNotFoundClasses} cache clean when memory is low
+	 */
+	private MemoryListener fMemoryListener;
+
+	public TaglibHelper(IProject project) {
+		super();
+		setProject(project);
+		fMemoryListener = new MemoryListener();
+		fMemoryListener.connect();
+		fNotFoundClasses = new HashSet();
+		fClassMap = Collections.synchronizedMap(new HashMap());
+	}
+
+	/**
+	 * Checks that <code>type</code> implements an IterationTag
+	 * 
+	 * @param type
+	 * @return true if <code>type</code> implements IterationTag
+	 * @throws JavaModelException
+	 * @throws ClassNotFoundException thrown when the <code>type</code> is null
+	 */
+	private boolean isIterationTag(IType type) throws JavaModelException, ClassNotFoundException {
+		if (type == null) {
+			throw new ClassNotFoundException();
+		}
+		synchronized (fClassMap) {
+			if (fClassMap.containsKey(type.getFullyQualifiedName()))
+				return ((Boolean) fClassMap.get(type.getFullyQualifiedName())).booleanValue();
+		}
+
+		String signature;
+		String qualifier;
+		String name;
+		String[] interfaces = type.getSuperInterfaceTypeSignatures();
+		boolean isIteration = false;
+		// Check any super interfaces for the iteration tag
+		for (int i = 0; i < interfaces.length; i++) {
+			// For source files, the interface may need to be resolved
+			String erasureSig = Signature.getTypeErasure(interfaces[i]);
+			qualifier = Signature.getSignatureQualifier(erasureSig);
+			name = Signature.getSignatureSimpleName(erasureSig);
+			// Interface type is unresolved
+			if (erasureSig.charAt(0) == Signature.C_UNRESOLVED) {
+				String[][] types = type.resolveType(getQualifiedType(qualifier, name));
+				// Type was resolved
+				if (types != null && types.length > 0) {
+					isIteration = handleInterface(type, types[0][0], types[0][1]);
+				}
+			}
+			else {
+				isIteration = handleInterface(type, qualifier, name);
+			}
+			if (isIteration)
+				return true;
+		}
+
+		signature = type.getSuperclassTypeSignature();
+		if (signature != null) {
+			String erasureSig = Signature.getTypeErasure(signature);
+			qualifier = Signature.getSignatureQualifier(erasureSig);
+			name = Signature.getSignatureSimpleName(erasureSig);
+			// superclass was unresolved
+			if (erasureSig.charAt(0) == Signature.C_UNRESOLVED) {
+				String[][] types = type.resolveType(getQualifiedType(qualifier, name));
+				// Type was resolved
+				if (types != null && types.length > 0) {
+					isIteration = isIterationTag(fJavaProject.findType(types[0][0], types[0][1]));
+				}
+			}
+			else {
+				isIteration = isIterationTag(fJavaProject.findType(qualifier, name));
+			}
+		}
+		fClassMap.put(type.getFullyQualifiedName(), Boolean.valueOf(isIteration));
+		return isIteration;
+	}
+
+	private boolean handleInterface(IType type, String qualifier, String name) throws JavaModelException, ClassNotFoundException {
+		boolean isIteration = false;
+		// Qualified interface is an iteration tag
+		if (ITERATION_QUALIFIER.equals(qualifier) && ITERATION_NAME.equals(name))
+			isIteration = true;
+		// Check ancestors of this interface
+		else
+			isIteration = isIterationTag(fJavaProject.findType(qualifier, name));
+
+		fClassMap.put(type.getFullyQualifiedName(), Boolean.valueOf(isIteration));
+		return isIteration;
+	}
+
+	private String getQualifiedType(String qualifier, String name) {
+		StringBuffer qual = new StringBuffer(qualifier);
+		if (qual.length() > 0)
+			qual.append('.');
+		qual.append(name);
+		return qual.toString();
+	}
+
+	private boolean isIterationTag(TLDElementDeclaration elementDecl, IStructuredDocument document, ITextRegionCollection customTag, List problems) {
+		String className = elementDecl.getTagclass();
+		if (className == null || className.length() == 0 || fProject == null || fNotFoundClasses.contains(className))
+			return false;
+
+		try {
+			synchronized (fClassMap) {
+				if (fClassMap.containsKey(className))
+					return ((Boolean) fClassMap.get(className)).booleanValue();
+			}
+			return isIterationTag(fJavaProject.findType(className));
+		} catch (ClassNotFoundException e) {
+			//the class could not be found so add it to the cache
+			fNotFoundClasses.add(className);
+
+			Object createdProblem = createJSPProblem(document, customTag, IJSPProblem.TagClassNotFound, JSPCoreMessages.TaglibHelper_3, className, true);
+			if (createdProblem != null)
+				problems.add(createdProblem);
+			if (DEBUG)
+				Logger.logException(className, e);
+		} catch (JavaModelException e) {
+			if (DEBUG)
+				Logger.logException(className, e);
+		} catch (Exception e) {
+			// this is 3rd party code, need to catch all errors
+			if (DEBUG)
+				Logger.logException(className, e);
+		} catch (Error e) {
+			// this is 3rd party code, need to catch all errors
+			if (DEBUG)
+				Logger.logException(className, e);
+		}
+
+		return false;
+	}
+
+	public CustomTag getCustomTag(String tagToAdd, IStructuredDocument structuredDoc, ITextRegionCollection customTag, List problems) {
+		List results = new ArrayList();
+		boolean isIterationTag = false;
+		String tagClass = null;
+		String teiClass = null;
+		if (problems == null)
+			problems = new ArrayList();
+		ModelQuery mq = getModelQuery(structuredDoc);
+		if (mq != null) {
+			TLDCMDocumentManager mgr = TaglibController.getTLDCMDocumentManager(structuredDoc);
+
+			if (mgr != null) {
+
+				List trackers = mgr.getCMDocumentTrackers(-1);
+				Iterator taglibs = trackers.iterator();
+	
+				CMDocument doc = null;
+				CMNamedNodeMap elements = null;
+				while (taglibs.hasNext()) {
+					doc = (CMDocument) taglibs.next();
+					CMNode node = null;
+					if ((elements = doc.getElements()) != null && (node = elements.getNamedItem(tagToAdd)) != null && node.getNodeType() == CMNode.ELEMENT_DECLARATION) {
+	
+						if (node instanceof CMNodeWrapper) {
+							node = ((CMNodeWrapper) node).getOriginNode();
+						}
+						TLDElementDeclaration tldElementDecl = (TLDElementDeclaration) node;
+
+						tagClass = tldElementDecl.getTagclass();
+						teiClass = tldElementDecl.getTeiclass();
+						isIterationTag = isIterationTag(tldElementDecl, structuredDoc, customTag, problems);
+						/*
+						 * Although clearly not the right place to add validation
+						 * design-wise, this is the first time we have the
+						 * necessary information to validate the tag class.
+						 */
+						validateTagClass(structuredDoc, customTag, tldElementDecl, problems);
+	
+						// 1.2+ taglib style
+						addVariables(results, node, customTag);
+	
+						// for 1.1 need more info from taglib tracker
+						if (doc instanceof TaglibTracker) {
+							String uri = ((TaglibTracker) doc).getURI();
+							String prefix = ((TaglibTracker) doc).getPrefix();
+							// only for 1.1 taglibs
+							addTEIVariables(structuredDoc, customTag, results, tldElementDecl, prefix, uri, problems);
+						}
+						break;
+					}
+				}
+			}
+		}
+
+		return new CustomTag(tagToAdd, tagClass, teiClass, (TaglibVariable[]) results.toArray(new TaglibVariable[results.size()]), isIterationTag);
+	}
+	/**
+	 * @param tagToAdd
+	 *            is the name of the tag whose variables we want
+	 * @param structuredDoc
+	 *            is the IStructuredDocument where the tag is found
+	 * @param customTag
+	 *            is the IStructuredDocumentRegion opening tag for the custom
+	 *            tag
+	 * @param problems problems that are generated while creating variables are added to this collection
+	 */
+	public TaglibVariable[] getTaglibVariables(String tagToAdd, IStructuredDocument structuredDoc, ITextRegionCollection customTag, List problems) {
+
+		List results = new ArrayList();
+		if (problems == null)
+			problems = new ArrayList();
+		ModelQuery mq = getModelQuery(structuredDoc);
+		if (mq != null) {
+			TLDCMDocumentManager mgr = TaglibController.getTLDCMDocumentManager(structuredDoc);
+
+			// TaglibSupport support = ((TaglibModelQuery)
+			// mq).getTaglibSupport();
+			if (mgr == null)
+				return new TaglibVariable[0];
+
+			List trackers = mgr.getCMDocumentTrackers(-1);
+			Iterator taglibs = trackers.iterator();
+
+			// TaglibSupport support = ((TaglibModelQuery)
+			// mq).getTaglibSupport();
+			// if (support == null)
+			// return new TaglibVariable[0];
+			//
+			// Iterator taglibs =
+			// support.getCMDocuments(customTag.getStartOffset()).iterator();
+			CMDocument doc = null;
+			CMNamedNodeMap elements = null;
+			while (taglibs.hasNext()) {
+				doc = (CMDocument) taglibs.next();
+				CMNode node = null;
+				if ((elements = doc.getElements()) != null && (node = elements.getNamedItem(tagToAdd)) != null && node.getNodeType() == CMNode.ELEMENT_DECLARATION) {
+
+					if (node instanceof CMNodeWrapper) {
+						node = ((CMNodeWrapper) node).getOriginNode();
+					}
+					TLDElementDeclaration tldElementDecl = (TLDElementDeclaration) node;
+
+					/*
+					 * Although clearly not the right place to add validation
+					 * design-wise, this is the first time we have the
+					 * necessary information to validate the tag class.
+					 */
+					validateTagClass(structuredDoc, customTag, tldElementDecl, problems);
+
+					// 1.2+ taglib style
+					addVariables(results, node, customTag);
+
+					// for 1.1 need more info from taglib tracker
+					if (doc instanceof TaglibTracker) {
+						String uri = ((TaglibTracker) doc).getURI();
+						String prefix = ((TaglibTracker) doc).getPrefix();
+						// only for 1.1 taglibs
+						addTEIVariables(structuredDoc, customTag, results, tldElementDecl, prefix, uri, problems);
+					}
+				}
+			}
+		}
+
+		return (TaglibVariable[]) results.toArray(new TaglibVariable[results.size()]);
+	}
+
+	/**
+	 * Adds 1.2 style TaglibVariables to the results list.
+	 * 
+	 * @param results
+	 *            list where the <code>TaglibVariable</code> s are added
+	 * @param node
+	 */
+	private void addVariables(List results, CMNode node, ITextRegionCollection customTag) {
+		List list = ((TLDElementDeclaration) node).getVariables();
+		Iterator it = list.iterator();
+		while (it.hasNext()) {
+			TLDVariable var = (TLDVariable) it.next();
+			if (!var.getDeclare())
+				continue;
+
+			String varName = var.getNameGiven();
+			if (varName == null) {
+				// 2.0
+				varName = var.getAlias();
+			}
+			if (varName == null) {
+				String attrName = var.getNameFromAttribute();
+				/*
+				 * Iterate through the document region to find the
+				 * corresponding attribute name, and then use its value
+				 */
+				ITextRegionList regions = customTag.getRegions();
+				boolean attrNameFound = false;
+				for (int i = 2; i < regions.size(); i++) {
+					ITextRegion region = regions.get(i);
+					if (DOMRegionContext.XML_TAG_ATTRIBUTE_NAME.equals(region.getType())) {
+						attrNameFound = attrName.equals(customTag.getText(region));
+					}
+					if (attrNameFound && DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE.equals(region.getType())) {
+						varName = StringUtils.strip(customTag.getText(region));
+					}
+				}
+			}
+			if (varName != null) {
+				String varClass = "java.lang.String"; // the default
+				// class...//$NON-NLS-1$
+				if (var.getVariableClass() != null) {
+					varClass = var.getVariableClass();
+				}
+				results.add(new TaglibVariable(varClass, varName, var.getScope(), var.getDescription()));
+			}
+		}
+	}
+
+	/**
+	 * Adds 1.1 style TaglibVariables (defined in a TagExtraInfo class) to the
+	 * results list. Also reports problems with the tag and tei classes in
+	 * fTranslatorProblems.
+	 * 
+	 * @param customTag
+	 * @param results
+	 *            list where the <code>TaglibVariable</code> s are added
+	 * @param decl
+	 *            TLDElementDeclaration for the custom tag
+	 * @param prefix
+	 *            custom tag prefix
+	 * @param uri
+	 *            URI where the tld can be found
+	 */
+	private void addTEIVariables(IStructuredDocument document, ITextRegionCollection customTag, List results, TLDElementDeclaration decl, String prefix, String uri, List problems) {
+		String teiClassname = decl.getTeiclass();
+		if (teiClassname == null || teiClassname.length() == 0 || fJavaProject == null || fNotFoundClasses.contains(teiClassname))
+			return;
+
+		ClassLoader loader = getClassloader();
+
+		Class teiClass = null;
+		try {
+			/*
+			 * JDT could tell us about it, but loading and calling it would
+			 * still take time
+			 */
+			teiClass = Class.forName(teiClassname, true, loader);
+			if (teiClass != null) {
+				Object teiObject = teiClass.newInstance();
+				if (TagExtraInfo.class.isInstance(teiObject)) {
+					TagExtraInfo tei = (TagExtraInfo) teiObject;
+					Hashtable tagDataTable = extractTagData(customTag);
+					TagInfo info = getTagInfo(decl, tei, prefix, uri);
+					if (info != null) {
+						tei.setTagInfo(info);
+
+						// add to results
+						TagData td = new TagData(tagDataTable);
+
+						VariableInfo[] vInfos = tei.getVariableInfo(td);
+						if (vInfos != null) {
+							for (int i = 0; i < vInfos.length; i++) {
+								results.add(new TaglibVariable(vInfos[i].getClassName(), vInfos[i].getVarName(), vInfos[i].getScope(), decl.getDescription()));
+							}
+						}
+
+						ValidationMessage[] messages = tei.validate(td);
+						if (messages != null && messages.length > 0) {
+							for (int i = 0; i < messages.length; i++) {
+								Object createdProblem = createValidationMessageProblem(document, customTag, messages[i].getMessage());
+								if (createdProblem != null) {
+									problems.add(createdProblem);
+								}
+							}
+						}
+					}
+				}
+				else {
+					Object createdProblem = createJSPProblem(document, customTag, IJSPProblem.TEIClassMisc, JSPCoreMessages.TaglibHelper_2, teiClassname, true);
+					if (createdProblem != null) {
+						problems.add(createdProblem);
+					}
+					// this is 3rd party code, need to catch all exceptions
+					if (DEBUG) {
+						Logger.log(Logger.WARNING, teiClassname + " is not a subclass of TaxExtraInfo"); //$NON-NLS-1$ 
+					}
+				}
+			}
+		}
+		catch (ClassNotFoundException e) {
+			//the class could not be found so add it to the cache
+			fNotFoundClasses.add(teiClassname);
+
+			Object createdProblem = createJSPProblem(document, customTag, IJSPProblem.TEIClassNotFound, JSPCoreMessages.TaglibHelper_0, teiClassname, true);
+			if (createdProblem != null) {
+				problems.add(createdProblem);
+			}
+			// TEI class wasn't on build path
+			if (DEBUG)
+				logException(teiClassname, e);
+		}
+		catch (InstantiationException e) {
+			Object createdProblem = createJSPProblem(document, customTag, IJSPProblem.TEIClassNotInstantiated, JSPCoreMessages.TaglibHelper_1, teiClassname, true);
+			if (createdProblem != null) {
+				problems.add(createdProblem);
+			}
+			// TEI class couldn't be instantiated
+			if (DEBUG)
+				logException(teiClassname, e);
+		}
+		catch (IllegalAccessException e) {
+			if (DEBUG)
+				logException(teiClassname, e);
+		}
+		// catch (ClassCastException e) {
+		// // TEI class wasn't really a subclass of TagExtraInfo
+		// if (DEBUG)
+		// logException(teiClassname, e);
+		// }
+		catch (Exception e) {
+			Object createdProblem = createJSPProblem(document, customTag, IJSPProblem.TEIClassMisc, JSPCoreMessages.TaglibHelper_2, teiClassname, true);
+			if (createdProblem != null) {
+				problems.add(createdProblem);
+			}
+			// this is 3rd party code, need to catch all exceptions
+			if (DEBUG)
+				logException(teiClassname, e);
+		}
+		catch (Error e) {
+			// this is 3rd party code, need to catch all errors
+			Object createdProblem = createJSPProblem(document, customTag, IJSPProblem.TEIClassNotInstantiated, JSPCoreMessages.TaglibHelper_1, teiClassname, true);
+			if (createdProblem != null) {
+				problems.add(createdProblem);
+			}
+			if (DEBUG)
+				logException(teiClassname, e);
+		}
+		finally {
+			// Thread.currentThread().setContextClassLoader(oldLoader);
+		}
+	}
+
+	/**
+	 * @param customTag
+	 * @param teiClass
+	 * @return
+	 */
+	private Object createJSPProblem(final IStructuredDocument document, final ITextRegionCollection customTag, final int problemID, final String messageKey, final String argument, boolean preferVars) {
+		final String tagname = customTag.getText(customTag.getRegions().get(1));
+
+		final int start;
+		if (customTag.getNumberOfRegions() > 1) {
+			start = customTag.getStartOffset(customTag.getRegions().get(1));
+		}
+		else {
+			start = customTag.getStartOffset();
+		}
+
+		final int end;
+		if (customTag.getNumberOfRegions() > 1) {
+			end = customTag.getTextEndOffset(customTag.getRegions().get(1)) - 1;
+		}
+		else {
+			end = customTag.getTextEndOffset() - 1;
+		}
+
+		final int line = document.getLineOfOffset(start);
+
+		final char[] name;
+		IPath location = TaglibController.getLocation(document);
+		if (location == null) {
+			name = new char[0];
+		}
+		else {
+			name = location.toString().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 name;
+			}
+
+			public String getMessage() {
+				return MessageFormat.format(messageKey, new String[]{tagname, argument});
+			}
+
+			public int getID() {
+				return problemID;
+			}
+
+			public String[] getArguments() {
+				return new String[0];
+			}
+
+			public int getEID() {
+				return problemID;
+			}
+		};
+	}
+
+	/**
+	 * @param customTag
+	 * @param validationMessage
+	 * @return
+	 */
+	private Object createValidationMessageProblem(final IStructuredDocument document, final ITextRegionCollection customTag, final String validationMessage) {
+		final int start;
+		if (customTag.getNumberOfRegions() > 3) {
+			start = customTag.getStartOffset(customTag.getRegions().get(2));
+		}
+		else if (customTag.getNumberOfRegions() > 1) {
+			start = customTag.getStartOffset(customTag.getRegions().get(1));
+		}
+		else {
+			start = customTag.getStartOffset();
+		}
+
+		final int end;
+		if (customTag.getNumberOfRegions() > 3) {
+			end = customTag.getTextEndOffset(customTag.getRegions().get(customTag.getNumberOfRegions() - 2)) - 1;
+		}
+		else if (customTag.getNumberOfRegions() > 1) {
+			end = customTag.getTextEndOffset(customTag.getRegions().get(1)) - 1;
+		}
+		else {
+			end = customTag.getTextEndOffset();
+		}
+
+		final int line = document.getLineOfOffset(start);
+
+		final char[] name;
+		IPath location = TaglibController.getLocation(document);
+		if (location == null) {
+			name = new char[0];
+		}
+		else {
+			name = location.toString().toCharArray();
+		}
+
+		return new IJSPProblem() {
+			public void setSourceStart(int sourceStart) {
+			}
+
+			public void setSourceLineNumber(int lineNumber) {
+			}
+
+			public void setSourceEnd(int sourceEnd) {
+			}
+
+			public boolean isWarning() {
+				return true;
+			}
+
+			public boolean isError() {
+				return false;
+			}
+
+			public int getSourceStart() {
+				return start;
+			}
+
+			public int getSourceLineNumber() {
+				return line;
+			}
+
+			public int getSourceEnd() {
+				return end;
+			}
+
+			public char[] getOriginatingFileName() {
+				return name;
+			}
+
+			public String getMessage() {
+				return validationMessage;
+			}
+
+			public int getID() {
+				return getEID();
+			}
+
+			public String[] getArguments() {
+				return new String[0];
+			}
+
+			public int getEID() {
+				return IJSPProblem.TEIValidationMessage;
+			}
+		};
+	}
+
+	/**
+	 * @param decl
+	 * @return the TagInfo for the TLDELementDeclaration if the declaration is
+	 *         valid, otherwise null
+	 */
+	private TagInfo getTagInfo(final TLDElementDeclaration decl, TagExtraInfo tei, String prefix, String uri) {
+
+		TagLibraryInfo libInfo = new TagLibraryInfoImpl(prefix, uri, decl);
+
+		CMNamedNodeMap attrs = decl.getAttributes();
+		TagAttributeInfo[] attrInfos = new TagAttributeInfo[attrs.getLength()];
+		TLDAttributeDeclaration attr = null;
+		String type = ""; //$NON-NLS-1$ 
+
+		// get tag attribute infos
+		for (int i = 0; i < attrs.getLength(); i++) {
+			attr = (TLDAttributeDeclaration) attrs.item(i);
+			type = attr.getType();
+			// default value for type is String
+			if (attr.getType() == null || attr.getType().equals("")) //$NON-NLS-1$ 
+				type = "java.lang.String"; //$NON-NLS-1$ 
+			attrInfos[i] = new TagAttributeInfo(attr.getAttrName(), attr.isRequired(), type, false);
+		}
+
+		String tagName = decl.getNodeName();
+		String tagClass = decl.getTagclass();
+		String bodyContent = decl.getBodycontent();
+		if (tagName != null && tagClass != null && bodyContent != null)
+			return new TagInfo(tagName, tagClass, bodyContent, decl.getInfo(), libInfo, tei, attrInfos);
+		return null;
+
+	}
+
+	/**
+	 * @param e
+	 */
+	private void logException(String teiClassname, Throwable e) {
+
+		String message = "teiClassname: ["; //$NON-NLS-1$ 
+		if (teiClassname != null)
+			message += teiClassname;
+		message += "]"; //$NON-NLS-1$
+		Logger.logException(message, e);
+	}
+
+	/**
+	 * Returns all attribute -> value pairs for the tag in a Hashtable.
+	 * 
+	 * @param customTag
+	 * @return
+	 */
+	private Hashtable extractTagData(ITextRegionCollection customTag) {
+		Hashtable tagDataTable = new Hashtable();
+		ITextRegionList regions = customTag.getRegions();
+		ITextRegion r = null;
+		String attrName = ""; //$NON-NLS-1$
+		String attrValue = ""; //$NON-NLS-1$
+		final int size = regions.size();
+		for (int i = 2; i < size; i++) {
+			r = regions.get(i);
+			// check if attr name
+			if (r.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) {
+				attrName = customTag.getText(r);
+				// check equals is next region
+				if (size > ++i) {
+					r = regions.get(i);
+					if (r.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_EQUALS && size > ++i) {
+						// get attr value
+						r = regions.get(i);
+						final String type = r.getType();
+						if (type == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
+							// attributes in our document have quotes, so we
+							// need to strip them
+							attrValue = StringUtils.stripQuotes(customTag.getText(r));
+							tagDataTable.put(attrName, attrValue);
+						}
+						else if (type == DOMJSPRegionContexts.JSP_TAG_ATTRIBUTE_VALUE_DQUOTE || type == DOMJSPRegionContexts.JSP_TAG_ATTRIBUTE_VALUE_SQUOTE) {
+							final StringBuffer buffer = new StringBuffer();
+							while (size > ++i && (r = regions.get(i)).getType() != type) {
+								buffer.append(customTag.getText(r));
+							}
+							tagDataTable.put(attrName, buffer.toString());
+						}
+					}
+				}
+			}
+		}
+
+		tagDataTable.put("jsp:id", customTag.getText(regions.get(1)) + "_" + customTag.getStartOffset()); //$NON-NLS-1$ 
+
+		return tagDataTable;
+	}
+
+	private ClassLoader getClassloader() {
+		if (fLoader == null) {
+			fLoader = new BuildPathClassLoader(this.getClass().getClassLoader(), fJavaProject);
+		}
+		return fLoader;
+	}
+
+	/**
+	 * @return Returns the fModelQuery.
+	 */
+	public ModelQuery getModelQuery(IDocument doc) {
+		IStructuredModel model = null;
+		ModelQuery mq = null;
+		try {
+			model = StructuredModelManager.getModelManager().getExistingModelForRead(doc);
+			mq = ModelQueryUtil.getModelQuery(model);
+		}
+		finally {
+			if (model != null)
+				model.releaseFromRead();
+		}
+		return mq;
+	}
+
+
+	/**
+	 * @return Returns the fFile.
+	 */
+	public IProject getProject() {
+
+		return fProject;
+	}
+
+	/**
+	 * @param file
+	 *            The fFile to set.
+	 */
+	public void setProject(IProject p) {
+		fProject = p;
+		IJavaProject javaProject = JavaCore.create(p);
+		if (javaProject.exists()) {
+			fJavaProject = javaProject;
+		}
+	}
+
+	private void validateTagClass(IStructuredDocument document, ITextRegionCollection customTag, TLDElementDeclaration decl, List problems) {
+		// skip if from a tag file
+		if (TLDElementDeclaration.SOURCE_TAG_FILE.equals(decl.getProperty(TLDElementDeclaration.TAG_SOURCE)) || fJavaProject == null) {
+			return;
+		}
+
+		String tagClassname = decl.getTagclass();
+		Object tagClass = null;
+		if (tagClassname != null && tagClassname.length() > 0 && fJavaProject.exists()) {
+			try {
+				tagClass = fJavaProject.findType(tagClassname);
+			}
+			catch (JavaModelException e) {
+				Logger.logException(e);
+			}
+		}
+		if (tagClass == null) {
+			Object createdProblem = createJSPProblem(document, customTag, IJSPProblem.TagClassNotFound, JSPCoreMessages.TaglibHelper_3, tagClassname, false);
+			if (createdProblem != null) {
+				problems.add(createdProblem);
+			}
+		}
+	}
+
+	/**
+	 * 
+	 */
+	public void dispose() {
+		fLoader = null;
+		fJavaProject = null;
+		fProject = null;
+		fNotFoundClasses = null;
+		fClassMap = null;
+		fMemoryListener.disconnect();
+		fMemoryListener = null;
+	}
+
+	public void invalidateClass(String className) {
+		fClassMap.remove(className);
+	}
+
+	/**
+	 * <p>A {@link AbstractMemoryListener} that clears the {@link #fNotFoundClasses} cache
+	 * whenever specific memory events are received.</p>
+	 * 
+	 * <p>Events:
+	 * <ul>
+	 * <li>{@link AbstractMemoryListener#SEV_NORMAL}</li>
+	 * <li>{@link AbstractMemoryListener#SEV_SERIOUS}</li>
+	 * <li>{@link AbstractMemoryListener#SEV_CRITICAL}</li>
+	 * </ul>
+	 * </p>
+	 */
+	private class MemoryListener extends AbstractMemoryListener {
+		/**
+		 * <p>Constructor causes this listener to listen for specific memory events.</p>
+		 * <p>Events:
+		 * <ul>
+		 * <li>{@link AbstractMemoryListener#SEV_NORMAL}</li>
+		 * <li>{@link AbstractMemoryListener#SEV_SERIOUS}</li>
+		 * <li>{@link AbstractMemoryListener#SEV_CRITICAL}</li>
+		 * </ul>
+		 * </p>
+		 */
+		MemoryListener() {
+			super(new String[] { SEV_NORMAL, SEV_SERIOUS, SEV_CRITICAL });
+		}
+
+		/**
+		 * On any memory event we handle clear out the project descriptions
+		 * 
+		 * @see org.eclipse.jst.jsp.core.internal.util.AbstractMemoryListener#handleMemoryEvent(org.osgi.service.event.Event)
+		 */
+		protected void handleMemoryEvent(Event event) {
+			/* if running low on memory then this cache can be cleared
+			 * and rebuilt at the expense of processing time
+			 */
+			fNotFoundClasses.clear();
+			fClassMap.clear();
+		}
+
+	}
+
+	class TagLibraryInfoImpl extends TagLibraryInfo {
+		TLDElementDeclaration decl;
+
+		TagLibraryInfoImpl(String prefix, String uri, TLDElementDeclaration decl){
+			super(prefix, uri);
+			this.decl = decl;
+		}
+
+		public String getURI() {
+			if (Platform.inDebugMode())
+				new NotImplementedException().printStackTrace();
+			return super.getURI();
+		}
+
+		public String getPrefixString() {
+			if (Platform.inDebugMode())
+				new NotImplementedException().printStackTrace();
+			return super.getPrefixString();
+		}
+
+		public String getShortName() {
+			return ((TLDDocument)decl.getOwnerDocument()).getShortname();
+		}
+
+		public String getReliableURN() {
+			return ((TLDDocument)decl.getOwnerDocument()).getUri();
+		}
+
+		public String getInfoString() {
+			return ((TLDDocument)decl.getOwnerDocument()).getInfo();
+		}
+
+		public String getRequiredVersion() {
+			return ((TLDDocument)decl.getOwnerDocument()).getJspversion();
+		}
+
+		public TagInfo[] getTags() {
+			if (Platform.inDebugMode())
+				new NotImplementedException().printStackTrace();
+			return super.getTags();
+		}
+
+		public TagFileInfo[] getTagFiles() {
+			if (Platform.inDebugMode())
+				new NotImplementedException().printStackTrace();
+			return super.getTagFiles();
+		}
+
+		public TagInfo getTag(String shortname) {
+			if (Platform.inDebugMode())
+				new NotImplementedException().printStackTrace();
+			return super.getTag(shortname);
+		}
+
+		public TagFileInfo getTagFile(String shortname) {
+			if (Platform.inDebugMode())
+				new NotImplementedException().printStackTrace();
+			return super.getTagFile(shortname);
+		}
+
+		public FunctionInfo[] getFunctions() {
+			if (Platform.inDebugMode())
+				new NotImplementedException().printStackTrace();
+			return super.getFunctions();
+		}
+
+		public FunctionInfo getFunction(String name) {
+			new NotImplementedException(name).printStackTrace();
+			return super.getFunction(name);
+		}
+
+		public TagLibraryInfo[] getTagLibraryInfos()  {
+			if (Platform.inDebugMode())
+				new NotImplementedException().printStackTrace();
+			return new TagLibraryInfo[] { this };
+		}
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/taglib/TaglibHelperCache.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/taglib/TaglibHelperCache.java
new file mode 100644
index 0000000..8c5eadf
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/taglib/TaglibHelperCache.java
@@ -0,0 +1,183 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.taglib;
+
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jst.jsp.core.internal.Logger;
+
+/**
+ * A simple cache for TaglibHelpers to avoid excessive creation of TaglibClassLoaders
+ * @author pavery
+ */
+class TaglibHelperCache {
+
+    private static final boolean DEBUG;
+    static {
+        String value = Platform.getDebugOption("org.eclipse.jst.jsp.core/debug/taglibvars"); //$NON-NLS-1$
+        DEBUG = value != null && value.equalsIgnoreCase("true"); //$NON-NLS-1$
+    }
+
+    /**
+     * An entry for the cache (projectPath string & TaglibHelper)
+     */
+    class Entry {
+        private TaglibHelper fHelper;
+        private String fProjectName;
+        
+        public Entry(String projectName, TaglibHelper helper) {
+            setProjectName(projectName);
+            setHelper(helper);
+        }
+        public TaglibHelper getHelper() {
+            return fHelper;
+        }
+        public void setHelper(TaglibHelper helper) {
+            fHelper = helper;
+        }
+        public String getProjectName() {
+            return fProjectName;
+        }
+        public void setProjectName(String projectName) {
+            fProjectName = projectName;
+        }
+        public String toString() {
+            return "Taglib Helper Entry [" + getProjectName() + "]"; //$NON-NLS-1$ //$NON-NLS-2$
+        }
+    }
+    
+    private List fHelpers;
+    // max size for the cache
+    private int MAX_SIZE;
+
+    /**
+     * Not intended to be large since underlying implmementation uses
+     * a List.
+     */
+    public TaglibHelperCache(int size) {
+        MAX_SIZE = size;
+        fHelpers = Collections.synchronizedList(new ArrayList(MAX_SIZE));
+    }
+    /**
+     * 
+     * @param projectPath
+     * @param f
+     * @param mq
+     * @return
+     */
+    public final synchronized TaglibHelper getHelper(IProject project) {
+        TaglibHelper helper = null;
+        Entry entry = null;
+        String projectName = project.getName();
+        int size = fHelpers.size();
+        // fist check for existing
+        for (int i=0; i<size; i++) {
+            entry = (Entry)fHelpers.get(i);
+            if(entry.getProjectName().equals(projectName)) {
+                // exists
+                helper = entry.getHelper();
+                // only move to front if it's not the first entry
+                if(i>0) {
+                    fHelpers.remove(entry);
+	                fHelpers.add(1, entry);
+	                if(DEBUG) {
+	                    Logger.log(Logger.INFO, "(->) TaglibHelperCache moved: " + entry + " to the front of the list"); //$NON-NLS-1$ //$NON-NLS-2$
+	                    printCacheContents();
+	                }
+                }
+                break;
+            }
+        }
+        // didn't exist
+        if(helper == null) {
+            helper = createNewHelper(projectName, project);
+        }
+        return helper;
+    }
+    
+    /**
+     * @param projectName
+     * @param f
+     * @param mq
+     * @return
+     */
+    private TaglibHelper createNewHelper(String projectName, IProject project) {
+
+        TaglibHelper helper;
+        // create
+        helper = new TaglibHelper(project);
+        Entry newEntry = new Entry(projectName, helper);
+        fHelpers.add(0, newEntry);
+        if(DEBUG) {
+        	Logger.log(Logger.INFO, "(+) TaglibHelperCache added: " + newEntry); //$NON-NLS-1$
+            printCacheContents();
+        }
+        if(fHelpers.size() > MAX_SIZE) {
+            // one too many, remove last
+        	Entry removed = (Entry) fHelpers.remove(fHelpers.size()-1);
+        	removed.getHelper().dispose();
+            if(DEBUG) {
+            	Logger.log(Logger.INFO, "(-) TaglibHelperCache removed: " + removed.getProjectName()); //$NON-NLS-1$
+                printCacheContents();
+            }
+        }
+        return helper;
+    }
+ 
+    public final synchronized void removeHelper(String projectName) {
+        Entry entry = null;
+        Iterator it = fHelpers.iterator();
+        while(it.hasNext()) {
+            entry = (Entry)it.next();
+            if(entry.getProjectName().equals(projectName)) {
+            	entry.getHelper().dispose();
+                fHelpers.remove(entry);
+                if(DEBUG) { 
+                    Logger.log(Logger.INFO, "(-) TaglibHelperCache removed: " + entry); //$NON-NLS-1$
+                    printCacheContents();
+                }
+                break;
+            }
+        }
+    }
+
+    public final synchronized void invalidate(String projectName, String className) {
+    	Entry entry = null;
+        Iterator it = fHelpers.iterator();
+        while(it.hasNext()) {
+            entry = (Entry)it.next();
+            if(entry.getProjectName().equals(projectName)) {
+            	entry.getHelper().invalidateClass(className);
+                if(DEBUG) { 
+                    Logger.log(Logger.INFO, "(-) TaglibHelperCache invalidated: " + className); //$NON-NLS-1$
+                    printCacheContents();
+                }
+                break;
+            }
+        }
+    }
+    private void printCacheContents() {
+        StringBuffer debugString = new StringBuffer();
+        debugString.append("\n-----------------------------------------------------------"); //$NON-NLS-1$
+        debugString.append("\ncache contents:"); //$NON-NLS-1$
+        for (int i=0; i<fHelpers.size(); i++)	
+        	debugString.append("\n -" + i + "- " + fHelpers.get(i)); //$NON-NLS-1$ //$NON-NLS-2$
+        debugString.append("\n-----------------------------------------------------------"); //$NON-NLS-1$
+        Logger.log(Logger.INFO, debugString.toString());
+    }
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/taglib/TaglibHelperManager.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/taglib/TaglibHelperManager.java
new file mode 100644
index 0000000..c0b26e0
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/taglib/TaglibHelperManager.java
@@ -0,0 +1,104 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.taglib;
+
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.jdt.core.ElementChangedEvent;
+import org.eclipse.jdt.core.IElementChangedListener;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IJavaElementDelta;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IType;
+
+/**
+ * Manages creation and caching (ordered MRU) of TaglibHelpers.
+ * Removes helpers when their classpath changes (so they are rebuilt).
+ * There is one helper per project (with a specific classpath entry).
+ * 
+ * @author pavery
+ */
+public class TaglibHelperManager implements IElementChangedListener {
+   
+
+    private static TaglibHelperManager instance = null;
+    // using a cache of just 3 loaders
+    private TaglibHelperCache fCache = new TaglibHelperCache(3);
+
+    private TaglibHelperManager() {
+        // use instance
+    }
+    public static synchronized TaglibHelperManager getInstance() {
+        if(instance == null)
+            instance = new TaglibHelperManager();
+        return instance;
+    }
+    
+    public TaglibHelper getTaglibHelper(IFile f) {
+        IProject p = f.getProject();
+        return getHelperFromCache(p);
+    }
+    
+    /**
+     * @param projectPath
+     */
+    private TaglibHelper getHelperFromCache(IProject project) {
+        return fCache.getHelper(project);
+    }
+    
+    /**
+     * Update classpath for appropriate loader.
+     * @see org.eclipse.jdt.core.IElementChangedListener#elementChanged(org.eclipse.jdt.core.ElementChangedEvent)
+     */
+	public void elementChanged(ElementChangedEvent event) {
+		// handle classpath changes
+		IJavaElementDelta delta = event.getDelta();
+		if (delta.getElement().getElementType() == IJavaElement.JAVA_MODEL) {
+			IJavaElementDelta[] changed = delta.getChangedChildren();
+			for (int i = 0; i < changed.length; i++) {
+				if ((changed[i].getFlags() & IJavaElementDelta.F_CLASSPATH_CHANGED) != 0 || (changed[i].getFlags() & IJavaElementDelta.F_REORDER) != 0 || (changed[i].getFlags() & IJavaElementDelta.F_RESOLVED_CLASSPATH_CHANGED) != 0 || (changed[i].getFlags() & IJavaElementDelta.F_PRIMARY_RESOURCE) != 0) {
+					IJavaElement proj = changed[i].getElement();
+					handleClasspathChange(changed, i, proj);
+				}
+			}
+		}
+		else if (delta.getElement().getElementType() == IJavaElement.COMPILATION_UNIT) {
+			IJavaElementDelta[] changed = delta.getChangedChildren();
+			for (int i = 0; i < changed.length; i++) {
+				if ((changed[i].getFlags() & IJavaElementDelta.F_SUPER_TYPES) != 0) {
+					IJavaElement element = changed[i].getElement();
+					handleSuperTypeChange(element);
+				}
+			}
+		}
+	}
+
+	private void handleSuperTypeChange(IJavaElement element) {
+		IJavaProject project = element.getJavaProject();
+		if (element instanceof IType) {
+			fCache.invalidate(project.getProject().getName(), ((IType) element).getFullyQualifiedName());
+		}
+	}
+    
+    /**
+     * @param changed
+     * @param i
+     * @param proj
+     */
+    private void handleClasspathChange(IJavaElementDelta[] changed, int i, IJavaElement proj) {
+        if (proj.getElementType() == IJavaElement.JAVA_PROJECT) {
+			String projectName = ((IJavaProject) proj).getProject().getName();
+			fCache.removeHelper(projectName);
+		}
+    }
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/taglib/TaglibVariable.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/taglib/TaglibVariable.java
new file mode 100644
index 0000000..ab91ce9
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/taglib/TaglibVariable.java
@@ -0,0 +1,167 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 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
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.taglib;
+
+import javax.servlet.jsp.tagext.VariableInfo;
+
+import org.eclipse.wst.sse.core.utils.StringUtils;
+
+/**
+ * Contains info about a TaglibVariable: classname, variablename.
+ */
+public class TaglibVariable {
+
+	private String fVarClass = null;
+	private String fVarName = null;
+	private int fScope;
+	private String fDescription;
+
+	/** fixed end-of-line value */
+	private final String ENDL = "\n"; //$NON-NLS-1$
+
+	private final static String AT_END = "AT_END";
+	private final static String AT_BEGIN = "AT_BEGIN";
+	private final static String NESTED = "NESTED";
+
+	public static final int M_PRIVATE = 1;
+	public static final int M_NONE = 0;
+
+	/**
+	 * 
+	 */
+	public TaglibVariable(String varClass, String varName, int scope) {
+		setVarClass(varClass);
+		setVarName(varName);
+		setScope(scope);
+	}
+
+	public TaglibVariable(String varClass, String varName, String scope) {
+		setVarClass(varClass);
+		setVarName(varName);
+		setScope(scope);
+	}
+
+	public TaglibVariable(String varClass, String varName, String scope, String description) {
+		setVarClass(varClass);
+		setVarName(varName);
+		setScope(scope);
+		setDescription(description);
+	}
+
+	TaglibVariable(String varClass, String varName, int scope, String description) {
+		setVarClass(varClass);
+		setVarName(varName);
+		setScope(scope);
+		setDescription(description);
+	}
+
+	/**
+	 * @return Returns the fVarClass.
+	 */
+	public final String getVarClass() {
+		return fVarClass;
+	}
+
+	/**
+	 * @param varClass
+	 *            The fVarClass to set.
+	 */
+	public final void setVarClass(String varClass) {
+		fVarClass = varClass;
+	}
+
+	/**
+	 * @return Returns the fVarName.
+	 */
+	public final String getVarName() {
+		return fVarName;
+	}
+
+	/**
+	 * @param varName
+	 *            The fVarName to set.
+	 */
+	public final void setVarName(String varName) {
+		fVarName = varName;
+	}
+
+	/**
+	 * Convenience method.
+	 * 
+	 * @return
+	 */
+	public final String getDeclarationString() {
+		return getDeclarationString(false, M_NONE);
+	}
+
+	/**
+	 * Convenience method.
+	 * 
+	 * @return
+	 */
+	public final String getDeclarationString(boolean includeDoc, int style) {
+		String declaration = null;
+		/*
+		 * no description for now --JDT would need to show it for local
+		 * variables and ILocalVariable has no "doc range"
+		 */
+		if (includeDoc && getDescription() != null) {
+			if (style == M_PRIVATE) {
+				declaration = "/** " + ENDL + StringUtils.replace(getDescription(), "*/", "*\\/") + ENDL + " */ " + ENDL + "private " + getVarClass() + " " + getVarName() + " = (" + getVarClass() + ") pageContext.getAttribute(\"" + getVarName() + "\");" + ENDL; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ //$NON-NLS-9$
+			}
+			else {
+				declaration = "/** " + ENDL + StringUtils.replace(getDescription(), "*/", "*\\/") + ENDL + " */ " + ENDL + getVarClass() + " " + getVarName() + " = (" + getVarClass() + ") pageContext.getAttribute(\"" + getVarName() + "\");" + ENDL; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
+			}
+		}
+		else {
+			if (style == M_PRIVATE) {
+				declaration = "private " + getVarClass() + " " + getVarName() + " = (" + getVarClass() + ") pageContext.getAttribute(\"" + getVarName() + "\");" + ENDL; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
+			}
+			else {
+				declaration = getVarClass() + " " + getVarName() + " = (" + getVarClass() + ") pageContext.getAttribute(\"" + getVarName() + "\");" + ENDL; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+			}
+		}
+		return declaration;
+	}
+
+	public String getDescription() {
+		return fDescription;
+	}
+
+	public int getScope() {
+		return fScope;
+	}
+
+	public void setScope(int scope) {
+		fScope = scope;
+	}
+
+	public void setScope(String scopeString) {
+		int scope = VariableInfo.AT_BEGIN;
+
+		String trimmedScope = scopeString.trim();
+		if (NESTED.equals(trimmedScope)) {
+			scope = VariableInfo.NESTED;
+		}
+		else if (AT_BEGIN.equals(trimmedScope)) {
+			scope = VariableInfo.AT_BEGIN;
+		}
+		else if (AT_END.equals(trimmedScope)) {
+			scope = VariableInfo.AT_END;
+		}
+
+		fScope = scope;
+	}
+
+	public void setDescription(String description) {
+		fDescription = description;
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/tasks/JSPFileTaskScanner.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/tasks/JSPFileTaskScanner.java
new file mode 100644
index 0000000..51f5faf
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/tasks/JSPFileTaskScanner.java
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.tasks;
+
+import org.eclipse.jst.jsp.core.internal.regions.DOMJSPRegionContexts;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+import org.eclipse.wst.xml.core.internal.tasks.XMLFileTaskScanner;
+
+public class JSPFileTaskScanner extends XMLFileTaskScanner {
+	protected boolean isCommentRegion(IStructuredDocumentRegion region, ITextRegion textRegion) {
+		return super.isCommentRegion(region, textRegion) || textRegion.getType().equals(DOMJSPRegionContexts.JSP_COMMENT_TEXT);
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/text/StructuredTextPartitionerForJSP.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/text/StructuredTextPartitionerForJSP.java
new file mode 100644
index 0000000..836557c
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/text/StructuredTextPartitionerForJSP.java
@@ -0,0 +1,470 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.text;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentPartitioner;
+import org.eclipse.jst.jsp.core.internal.encoding.JSPDocumentHeadContentDetector;
+import org.eclipse.jst.jsp.core.internal.parser.JSPSourceParser;
+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.text.IJSPPartitions;
+import org.eclipse.wst.html.core.internal.text.StructuredTextPartitionerForHTML;
+import org.eclipse.wst.sse.core.internal.ltk.parser.RegionParser;
+import org.eclipse.wst.sse.core.internal.ltk.parser.TagMarker;
+import org.eclipse.wst.sse.core.internal.parser.ForeignRegion;
+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.IStructuredTextPartitioner;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+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.internal.text.rules.IStructuredTypedRegion;
+import org.eclipse.wst.sse.core.internal.text.rules.StructuredTextPartitioner;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+import org.eclipse.wst.xml.core.internal.text.rules.StructuredTextPartitionerForXML;
+
+public class StructuredTextPartitionerForJSP extends StructuredTextPartitioner {
+	// for compatibility with v5.1.0, we'll reuse ST_JSP_DIRECTIVE for action
+	// tags
+	private final static boolean fEnableJSPActionPartitions = true;
+	// list of valid JSP 1.2 tag and action names
+	private static List fJSPActionTagNames = null;
+	private static final String HTML_MIME_TYPE = "text/html"; //$NON-NLS-1$
+	private static final String XHTML_MIME_TYPE = "text/xhtml"; //$NON-NLS-1$
+	private static final String XML_MIME_TYPE = "text/xml"; //$NON-NLS-1$
+	private static final String VND_WAP_WML = "text/vnd.wap.wml"; //$NON-NLS-1$
+
+	private final static String[] fConfiguredContentTypes = new String[]{IJSPPartitions.JSP_DEFAULT, IJSPPartitions.JSP_DEFAULT_EL, IJSPPartitions.JSP_DEFAULT_EL2, IJSPPartitions.JSP_DIRECTIVE, IJSPPartitions.JSP_CONTENT_DELIMITER, IJSPPartitions.JSP_CONTENT_JAVA, IJSPPartitions.JSP_CONTENT_JAVASCRIPT, IJSPPartitions.JSP_COMMENT};
+
+	/**
+	 * @return
+	 */
+	public static String[] getConfiguredContentTypes() {
+		return fConfiguredContentTypes;
+	}
+
+	private IStructuredTextPartitioner fEmbeddedPartitioner = null;
+	/*
+	 * Save last taglib prefix that was checked (see isAction()) for better
+	 * performance
+	 */
+	private String fLastCheckedPrefix = null;
+
+	/**
+	 * Assume language=java by default ... client, such as
+	 * PageDirectiveAdapter, must set language of document partitioner,
+	 * if/when it changes.
+	 */
+	private String fLanguage = "java"; //$NON-NLS-1$
+
+	/**
+	 * Constructor for JSPDocumentPartioner.
+	 */
+	public StructuredTextPartitionerForJSP() {
+		super();
+		if (fJSPActionTagNames == null) {
+			fJSPActionTagNames = new ArrayList(); // uses .equals() for
+			// contains()
+			fJSPActionTagNames.add(JSP12Namespace.ElementName.DECLARATION);
+			// fJSPActionTagNames.add(JSP12Namespace.ElementName.DIRECTIVE_INCLUDE);
+			// fJSPActionTagNames.add(JSP12Namespace.ElementName.DIRECTIVE_PAGE);
+			// fJSPActionTagNames.add(JSP12Namespace.ElementName.DIRECTIVE_TAGLIB);
+			fJSPActionTagNames.add(JSP12Namespace.ElementName.EXPRESSION);
+			fJSPActionTagNames.add(JSP12Namespace.ElementName.FALLBACK);
+			fJSPActionTagNames.add(JSP12Namespace.ElementName.FORWARD);
+			fJSPActionTagNames.add(JSP12Namespace.ElementName.GETPROPERTY);
+			fJSPActionTagNames.add(JSP12Namespace.ElementName.INCLUDE);
+			fJSPActionTagNames.add(JSP12Namespace.ElementName.PARAM);
+			fJSPActionTagNames.add(JSP12Namespace.ElementName.PARAMS);
+			fJSPActionTagNames.add(JSP12Namespace.ElementName.PLUGIN);
+			// fJSPActionTagNames.add(JSP12Namespace.ElementName.ROOT);
+			fJSPActionTagNames.add(JSP12Namespace.ElementName.SCRIPTLET);
+			fJSPActionTagNames.add(JSP12Namespace.ElementName.SETPROPERTY);
+			fJSPActionTagNames.add(JSP12Namespace.ElementName.TEXT);
+			fJSPActionTagNames.add(JSP12Namespace.ElementName.USEBEAN);
+		}
+	}
+
+	/**
+	 * @see org.eclipse.jface.text.IDocumentPartitioner#connect(org.eclipse.jface.text.IDocument)
+	 */
+	public void connect(IDocument document) {
+		super.connect(document);
+		fSupportedTypes = null;
+	}
+
+	private IStructuredTextPartitioner createStructuredTextPartitioner(IStructuredDocument structuredDocument) {
+		IStructuredTextPartitioner result = null;
+		// this same detector should underly content describer, to have consistent results
+		JSPDocumentHeadContentDetector jspHeadContentDetector = new JSPDocumentHeadContentDetector();
+		jspHeadContentDetector.set(structuredDocument);
+		String contentType = null;
+		try {
+			contentType = jspHeadContentDetector.getContentType();
+			// if XHTML or WML, that trumps what is in the page directive
+			if (jspHeadContentDetector.isXHTML() || jspHeadContentDetector.isWML()) {
+				contentType = "text/html";
+		}
+		}
+		catch (IOException e) {
+			// impossible in this context, since working with document stream
+			throw new Error(e);
+		}
+		// null or empty, treat as "default"
+		if (contentType == null || contentType.length() == 0) {
+			contentType = "text/html"; //$NON-NLS-1$
+		}
+		// we currently only have two ... eventually should
+		// make or tie-in to existing registry.
+		if (contentType.equalsIgnoreCase(HTML_MIME_TYPE) || contentType.equalsIgnoreCase(VND_WAP_WML)) {
+			result = new StructuredTextPartitionerForHTML();
+			result.connect(structuredDocument);
+		}
+		else if (contentType.equalsIgnoreCase(XHTML_MIME_TYPE)) {
+			result = new StructuredTextPartitionerForHTML();
+			result.connect(structuredDocument);
+		}
+		else if (contentType.equalsIgnoreCase(XML_MIME_TYPE) || contentType.endsWith("+xml")) { //$NON-NLS-1$
+			result = new StructuredTextPartitionerForXML();
+			result.connect(structuredDocument);
+		}
+		else {
+			result = new StructuredTextPartitioner();
+			result.connect(structuredDocument);
+		}
+		return result;
+
+	}
+
+	/**
+	 * @see org.eclipse.jface.text.IDocumentPartitioner#disconnect()
+	 */
+	public void disconnect() {
+		if (fEmbeddedPartitioner != null) {
+			fEmbeddedPartitioner.disconnect();
+			// https://w3.opensource.ibm.com/bugzilla/show_bug.cgi?id=4909
+			/**
+			 * force recreation when reconnected
+			 */
+			fEmbeddedPartitioner = null;
+		}
+		// super.disconnect should come at end, since it (may) set
+		// structuredDocument to null
+		super.disconnect();
+	}
+
+	public String getDefaultPartitionType() {
+		return getEmbeddedPartitioner().getDefaultPartitionType();
+	}
+
+	/**
+	 * Returns the embeddedPartitioner.
+	 * 
+	 * @return IStructuredTextPartitioner
+	 */
+	public IStructuredTextPartitioner getEmbeddedPartitioner() {
+		if (fEmbeddedPartitioner == null) {
+			fEmbeddedPartitioner = createStructuredTextPartitioner(fStructuredDocument);
+			fEmbeddedPartitioner.connect(fStructuredDocument);
+		}
+
+		return fEmbeddedPartitioner;
+	}
+
+	/**
+	 * Returns the language.
+	 * 
+	 * @return String
+	 */
+	public String getLanguage() {
+		return fLanguage;
+	}
+
+	private List getLocalLegalContentTypes() {
+		List types = new ArrayList();
+		Object[] configuredTypes = getConfiguredContentTypes();
+		for (int i = 0; i < configuredTypes.length; i++)
+			types.add(configuredTypes[i]);
+		return types;
+	}
+
+	private String getParentName(IStructuredDocumentRegion sdRegion) {
+		String result = "UNKNOWN"; //$NON-NLS-1$
+		while (sdRegion != null && isValidJspActionRegionType(sdRegion.getType()))
+			sdRegion = sdRegion.getPrevious();
+
+		if (sdRegion != null) {
+			ITextRegionList regions = sdRegion.getRegions();
+			// only find parent names from a start tag
+			if (regions.size() > 1) {
+				ITextRegion r = regions.get(1);
+				if (regions.get(0).getType().equals(DOMRegionContext.XML_TAG_OPEN) && r.getType().equals(DOMRegionContext.XML_TAG_NAME)) {
+					result = sdRegion.getText(r);
+				}
+			}
+		}
+		return result;
+	}
+
+	protected String getPartitionType(ForeignRegion region, int offset) {
+		return getEmbeddedPartitioner().getPartitionType(region, offset);
+	}
+
+
+	public String getPartitionType(ITextRegion region, int offset) {
+		String result = null;
+		final String region_type = region.getType();
+		if (region_type == DOMJSPRegionContexts.JSP_CONTENT) {
+			result = getPartitionTypeForDocumentLanguage();
+		}
+		else if (region_type == DOMJSPRegionContexts.JSP_COMMENT_TEXT || region_type == DOMJSPRegionContexts.JSP_COMMENT_OPEN || region_type == DOMJSPRegionContexts.JSP_COMMENT_CLOSE)
+			result = IJSPPartitions.JSP_COMMENT;
+		else if (region_type == DOMJSPRegionContexts.JSP_DIRECTIVE_NAME || region_type == DOMJSPRegionContexts.JSP_DIRECTIVE_OPEN || region_type == DOMJSPRegionContexts.JSP_DIRECTIVE_CLOSE)
+			result = IJSPPartitions.JSP_DIRECTIVE;
+		else if (region_type == DOMJSPRegionContexts.JSP_CLOSE || region_type == DOMJSPRegionContexts.JSP_SCRIPTLET_OPEN || region_type == DOMJSPRegionContexts.JSP_EXPRESSION_OPEN || region_type == DOMJSPRegionContexts.JSP_DECLARATION_OPEN)
+			result = IJSPPartitions.JSP_CONTENT_DELIMITER;
+		else if (region_type == DOMJSPRegionContexts.JSP_ROOT_TAG_NAME)
+			result = IJSPPartitions.JSP_DEFAULT;
+		else if (region_type == DOMJSPRegionContexts.JSP_EL_OPEN || region_type == DOMJSPRegionContexts.JSP_EL_CONTENT || region_type == DOMJSPRegionContexts.JSP_EL_CLOSE || region_type == DOMJSPRegionContexts.JSP_EL_DQUOTE || region_type == DOMJSPRegionContexts.JSP_EL_SQUOTE || region_type == DOMJSPRegionContexts.JSP_EL_QUOTED_CONTENT)
+			result = IJSPPartitions.JSP_DEFAULT_EL;
+		else if (region_type == DOMJSPRegionContexts.JSP_VBL_OPEN || region_type == DOMJSPRegionContexts.JSP_VBL_CONTENT || region_type == DOMJSPRegionContexts.JSP_VBL_CLOSE || region_type == DOMJSPRegionContexts.JSP_VBL_DQUOTE || region_type == DOMJSPRegionContexts.JSP_VBL_SQUOTE || region_type == DOMJSPRegionContexts.JSP_VBL_QUOTED_CONTENT)
+			result = IJSPPartitions.JSP_DEFAULT_EL2;
+		else if (region_type == DOMJSPRegionContexts.XML_TAG_ATTRIBUTE_VALUE_DQUOTE || region_type == DOMJSPRegionContexts.XML_TAG_ATTRIBUTE_VALUE_SQUOTE)
+			result = IJSPPartitions.JSP_DEFAULT;
+		else if (region_type == DOMRegionContext.XML_CDATA_TEXT) {
+			// BUG131463: possibly between <jsp:scriptlet>, <jsp:expression>,
+			// <jsp:declaration>
+			IStructuredDocumentRegion sdRegion = this.fStructuredDocument.getRegionAtCharacterOffset(offset);
+			if (isJspJavaActionName(getParentName(sdRegion)))
+				result = getPartitionTypeForDocumentLanguage();
+			else
+				result = getEmbeddedPartitioner().getPartitionType(region, offset);
+		}
+		else if (region_type == DOMRegionContext.XML_CONTENT) {
+			// possibly between <jsp:scriptlet>, <jsp:expression>,
+			// <jsp:declaration>
+			IStructuredDocumentRegion sdRegion = this.fStructuredDocument.getRegionAtCharacterOffset(offset);
+			if (isJspJavaActionName(getParentName(sdRegion)))
+				result = getPartitionTypeForDocumentLanguage();
+			else
+				result = getDefaultPartitionType();
+		}
+//		else if (region_type == DOMRegionContext.BLOCK_TEXT) {
+			// possibly between <jsp:scriptlet>, <jsp:expression>,
+			// <jsp:declaration>
+//			IStructuredDocumentRegion sdRegion = this.fStructuredDocument.getRegionAtCharacterOffset(offset);
+//			if (isJspJavaActionName(getParentName(sdRegion)))
+//				result = getPartitionTypeForDocumentLanguage();
+//			else
+//				result = getDefaultPartitionType();
+//		}
+		else {
+			result = getEmbeddedPartitioner().getPartitionType(region, offset);
+		}
+		return result;
+	}
+
+	public String getPartitionTypeBetween(IStructuredDocumentRegion previousNode, IStructuredDocumentRegion nextNode) {
+		return getEmbeddedPartitioner().getPartitionTypeBetween(previousNode, nextNode);
+	}
+
+	private String getPartitionTypeForDocumentLanguage() {
+		String result;
+		if (fLanguage == null || fLanguage.equalsIgnoreCase("java")) { //$NON-NLS-1$
+			result = IJSPPartitions.JSP_CONTENT_JAVA;
+		}
+		else if (fLanguage.equalsIgnoreCase("javascript")) { //$NON-NLS-1$
+			result = IJSPPartitions.JSP_CONTENT_JAVASCRIPT;
+		}
+		else {
+			result = IJSPPartitions.JSP_SCRIPT_PREFIX + getLanguage().toUpperCase(Locale.ENGLISH);
+		}
+		return result;
+	}
+
+	protected void initLegalContentTypes() {
+		List combinedTypes = getLocalLegalContentTypes();
+		if (getEmbeddedPartitioner() != null) {
+			String[] moreTypes = getEmbeddedPartitioner().getLegalContentTypes();
+			for (int i = 0; i < moreTypes.length; i++)
+				combinedTypes.add(moreTypes[i]);
+		}
+		fSupportedTypes = new String[0];
+		combinedTypes.toArray(fSupportedTypes);
+	}
+
+	/**
+	 * @param sdRegion
+	 * @param offset
+	 * @return
+	 */
+	private boolean isAction(IStructuredDocumentRegion sdRegion, int offset) {
+		if (!sdRegion.getType().equals(DOMRegionContext.XML_TAG_NAME))
+			return false;
+		/*
+		 * shouldn't get a tag name region type unless a tag name region
+		 * exists at [1]
+		 */
+		ITextRegion tagNameRegion = sdRegion.getRegions().get(1);
+		String tagName = sdRegion.getText(tagNameRegion);
+
+		RegionParser parser = fStructuredDocument.getParser();
+		if (parser instanceof JSPSourceParser) {
+			if (tagName.equals(fLastCheckedPrefix))
+				return true;
+			List fCustomActionPrefixes = ((JSPSourceParser) parser).getNestablePrefixes();
+			for (int i = 0; i < fCustomActionPrefixes.size(); i++)
+				if (tagName.startsWith(((TagMarker) fCustomActionPrefixes.get(i)).getTagName())) {
+					fLastCheckedPrefix = ((TagMarker) fCustomActionPrefixes.get(i)).getTagName();
+					return true;
+				}
+		}
+		return false;
+	}
+
+	protected boolean isDocumentRegionBasedPartition(IStructuredDocumentRegion sdRegion, ITextRegion containedChildRegion, int offset) {
+		String documentRegionContext = sdRegion.getType();
+		if (containedChildRegion != null) {
+			if (documentRegionContext.equals(DOMJSPRegionContexts.JSP_DIRECTIVE_NAME) || documentRegionContext.equals(DOMJSPRegionContexts.JSP_ROOT_TAG_NAME)) {
+				setInternalPartition(offset, containedChildRegion.getLength(), IJSPPartitions.JSP_DIRECTIVE);
+				return true;
+			}
+			
+			//if is a JSP custom tag but not a JSP_EL region
+			if (fEnableJSPActionPartitions && !isELRegion(containedChildRegion) && isAction(sdRegion, offset) && !(containedChildRegion instanceof ITextRegionContainer) ) {
+				setInternalPartition(offset, containedChildRegion.getLength(), IJSPPartitions.JSP_DIRECTIVE);
+				return true;
+			}
+		}
+		return super.isDocumentRegionBasedPartition(sdRegion, containedChildRegion, offset);
+	}
+
+	/**
+	 * @param possibleJspJavaAction
+	 * @return
+	 */
+	private boolean isJspJavaActionName(String possibleJspJavaAction) {
+		return possibleJspJavaAction.equals(JSP11Namespace.ElementName.SCRIPTLET) || possibleJspJavaAction.equals(JSP11Namespace.ElementName.EXPRESSION) || possibleJspJavaAction.equals(JSP11Namespace.ElementName.DECLARATION);
+	}
+
+	private boolean isValidJspActionRegionType(String type) {
+		// true for anything that can be within <jsp:scriptlet>,
+		// <jsp:expression>, <jsp:declaration>
+		return type == DOMRegionContext.XML_CONTENT || type == DOMRegionContext.BLOCK_TEXT || type == DOMRegionContext.XML_CDATA_OPEN || type == DOMRegionContext.XML_CDATA_TEXT || type == DOMRegionContext.XML_CDATA_CLOSE;
+	}
+
+	public IDocumentPartitioner newInstance() {
+		StructuredTextPartitionerForJSP instance = new StructuredTextPartitionerForJSP();
+		instance.setEmbeddedPartitioner(createStructuredTextPartitioner(fStructuredDocument));
+		instance.setLanguage(fLanguage);
+		return instance;
+	}
+
+	/**
+	 * Sets the embeddedPartitioner.
+	 * 
+	 * @param embeddedPartitioner
+	 *            The embeddedPartitioner to set
+	 */
+	public void setEmbeddedPartitioner(IStructuredTextPartitioner embeddedPartitioner) {
+		// https://w3.opensource.ibm.com/bugzilla/show_bug.cgi?id=4909
+		/**
+		 * manage connected state of embedded partitioner
+		 */
+		if (fEmbeddedPartitioner != null && fStructuredDocument != null) {
+			fEmbeddedPartitioner.disconnect();
+		}
+
+		this.fEmbeddedPartitioner = embeddedPartitioner;
+
+		if (fEmbeddedPartitioner != null && fStructuredDocument != null) {
+			fEmbeddedPartitioner.connect(fStructuredDocument);
+		}
+	}
+
+	protected void setInternalPartition(int offset, int length, String type) {
+		// TODO: need to carry this single instance idea further to be
+		// complete,
+		// but hopefully this will be less garbage than before (especially for
+		// HTML, XML,
+		// naturally!)
+		IStructuredTypedRegion region = getEmbeddedPartitioner().createPartition(offset, length, type);
+		super.setInternalPartition(region.getOffset(), region.getLength(), region.getType());
+
+	}
+
+	/**
+	 * Sets the language.
+	 * 
+	 * @param language
+	 *            The language to set
+	 */
+	public void setLanguage(String language) {
+		this.fLanguage = language;
+	}
+	
+	/**
+	 * @param region decide if this region is an EL region
+	 * @return <code>true</code> if the given <code>region</code> is a EL region,
+	 * <code>false</code> otherwise.
+	 */
+	private boolean isELRegion(ITextRegion region) {
+		String type = region.getType();
+		return
+			type == DOMJSPRegionContexts.JSP_EL_CLOSE ||
+			type == DOMJSPRegionContexts.JSP_EL_CONTENT ||
+			type == DOMJSPRegionContexts.JSP_EL_DQUOTE ||
+			type == DOMJSPRegionContexts.JSP_EL_OPEN ||
+			type == DOMJSPRegionContexts.JSP_EL_QUOTED_CONTENT ||
+			type == DOMJSPRegionContexts.JSP_EL_SQUOTE ||
+			type == DOMJSPRegionContexts.JSP_VBL_CLOSE ||
+			type == DOMJSPRegionContexts.JSP_VBL_CONTENT ||
+			type == DOMJSPRegionContexts.JSP_VBL_DQUOTE ||
+			type == DOMJSPRegionContexts.JSP_VBL_OPEN ||
+			type == DOMJSPRegionContexts.JSP_VBL_QUOTED_CONTENT ||
+			type == DOMJSPRegionContexts.JSP_VBL_SQUOTE;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.sse.core.internal.text.rules.StructuredTextPartitioner#doParserSpecificCheck(int, boolean, org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion, org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion, org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion, org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion)
+	 */
+	protected boolean doParserSpecificCheck(int offset, boolean partitionFound, IStructuredDocumentRegion sdRegion, IStructuredDocumentRegion previousStructuredDocumentRegion, ITextRegion next, ITextRegion previousStart) {
+		if (previousStart != null && previousStart.getType() == DOMRegionContext.XML_TAG_OPEN && next.getType() == DOMRegionContext.XML_END_TAG_OPEN) {
+			ITextRegion previousName = previousStructuredDocumentRegion.getRegionAtCharacterOffset(previousStructuredDocumentRegion.getEndOffset(previousStart));
+			ITextRegion nextName = sdRegion.getRegionAtCharacterOffset(sdRegion.getEndOffset(next));
+			if (previousName != null && nextName != null && previousName.getType() == DOMRegionContext.XML_TAG_NAME && nextName.getType() == DOMRegionContext.XML_TAG_NAME) {
+				setInternalPartition(offset, 0, getPartitionTypeBetween(previousStructuredDocumentRegion, sdRegion));
+				partitionFound = true;
+			}
+		}
+		return partitionFound;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.sse.core.internal.text.rules.StructuredTextPartitioner#getParserSpecificPreviousRegion(org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion)
+	 */
+	protected IStructuredDocumentRegion getParserSpecificPreviousRegion(IStructuredDocumentRegion currentRegion) {
+		if (currentRegion == null)
+			return null;
+		do {
+			currentRegion = currentRegion.getPrevious();
+		} while (currentRegion != null && currentRegion.getType().equals(DOMRegionContext.BLOCK_TEXT));
+
+		return currentRegion;
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/util/CommonXML.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/util/CommonXML.java
new file mode 100644
index 0000000..3db336c
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/util/CommonXML.java
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.util;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.TransformerFactoryConfigurationError;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import org.eclipse.jst.jsp.core.internal.Logger;
+import org.w3c.dom.Document;
+
+public class CommonXML {
+
+	public synchronized static DocumentBuilder getDocumentBuilder() {
+		DocumentBuilder result = null;
+		try {
+			result = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+		}
+		catch (ParserConfigurationException e) {
+			Logger.logException(e);
+		}
+		return result;
+	}
+
+	public synchronized static DocumentBuilder getDocumentBuilder(boolean validating) {
+		DocumentBuilder result = null;
+		try {
+			DocumentBuilderFactory instance = DocumentBuilderFactory.newInstance();
+			instance.setValidating(validating);
+			instance.setExpandEntityReferences(false);
+			instance.setCoalescing(true);
+			result = instance.newDocumentBuilder();
+		}
+		catch (ParserConfigurationException e) {
+			Logger.logException(e);
+		}
+		return result;
+	}
+
+	public static void serialize(Document document, OutputStream ostream) throws IOException {
+		Source domSource = new DOMSource(document);
+		try {
+			Transformer serializer = TransformerFactory.newInstance().newTransformer();
+			try {
+				serializer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
+				serializer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4"); //$NON-NLS-1$ //$NON-NLS-2$
+				serializer.setOutputProperty(OutputKeys.ENCODING, "UTF-16"); //$NON-NLS-1$
+			}
+			catch (IllegalArgumentException e) {
+				// unsupported properties
+			}
+			serializer.transform(domSource, new StreamResult(ostream));
+		}
+		catch (TransformerConfigurationException e) {
+			throw new IOException(e.getMessage());
+		}
+		catch (TransformerFactoryConfigurationError e) {
+			throw new IOException(e.getMessage());
+		}
+		catch (TransformerException e) {
+			throw new IOException(e.getMessage());
+		}
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/util/DocumentProvider.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/util/DocumentProvider.java
new file mode 100644
index 0000000..2c9c28c
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/util/DocumentProvider.java
@@ -0,0 +1,476 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.util;
+
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.net.URLConnection;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.FactoryConfigurationError;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.eclipse.jst.jsp.core.internal.Logger;
+import org.eclipse.wst.sse.core.internal.util.JarUtilities;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+import com.ibm.icu.util.StringTokenizer;
+
+/**
+ * An XML Creator/Reader/Writer that 1) Ignores any DocumentType Nodes found
+ * within the document (as well as any entities) 2) Ignores any
+ * errors/exceptions from Xerces when loading a document 3) Can load Documents
+ * from within a .JAR file (***read-only***)
+ */
+
+public class DocumentProvider {
+	private Document document = null;
+	private ErrorHandler errorHandler = null;
+	private String fBaseReference;
+	private String fileName = null;
+	private boolean fValidating = false;
+	private InputStream inputStream = null;
+	private String jarFileName = null;
+	private EntityResolver resolver = null;
+
+	private Node rootElement = null;
+	private String rootElementName = null;
+
+	public DocumentProvider() {
+		super();
+	}
+
+	private String _getFileName() {
+		if (inputStream != null)
+			return null;
+		else if (isJAR()) {
+			return getJarFileName();
+		}
+		return getFileName();
+	}
+
+	private Document _getParsedDocumentDOM2() {
+		Document result = null;
+
+		InputStream is = null;
+		try {
+			DocumentBuilder builder = getDocumentBuilder();
+			// DOMParser parser = new DOMParser();
+			// parser.setFeature("http://apache.org/xml/features/continue-after-fatal-error",
+			// false);//$NON-NLS-1$
+			// parser.setFeature("http://apache.org/xml/features/nonvalidating/load-dtd-grammar",
+			// false);//$NON-NLS-1$
+			// parser.setErrorHandler(getNullErrorHandler());
+			// parser.setEntityResolver(getNullEntityResolver());
+			// is = getInputStream();
+			builder.setEntityResolver(getEntityResolver());
+			builder.setErrorHandler(getNullErrorHandler());
+			is = getInputStream();
+			if (is != null)
+				result = builder.parse(is, getBaseReference());
+		}
+		catch (SAXException e) {
+			// parsing exception, notify the user?
+			Logger.log(Logger.WARNING_DEBUG, "SAXException while reading descriptor " + _getFileName() + " " + e); //$NON-NLS-1$ //$NON-NLS-2$
+		}
+		catch (FileNotFoundException e) {
+			// NOT an "exceptional case"; do not Log
+		}
+		catch (IOException e) {
+			Logger.log(Logger.WARNING_DEBUG, "IOException while reading descriptor " + _getFileName() + " " + e); //$NON-NLS-1$ //$NON-NLS-2$
+		}
+		finally {
+			if (is != null) {
+				try {
+					is.close();
+				}
+				catch (Exception e) {
+					// what can be done?
+				}
+			}
+		}
+		return result;
+	}
+
+	/**
+	 * @return
+	 */
+	public String getBaseReference() {
+		return fBaseReference;
+	}
+
+	/**
+	 * 
+	 * @return Document
+	 */
+	public Document getDocument() {
+		return getDocument(true);
+	}
+
+	public Document getDocument(boolean createEmptyOnFailure) {
+		if (document == null)
+			load(createEmptyOnFailure);
+		return document;
+	}
+
+	DocumentBuilder fDocumentBuilder = null;
+	
+	private DocumentBuilder getDocumentBuilder() {
+		if (fDocumentBuilder == null) {
+			fDocumentBuilder = CommonXML.getDocumentBuilder(isValidating());
+		}
+		return fDocumentBuilder;
+	}
+
+	private DOMImplementation getDomImplementation() {
+		DocumentBuilder builder = null;
+		try {
+			builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+		}
+		catch (ParserConfigurationException e1) {
+			Logger.logException(e1);
+		}
+		catch (FactoryConfigurationError e1) {
+			Logger.logException(e1);
+		}
+		DOMImplementation impl = builder.getDOMImplementation();
+		return impl;
+	}
+
+	/*************************************************************************
+	 * Takes a single string of the form "a/b/c" and ensures that that
+	 * structure exists below the head element, down through 'c', and returns
+	 * a <em>single</em> element 'c'. For multiple elements (such as
+	 * multiple &lt;macro&gt; elements contained within a single
+	 * &lt;macros&gt; element, full DOM access is required for searching and
+	 * child element manipulation.
+	 ************************************************************************/
+	public Element getElement(String name) {
+		Element result = null;
+		if (document == null)
+			load(false);
+		if (document != null) {
+			result = (Element) getNode(getRootElement(), name);
+		}
+		return result;
+	}
+
+	/**
+	 * Returns an EntityResolver that won't try to load and resolve ANY
+	 * entities
+	 */
+	private EntityResolver getEntityResolver() {
+		if (resolver == null) {
+			resolver = new EntityResolver() {
+				public InputSource resolveEntity(String publicID, String systemID) throws SAXException, IOException {
+					InputSource result = null;
+					if (isValidating()) {
+						try {
+							URL spec = new URL("file://" + getBaseReference()); //$NON-NLS-1$
+							URL url = new URL(spec, systemID);
+							if (url.getProtocol().startsWith("file:")) { //$NON-NLS-1$
+								URLConnection connection = url.openConnection();
+								result = new InputSource(systemID != null ? systemID : "/_" + toString()); //$NON-NLS-1$
+								result.setPublicId(publicID);
+								result.setByteStream(connection.getInputStream());
+							}
+						}
+						catch (Exception e) {
+							result = null;
+						}
+					}
+
+					if (result == null) {
+						result = new InputSource(new ByteArrayInputStream(new byte[0]));
+						result.setPublicId(publicID);
+						result.setSystemId(systemID != null ? systemID : "/_" + getClass().getName()); //$NON-NLS-1$
+					}
+					return result;
+				}
+			};
+		}
+		return resolver;
+	}
+
+	/**
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getFileName() {
+		return fileName;
+	}
+
+	/**
+	 * Returns and input stream to use as the source of the Document 1) from
+	 * an InputStream set on this instance 2) from a JAR file with the given
+	 * entry name 3) from a normal file
+	 * 
+	 * @return InputStream
+	 */
+	public InputStream getInputStream() throws FileNotFoundException {
+		if (inputStream != null)
+			return inputStream;
+		else if (isJAR()) {
+			return JarUtilities.getInputStream(getJarFileName(), getFileName());
+		}
+		else {
+			return new BufferedInputStream(new FileInputStream(getFileName()));
+		}
+	}
+
+	/**
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getJarFileName() {
+		return jarFileName;
+	}
+
+	private Node getNamedChild(Node parent, String childName) {
+		if (parent == null) {
+			return null;
+		}
+		NodeList childList = parent.getChildNodes();
+		for (int i = 0; i < childList.getLength(); i++) {
+			if (childList.item(i).getNodeName().equals(childName))
+				return childList.item(i);
+		}
+		return null;
+	}
+
+	private Document getNewDocument() {
+		Document result = null;
+		try {
+			result = getDomImplementation().createDocument("http://www.w3.org/XML/1998/namespace", getRootElementName(), null); //$NON-NLS-1$
+			NodeList children = result.getChildNodes();
+			for (int i = 0; i < children.getLength(); i++) {
+				result.removeChild(children.item(i));
+			}
+			// we're going through this effort to avoid a NS element
+			Element settings = result.createElementNS("http://www.w3.org/XML/1998/namespace", getRootElementName()); //$NON-NLS-1$
+			result.appendChild(settings);
+			return result;
+		}
+		catch (DOMException e) {
+			Logger.logException(e);
+		}
+		return null;
+	}
+
+	/*************************************************************************
+	 * Takes a single string of the form "a/b/c" and ensures that that
+	 * structure exists below the head element, down through 'c', and returns
+	 * the element 'c'.
+	 ************************************************************************/
+	private Node getNode(Node node, String name) {
+		StringTokenizer tokenizer = new StringTokenizer(name, "/"); //$NON-NLS-1$
+		String token = null;
+		while (tokenizer.hasMoreTokens()) {
+			token = tokenizer.nextToken();
+			if (getNamedChild(node, token) == null)
+				node.appendChild(document.createElement(token));
+			node = getNamedChild(node, token);
+		}
+		return node;
+	}
+
+	/**
+	 * Returns an ErrorHandler that will not stop the parser on reported
+	 * errors
+	 */
+	private ErrorHandler getNullErrorHandler() {
+		if (errorHandler == null) {
+			errorHandler = new ErrorHandler() {
+				public void error(SAXParseException exception) throws SAXException {
+					Logger.log(Logger.WARNING, "SAXParseException with " + fBaseReference + "/" + getJarFileName() + "/" + getFileName() + " (error) while reading descriptor: " + exception.getMessage()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+				}
+
+				public void fatalError(SAXParseException exception) throws SAXException {
+					Logger.log(Logger.WARNING, "SAXParseException with " + fBaseReference + "/" + getJarFileName() + "/" + getFileName() + " (fatalError) while reading descriptor: " + exception.getMessage()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+				}
+
+				public void warning(SAXParseException exception) throws SAXException {
+					Logger.log(Logger.WARNING, "SAXParseException with " + fBaseReference + "/" + getJarFileName() + "/" + getFileName() + " (warning) while reading descriptor: " + exception.getMessage()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+				}
+			};
+		}
+		return errorHandler;
+	}
+
+	private Document getParsedDocument() {
+		Document result = null;
+		if (inputStream == null) {
+			File existenceTester = null;
+			if (isJAR())
+				existenceTester = new File(getJarFileName());
+			else
+				existenceTester = new File(getFileName());
+			if (!existenceTester.exists())
+				return null;
+		}
+
+		result = _getParsedDocumentDOM2();
+
+		return result;
+
+	}
+
+	/**
+	 * Returns the root Element of the current document
+	 * 
+	 * @return org.w3c.dom.Element
+	 */
+	public Node getRootElement() {
+		return getRootElement(getDocument());
+	}
+
+	/**
+	 * Returns the/a root Element for the current document
+	 * 
+	 * @return org.w3c.dom.Element
+	 */
+	private Node getRootElement(Document doc) {
+		if (doc == null)
+			return null;
+		if (doc.getDocumentElement() != null)
+			return doc.getDocumentElement();
+		try {
+			Element newRootElement = doc.createElement(getRootElementName());
+			doc.appendChild(newRootElement);
+			return newRootElement;
+		}
+		catch (DOMException e) {
+			Logger.logException(e);
+		}
+		return null;
+	}
+
+	/**
+	 * 
+	 * @return java.lang.String
+	 */
+	public java.lang.String getRootElementName() {
+		return rootElementName;
+	}
+
+	private boolean isJAR() {
+		return getJarFileName() != null;
+	}
+
+	/**
+	 * @return
+	 */
+	public boolean isValidating() {
+		return fValidating;
+	}
+
+	void load(boolean createEmptyOnFailure) {
+		// rootElementName and fileName are expected to be defined at this
+		// point
+		document = getParsedDocument();
+		if (document != null) {
+			if (rootElementName != null)
+				rootElement = getRootElement(document);
+			else
+				rootElement = document.getDocumentElement();
+		}
+
+		if (document == null || rootElement == null) {
+			if (createEmptyOnFailure) {
+				document = getNewDocument();
+				if (document != null) {
+					NodeList children = document.getChildNodes();
+					for (int i = 0; i < children.getLength(); i++) {
+						if (children.item(i).getNodeType() == Node.ELEMENT_NODE && children.item(i).getNodeName().equals(getRootElementName()))
+							rootElement = children.item(i);
+					}
+					if (rootElement == null) {
+						for (int i = 0; i < children.getLength(); i++) {
+							if (children.item(i).getNodeType() == Node.ELEMENT_NODE) {
+								rootElement = children.item(i);
+								break;
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+
+	/**
+	 * @param string
+	 */
+	public void setBaseReference(String string) {
+		fBaseReference = string;
+	}
+
+	/**
+	 * 
+	 * @param newFileName
+	 *            java.lang.String
+	 */
+	public void setFileName(java.lang.String newFileName) {
+		fileName = newFileName;
+	}
+
+	/**
+	 * Sets the inputStream for which to provide a Document.
+	 * 
+	 * @param inputStream
+	 *            The inputStream to set
+	 */
+	public void setInputStream(InputStream iStream) {
+		this.inputStream = iStream;
+	}
+
+	/**
+	 * 
+	 * @param newJarFileName
+	 *            java.lang.String
+	 */
+	public void setJarFileName(java.lang.String newJarFileName) {
+		jarFileName = newJarFileName;
+	}
+
+	/**
+	 * 
+	 * @param newRootElementName
+	 *            java.lang.String
+	 */
+	public void setRootElementName(java.lang.String newRootElementName) {
+		rootElementName = newRootElementName;
+	}
+
+	/**
+	 * @param b
+	 */
+	public void setValidating(boolean b) {
+		fValidating = b;
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/util/FacetModuleCoreSupport.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/util/FacetModuleCoreSupport.java
new file mode 100644
index 0000000..33b8c64
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/util/FacetModuleCoreSupport.java
@@ -0,0 +1,235 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 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
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.util;
+
+import org.eclipse.core.filebuffers.FileBuffers;
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+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.IPath;
+import org.eclipse.core.runtime.Path;
+
+/**
+ * This class encapsulates any used Module Core and Facets APIs along with
+ * fallbacks for use on non-compliant projects and when those services are not
+ * available at runtime.
+ * 
+ * Because ModuleCore API calls can result in locks needing to be acquired,
+ * none of these methods should be called while other thread locks have
+ * already been acquired.
+ */
+public final class FacetModuleCoreSupport {
+	static final boolean _dump_NCDFE = false;
+	private static final String WEB_INF = "WEB-INF"; //$NON-NLS-1$
+	private static final IPath WEB_INF_PATH = new Path(WEB_INF);
+
+	static final float DEFAULT_SERVLET_VERSION = 3f;
+
+	/**
+	 * @param project
+	 * @return the computed IPath to the "root" of the web contents, either from facet knowledge or hueristics, or null if one can not be determined
+	 */
+	public static IPath computeWebContentRootPath(IPath path) {
+		IPath root = null;
+		try {
+			root = FacetModuleCoreSupportDelegate.getWebContentRootPath(ResourcesPlugin.getWorkspace().getRoot().getProject(path.segment(0)));
+		}
+		catch (NoClassDefFoundError e) {
+			if (_dump_NCDFE)
+				e.printStackTrace();
+		}
+		if(root == null) {
+			/*
+			 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=213245
+			 * 
+			 * NPE in JSPTaglibDirectiveContentAssistProcessor with
+			 * non-faceted project
+			 */
+			root = getLocalRoot(path);
+		}
+		return root;
+	}
+
+	/**
+	 * @param project
+	 * @return -1 if the project does not have the JST Web facet, the version
+	 *         number of it otherwise
+	 * @throws org.eclipse.core.runtime.CoreException
+	 */
+	public static float getDynamicWebProjectVersion(IProject project) {
+		// In the absence of any facet information, assume the highest level
+		float version = DEFAULT_SERVLET_VERSION;
+		try {
+			version = FacetModuleCoreSupportDelegate.getDynamicWebProjectVersion(project);
+		}
+		catch (NoClassDefFoundError e) {
+			if (_dump_NCDFE)
+				e.printStackTrace();
+		}
+		return version;
+	}
+
+	/**
+	 * @param project
+	 * @return the IPath to the "root" of the web contents
+	 */
+	public static IPath getWebContentRootPath(IProject project) {
+		if (project == null)
+			return null;
+
+		IPath path = null;
+		try {
+			path = FacetModuleCoreSupportDelegate.getWebContentRootPath(project);
+		}
+		catch (NoClassDefFoundError e) {
+			if (_dump_NCDFE)
+				e.printStackTrace();
+		}
+		return path;
+	}
+
+	/**
+	 * @param path -
+	 *            the full path to a resource within the workspace
+	 * @return - the runtime path of the resource if one exists, null
+	 *         otherwise
+	 */
+	public static IPath getRuntimePath(IPath path) {
+		IPath result = null;
+		try {
+			result = FacetModuleCoreSupportDelegate.getRuntimePath(path);
+		}
+		catch (NoClassDefFoundError e) {
+			if (_dump_NCDFE)
+				e.printStackTrace();
+		}
+		if (result == null) {
+			IPath root = getLocalRoot(path);
+			result = path.removeFirstSegments(root.segmentCount()).makeAbsolute();
+		}
+		return result;
+	}
+
+	/**
+	 * @param project
+	 * @return
+	 * @throws CoreException
+	 */
+	public static boolean isDynamicWebProject(IProject project) {
+		if (project == null)
+			return false;
+		
+		try {
+			return FacetModuleCoreSupportDelegate.isDynamicWebProject(project);
+		}
+		catch (NoClassDefFoundError e) {
+			if (_dump_NCDFE)
+				e.printStackTrace();
+		}
+		return true;
+	}
+
+	/**
+	 * @param basePath -
+	 *            the full path to a resource within the workspace
+	 * @param reference -
+	 *            the reference string to resolve
+	 * @return - the full path within the workspace that corresponds to the
+	 *         given reference according to the virtual pathing support
+	 */
+	public static IPath resolve(IPath basePath, String reference) {
+		IPath resolvedPath = null;
+		try {
+			resolvedPath = FacetModuleCoreSupportDelegate.resolve(basePath, reference);
+		}
+		catch (NoClassDefFoundError e) {
+			if (_dump_NCDFE)
+				e.printStackTrace();
+		}
+
+		if (resolvedPath == null) {
+			IPath rootPath = getLocalRoot(basePath);
+			if (reference.startsWith(Path.ROOT.toString())) {
+				resolvedPath = rootPath.append(reference);
+			}
+			else {
+				resolvedPath = basePath.removeLastSegments(1).append(reference);
+			}
+		}
+
+		return resolvedPath;
+	}
+
+	/**
+	 * @param basePath
+	 * @return the applicable Web context root path, if one exists
+	 */
+	private static IPath getLocalRoot(IPath basePath) {
+		IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
+
+		// existing workspace resources - this is the 93% case
+		IResource file = FileBuffers.getWorkspaceFileAtLocation(basePath);
+
+		// Try the base path as a folder first
+		if (file == null && basePath.segmentCount() > 1) {
+			file = workspaceRoot.getFolder(basePath);
+		}
+		// If not a folder, then try base path as a file
+		if (file != null && !file.exists() && basePath.segmentCount() > 1) {
+			file = workspaceRoot.getFile(basePath);
+		}
+
+		if (file == null && basePath.segmentCount() == 1) {
+			file = workspaceRoot.getProject(basePath.segment(0));
+		}
+
+		if (file == null) {
+			/*
+			 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=116529
+			 * 
+			 * This method produces a less accurate result, but doesn't
+			 * require that the file exist yet.
+			 */
+			IFile[] files = ResourcesPlugin.getWorkspace().getRoot().findFilesForLocation(basePath);
+			if (files.length > 0)
+				file = files[0];
+		}
+
+		while (file != null) {
+			/**
+			 * Treat any parent folder with a WEB-INF subfolder as a web-app
+			 * root
+			 */
+			IContainer folder = null;
+			if ((file.getType() & IResource.FOLDER) != 0) {
+				folder = (IContainer) file;
+			}
+			else {
+				folder = file.getParent();
+			}
+			// getFolder on a workspace root must use a full path, skip
+			if (folder != null && (folder.getType() & IResource.ROOT) == 0) {
+				IFolder webinf = folder.getFolder(WEB_INF_PATH);
+				if (webinf != null && webinf.exists()) {
+					return folder.getFullPath();
+				}
+			}
+			file = file.getParent();
+		}
+
+		return basePath.uptoSegment(1);
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/util/FacetModuleCoreSupportDelegate.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/util/FacetModuleCoreSupportDelegate.java
new file mode 100644
index 0000000..56b748d
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/util/FacetModuleCoreSupportDelegate.java
@@ -0,0 +1,208 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.util;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jst.jsp.core.internal.Logger;
+import org.eclipse.wst.common.componentcore.ComponentCore;
+import org.eclipse.wst.common.componentcore.ModuleCoreNature;
+import org.eclipse.wst.common.componentcore.resources.IVirtualComponent;
+import org.eclipse.wst.common.componentcore.resources.IVirtualFile;
+import org.eclipse.wst.common.componentcore.resources.IVirtualFolder;
+import org.eclipse.wst.common.componentcore.resources.IVirtualResource;
+import org.eclipse.wst.common.project.facet.core.IFacetedProject;
+import org.eclipse.wst.common.project.facet.core.IProjectFacet;
+import org.eclipse.wst.common.project.facet.core.ProjectFacetsManager;
+
+/**
+ * Wrapper class for all Facet-related calls. If the Facet or ModuleCore
+ * bundles are not available, this class will not load, or if it does, its
+ * methods will cause NoClassDefFoundErrors. This allows us to
+ * compartmentalize the dependencies.
+ * 
+ */
+final class FacetModuleCoreSupportDelegate {
+	private static final String SLASH = "/";
+
+	/**
+	 * Copied to avoid unneeded extra dependency (plus it's unclear why the
+	 * value is in that plug-in).
+	 * 
+	 * @see org.eclipse.wst.common.componentcore.internal.util.IModuleConstants.JST_WEB_MODULE
+	 */
+	private final static String JST_WEB_MODULE = "jst.web"; //$NON-NLS-1$
+	/**
+	 * @param project
+	 * @return -1 if the project does not have the JST Web facet, the version
+	 *         number of it otherwise
+	 * @throws CoreException
+	 */
+	static float getDynamicWebProjectVersion(IProject project) {
+		if (project == null)
+			return FacetModuleCoreSupport.DEFAULT_SERVLET_VERSION;
+
+		// In the absence of any facet information, assume the highest level
+		float version = FacetModuleCoreSupport.DEFAULT_SERVLET_VERSION;
+		try {
+			IFacetedProject faceted = ProjectFacetsManager.create(project);
+			if (faceted != null && ProjectFacetsManager.isProjectFacetDefined(JST_WEB_MODULE)) {
+				IProjectFacet webModuleFacet = ProjectFacetsManager.getProjectFacet(JST_WEB_MODULE);
+				if (faceted.hasProjectFacet(webModuleFacet)) {
+					version = Float.parseFloat(faceted.getInstalledVersion(webModuleFacet).getVersionString());
+				}
+			}
+		}
+		catch (NumberFormatException e) {
+			Logger.logException(e);
+		}
+		catch (CoreException e) {
+			Logger.logException(e);
+		}
+		return version;
+	}
+
+	/**
+	 * @param path -
+	 *            the full path to a resource within the workspace
+	 * @return - the runtime path of the resource if one exists, null
+	 *         otherwise
+	 */
+	static IPath getRuntimePath(IPath path) {
+		if (path == null)
+			return null;
+
+		IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(path.segment(0));
+
+		if (!ModuleCoreNature.isFlexibleProject(project))
+			return null;
+
+		IVirtualResource[] virtualResources = ComponentCore.createResources(ResourcesPlugin.getWorkspace().getRoot().getFile(path));
+		if (virtualResources != null && virtualResources.length > 0) {
+			return virtualResources[0].getRuntimePath();
+		}
+		return null;
+	}
+
+	/**
+	 * @param project
+	 * @return the IPath to the "root" of the web contents
+	 */
+	static IPath getWebContentRootPath(IProject project) {
+		if (project == null)
+			return null;
+
+		if (!ModuleCoreNature.isFlexibleProject(project))
+			return null;
+
+		IPath path = null;
+		IVirtualComponent component = ComponentCore.createComponent(project);
+		if (component != null && component.exists()) {
+			path = component.getRootFolder().getWorkspaceRelativePath();
+		}
+		return path;
+	}
+
+	/**
+	 * @param project
+	 * @return
+	 * @throws CoreException
+	 */
+	static boolean isDynamicWebProject(IProject project) {
+		if (project == null)
+			return false;
+		
+		try {
+			if (ProjectFacetsManager.isProjectFacetDefined(JST_WEB_MODULE)) {
+				IFacetedProject faceted = ProjectFacetsManager.create(project);
+				IProjectFacet webModuleFacet = ProjectFacetsManager.getProjectFacet(JST_WEB_MODULE);
+				if (faceted != null && faceted.hasProjectFacet(webModuleFacet)) {
+					return true;
+				}
+			}
+		}
+		catch (CoreException e) {
+			Logger.logException(e);
+		}
+		return false;
+	}
+
+	/**
+	 * @param basePath -
+	 *            the full path to a resource within the workspace
+	 * @param reference -
+	 *            the reference string to resolve
+	 * @return - the full path within the workspace that corresponds to the
+	 *         given reference according to the virtual pathing support
+	 */
+	static IPath resolve(IPath basePath, String reference) {
+		if (reference == null || basePath == null || basePath.segmentCount() == 0)
+			return null;
+
+		IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(basePath.segment(0));
+
+		if (!ModuleCoreNature.isFlexibleProject(project))
+			return null;
+
+		if (basePath.segmentCount() > 1) {
+			IResource baseResource = ResourcesPlugin.getWorkspace().getRoot().findMember(basePath);
+			if (baseResource != null) {
+				IVirtualResource[] virtualResources = ComponentCore.createResources(baseResource);
+				for (int i = 0; i < virtualResources.length; i++) {
+					IPath referenceRuntimePath = null;
+					if (reference.startsWith(SLASH)) {
+						referenceRuntimePath = new Path(reference);
+					}
+					else {
+						IPath baseRuntimePath = virtualResources[i].getRuntimePath();
+						referenceRuntimePath = baseRuntimePath.removeLastSegments(1).append(reference);
+					}
+					
+					IVirtualFile virtualFile = ComponentCore.createFile(project, referenceRuntimePath);
+					if (virtualFile != null && virtualFile.exists()) {
+						IFile[] underlyingFiles = virtualFile.getUnderlyingFiles();
+						for (int j = 0; j < underlyingFiles.length; j++) {
+							if (underlyingFiles[j].getProject().equals(project) && underlyingFiles[j].isAccessible()) {
+								return underlyingFiles[j].getFullPath();
+							}
+
+						}
+					}
+					else {
+						// http://bugs.eclipse.org/338751 
+						IVirtualFolder virtualFolder = ComponentCore.createFolder(project, referenceRuntimePath);
+						if (virtualFolder != null && virtualFolder.exists()) {
+							IContainer[] underlyingFolders = virtualFolder.getUnderlyingFolders();
+							for (int j = 0; j < underlyingFolders.length; j++) {
+								if (underlyingFolders[j].getProject().equals(project) && underlyingFolders[j].isAccessible()) {
+									return underlyingFolders[j].getFullPath();
+								}
+							}
+						}
+					}
+				}
+			}
+		}
+		else {
+			IVirtualFile virtualFile = ComponentCore.createFile(project, new Path(reference));
+			if (virtualFile != null && virtualFile.exists()) {
+				return virtualFile.getUnderlyingFile().getFullPath();
+			}
+		}
+		return null;
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/util/FileContentCache.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/util/FileContentCache.java
new file mode 100644
index 0000000..5a2de58
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/util/FileContentCache.java
@@ -0,0 +1,245 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 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
+ *     
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.util;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.lang.ref.Reference;
+import java.lang.ref.SoftReference;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.eclipse.core.filebuffers.FileBuffers;
+import org.eclipse.core.filebuffers.ITextFileBuffer;
+import org.eclipse.core.filebuffers.LocationKind;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.core.runtime.content.IContentDescription;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jst.jsp.core.internal.Logger;
+import org.eclipse.wst.sse.core.internal.util.Debug;
+
+public class FileContentCache {
+	private static class CacheEntry {
+		String contents;
+		long modificationStamp = IResource.NULL_STAMP;
+		IPath path;
+
+		CacheEntry(IPath path) {
+			this.path = path;
+			modificationStamp = getModificationStamp(path);
+			contents = readContents(path);
+		}
+
+		private IFile getFile(IPath path) {
+			if (path.segmentCount() > 1) {
+				return ResourcesPlugin.getWorkspace().getRoot().getFile(path);
+			}
+			return null;
+		}
+
+		boolean isStale() {
+			if (modificationStamp == IResource.NULL_STAMP) {
+				return true;
+			}
+			long newStamp = getModificationStamp(path);
+			return newStamp > modificationStamp;
+		}
+
+		private String detectCharset(IFile file) {
+			if (file.getType() == IResource.FILE && file.isAccessible()) {
+				IContentDescription d = null;
+				try {
+					// optimized description lookup, might not succeed
+					d = file.getContentDescription();
+					if (d != null)
+						return d.getCharset();
+				}
+				catch (CoreException e) {
+					// should not be possible given the accessible and file
+					// type
+					// check above
+				}
+				InputStream contents = null;
+				try {
+					contents = file.getContents();
+					IContentDescription description = Platform.getContentTypeManager().getDescriptionFor(contents, file.getName(), new QualifiedName[]{IContentDescription.CHARSET});
+					if (description != null) {
+						return description.getCharset();
+					}
+				}
+				catch (IOException e) {
+					// will try to cleanup in finally
+				}
+				catch (CoreException e) {
+					// out of sync
+				}
+				finally {
+					if (contents != null) {
+						try {
+							contents.close();
+						}
+						catch (Exception e) {
+							// not sure how to recover at this point
+						}
+					}
+				}
+			}
+			return ResourcesPlugin.getEncoding();
+		}
+
+		private long getModificationStamp(IPath filePath) {
+			IFile f = getFile(filePath);
+			if (f != null && f.isAccessible()) {
+				return f.getModificationStamp();
+			}
+			File file = filePath.toFile();
+			if (file.exists())
+				return file.lastModified();
+			return IResource.NULL_STAMP;
+		}
+
+		private String readContents(IPath filePath) {
+			if (DEBUG)
+				System.out.println("readContents:" + filePath);
+			StringBuffer s = new StringBuffer();
+			InputStream is = null;
+			try {
+				IFile f = getFile(filePath);
+				if (f != null && f.isAccessible()) {
+					String charset = detectCharset(f);
+					if (charset == null) {
+						charset = ResourcesPlugin.getEncoding();
+					}
+					is = f.getContents();
+					Reader reader = new InputStreamReader(is, charset);
+					char[] readBuffer = new char[8092];
+					int n = reader.read(readBuffer);
+					while (n > 0) {
+						s.append(readBuffer, 0, n);
+						n = reader.read(readBuffer);
+					}
+				}
+			}
+			catch (CoreException e) {
+				// out of sync
+			}
+			catch (Exception e) {
+				if (Debug.debugStructuredDocument) {
+					Logger.logException(e);
+				}
+			}
+			finally {
+				try {
+					if (is != null) {
+						is.close();
+					}
+				}
+				catch (Exception e) {
+					// nothing to do
+				}
+			}
+			if (is == null) {
+				try {
+					FileBuffers.getTextFileBufferManager().connect(filePath, LocationKind.LOCATION, new NullProgressMonitor());
+					ITextFileBuffer buffer = FileBuffers.getTextFileBufferManager().getTextFileBuffer(filePath, LocationKind.LOCATION);
+					if (buffer != null) {
+						s.append(buffer.getDocument().get());
+					}
+				}
+				catch (CoreException e) {
+					// nothing to do
+					Logger.logException(e);
+				}
+				finally {
+					try {
+						FileBuffers.getTextFileBufferManager().disconnect(filePath, LocationKind.LOCATION, new NullProgressMonitor());
+					}
+					catch (CoreException e) {
+						Logger.logException(e);
+					}
+				}
+			}
+			return s.toString();
+		}
+
+	}
+
+	static final boolean DEBUG = false;
+
+	static FileContentCache instance = new FileContentCache();
+
+	public static FileContentCache getInstance() {
+		return instance;
+	}
+
+	private HashMap fContentMap;
+
+	private FileContentCache() {
+		super();
+		fContentMap = new HashMap();
+	}
+
+	private void cleanup() {
+		synchronized (fContentMap) {
+			Iterator iterator = fContentMap.entrySet().iterator();
+			while (iterator.hasNext()) {
+				Map.Entry entry = (Map.Entry) iterator.next();
+				if (entry.getValue() != null && ((Reference) entry.getValue()).get() == null) {
+					iterator.remove();
+				}
+			}
+		}
+	}
+
+	public String getContents(IPath filePath) {
+		if (DEBUG)
+			System.out.println("getContents:" + filePath);
+		
+		// use an text file buffer if one is already open
+		ITextFileBuffer existingBuffer = FileBuffers.getTextFileBufferManager().getTextFileBuffer(filePath, LocationKind.IFILE);
+		if (existingBuffer != null) {
+			IDocument document = existingBuffer.getDocument();
+			if (document != null) {
+				return document.get();
+			}
+		}
+		
+		CacheEntry entry = null;
+		Object o = fContentMap.get(filePath);
+		if (o instanceof Reference) {
+			entry = (CacheEntry) ((Reference) o).get();
+		}
+		if (entry == null || entry.isStale()) {
+			if (DEBUG && entry != null && entry.isStale())
+				System.out.println("stale contents:" + filePath);
+			entry = new CacheEntry(filePath);
+			synchronized (fContentMap) {
+				fContentMap.put(filePath, new SoftReference(entry));
+			}
+		}
+		cleanup();
+		return entry.contents;
+	}
+
+
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/util/ZeroStructuredDocumentRegion.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/util/ZeroStructuredDocumentRegion.java
new file mode 100644
index 0000000..0772450
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/util/ZeroStructuredDocumentRegion.java
@@ -0,0 +1,290 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.util;
+
+import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentEvent;
+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.ITextRegionContainer;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList;
+import org.eclipse.wst.sse.core.internal.text.TextRegionListImpl;
+
+
+public class ZeroStructuredDocumentRegion implements IStructuredDocumentRegion {
+	private int length = 0;
+
+	private int offset = 0;
+	private IStructuredDocument fParentDocument;
+
+	/**
+	 */
+	public ZeroStructuredDocumentRegion(IStructuredDocument document, int start) {
+		super();
+		fParentDocument = document;
+		offset = start;
+	}
+
+	public void addRegion(ITextRegion aRegion) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	public void adjust(int i) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+
+	}
+
+	public void adjustLength(int i) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+
+	}
+
+	public void adjustStart(int i) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+
+	}
+
+	public void adjustTextLength(int i) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+
+	}
+
+	public boolean containsOffset(int i) {
+		return offset <= i && i < getEndOffset();
+	}
+
+	public boolean containsOffset(ITextRegion region, int i) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	public void equatePositions(ITextRegion region) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+
+	}
+
+	public ITextRegion getDeepestRegionAtCharacterOffset(int offset) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	public int getEnd() {
+		return offset + length;
+	}
+
+	public int getEndOffset() {
+		return getEnd();
+	}
+
+	public int getEndOffset(ITextRegion containedRegion) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	public ITextRegion getFirstRegion() {
+		return null;
+	}
+
+	public String getFullText() {
+		return getText();
+	}
+
+	public String getFullText(ITextRegion aRegion) {
+		return getText();
+	}
+
+	/**
+	 */
+	public String getFullText(String context) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	public ITextRegion getLastRegion() {
+		return null;
+	}
+
+	public int getLength() {
+		return this.length;
+	}
+
+	public IStructuredDocumentRegion getNext() {
+		return getParentDocument().getFirstStructuredDocumentRegion();
+	}
+
+	public int getNumberOfRegions() {
+		return 0;
+	}
+
+	int getOffset() {
+		return offset;
+	}
+
+	/**
+	 */
+	public ITextRegionContainer getParent() {
+		return null;
+	}
+
+	public IStructuredDocument getParentDocument() {
+		return fParentDocument;
+	}
+
+	public IStructuredDocumentRegion getPrevious() {
+		return null; //$NON-NLS-1$
+	}
+
+	/**
+	 */
+	public ITextRegion getRegionAtCharacterOffset(int offset) {
+		return null; //$NON-NLS-1$
+	}
+
+	/**
+	 */
+	public ITextRegionList getRegions() {
+		return new TextRegionListImpl(); //$NON-NLS-1$
+	}
+
+	/**
+	 */
+	public int getStart() {
+		return this.offset;
+	}
+
+	/**
+	 */
+	public int getStartOffset() {
+		return getStart();
+	}
+
+	public int getStartOffset(ITextRegion containedRegion) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	/**
+	 */
+	public IStructuredDocument getStructuredDocument() {
+		return getParentDocument();
+	}
+
+	/**
+	 */
+	public String getText() {
+		return new String();
+	}
+
+	/**
+	 */
+	public String getText(ITextRegion aRegion) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	/**
+	 */
+	public String getText(String context) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	/**
+	 */
+	public int getTextEnd() {
+		return getEnd();
+	}
+
+	/**
+	 */
+	public int getTextEndOffset() {
+		return getTextEnd();
+	}
+
+	public int getTextEndOffset(ITextRegion containedRegion) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	/**
+	 * The text length is equal to length if there is no white space at the
+	 * end of a region. Otherwise it is smaller than length.
+	 */
+	public int getTextLength() {
+		return getLength();
+	}
+
+	/**
+	 */
+	public String getType() {
+		return "ZeroStructuredDocumentRegion";//$NON-NLS-1$
+	}
+
+	public boolean isDeleted() {
+		return false;
+	}
+
+	public boolean isEnded() {
+		return true;
+	}
+
+	public boolean sameAs(IStructuredDocumentRegion region, int shift) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	/**
+	 */
+	public boolean sameAs(ITextRegion region, int shift) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	public boolean sameAs(ITextRegion oldRegion, IStructuredDocumentRegion documentRegion, ITextRegion newRegion, int shift) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	public void setDeleted(boolean deleted) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	public void setEnded(boolean hasEnd) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	/**
+	 * had to make public, due to API transition.
+	 */
+	public void setLength(int length) {
+		this.length = length;
+	}
+
+	public void setNext(IStructuredDocumentRegion newNext) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	/**
+	 */
+	void setOffset(int offset) {
+		this.offset = offset;
+	}
+
+	public void setParentDocument(IStructuredDocument document) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	public void setPrevious(IStructuredDocumentRegion newPrevious) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	public void setRegions(ITextRegionList embeddedRegions) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	public void setStart(int newStart) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	public StructuredDocumentEvent updateRegion(Object requester, IStructuredDocumentRegion flatnode, String changes, int start, int end) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/validation/FragmentValidationTools.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/validation/FragmentValidationTools.java
new file mode 100644
index 0000000..83a95ab
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/validation/FragmentValidationTools.java
@@ -0,0 +1,57 @@
+/*******************************************************************************

+ * Copyright (c) 2008 IBM Corporation and others.

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ * 

+ * Contributors:

+ *     IBM Corporation - initial API and implementation

+ *******************************************************************************/

+

+package org.eclipse.jst.jsp.core.internal.validation;

+

+import org.eclipse.core.resources.IProject;

+import org.eclipse.core.resources.IResource;

+import org.eclipse.core.resources.ProjectScope;

+import org.eclipse.core.runtime.preferences.IEclipsePreferences;

+import org.eclipse.core.runtime.preferences.InstanceScope;

+import org.eclipse.jst.jsp.core.internal.JSPCorePlugin;

+import org.eclipse.jst.jsp.core.internal.preferences.JSPCorePreferenceNames;

+

+

+/**

+ * Utility class for reading fragment validation preferences/properties.

+ * JSPFContentProperties does not respect the project override preference.

+ * 

+ */

+class FragmentValidationTools {

+	/**

+	 * @param resource

+	 * @return whether to perform validation on a fragment, returning the

+	 *         project-specific preference only of project-specific values are

+	 *         enabled

+	 */

+	static boolean shouldValidateFragment(IResource resource) {

+		String qualifier = JSPCorePlugin.getDefault().getBundle().getSymbolicName();

+

+		IProject project = null;

+		if (resource.getType() == IResource.PROJECT) {

+			project = (IProject) resource;

+		}

+		else {

+			project = resource.getProject();

+		}

+		if (project != null) {

+			IEclipsePreferences node = new ProjectScope(project).getNode(qualifier);

+			// first, check whether project specific settings are to be used

+			boolean useProjectSettings = node.getBoolean(JSPCorePreferenceNames.VALIDATION_USE_PROJECT_SETTINGS, false);

+			if (useProjectSettings) {

+				// only if so, return that value

+				return node.getBoolean(JSPCorePreferenceNames.VALIDATE_FRAGMENTS, true);

+			}

+			// if not, return the workspace value

+		}

+		return new InstanceScope().getNode(qualifier).getBoolean(JSPCorePreferenceNames.VALIDATE_FRAGMENTS, true);

+	}

+}

diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/validation/HTMLValidationReporter.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/validation/HTMLValidationReporter.java
new file mode 100644
index 0000000..1c77c11
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/validation/HTMLValidationReporter.java
@@ -0,0 +1,108 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.validation;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.wst.html.core.internal.validate.MessageFactory;
+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.validate.ErrorInfo;
+import org.eclipse.wst.sse.core.internal.validate.ValidationMessage;
+import org.eclipse.wst.sse.core.internal.validate.ValidationReporter;
+import org.eclipse.wst.validation.internal.provisional.core.IMessage;
+import org.eclipse.wst.validation.internal.provisional.core.IReporter;
+import org.eclipse.wst.validation.internal.provisional.core.IValidator;
+
+/*
+ * Copied from html.ui's HTMLValidationReporter with some minor cleanup
+ * modifications
+ */
+class HTMLValidationReporter implements ValidationReporter {
+
+	private IValidator owner = null;
+	private IReporter reporter = null;
+	private IFile file = null;
+	private IStructuredModel model = null;
+	private MessageFactory fFactory = null;
+	
+	/**
+	 */
+	public HTMLValidationReporter(IValidator owner, IReporter reporter, IFile file, IStructuredModel model) {
+		super();
+		this.owner = owner;
+		this.reporter = reporter;
+		this.file = file;
+		this.model = model;
+		fFactory = new MessageFactory(file != null ? file.getProject() : null);
+	}
+
+	/**
+	 */
+	public void clear() {
+		if (this.file == null)
+			return;
+
+
+		if (this.reporter != null) {
+			this.reporter.removeAllMessages(this.owner, this.file);
+		}
+	}
+
+
+
+	/**
+	 */
+	public void report(ValidationMessage message) {
+		if (message == null || this.file == null || message.getSeverity() == ValidationMessage.IGNORE)
+			return;
+		IMessage mes = translateMessage(message);
+
+		if (this.reporter != null) {
+			this.reporter.addMessage(this.owner, mes);
+		}
+	}
+
+	/**
+	 * Translate ValidationMessage to IMessage and generate result log
+	 */
+	private IMessage translateMessage(ValidationMessage message) {
+		int severity = IMessage.LOW_SEVERITY;
+		switch (message.getSeverity()) {
+			case ValidationMessage.ERROR :
+				severity = IMessage.HIGH_SEVERITY;
+				break;
+			case ValidationMessage.WARNING :
+				severity = IMessage.NORMAL_SEVERITY;
+				break;
+			case ValidationMessage.INFORMATION :
+				break;
+			default :
+				break;
+		}
+
+		IMessage mes = new LocalizedMessage(severity, message.getMessage(), this.file);
+		mes.setOffset(message.getOffset());
+		mes.setLength(message.getLength());
+		if (this.model != null) {
+			IStructuredDocument flatModel = this.model.getStructuredDocument();
+			if (flatModel != null) {
+				int line = flatModel.getLineOfOffset(message.getOffset());
+				mes.setLineNo(line + 1);
+			}
+		}
+
+		return mes;
+	}
+
+	public void report(ErrorInfo info) {
+		report(fFactory.createMessage(info));
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/validation/JSPActionValidator.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/validation/JSPActionValidator.java
new file mode 100644
index 0000000..5185fbc
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/validation/JSPActionValidator.java
@@ -0,0 +1,476 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 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
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.validation;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.ProjectScope;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.preferences.DefaultScope;
+import org.eclipse.core.runtime.preferences.IPreferencesService;
+import org.eclipse.core.runtime.preferences.IScopeContext;
+import org.eclipse.core.runtime.preferences.InstanceScope;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jst.jsp.core.internal.JSPCoreMessages;
+import org.eclipse.jst.jsp.core.internal.JSPCorePlugin;
+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.TaglibTracker;
+import org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.JSP11TLDNames;
+import org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.TLDAttributeDeclaration;
+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.document.PageDirectiveAdapter;
+import org.eclipse.jst.jsp.core.internal.document.PageDirectiveAdapterImpl;
+import org.eclipse.jst.jsp.core.internal.preferences.JSPCorePreferenceNames;
+import org.eclipse.jst.jsp.core.internal.regions.DOMJSPRegionContexts;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
+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.ITextRegionContainer;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList;
+import org.eclipse.wst.sse.core.internal.validate.ValidationMessage;
+import org.eclipse.wst.validation.internal.provisional.core.IMessage;
+import org.eclipse.wst.validation.internal.provisional.core.IReporter;
+import org.eclipse.wst.validation.internal.provisional.core.IValidator;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.contentmodel.basic.CMNamedNodeMapImpl;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.modelquery.ModelQueryUtil;
+import org.eclipse.wst.xml.core.internal.provisional.contentmodel.CMNodeWrapper;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMAttr;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
+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 org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.NodeList;
+
+/**
+ * Checks for: missing required attributes & undefined attributes in jsp
+ * action tags such as jsp directives and jsp custom tags as well as non-empty
+ * inline jsp action tags
+ */
+public class JSPActionValidator extends JSPValidator {
+	/**
+	 * 
+	 */
+	private static final String PREFERENCE_NODE_QUALIFIER = JSPCorePlugin.getDefault().getBundle().getSymbolicName();
+	private IValidator fMessageOriginator;
+	private IPreferencesService fPreferencesService = null;
+	private IScopeContext[] fScopes = null;
+	private int fSeverityMissingRequiredAttribute = IMessage.HIGH_SEVERITY;
+	private int fSeverityNonEmptyInlineTag = IMessage.NORMAL_SEVERITY;
+	private int fSeverityUnknownAttribute = IMessage.NORMAL_SEVERITY;
+	private int fSeverityUnexpectedRuntimeExpression = IMessage.NORMAL_SEVERITY;
+
+	private HashSet fTaglibPrefixes = new HashSet();
+	private boolean fIsELIgnored = false;
+
+	public JSPActionValidator() {
+		this.fMessageOriginator = this;
+	}
+
+	public JSPActionValidator(IValidator validator) {
+		this.fMessageOriginator = validator;
+	}
+
+	private void checkNonEmptyInlineTag(IDOMElement element, CMElementDeclaration cmElementDecl, IReporter reporter, IFile file, IStructuredDocument document) {
+		if (cmElementDecl.getContentType() == CMElementDeclaration.EMPTY && element.getChildNodes().getLength() > 0) {
+			String msgText = NLS.bind(JSPCoreMessages.JSPActionValidator_0, element.getNodeName());
+			LocalizedMessage message = new LocalizedMessage(fSeverityNonEmptyInlineTag, msgText, file);
+			int start = element.getStartOffset();
+			int length = element.getStartEndOffset() - start;
+			int lineNo = document.getLineOfOffset(start);
+			message.setLineNo(lineNo);
+			message.setOffset(start);
+			message.setLength(length);
+
+			reporter.addMessage(fMessageOriginator, message);
+		}
+	}
+
+	/**
+	 * Checks an attribute for runtime expressions
+	 * @param a The attribute to check for runtime expressions
+	 * @return true if the attribute contains a runtime expression, false otherwise
+	 */
+	private boolean checkRuntimeValue(IDOMAttr a) {
+		ITextRegion value = a.getValueRegion();
+		if (value instanceof ITextRegionContainer) {
+			Iterator it = ((ITextRegionContainer) value).getRegions().iterator();
+			while (it.hasNext()) {
+				String type = ((ITextRegion) it.next()).getType();
+				if (type == DOMJSPRegionContexts.JSP_EL_OPEN)
+					return true;
+			}
+		}
+		return false;
+	}
+
+	/**
+	 * Determines if EL should be ignored. Checks
+	 * <ol>
+	 *  <li>JSP version</li>
+	 * 	<li>Page directive isELIgnored</li>
+	 *  <li>Deployment descriptor's el-ignored</li>
+	 * </ol>
+	 * @return true if EL should be ignored, false otherwise. If the JSP version is < 2.0, EL is ignored by default
+	 */
+	private boolean isElIgnored(IPath path, IStructuredModel model) {
+		if (DeploymentDescriptorPropertyCache.getInstance().getJSPVersion(path) < 2.0f)
+			return true;
+		String directiveIsELIgnored = ((PageDirectiveAdapterImpl)(((IDOMModel) model).getDocument().getAdapterFor(PageDirectiveAdapter.class))).getElIgnored();
+		// isELIgnored directive found
+		if (directiveIsELIgnored != null)
+			return Boolean.valueOf(directiveIsELIgnored).booleanValue();
+		// Check the deployment descriptor for el-ignored
+		PropertyGroup[] groups = DeploymentDescriptorPropertyCache.getInstance().getPropertyGroups(path);
+		if (groups.length > 0)
+			return groups[0].isELignored();
+		// JSP version >= 2.0 defaults to evaluating EL
+		return false;
+	}
+
+	private void checkRequiredAttributes(IDOMElement element, CMNamedNodeMap attrMap, IReporter reporter, IFile file, IStructuredDocument document, IStructuredDocumentRegion documentRegion) {
+		Iterator it = attrMap.iterator();
+		CMAttributeDeclaration attr = null;
+		while (it.hasNext()) {
+			attr = (CMAttributeDeclaration) it.next();
+			if (attr.getUsage() == CMAttributeDeclaration.REQUIRED) {
+				Attr a = element.getAttributeNode(attr.getAttrName());
+				if (a == null) {
+					// Attribute may be defined using a jsp:attribute action
+					if (!checkJSPAttributeAction(element, attr)) {
+						String msgText = NLS.bind(JSPCoreMessages.JSPDirectiveValidator_5, attr.getAttrName());
+						LocalizedMessage message = new LocalizedMessage(fSeverityMissingRequiredAttribute, msgText, file);
+						int start = element.getStartOffset();
+						int length = element.getStartEndOffset() - start;
+						int lineNo = document.getLineOfOffset(start);
+						message.setLineNo(lineNo);
+						message.setOffset(start);
+						message.setLength(length);
+	
+						reporter.addMessage(fMessageOriginator, message);
+					}
+				}
+			}
+		}
+	}
+	
+	/**
+	 * Checks for jsp:attribute actions of <code>element</code> to see if they
+	 * satisfy the required attribute <code>attr</code>
+	 * 
+	 * @param element The element with a required attribute
+	 * @param attr The required attribute
+	 * @return <code>true</code> if a jsp:attribute action has the name of
+	 * the required attribute <code>attr</code>; <code>false</code> otherwise.
+	 */
+	private boolean checkJSPAttributeAction(IDOMElement element, CMAttributeDeclaration attr) {
+		if (element != null && attr != null) {
+			NodeList elements = element.getElementsByTagName("jsp:attribute"); //$NON-NLS-1$
+			String neededAttrName = attr.getNodeName();
+			for (int i = 0; i < elements.getLength(); i++) {
+				Element childElement = (Element) elements.item(i);
+				/*
+				 * Get the name attribute of jsp:attribute and compare its
+				 * value to the required attribute name
+				 */
+				if (childElement.hasAttribute("name") && neededAttrName.equals(childElement.getAttribute("name"))) {//$NON-NLS-1$ //$NON-NLS-2$
+					return true;
+				}
+			}
+		}
+		return false;
+	}
+
+	private boolean checkUnknownAttributes(IDOMElement element, CMElementDeclaration elementDecl, CMNamedNodeMap cmAttrs, IReporter reporter, IFile file, IStructuredDocument document, IStructuredDocumentRegion documentRegion) {
+		boolean foundjspattribute = false;
+		boolean dynamicAttributesAllowed = false;
+		CMElementDeclaration decl = elementDecl;
+		if (decl instanceof CMNodeWrapper)
+			decl = (CMElementDeclaration) ((CMNodeWrapper) decl).getOriginNode();
+		if (decl instanceof TLDElementDeclaration) {
+			String dynamicAttributes = ((TLDElementDeclaration) decl).getDynamicAttributes();
+			dynamicAttributesAllowed = dynamicAttributes != null ? Boolean.valueOf(dynamicAttributes).booleanValue() : false;
+		}
+
+		NamedNodeMap attrs = element.getAttributes();
+		for (int i = 0; i < attrs.getLength(); i++) {
+			Attr a = (Attr) attrs.item(i);
+			CMAttributeDeclaration adec = (CMAttributeDeclaration) cmAttrs.getNamedItem(a.getName());
+			if (adec == null) {
+				/*
+				 * No attr declaration was found. That is, the attr name is
+				 * undefined. Disregard it includes JSP structure or this
+				 * element supports dynamic attributes
+				 */
+				if (!hasJSPRegion(((IDOMNode) a).getNameRegion()) && fSeverityUnknownAttribute != ValidationMessage.IGNORE) {
+					if (!dynamicAttributesAllowed) {
+						String msgText = NLS.bind(JSPCoreMessages.JSPDirectiveValidator_6, a.getName());
+						LocalizedMessage message = new LocalizedMessage(fSeverityUnknownAttribute, msgText, file);
+						int start = ((IDOMAttr) a).getNameRegionStartOffset();
+						int length = ((IDOMAttr) a).getNameRegionEndOffset() - start;
+						int lineNo = document.getLineOfOffset(start);
+						message.setLineNo(lineNo);
+						message.setOffset(start);
+						message.setLength(length);
+
+						reporter.addMessage(fMessageOriginator, message);
+					}
+				}
+				else {
+					foundjspattribute = true;
+				}
+			}
+			else {
+				if (fSeverityUnexpectedRuntimeExpression != ValidationMessage.IGNORE && adec instanceof TLDAttributeDeclaration) {
+					// The attribute cannot have a runtime evaluation of an expression
+					if (!isTrue(((TLDAttributeDeclaration) adec).getRtexprvalue())) {
+						IDOMAttr attr = (IDOMAttr) a;
+						if(checkRuntimeValue(attr) && !fIsELIgnored) {
+							String msg = NLS.bind(JSPCoreMessages.JSPActionValidator_1, a.getName());
+							LocalizedMessage message = new LocalizedMessage(fSeverityUnexpectedRuntimeExpression, msg, file);
+							ITextRegion region = attr.getValueRegion();
+							int start = attr.getValueRegionStartOffset();
+							int length = region != null ? region.getTextLength() : 0;
+							int lineNo = document.getLineOfOffset(start);
+							message.setLineNo(lineNo);
+							message.setOffset(start);
+							message.setLength(length);
+							reporter.addMessage(fMessageOriginator, message);
+						}
+					}
+				}
+			}
+		}
+		return foundjspattribute;
+	}
+
+	private boolean isTrue(String value) {
+		return JSP11TLDNames.TRUE.equalsIgnoreCase(value) || JSP11TLDNames.YES.equalsIgnoreCase(value);
+	}
+
+	public void cleanup(IReporter reporter) {
+		super.cleanup(reporter);
+		fTaglibPrefixes.clear();
+	}
+
+	int getMessageSeverity(String key) {
+		int sev = fPreferencesService.getInt(PREFERENCE_NODE_QUALIFIER, key, IMessage.NORMAL_SEVERITY, fScopes);
+		switch (sev) {
+			case ValidationMessage.ERROR :
+				return IMessage.HIGH_SEVERITY;
+			case ValidationMessage.WARNING :
+				return IMessage.NORMAL_SEVERITY;
+			case ValidationMessage.INFORMATION :
+				return IMessage.LOW_SEVERITY;
+			case ValidationMessage.IGNORE :
+				return ValidationMessage.IGNORE;
+		}
+		return IMessage.NORMAL_SEVERITY;
+	}
+
+	private String getStartTagName(IStructuredDocumentRegion sdr) {
+		String name = new String();
+		ITextRegionList subRegions = sdr.getRegions();
+		if (subRegions.size() > 2) {
+			ITextRegion subRegion = subRegions.get(0);
+			if (subRegion.getType() == DOMRegionContext.XML_TAG_OPEN) {
+				subRegion = subRegions.get(1);
+				if (subRegion.getType() == DOMRegionContext.XML_TAG_NAME) {
+					name = sdr.getText(subRegion);
+				}
+			}
+		}
+		return name;
+	}
+
+	private HashSet getTaglibPrefixes(IStructuredDocument document) {
+		if (fTaglibPrefixes.isEmpty()) {
+			// add all reserved prefixes
+			fTaglibPrefixes.add("jsp"); //$NON-NLS-1$
+			fTaglibPrefixes.add("jspx"); //$NON-NLS-1$
+			fTaglibPrefixes.add("java"); //$NON-NLS-1$
+			fTaglibPrefixes.add("javax"); //$NON-NLS-1$ 
+			fTaglibPrefixes.add("servlet"); //$NON-NLS-1$ 
+			fTaglibPrefixes.add("sun"); //$NON-NLS-1$ 
+			fTaglibPrefixes.add("sunw"); //$NON-NLS-1$
+
+			// add all taglib prefixes
+			TLDCMDocumentManager manager = TaglibController.getTLDCMDocumentManager(document);
+			if (manager != null) {
+				List trackers = manager.getTaglibTrackers();
+				for (Iterator it = trackers.iterator(); it.hasNext();) {
+					TaglibTracker tracker = (TaglibTracker) it.next();
+					if (tracker.getElements().getLength() == 0)
+						continue;
+					String prefix = tracker.getPrefix();
+					fTaglibPrefixes.add(prefix);
+				}
+			}
+		}
+		return fTaglibPrefixes;
+	}
+
+	private boolean hasJSPRegion(ITextRegion container) {
+		if (!(container instanceof ITextRegionContainer))
+			return false;
+		ITextRegionList regions = ((ITextRegionContainer) container).getRegions();
+		if (regions == null)
+			return false;
+		Iterator e = regions.iterator();
+		while (e.hasNext()) {
+			ITextRegion region = (ITextRegion) e.next();
+			if (region == null)
+				continue;
+			String regionType = region.getType();
+			if (regionType == DOMRegionContext.XML_TAG_OPEN || (isNestedTagName(regionType)))
+				return true;
+		}
+		return false;
+	}
+
+	private boolean isNestedTagName(String regionType) {
+		boolean result = regionType.equals(DOMJSPRegionContexts.JSP_SCRIPTLET_OPEN) || regionType.equals(DOMJSPRegionContexts.JSP_EXPRESSION_OPEN) || regionType.equals(DOMJSPRegionContexts.JSP_DECLARATION_OPEN) || regionType.equals(DOMJSPRegionContexts.JSP_DIRECTIVE_OPEN);
+		return result;
+	}
+
+	private void loadPreferences(IFile file) {
+		fScopes = new IScopeContext[]{new InstanceScope(), new DefaultScope()};
+
+		fPreferencesService = Platform.getPreferencesService();
+		if (file != null && file.isAccessible()) {
+			ProjectScope projectScope = new ProjectScope(file.getProject());
+			if (projectScope.getNode(PREFERENCE_NODE_QUALIFIER).getBoolean(JSPCorePreferenceNames.VALIDATION_USE_PROJECT_SETTINGS, false)) {
+				fScopes = new IScopeContext[]{projectScope, new InstanceScope(), new DefaultScope()};
+			}
+		}
+
+		fSeverityMissingRequiredAttribute = getMessageSeverity(JSPCorePreferenceNames.VALIDATION_ACTIONS_SEVERITY_MISSING_REQUIRED_ATTRIBUTE);
+		fSeverityNonEmptyInlineTag = getMessageSeverity(JSPCorePreferenceNames.VALIDATION_ACTIONS_SEVERITY_NON_EMPTY_INLINE_TAG);
+		fSeverityUnknownAttribute = getMessageSeverity(JSPCorePreferenceNames.VALIDATION_ACTIONS_SEVERITY_UNKNOWN_ATTRIBUTE);
+		fSeverityUnexpectedRuntimeExpression = getMessageSeverity(JSPCorePreferenceNames.VALIDATION_ACTIONS_SEVERITY_UNEXPECTED_RTEXPRVALUE);
+	}
+
+	void performValidation(IFile f, IReporter reporter, IStructuredModel model) {
+		fTaglibPrefixes.clear();
+		int length = model.getStructuredDocument().getLength();
+		performValidation(f, reporter, model, new Region(0, length));
+	}
+
+	protected void performValidation(IFile f, IReporter reporter, IStructuredModel model, IRegion validateRegion) {
+		loadPreferences(f);
+		IStructuredDocument sDoc = model.getStructuredDocument();
+
+		fIsELIgnored = isElIgnored(f.getFullPath(), model);
+		// iterate all document regions
+		IStructuredDocumentRegion region = sDoc.getRegionAtCharacterOffset(validateRegion.getOffset());
+		while (region != null && !reporter.isCancelled() && (region.getStartOffset() <= (validateRegion.getOffset() + validateRegion.getLength()))) {
+			if (region.getType() == DOMJSPRegionContexts.JSP_DIRECTIVE_NAME) {
+				// only checking directives
+				processDirective(reporter, f, model, region);
+				fTaglibPrefixes.clear();
+			}
+			else if (region.getType() == DOMRegionContext.XML_TAG_NAME) {
+				// and jsp tags
+				String tagName = getStartTagName(region);
+				int colonPosition = tagName.indexOf(':');
+				if (colonPosition > -1) {
+					// get tag's prefix and check if it's really a jsp action
+					// tag
+					String prefix = tagName.substring(0, colonPosition);
+					if (getTaglibPrefixes(sDoc).contains(prefix))
+						processDirective(reporter, f, model, region);
+				}
+			}
+			region = region.getNext();
+		}
+		unloadPreferences();
+	}
+
+	private void processDirective(IReporter reporter, IFile file, IStructuredModel model, IStructuredDocumentRegion documentRegion) {
+		IndexedRegion ir = model.getIndexedRegion(documentRegion.getStartOffset());
+		if (ir instanceof IDOMElement) {
+			IDOMElement element = (IDOMElement) ir;
+			ModelQuery query = ModelQueryUtil.getModelQuery(model);
+			if (query != null) {
+				CMElementDeclaration cmElement = query.getCMElementDeclaration(element);
+				if (cmElement != null) {
+					CMNamedNodeMap cmAttributes = null;
+
+					CMNamedNodeMapImpl allAttributes = new CMNamedNodeMapImpl();
+					List nodes = query.getAvailableContent(element, cmElement, ModelQuery.INCLUDE_ATTRIBUTES);
+					for (int k = 0; k < nodes.size(); k++) {
+						CMNode cmnode = (CMNode) nodes.get(k);
+						if (cmnode.getNodeType() == CMNode.ATTRIBUTE_DECLARATION) {
+							allAttributes.put(cmnode);
+						}
+					}
+					cmAttributes = allAttributes;
+
+					boolean foundjspattribute = checkUnknownAttributes(element, cmElement, cmAttributes, reporter, file, model.getStructuredDocument(), documentRegion);
+					// required attributes could be hidden in jsp regions in
+					// tags, so if jsp regions were detected, do not check for
+					// missing required attributes
+					if (!foundjspattribute && fSeverityMissingRequiredAttribute != ValidationMessage.IGNORE)
+						checkRequiredAttributes(element, cmAttributes, reporter, file, model.getStructuredDocument(), documentRegion);
+
+					if (fSeverityNonEmptyInlineTag != ValidationMessage.IGNORE)
+						checkNonEmptyInlineTag(element, cmElement, reporter, file, model.getStructuredDocument());
+				}
+			}
+		}
+	}
+
+	private void unloadPreferences() {
+		fPreferencesService = null;
+		fScopes = null;
+	}
+
+	protected void validateFile(IFile f, IReporter reporter) {
+		if (DEBUG) {
+			Logger.log(Logger.INFO, getClass().getName() + " validating: " + f); //$NON-NLS-1$
+		}
+
+		IStructuredModel sModel = null;
+		try {
+			sModel = StructuredModelManager.getModelManager().getModelForRead(f);
+			if (sModel != null && !reporter.isCancelled()) {
+				performValidation(f, reporter, sModel);
+			}
+		}
+		catch (Exception e) {
+			Logger.logException(e);
+		}
+		finally {
+			if (sModel != null)
+				sModel.releaseFromRead();
+		}
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/validation/JSPBatchValidator.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/validation/JSPBatchValidator.java
new file mode 100644
index 0000000..42c287b
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/validation/JSPBatchValidator.java
@@ -0,0 +1,539 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.validation;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceProxy;
+import org.eclipse.core.resources.IResourceProxyVisitor;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.IWorkspaceRunnable;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExecutableExtension;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.content.IContentDescription;
+import org.eclipse.core.runtime.content.IContentType;
+import org.eclipse.core.runtime.jobs.ISchedulingRule;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jst.jsp.core.internal.JSPCoreMessages;
+import org.eclipse.jst.jsp.core.internal.Logger;
+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.contenttype.ContentTypeIdForJSP;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.utils.StringUtils;
+import org.eclipse.wst.validation.AbstractValidator;
+import org.eclipse.wst.validation.ValidationResult;
+import org.eclipse.wst.validation.ValidationState;
+import org.eclipse.wst.validation.internal.ConfigurationManager;
+import org.eclipse.wst.validation.internal.ProjectConfiguration;
+import org.eclipse.wst.validation.internal.ValidationRegistryReader;
+import org.eclipse.wst.validation.internal.core.Message;
+import org.eclipse.wst.validation.internal.core.ValidationException;
+import org.eclipse.wst.validation.internal.operations.IWorkbenchContext;
+import org.eclipse.wst.validation.internal.provisional.core.IMessage;
+import org.eclipse.wst.validation.internal.provisional.core.IReporter;
+import org.eclipse.wst.validation.internal.provisional.core.IValidationContext;
+import org.eclipse.wst.validation.internal.provisional.core.IValidatorJob;
+
+/**
+ * Performs JSP validation tasks for batch validation. The individual
+ * validator classes will still be used for source validation.
+ */
+public final class JSPBatchValidator extends AbstractValidator implements IValidatorJob, IExecutableExtension {
+	class JSPFileVisitor implements IResourceProxyVisitor {
+
+		private List fFiles = new ArrayList();
+		private IReporter fReporter = null;
+
+		public JSPFileVisitor(IReporter reporter) {
+			fReporter = reporter;
+		}
+
+		final IFile[] getFiles() {
+			return (IFile[]) fFiles.toArray(new IFile[fFiles.size()]);
+		}
+
+		public boolean visit(IResourceProxy proxy) throws CoreException {
+
+			// check validation
+			if (fReporter.isCancelled())
+				return false;
+
+			if (proxy.getType() == IResource.FILE) {
+
+				if (isJSPType(proxy.getName()) && proxy.isAccessible()) {
+					IFile file = (IFile) proxy.requestResource();
+					if (DEBUG)
+						System.out.println("(+) JSPValidator adding file: " + file.getName()); //$NON-NLS-1$
+					fFiles.add(file);
+
+					// don't search deeper for files
+					return false;
+				}
+			}
+			return true;
+		}
+	}
+
+	// for debugging
+	static final boolean DEBUG = Boolean.valueOf(Platform.getDebugOption("org.eclipse.jst.jsp.core/debug/jspvalidator")).booleanValue(); //$NON-NLS-1$
+
+	private static final String PLUGIN_ID_JSP_CORE = "org.eclipse.jst.jsp.core"; //$NON-NLS-1$
+
+	/**
+	 * List of IResources that the currently validating file depends upon
+	 */
+	private Collection fDependsOn;
+
+	/**
+	 * Gets current validation project configuration based on current project
+	 * (which is based on current document)
+	 * 
+	 * @return ProjectConfiguration
+	 */
+	static private ProjectConfiguration getProjectConfiguration(IFile file) {
+		ProjectConfiguration projectConfiguration = null;
+		if (file != null) {
+			IProject project = file.getProject();
+			if (project != null) {
+				try {
+					projectConfiguration = ConfigurationManager.getManager().getProjectConfiguration(project);
+				}
+				catch (InvocationTargetException e) {
+					Logger.log(Logger.WARNING_DEBUG, e.getMessage(), e);
+				}
+			}
+		}
+
+		return projectConfiguration;
+	}
+
+	/**
+	 * Checks if validator is enabled according in Validation preferences
+	 * 
+	 * @param vmd
+	 * @return
+	 */
+	static boolean isBatchValidatorPreferenceEnabled(IFile file) {
+		if (file == null) {
+			return true;
+		}
+
+		boolean enabled = true;
+		ProjectConfiguration configuration = getProjectConfiguration(file);
+		if (configuration != null) {
+			org.eclipse.wst.validation.internal.ValidatorMetaData metadata = ValidationRegistryReader.getReader().getValidatorMetaData(JSPBatchValidator.class.getName());
+			if (configuration != null && metadata != null) {
+				if (!configuration.isBuildEnabled(metadata) && !configuration.isManualEnabled(metadata))
+					enabled = false;
+			}
+		}
+		return enabled;
+	}
+
+	String fAdditionalContentTypesIDs[] = null;
+
+	private IContentType[] fContentTypes = null;
+
+	private JSPDirectiveValidator fJSPDirectiveValidator = new JSPDirectiveValidator(this);
+
+	private JSPELValidator fJSPELValidator = new JSPELValidator(this);
+
+	private IContentType fJSPFContentType = null;
+
+	private JSPJavaValidator fJSPJavaValidator = new JSPJavaValidator(this);
+
+	private JSPActionValidator fJSPActionValidator = new JSPActionValidator(this);
+
+	void addDependsOn(IResource resource) {
+		if(resource != null) {
+			fDependsOn.add(resource);
+		}
+	}
+
+	public void cleanup(IReporter reporter) {
+		fJSPDirectiveValidator.cleanup(reporter);
+		fJSPELValidator.cleanup(reporter);
+		fJSPJavaValidator.cleanup(reporter);
+		fJSPActionValidator.cleanup(reporter);
+	}
+
+
+	void doValidate(IValidationContext helper, IReporter reporter) throws ValidationException {
+		String[] uris = helper.getURIs();
+		if (uris.length > 0) {
+			IWorkspaceRoot wsRoot = ResourcesPlugin.getWorkspace().getRoot();
+			IFile currentFile = null;
+			for (int i = 0; i < uris.length && !reporter.isCancelled(); i++) {
+				currentFile = wsRoot.getFile(new Path(uris[i]));
+				if (currentFile != null && currentFile.exists()) {
+					if (shouldValidate(currentFile) && fragmentCheck(currentFile)) {
+						Message message = new LocalizedMessage(IMessage.LOW_SEVERITY, currentFile.getFullPath().toString().substring(1));
+						reporter.displaySubtask(this, message);
+						validateFile(currentFile, reporter);
+					}
+					if (DEBUG)
+						System.out.println("validating: [" + uris[i] + "]"); //$NON-NLS-1$ //$NON-NLS-2$
+				}
+			}
+		}
+		else {
+			// if uris[] length 0 -> validate() gets called for each project
+			if (helper instanceof IWorkbenchContext) {
+				IProject project = ((IWorkbenchContext) helper).getProject();
+
+				Message message = new LocalizedMessage(IMessage.LOW_SEVERITY, NLS.bind(JSPCoreMessages.JSPBatchValidator_0, project.getFullPath()));
+				reporter.displaySubtask(this, message);
+
+				JSPFileVisitor visitor = new JSPFileVisitor(reporter);
+				try {
+					// collect all jsp files for the project
+					project.accept(visitor, IResource.DEPTH_INFINITE);
+				}
+				catch (CoreException e) {
+					if (DEBUG)
+						e.printStackTrace();
+				}
+				IFile[] files = visitor.getFiles();
+				for (int i = 0; i < files.length && !reporter.isCancelled(); i++) {
+					if (shouldValidate(files[i]) && fragmentCheck(files[i])) {
+
+						message = new LocalizedMessage(IMessage.LOW_SEVERITY, files[i].getFullPath().toString().substring(1));
+						reporter.displaySubtask(this, message);
+
+						validateFile(files[i], reporter);
+					}
+					if (DEBUG)
+						System.out.println("validating: [" + files[i] + "]"); //$NON-NLS-1$ //$NON-NLS-2$
+				}
+			}
+		}
+	}
+
+	/**
+	 * Checks if file is a jsp fragment or not. If so, check if the fragment
+	 * should be validated or not.
+	 * 
+	 * @param file
+	 *            Assumes shouldValidate was already called on file so it
+	 *            should not be null and does exist
+	 * @return false if file is a fragment and it should not be validated,
+	 *         true otherwise
+	 */
+	private boolean fragmentCheck(IFile file) {
+		boolean shouldValidate = true;
+		// quick check to see if this is possibly a jsp fragment
+		if (getJSPFContentType().isAssociatedWith(file.getName())) {
+			// get preference for validate jsp fragments
+			boolean shouldValidateFragments = FragmentValidationTools.shouldValidateFragment(file);
+			/*
+			 * if jsp fragments should not be validated, check if file is
+			 * really jsp fragment
+			 */
+			if (!shouldValidateFragments) {
+				boolean isFragment = isFragment(file);
+				shouldValidate = !isFragment;
+			}
+		}
+		return shouldValidate;
+	}
+
+	/**
+	 * Returns JSP fragment content type
+	 * 
+	 * @return jspf content type
+	 */
+	private IContentType getJSPFContentType() {
+		if (fJSPFContentType == null) {
+			fJSPFContentType = Platform.getContentTypeManager().getContentType(ContentTypeIdForJSP.ContentTypeID_JSPFRAGMENT);
+		}
+		return fJSPFContentType;
+	}
+
+	public ISchedulingRule getSchedulingRule(IValidationContext helper) {
+		if (helper instanceof IWorkbenchContext) {
+			/*
+			 * Use a single build rule when running batch validation.
+			 */
+			return ResourcesPlugin.getWorkspace().getRuleFactory().buildRule();
+		}
+		/*
+		 * For other kinds of validation, use no specific rule
+		 */
+		return null;
+	}
+
+	/**
+	 * Gets list of content types this visitor is interested in
+	 * 
+	 * @return All JSP-related content types
+	 */
+	private IContentType[] getValidContentTypes() {
+		if (fContentTypes == null) {
+			// currently "hard-coded" to be jsp & jspf
+			fContentTypes = new IContentType[]{Platform.getContentTypeManager().getContentType(ContentTypeIdForJSP.ContentTypeID_JSP), Platform.getContentTypeManager().getContentType(ContentTypeIdForJSP.ContentTypeID_JSPFRAGMENT)};
+			if (fAdditionalContentTypesIDs != null) {
+				List allTypes = new ArrayList(Arrays.asList(fContentTypes));
+				for (int i = 0; i < fAdditionalContentTypesIDs.length; i++) {
+					IContentType type = Platform.getContentTypeManager().getContentType(fAdditionalContentTypesIDs[i]);
+					if (type != null) {
+						allTypes.add(type);
+					}
+				}
+				fContentTypes = (IContentType[]) allTypes.toArray(new IContentType[allTypes.size()]);
+			}
+		}
+		return fContentTypes;
+	}
+
+	/**
+	 * Determines if file is jsp fragment or not (does a deep, indepth check,
+	 * looking into contents of file)
+	 * 
+	 * @param file
+	 *            assumes file is not null and exists
+	 * @return true if file is jsp fragment, false otherwise
+	 */
+	private boolean isFragment(IFile file) {
+		boolean isFragment = false;
+		InputStream is = null;
+		try {
+			IContentDescription contentDescription = file.getContentDescription();
+			// it can be null
+			if (contentDescription == null) {
+				is = file.getContents();
+				contentDescription = Platform.getContentTypeManager().getDescriptionFor(is, file.getName(), new QualifiedName[]{IContentDescription.CHARSET});
+			}
+			if (contentDescription != null) {
+				String fileCtId = contentDescription.getContentType().getId();
+				isFragment = (fileCtId != null && ContentTypeIdForJSP.ContentTypeID_JSPFRAGMENT.equals(fileCtId));
+			}
+		}
+		catch (IOException e) {
+			// ignore, assume it's invalid JSP
+		}
+		catch (CoreException e) {
+			// ignore, assume it's invalid JSP
+		}
+		finally {
+			/*
+			 * must close input stream in case others need it
+			 * (IFile.getContents() requirement as well)
+			 */
+			if (is != null)
+				try {
+					is.close();
+				}
+				catch (Exception e) {
+					// not sure how to recover at this point
+				}
+		}
+		return isFragment;
+	}
+
+	/**
+	 * Checks if fileName is some type of JSP (including JSP fragments)
+	 * 
+	 * @param fileName
+	 * @return true if filename indicates some type of JSP, false otherwise
+	 */
+	private boolean isJSPType(String fileName) {
+		boolean valid = false;
+
+		IContentType[] types = getValidContentTypes();
+		int i = 0;
+		while (i < types.length && !valid) {
+			valid = types[i].isAssociatedWith(fileName);
+			++i;
+		}
+		return valid;
+	}
+
+	private void performValidation(IFile f, IReporter reporter, IStructuredModel model) {
+		if (!reporter.isCancelled())
+			fJSPJavaValidator.performValidation(f, reporter, model);
+		if (!reporter.isCancelled())
+			fJSPDirectiveValidator.performValidation(f, reporter, model.getStructuredDocument());
+		if (!reporter.isCancelled())
+			fJSPELValidator.performValidation(f, reporter, model.getStructuredDocument());
+		if (!reporter.isCancelled())
+			fJSPActionValidator.performValidation(f, reporter, model);
+	}
+
+	/**
+	 * @see org.eclipse.core.runtime.IExecutableExtension#setInitializationData(org.eclipse.core.runtime.IConfigurationElement,
+	 *      java.lang.String, java.lang.Object)
+	 */
+	public void setInitializationData(IConfigurationElement config, String propertyName, Object data) throws CoreException {
+		fAdditionalContentTypesIDs = new String[0];
+		if (data != null) {
+			if (data instanceof String && data.toString().length() > 0) {
+				fAdditionalContentTypesIDs = StringUtils.unpack(data.toString());
+			}
+		}
+	}
+
+	private boolean shouldValidate(IFile file) {
+		IResource resource = file;
+		do {
+			if (resource.isDerived() || resource.isTeamPrivateMember() || !resource.isAccessible() || resource.getName().charAt(0) == '.') {
+				return false;
+			}
+			resource = resource.getParent();
+		}
+		while ((resource.getType() & IResource.PROJECT) == 0);
+		return true;
+	}
+
+	public void validate(IValidationContext helper, IReporter reporter) throws ValidationException {
+		doValidate(helper, reporter);
+	}
+
+	/**
+	 * Validate one file. It's assumed that the file has JSP content type.
+	 * 
+	 * @param f
+	 * @param reporter
+	 */
+	void validateFile(IFile f, IReporter reporter) {
+		try {
+			f.refreshLocal(IResource.DEPTH_ZERO, new NullProgressMonitor());
+		}
+		catch (CoreException e) {
+			Logger.logException(e);
+		}
+		IStructuredModel model = null;
+		try {
+			// get JSP model on behalf of all JSP validators
+			model = StructuredModelManager.getModelManager().getModelForRead(f);
+			if (!reporter.isCancelled() && model != null) {
+				reporter.removeAllMessages(this, f);
+				performValidation(f, reporter, model);
+			}
+		}
+		catch (IOException e) {
+			Logger.logException(e);
+		}
+		catch (CoreException e) {
+			Logger.logException(e);
+		}
+		finally {
+			if (model != null)
+				model.releaseFromRead();
+		}
+	}
+
+	public IStatus validateInJob(final IValidationContext helper, final IReporter reporter) throws ValidationException {
+		Job currentJob = Job.getJobManager().currentJob();
+		ISchedulingRule rule = null;
+		if (currentJob != null) {
+			rule = currentJob.getRule();
+		}
+		IWorkspaceRunnable validationRunnable = new IWorkspaceRunnable() {
+			public void run(IProgressMonitor monitor) throws CoreException {
+				try {
+					doValidate(helper, reporter);
+				}
+				catch (ValidationException e) {
+					throw new CoreException(new Status(IStatus.ERROR, PLUGIN_ID_JSP_CORE, 0, PLUGIN_ID_JSP_CORE, e));
+				}
+			}
+		};
+		try {
+			JavaCore.run(validationRunnable, rule, new NullProgressMonitor());
+		}
+		catch (CoreException e) {
+			if (e.getCause() instanceof ValidationException) {
+				throw (ValidationException) e.getCause();
+			}
+			throw new ValidationException(new LocalizedMessage(IMessage.ERROR_AND_WARNING, e.getMessage()), e);
+		}
+		return Status.OK_STATUS;
+	}
+
+	public ValidationResult validate(final IResource resource, int kind, ValidationState state, IProgressMonitor monitor) {
+		if (resource.getType() != IResource.FILE)
+			return null;
+		final ValidationResult result = new ValidationResult();
+		final IReporter reporter = result.getReporter(monitor);
+		
+		if(result.getDependsOn() != null) {
+			fDependsOn = new HashSet(Arrays.asList(result.getDependsOn()));
+		}
+		else {
+			fDependsOn = new HashSet();
+		}
+		
+		// add web.xml as a dependency
+		addDependsOn(DeploymentDescriptorPropertyCache.getInstance().getWebXML(resource.getFullPath()));
+
+		// List relevant JSP 2.0 preludes/codas as dependencies
+		IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
+		PropertyGroup[] propertyGroups = DeploymentDescriptorPropertyCache.getInstance().getPropertyGroups(resource.getFullPath());
+		for (int j = 0; j < propertyGroups.length; j++) {
+			IPath[] preludes = propertyGroups[j].getIncludePrelude();
+			for (int i = 0; i < preludes.length; i++) {
+				addDependsOn(workspaceRoot.getFile(preludes[i]));
+			}
+			IPath[] codas = propertyGroups[j].getIncludeCoda();
+			for (int i = 0; i < codas.length; i++) {
+				addDependsOn(workspaceRoot.getFile(codas[i]));
+			}
+		}
+		
+		IWorkspaceRunnable validationRunnable = new IWorkspaceRunnable() {
+			public void run(IProgressMonitor monitor) throws CoreException {
+				if (fragmentCheck((IFile) resource)) {
+					validateFile((IFile) resource, reporter);
+				}
+				IResource[] resources = (IResource[]) fDependsOn.toArray(new IResource[fDependsOn.size()]);
+				result.setDependsOn(resources);
+				fDependsOn.clear();
+			}
+		};
+		Job currentJob = Job.getJobManager().currentJob();
+		ISchedulingRule rule = null;
+		if (currentJob != null) {
+			rule = currentJob.getRule();
+		}
+		try {
+			JavaCore.run(validationRunnable, rule, new NullProgressMonitor());
+		}
+		catch (CoreException e) {
+			Logger.logException(e);
+		}
+		return result;
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/validation/JSPContentValidator.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/validation/JSPContentValidator.java
new file mode 100644
index 0000000..2c13d19
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/validation/JSPContentValidator.java
@@ -0,0 +1,265 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.validation;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.core.runtime.content.IContentDescription;
+import org.eclipse.core.runtime.content.IContentType;
+import org.eclipse.jst.jsp.core.internal.Logger;
+import org.eclipse.jst.jsp.core.internal.provisional.contenttype.ContentTypeIdForJSP;
+import org.eclipse.wst.html.core.internal.document.HTMLDocumentTypeConstants;
+import org.eclipse.wst.html.core.internal.validate.HTMLValidationAdapterFactory;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapterFactory;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.validate.ValidationAdapter;
+import org.eclipse.wst.validation.ValidationResult;
+import org.eclipse.wst.validation.ValidationState;
+import org.eclipse.wst.validation.internal.provisional.core.IReporter;
+import org.eclipse.wst.xml.core.internal.document.DocumentTypeAdapter;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
+import org.eclipse.wst.xml.core.internal.validation.eclipse.Validator;
+import org.w3c.dom.Element;
+
+/**
+ * This validator validates the contents of the content type of the JSP, like
+ * the HTML regions in a JSP with content type="text/html"
+ */
+public class JSPContentValidator extends JSPValidator {
+	private static final String HTTP_JAVA_SUN_COM_JSP_PAGE = "http://java.sun.com/JSP/Page"; //$NON-NLS-1$
+	private static final String XMLNS = "xmlns"; //$NON-NLS-1$
+	private static final String XMLNS_JSP = "xmlns:jsp"; //$NON-NLS-1$
+	private IContentType fJSPFContentType = null;
+
+
+	/**
+	 * Checks if file is a jsp fragment or not. If so, check if the fragment
+	 * should be validated or not.
+	 * 
+	 * @param file
+	 *            Assumes shouldValidate was already called on file so it
+	 *            should not be null and does exist
+	 * @return false if file is a fragment and it should not be validated,
+	 *         true otherwise
+	 */
+	private boolean fragmentCheck(IFile file) {
+		boolean shouldValidate = true;
+		// quick check to see if this is possibly a jsp fragment
+		if (getJSPFContentType().isAssociatedWith(file.getName())) {
+			// get preference for validate jsp fragments
+			boolean shouldValidateFragments = FragmentValidationTools.shouldValidateFragment(file);
+			/*
+			 * if jsp fragments should not be validated, check if file is
+			 * really jsp fragment
+			 */
+			if (!shouldValidateFragments) {
+				boolean isFragment = isFragment(file);
+				shouldValidate = !isFragment;
+			}
+		}
+		return shouldValidate;
+	}
+
+	/**
+	 * Returns JSP fragment content type
+	 * 
+	 * @return jspf content type
+	 */
+	private IContentType getJSPFContentType() {
+		if (fJSPFContentType == null) {
+			fJSPFContentType = Platform.getContentTypeManager().getContentType(ContentTypeIdForJSP.ContentTypeID_JSPFRAGMENT);
+		}
+		return fJSPFContentType;
+	}
+
+	/*
+	 * Copied from HTMLValidator
+	 */
+	private HTMLValidationReporter getReporter(IReporter reporter, IFile file, IDOMModel model) {
+		return new HTMLValidationReporter(this, reporter, file, model);
+	}
+
+	/*
+	 * Copied from HTMLValidator
+	 */
+	private boolean hasHTMLFeature(IDOMDocument document) {
+		DocumentTypeAdapter adapter = (DocumentTypeAdapter) document.getAdapterFor(DocumentTypeAdapter.class);
+		if (adapter == null)
+			return false;
+		return adapter.hasFeature(HTMLDocumentTypeConstants.HTML);
+	}
+
+	/**
+	 * Determines if file is jsp fragment or not (does a deep, indepth check,
+	 * looking into contents of file)
+	 * 
+	 * @param file
+	 *            assumes file is not null and exists
+	 * @return true if file is jsp fragment, false otherwise
+	 */
+	private boolean isFragment(IFile file) {
+		boolean isFragment = false;
+		InputStream is = null;
+		try {
+			IContentDescription contentDescription = file.getContentDescription();
+			// it can be null
+			if (contentDescription == null) {
+				is = file.getContents();
+				contentDescription = Platform.getContentTypeManager().getDescriptionFor(is, file.getName(), new QualifiedName[]{IContentDescription.CHARSET});
+			}
+			if (contentDescription != null) {
+				String fileCtId = contentDescription.getContentType().getId();
+				isFragment = (fileCtId != null && ContentTypeIdForJSP.ContentTypeID_JSPFRAGMENT.equals(fileCtId));
+			}
+		}
+		catch (IOException e) {
+			// ignore, assume it's invalid JSP
+		}
+		catch (CoreException e) {
+			// ignore, assume it's invalid JSP
+		}
+		finally {
+			/*
+			 * must close input stream in case others need it
+			 * (IFile.getContents() requirement as well)
+			 */
+			if (is != null)
+				try {
+					is.close();
+				}
+				catch (Exception e) {
+					// not sure how to recover at this point
+				}
+		}
+		return isFragment;
+	}
+
+	private boolean isXMLJSP(IDOMDocument document) {
+		Element root = document.getDocumentElement();
+		return root != null && (root.hasAttribute(XMLNS_JSP) || HTTP_JAVA_SUN_COM_JSP_PAGE.equals(root.getAttribute(XMLNS)));
+	}
+
+	private void validate(IFile file, int kind, ValidationState state, IProgressMonitor monitor, IDOMModel model, IReporter reporter) {
+		IDOMDocument document = model.getDocument();
+		if (document == null)
+			return; // error
+
+		boolean isXMLJSP = isXMLJSP(document);
+		boolean hasHTMLFeature = hasHTMLFeature(document);
+
+		if (hasHTMLFeature && !isXMLJSP) {
+			INodeAdapterFactory factory = HTMLValidationAdapterFactory.getInstance();
+			ValidationAdapter adapter = (ValidationAdapter) factory.adapt(document);
+			if (adapter != null) {
+				HTMLValidationReporter rep = getReporter(reporter, file, model);
+				rep.clear();
+				adapter.setReporter(rep);
+				adapter.validate(document);
+			}
+		}
+		if (!hasHTMLFeature && isXMLJSP) {
+			Validator xmlValidator = new Validator();
+			xmlValidator.validate(file, kind, state, monitor);
+		}
+	}
+
+
+	/*
+	 * Mostly copied from HTMLValidator
+	 */
+	private void validate(IReporter reporter, IFile file, IDOMModel model) {
+		if (file == null || model == null)
+			return; // error
+		IDOMDocument document = model.getDocument();
+		if (document == null)
+			return; // error
+
+		// This validator currently only handles validating HTML content in
+		// JSP
+		boolean hasXMLFeature = isXMLJSP(document);
+		boolean hasHTMLFeature = hasHTMLFeature(document);
+		if (hasHTMLFeature && !hasXMLFeature) {
+			INodeAdapterFactory factory = HTMLValidationAdapterFactory.getInstance();
+			ValidationAdapter adapter = (ValidationAdapter) factory.adapt(document);
+			if (adapter == null)
+				return; // error
+
+			HTMLValidationReporter rep = getReporter(reporter, file, model);
+			rep.clear();
+			adapter.setReporter(rep);
+			adapter.validate(document);
+		}
+	}
+
+	public ValidationResult validate(final IResource resource, int kind, ValidationState state, IProgressMonitor monitor) {
+		if (resource.getType() != IResource.FILE)
+			return null;
+
+		ValidationResult result = new ValidationResult();
+		final IReporter reporter = result.getReporter(monitor);
+
+		if (fragmentCheck((IFile) resource)) {
+			IStructuredModel model = null;
+			try {
+				model = StructuredModelManager.getModelManager().getModelForRead((IFile) resource);
+				if (!reporter.isCancelled() && model instanceof IDOMModel) {
+					reporter.removeAllMessages(this, resource);
+					validate((IFile) resource, kind, state, monitor, (IDOMModel) model, reporter);
+				}
+			}
+			catch (IOException e) {
+				Logger.logException(e);
+			}
+			catch (CoreException e) {
+				Logger.logException(e);
+			}
+			finally {
+				if (model != null)
+					model.releaseFromRead();
+			}
+		}
+
+		return result;
+	}
+
+	protected void validateFile(IFile f, IReporter reporter) {
+		IStructuredModel model = null;
+		try {
+			if (fragmentCheck(f)) {
+				model = StructuredModelManager.getModelManager().getModelForRead(f);
+				if (!reporter.isCancelled() && model instanceof IDOMModel) {
+					reporter.removeAllMessages(this, f);
+					validate(reporter, f, (IDOMModel) model);
+				}
+			}
+		}
+		catch (IOException e) {
+			Logger.logException(e);
+		}
+		catch (CoreException e) {
+			Logger.logException(e);
+		}
+		finally {
+			if (model != null)
+				model.releaseFromRead();
+		}
+	}
+
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/validation/JSPDirectiveValidator.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/validation/JSPDirectiveValidator.java
new file mode 100644
index 0000000..a1c9367
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/validation/JSPDirectiveValidator.java
@@ -0,0 +1,729 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.validation;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceVisitor;
+import org.eclipse.core.resources.ProjectScope;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.preferences.DefaultScope;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences;
+import org.eclipse.core.runtime.preferences.IPreferencesService;
+import org.eclipse.core.runtime.preferences.IScopeContext;
+import org.eclipse.core.runtime.preferences.InstanceScope;
+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.jst.jsp.core.internal.JSPCoreMessages;
+import org.eclipse.jst.jsp.core.internal.JSPCorePlugin;
+import org.eclipse.jst.jsp.core.internal.Logger;
+import org.eclipse.jst.jsp.core.internal.contenttype.DeploymentDescriptorPropertyCache;
+import org.eclipse.jst.jsp.core.internal.preferences.JSPCorePreferenceNames;
+import org.eclipse.jst.jsp.core.internal.provisional.JSP11Namespace;
+import org.eclipse.jst.jsp.core.internal.regions.DOMJSPRegionContexts;
+import org.eclipse.jst.jsp.core.internal.util.FacetModuleCoreSupport;
+import org.eclipse.jst.jsp.core.taglib.IJarRecord;
+import org.eclipse.jst.jsp.core.taglib.ITLDRecord;
+import org.eclipse.jst.jsp.core.taglib.ITagDirRecord;
+import org.eclipse.jst.jsp.core.taglib.ITaglibRecord;
+import org.eclipse.jst.jsp.core.taglib.IURLRecord;
+import org.eclipse.jst.jsp.core.taglib.TaglibIndex;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.wst.html.core.internal.contentmodel.JSP20Namespace;
+import org.eclipse.wst.html.core.internal.preferences.HTMLCorePreferenceNames;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+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.text.IRegionComparible;
+import org.eclipse.wst.sse.core.internal.validate.ValidationMessage;
+import org.eclipse.wst.sse.core.utils.StringUtils;
+import org.eclipse.wst.validation.internal.provisional.core.IMessage;
+import org.eclipse.wst.validation.internal.provisional.core.IReporter;
+import org.eclipse.wst.validation.internal.provisional.core.IValidator;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+
+import com.ibm.icu.text.Collator;
+
+/**
+ * Checks for: - duplicate taglib prefix values and reserved taglib prefix
+ * values in the same file
+ */
+public class JSPDirectiveValidator extends JSPValidator {
+	/**
+	 * 
+	 */
+	private static final String PREFERENCE_NODE_QUALIFIER = JSPCorePlugin.getDefault().getBundle().getSymbolicName();
+
+	private static Collator collator = Collator.getInstance(Locale.US);
+
+	private static final boolean DEBUG = Boolean.valueOf(Platform.getDebugOption("org.eclipse.jst.jsp.core/debug/jspvalidator")).booleanValue(); //$NON-NLS-1$
+
+	private IValidator fMessageOriginator;
+	private IEclipsePreferences fPreferences = null;
+
+	private IPreferencesService fPreferencesService = null;
+	private HashMap fPrefixValueRegionToDocumentRegionMap = new HashMap();
+	private IJavaProject fProject = null;
+	private HashMap fReservedPrefixes = new HashMap();
+	private IScopeContext[] fScopes = null;
+	private int fSeverityIncludeFileMissing = -1;
+	private int fSeverityIncludeFileNotSpecified = -1;
+	private int fSeveritySuperClassNotFound = -1;
+	private int fSeverityTagdirUnresolvableURI = -1;
+	private int fSeverityTaglibDuplicatePrefixWithDifferentURIs = -1;
+
+	private int fSeverityTaglibDuplicatePrefixWithSameURIs = -1;
+	private int fSeverityTaglibMissingPrefix = -1;
+
+	private int fSeverityTaglibMissingURI = -1;
+
+
+	private int fSeverityTaglibUnresolvableURI = -1;
+
+	private HashMap fTaglibPrefixesInUse = new HashMap();
+
+	public JSPDirectiveValidator() {
+		initReservedPrefixes();
+		fMessageOriginator = this;
+	}
+
+	public JSPDirectiveValidator(IValidator validator) {
+		initReservedPrefixes();
+		this.fMessageOriginator = validator;
+	}
+
+	/**
+	 * Record that the currently validating resource depends on the given
+	 * file. Only possible during batch (not source) validation.
+	 * 
+	 * @param file
+	 */
+	void addDependsOn(IResource file) {
+		if (fMessageOriginator instanceof JSPBatchValidator) {
+			((JSPBatchValidator) fMessageOriginator).addDependsOn(file);
+		}
+	}
+
+	public void cleanup(IReporter reporter) {
+		super.cleanup(reporter);
+		fTaglibPrefixesInUse.clear();
+		fPrefixValueRegionToDocumentRegionMap.clear();
+	}
+
+	private void collectTaglibPrefix(ITextRegionCollection documentRegion, ITextRegion valueRegion, String taglibPrefix) {
+		fPrefixValueRegionToDocumentRegionMap.put(valueRegion, documentRegion);
+
+		Object o = fTaglibPrefixesInUse.get(taglibPrefix);
+		if (o == null) {
+			// prefix doesn't exist, remember it
+			fTaglibPrefixesInUse.put(taglibPrefix, valueRegion);
+		}
+		else {
+			List regionList = null;
+			// already a List
+			if (o instanceof List) {
+				regionList = (List) o;
+			}
+			/*
+			 * a single value region, create a new List and add previous
+			 * valueRegion
+			 */
+			else {
+				regionList = new ArrayList();
+				regionList.add(o);
+				fTaglibPrefixesInUse.put(taglibPrefix, regionList);
+			}
+			regionList.add(valueRegion);
+		}
+	}
+
+	int getMessageSeverity(String key) {
+		int sev = fPreferencesService.getInt(PREFERENCE_NODE_QUALIFIER, key, IMessage.NORMAL_SEVERITY, fScopes);
+		switch (sev) {
+			case ValidationMessage.ERROR :
+				return IMessage.HIGH_SEVERITY;
+			case ValidationMessage.WARNING :
+				return IMessage.NORMAL_SEVERITY;
+			case ValidationMessage.INFORMATION :
+				return IMessage.LOW_SEVERITY;
+			case ValidationMessage.IGNORE :
+				return ValidationMessage.IGNORE;
+		}
+		return IMessage.NORMAL_SEVERITY;
+	}
+	private void initReservedPrefixes() {
+		fReservedPrefixes.put("jsp", ""); //$NON-NLS-1$ //$NON-NLS-2$
+		fReservedPrefixes.put("jspx", ""); //$NON-NLS-1$ //$NON-NLS-2$
+		fReservedPrefixes.put("java", ""); //$NON-NLS-1$ //$NON-NLS-2$
+		fReservedPrefixes.put("javax", ""); //$NON-NLS-1$ //$NON-NLS-2$ 
+		fReservedPrefixes.put("servlet", ""); //$NON-NLS-1$ //$NON-NLS-2$ 
+		fReservedPrefixes.put("sun", ""); //$NON-NLS-1$ //$NON-NLS-2$ 
+		fReservedPrefixes.put("sunw", ""); //$NON-NLS-1$ //$NON-NLS-2$ 
+	}
+
+	private boolean isReservedTaglibPrefix(String name) {
+		return fReservedPrefixes.get(name) != null;
+	}
+	
+	private void loadPreferences(IFile file) {
+		fScopes = new IScopeContext[]{new InstanceScope(), new DefaultScope()};
+
+		fPreferencesService = Platform.getPreferencesService();
+		if (file != null && file.isAccessible()) {
+			ProjectScope projectScope = new ProjectScope(file.getProject());
+			if (projectScope.getNode(PREFERENCE_NODE_QUALIFIER).getBoolean(JSPCorePreferenceNames.VALIDATION_USE_PROJECT_SETTINGS, false)) {
+				fScopes = new IScopeContext[]{projectScope, new InstanceScope(), new DefaultScope()};
+			}
+		}
+
+		fSeverityIncludeFileMissing = getMessageSeverity(JSPCorePreferenceNames.VALIDATION_DIRECTIVE_INCLUDE_FILE_NOT_FOUND);
+		fSeverityIncludeFileNotSpecified = getMessageSeverity(JSPCorePreferenceNames.VALIDATION_DIRECTIVE_INCLUDE_NO_FILE_SPECIFIED);
+		fSeverityTaglibDuplicatePrefixWithDifferentURIs = getMessageSeverity(JSPCorePreferenceNames.VALIDATION_DIRECTIVE_TAGLIB_DUPLICATE_PREFIXES_DIFFERENT_URIS);
+		fSeverityTaglibDuplicatePrefixWithSameURIs = getMessageSeverity(JSPCorePreferenceNames.VALIDATION_DIRECTIVE_TAGLIB_DUPLICATE_PREFIXES_SAME_URIS);
+		fSeverityTaglibMissingPrefix = getMessageSeverity(JSPCorePreferenceNames.VALIDATION_DIRECTIVE_TAGLIB_MISSING_PREFIX);
+		fSeverityTaglibMissingURI = getMessageSeverity(JSPCorePreferenceNames.VALIDATION_DIRECTIVE_TAGLIB_MISSING_URI_OR_TAGDIR);
+		fSeverityTaglibUnresolvableURI = getMessageSeverity(JSPCorePreferenceNames.VALIDATION_DIRECTIVE_TAGLIB_UNRESOLVABLE_URI_OR_TAGDIR);
+		fSeverityTagdirUnresolvableURI = getMessageSeverity(JSPCorePreferenceNames.VALIDATION_DIRECTIVE_TAGLIB_UNRESOLVABLE_URI_OR_TAGDIR);
+		fSeveritySuperClassNotFound = getMessageSeverity(JSPCorePreferenceNames.VALIDATION_DIRECTIVE_PAGE_SUPERCLASS_NOT_FOUND);
+
+	}
+	
+	protected void performValidation(IFile f, IReporter reporter, IStructuredDocument sDoc) {
+		loadPreferences(f);
+		
+		
+		setProject(f.getProject());
+		/*
+		 * when validating an entire file need to clear dupes or else you're
+		 * comparing between files
+		 */
+		fPrefixValueRegionToDocumentRegionMap.clear();
+		fTaglibPrefixesInUse.clear();
+
+		IRegionComparible comparer = null;
+		if (sDoc instanceof IRegionComparible)
+			comparer = (IRegionComparible) sDoc;
+		
+		// iterate all document regions
+		IStructuredDocumentRegion region = sDoc.getFirstStructuredDocumentRegion();
+		while (region != null && !reporter.isCancelled()) {
+			// only checking directives
+			if (region.getType() == DOMJSPRegionContexts.JSP_DIRECTIVE_NAME) {
+				processDirective(reporter, f, sDoc, region);
+			}
+			//To check directives inside script tag.
+			else if (region.getType() == DOMRegionContext.BLOCK_TEXT) {
+				Iterator it = region.getRegions().iterator();
+				while (it.hasNext()) {
+					Object blockRegion = it.next();
+					if (blockRegion instanceof ITextRegionCollection) {
+						processDirective(reporter, f, sDoc, (ITextRegionCollection)blockRegion);
+					}
+				}
+			}
+			// requires tag name, attribute, equals, and value
+			else if (comparer != null && region.getNumberOfRegions() > 4) {
+				ITextRegion nameRegion = region.getRegions().get(1);
+				if (comparer.regionMatches(region.getStartOffset(nameRegion), nameRegion.getTextLength(), "jsp:include")) { //$NON-NLS-1$
+					processInclude(reporter, f, sDoc, region, JSP11Namespace.ATTR_NAME_PAGE);
+				}
+				// https://bugs.eclipse.org/bugs/show_bug.cgi?id=295950
+				else if (comparer.regionMatches(region.getStartOffset(nameRegion), 14, "jsp:directive.")) { //$NON-NLS-1$
+					processDirective(reporter, f, sDoc, region);
+				}
+
+			}
+			region = region.getNext();
+		}
+
+		if (!reporter.isCancelled()) {
+			reportTaglibDuplicatePrefixes(f, reporter, sDoc);
+		}
+
+		fPrefixValueRegionToDocumentRegionMap.clear();
+		fTaglibPrefixesInUse.clear();
+		setProject(null);
+		unloadPreferences();
+	}
+
+	private void processDirective(IReporter reporter, IFile file, IStructuredDocument sDoc, ITextRegionCollection documentRegion) {
+		String directiveName = getDirectiveName(documentRegion);
+
+		if (directiveName.endsWith("taglib")) { //$NON-NLS-1$
+			processTaglibDirective(reporter, file, sDoc, documentRegion);
+		}
+		else if (directiveName.equals("jsp:include")) { //$NON-NLS-1$
+			processInclude(reporter, file, sDoc, documentRegion, JSP11Namespace.ATTR_NAME_PAGE);
+		}
+		else if (directiveName.endsWith("include")) { //$NON-NLS-1$
+			processInclude(reporter, file, sDoc, documentRegion, JSP11Namespace.ATTR_NAME_FILE);
+		}
+		else if (directiveName.endsWith("page")) { //$NON-NLS-1$
+			processPageDirective(reporter, file, sDoc, documentRegion);
+		}
+	}
+
+	private void processInclude(IReporter reporter, IFile file, IStructuredDocument sDoc, ITextRegionCollection documentRegion, String attrName) {
+		ITextRegion fileValueRegion = getAttributeValueRegion(documentRegion, attrName);
+		// There is a file and it isn't a nested region which could contain a JSP expression
+		if (fileValueRegion != null && !hasNestedRegion(fileValueRegion)) {
+			// file specified
+			String fileValue = documentRegion.getText(fileValueRegion);
+			fileValue = StringUtils.stripQuotes(fileValue);
+
+			if (fileValue.length() == 0 && fSeverityIncludeFileNotSpecified != ValidationMessage.IGNORE) {
+				// file value is specified but empty
+				String msgText = NLS.bind(JSPCoreMessages.JSPDirectiveValidator_3, attrName);
+				LocalizedMessage message = new LocalizedMessage(fSeverityIncludeFileNotSpecified, msgText, file);
+				int start = documentRegion.getStartOffset(fileValueRegion);
+				int length = fileValueRegion.getTextLength();
+				int lineNo = sDoc.getLineOfOffset(start);
+				message.setLineNo(lineNo + 1);
+				message.setOffset(start);
+				message.setLength(length);
+
+				reporter.addMessage(fMessageOriginator, message);
+			}
+			else if (DeploymentDescriptorPropertyCache.getInstance().getURLMapping(file.getFullPath(), fileValue) == null) {
+				IPath testPath = FacetModuleCoreSupport.resolve(file.getFullPath(), fileValue);
+				if (testPath.segmentCount() > 1) {
+					IFile testFile = file.getWorkspace().getRoot().getFile(testPath);
+					addDependsOn(testFile);
+					if (!testFile.isAccessible()) {
+						if (fSeverityIncludeFileMissing != ValidationMessage.IGNORE) {
+							// File not found
+							String msgText = NLS.bind(JSPCoreMessages.JSPDirectiveValidator_4, new String[]{fileValue, testPath.toString()});
+							LocalizedMessage message = new LocalizedMessage(fSeverityIncludeFileMissing, msgText, file);
+							int start = documentRegion.getStartOffset(fileValueRegion);
+							int length = fileValueRegion.getTextLength();
+							int lineNo = sDoc.getLineOfOffset(start);
+							message.setLineNo(lineNo + 1);
+							message.setOffset(start);
+							message.setLength(length);
+
+							reporter.addMessage(fMessageOriginator, message);
+						}
+					}
+				}
+			}
+		}
+		else if (fileValueRegion == null && fSeverityIncludeFileNotSpecified != ValidationMessage.IGNORE) {
+			// file is not specified at all
+			String msgText = NLS.bind(JSPCoreMessages.JSPDirectiveValidator_3, attrName);
+			LocalizedMessage message = new LocalizedMessage(fSeverityIncludeFileNotSpecified, msgText, file);
+			int start = documentRegion.getStartOffset();
+			int length = documentRegion.getTextLength();
+			int lineNo = sDoc.getLineOfOffset(start);
+			message.setLineNo(lineNo + 1);
+			message.setOffset(start);
+			message.setLength(length);
+
+			reporter.addMessage(fMessageOriginator, message);
+		}
+	}
+
+	/**
+	 * @param reporter
+	 * @param file
+	 * @param doc
+	 * @param documentRegion
+	 */
+	private void processPageDirective(IReporter reporter, IFile file, IStructuredDocument doc, ITextRegionCollection documentRegion) {
+		ITextRegion superclassValueRegion = getAttributeValueRegion(documentRegion, JSP11Namespace.ATTR_NAME_EXTENDS);
+		if (superclassValueRegion != null) {
+			// file specified
+			String superclassName = documentRegion.getText(superclassValueRegion);
+			superclassName = StringUtils.stripQuotes(superclassName);
+
+			IType superClass = null;
+			if (superclassName != null && superclassName.length() > 0 && fProject != null && fProject.exists()) {
+				try {
+					superClass = fProject.findType(superclassName.trim(), new NullProgressMonitor());
+				}
+				catch (JavaModelException e) {
+					Logger.logException(e);
+				}
+			}
+
+			if (superClass == null && fSeveritySuperClassNotFound != ValidationMessage.IGNORE) {
+				// superclass not found
+				String msgText = NLS.bind(JSPCoreMessages.JSPDirectiveValidator_8, superclassName);
+				LocalizedMessage message = new LocalizedMessage(fSeveritySuperClassNotFound, msgText, file);
+				int start = documentRegion.getStartOffset(superclassValueRegion);
+				int length = superclassValueRegion.getTextLength();
+				int lineNo = doc.getLineOfOffset(start);
+				message.setLineNo(lineNo + 1);
+				message.setOffset(start);
+				message.setLength(length);
+
+				reporter.addMessage(fMessageOriginator, message);
+			}
+		}
+	}
+
+	private void processTaglibDirective(IReporter reporter, IFile file, IStructuredDocument sDoc, ITextRegionCollection documentRegion) {
+		ITextRegion prefixValueRegion = null;
+		ITextRegion uriValueRegion = getAttributeValueRegion(documentRegion, JSP11Namespace.ATTR_NAME_URI);
+		ITextRegion tagdirValueRegion = getAttributeValueRegion(documentRegion, JSP20Namespace.ATTR_NAME_TAGDIR);
+		if (uriValueRegion != null) {
+			// URI is specified
+			String uri = documentRegion.getText(uriValueRegion);
+
+			if (file != null) {
+				uri = StringUtils.stripQuotes(uri);
+				if (uri.length() > 0) {
+					ITaglibRecord reference = TaglibIndex.resolve(file.getFullPath().toString(), uri, false);
+					if (reference != null) {
+						switch (reference.getRecordType()) {
+							case (ITaglibRecord.TLD) : {
+								ITLDRecord record = (ITLDRecord) reference;
+								IResource tldfile = ResourcesPlugin.getWorkspace().getRoot().getFile(record.getPath());
+								addDependsOn(tldfile);
+							}
+								break;
+							case (ITaglibRecord.JAR) : {
+								IJarRecord record = (IJarRecord) reference;
+								IFile[] foundFilesForLocation = ResourcesPlugin.getWorkspace().getRoot().findFilesForLocation(record.getLocation());
+								for (int i = 0; i < foundFilesForLocation.length; i++) {
+									addDependsOn(foundFilesForLocation[i]);
+								}
+							}
+								break;
+							case (ITaglibRecord.TAGDIR) : {
+								ITagDirRecord record = (ITagDirRecord) reference;
+								IPath path = record.getPath();
+								IResource found = ResourcesPlugin.getWorkspace().getRoot().findMember(path, false);
+
+								try {
+									found.accept(new IResourceVisitor() {
+										public boolean visit(IResource resource) throws CoreException {
+											if (resource.getType() == IResource.FILE) {
+												addDependsOn(resource);
+											}
+											return true;
+										}
+									});
+								}
+								catch (CoreException e) {
+									Logger.logException(e);
+								}
+							}
+								break;
+							case (ITaglibRecord.URL) : {
+								IURLRecord record = (IURLRecord) reference;
+								String baseLocation = record.getBaseLocation();
+								if (baseLocation != null && baseLocation.indexOf("://") < 0) {
+									IResource found = ResourcesPlugin.getWorkspace().getRoot().findMember(baseLocation, false);
+									if (found != null) {
+										try {
+											found.accept(new IResourceVisitor() {
+												public boolean visit(IResource resource) throws CoreException {
+													if (resource.getType() == IResource.FILE) {
+														addDependsOn(resource);
+													}
+													return true;
+												}
+											});
+										}
+										catch (CoreException e) {
+											Logger.logException(e);
+										}
+									}
+									else {
+										IFile externalJar = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(new Path(baseLocation));
+										if (externalJar != null) {
+											addDependsOn(externalJar);
+										}
+									}
+								}
+							}
+								break;
+						}
+					}
+					if (reference == null && fSeverityTaglibUnresolvableURI != ValidationMessage.IGNORE) {
+						// URI specified but does not resolve
+						String msgText = null;
+						// provide better messages for typical "http:*" URIs
+						if (uri.startsWith("http:") && DeploymentDescriptorPropertyCache.getInstance().getJSPVersion(file.getFullPath()) < 1.2) { //$NON-NLS-1$
+							if (FacetModuleCoreSupport.isDynamicWebProject(file.getProject())) {
+								msgText = NLS.bind(JSPCoreMessages.JSPDirectiveValidator_9, uri);
+							}
+							else {
+								msgText = NLS.bind(JSPCoreMessages.JSPDirectiveValidator_10, uri);
+							}
+						}
+						else {
+							msgText = NLS.bind(JSPCoreMessages.JSPDirectiveValidator_1, uri);
+						}
+						LocalizedMessage message = new LocalizedMessage(fSeverityTaglibUnresolvableURI, msgText, file);
+						int start = documentRegion.getStartOffset(uriValueRegion);
+						int length = uriValueRegion.getTextLength();
+						int lineNo = sDoc.getLineOfOffset(start);
+						message.setLineNo(lineNo + 1);
+						message.setOffset(start);
+						message.setLength(length);
+
+						message.setAttribute("PROBLEM_ID", new Integer(611)); //$NON-NLS-1$
+
+						reporter.addMessage(fMessageOriginator, message);
+					}
+				}
+				else if (fSeverityTaglibMissingURI != ValidationMessage.IGNORE) {
+					// URI specified but empty string
+					String msgText = NLS.bind(JSPCoreMessages.JSPDirectiveValidator_3, JSP11Namespace.ATTR_NAME_URI);
+					LocalizedMessage message = new LocalizedMessage(fSeverityTaglibMissingURI, msgText, file);
+					int start = documentRegion.getStartOffset(uriValueRegion);
+					int length = uriValueRegion.getTextLength();
+					int lineNo = sDoc.getLineOfOffset(start);
+					message.setLineNo(lineNo + 1);
+					message.setOffset(start);
+					message.setLength(length);
+
+					reporter.addMessage(fMessageOriginator, message);
+				}
+			}
+		}
+		else if (tagdirValueRegion != null) {
+			// URI is specified
+			String tagdir = documentRegion.getText(tagdirValueRegion);
+
+			if (file != null) {
+				tagdir = StringUtils.stripQuotes(tagdir);
+				if (tagdir.length() <= 0 && fSeverityTaglibMissingURI != ValidationMessage.IGNORE) {
+					// tagdir specified but empty string
+					String msgText = NLS.bind(JSPCoreMessages.JSPDirectiveValidator_3, JSP20Namespace.ATTR_NAME_TAGDIR);
+					LocalizedMessage message = new LocalizedMessage(fSeverityTaglibMissingURI, msgText, file);
+					int start = documentRegion.getStartOffset(tagdirValueRegion);
+					int length = tagdirValueRegion.getTextLength();
+					int lineNo = sDoc.getLineOfOffset(start);
+					message.setLineNo(lineNo + 1);
+					message.setOffset(start);
+					message.setLength(length);
+
+					reporter.addMessage(fMessageOriginator, message);
+				}
+				else if (TaglibIndex.resolve(file.getFullPath().toString(), tagdir, false) == null && fSeverityTagdirUnresolvableURI != ValidationMessage.IGNORE) {
+					// URI specified but does not resolve
+					String msgText = NLS.bind(JSPCoreMessages.JSPDirectiveValidator_11, tagdir);
+					LocalizedMessage message = new LocalizedMessage(fSeverityTaglibUnresolvableURI, msgText, file);
+					int start = documentRegion.getStartOffset(tagdirValueRegion);
+					int length = tagdirValueRegion.getTextLength();
+					int lineNo = sDoc.getLineOfOffset(start);
+					message.setLineNo(lineNo + 1);
+					message.setOffset(start);
+					message.setLength(length);
+
+					reporter.addMessage(fMessageOriginator, message);
+				}
+			}
+		}
+		else if (fSeverityTaglibMissingURI != ValidationMessage.IGNORE) {
+			// URI not specified or empty string
+			String msgText = NLS.bind(JSPCoreMessages.JSPDirectiveValidator_7, new String[]{JSP20Namespace.ATTR_NAME_TAGDIR, JSP11Namespace.ATTR_NAME_URI});
+			LocalizedMessage message = new LocalizedMessage(fSeverityTaglibMissingURI, msgText, file);
+			int start = documentRegion.getStartOffset();
+			int length = documentRegion.getTextLength();
+			int lineNo = sDoc.getLineOfOffset(start);
+			message.setLineNo(lineNo + 1);
+			message.setOffset(start);
+			message.setLength(length);
+
+			reporter.addMessage(fMessageOriginator, message);
+		}
+
+		prefixValueRegion = getAttributeValueRegion(documentRegion, JSP11Namespace.ATTR_NAME_PREFIX);
+		if (prefixValueRegion != null) {
+			// prefix specified
+			String taglibPrefix = documentRegion.getText(prefixValueRegion);
+			taglibPrefix = StringUtils.stripQuotes(taglibPrefix);
+
+			collectTaglibPrefix(documentRegion, prefixValueRegion, taglibPrefix);
+
+			if (isReservedTaglibPrefix(taglibPrefix)) {
+				// prefix is a reserved prefix
+				String msgText = NLS.bind(JSPCoreMessages.JSPDirectiveValidator_0, taglibPrefix);
+				int sev = IMessage.HIGH_SEVERITY;
+				LocalizedMessage message = (file == null ? new LocalizedMessage(sev, msgText) : new LocalizedMessage(sev, msgText, file));
+				int start = documentRegion.getStartOffset(prefixValueRegion);
+				int length = prefixValueRegion.getTextLength();
+				int lineNo = sDoc.getLineOfOffset(start);
+				message.setLineNo(lineNo + 1);
+				message.setOffset(start);
+				message.setLength(length);
+
+				reporter.addMessage(fMessageOriginator, message);
+			}
+			if (taglibPrefix.length() == 0 && fSeverityTaglibMissingPrefix != ValidationMessage.IGNORE) {
+				// prefix is specified but empty
+				String msgText = NLS.bind(JSPCoreMessages.JSPDirectiveValidator_3, JSP11Namespace.ATTR_NAME_PREFIX);
+				LocalizedMessage message = new LocalizedMessage(fSeverityTaglibMissingPrefix, msgText, file);
+				int start = documentRegion.getStartOffset(prefixValueRegion);
+				int length = prefixValueRegion.getTextLength();
+				int lineNo = sDoc.getLineOfOffset(start);
+				message.setLineNo(lineNo + 1);
+				message.setOffset(start);
+				message.setLength(length);
+
+				reporter.addMessage(fMessageOriginator, message);
+			}
+		}
+		else if (fSeverityTaglibMissingPrefix != ValidationMessage.IGNORE) {
+			// prefix is not specified
+			String msgText = NLS.bind(JSPCoreMessages.JSPDirectiveValidator_3, JSP11Namespace.ATTR_NAME_PREFIX);
+			LocalizedMessage message = new LocalizedMessage(fSeverityTaglibMissingPrefix, msgText, file);
+			int start = documentRegion.getStartOffset();
+			int length = documentRegion.getTextLength();
+			int lineNo = sDoc.getLineOfOffset(start);
+			message.setLineNo(lineNo + 1);
+			message.setOffset(start);
+			message.setLength(length);
+
+			reporter.addMessage(fMessageOriginator, message);
+		}
+	}
+
+	private void reportTaglibDuplicatePrefixes(IFile file, IReporter reporter, IStructuredDocument document) {
+		if (fSeverityTaglibDuplicatePrefixWithDifferentURIs == ValidationMessage.IGNORE && fSeverityTaglibDuplicatePrefixWithSameURIs == ValidationMessage.IGNORE)
+			return;
+
+		String[] prefixes = (String[]) fTaglibPrefixesInUse.keySet().toArray(new String[0]);
+		for (int prefixNumber = 0; prefixNumber < prefixes.length; prefixNumber++) {
+			int severity = fSeverityTaglibDuplicatePrefixWithSameURIs;
+
+			Object o = fTaglibPrefixesInUse.get(prefixes[prefixNumber]);
+			/*
+			 * Only care if it's a List (because there was more than one
+			 * directive with that prefix) and if we're supposed to report
+			 * duplicates
+			 */
+			if (o instanceof List) {
+				List valueRegions = (List) o;
+				String uri = null;
+				for (int regionNumber = 0; regionNumber < valueRegions.size(); regionNumber++) {
+					ITextRegionCollection documentRegion = (ITextRegionCollection) fPrefixValueRegionToDocumentRegionMap.get(valueRegions.get(regionNumber));
+					ITextRegion uriValueRegion = getAttributeValueRegion(documentRegion, JSP11Namespace.ATTR_NAME_URI);
+					if (uriValueRegion == null) {
+						uriValueRegion = getAttributeValueRegion(documentRegion, JSP20Namespace.ATTR_NAME_TAGDIR);
+					}
+					if (uriValueRegion != null) {
+						String uri2 = StringUtils.stripQuotes(documentRegion.getText(uriValueRegion));
+						if (uri == null) {
+							uri = uri2;
+						}
+						else {
+							if (collator.compare(uri, uri2) != 0) {
+								severity = fSeverityTaglibDuplicatePrefixWithDifferentURIs;
+							}
+						}
+					}
+				}
+
+				if (severity != ValidationMessage.IGNORE) {
+					String msgText = NLS.bind(JSPCoreMessages.JSPDirectiveValidator_2, prefixes[prefixNumber]); //$NON-NLS-2$ //$NON-NLS-1$
+
+					// Report an error in all directives using this prefix
+					for (int regionNumber = 0; regionNumber < valueRegions.size(); regionNumber++) {
+
+						ITextRegion valueRegion = (ITextRegion) valueRegions.get(regionNumber);
+						ITextRegionCollection documentRegion = (ITextRegionCollection) fPrefixValueRegionToDocumentRegionMap.get(valueRegion);
+						LocalizedMessage message = (file == null ? new LocalizedMessage(severity, msgText) : new LocalizedMessage(severity, msgText, file));
+
+						// if there's a message, there was an error found
+						int start = documentRegion.getStartOffset(valueRegion);
+						int length = valueRegion.getTextLength();
+						int lineNo = document.getLineOfOffset(start);
+						message.setLineNo(lineNo + 1);
+						message.setOffset(start);
+						message.setLength(length);
+
+						reporter.addMessage(fMessageOriginator, message);
+					}
+				}
+			}
+		}
+	}
+
+	/**
+	 * @param project
+	 */
+	private void setProject(IProject project) {
+		boolean useProject = false;
+		if (project != null) {
+			fProject = JavaCore.create(project);
+			fPreferences = new ProjectScope(fProject.getProject()).getNode(PREFERENCE_NODE_QUALIFIER);
+			useProject = fPreferences.getBoolean(HTMLCorePreferenceNames.USE_PROJECT_SETTINGS, false);
+		}
+		else {
+			fProject = null;
+		}
+
+		if (!useProject) {
+			fPreferences = new InstanceScope().getNode(PREFERENCE_NODE_QUALIFIER);
+		}
+	}
+
+	private void unloadPreferences() {
+		fPreferencesService = null;
+		fScopes = null;
+	}
+	
+	/**
+	 * True if container has nested regions, meaning container is probably too
+	 * complicated (like JSP expressions or EL) to validate with this validator.
+	 */
+	private boolean hasNestedRegion(ITextRegion container) {
+		return (container instanceof ITextRegionContainer && ((ITextRegionContainer) container).getRegions() != null);
+	}
+
+	/**
+	 * batch validation call
+	 */
+	protected void validateFile(IFile f, IReporter reporter) {
+		if (DEBUG) {
+			Logger.log(Logger.INFO, getClass().getName() + " validating: " + f); //$NON-NLS-1$
+		}
+
+		IStructuredModel sModel = null;
+		try {
+			sModel = StructuredModelManager.getModelManager().getModelForRead(f);
+			if (sModel != null && !reporter.isCancelled()) {
+				performValidation(f, reporter, sModel.getStructuredDocument());
+			}
+		}
+		catch (Exception e) {
+			Logger.logException(e);
+		}
+		finally {
+			if (sModel != null)
+				sModel.releaseFromRead();
+		}
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/validation/JSPELValidator.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/validation/JSPELValidator.java
new file mode 100644
index 0000000..cf84532
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/validation/JSPELValidator.java
@@ -0,0 +1,222 @@
+/*******************************************************************************
+ Copyright (c) 2005, 2008 BEA Systems 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:
+ *     BEA Systems - initial implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.validation;
+
+import java.util.Iterator;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.ProjectScope;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.preferences.DefaultScope;
+import org.eclipse.core.runtime.preferences.IPreferencesService;
+import org.eclipse.core.runtime.preferences.IScopeContext;
+import org.eclipse.core.runtime.preferences.InstanceScope;
+import org.eclipse.jst.jsp.core.internal.JSPCoreMessages;
+import org.eclipse.jst.jsp.core.internal.JSPCorePlugin;
+import org.eclipse.jst.jsp.core.internal.Logger;
+import org.eclipse.jst.jsp.core.internal.java.jspel.JSPELParser;
+import org.eclipse.jst.jsp.core.internal.java.jspel.ParseException;
+import org.eclipse.jst.jsp.core.internal.java.jspel.Token;
+import org.eclipse.jst.jsp.core.internal.java.jspel.TokenMgrError;
+import org.eclipse.jst.jsp.core.internal.preferences.JSPCorePreferenceNames;
+import org.eclipse.jst.jsp.core.internal.regions.DOMJSPRegionContexts;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+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.validate.ValidationMessage;
+import org.eclipse.wst.validation.internal.core.Message;
+import org.eclipse.wst.validation.internal.provisional.core.IMessage;
+import org.eclipse.wst.validation.internal.provisional.core.IReporter;
+import org.eclipse.wst.validation.internal.provisional.core.IValidator;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+
+
+public class JSPELValidator extends JSPValidator {
+	private static final boolean DEBUG = Boolean.valueOf(Platform.getDebugOption("org.eclipse.jst.jsp.core/debug/jspvalidator")).booleanValue(); //$NON-NLS-1$		
+	private static final String PREFERENCE_NODE_QUALIFIER = JSPCorePlugin.getDefault().getBundle().getSymbolicName();
+	private static final int MAX_REGIONS = 1000;
+	
+	private IValidator fMessageOriginator;
+
+	public JSPELValidator() {
+		this.fMessageOriginator = this;
+	}
+
+	public JSPELValidator(IValidator validator) {
+		this.fMessageOriginator = validator;
+	}
+
+	protected void validateFile(IFile file, IReporter reporter) {
+		if (DEBUG) {
+			Logger.log(Logger.INFO, getClass().getName() + " validating: " + file); //$NON-NLS-1$
+		}
+
+		IStructuredModel model = null;
+		try {
+			model = StructuredModelManager.getModelManager().getModelForRead(file);
+			if (!reporter.isCancelled() && model != null) {
+				performValidation(file, reporter, model.getStructuredDocument());
+			}
+		}
+		catch (Exception e) {
+			Logger.logException(e);
+		}
+		finally {
+			if (null != model)
+				model.releaseFromRead();
+		}
+	}
+
+	private IPreferencesService fPreferencesService = null;
+	private IScopeContext[] fScopes = null;
+
+	private void loadPreferences(IFile file) {
+		fScopes = new IScopeContext[]{new InstanceScope(), new DefaultScope()};
+
+		fPreferencesService = Platform.getPreferencesService();
+		if (file != null && file.isAccessible()) {
+			ProjectScope projectScope = new ProjectScope(file.getProject());
+			if (projectScope.getNode(PREFERENCE_NODE_QUALIFIER).getBoolean(JSPCorePreferenceNames.VALIDATION_USE_PROJECT_SETTINGS, false)) {
+				fScopes = new IScopeContext[]{projectScope, new InstanceScope(), new DefaultScope()};
+			}
+		}
+	}
+	
+	int getMessageSeverity(String key) {
+		int sev = fPreferencesService.getInt(PREFERENCE_NODE_QUALIFIER, key, IMessage.NORMAL_SEVERITY, fScopes);
+		switch (sev) {
+			case ValidationMessage.ERROR :
+				return IMessage.HIGH_SEVERITY;
+			case ValidationMessage.WARNING :
+				return IMessage.NORMAL_SEVERITY;
+			case ValidationMessage.INFORMATION :
+				return IMessage.LOW_SEVERITY;
+			case ValidationMessage.IGNORE :
+				return ValidationMessage.IGNORE;
+		}
+		return IMessage.NORMAL_SEVERITY;
+	}
+	
+	private void unloadPreferences() {
+		fPreferencesService = null;
+		fScopes = null;
+	}
+
+	protected void performValidation(IFile file, IReporter reporter, IStructuredDocument structuredDoc) {
+		loadPreferences(file);
+		IStructuredDocumentRegion curNode = structuredDoc.getFirstStructuredDocumentRegion();
+		while (null != curNode && !reporter.isCancelled()) {
+			if (curNode.getType() != DOMRegionContext.XML_COMMENT_TEXT && curNode.getType() != DOMRegionContext.XML_CDATA_TEXT && curNode.getType() != DOMRegionContext.UNDEFINED) {
+				validateRegionContainer(curNode, reporter, file);
+			}
+			curNode = curNode.getNext();
+		}
+		unloadPreferences();
+	}
+
+	protected void validateRegionContainer(ITextRegionCollection container, IReporter reporter, IFile file) {
+		ITextRegionCollection containerRegion = container;
+		Iterator regions = containerRegion.getRegions().iterator();
+		ITextRegion region = null;
+		while (regions.hasNext() && !reporter.isCancelled()) {
+			region = (ITextRegion) regions.next();
+			String type = region.getType();
+			if (type != null && region instanceof ITextRegionCollection) {
+				ITextRegionCollection parentRegion = ((ITextRegionCollection) region);
+				Iterator childRegions = parentRegion.getRegions().iterator();
+				while (childRegions.hasNext() && !reporter.isCancelled()) {
+					ITextRegion childRegion = (ITextRegion) childRegions.next();
+					/* [136795] Validate everything in the EL container, not just JSP_EL_CONTENT */
+					if (childRegion.getType() == DOMJSPRegionContexts.JSP_EL_OPEN)
+						validateELContent(parentRegion, childRegion, childRegions, reporter, file);
+				}
+			}
+		}
+	}
+	
+	protected void validateELContent(ITextRegionCollection container, ITextRegion elOpenRegion, Iterator elRegions, IReporter reporter, IFile file) {
+		int contentStart = elOpenRegion.getEnd();
+		int contentDocStart = container.getEndOffset(elOpenRegion);
+		int contentLength = container.getLength();
+		int regionCount = 0;
+		ITextRegion elRegion = null;
+		/* Find the EL closing region, otherwise the last region will be used to calculate the EL content text */
+		while (elRegions != null && elRegions.hasNext() && (regionCount++ < MAX_REGIONS)) {
+			elRegion = (ITextRegion) elRegions.next();
+			if (elRegion.getType() == DOMJSPRegionContexts.JSP_EL_CLOSE)
+				break;
+		}
+		
+		String elText = container.getFullText().substring(contentStart, (elRegion != null) ? elRegion.getStart() : (contentLength - 1));
+		JSPELParser elParser = JSPELParser.createParser(elText);
+		try {
+			elParser.Expression();
+		}
+		catch (ParseException e) {
+			int sev = getMessageSeverity(JSPCorePreferenceNames.VALIDATION_EL_SYNTAX);
+			if (sev != ValidationMessage.IGNORE) {
+				Token curTok = e.currentToken;
+				int problemStartOffset = contentDocStart + curTok.beginColumn;
+				Message message = new LocalizedMessage(sev, JSPCoreMessages.JSPEL_Syntax);
+				message.setOffset(problemStartOffset);
+				message.setLength(curTok.endColumn - curTok.beginColumn + 1);
+				message.setTargetObject(file);
+				reporter.addMessage(fMessageOriginator, message);
+			}
+		}
+		catch (TokenMgrError te) {
+			int sev = getMessageSeverity(JSPCorePreferenceNames.VALIDATION_EL_LEXER);
+			if (sev != ValidationMessage.IGNORE) {
+				Message message = new LocalizedMessage(IMessage.NORMAL_SEVERITY, JSPCoreMessages.JSPEL_Token);
+				message.setOffset(contentDocStart);
+				message.setLength(contentLength);
+				message.setTargetObject(file);
+				reporter.addMessage(fMessageOriginator, message);
+			}
+		}
+	}
+
+	protected void validateXMLNode(ITextRegionCollection container, ITextRegion region, IReporter reporter, IFile file) {
+		String elText = container.getText(region);
+		JSPELParser elParser = JSPELParser.createParser(elText);
+		int contentStart = container.getStartOffset(region);
+		int contentLength = container.getLength();
+		try {
+			elParser.Expression();
+		}
+		catch (ParseException e) {
+			int sev = getMessageSeverity(JSPCorePreferenceNames.VALIDATION_EL_SYNTAX);
+			if (sev != ValidationMessage.IGNORE) {
+				Token curTok = e.currentToken;
+				int problemStartOffset = contentStart + curTok.beginColumn;
+				Message message = new LocalizedMessage(sev, JSPCoreMessages.JSPEL_Syntax);
+				message.setOffset(problemStartOffset);
+				message.setLength(curTok.endColumn - curTok.beginColumn + 1);
+				message.setTargetObject(file);
+				reporter.addMessage(fMessageOriginator, message);
+			}
+		}
+		catch (TokenMgrError te) {
+			int sev = getMessageSeverity(JSPCorePreferenceNames.VALIDATION_EL_LEXER);
+			if (sev != ValidationMessage.IGNORE) {
+				Message message = new LocalizedMessage(IMessage.NORMAL_SEVERITY, JSPCoreMessages.JSPEL_Token);
+				message.setOffset(contentStart);
+				message.setLength(contentLength);
+				message.setTargetObject(file);
+				reporter.addMessage(fMessageOriginator, message);
+			}
+		}
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/validation/JSPJavaValidator.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/validation/JSPJavaValidator.java
new file mode 100644
index 0000000..9bd15ab
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/validation/JSPJavaValidator.java
@@ -0,0 +1,445 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.validation;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ProjectScope;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.preferences.DefaultScope;
+import org.eclipse.core.runtime.preferences.IPreferencesService;
+import org.eclipse.core.runtime.preferences.IScopeContext;
+import org.eclipse.core.runtime.preferences.InstanceScope;
+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.JSPCorePlugin;
+import org.eclipse.jst.jsp.core.internal.Logger;
+import org.eclipse.jst.jsp.core.internal.java.IJSPProblem;
+import org.eclipse.jst.jsp.core.internal.java.IJSPTranslation;
+import org.eclipse.jst.jsp.core.internal.java.JSPTranslation;
+import org.eclipse.jst.jsp.core.internal.java.JSPTranslationAdapter;
+import org.eclipse.jst.jsp.core.internal.java.JSPTranslationExtension;
+import org.eclipse.jst.jsp.core.internal.modelhandler.ModelHandlerForJSP;
+import org.eclipse.jst.jsp.core.internal.preferences.JSPCorePreferenceNames;
+import org.eclipse.jst.jsp.core.internal.regions.DOMJSPRegionContexts;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+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.validate.ValidationMessage;
+import org.eclipse.wst.validation.internal.provisional.core.IMessage;
+import org.eclipse.wst.validation.internal.provisional.core.IReporter;
+import org.eclipse.wst.validation.internal.provisional.core.IValidator;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
+
+public class JSPJavaValidator extends JSPValidator {
+	private static final boolean DEBUG = Boolean.valueOf(Platform.getDebugOption("org.eclipse.jst.jsp.core/debug/jspvalidator")).booleanValue(); //$NON-NLS-1$
+	private IValidator fMessageOriginator;
+
+	private IPreferencesService fPreferencesService = Platform.getPreferencesService();
+	private static final String PREFERENCE_NODE_QUALIFIER = JSPCorePlugin.getDefault().getBundle().getSymbolicName();
+	private IScopeContext[] fScopes = null;
+	
+	private static final boolean UPDATE_JAVA_TASKS = true;
+	private static final String JAVA_TASK_MARKER_TYPE = "org.eclipse.jdt.core.task"; //$NON-NLS-1$
+	private static final String[] DEPEND_ONs = new String[]{".classpath", ".project", ".settings/org.eclipse.jdt.core.prefs", ".settings/org.eclipse.jst.jsp.core.prefs", ".settings/org.eclipse.wst.common.project.facet.core.xml", ".settings/org.eclipse.wst.common.component"};
+
+	public JSPJavaValidator() {
+		this.fMessageOriginator = this;
+	}
+
+	public JSPJavaValidator(IValidator validator) {
+		this.fMessageOriginator = validator;
+	}
+
+	/**
+	 * Assumed the message offset is an indirect position. In other words, an
+	 * error from an included file.
+	 * 
+	 * @param m
+	 * @param translation
+	 */
+	private void adjustIndirectPosition(IMessage m, IJSPTranslation translation) {
+
+		if (!(translation instanceof JSPTranslationExtension))
+			return;
+
+		IDocument jspDoc = ((JSPTranslationExtension) translation).getJspDocument();
+		if (!(jspDoc instanceof IStructuredDocument))
+			return;
+
+		IStructuredDocument sDoc = (IStructuredDocument) jspDoc;
+		IStructuredDocumentRegion[] regions = sDoc.getStructuredDocumentRegions(0, m.getOffset() + m.getLength());
+		// iterate backwards until you hit the include directive
+		for (int i = regions.length - 1; i >= 0; i--) {
+			IStructuredDocumentRegion region = regions[i];
+			if (region.getType() == DOMJSPRegionContexts.JSP_DIRECTIVE_NAME) {
+				if (getDirectiveName(region).equals("include")) { //$NON-NLS-1$
+					ITextRegion fileValueRegion = getAttributeValueRegion(region, "file"); //$NON-NLS-1$
+					if (fileValueRegion != null) {
+						m.setOffset(region.getStartOffset(fileValueRegion));
+						m.setLength(fileValueRegion.getTextLength());
+					}
+					else {
+						m.setOffset(region.getStartOffset());
+						m.setLength(region.getTextLength());
+					}
+					/**
+					 * Bug 219761 - Syntax error reported at wrong location
+					 * (don't forget to adjust the line number, too)
+					 */
+					m.setLineNo(sDoc.getLineOfOffset(m.getOffset()) + 1);
+					break;
+				}
+			}
+		}
+	}
+
+	/**
+	 * Creates an IMessage from asn IProblem
+	 * 
+	 * @param problem
+	 * @param f
+	 * @param translation
+	 * @param structuredDoc
+	 * @return message representation of the problem, or null if it could not
+	 *         create one
+	 */
+	private IMessage createMessageFromProblem(IProblem problem, IFile f, IJSPTranslation translation, IStructuredDocument structuredDoc) {
+		int sev = -1;
+		int sourceStart = -1;
+		int sourceEnd = -1;
+
+		if (problem instanceof IJSPProblem) {
+			sourceStart = problem.getSourceStart();
+			sourceEnd = problem.getSourceEnd();
+			switch (((IJSPProblem) problem).getEID()) {
+				case IJSPProblem.TEIClassNotFound :
+					sev = getMessageSeverity(JSPCorePreferenceNames.VALIDATION_TRANSLATION_TEI_CLASS_NOT_FOUND);
+					break;
+				case IJSPProblem.TEIValidationMessage :
+					sev = getMessageSeverity(JSPCorePreferenceNames.VALIDATION_TRANSLATION_TEI_VALIDATION_MESSAGE);
+					break;
+				case IJSPProblem.TEIClassNotInstantiated :
+					sev = getMessageSeverity(JSPCorePreferenceNames.VALIDATION_TRANSLATION_TEI_CLASS_NOT_INSTANTIATED);
+					break;
+				case IJSPProblem.TEIClassMisc :
+					sev = getMessageSeverity(JSPCorePreferenceNames.VALIDATION_TRANSLATION_TEI_CLASS_RUNTIME_EXCEPTION);
+					break;
+				case IJSPProblem.TagClassNotFound :
+					sev = getMessageSeverity(JSPCorePreferenceNames.VALIDATION_TRANSLATION_TAG_HANDLER_CLASS_NOT_FOUND);
+					break;
+				case IJSPProblem.UseBeanInvalidID :
+					sev = getMessageSeverity(JSPCorePreferenceNames.VALIDATION_TRANSLATION_USEBEAN_INVALID_ID);
+					break;
+				case IJSPProblem.UseBeanMissingTypeInfo :
+					sev = getMessageSeverity(JSPCorePreferenceNames.VALIDATION_TRANSLATION_USBEAN_MISSING_TYPE_INFO);
+					break;
+				case IJSPProblem.UseBeanAmbiguousType :
+					sev = getMessageSeverity(JSPCorePreferenceNames.VALIDATION_TRANSLATION_USEBEAN_AMBIGUOUS_TYPE_INFO);
+					break;
+				default :
+					sev = problem.isError() ? IMessage.HIGH_SEVERITY : (problem.isWarning() ? IMessage.NORMAL_SEVERITY : ValidationMessage.IGNORE);
+
+			}
+		}
+		else {
+			sourceStart = translation.getJspOffset(problem.getSourceStart());
+			sourceEnd = translation.getJspOffset(problem.getSourceEnd());
+			switch (problem.getID()) {
+				case IProblem.LocalVariableIsNeverUsed : {
+					sev = getSourceSeverity(JSPCorePreferenceNames.VALIDATION_JAVA_LOCAL_VARIABLE_NEVER_USED, sourceStart, sourceEnd);
+				}
+					break;
+				case IProblem.NullLocalVariableReference : {
+					sev = getSourceSeverity(JSPCorePreferenceNames.VALIDATION_JAVA_NULL_LOCAL_VARIABLE_REFERENCE, sourceStart, sourceEnd);
+				}
+					break;
+				case IProblem.ArgumentIsNeverUsed : {
+					sev = getSourceSeverity(JSPCorePreferenceNames.VALIDATION_JAVA_ARGUMENT_IS_NEVER_USED, sourceStart, sourceEnd);
+				}
+					break;
+				case IProblem.PotentialNullLocalVariableReference : {
+					sev = getSourceSeverity(JSPCorePreferenceNames.VALIDATION_JAVA_POTENTIAL_NULL_LOCAL_VARIABLE_REFERENCE, sourceStart, sourceEnd);
+				}
+					break;
+				case IProblem.UnusedImport : {
+					sev = getSourceSeverity(JSPCorePreferenceNames.VALIDATION_JAVA_UNUSED_IMPORT, sourceStart, sourceEnd);
+				}
+					break;
+				case IProblem.UnusedPrivateField:
+				case IProblem.MissingSerialVersion : {
+					// JSP files don't get serialized...right?
+					sev = ValidationMessage.IGNORE;
+				}
+				break;
+
+				default : {
+					if (problem.isError()) {
+						sev = IMessage.HIGH_SEVERITY;
+					}
+					else if (problem.isWarning()) {
+						sev = IMessage.NORMAL_SEVERITY;
+					}
+					else {
+						sev = IMessage.LOW_SEVERITY;
+					}
+				}
+					if (sev == ValidationMessage.IGNORE) {
+						return null;
+					}
+
+					/* problems without JSP positions are in generated code */
+					if (sourceStart == -1) {
+						int problemID = problem.getID();
+						/*
+						 * Quoting IProblem doc: "When a problem is tagged as
+						 * Internal, it means that no change other than a
+						 * local source code change can fix the corresponding
+						 * problem." Assuming that our generated code is
+						 * correct, that should reduce the reported problems
+						 * to those the user can correct.
+						 */
+						if (((problemID & IProblem.Internal) != 0) && ((problemID & IProblem.Syntax) != 0) && translation instanceof JSPTranslation) {
+							// Attach to the last code scripting section
+							JSPTranslation jspTranslation = ((JSPTranslation) translation);
+							Position[] jspPositions = (Position[]) jspTranslation.getJsp2JavaMap().keySet().toArray(new Position[jspTranslation.getJsp2JavaMap().size()]);
+							for (int i = 0; i < jspPositions.length; i++) {
+								sourceStart = Math.max(sourceStart, jspPositions[i].getOffset());
+							}
+							IMessage m = new LocalizedMessage(sev, problem.getMessage(), f);
+							m.setOffset(sourceStart);
+							m.setLength(1);
+							return m;
+						}
+						else {
+							return null;
+						}
+					}
+			}
+		}
+		if (sev == ValidationMessage.IGNORE) {
+			return null;
+		}
+
+		final boolean isIndirect = translation.isIndirect(problem.getSourceStart());
+		if (isIndirect && !FragmentValidationTools.shouldValidateFragment(f)) {
+			return null;
+		}
+
+		// line number for marker starts @ 1
+		// line number from document starts @ 0
+		int lineNo = structuredDoc.getLineOfOffset(sourceStart) + 1;
+
+		IMessage m = new LocalizedMessage(sev, problem.getMessage(), f);
+
+		m.setLineNo(lineNo);
+		m.setOffset(sourceStart);
+		m.setLength((sourceEnd >= sourceStart) ? (sourceEnd - sourceStart + 1) : 0);
+
+		// need additional adjustment for problems from
+		// indirect (included) files
+		// https://bugs.eclipse.org/bugs/show_bug.cgi?id=119633
+		if (isIndirect) {
+			adjustIndirectPosition(m, translation);
+		}
+
+		return m;
+	}
+
+	/**
+	 * Provides the severity for the given message key only when it's within the source range of the JSP (i.e., not boilerplate code).
+	 * @param key the key to get the severity of
+	 * @param start start within the JSP source
+	 * @param end end wtihin the JSP source
+	 * @return The message severity for the key if it is part of the JSP's source. IGNORE if it's boilerplate code.
+	 */
+	private int getSourceSeverity(String key, int start, int end) {
+		return (start >= 0 && end >= 0 ) ? getMessageSeverity(key) : ValidationMessage.IGNORE;
+	}
+
+	int getMessageSeverity(String key) {
+		int sev = fPreferencesService.getInt(PREFERENCE_NODE_QUALIFIER, key, IMessage.NORMAL_SEVERITY, fScopes);
+		switch (sev) {
+			case ValidationMessage.ERROR :
+				return IMessage.HIGH_SEVERITY;
+			case ValidationMessage.WARNING :
+				return IMessage.NORMAL_SEVERITY;
+			case ValidationMessage.INFORMATION :
+				return IMessage.LOW_SEVERITY;
+			case ValidationMessage.IGNORE :
+				return ValidationMessage.IGNORE;
+		}
+		return IMessage.NORMAL_SEVERITY;
+	}
+
+	private void loadPreferences(IFile file) {
+		fScopes = new IScopeContext[]{new InstanceScope(), new DefaultScope()};
+
+		if (file != null && file.isAccessible()) {
+			ProjectScope projectScope = new ProjectScope(file.getProject());
+			if (projectScope.getNode(PREFERENCE_NODE_QUALIFIER).getBoolean(JSPCorePreferenceNames.VALIDATION_USE_PROJECT_SETTINGS, false)) {
+				fScopes = new IScopeContext[]{projectScope, new InstanceScope(), new DefaultScope()};
+			}
+		}
+	}
+
+	void performValidation(IFile f, IReporter reporter, IStructuredModel model) {
+		for (int i = 0; i < DEPEND_ONs.length; i++) {
+			addDependsOn(f.getProject().getFile(DEPEND_ONs[i]));	
+		}
+		if (model instanceof IDOMModel) {
+			IDOMModel domModel = (IDOMModel) model;
+			ModelHandlerForJSP.ensureTranslationAdapterFactory(domModel);
+
+			IDOMDocument xmlDoc = domModel.getDocument();
+			JSPTranslationAdapter translationAdapter = (JSPTranslationAdapter) xmlDoc.getAdapterFor(IJSPTranslation.class);
+			IJSPTranslation translation = translationAdapter.getJSPTranslation();
+
+			if (!reporter.isCancelled()) {
+				loadPreferences(f);
+
+				// only update task markers if the model is the same as what's on disk
+				boolean updateJavaTasks = UPDATE_JAVA_TASKS && !domModel.isDirty() && f != null && f.isAccessible();
+				if (updateJavaTasks) {
+					// remove old Java task markers
+					try {
+						IMarker[] foundMarkers = f.findMarkers(JAVA_TASK_MARKER_TYPE, true, IResource.DEPTH_ONE);
+						for (int i = 0; i < foundMarkers.length; i++) {
+							foundMarkers[i].delete();
+						}
+					}
+					catch (CoreException e) {
+						Logger.logException(e);
+					}
+				}
+
+				translation.setProblemCollectingActive(true);
+				translation.reconcileCompilationUnit();
+				List problems = translation.getProblems();
+				// add new messages
+				for (int i = 0; i < problems.size() && !reporter.isCancelled(); i++) {
+					IProblem problem = (IProblem) problems.get(i);
+					/*
+					 * Possible error in problem collection; EL translation is
+					 * extensible, so we must be paranoid about this.
+					 */
+					if (problem == null)
+						continue;
+					IMessage m = createMessageFromProblem(problem, f, translation, domModel.getStructuredDocument());
+					if (m != null) {
+						if (problem.getID() == IProblem.Task) {
+							if (updateJavaTasks) {
+								// add new Java task marker
+								try {
+									IMarker task = f.createMarker(JAVA_TASK_MARKER_TYPE);
+									task.setAttribute(IMarker.LINE_NUMBER, new Integer(m.getLineNumber()));
+									task.setAttribute(IMarker.CHAR_START, new Integer(m.getOffset()));
+									task.setAttribute(IMarker.CHAR_END, new Integer(m.getOffset() + m.getLength()));
+									task.setAttribute(IMarker.MESSAGE, m.getText());
+									task.setAttribute(IMarker.USER_EDITABLE, Boolean.FALSE);
+
+									switch (m.getSeverity()) {
+										case IMessage.HIGH_SEVERITY: {
+											task.setAttribute(IMarker.PRIORITY, new Integer(IMarker.PRIORITY_HIGH));
+											task.setAttribute(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_ERROR));
+										}
+											break;
+										case IMessage.LOW_SEVERITY : {
+											task.setAttribute(IMarker.PRIORITY, new Integer(IMarker.PRIORITY_LOW));
+											task.setAttribute(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_INFO));
+										}
+											break;
+										default : {
+											task.setAttribute(IMarker.PRIORITY, new Integer(IMarker.PRIORITY_NORMAL));
+											task.setAttribute(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_WARNING));
+										}
+									}
+								}
+								catch (CoreException e) {
+									Logger.logException(e);
+								}
+							}
+						}
+						else {
+							reporter.addMessage(fMessageOriginator, m);
+						}
+					}
+				}
+			}
+		}
+		unloadPreferences();
+	}
+
+	private void unloadPreferences() {
+		fScopes = null;
+	}
+
+	/**
+	 * Validate one file. It's assumed that the file has JSP content type.
+	 * 
+	 * @param f
+	 * @param reporter
+	 */
+	protected void validateFile(IFile f, IReporter reporter) {
+		if (DEBUG) {
+			Logger.log(Logger.INFO, getClass().getName() + " validating: " + f); //$NON-NLS-1$
+		}
+
+		IStructuredModel model = null;
+		try {
+			// get jsp model, get tranlsation
+			model = StructuredModelManager.getModelManager().getModelForRead(f);
+			if (!reporter.isCancelled() && model != null) {
+				for (int i = 0; i < DEPEND_ONs.length; i++) {
+					addDependsOn(f.getProject().getFile(DEPEND_ONs[i]));	
+				}
+				// get jsp model, get translation
+				if (model instanceof IDOMModel) {
+					reporter.removeAllMessages(fMessageOriginator, f);
+					performValidation(f, reporter, model);
+				}
+			}
+		}
+		catch (IOException e) {
+			Logger.logException(e);
+		}
+		catch (CoreException e) {
+			Logger.logException(e);
+		}
+		finally {
+			if (model != null)
+				model.releaseFromRead();
+		}
+	}
+
+	/**
+	 * Record that the currently validating resource depends on the given
+	 * file. Only possible during batch (not source) validation.
+	 * 
+	 * @param file
+	 */
+	private void addDependsOn(IFile file) {
+		if (fMessageOriginator instanceof JSPBatchValidator) {
+			((JSPBatchValidator) fMessageOriginator).addDependsOn(file);
+		}
+	}
+
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/validation/JSPValidator.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/validation/JSPValidator.java
new file mode 100644
index 0000000..a6b20c1
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/validation/JSPValidator.java
@@ -0,0 +1,420 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.validation;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceProxy;
+import org.eclipse.core.resources.IResourceProxyVisitor;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.content.IContentDescription;
+import org.eclipse.core.runtime.content.IContentType;
+import org.eclipse.core.runtime.jobs.ISchedulingRule;
+import org.eclipse.jst.jsp.core.internal.Logger;
+import org.eclipse.jst.jsp.core.internal.contentproperties.JSPFContentProperties;
+import org.eclipse.jst.jsp.core.internal.provisional.contenttype.ContentTypeIdForJSP;
+import org.eclipse.jst.jsp.core.internal.regions.DOMJSPRegionContexts;
+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.ITextRegionList;
+import org.eclipse.wst.validation.AbstractValidator;
+import org.eclipse.wst.validation.ValidationResult;
+import org.eclipse.wst.validation.ValidationState;
+import org.eclipse.wst.validation.internal.core.Message;
+import org.eclipse.wst.validation.internal.core.ValidationException;
+import org.eclipse.wst.validation.internal.operations.IWorkbenchContext;
+import org.eclipse.wst.validation.internal.provisional.core.IMessage;
+import org.eclipse.wst.validation.internal.provisional.core.IReporter;
+import org.eclipse.wst.validation.internal.provisional.core.IValidationContext;
+import org.eclipse.wst.validation.internal.provisional.core.IValidatorJob;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+
+/**
+ * Performs some common JSP validation tasks
+ */
+public class JSPValidator extends AbstractValidator implements IValidatorJob {
+
+	private static final String PLUGIN_ID_JSP_CORE = "org.eclipse.jst.jsp.core"; //$NON-NLS-1$
+	private IContentType fJSPFContentType = null;
+
+	protected class LocalizedMessage extends Message {
+
+		private String _message = null;
+
+		public LocalizedMessage(int severity, String messageText) {
+			this(severity, messageText, null);
+		}
+
+		public LocalizedMessage(int severity, String messageText, IResource targetObject) {
+			this(severity, messageText, (Object) targetObject);
+		}
+
+		public LocalizedMessage(int severity, String messageText, Object targetObject) {
+			super(null, severity, null);
+			setLocalizedMessage(messageText);
+			setTargetObject(targetObject);
+		}
+
+		public void setLocalizedMessage(String message) {
+			_message = message;
+		}
+
+		public String getLocalizedMessage() {
+			return _message;
+		}
+
+		public String getText() {
+			return getLocalizedMessage();
+		}
+
+		public String getText(ClassLoader cl) {
+			return getLocalizedMessage();
+		}
+
+		public String getText(Locale l) {
+			return getLocalizedMessage();
+		}
+
+		public String getText(Locale l, ClassLoader cl) {
+			return getLocalizedMessage();
+		}
+	}
+
+	protected class JSPFileVisitor implements IResourceProxyVisitor {
+
+		private List fFiles = new ArrayList();
+		private IContentType[] fContentTypes = null;
+		private IReporter fReporter = null;
+
+		public JSPFileVisitor(IReporter reporter) {
+			fReporter = reporter;
+		}
+
+		public boolean visit(IResourceProxy proxy) throws CoreException {
+
+			// check validation
+			if (fReporter.isCancelled())
+				return false;
+
+			if (proxy.getType() == IResource.FILE) {
+
+				if (isJSPType(proxy.getName())) {
+					IFile file = (IFile) proxy.requestResource();
+					if (file.exists()) {
+
+						if (DEBUG)
+							System.out.println("(+) JSPValidator adding file: " + file.getName()); //$NON-NLS-1$
+						fFiles.add(file);
+
+						// don't search deeper for files
+						return false;
+					}
+				}
+			}
+			return true;
+		}
+
+		public final IFile[] getFiles() {
+			return (IFile[]) fFiles.toArray(new IFile[fFiles.size()]);
+		}
+
+		/**
+		 * Gets list of content types this visitor is interested in
+		 * 
+		 * @return All JSP-related content types
+		 */
+		private IContentType[] getValidContentTypes() {
+			if (fContentTypes == null) {
+				// currently "hard-coded" to be jsp & jspf
+				fContentTypes = new IContentType[]{Platform.getContentTypeManager().getContentType(ContentTypeIdForJSP.ContentTypeID_JSP), Platform.getContentTypeManager().getContentType(ContentTypeIdForJSP.ContentTypeID_JSPFRAGMENT)};
+			}
+			return fContentTypes;
+		}
+
+		/**
+		 * Checks if fileName is some type of JSP (including JSP fragments)
+		 * 
+		 * @param fileName
+		 * @return true if filename indicates some type of JSP, false
+		 *         otherwise
+		 */
+		private boolean isJSPType(String fileName) {
+			boolean valid = false;
+
+			IContentType[] types = getValidContentTypes();
+			int i = 0;
+			while (i < types.length && !valid) {
+				valid = types[i].isAssociatedWith(fileName);
+				++i;
+			}
+			return valid;
+		}
+	}
+
+	public void cleanup(IReporter reporter) {
+		// nothing to do
+	}
+
+	public void validate(IValidationContext helper, IReporter reporter) throws ValidationException {
+		String[] uris = helper.getURIs();
+		IWorkspaceRoot wsRoot = ResourcesPlugin.getWorkspace().getRoot();
+		if (uris.length > 0) {
+			IFile currentFile = null;
+
+			for (int i = 0; i < uris.length && !reporter.isCancelled(); i++) {
+				// might be called with just project path?
+				currentFile = wsRoot.getFile(new Path(uris[i]));
+				if (currentFile != null && currentFile.exists()) {
+					if (shouldValidate(currentFile) && fragmentCheck(currentFile)) {
+
+						Message message = new LocalizedMessage(IMessage.LOW_SEVERITY, uris[i]);
+						reporter.displaySubtask(this, message);
+
+						validateFile(currentFile, reporter);
+					}
+					if (DEBUG)
+						System.out.println("validating: [" + uris[i] + "]"); //$NON-NLS-1$ //$NON-NLS-2$
+				}
+			}
+		}
+		else {
+
+			// if uris[] length 0 -> validate() gets called for each project
+			if (helper instanceof IWorkbenchContext) {
+
+				IProject project = ((IWorkbenchContext) helper).getProject();
+				JSPFileVisitor visitor = new JSPFileVisitor(reporter);
+				try {
+					// collect all jsp files for the project
+					project.accept(visitor, IResource.DEPTH_INFINITE);
+				}
+				catch (CoreException e) {
+					if (DEBUG)
+						e.printStackTrace();
+				}
+				IFile[] files = visitor.getFiles();
+				for (int i = 0; i < files.length && !reporter.isCancelled(); i++) {
+					if (shouldValidate(files[i]) && fragmentCheck(files[i])) {
+						int percent = (i * 100) / files.length + 1;
+						Message message = new LocalizedMessage(IMessage.LOW_SEVERITY, percent + "% " + files[i].getFullPath().toString());
+						reporter.displaySubtask(this, message);
+
+						validateFile(files[i], reporter);
+					}
+					if (DEBUG)
+						System.out.println("validating: [" + files[i] + "]"); //$NON-NLS-1$ //$NON-NLS-2$
+				}
+			}
+		}
+	}
+
+	/**
+	 * Validate one file. It's assumed that the file has JSP content type.
+	 * 
+	 * @param f
+	 * @param reporter
+	 */
+	protected void validateFile(IFile f, IReporter reporter) {
+		// subclasses should implement (for batch validation)
+	}
+
+	public ValidationResult validate(final IResource resource, int kind, ValidationState state, IProgressMonitor monitor) {
+		if (resource.getType() != IResource.FILE)
+			return null;
+		ValidationResult result = new ValidationResult();
+		final IReporter reporter = result.getReporter(monitor);
+		validateFile((IFile) resource, reporter);
+		return result;
+	}
+
+	/**
+	 * 
+	 * @param collection
+	 * @return the jsp directive name
+	 */
+	protected String getDirectiveName(ITextRegionCollection collection) {
+		String name = ""; //$NON-NLS-1$
+		ITextRegionList subRegions = collection.getRegions();
+		for (int j = 0; j < subRegions.size(); j++) {
+			ITextRegion subRegion = subRegions.get(j);
+			if (subRegion.getType() == DOMJSPRegionContexts.JSP_DIRECTIVE_NAME) {
+				name = collection.getText(subRegion);
+				break;
+			}
+		}
+		return name;
+	}
+
+	/**
+	 * 
+	 * @param sdr
+	 * @param attrName
+	 * @return the ITextRegion for the attribute value of the given attribute
+	 *         name, case sensitive, null if no matching attribute is found
+	 */
+	protected ITextRegion getAttributeValueRegion(ITextRegionCollection sdr, String attrName) {
+		ITextRegion valueRegion = null;
+		ITextRegionList subRegions = sdr.getRegions();
+		for (int i = 0; i < subRegions.size(); i++) {
+			ITextRegion subRegion = subRegions.get(i);
+			if (subRegion.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME && sdr.getText(subRegion).equals(attrName)) {
+				for (int j = i; j < subRegions.size(); j++) {
+					subRegion = subRegions.get(j);
+					if (subRegion.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
+						valueRegion = subRegion;
+						break;
+					}
+				}
+				break;
+			}
+		}
+		return valueRegion;
+	}
+
+	protected String getAttributeValue(ITextRegionCollection sdr, String attrName) {
+		ITextRegion r = getAttributeValueRegion(sdr, attrName);
+		if (r != null)
+			return sdr.getText(r).trim();
+		return ""; //$NON-NLS-1$
+	}
+
+	/**
+	 * Determines if file is jsp fragment or not (does a deep, indepth check,
+	 * looking into contents of file)
+	 * 
+	 * @param file
+	 *            assumes file is not null and exists
+	 * @return true if file is jsp fragment, false otherwise
+	 */
+	private boolean isFragment(IFile file) {
+		boolean isFragment = false;
+		InputStream is = null;
+		try {
+			IContentDescription contentDescription = file.getContentDescription();
+			// it can be null
+			if (contentDescription == null) {
+				is = file.getContents();
+				contentDescription = Platform.getContentTypeManager().getDescriptionFor(is, file.getName(), new QualifiedName[]{IContentDescription.CHARSET});
+			}
+			if (contentDescription != null) {
+				String fileCtId = contentDescription.getContentType().getId();
+				isFragment = (fileCtId != null && ContentTypeIdForJSP.ContentTypeID_JSPFRAGMENT.equals(fileCtId));
+			}
+		}
+		catch (IOException e) {
+			// ignore, assume it's invalid JSP
+		}
+		catch (CoreException e) {
+			// ignore, assume it's invalid JSP
+		}
+		finally {
+			// must close input stream in case others need it
+			if (is != null)
+				try {
+					is.close();
+				}
+				catch (Exception e) {
+					// not sure how to recover at this point
+				}
+		}
+		return isFragment;
+	}
+
+	private boolean shouldValidate(IFile file) {
+		IResource resource = file;
+		do {
+			if (resource.isDerived() || resource.isTeamPrivateMember() || !resource.isAccessible() || resource.getName().charAt(0) == '.') {
+				return false;
+			}
+			resource = resource.getParent();
+		}
+		while ((resource.getType() & IResource.PROJECT) == 0);
+		return true;
+	}
+
+	// for debugging
+	static final boolean DEBUG;
+	static {
+		String value = Platform.getDebugOption("org.eclipse.jst.jsp.core/debug/jspvalidator"); //$NON-NLS-1$
+		DEBUG = value != null && value.equalsIgnoreCase("true"); //$NON-NLS-1$
+	}
+
+	/**
+	 * Checks if file is a jsp fragment or not. If so, check if the fragment
+	 * should be validated or not.
+	 * 
+	 * @param file
+	 *            Assumes shouldValidate was already called on file so it
+	 *            should not be null and does exist
+	 * @return false if file is a fragment and it should not be validated,
+	 *         true otherwise
+	 */
+	private boolean fragmentCheck(IFile file) {
+		boolean shouldValidate = true;
+		// quick check to see if this is possibly a jsp fragment
+		if (getJSPFContentType().isAssociatedWith(file.getName())) {
+			// get preference for validate jsp fragments
+			boolean shouldValidateFragments = Boolean.valueOf(JSPFContentProperties.getProperty(JSPFContentProperties.VALIDATE_FRAGMENTS, file, true)).booleanValue();
+			/*
+			 * if jsp fragments should not be validated, check if file is
+			 * really jsp fragment
+			 */
+			if (!shouldValidateFragments) {
+				boolean isFragment = isFragment(file);
+				shouldValidate = !isFragment;
+			}
+		}
+		return shouldValidate;
+	}
+
+	/**
+	 * Returns JSP fragment content type
+	 * 
+	 * @return jspf content type
+	 */
+	private IContentType getJSPFContentType() {
+		if (fJSPFContentType == null) {
+			fJSPFContentType = Platform.getContentTypeManager().getContentType(ContentTypeIdForJSP.ContentTypeID_JSPFRAGMENT);
+		}
+		return fJSPFContentType;
+	}
+
+	public ISchedulingRule getSchedulingRule(IValidationContext helper) {
+		return null;
+	}
+
+	public IStatus validateInJob(IValidationContext helper, IReporter reporter) throws ValidationException {
+		IStatus status = Status.OK_STATUS;
+		try {
+			validate(helper, reporter);
+		}
+		catch (ValidationException e) {
+			Logger.logException(e);
+			status = new Status(IStatus.ERROR, PLUGIN_ID_JSP_CORE, IStatus.ERROR, e.getLocalizedMessage(), e);
+		}
+		return status;
+	}
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/validation/LocalizedMessage.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/validation/LocalizedMessage.java
new file mode 100644
index 0000000..7bd2f31
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/validation/LocalizedMessage.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.validation;
+
+import java.util.Locale;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.wst.validation.internal.core.Message;
+
+/**
+ * Simple implementation of Message all validators in package can use.
+ */
+class LocalizedMessage extends Message {
+	private String _message = null;
+
+	public LocalizedMessage(int severity, String messageText) {
+		this(severity, messageText, null);
+	}
+
+	public LocalizedMessage(int severity, String messageText, IResource targetObject) {
+		this(severity, messageText, (Object) targetObject);
+	}
+
+	public LocalizedMessage(int severity, String messageText, Object targetObject) {
+		super(null, severity, null);
+		setLocalizedMessage(messageText);
+		setTargetObject(targetObject);
+	}
+
+	public void setLocalizedMessage(String message) {
+		_message = message;
+	}
+
+	public String getLocalizedMessage() {
+		return _message;
+	}
+
+	public String getText() {
+		return getLocalizedMessage();
+	}
+
+	public String getText(ClassLoader cl) {
+		return getLocalizedMessage();
+	}
+
+	public String getText(Locale l) {
+		return getLocalizedMessage();
+	}
+
+	public String getText(Locale l, ClassLoader cl) {
+		return getLocalizedMessage();
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/validation/TLDValidator.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/validation/TLDValidator.java
new file mode 100644
index 0000000..ae70a60
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/validation/TLDValidator.java
@@ -0,0 +1,219 @@
+/*******************************************************************************
+ * Copyright (c) 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jst.jsp.core.internal.validation;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ProjectScope;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.preferences.DefaultScope;
+import org.eclipse.core.runtime.preferences.IPreferencesService;
+import org.eclipse.core.runtime.preferences.IScopeContext;
+import org.eclipse.core.runtime.preferences.InstanceScope;
+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.jst.jsp.core.internal.Assert;
+import org.eclipse.jst.jsp.core.internal.JSPCoreMessages;
+import org.eclipse.jst.jsp.core.internal.JSPCorePlugin;
+import org.eclipse.jst.jsp.core.internal.Logger;
+import org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.JSP11TLDNames;
+import org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.JSP12TLDNames;
+import org.eclipse.jst.jsp.core.internal.preferences.JSPCorePreferenceNames;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.validate.ValidationMessage;
+import org.eclipse.wst.validation.AbstractValidator;
+import org.eclipse.wst.validation.ValidationResult;
+import org.eclipse.wst.validation.ValidationState;
+import org.eclipse.wst.validation.ValidatorMessage;
+import org.eclipse.wst.validation.internal.provisional.core.IMessage;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * A miniature validator for .tld files. Checks for valid class names.
+ */
+public class TLDValidator extends AbstractValidator {
+	private static final String MARKER_TYPE = "org.eclipse.jst.jsp.core.validationMarker"; //$NON-NLS-1$
+	private static final String PREFERENCE_NODE_QUALIFIER = JSPCorePlugin.getDefault().getBundle().getSymbolicName();
+
+	private IPreferencesService fPreferencesService = Platform.getPreferencesService();
+
+	private static final String[] classElementNames = new String[]{JSP11TLDNames.TAGCLASS, JSP12TLDNames.TAG_CLASS, JSP11TLDNames.TEICLASS, JSP12TLDNames.TEI_CLASS, JSP12TLDNames.VALIDATOR_CLASS, JSP12TLDNames.VARIABLE_CLASS, JSP12TLDNames.LISTENER_CLASS};
+	private static final String[] missingClassMessages = new String[]{JSPCoreMessages.TaglibHelper_3, JSPCoreMessages.TaglibHelper_3, JSPCoreMessages.TaglibHelper_0, JSPCoreMessages.TaglibHelper_0, JSPCoreMessages.TLDValidator_MissingValidator, JSPCoreMessages.TLDValidator_MissingVariable, JSPCoreMessages.TLDValidator_MissingListener};
+	private static final String[] missingClassSeverityPreferenceKeys = new String[]{JSPCorePreferenceNames.VALIDATION_TRANSLATION_TAG_HANDLER_CLASS_NOT_FOUND, JSPCorePreferenceNames.VALIDATION_TRANSLATION_TAG_HANDLER_CLASS_NOT_FOUND, JSPCorePreferenceNames.VALIDATION_TRANSLATION_TEI_CLASS_NOT_FOUND, JSPCorePreferenceNames.VALIDATION_TRANSLATION_TEI_CLASS_NOT_FOUND, JSPCorePreferenceNames.VALIDATION_TRANSLATION_TAG_HANDLER_CLASS_NOT_FOUND, JSPCorePreferenceNames.VALIDATION_TRANSLATION_TAG_HANDLER_CLASS_NOT_FOUND, JSPCorePreferenceNames.VALIDATION_TRANSLATION_TAG_HANDLER_CLASS_NOT_FOUND};
+
+	public TLDValidator() {
+		super();
+
+		Assert.isTrue(classElementNames.length == missingClassMessages.length, "mismanaged arrays"); //$NON-NLS-1$
+		Assert.isTrue(classElementNames.length == missingClassSeverityPreferenceKeys.length, "mismanaged arrays"); //$NON-NLS-1$
+		Assert.isTrue(missingClassMessages.length == missingClassSeverityPreferenceKeys.length, "mismanaged arrays"); //$NON-NLS-1$
+	}
+
+	private Map checkClass(IJavaProject javaProject, Node classSpecifier, IScopeContext[] preferenceScopes, String preferenceKey, String errorMessage) {
+		String className = getTextContents(classSpecifier);
+		if (className != null && className.length() > 2) {
+			IType type = null;
+			try {
+				type = javaProject.findType(className);
+			}
+			catch (JavaModelException e) {
+				return null;
+			}
+
+			if (type == null || !type.exists()) {
+				Object severity = getMessageSeverity(preferenceScopes, preferenceKey);
+				if (severity == null)
+					return null;
+
+				IDOMNode classElement = (IDOMNode) classSpecifier;
+				Map markerValues = new HashMap();
+				markerValues.put(IMarker.SEVERITY, severity);
+				int start = classElement.getStartOffset();
+				if (classElement.getStartStructuredDocumentRegion() != null && classElement.getEndStructuredDocumentRegion() != null)
+					start = classElement.getStartStructuredDocumentRegion().getEndOffset();
+				markerValues.put(IMarker.CHAR_START, new Integer(start));
+				int end = classElement.getEndOffset();
+				if (classElement.getStartStructuredDocumentRegion() != null && classElement.getEndStructuredDocumentRegion() != null)
+					end = classElement.getEndStructuredDocumentRegion().getStartOffset();
+				markerValues.put(IMarker.CHAR_END, new Integer(end));
+				int line = classElement.getStructuredDocument().getLineOfOffset(start);
+				markerValues.put(IMarker.LINE_NUMBER, new Integer(line + 1));
+				markerValues.put(IMarker.MESSAGE, NLS.bind(errorMessage, (errorMessage.indexOf("{1}") >= 0) ? new String[]{getTagName(classSpecifier), className} : new String[]{className})); //$NON-NLS-1$
+				return markerValues;
+			}
+		}
+		return null;
+	}
+
+	private Map[] detectProblems(IJavaProject javaProject, IFile tld, IScopeContext[] preferenceScopes) throws CoreException {
+		List problems = new ArrayList();
+
+		IStructuredModel m = null;
+		try {
+			m = StructuredModelManager.getModelManager().getModelForRead(tld);
+			if (m != null && m instanceof IDOMModel) {
+				IDOMDocument document = ((IDOMModel) m).getDocument();
+
+				for (int i = 0; i < classElementNames.length; i++) {
+					NodeList classes = document.getElementsByTagName(classElementNames[i]);
+					for (int j = 0; j < classes.getLength(); j++) {
+						Map problem = checkClass(javaProject, classes.item(j), preferenceScopes, missingClassSeverityPreferenceKeys[i], missingClassMessages[i]);
+						if (problem != null)
+							problems.add(problem);
+					}
+				}
+
+			}
+		}
+		catch (IOException e) {
+			Logger.logException(e);
+		}
+		finally {
+			if (m != null)
+				m.releaseFromRead();
+		}
+
+		return (Map[]) problems.toArray(new Map[problems.size()]);
+	}
+
+	Integer getMessageSeverity(IScopeContext[] preferenceScopes, String key) {
+		int sev = fPreferencesService.getInt(PREFERENCE_NODE_QUALIFIER, key, IMessage.NORMAL_SEVERITY, preferenceScopes);
+		switch (sev) {
+			case ValidationMessage.ERROR :
+				return new Integer(IMarker.SEVERITY_ERROR);
+			case ValidationMessage.WARNING :
+				return new Integer(IMarker.SEVERITY_WARNING);
+			case ValidationMessage.INFORMATION :
+				return new Integer(IMarker.SEVERITY_INFO);
+			case ValidationMessage.IGNORE :
+				return null;
+		}
+		return new Integer(IMarker.SEVERITY_WARNING);
+	}
+
+	private String getTagName(Node classSpecifier) {
+		Node tagElement = classSpecifier.getParentNode();
+		Node child = tagElement.getFirstChild();
+		while (child != null) {
+			if (child.getNodeType() == Node.ELEMENT_NODE) {
+				String name = child.getNodeName();
+				if (JSP11TLDNames.NAME.equals(name))
+					return getTextContents(child);
+			}
+			child = child.getNextSibling();
+		}
+		return "";
+	}
+
+	private String getTextContents(Node parent) {
+		NodeList children = parent.getChildNodes();
+		if (children.getLength() == 1) {
+			return children.item(0).getNodeValue().trim();
+		}
+		StringBuffer s = new StringBuffer();
+		Node child = parent.getFirstChild();
+		while (child != null) {
+			s.append(child.getNodeValue().trim());
+			child = child.getNextSibling();
+		}
+		return s.toString().trim();
+	}
+
+	public ValidationResult validate(IResource resource, int kind, ValidationState state, IProgressMonitor monitor) {
+		if (resource.getType() != IResource.FILE)
+			return null;
+		ValidationResult result = new ValidationResult();
+
+		IFile tld = (IFile) resource;
+		if (tld.isAccessible()) {
+			try {
+				final IJavaProject javaProject = JavaCore.create(tld.getProject());
+				if (javaProject.exists()) {
+					IScopeContext[] scopes = new IScopeContext[]{new InstanceScope(), new DefaultScope()};
+					ProjectScope projectScope = new ProjectScope(tld.getProject());
+					if (projectScope.getNode(PREFERENCE_NODE_QUALIFIER).getBoolean(JSPCorePreferenceNames.VALIDATION_USE_PROJECT_SETTINGS, false)) {
+						scopes = new IScopeContext[]{projectScope, new InstanceScope(), new DefaultScope()};
+					}
+					Map[] problems = detectProblems(javaProject, tld, scopes);
+					for (int i = 0; i < problems.length; i++) {
+						ValidatorMessage message = ValidatorMessage.create(problems[i].get(IMarker.MESSAGE).toString(), resource);
+						message.setType(MARKER_TYPE);
+						message.setAttributes(problems[i]);
+						result.add(message);
+					}
+				}
+			}
+			catch (Exception e) {
+				Logger.logException(e);
+			}
+		}
+
+		return result;
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/jspel/ELProblem.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/jspel/ELProblem.java
new file mode 100644
index 0000000..ef95d18
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/jspel/ELProblem.java
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 BEA Systems 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:
+ *     BEA Systems - initial implementation
+ *     
+ *******************************************************************************/
+
+package org.eclipse.jst.jsp.core.jspel;
+
+import org.eclipse.jface.text.Position;
+import org.eclipse.jst.jsp.core.internal.java.IJSPProblem;
+
+/**
+ * All ELProblems are currently assumed to be errors.
+ */
+public class ELProblem implements IJSPProblem {
+	private Position fPos;
+	private String fMessage;
+	private int fId = IJSPProblem.ELProblem;
+
+	/**
+	 * @param pos should be relative to the JSP document the error is to be reported on
+	 * @param message
+	 */
+	public ELProblem(Position pos, String message)	{
+		fPos = pos;
+		fMessage = message;
+	}
+
+	public ELProblem(Position pos, String message, int id)	{
+		fPos = pos;
+		fMessage = message;
+		fId = id;
+	}
+	
+	public String getMessage() {
+		return fMessage;
+	}
+	
+	public Position getPosition() {
+		return fPos;
+	}
+
+	public String[] getArguments() {
+		return null;
+	}
+
+	public int getID() {
+		return fId;
+	}
+	
+	public int getEID() {
+		return fId;
+	}
+
+	public char[] getOriginatingFileName() {
+		return null;
+	}
+
+	public int getSourceEnd() {
+		return fPos.getOffset() + fPos.getLength();
+	}
+
+	public int getSourceLineNumber() {
+		return 0;
+	}
+
+	public int getSourceStart() {
+		return fPos.getOffset();
+	}
+
+	public boolean isError() {
+		return true;
+	}
+
+	public boolean isWarning() {
+		return false;
+	}
+
+	public void setSourceEnd(int sourceEnd) {}
+
+	public void setSourceLineNumber(int lineNumber) {}
+
+	public void setSourceStart(int sourceStart) {}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/jspel/IJSPELTranslator.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/jspel/IJSPELTranslator.java
new file mode 100644
index 0000000..55e8460
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/jspel/IJSPELTranslator.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 BEA Systems 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:
+ *     BEA Systems - initial implementation
+ *     
+ *******************************************************************************/
+
+package org.eclipse.jst.jsp.core.jspel;
+
+import java.util.List;
+import java.util.HashMap;
+
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+
+public interface IJSPELTranslator {
+
+	/**
+	 * To override the EL translation, please see the extension point 
+	 * org.eclipse.jst.jsp.core.eltranslator.
+	 * 
+	 * @param elText  The text to be translated.
+	 * @param delim	The starting delimiter
+	 * @param currentNode The current IStructuredDocumentRegion
+	 * @param contentStart The starting offset of the EL to be translated
+	 * @param contentLength The length of the EL content to be translated
+	 * @param fUserELExpressions A string buffer to which generated code can be appended.
+	 *		The text appended here will be inserted into the generated class at the top level 
+	 *		not at the point in the JSP translation where the EL was found. 
+	 * 
+	 * @param fUserELRanges  Map of location ranges from JSP EL offsets to generated Java code.
+	 * @param document The structured document.
+	 * @return A list of ELProblems that describes any syntactic issues found.
+	 */
+	public List translateEL(String elText,
+			String delim,
+			IStructuredDocumentRegion currentNode, 
+			int contentStart,
+			int contentLength,
+			StringBuffer userELExpressions,
+			HashMap userELRanges,
+			IStructuredDocument document);
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/taglib/IJarRecord.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/taglib/IJarRecord.java
new file mode 100644
index 0000000..6416473
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/taglib/IJarRecord.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.taglib;
+
+import org.eclipse.core.runtime.IPath;
+
+/**
+ * A record to a .jar file directly referencable as a tag library.
+ * 
+ * <p>
+ * This interface is not intended to be implemented by clients.
+ * </p>
+ * 
+ * @since 1.0
+ */
+
+public interface IJarRecord extends ITaglibRecord {
+	/**
+	 * @return Returns the location of the .jar in the file-system.
+	 */
+	public IPath getLocation();
+
+	/**
+	 * @return Returns the recommended/default prefix if one was given.
+	 */
+	public String getShortName();
+
+	/**
+	 * @deprecated - use the descriptor's URI value
+	 * @return Returns the uri.
+	 */
+	String getURI();
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/taglib/ITLDRecord.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/taglib/ITLDRecord.java
new file mode 100644
index 0000000..395d3b1
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/taglib/ITLDRecord.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.taglib;
+
+import org.eclipse.core.runtime.IPath;
+
+/**
+ * A record representing a standalone .tld file.
+ * <p>
+ * This interface is not intended to be implemented by clients.
+ * </p>
+ * 
+ * @since 1.0
+ */
+public interface ITLDRecord extends ITaglibRecord {
+
+	/**
+	 * @return Returns the path within the workspace.
+	 */
+	IPath getPath();
+
+	/**
+	 * @return Returns the recommended/default prefix if one was given.
+	 */
+	String getShortName();
+
+	/**
+	 * @deprecated - use the descriptor's URI value
+	 * @return Returns the uri.
+	 */
+	String getURI();
+
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/taglib/ITagDirRecord.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/taglib/ITagDirRecord.java
new file mode 100644
index 0000000..af20861
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/taglib/ITagDirRecord.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.taglib;
+
+import org.eclipse.core.runtime.IPath;
+
+/**
+ * A record representing a folder of .tag/.tagx files
+ * <p>
+ * This interface is not intended to be implemented by clients.
+ * </p>
+ * 
+ * @since 1.0
+ */
+public interface ITagDirRecord extends ITaglibRecord {
+	/**
+	 * @return Returns the path within the workspace to this directory.
+	 */
+	IPath getPath();
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/taglib/ITaglibDescriptor.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/taglib/ITaglibDescriptor.java
new file mode 100644
index 0000000..dfba477
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/taglib/ITaglibDescriptor.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.taglib;
+
+/**
+ * A representation of information within a tag library descriptor. Provides
+ * much of the high-level information expressed by the descriptor.
+ * <p>
+ * This interface is not intended to be implemented by clients.
+ * </p>
+ * 
+ * @since 1.2
+ */
+public interface ITaglibDescriptor {
+	/**
+	 * @return the description value of this tag library
+	 */
+	String getDescription();
+	/**
+	 * @return the display name value of this tag library
+	 */
+	String getDisplayName();
+	/**
+	 * @return the stated required JSP version of this tag library
+	 */
+	String getJSPVersion();
+	/**
+	 * @return a URL string to the large icon for this tag library
+	 */
+	String getLargeIcon();
+	/**
+	 * @return the stated short name for this tag library
+	 */
+	String getShortName();
+	/**
+	 * @return a URL string to the small icon for this tag library
+	 */
+	String getSmallIcon();
+	/**
+	 * @return the stated version of this tag library if specified
+	 */
+	String getTlibVersion();
+	/**
+	 * @return a URI pointing to this tag library's descriptor, or null
+	 */
+	String getURI();
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/taglib/ITaglibIndexDelta.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/taglib/ITaglibIndexDelta.java
new file mode 100644
index 0000000..c1a611b
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/taglib/ITaglibIndexDelta.java
@@ -0,0 +1,82 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.taglib;
+
+import org.eclipse.core.resources.IProject;
+
+/**
+ * Describes changes to the known records within the TaglibIndex.
+ * <p>
+ * @noimplement This interface is not intended to be implemented by clients.
+ * </p>
+ * 
+ * @since 1.2
+ */
+public interface ITaglibIndexDelta {
+
+	/**
+	 * Status constant indicating that the record has been added. Note that an
+	 * added taglib record delta has no children, as they are all implicitely
+	 * added.
+	 */
+	public int ADDED = 1;
+	/**
+	 * Status constant indicating that the record has been changed, as
+	 * described by the change flags.
+	 */
+	public int CHANGED = 4;
+	/**
+	 * Status constant indicating that the record has been removed. Note that
+	 * a removed taglib element delta has no children, as they are all
+	 * implicitely removed.
+	 */
+	public int REMOVED = 2;
+
+
+	/**
+	 * Returns deltas for the affected (added, removed, or changed) records.
+	 * 
+	 * @return
+	 */
+	ITaglibIndexDelta[] getAffectedChildren();
+
+	/**
+	 * @return the type of change, one of ADDED, CHANGED, or REMOVED
+	 */
+	int getKind();
+	
+	/**
+	 * @return the IProject in which this delta originated
+	 */
+	IProject getProject();
+
+
+	/**
+	 * @return the record that was changed
+	 */
+	ITaglibRecord getTaglibRecord();
+
+	/**
+	 * Accepts the given visitor. The only kinds of index deltas visited are
+	 * <code>ADDED</code>, <code>REMOVED</code>, and
+	 * <code>CHANGED</code>. The visitor's <code>visit</code> method is
+	 * called with this index delta if applicable. If the visitor returns
+	 * <code>true</code>, the resource delta's children are also visited.
+	 * 
+	 * @param visitor
+	 *            the visitor
+	 * @exception CoreException
+	 *                if the visitor failed with this exception.
+	 * @see IResourceDeltaVisitor#visit(ITaglibIndexDeltaVisitor)
+	 */
+	// public void accept(ITaglibIndexDeltaVisitor visitor);
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/taglib/ITaglibIndexListener.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/taglib/ITaglibIndexListener.java
new file mode 100644
index 0000000..e4e404c
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/taglib/ITaglibIndexListener.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.taglib;
+
+/**
+ * A listener for changes in the index's records.
+ */
+public interface ITaglibIndexListener {
+
+	/**
+	 * Notifies this listener that a change in the TaglibIndex, described by
+	 * an ITaglibIndexDelta, has occurred
+	 * 
+	 * @param delta
+	 *            the delta of changes
+	 */
+	void indexChanged(ITaglibIndexDelta delta);
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/taglib/ITaglibRecord.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/taglib/ITaglibRecord.java
new file mode 100644
index 0000000..5cb6462
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/taglib/ITaglibRecord.java
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.taglib;
+
+/**
+ * A representation of information about a single tag library descriptor. This
+ * interface is common to all record types.
+ * 
+ * 
+ * @see IJarRecord
+ * @see ITagDirRecord
+ * @see ITLDRecord
+ * @see IURLRecord
+ *      <p>
+ *      This interface is not intended to be implemented by clients.
+ *      </p>
+ * 
+ * @since 1.0
+ */
+public interface ITaglibRecord {
+	/**
+	 * A record to a .jar file referrable directly, 1.1 style, or mentioned in
+	 * a web.xml file.
+	 */
+	int JAR = 1 << 1;
+
+	/**
+	 * A record representing a folder of .tag/.tagx files
+	 */
+	int TAGDIR = 1 << 3;
+
+	/**
+	 * A record representing a standalone .tld file
+	 */
+	int TLD = 1;
+
+	/**
+	 * A record representing a .tld that is not a standalone file
+	 */
+	int URL = 1 << 2;
+
+	/**
+	 * Returns the type of this record. The returned value will be one of
+	 * <code>URL</code>, <code>TAGDIR</code>, <code>TLD</code>, or
+	 * <code>JAR</code>.
+	 * <p>
+	 * <ul>
+	 * <li> All records of type <code>JAR</code> implement
+	 * <code>IJarRecord</code>.</li>
+	 * <li> All records of type <code>TAGDIR</code> implement
+	 * <code>ITagDirRecord</code>.</li>
+	 * <li> All records of type <code>TLD</code> implement
+	 * <code>ITLDRecord</code>.</li>
+	 * <li> All records of type <code>URL</code> implement
+	 * <code>IURLRecord</code>.</li>
+	 * </ul>
+	 * </p>
+	 * 
+	 * @return the type of this resource
+	 * @see #JAR
+	 * @see #TAGDIR
+	 * @see #TLD
+	 * @see #URL
+	 */
+	int getRecordType();
+	
+	ITaglibDescriptor getDescriptor();
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/taglib/ITaglibRecordEvent.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/taglib/ITaglibRecordEvent.java
new file mode 100644
index 0000000..b316511
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/taglib/ITaglibRecordEvent.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.taglib;
+
+import org.eclipse.core.resources.IResourceDelta;
+
+/**
+ * Describes changes to the known records within the TaglibIndex.
+ * 
+ * <p>
+ * @noimplement This interface is not intended to be implemented by clients.
+ * </p>
+ */
+public interface ITaglibRecordEvent {
+
+	/**
+	 * @return the record that was changed
+	 */
+	ITaglibRecord getTaglibRecord();
+
+	/**
+	 * @return the type of change, one of ADDED, CHANGED, or REMOVED
+	 */
+	int getType();
+
+	int ADDED = IResourceDelta.ADDED;
+	int CHANGED = IResourceDelta.CHANGED;
+	int REMOVED = IResourceDelta.REMOVED;
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/taglib/IURLRecord.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/taglib/IURLRecord.java
new file mode 100644
index 0000000..e974d36
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/taglib/IURLRecord.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.taglib;
+
+import java.net.URL;
+
+/**
+ * A record representing a .tld that is not a standalone file
+ * <p>
+ * This interface is not intended to be implemented by clients.
+ * </p>
+ * 
+ * @since 1.0
+ */
+public interface IURLRecord extends ITaglibRecord {
+
+	/**
+	 * @return the base location to use for further resolution of resources
+	 *         from the TLD
+	 */
+	String getBaseLocation();
+
+	/**
+	 * @return Returns the short-name (normally treated as the
+	 *         recommended/default prefix), if one was specified within this
+	 *         TLD's contents.
+	 */
+	String getShortName();
+
+	/**
+	 * @deprecated - use the descriptor's URI value
+	 * @return Returns the uri specified within this TLD's contents.
+	 */
+	String getURI();
+
+	/**
+	 * @return Returns the URL to this TLD's contents.
+	 */
+	URL getURL();
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/taglib/ProjectDescription.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/taglib/ProjectDescription.java
new file mode 100644
index 0000000..79c2261
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/taglib/ProjectDescription.java
@@ -0,0 +1,2604 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.taglib;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.Reader;
+import java.io.Writer;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipException;
+import java.util.zip.ZipFile;
+import java.util.zip.ZipInputStream;
+
+import org.eclipse.core.filebuffers.FileBuffers;
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.resources.IResourceDeltaVisitor;
+import org.eclipse.core.resources.IResourceProxy;
+import org.eclipse.core.resources.IResourceProxyVisitor;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.ILock;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jdt.core.IClasspathContainer;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IJavaElementDelta;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IPackageFragmentRoot;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jst.jsp.core.internal.Logger;
+import org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.JSP11TLDNames;
+import org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.JSP12TLDNames;
+import org.eclipse.jst.jsp.core.internal.contenttype.DeploymentDescriptorPropertyCache;
+import org.eclipse.jst.jsp.core.internal.java.ArrayMap;
+import org.eclipse.jst.jsp.core.internal.util.DocumentProvider;
+import org.eclipse.jst.jsp.core.internal.util.FacetModuleCoreSupport;
+import org.eclipse.wst.common.uriresolver.internal.util.URIHelper;
+import org.eclipse.wst.sse.core.internal.util.JarUtilities;
+import org.eclipse.wst.sse.core.internal.util.Sorter;
+import org.eclipse.wst.sse.core.utils.StringUtils;
+import org.eclipse.wst.xml.core.internal.XMLCorePlugin;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalog;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalogEntry;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.INextCatalog;
+import org.w3c.dom.Document;
+import org.w3c.dom.EntityReference;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import com.ibm.icu.text.Collator;
+import com.ibm.icu.util.StringTokenizer;
+
+/**
+ * Contains the tag library information for a single project.
+ * 
+ *  * <p>
+ * This class is neither intended to be instantiated nor accessed by clients.
+ * </p>
+ *
+ */
+class ProjectDescription {
+	class BuildPathJob extends Job {
+		public BuildPathJob() {
+			super("Updating Tag Library Index");
+			setSystem(true);
+			setUser(false);
+		}
+
+		protected IStatus run(IProgressMonitor monitor) {
+			try {
+				LOCK.acquire();
+
+				PackageFragmentRootDelta[] removes = (PackageFragmentRootDelta[]) fPackageFragmentRootsRemoved.values().toArray(new PackageFragmentRootDelta[fPackageFragmentRootsRemoved.size()]);
+				for (int i = 0; i < removes.length; i++) {
+					handleElementChanged(removes[i].elementPath, removes[i].deltaKind, removes[i].isExported);
+				}
+				fPackageFragmentRootsRemoved.clear();
+				if (monitor.isCanceled())
+					return Status.OK_STATUS;
+				
+				PackageFragmentRootDelta[] changes = (PackageFragmentRootDelta[]) fPackageFragmentRootsChanged.values().toArray(new PackageFragmentRootDelta[fPackageFragmentRootsChanged.size()]);
+				for (int i = 0; i < changes.length; i++) {
+					handleElementChanged(changes[i].elementPath, changes[i].deltaKind, changes[i].isExported);
+				}
+				fPackageFragmentRootsChanged.clear();
+				if (monitor.isCanceled())
+					return Status.OK_STATUS;
+				
+				PackageFragmentRootDelta[] adds = (PackageFragmentRootDelta[]) fPackageFragmentRootsAdded.values().toArray(new PackageFragmentRootDelta[fPackageFragmentRootsAdded.size()]);
+				for (int i = 0; i < adds.length; i++) {
+					handleElementChanged(adds[i].elementPath, adds[i].deltaKind, adds[i].isExported);
+				}
+				fPackageFragmentRootsAdded.clear();
+			}
+			finally {
+				LOCK.release();
+			}
+			TaglibIndex.getInstance().fireCurrentDelta(BuildPathJob.this);
+			return Status.OK_STATUS;
+		}
+	}
+	
+	class PackageFragmentRootDelta {
+		PackageFragmentRootDelta(IPath path, int kind, boolean exported) {
+			super();
+			elementPath = path;
+			deltaKind = kind;
+			isExported = exported;
+		}
+
+		/*
+			IJavaElementDelta.F_ADDED_TO_CLASSPATH
+			IJavaElementDelta.F_ARCHIVE_CONTENT_CHANGED
+			IJavaElementDelta.F_REMOVED_FROM_CLASSPATH
+		*/ 
+		int deltaKind;
+		IPath elementPath;
+		boolean isExported;
+	}
+
+	class DeltaVisitor implements IResourceDeltaVisitor {
+		public boolean visit(IResourceDelta delta) throws CoreException {
+			IResource resource = delta.getResource();
+			if (resource.getType() == IResource.FILE) {
+				if (delta.getKind() == IResourceDelta.CHANGED && (delta.getFlags() == IResourceDelta.ENCODING || delta.getFlags() == IResourceDelta.MARKERS))
+					return true;
+				if (resource.getName().endsWith(".tld")) { //$NON-NLS-1$
+					if (delta.getKind() == IResourceDelta.REMOVED) {
+						removeTLD(resource);
+					}
+					else {
+						updateTLD(resource, delta.getKind());
+					}
+				}
+				else if (resource.getName().endsWith(".jar")) { //$NON-NLS-1$
+					if (delta.getKind() == IResourceDelta.REMOVED) {
+						removeJAR(resource);
+					}
+					else {
+						updateJAR(resource, delta.getKind());
+					}
+				}
+				else if ("tag".equalsIgnoreCase(resource.getFileExtension()) || "tagx".equalsIgnoreCase(resource.getFileExtension())) { //$NON-NLS-1$ //$NON-NLS-2$
+					if (delta.getKind() == IResourceDelta.REMOVED) {
+						removeTag(resource);
+					}
+					else {
+						updateTag(resource, delta.getKind());
+					}
+				}
+				else if (resource.getName().equals(WEB_XML) && resource.getParent().getName().equals(WEB_INF)) {
+					if (delta.getKind() == IResourceDelta.REMOVED) {
+						removeWebXML(resource);
+					}
+					else {
+						updateWebXML(resource, delta.getKind());
+					}
+				}
+			}
+			return resource.getName().length() != 0 && resource.getName().charAt(0) != '.';
+		}
+	}
+
+	class Indexer implements IResourceProxyVisitor {
+		public boolean visit(IResourceProxy proxy) throws CoreException {
+			boolean visitMembers = true;
+			if (proxy.getType() == IResource.FILE) {
+				if (proxy.getName().endsWith(".tld")) { //$NON-NLS-1$
+					updateTLD(proxy.requestResource(), ITaglibIndexDelta.ADDED);
+				}
+				else if (proxy.getName().endsWith(".jar")) { //$NON-NLS-1$
+					updateJAR(proxy.requestResource(), ITaglibIndexDelta.ADDED);
+				}
+				else if (proxy.getName().endsWith(".tag") || proxy.getName().endsWith(".tagx")) { //$NON-NLS-1$ //$NON-NLS-2$
+					updateTagDir(proxy.requestResource().getParent(), ITaglibIndexDelta.ADDED);
+					// any folder with these files will create a record for
+					// that folder in one pass
+					visitMembers = false;
+				}
+				else if (proxy.getName().equals(WEB_XML) && proxy.requestResource().getParent().getName().equals(WEB_INF)) {
+					updateWebXML(proxy.requestResource(), ITaglibIndexDelta.ADDED);
+				}
+			}
+			String name = proxy.getName();
+			return name.length() != 0 && name.charAt(0) != '.' && visitMembers;
+		}
+	}
+
+	static class JarRecord implements IJarRecord {
+		boolean has11TLD;
+		TaglibInfo info;
+
+		boolean isExported = true;
+		boolean isMappedInWebXML;
+		boolean isConsistent = false;
+		IPath location;
+		Collection urlRecords;
+
+		public boolean equals(Object obj) {
+			if (!(obj instanceof JarRecord))
+				return false;
+			return ((JarRecord) obj).location.equals(location) && ((JarRecord) obj).has11TLD == has11TLD && ((JarRecord) obj).info.equals(info);
+		}
+
+		public ITaglibDescriptor getDescriptor() {
+			return info != null ? info : new TaglibInfo();
+		}
+
+		/**
+		 * @return Returns the location.
+		 */
+		public IPath getLocation() {
+			return location;
+		}
+
+		public int getRecordType() {
+			return ITaglibRecord.JAR;
+		}
+
+		/**
+		 * @return Returns the recommended/default prefix if one was given.
+		 */
+		public String getShortName() {
+			if (info == null)
+				return null;
+			return info.shortName;
+		}
+
+		/**
+		 * @return Returns the uri.
+		 */
+		public String getURI() {
+			if (info == null)
+				return null;
+			return info.uri;
+		}
+
+		public Collection getURLRecords() {
+			return urlRecords;
+		}
+
+		public String toString() {
+			StringBuffer s = new StringBuffer("JarRecord: ");//$NON-NLS-1$ 
+			s.append(location);
+			if (urlRecords.size() > 0) {
+				s.append('\n');//$NON-NLS-1$ 
+				for (Iterator it = urlRecords.iterator(); it.hasNext();) {
+					s.append(it.next());
+					s.append('\n');//$NON-NLS-1$ 
+				}
+			}
+			return s.toString();
+		}
+	}
+
+	static class TagDirRecord implements ITagDirRecord {
+		TaglibInfo info;
+		IPath path;
+		// a List holding Strings of .tag and .tagx filenames relative to the
+		// tagdir's location
+		List tags = new ArrayList(0);
+
+		public boolean equals(Object obj) {
+			if (!(obj instanceof TagDirRecord))
+				return false;
+			return ((TagDirRecord) obj).path.equals(path) && ((TagDirRecord) obj).info.equals(info);
+		}
+
+		public ITaglibDescriptor getDescriptor() {
+			return info != null ? info : (info = new TaglibInfo());
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see org.eclipse.jst.jsp.core.taglib.ITagDirRecord#getPath()
+		 */
+		public IPath getPath() {
+			return path;
+		}
+
+		public int getRecordType() {
+			return ITaglibRecord.TAGDIR;
+		}
+
+		/**
+		 * @return Returns the tags.
+		 */
+		public String[] getTagFilenames() {
+			return (String[]) tags.toArray(new String[tags.size()]);
+		}
+
+		public String toString() {
+			return "TagdirRecord: " + path + " <-> " + info.shortName; //$NON-NLS-1$ //$NON-NLS-2$
+		}
+	}
+
+	/**
+	 * A brief representation of the information in a TLD.
+	 */
+	static class TaglibInfo implements ITaglibDescriptor {
+		// extract only when asked?
+		String description = "";
+		String displayName = "";
+		String jspVersion = "";
+		String largeIcon = "";
+		String shortName = "";
+		String smallIcon = "";
+		String tlibVersion = "";
+		String uri = "";
+
+		public TaglibInfo() {
+			super();
+		}
+
+		public boolean equals(Object obj) {
+			if (!(obj instanceof TaglibInfo))
+				return false;
+			return ((TaglibInfo) obj).jspVersion.equals(jspVersion) && ((TaglibInfo) obj).description.equals(description) && ((TaglibInfo) obj).largeIcon.equals(largeIcon) && ((TaglibInfo) obj).shortName.equals(shortName) && ((TaglibInfo) obj).smallIcon.equals(smallIcon) && ((TaglibInfo) obj).tlibVersion.equals(tlibVersion) && ((TaglibInfo) obj).uri.equals(uri);
+		}
+
+		public String getDescription() {
+			return description;
+		}
+
+		public String getDisplayName() {
+			return displayName;
+		}
+
+		public String getJSPVersion() {
+			return jspVersion;
+		}
+
+		public String getLargeIcon() {
+			return largeIcon;
+		}
+
+		public String getShortName() {
+			return shortName;
+		}
+
+		public String getSmallIcon() {
+			return smallIcon;
+		}
+
+		public String getTlibVersion() {
+			return tlibVersion;
+		}
+
+		public String getURI() {
+			return uri;
+		}
+
+		public String toString() {
+			return "TaglibInfo|" + uri + "|" + shortName + "|" + tlibVersion + "|" + smallIcon + "|" + largeIcon + "|" + jspVersion + "|" + description; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$
+		}
+	}
+
+	static class TLDRecord implements ITLDRecord {
+		TaglibInfo info;
+		IPath path;
+
+		public boolean equals(Object obj) {
+			if (!(obj instanceof TLDRecord))
+				return false;
+			return ((TLDRecord) obj).path.equals(path) && ((TLDRecord) obj).getURI().equals(getURI()) && ((TLDRecord) obj).info.equals(info);
+		}
+
+		public ITaglibDescriptor getDescriptor() {
+			return info != null ? info : new TaglibInfo();
+		}
+
+		public IPath getPath() {
+			return path;
+		}
+
+		public int getRecordType() {
+			return ITaglibRecord.TLD;
+		}
+
+		public String getShortName() {
+			if (info == null)
+				return null;
+			return info.shortName;
+		}
+
+		/**
+		 * @return Returns the uri.
+		 */
+		public String getURI() {
+			if (info == null)
+				return null;
+			return info.uri;
+		}
+
+		public String toString() {
+			return "TLDRecord: " + getURI() + " <-> " + path; //$NON-NLS-1$ //$NON-NLS-2$
+		}
+	}
+
+	static class URLRecord implements IURLRecord {
+		String baseLocation;
+		TaglibInfo info;
+		boolean isExported = true;
+		URL url;
+
+		public URLRecord() {
+			super();
+		}
+
+		public boolean equals(Object obj) {
+			if (!(obj instanceof URLRecord))
+				return false;
+			return ((URLRecord) obj).baseLocation.equals(baseLocation) && ((URLRecord) obj).url.equals(url) && ((URLRecord) obj).info.equals(info);
+		}
+
+		public int hashCode() {
+			return baseLocation.hashCode() + url.hashCode() + (isExported ? 1 : 0);
+		}
+
+		public String getBaseLocation() {
+			return baseLocation;
+		}
+
+		public ITaglibDescriptor getDescriptor() {
+			return info != null ? info : new TaglibInfo();
+		}
+
+		public int getRecordType() {
+			return ITaglibRecord.URL;
+		}
+
+		/**
+		 * @return Returns the recommended/default prefix if one was given.
+		 */
+		public String getShortName() {
+			if (info == null)
+				return null;
+			return info.shortName;
+		}
+
+		/**
+		 * @return Returns the uri.
+		 */
+		public String getURI() {
+			if (info == null)
+				return ""; //$NON-NLS-1$
+			return info.uri;
+		}
+
+		/**
+		 * @return Returns the URL.
+		 */
+		public URL getURL() {
+			return url;
+		}
+
+		public String toString() {
+			return "URLRecord: (exported=" + isExported + ") " + baseLocation + " <-> " + getURI(); //$NON-NLS-1$ //$NON-NLS-2$
+		}
+	}
+
+	static class WebXMLRecord {
+		TaglibInfo info;
+		IPath path;
+		List tldRecords = new ArrayList(0);
+
+		public boolean equals(Object obj) {
+			if (!(obj instanceof WebXMLRecord))
+				return false;
+			return ((WebXMLRecord) obj).path.equals(path) && ((WebXMLRecord) obj).info.equals(info);
+		}
+
+		/**
+		 * @return Returns the recommended/default prefix if one was given.
+		 */
+		public String getPrefix() {
+			if (info == null)
+				return null;
+			return info.shortName;
+		}
+
+		/**
+		 * 
+		 */
+		public List getTLDRecords() {
+			return tldRecords;
+		}
+
+		/**
+		 * @return Returns the webxml.
+		 */
+		public IPath getWebXML() {
+			return path;
+		}
+
+		public String toString() {
+			StringBuffer s = new StringBuffer("WebXMLRecord: ");//$NON-NLS-1$ 
+			s.append(path);
+			if (tldRecords.size() > 0) {
+				s.append('\n');//$NON-NLS-1$ 
+				for (int i = 0; i < tldRecords.size(); i++) {
+					s.append(tldRecords.get(i));
+					s.append('\n');//$NON-NLS-1$ 
+				}
+			}
+			return s.toString();
+		}
+	}
+	
+	private class TaglibSorter extends Sorter {
+		Collator collator = Collator.getInstance();
+
+		public boolean compare(Object elementOne, Object elementTwo) {
+			/**
+			 * Returns true if elementTwo is 'greater than' elementOne This is
+			 * the 'ordering' method of the sort operation. Each subclass
+			 * overides this method with the particular implementation of the
+			 * 'greater than' concept for the objects being sorted.
+			 */
+			
+			return (collator.compare(getTaglibPath((ITaglibRecord) elementOne), getTaglibPath((ITaglibRecord) elementTwo))) < 0;
+		}
+		
+		private String getTaglibPath(ITaglibRecord record) {
+			switch(record.getRecordType()) {
+				case ITaglibRecord.JAR:
+					return ((JarRecord) record).getLocation().toString();
+				case ITaglibRecord.TAGDIR:
+					return ((TagDirRecord) record).getPath().toString();
+				case ITaglibRecord.TLD:
+					return ((TLDRecord) record).getPath().toString();
+				case ITaglibRecord.URL:
+					return ((URLRecord) record).getBaseLocation();
+				default:
+					return ""; //$NON-NLS-1$
+			}
+		}
+	}
+
+	static boolean _debugIndexCreation = "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.jst.jsp.core/taglib/indexcreation")); //$NON-NLS-1$ //$NON-NLS-2$
+	static boolean _debugIndexTime = "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.jst.jsp.core/taglib/indextime")); //$NON-NLS-1$ //$NON-NLS-2$
+
+	private static final String BUILDPATH_DIRTY = "BUILDPATH_DIRTY"; //$NON-NLS-1$
+	private static final String BUILDPATH_ENTRIES = "BUILDPATH_ENTRIES"; //$NON-NLS-1$
+	private static final String BUILDPATH_PROJECT = "BUILDPATH_PROJECT"; //$NON-NLS-1$
+	private static final String SAVE_FORMAT_VERSION = "Tag Library Index 1.1.0"; //$NON-NLS-1$
+	private static final String WEB_INF = "WEB-INF"; //$NON-NLS-1$
+	private static final IPath WEB_INF_PATH = new Path(WEB_INF);
+	private static final String WEB_XML = "web.xml"; //$NON-NLS-1$
+	private static final char[] TLD = { 't', 'T', 'l', 'L', 'd', 'D'} ;
+	/**
+	 * Notes that the build path information is stale. Some operations can now
+	 * be skipped until a resolve/getAvailable call is made.
+	 */
+	boolean fBuildPathIsDirty = false;
+
+	/**
+	 * Count of entries on the build path. Primary use case is for classpath
+	 * containers that add an entry. Without notification (3.3), we can only
+	 * check after-the-fact.
+	 */
+	int fBuildPathEntryCount = 0;
+
+	/**
+	 * A cached copy of all of the records createable from the XMLCatalog.
+	 */
+	private Collection fCatalogRecords;
+
+	/*
+	 * Records active JARs on the classpath. Taglib descriptors should be
+	 * usable, but the jars by themselves are not.
+	 */
+	Hashtable fClasspathJars;
+
+	/**
+	 * A set of the projects that are in this project's build path.
+	 * Lookups/enumerations will be redirected to the corresponding
+	 * ProjectDescription instances
+	 */
+	Set fClasspathProjects = null;
+
+	// holds references by URI to JARs
+	Hashtable fClasspathReferences;
+
+	/*
+	 * this table is special in that it holds tables of references according
+	 * to local roots
+	 */
+	Hashtable fImplicitReferences;
+
+	Hashtable fJARReferences;
+
+	IProject fProject;
+
+	private String fSaveStateFilename;
+
+	/**
+	 * String->ITaglibRecord
+	 */
+	Hashtable fTagDirReferences;
+
+	Hashtable fTLDReferences;
+
+	IResourceDeltaVisitor fVisitor;
+	Hashtable fWebXMLReferences;
+	
+	private Map fPackageFragmentRootsAdded = new HashMap();
+	private Map fPackageFragmentRootsChanged = new HashMap();
+	private Map fPackageFragmentRootsRemoved = new HashMap();
+
+	ILock LOCK = Job.getJobManager().newLock();
+
+	private long time0;
+	
+	private TaglibSorter fTaglibSorter = new TaglibSorter();
+	private BuildPathJob fBuildPathJob = new BuildPathJob();
+
+	/** Shared JAR records between projects */
+	private static final Map fJarRecords = new Hashtable();
+
+	ProjectDescription(IProject project, String saveStateFile) {
+		super();
+		fProject = project;
+		fSaveStateFilename = saveStateFile;
+
+		fClasspathJars = new Hashtable(0);
+		fJARReferences = new Hashtable(0);
+		fTagDirReferences = new Hashtable(0);
+		fTLDReferences = new Hashtable(0);
+		fWebXMLReferences = new Hashtable(0);
+		fImplicitReferences = new Hashtable(0);
+		fClasspathReferences = new Hashtable(0);
+		fClasspathProjects = new HashSet();
+
+		restoreReferences();
+	}
+
+	private Collection _getJSP11AndWebXMLJarReferences(Collection allJARs) {
+		List collection = new ArrayList(allJARs.size());
+		Iterator i = allJARs.iterator();
+		while (i.hasNext()) {
+			JarRecord record = (JarRecord) i.next();
+			if (record.has11TLD || record.isMappedInWebXML) {
+				collection.add(record);
+			}
+		}
+		return collection;
+	}
+
+	/**
+	 * Adds the list of known references from this project's build path to the
+	 * map, appending any processed projects into the list to avoid
+	 * build-path-cycles.
+	 * 
+	 * @see https://bugs.eclipse.org/bugs/show_bug.cgi?id=142408
+	 * 
+	 * @param references -
+	 *            the map of references to ITaglibRecords
+	 * @param projectsProcessed -
+	 *            the list of projects already considered
+	 * @param exportedOnly -
+	 *            Whether to only add references derived from exported build
+	 *            path containers. This method calls itself recursively with
+	 *            this parameter as false.
+	 */
+	void addBuildPathReferences(Map references, List projectsProcessed, boolean exportedOnly) {
+		ensureUpTodate();
+
+		// Add the build path references that are exported from this project
+		Enumeration keys = fClasspathReferences.keys();
+		while (keys.hasMoreElements()) {
+			Object key = keys.nextElement();
+			URLRecord urlRecord = (URLRecord) fClasspathReferences.get(key);
+			if (exportedOnly) {
+				if (urlRecord.isExported) {
+					references.put(key, urlRecord);
+				}
+			}
+			else {
+				references.put(key, urlRecord);
+			}
+		}
+		IProject[] buildpathProjects = (IProject[]) fClasspathProjects.toArray(new IProject[fClasspathProjects.size()]);
+		for (int i = 0; i < buildpathProjects.length; i++) {
+			if (!projectsProcessed.contains(buildpathProjects[i]) && buildpathProjects[i].isAccessible()) {
+				projectsProcessed.add(buildpathProjects[i]);
+				ProjectDescription description = TaglibIndex.getInstance().createDescription(buildpathProjects[i]);
+				description.addBuildPathReferences(references, projectsProcessed, true);
+
+				/*
+				 * 199843 (183756) - JSP Validation Cannot Find Tag Library
+				 * Descriptor in Referenced Projects
+				 * 
+				 * Add any TLD records having URI values from projects on the
+				 * build path
+				 */
+				Map[] rootReferences = (Map[]) description.fImplicitReferences.values().toArray(new Map[description.fImplicitReferences.size()]);
+				for (int j = 0; j < rootReferences.length; j++) {
+					Iterator implicitRecords = rootReferences[j].values().iterator();
+					while (implicitRecords.hasNext()) {
+						ITaglibRecord record = (ITaglibRecord) implicitRecords.next();
+						if (record.getRecordType() == ITaglibRecord.TLD && ((ITLDRecord) record).getURI() != null && ((ITLDRecord) record).getURI().length() > 0) {
+							references.put(((ITLDRecord) record).getURI(), record);
+						}
+					}
+				}
+			}
+		}
+	}
+
+	/**
+	 * Erases all known tables
+	 */
+	void clear() {
+		fClasspathJars = new Hashtable(0);
+		fJARReferences = new Hashtable(0);
+		fTagDirReferences = new Hashtable(0);
+		fTLDReferences = new Hashtable(0);
+		fWebXMLReferences = new Hashtable(0);
+		fImplicitReferences = new Hashtable(0);
+		fClasspathReferences = new Hashtable(0);
+	}
+
+	private void closeJarFile(ZipFile file) {
+		if (file == null)
+			return;
+		try {
+			file.close();
+		}
+		catch (IOException ioe) {
+			// no cleanup can be done
+			Logger.logException("TaglibIndex: Could not close zip file " + file.getName(), ioe); //$NON-NLS-1$
+		}
+	}
+
+	/**
+	 * @param catalogEntry
+	 *            a XML catalog entry pointing to a .jar or .tld file
+	 * @return a ITaglibRecord describing a TLD contributed to the XMLCatalog
+	 *         if one was found at the given location, null otherwise
+	 */
+	private ITaglibRecord createCatalogRecord(ICatalogEntry catalogEntry) {
+		return createCatalogRecord(catalogEntry.getKey(), catalogEntry.getURI());
+	}
+
+	/**
+	 * @param uri -
+	 *            the key value that will become the returned record's "URI"
+	 * @param urlString -
+	 *            the string indicating where the TLD really is
+	 * @return a ITaglibRecord describing a TLD contributed to the XMLCatalog
+	 *         if one was found at the given location, null otherwise
+	 */
+	private ITaglibRecord createCatalogRecord(String uri, String urlString) {
+		ITaglibRecord record = null;
+		// handle "file:" URLs that point to a .jar file on disk (1.1 mode)
+		if (urlString.toLowerCase(Locale.US).endsWith((".jar")) && urlString.startsWith("file:")) { //$NON-NLS-1$ //$NON-NLS-2$
+			String fileLocation = null;
+			try {
+				URL url = new URL(urlString);
+				fileLocation = url.getFile();
+			}
+			catch (MalformedURLException e) {
+				// not worth reporting
+				Logger.log(Logger.ERROR_DEBUG, null, e);
+			}
+			if (fileLocation != null) {
+				JarRecord jarRecord = createJARRecord(fileLocation);
+				String[] entries = JarUtilities.getEntryNames(fileLocation);
+				for (int jEntry = 0; jEntry < entries.length; jEntry++) {
+					if (entries[jEntry].endsWith(".tld")) { //$NON-NLS-1$
+						if (entries[jEntry].equals(JarUtilities.JSP11_TAGLIB)) {
+							jarRecord.has11TLD = true;
+							InputStream contents = JarUtilities.getInputStream(fileLocation, entries[jEntry]);
+							if (contents != null) {
+								TaglibInfo info = extractInfo(fileLocation, contents);
+								/*
+								 * the record's reported URI should match the
+								 * catalog entry's "key" so replace the
+								 * detected value
+								 */
+								info.uri = uri;
+								jarRecord.info = info;
+							}
+							try {
+								contents.close();
+							}
+							catch (IOException e) {
+								Logger.log(Logger.ERROR_DEBUG, null, e);
+							}
+						}
+					}
+				}
+				if (jarRecord.has11TLD) {
+					if (_debugIndexCreation)
+						Logger.log(Logger.INFO, "created catalog record for " + urlString + "@" + jarRecord.getLocation()); //$NON-NLS-1$ //$NON-NLS-2$
+					record = jarRecord;
+				}
+
+			}
+		}
+		// The rest are URLs into a plug-in...somewhere
+		else {
+			URL url = null;
+			InputStream tldStream = null;
+			try {
+				url = new URL(urlString);
+				tldStream = JarUtilities.getInputStream(url);
+			}
+			catch (Exception e1) {
+				Logger.logException("Exception reading TLD contributed to the XML Catalog", e1);
+			}
+
+			if (tldStream != null) {
+				URLRecord urlRecord = null;
+				TaglibInfo info = extractInfo(urlString, tldStream);
+				if (info != null) {
+					/*
+					 * the record's reported URI should match the catalog
+					 * entry's "key" so replace the detected value
+					 */
+					info.uri = uri;
+					urlRecord = new URLRecord();
+					urlRecord.info = info;
+					urlRecord.baseLocation = urlString;
+					urlRecord.url = url; //$NON-NLS-1$ //$NON-NLS-2$
+				}
+				try {
+					tldStream.close();
+				}
+				catch (IOException e) {
+					Logger.log(Logger.ERROR_DEBUG, null, e);
+				}
+				record = urlRecord;
+			}
+		}
+		return record;
+	}
+
+	/**
+	 * @param resource
+	 * @return
+	 */
+	private JarRecord createJARRecord(IResource jar) {
+		IPath location = jar.getLocation();
+		JarRecord jarRecord = null;
+		if (location != null) {
+			jarRecord = createJARRecord(location.toString());
+		}
+		else if (jar.getLocationURI() != null) {
+			jarRecord = createJARRecord(jar.getLocationURI().toString());
+		}
+		return jarRecord;
+	}
+
+	private JarRecord createJARRecord(String fileLocation) {
+		synchronized (fJarRecords) {
+			JarRecord record = (JarRecord) fJarRecords.get(fileLocation);
+			if (record == null) {
+				record = new JarRecord();
+				record.info = new TaglibInfo();
+				record.location = new Path(fileLocation);
+				record.urlRecords = new HashSet(0);
+				fJarRecords.put(fileLocation, record);
+			}
+			return record;
+		}
+	}
+
+	/**
+	 * @return
+	 */
+	private TagDirRecord createTagdirRecord(IFolder tagdir) {
+		IPath tagdirPath = tagdir.getFullPath();
+		TagDirRecord record = new TagDirRecord();
+		record.path = tagdir.getFullPath();
+		record.info = new TaglibInfo();
+		// 8.4.3
+		if (tagdir.getName().equals("tags")) //$NON-NLS-1$
+			record.info.shortName = "tags"; //$NON-NLS-1$
+		else {
+			boolean determined = false;
+			IPath path = tagdirPath;
+			String[] segments = path.segments();
+			for (int i = 1; i < segments.length; i++) {
+				if (segments[i - 1].equals("WEB-INF") && segments[i].equals("tags")) { //$NON-NLS-1$ //$NON-NLS-2$
+					IPath tagdirLocalPath = path.removeFirstSegments(i + 1);
+					record.info.shortName = StringUtils.replace(tagdirLocalPath.toString(), "/", "-");
+					determined = true;
+				}
+			}
+			if (!determined) {
+				record.info.shortName = StringUtils.replace(tagdirPath.toString(), "/", "-");
+			}
+		}
+		// 8.4.3
+		record.info.tlibVersion = "1.0";
+		record.info.description = "";
+		record.info.displayName = "";
+		record.info.smallIcon = "";
+		record.info.largeIcon = "";
+
+		try {
+			IResource[] tagfiles = tagdir.members();
+			for (int i = 0; i < tagfiles.length; i++) {
+				if (tagfiles[i].getType() != IResource.FILE)
+					continue;
+				String extension = tagfiles[i].getFileExtension();
+				if (extension != null && (extension.equals("tag") || extension.equals("tagx"))) {
+					record.tags.add(tagfiles[i].getName());
+				}
+			}
+		}
+		catch (CoreException e) {
+			Logger.logException(e);
+		}
+
+		return record;
+	}
+
+	/**
+	 * @param resource
+	 * @return
+	 */
+	private TLDRecord createTLDRecord(IResource tld) {
+		TLDRecord record = new TLDRecord();
+		record.path = tld.getFullPath();
+		InputStream contents = null;
+		try {
+			if (tld.isAccessible()) {
+				contents = ((IFile) tld).getContents();
+				String basePath = tld.getFullPath().toString();
+				TaglibInfo info = extractInfo(basePath, contents);
+				if (info != null) {
+					record.info = info;
+				}
+			}
+		}
+		catch (CoreException e) {
+			// out of sync
+		}
+		finally {
+			try {
+				if (contents != null) {
+					contents.close();
+				}
+			}
+			catch (IOException e) {
+				// ignore
+				Logger.log(Logger.ERROR_DEBUG, null, e);
+			}
+		}
+		return record;
+	}
+
+	private void ensureUpTodate() {
+		IClasspathEntry[] entries = null;
+			try {
+				/*
+				 * If the Java nature isn't present (or something else is
+				 * wrong), don't check the build path.
+				 */
+				IJavaProject jproject = JavaCore.create(fProject);
+				if (jproject != null && jproject.exists()) {
+					entries = jproject.getResolvedClasspath(true);
+				}
+			}
+			catch (JavaModelException e) {
+				Logger.logException(e);
+			}
+		if (entries != null) {
+			try {
+				LOCK.acquire();
+				/*
+				 * Double-check that the number of build path entries has not
+				 * changed. This should cover most cases such as when a
+				 * library is added into or removed from a container.
+				 */
+				fBuildPathIsDirty = fBuildPathIsDirty || (fBuildPathEntryCount != entries.length);
+
+				if (fBuildPathIsDirty) {
+					indexClasspath(entries);
+					fBuildPathIsDirty = false;
+				}
+				else {
+					PackageFragmentRootDelta[] removes = (PackageFragmentRootDelta[]) fPackageFragmentRootsRemoved.values().toArray(new PackageFragmentRootDelta[fPackageFragmentRootsRemoved.size()]);
+					for (int i = 0; i < removes.length; i++) {
+						handleElementChanged(removes[i].elementPath, removes[i].deltaKind, removes[i].isExported);
+					}
+					PackageFragmentRootDelta[] changes = (PackageFragmentRootDelta[]) fPackageFragmentRootsChanged.values().toArray(new PackageFragmentRootDelta[fPackageFragmentRootsChanged.size()]);
+					for (int i = 0; i < changes.length; i++) {
+						handleElementChanged(changes[i].elementPath, changes[i].deltaKind, changes[i].isExported);
+					}
+					PackageFragmentRootDelta[] adds = (PackageFragmentRootDelta[]) fPackageFragmentRootsAdded.values().toArray(new PackageFragmentRootDelta[fPackageFragmentRootsAdded.size()]);
+					for (int i = 0; i < adds.length; i++) {
+						handleElementChanged(adds[i].elementPath, adds[i].deltaKind, adds[i].isExported);
+					}
+					fPackageFragmentRootsRemoved.clear();
+					fPackageFragmentRootsChanged.clear();
+					fPackageFragmentRootsAdded.clear();
+				}
+			}
+			finally {
+				LOCK.release();
+			}
+		}
+	}
+
+	private TaglibInfo extractInfo(String basePath, InputStream tldContents) {
+		TaglibInfo info = new TaglibInfo();
+		if (tldContents != null) {
+			DocumentProvider provider = new DocumentProvider();
+			provider.setInputStream(tldContents);
+			provider.setValidating(false);
+			provider.setRootElementName(JSP12TLDNames.TAGLIB);
+			provider.setBaseReference(basePath);
+			Node child = provider.getRootElement();
+			if (child == null || child.getNodeType() != Node.ELEMENT_NODE || !child.getNodeName().equals(JSP12TLDNames.TAGLIB)) {
+				return null;
+			}
+			child = child.getFirstChild();
+			while (child != null) {
+				if (child.getNodeType() == Node.ELEMENT_NODE) {
+					if (child.getNodeName().equals(JSP12TLDNames.URI)) {
+						info.uri = getTextContents(child);
+					}
+					else if (child.getNodeName().equals(JSP12TLDNames.SHORT_NAME) || child.getNodeName().equals(JSP11TLDNames.SHORTNAME)) {
+						info.shortName = getTextContents(child);
+					}
+					else if (child.getNodeName().equals(JSP12TLDNames.DESCRIPTION) || child.getNodeName().equals(JSP11TLDNames.INFO)) {
+						info.description = getTextContents(child);
+					}
+					else if (child.getNodeName().equals(JSP12TLDNames.DISPLAY_NAME)) {
+						info.displayName = getTextContents(child);
+					}
+					else if (child.getNodeName().equals(JSP12TLDNames.JSP_VERSION) || child.getNodeName().equals(JSP11TLDNames.JSPVERSION)) {
+						info.jspVersion = getTextContents(child);
+					}
+					else if (child.getNodeName().equals(JSP12TLDNames.TLIB_VERSION) || child.getNodeName().equals(JSP11TLDNames.TLIBVERSION)) {
+						info.tlibVersion = getTextContents(child);
+					}
+					else if (child.getNodeName().equals(JSP12TLDNames.SMALL_ICON)) {
+						info.smallIcon = getTextContents(child);
+					}
+					else if (child.getNodeName().equals(JSP12TLDNames.LARGE_ICON)) {
+						info.largeIcon = getTextContents(child);
+					}
+				}
+				child = child.getNextSibling();
+			}
+		}
+		return info;
+	}
+
+	List getAvailableTaglibRecords(IPath path) {
+		ensureUpTodate();
+		Collection records = null;
+		try {
+			float jspVersion = DeploymentDescriptorPropertyCache.getInstance().getJSPVersion(path);
+			LOCK.acquire();
+
+			Collection implicitReferences = new HashSet(getImplicitReferences(path.toString()).values());
+			records = new HashSet(fTLDReferences.size() + fTagDirReferences.size() + fJARReferences.size() + fWebXMLReferences.size());
+			records.addAll(fTLDReferences.values());
+			if (jspVersion >= 1.1) {
+				records.addAll(_getJSP11AndWebXMLJarReferences(fJARReferences.values()));
+			}
+
+			if (jspVersion >= 1.2) {
+				records.addAll(implicitReferences);
+
+				Map buildPathReferences = new HashMap();
+				List projectsProcessed = new ArrayList(fClasspathProjects.size() + 1);
+				projectsProcessed.add(fProject);
+				addBuildPathReferences(buildPathReferences, projectsProcessed, false);
+				records.addAll(buildPathReferences.values());
+				
+				if(path.segmentCount() > 1) {
+					records.addAll(new HashSet(getImplicitReferences(fProject.getFullPath().toString()).values()));
+				}
+			}
+			if (jspVersion >= 2.0) {
+				records.addAll(fTagDirReferences.values());
+			}
+			
+			IPath localWebXML = new Path(getLocalRoot(path.toString())).append("/WEB-INF/web.xml"); //$NON-NLS-1$ 
+			WebXMLRecord webxmlRecord = (WebXMLRecord) fWebXMLReferences.get(localWebXML.toString());
+			if(webxmlRecord != null)
+				records.addAll(webxmlRecord.getTLDRecords());
+
+			records.addAll(getCatalogRecords());
+		}
+		finally {
+			LOCK.release();
+		}
+		return new ArrayList(records);
+	}
+
+	/**
+	 * Provides a stream to a local copy of the input or null if not possible
+	 */
+	private InputStream getCachedInputStream(ZipFile zipFile, ZipEntry zipEntry) {
+		InputStream cache = null;
+		if (zipFile != null) {
+			if (zipEntry != null) {
+				InputStream entryInputStream = null;
+				try {
+					entryInputStream = zipFile.getInputStream(zipEntry);
+				}
+				catch (IOException ioExc) {
+					Logger.logException("Taglib Index: " + zipFile.getName(), ioExc); //$NON-NLS-1$
+				}
+
+				if (entryInputStream != null) {
+					int c;
+					ByteArrayOutputStream buffer = null;
+					if (zipEntry.getSize() > 0) {
+						buffer = new ByteArrayOutputStream((int) zipEntry.getSize());
+					}
+					else {
+						buffer = new ByteArrayOutputStream();
+					}
+					// array dim restriction?
+					byte bytes[] = new byte[2048];
+					try {
+						while ((c = entryInputStream.read(bytes)) >= 0) {
+							buffer.write(bytes, 0, c);
+						}
+						cache = new ByteArrayInputStream(buffer.toByteArray());
+					}
+					catch (IOException ioe) {
+						// no cleanup can be done
+						Logger.log(Logger.ERROR_DEBUG, null, ioe);
+					}
+					finally {
+						try {
+							entryInputStream.close();
+						}
+						catch (IOException e) {
+							Logger.log(Logger.ERROR_DEBUG, null, e);
+						}
+					}
+				}
+			}
+		}
+
+		return cache;
+	}
+
+	private Collection getCatalogRecords() {
+		if (fCatalogRecords == null) {
+			List records = new ArrayList();
+			ICatalog defaultCatalog = XMLCorePlugin.getDefault().getDefaultXMLCatalog();
+			if (defaultCatalog != null) {
+				// Process default catalog
+				ICatalogEntry[] entries = defaultCatalog.getCatalogEntries();
+				for (int entry = 0; entry < entries.length; entry++) {
+					ITaglibRecord record = createCatalogRecord(entries[entry]);
+					records.add(record);
+				}
+
+				// Process declared OASIS nextCatalogs catalog
+				INextCatalog[] nextCatalogs = defaultCatalog.getNextCatalogs();
+				for (int nextCatalog = 0; nextCatalog < nextCatalogs.length; nextCatalog++) {
+					ICatalog catalog = nextCatalogs[nextCatalog].getReferencedCatalog();
+					ICatalogEntry[] entries2 = catalog.getCatalogEntries();
+					for (int entry = 0; entry < entries2.length; entry++) {
+						String uri = entries2[entry].getURI();
+						if (uri != null) {
+							uri = uri.toLowerCase(Locale.US);
+							if (uri.endsWith((".jar")) || uri.endsWith((".tld"))) {
+								ITaglibRecord record = createCatalogRecord(entries2[entry]);
+								if (record != null) {
+									records.add(record);
+								}
+							}
+						}
+					}
+				}
+			}
+			fCatalogRecords = records;
+		}
+		return fCatalogRecords;
+	}
+
+	/**
+	 * @return Returns the implicitReferences for the given path
+	 */
+	Hashtable getImplicitReferences(String path) {
+		String localRoot = getLocalRoot(path);
+		Hashtable implicitReferences = (Hashtable) fImplicitReferences.get(localRoot);
+		if (implicitReferences == null) {
+			implicitReferences = new ArrayMap(1);
+			fImplicitReferences.put(localRoot, implicitReferences);
+		}
+		return implicitReferences;
+	}
+
+	/**
+	 * @param basePath
+	 * @return the applicable Web context root path, if one exists
+	 * @deprecated
+	 */
+	IPath getLocalRoot(IPath basePath) {
+		IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
+
+		// existing workspace resources - this is the 93% case
+		IResource file = FileBuffers.getWorkspaceFileAtLocation(basePath);
+
+		// Try the base path as a folder first
+		if (file == null && basePath.segmentCount() > 1) {
+			file = workspaceRoot.getFolder(basePath);
+		}
+		// If not a folder, then try base path as a file
+		if (file != null && !file.exists() && basePath.segmentCount() > 1) {
+			file = workspaceRoot.getFile(basePath);
+		}
+
+		if (file == null && basePath.segmentCount() == 1) {
+			file = workspaceRoot.getProject(basePath.segment(0));
+		}
+
+		if (file == null) {
+			/*
+			 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=116529
+			 * 
+			 * This method produces a less accurate result, but doesn't
+			 * require that the file exist yet.
+			 */
+			IFile[] files = ResourcesPlugin.getWorkspace().getRoot().findFilesForLocation(basePath);
+			if (files.length > 0)
+				file = files[0];
+		}
+
+		while (file != null) {
+			/**
+			 * Treat any parent folder with a WEB-INF subfolder as a web-app
+			 * root
+			 */
+			IContainer folder = null;
+			if ((file.getType() & IResource.FOLDER) != 0) {
+				folder = (IContainer) file;
+			}
+			else {
+				folder = file.getParent();
+			}
+			// getFolder on a workspace root must use a full path, skip
+			if (folder != null && (folder.getType() & IResource.ROOT) == 0) {
+				IFolder webinf = folder.getFolder(WEB_INF_PATH);
+				if (webinf != null && webinf.exists()) {
+					return folder.getFullPath();
+				}
+			}
+			file = file.getParent();
+		}
+
+		return fProject.getFullPath();
+	}
+
+	/**
+	 * @param basePath
+	 * @return
+	 */
+	private String getLocalRoot(String basePath) {
+		return getLocalRoot(new Path(basePath)).toString();
+	}
+
+	private String getTextContents(Node parent) {
+		NodeList children = parent.getChildNodes();
+		if (children.getLength() == 1) {
+			Node child = children.item(0);
+			if (child.getNodeValue() != null)
+				return child.getNodeValue().trim();
+		}
+		StringBuffer s = new StringBuffer();
+		Node child = parent.getFirstChild();
+		while (child != null) {
+			if (child.getNodeType() == Node.ENTITY_REFERENCE_NODE) {
+				String reference = ((EntityReference) child).getNodeValue();
+				if (reference == null && child.getNodeName() != null) {
+					reference = "&" + child.getNodeName() + ";"; //$NON-NLS-1$ //$NON-NLS-2$
+				}
+				if (reference != null) {
+					s.append(reference.trim());
+				}
+			}
+			else if (child.getNodeValue() != null) {
+				s.append(child.getNodeValue().trim());
+			}
+			child = child.getNextSibling();
+		}
+		return s.toString().trim();
+	}
+
+	/**
+	 * @return Returns the visitor.
+	 */
+	IResourceDeltaVisitor getVisitor() {
+		if (fVisitor == null) {
+			fVisitor = new DeltaVisitor();
+		}
+		return fVisitor;
+	}
+
+	void handleElementChanged(IPath libraryPath, int deltaKind, boolean exported) {
+		IFile file = libraryPath.segmentCount() > 1 ? ResourcesPlugin.getWorkspace().getRoot().getFile(libraryPath) : null;
+		String libraryLocation = null;
+		if (file != null && file.isAccessible() && file.getLocation() != null)
+			libraryLocation = file.getLocation().toString();
+		else
+			libraryLocation = libraryPath.toString();
+		updateClasspathLibrary(libraryLocation, deltaKind, exported);
+	}
+	
+	void handleElementChanged(IJavaElementDelta delta) {
+		if (fBuildPathIsDirty) {
+			return;
+		}
+
+		// Logger.log(Logger.INFO_DEBUG, "IJavaElementDelta: " + delta);
+		IJavaElement element = delta.getElement();
+		if (element.getElementType() == IJavaElement.JAVA_PROJECT) {
+			IJavaElementDelta[] affectedChildren = delta.getAffectedChildren();
+			for (int i = 0; i < affectedChildren.length; i++) {
+				handleElementChanged(affectedChildren[i]);
+			}
+		}
+		if (element.getElementType() == IJavaElement.PACKAGE_FRAGMENT_ROOT && ((IPackageFragmentRoot) element).isArchive()) {
+			time0 = System.currentTimeMillis();
+			if (element.getElementType() == IJavaElement.PACKAGE_FRAGMENT_ROOT && ((IPackageFragmentRoot) element).isExternal()) {
+			}
+			String libLocation = null;
+			int taglibRecordEventKind = -1;
+			if ((delta.getFlags() & IJavaElementDelta.F_ADDED_TO_CLASSPATH) > 0 || (delta.getFlags() & IJavaElementDelta.F_ARCHIVE_CONTENT_CHANGED) > 0 || (delta.getFlags() & IJavaElementDelta.F_REMOVED_FROM_CLASSPATH) > 0) {
+				taglibRecordEventKind = ITaglibIndexDelta.CHANGED;
+				if ((delta.getFlags() & IJavaElementDelta.F_ADDED_TO_CLASSPATH) > 0) {
+					taglibRecordEventKind = ITaglibIndexDelta.ADDED;
+				}
+				else if ((delta.getFlags() & IJavaElementDelta.F_ARCHIVE_CONTENT_CHANGED) > 0) {
+					taglibRecordEventKind = ITaglibIndexDelta.CHANGED;
+				}
+				else if ((delta.getFlags() & IJavaElementDelta.F_REMOVED_FROM_CLASSPATH) > 0) {
+					taglibRecordEventKind = ITaglibIndexDelta.REMOVED;
+				}
+				IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(element.getPath());
+				if (file.isAccessible() && file.getLocation() != null)
+					libLocation = file.getLocation().toString();
+				else
+					libLocation = element.getPath().toString();
+			}
+			if (libLocation != null) {
+				boolean fragmentisExported = true;
+				try {
+					IClasspathEntry rawClasspathEntry = ((IPackageFragmentRoot) element).getRawClasspathEntry();
+					/*
+					 * null may also be returned for deletions depending on
+					 * resource/build path notification order. If it's null,
+					 * it's been deleted and whether it's exported won't
+					 * really matter
+					 */
+					if (rawClasspathEntry != null) {
+						fragmentisExported = rawClasspathEntry.isExported();
+					}
+				}
+				catch (JavaModelException e) {
+					// IPackageFragmentRoot not part of the build path
+				}
+				if ((delta.getFlags() & IJavaElementDelta.F_ADDED_TO_CLASSPATH) > 0) {
+					fBuildPathEntryCount++;
+				}
+				else if ((delta.getFlags() & IJavaElementDelta.F_REMOVED_FROM_CLASSPATH) > 0) {
+					fBuildPathEntryCount--;
+				}
+				updateClasspathLibrary(libLocation, taglibRecordEventKind, fragmentisExported);
+			}
+			if (_debugIndexTime)
+				Logger.log(Logger.INFO, "processed build path delta for " + fProject.getName() + "(" + element.getPath() + ") in " + (System.currentTimeMillis() - time0) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+		}
+	}
+
+	void index() {
+		time0 = System.currentTimeMillis();
+
+		fTLDReferences.clear();
+		fJARReferences.clear();
+		fTagDirReferences.clear();
+		fWebXMLReferences.clear();
+
+		try {
+			fProject.accept(new Indexer(), 0);
+		}
+		catch (CoreException e) {
+			Logger.logException(e);
+		}
+
+		if (_debugIndexTime)
+			Logger.log(Logger.INFO, "indexed " + fProject.getName() + " contents in " + (System.currentTimeMillis() - time0) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+	}
+
+	/**
+	 * @deprecated
+	 */
+	void indexClasspath() {
+		if (_debugIndexTime)
+			time0 = System.currentTimeMillis();
+		fClasspathProjects.clear();
+		fClasspathReferences.clear();
+		fClasspathJars.clear();
+		fBuildPathEntryCount = 0;
+
+		IJavaProject javaProject = JavaCore.create(fProject);
+		/*
+		 * If the Java nature isn't present (or something else is wrong),
+		 * don't check the build path.
+		 */
+		if (javaProject != null && javaProject.exists()) {
+			indexClasspath(javaProject);
+		}
+		// else {
+		// Logger.log(Logger.WARNING, "TaglibIndex was asked to index non-Java
+		// Project " + fProject.getName()); //$NON-NLS-1$
+		// }
+
+		if (_debugIndexTime)
+			Logger.log(Logger.INFO, "indexed " + fProject.getName() + " classpath in " + (System.currentTimeMillis() - time0) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+	}
+
+	void indexClasspath(IClasspathEntry[] entries) {
+		if (_debugIndexTime)
+			time0 = System.currentTimeMillis();
+		fClasspathProjects.clear();
+		fClasspathReferences.clear();
+		fClasspathJars.clear();
+
+		fBuildPathEntryCount = entries.length;
+		for (int i = 0; i < entries.length; i++) {
+			indexClasspath(entries[i]);
+		}
+
+		if (_debugIndexTime)
+			Logger.log(Logger.INFO, "indexed " + fProject.getName() + " classpath in " + (System.currentTimeMillis() - time0) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+	}
+
+	/**
+	 * @param entry
+	 */
+	private void indexClasspath(IClasspathEntry entry) {
+		switch (entry.getEntryKind()) {
+			case IClasspathEntry.CPE_CONTAINER : {
+				IClasspathContainer container = (IClasspathContainer) entry;
+				IClasspathEntry[] containedEntries = container.getClasspathEntries();
+				for (int i = 0; i < containedEntries.length; i++) {
+					indexClasspath(containedEntries[i]);
+				}
+			}
+				break;
+			case IClasspathEntry.CPE_LIBRARY : {
+				/*
+				 * Ignore libs in required projects that are not exported
+				 */
+				IPath libPath = entry.getPath();
+				if (!fClasspathJars.containsKey(libPath.toString())) {
+					if (libPath.toFile().exists()) {
+						updateClasspathLibrary(libPath.toString(), ITaglibIndexDelta.ADDED, entry.isExported());
+					}
+					else {
+						/*
+						 * Note: .jars on the classpath inside of the project
+						 * will have duplicate entries in the JAR references
+						 * table that will e returned to
+						 * getAvailableTaglibRecords().
+						 */
+						IResource resource = ResourcesPlugin.getWorkspace().getRoot().findMember(libPath);
+						if (resource != null && resource.isAccessible()) {
+							if (resource.getType() == IResource.FILE) {
+								if (resource.getLocation() != null) {
+									updateClasspathLibrary(resource.getLocation().toString(), ITaglibIndexDelta.ADDED, entry.isExported());
+								}
+							}
+							else if (resource.getType() == IResource.FOLDER) {
+								try {
+									resource.accept(new Indexer(), 0);
+								}
+								catch (CoreException e) {
+									Logger.logException(e);
+								}
+							}
+						}
+					}
+				}
+			}
+				break;
+			case IClasspathEntry.CPE_PROJECT : {
+				/*
+				 * We're currently ignoring whether the project exports all of
+				 * its build path
+				 */
+				IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(entry.getPath().lastSegment());
+				if (project != null) {
+					fClasspathProjects.add(project);
+				}
+			}
+				break;
+			case IClasspathEntry.CPE_SOURCE : {
+				IPath path = entry.getPath();
+				try {
+					IResource sourceFolder = ResourcesPlugin.getWorkspace().getRoot().findMember(path);
+					// could be a bad .classpath file
+					if(sourceFolder != null) {
+						sourceFolder.accept(new Indexer(), 0);
+					}
+				}
+				catch (CoreException e) {
+					Logger.logException(e);
+				}
+			}
+				break;
+			case IClasspathEntry.CPE_VARIABLE : {
+				IPath libPath = JavaCore.getResolvedVariablePath(entry.getPath());
+				if (libPath != null) {
+					File file = libPath.toFile();
+
+					// file in filesystem
+					if (file.exists() && !file.isDirectory()) {
+						updateClasspathLibrary(libPath.toString(), ITaglibRecordEvent.ADDED, entry.isExported());
+					}
+					else {
+						// workspace file
+						IFile jarFile = ResourcesPlugin.getWorkspace().getRoot().getFile(libPath);
+						if (jarFile.isAccessible() && jarFile.getType() == IResource.FILE && jarFile.getLocation() != null) {
+							String jarPathString = jarFile.getLocation().toString();
+							updateClasspathLibrary(jarPathString, ITaglibRecordEvent.ADDED, entry.isExported());
+						}
+					}
+				}
+			}
+				break;
+		}
+	}
+
+	/*
+	 * private void removeClasspathLibrary(String libraryLocation) { JarRecord
+	 * record = (JarRecord) fClasspathJars.remove(libraryLocation); if (record !=
+	 * null) { URLRecord[] records = (URLRecord[])
+	 * record.getURLRecords().toArray(new URLRecord[0]); for (int i = 0; i <
+	 * records.length; i++) {
+	 * fClasspathReferences.remove(records[i].getURI()); }
+	 * TaglibIndex.fireTaglibRecordEvent(new TaglibRecordEvent(record,
+	 * ITaglibIndexDelta.REMOVED)); } }
+	 */
+
+	/**
+	 * @deprecated
+	 */
+	private void indexClasspath(IJavaProject javaProject) {
+		if (javaProject == null)
+			return;
+
+		IProject project = javaProject.getProject();
+		if (project.equals(fProject)) {
+			try {
+				IClasspathEntry[] entries = javaProject.getResolvedClasspath(true);
+				fBuildPathEntryCount = entries.length;
+				for (int i = 0; i < entries.length; i++) {
+					indexClasspath(entries[i]);
+				}
+			}
+			catch (JavaModelException e) {
+				Logger.logException("Error searching Java Build Path + (" + fProject.getName() + ") for tag libraries", e); //$NON-NLS-1$ //$NON-NLS-2$
+			}
+		}
+	}
+	
+	void queueElementChanged(IJavaElementDelta delta) {
+		try {
+			LOCK.acquire();
+			IJavaElement element = delta.getElement();
+			if (element.getElementType() == IJavaElement.JAVA_PROJECT) {
+				IJavaElementDelta[] affectedChildren = delta.getAffectedChildren();
+				for (int i = 0; i < affectedChildren.length; i++) {
+					queueElementChanged(affectedChildren[i]);
+				}
+			}
+			if (element.getElementType() == IJavaElement.PACKAGE_FRAGMENT_ROOT && ((IPackageFragmentRoot) element).isArchive()) {
+				IPath path = element.getPath();
+				boolean fragmentisExported = true;
+				try {
+					IClasspathEntry rawClasspathEntry = ((IPackageFragmentRoot) element).getRawClasspathEntry();
+					/*
+					 * null may also be returned for deletions depending on
+					 * resource/build path notification order. If it's null,
+					 * it's been deleted and whether it's exported won't
+					 * really matter
+					 */
+					if (rawClasspathEntry != null) {
+						fragmentisExported = rawClasspathEntry.isExported();
+					}
+				}
+				catch (JavaModelException e) {
+					// IPackageFragmentRoot not part of the build path
+				}
+				String key = path.toString();
+				if ((delta.getFlags() & IJavaElementDelta.F_ADDED_TO_CLASSPATH) > 0) {
+					fPackageFragmentRootsAdded.put(key, new PackageFragmentRootDelta(path, ITaglibIndexDelta.ADDED, fragmentisExported));
+					fPackageFragmentRootsChanged.remove(key);
+					fPackageFragmentRootsRemoved.remove(key);
+					fBuildPathEntryCount++;
+				}
+				else if ((delta.getFlags() & IJavaElementDelta.F_ARCHIVE_CONTENT_CHANGED) > 0) {
+					fPackageFragmentRootsChanged.put(key, new PackageFragmentRootDelta(path, ITaglibIndexDelta.CHANGED, fragmentisExported));
+				}
+				else if ((delta.getFlags() & IJavaElementDelta.F_REMOVED_FROM_CLASSPATH) > 0) {
+					fPackageFragmentRootsAdded.remove(key);
+					fPackageFragmentRootsChanged.remove(key);
+					fPackageFragmentRootsRemoved.put(key, new PackageFragmentRootDelta(path, ITaglibIndexDelta.REMOVED, fragmentisExported));
+					fBuildPathEntryCount--;
+				}
+			}
+		}
+		finally {
+			LOCK.release();
+		}
+
+		fBuildPathJob.cancel();
+		fBuildPathJob.schedule(2000);
+	}
+
+
+	private String readTextofChild(Node node, String childName) {
+		NodeList children = node.getChildNodes();
+		for (int i = 0; i < children.getLength(); i++) {
+			Node child = children.item(i);
+			if (child.getNodeType() == Node.ELEMENT_NODE && child.getNodeName().equals(childName)) {
+				return getTextContents(child);
+			}
+		}
+		return ""; //$NON-NLS-1$
+	}
+
+	void removeJAR(IResource jar) {
+		if (_debugIndexCreation)
+			Logger.log(Logger.INFO, "removing records for JAR " + jar.getFullPath()); //$NON-NLS-1$
+		JarRecord record = (JarRecord) fJARReferences.remove(jar.getFullPath().toString());
+		if (record != null) {
+			URLRecord[] records = (URLRecord[]) record.getURLRecords().toArray(new URLRecord[0]);
+			for (int i = 0; i < records.length; i++) {
+				TaglibIndex.getInstance().addDelta(new TaglibIndexDelta(fProject, records[i], ITaglibIndexDelta.REMOVED));
+				((ArrayMap) getImplicitReferences(jar.getFullPath().toString())).remove(records[i].getURI(), records[i]);
+			}
+			if (record.has11TLD) {
+				TaglibIndex.getInstance().addDelta(new TaglibIndexDelta(fProject, record, ITaglibIndexDelta.REMOVED));
+			}
+		}
+	}
+
+	void removeTag(IResource resource) {
+		TagDirRecord record = (TagDirRecord) fTagDirReferences.get(resource.getParent().getFullPath().toString());
+		if (record != null) {
+			record.tags.remove(resource.getName());
+			TaglibIndex.getInstance().addDelta(new TaglibIndexDelta(fProject, record, ITaglibIndexDelta.CHANGED));
+		}
+	}
+
+	void removeTagDir(IResource tagdir) {
+		IPath tagdirPath = tagdir.getFullPath();
+		if (_debugIndexCreation)
+			Logger.log(Logger.INFO, "removing record for " + tagdirPath); //$NON-NLS-1$
+		ITaglibRecord record = (ITaglibRecord) fTagDirReferences.remove(tagdirPath.toString());
+		if (record != null) {
+			TaglibIndex.getInstance().addDelta(new TaglibIndexDelta(fProject, record, ITaglibIndexDelta.REMOVED));
+		}
+	}
+
+	void removeTLD(IResource tld) {
+		if (_debugIndexCreation)
+			Logger.log(Logger.INFO, "removing record for " + tld.getFullPath()); //$NON-NLS-1$
+		TLDRecord record = (TLDRecord) fTLDReferences.remove(tld.getFullPath().toString());
+		if (record != null) {
+			if (record.getURI() != null) {
+				((ArrayMap) getImplicitReferences(tld.getFullPath().toString())).remove(record.getURI(), record);
+			}
+			TaglibIndex.getInstance().addDelta(new TaglibIndexDelta(fProject, record, ITaglibIndexDelta.REMOVED));
+		}
+	}
+
+	void removeWebXML(IResource webxml) {
+		if (_debugIndexCreation)
+			Logger.log(Logger.INFO, "removing records for " + webxml.getFullPath()); //$NON-NLS-1$
+		WebXMLRecord record = (WebXMLRecord) fWebXMLReferences.remove(webxml.getFullPath().toString());
+		if (record != null) {
+			TLDRecord[] records = (TLDRecord[]) record.getTLDRecords().toArray(new TLDRecord[0]);
+			for (int i = 0; i < records.length; i++) {
+				if (_debugIndexCreation)
+					Logger.log(Logger.INFO, "removed record for " + records[i].getURI() + "@" + records[i].path); //$NON-NLS-1$ //$NON-NLS-2$
+				((ArrayMap) getImplicitReferences(webxml.getFullPath().toString())).remove(records[i].getURI(), records[i]);
+				TaglibIndex.getInstance().addDelta(new TaglibIndexDelta(fProject, records[i], ITaglibIndexDelta.REMOVED));
+			}
+		}
+	}
+	
+	private boolean requestedRefresh() {
+		boolean requested = false;
+		String[] commandLineArgs = Platform.getCommandLineArgs();
+		for (int i = 0; i < commandLineArgs.length; i++) {
+			requested = requested || "-refresh".equals(commandLineArgs[i]); //$NON-NLS-1$ 
+		}
+		return requested;
+	}
+
+	/**
+	 * @param basePath
+	 * @param reference
+	 * @return
+	 */
+	ITaglibRecord resolve(String basePath, String reference) {
+		ensureUpTodate();
+
+		ITaglibRecord record = null;
+		String path = null;
+		try {
+			float jspVersion = DeploymentDescriptorPropertyCache.getInstance().getJSPVersion(new Path(basePath));
+
+			/**
+			 * http://bugs.eclipse.org/196177 - Support resolution in flexible
+			 * projects
+			 */
+			IPath resourcePath = FacetModuleCoreSupport.resolve(new Path(basePath), reference);
+			if (resourcePath.segmentCount() > 1) {
+				String fileExtension = resourcePath.getFileExtension();
+				if (fileExtension != null && fileExtension.toLowerCase(Locale.US).equals("tld")) { //$NON-NLS-1$ 
+					IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(resourcePath);
+					if (file.isAccessible()) {
+						path = resourcePath.toString();
+					}
+				}
+				else if (fileExtension != null && fileExtension.toLowerCase(Locale.US).equals("jar")) { //$NON-NLS-1$ 
+					IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(resourcePath);
+					if (file.isAccessible()) {
+						path = resourcePath.toString();
+					}
+				}
+				else {
+					IFolder folder = ResourcesPlugin.getWorkspace().getRoot().getFolder(resourcePath);
+					if (folder.isAccessible()) {
+						path = resourcePath.toString();
+					}
+				}
+			}
+
+			LOCK.acquire();
+
+			String localRoot = getLocalRoot(basePath);
+			/**
+			 * Workaround for problem in URIHelper; uris starting with '/' are
+			 * returned as-is.
+			 */
+			if (path == null) {
+				if (reference.startsWith("/")) { //$NON-NLS-1$
+					path = localRoot + reference;
+				}
+				else {
+					path = URIHelper.normalize(reference, basePath, localRoot);
+				}
+			}
+
+			IPath localWebXML = new Path(localRoot).append("/WEB-INF/web.xml"); //$NON-NLS-1$ 
+			WebXMLRecord webxmlRecord = (WebXMLRecord) fWebXMLReferences.get(localWebXML.toString());
+			if (webxmlRecord != null) {
+				for (int i = 0; i < webxmlRecord.tldRecords.size(); i++) {
+					ITaglibRecord record2 = (ITaglibRecord) webxmlRecord.tldRecords.get(i);
+					ITaglibDescriptor descriptor = record2.getDescriptor();
+					if (reference.equals(descriptor.getURI())) {
+						record = record2;
+					}
+				}
+			}
+
+			if (record == null) {
+				// order dictated by JSP spec 2.0 section 7.2.3
+				record = (ITaglibRecord) fJARReferences.get(path);
+
+				// only if 1.1 TLD was found
+				if (jspVersion < 1.1 || (record instanceof JarRecord && !((JarRecord) record).has11TLD)) {
+					record = null;
+				}
+			}
+			
+			if (record == null) {
+				record = (ITaglibRecord) fTLDReferences.get(path);
+			}
+			if (record == null && jspVersion >= 1.2) {
+				Object[] records = (Object[]) getImplicitReferences(basePath).get(reference);
+				if (records != null && records.length > 0) {
+					if (records.length > 1)
+						records = fTaglibSorter.sort(records);
+					record =  (ITaglibRecord) records[records.length - 1];
+				}
+			}
+
+
+			if (record == null && jspVersion >= 2.0) {
+				record = (ITaglibRecord) fTagDirReferences.get(path);
+			}
+
+			if (record == null && jspVersion >= 1.2) {
+				record = (ITaglibRecord) fClasspathReferences.get(reference);
+			}
+			if (record == null && jspVersion >= 1.2) {
+				Map buildPathReferences = new HashMap();
+				List projectsProcessed = new ArrayList(fClasspathProjects.size() + 1);
+				projectsProcessed.add(fProject);
+				addBuildPathReferences(buildPathReferences, projectsProcessed, false);
+				record = (ITaglibRecord) buildPathReferences.get(reference);
+			}
+			
+			// Check the XML Catalog
+			if (record == null) {
+				ICatalog catalog = XMLCorePlugin.getDefault().getDefaultXMLCatalog();
+				if (catalog != null) {
+					String resolvedString = null;
+					try {
+						// Check as system reference first
+						resolvedString = catalog.resolveSystem(reference);
+						// Check as URI
+						if (resolvedString == null || resolvedString.trim().length() == 0) {
+							resolvedString = catalog.resolveURI(reference);
+						}
+						// Check as public ID
+						if (resolvedString == null || resolvedString.trim().length() == 0) {
+							resolvedString = catalog.resolvePublic(reference, basePath);
+						}
+					}
+					catch (Exception e) {
+						Logger.logException(e);
+					}
+					if (resolvedString != null && resolvedString.trim().length() > 0) {
+						record = createCatalogRecord(reference, resolvedString);
+					}
+				}
+			}
+			
+			/*
+			 * If no records were found and no local-root applies, check ALL
+			 * of the web.xml files as a fallback
+			 */
+			if (record == null && fProject.getFullPath().toString().equals(localRoot)) {
+				WebXMLRecord[] webxmls = (WebXMLRecord[]) fWebXMLReferences.values().toArray(new WebXMLRecord[0]);
+				for (int i = 0; i < webxmls.length; i++) {
+					if (record != null)
+						continue;
+					Object[] records = (Object[]) getImplicitReferences(webxmls[i].path.toString()).get(reference);
+					if (records != null && records.length > 0) {
+						if (records.length > 1)
+							records = fTaglibSorter.sort(records);
+						record =  (ITaglibRecord) records[records.length - 1];
+					}
+				}
+			}
+			/*
+			 * If no records were found, check the implicit references on the project itself as a fallback
+			 */
+			if (record == null && jspVersion >= 1.2) {
+				Object[] records = (Object[]) getImplicitReferences(fProject.getFullPath().toString()).get(reference);
+				if (records != null && records.length > 0) {
+					if (records.length > 1)
+						records = fTaglibSorter.sort(records);
+					record =  (ITaglibRecord) records[records.length - 1];
+				}
+			}
+
+		}
+		finally {
+			LOCK.release();
+		}
+
+		return record;
+	}
+
+	/**
+	 * Restores any saved reference tables
+	 */
+	private void restoreReferences() {
+		final boolean notifyOnRestoration = true;
+		if (TaglibIndex.ENABLED) {
+			// resources first
+			index();
+			// now build path
+
+			// ================ test reload time ========================
+			boolean restored = false;
+			File savedState = new File(fSaveStateFilename);
+			if (savedState.exists() && !requestedRefresh()) {
+				Reader reader = null;
+				try {
+					time0 = System.currentTimeMillis();
+					reader = new InputStreamReader(new BufferedInputStream(new FileInputStream(savedState)), "UTF-16"); //$NON-NLS-1$ 
+					// use a string buffer temporarily to reduce string
+					// creation
+					StringBuffer buffer = new StringBuffer();
+					char array[] = new char[2048];
+					int charsRead = 0;
+					while ((charsRead = reader.read(array)) != -1) {
+						if (charsRead > 0) {
+							buffer.append(array, 0, charsRead);
+						}
+					}
+
+					IDocument doc = new org.eclipse.jface.text.Document();
+					doc.set(buffer.toString());
+					int lines = doc.getNumberOfLines();
+					if (lines > 0) {
+						IRegion line = doc.getLineInformation(0);
+						String lineText = doc.get(line.getOffset(), line.getLength());
+						JarRecord libraryRecord = null;
+						if (SAVE_FORMAT_VERSION.equals(lineText.trim())) {
+							IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
+
+							for (int i = 1; i < lines && !fBuildPathIsDirty; i++) {
+								line = doc.getLineInformation(i);
+								lineText = doc.get(line.getOffset(), line.getLength());
+								StringTokenizer toker = new StringTokenizer(lineText, "|"); //$NON-NLS-1$
+								if (toker.hasMoreTokens()) {
+									String tokenType = toker.nextToken();
+									if ("JAR".equalsIgnoreCase(tokenType)) { //$NON-NLS-1$ //$NON-NLS-2$
+										boolean has11TLD = Boolean.valueOf(toker.nextToken()).booleanValue();
+										boolean exported = Boolean.valueOf(toker.nextToken()).booleanValue();
+										// make the rest the libraryLocation
+										String libraryLocation = toker.nextToken();
+										while (toker.hasMoreTokens()) {
+											libraryLocation = libraryLocation + "|" + toker.nextToken(); //$NON-NLS-1$ //$NON-NLS-2$
+										}
+										libraryLocation = libraryLocation.trim();
+										if (libraryRecord != null && notifyOnRestoration) {
+											TaglibIndex.getInstance().addDelta(new TaglibIndexDelta(fProject, libraryRecord, ITaglibIndexDelta.ADDED));
+										}
+										// Create a new JarRecord
+										libraryRecord = createJARRecord(libraryLocation);
+										libraryRecord.has11TLD = has11TLD;
+										libraryRecord.isExported = exported;
+
+										// Add a URLRecord for the 1.1 TLD
+										if (has11TLD) {
+											InputStream contents = JarUtilities.getInputStream(libraryLocation, JarUtilities.JSP11_TAGLIB);
+											if (contents != null) {
+												TaglibInfo info = extractInfo(libraryLocation, contents);
+
+												if (info != null && info.uri != null && info.uri.length() > 0) {
+													URLRecord urlRecord = new URLRecord();
+													urlRecord.info = info;
+													urlRecord.isExported = exported;
+													urlRecord.baseLocation = libraryLocation;
+													try {
+														urlRecord.url = new URL("jar:file:" + libraryLocation + "!/" + JarUtilities.JSP11_TAGLIB); //$NON-NLS-1$ //$NON-NLS-2$
+														libraryRecord.urlRecords.add(urlRecord);
+														fClasspathReferences.put(urlRecord.getURI(), urlRecord);
+														if (_debugIndexCreation)
+															Logger.log(Logger.INFO, "created record for " + urlRecord.getURI() + "@" + urlRecord.getURL()); //$NON-NLS-1$ //$NON-NLS-2$
+													}
+													catch (MalformedURLException e) {
+														/*
+														 * don't record this
+														 * URI
+														 */
+														Logger.logException(e);
+													}
+												}
+												try {
+													contents.close();
+												}
+												catch (IOException e) {
+													Logger.log(Logger.ERROR_DEBUG, null, e);
+												}
+											}
+										}
+
+										fClasspathJars.put(libraryLocation, libraryRecord);
+									}
+									else if ("URL".equalsIgnoreCase(tokenType) && libraryRecord != null) { //$NON-NLS-1$
+										// relies on a previously declared JAR record
+										boolean exported = Boolean.valueOf(toker.nextToken()).booleanValue();
+										// make the rest the URL
+										String urlString = toker.nextToken();
+										while (toker.hasMoreTokens()) {
+											urlString = urlString + "|" + toker.nextToken(); //$NON-NLS-1$ //$NON-NLS-2$
+										}
+										urlString = urlString.trim();
+										// Append a URLrecord
+										URLRecord urlRecord = new URLRecord();
+										urlRecord.url = new URL(urlString);
+										urlRecord.isExported = exported;
+										urlRecord.baseLocation = libraryRecord.location.toString();
+
+										InputStream tldStream = JarUtilities.getInputStream(urlRecord.url);
+										if(tldStream != null) {
+											TaglibInfo info = extractInfo(urlRecord.url.toString(), tldStream);
+											if (info != null) {
+												urlRecord.info = info;
+											}
+											libraryRecord.urlRecords.add(urlRecord);
+											try {
+												tldStream.close();
+											}
+											catch (IOException e) {
+												Logger.log(Logger.ERROR_DEBUG, null, e);
+											}
+											if (urlRecord.getURI() != null && urlRecord.getURI().length() > 0) {
+												fClasspathReferences.put(urlRecord.getURI(), urlRecord);
+											}
+										}
+									}
+									else if (BUILDPATH_PROJECT.equalsIgnoreCase(tokenType)) {
+										String projectName = toker.nextToken();
+										if (Path.ROOT.isValidSegment(projectName)) {
+											IProject project = workspaceRoot.getProject(projectName);
+											/* do not check if "open" here */
+											if (project != null) {
+												fClasspathProjects.add(project);
+											}
+										}
+									}
+									// last since they occur once
+									else if (BUILDPATH_DIRTY.equalsIgnoreCase(tokenType)) {
+										fBuildPathIsDirty = Boolean.valueOf(toker.nextToken()).booleanValue();
+									}
+									else if (BUILDPATH_ENTRIES.equalsIgnoreCase(tokenType)) {
+										fBuildPathEntryCount = Integer.valueOf(toker.nextToken()).intValue();
+									}
+								}
+								if (libraryRecord != null && notifyOnRestoration) {
+									TaglibIndex.getInstance().addDelta(new TaglibIndexDelta(fProject, libraryRecord, ITaglibIndexDelta.ADDED));
+								}
+							}
+							restored = true;
+						}
+						else {
+							Logger.log(Logger.INFO_DEBUG, "Tag Library Index: different cache format found, was \"" + lineText + "\", supports \"" + SAVE_FORMAT_VERSION + "\", reindexing build path"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+						}
+					}
+					if (_debugIndexTime)
+						Logger.log(Logger.INFO, "time spent reloading " + fProject.getName() + " build path: " + (System.currentTimeMillis() - time0)); //$NON-NLS-1$ //$NON-NLS-2$
+				}
+				catch (Exception e) {
+					restored = false;
+					if (_debugIndexTime)
+						Logger.log(Logger.INFO, "failure reloading " + fProject.getName() + " build path index", e); //$NON-NLS-1$ //$NON-NLS-2$
+				}
+				finally {
+					if (reader != null) {
+						try {
+							reader.close();
+						}
+						catch (IOException e) {
+							Logger.log(Logger.ERROR_DEBUG, null, e);
+						}
+					}
+				}
+			}
+
+			// ================ test reload time (end) ==================
+
+
+			if (!restored) {
+				setBuildPathIsDirty();
+			}
+		}
+	}
+
+	/**
+	 * Saves any storable references to disk. This is only called when the
+	 * description is being cleared and not after every update.
+	 */
+	void saveReferences() {
+		// the build path information is out of date, remember that
+		time0 = System.currentTimeMillis();
+		Writer writer = null;
+
+		/**
+		 * <pre>
+		 *                     		 1.1.0
+		 *                     		 Save classpath information (| is field delimiter)
+		 *                     		 Jars are saved as &quot;JAR:&quot;+ has11TLD + jar path 
+		 *                     		 URLRecords as &quot;URL:&quot;+URL
+		 * </pre>
+		 */
+		try {
+			writer = new OutputStreamWriter(new FileOutputStream(fSaveStateFilename), "UTF-16"); //$NON-NLS-1$
+			writer.write(SAVE_FORMAT_VERSION);
+			writer.write('\n'); //$NON-NLS-1$
+			writer.write(BUILDPATH_DIRTY + "|" + fBuildPathIsDirty); //$NON-NLS-1$
+			writer.write('\n'); //$NON-NLS-1$
+			writer.write(BUILDPATH_ENTRIES + "|" + fBuildPathEntryCount); //$NON-NLS-1$
+			writer.write('\n'); //$NON-NLS-1$
+
+			IProject[] projects = (IProject[]) fClasspathProjects.toArray(new IProject[0]);
+			for (int i = 0; i < projects.length; i++) {
+				writer.write(BUILDPATH_PROJECT);
+				writer.write("|"); //$NON-NLS-1$
+				writer.write(projects[i].getName());
+				writer.write('\n'); //$NON-NLS-1$
+			}
+
+			Enumeration jars = fClasspathJars.keys();
+			while (jars.hasMoreElements()) {
+				String jarPath = jars.nextElement().toString();
+				JarRecord jarRecord = (JarRecord) fClasspathJars.get(jarPath);
+				writer.write("JAR|"); //$NON-NLS-1$
+				writer.write(Boolean.toString(jarRecord.has11TLD));
+				writer.write('|'); //$NON-NLS-1$
+				writer.write(Boolean.toString(jarRecord.isExported));
+				writer.write('|'); //$NON-NLS-1$
+				writer.write(jarPath);
+				writer.write('\n'); //$NON-NLS-1$
+				Iterator i = jarRecord.urlRecords.iterator();
+				while (i.hasNext()) {
+					URLRecord urlRecord = (URLRecord) i.next();
+					writer.write("URL|"); //$NON-NLS-1$
+					writer.write(String.valueOf(urlRecord.isExported));
+					writer.write("|"); //$NON-NLS-1$
+					writer.write(urlRecord.getURL().toExternalForm());
+					writer.write('\n'); //$NON-NLS-1$
+				}
+			}
+		}
+		catch (IOException e) {
+			Logger.log(Logger.ERROR_DEBUG, null, e);
+		}
+		finally {
+			try {
+				if (writer != null) {
+					writer.close();
+				}
+			}
+			catch (Exception e) {
+				Logger.log(Logger.ERROR_DEBUG, null, e);
+			}
+		}
+
+		if (_debugIndexTime)
+			Logger.log(Logger.INFO, "time spent saving index for " + fProject.getName() + ": " + (System.currentTimeMillis() - time0)); //$NON-NLS-1$
+	}
+
+	void setBuildPathIsDirty() {
+		fBuildPathIsDirty = true;
+		if (_debugIndexTime)
+			Logger.log(Logger.INFO, "marking build path information for " + fProject.getName() + " as dirty"); //$NON-NLS-1$
+	}
+
+	void updateClasspathLibrary(String libraryLocation, int deltaKind, boolean isExported) {
+		JarRecord libraryRecord = null;
+		if (deltaKind == ITaglibIndexDelta.REMOVED || deltaKind == ITaglibIndexDelta.CHANGED) {
+			libraryRecord = (JarRecord) fClasspathJars.remove(libraryLocation);
+			synchronized (fJarRecords) {
+				fJarRecords.remove(libraryLocation);
+			}
+			if (libraryRecord != null) {
+				IURLRecord[] urlRecords = (IURLRecord[]) libraryRecord.urlRecords.toArray(new IURLRecord[0]);
+				for (int i = 0; i < urlRecords.length; i++) {
+					ITaglibRecord record = (ITaglibRecord) fClasspathReferences.remove(urlRecords[i].getURI());
+					if (record != null) {
+						TaglibIndex.getInstance().addDelta(new TaglibIndexDelta(fProject, record, ITaglibIndexDelta.REMOVED));
+					}
+				}
+			}
+		}
+		if (deltaKind == ITaglibIndexDelta.ADDED || deltaKind == ITaglibIndexDelta.CHANGED) {
+			// XXX: runs on folders as well?!
+			libraryRecord = createJARRecord(libraryLocation);
+			synchronized (libraryRecord) {
+				if (libraryRecord.isConsistent) {
+					// Library loaded by another Project Description, initialize our references from the existing
+					fClasspathJars.put(libraryLocation, libraryRecord);
+					Iterator records = libraryRecord.urlRecords.iterator();
+					while (records.hasNext()) {
+						URLRecord record = (URLRecord)records.next();
+						int urlDeltaKind = ITaglibIndexDelta.ADDED;
+						if (fClasspathReferences.containsKey(record.getURI())) {
+							urlDeltaKind = ITaglibIndexDelta.CHANGED;
+						}
+						fClasspathReferences.put(record.getURI(), record);
+						TaglibIndex.getInstance().addDelta(new TaglibIndexDelta(fProject, record, urlDeltaKind));
+						fClasspathReferences.put(record.info.uri, record);
+					}
+					return;
+				}
+				libraryRecord.isExported = isExported;
+				fClasspathJars.put(libraryLocation, libraryRecord);
+	
+				ZipFile jarfile = null;
+				try {
+					jarfile = new ZipFile(libraryLocation);
+					Enumeration entries = jarfile.entries();
+					while (entries.hasMoreElements()) {
+						ZipEntry z = (ZipEntry) entries.nextElement();
+						if (!z.isDirectory()) {
+							if (isTLD(z.getName())) {
+								if (z.getName().equals(JarUtilities.JSP11_TAGLIB)) {
+									libraryRecord.has11TLD = true;
+								}
+								InputStream contents = getCachedInputStream(jarfile, z);
+								if (contents != null) {
+									TaglibInfo info = extractInfo(libraryLocation, contents);
+	
+									if (info != null && info.uri != null && info.uri.length() > 0) {
+										URLRecord urlRecord = new URLRecord();
+										urlRecord.info = info;
+										urlRecord.baseLocation = libraryLocation;
+										try {
+											urlRecord.isExported = isExported;
+											urlRecord.url = new URL("jar:file:" + libraryLocation + "!/" + z.getName()); //$NON-NLS-1$ //$NON-NLS-2$
+											libraryRecord.urlRecords.add(urlRecord);
+											int urlDeltaKind = ITaglibIndexDelta.ADDED;
+											if (fClasspathReferences.containsKey(urlRecord.getURI())) {
+												// TODO: not minimized enough
+												urlDeltaKind = ITaglibIndexDelta.CHANGED;
+											}
+											fClasspathReferences.put(urlRecord.getURI(), urlRecord);
+											TaglibIndex.getInstance().addDelta(new TaglibIndexDelta(fProject, urlRecord, urlDeltaKind));
+											fClasspathReferences.put(info.uri, urlRecord);
+											if (_debugIndexCreation)
+												Logger.log(Logger.INFO, "created record for " + urlRecord.getURI() + "@" + urlRecord.getURL()); //$NON-NLS-1$ //$NON-NLS-2$
+										}
+										catch (MalformedURLException e) {
+											// don't record this URI
+											Logger.logException(e);
+										}
+									}
+									try {
+										contents.close();
+									}
+									catch (IOException e) {
+										Logger.log(Logger.ERROR_DEBUG, null, e);
+									}
+								}
+							}
+						}
+					}
+				}
+				catch (ZipException zExc) {
+					Logger.log(Logger.WARNING, "Taglib Index ZipException: " + libraryLocation + " " + zExc.getMessage()); //$NON-NLS-1$ //$NON-NLS-2$
+				}
+				catch (IOException ioExc) {
+					Logger.log(Logger.WARNING, "Taglib Index IOException: " + libraryLocation + " " + ioExc.getMessage()); //$NON-NLS-1$ //$NON-NLS-2$
+				}
+				finally {
+					closeJarFile(jarfile);
+				}
+				libraryRecord.isConsistent = true;
+			}
+		}
+		if (libraryRecord != null) {
+			TaglibIndex.getInstance().addDelta(new TaglibIndexDelta(fProject, libraryRecord, deltaKind));
+		}
+	}
+
+	private boolean isTLD(String name) {
+		if (name == null)
+			return false;
+
+		final int length = name.length();
+
+		if (length < 4)
+			return false;
+		if (name.charAt(length - 4) != '.')
+			return false;
+
+		for (int i = length - 3, j = 0; i < length; i++, j++) {
+			final char c = name.charAt(i);
+			if (c != TLD[2*j] && c != TLD[2*j + 1])
+				return false;
+		}
+		return true;
+	}
+
+	void updateJAR(IResource jar, int deltaKind) {
+		if (_debugIndexCreation)
+			Logger.log(Logger.INFO, "creating records for JAR " + jar.getFullPath()); //$NON-NLS-1$
+
+		String jarLocationString = null;
+		if (jar.getLocation() != null)
+			jarLocationString = jar.getLocation().toString();
+		else
+			jarLocationString = jar.getLocationURI().toString();
+		JarRecord jarRecord = createJARRecord(jar);
+		fJARReferences.put(jar.getFullPath().toString(), jarRecord);
+		ZipInputStream zip = getZipInputStream(jar);
+		if(zip != null) {
+			try {
+				ZipEntry entry;
+				while ((entry = zip.getNextEntry()) != null) {
+					if (isTLD(entry.getName())) { //$NON-NLS-1$
+						if (entry.getName().equals(JarUtilities.JSP11_TAGLIB)) {
+							jarRecord.has11TLD = true;
+						}
+						InputStream contents = copyZipEntry(zip);
+						if (contents != null) {
+							TaglibInfo info = extractInfo(jarLocationString, contents);
+		
+							if (info != null && info.uri != null && info.uri.length() > 0) {
+								URLRecord record = new URLRecord();
+								record.info = info;
+								record.baseLocation = jarLocationString;
+								try {
+									record.url = new URL("jar:file:" + jarLocationString + "!/" + entry.getName()); //$NON-NLS-1$ //$NON-NLS-2$
+									jarRecord.urlRecords.add(record);
+		
+									int taglibDeltaKind = ITaglibIndexDelta.ADDED;
+									Hashtable table = getImplicitReferences(jar.getFullPath().toString());
+									if (table != null && table.get(record.getURI()) != null) {
+										taglibDeltaKind = ITaglibIndexDelta.CHANGED;
+									}
+		
+									getImplicitReferences(jar.getFullPath().toString()).put(info.uri, record);
+									TaglibIndex.getInstance().addDelta(new TaglibIndexDelta(fProject, record, taglibDeltaKind));
+									if (_debugIndexCreation)
+										Logger.log(Logger.INFO, "created record for " + record.getURI() + "@" + record.getURL()); //$NON-NLS-1$ //$NON-NLS-2$
+								}
+								catch (MalformedURLException e) {
+									// don't record this URI
+									Logger.logException(e);
+								}
+							}
+							try {
+								contents.close();
+							}
+							catch (IOException e) {
+								Logger.log(Logger.ERROR_DEBUG, null, e);
+							}
+						}
+						else {
+							Logger.log(Logger.ERROR_DEBUG, getClass().getName() + "could not read resource " + jar.getFullPath()); //$NON-NLS-1$
+						}
+					}
+				}
+			} catch (IOException e) { }
+			finally {
+				closeInputStream(zip);
+			}
+		}
+		if (jarRecord.has11TLD) {
+			TaglibIndex.getInstance().addDelta(new TaglibIndexDelta(fProject, jarRecord, deltaKind));
+		}
+	}
+
+	private InputStream copyZipEntry(ZipInputStream stream) {
+		ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+		InputStream copy = null;
+
+		if (stream != null) {
+			int c;
+			// array dim restriction?
+			byte bytes[] = new byte[2048];
+			try {
+				while ((c = stream.read(bytes)) >= 0) {
+					buffer.write(bytes, 0, c);
+				}
+				copy = new ByteArrayInputStream(buffer.toByteArray());
+				closeZipEntry(stream);
+			}
+			catch (IOException ioe) {
+				// no cleanup can be done
+			}
+		}
+		return copy;
+	}
+
+	private ZipInputStream getZipInputStream(IResource jar) {
+		if (jar == null || jar.getType() != IResource.FILE || !jar.isAccessible())
+			return null;
+
+		try {
+			InputStream zipStream = ((IFile) jar).getContents();
+			return new ZipInputStream(zipStream);
+		} catch (CoreException e) { }
+		return null;
+	}
+
+	private void closeInputStream(InputStream stream) {
+		if (stream != null) {
+			try {
+				stream.close();
+			} catch (IOException e) { }
+		}
+			
+	}
+
+	private void closeZipEntry(ZipInputStream zis) {
+		if (zis != null) {
+			try {
+				zis.closeEntry();
+			} catch (IOException e) {
+				System.out.println("Error");
+			}
+		}
+			
+	}
+
+	void updateTag(IResource resource, int kind) {
+		TagDirRecord record = (TagDirRecord) fTagDirReferences.get(resource.getParent().getFullPath().toString());
+		if (record == null) {
+			record = createTagdirRecord((IFolder) resource.getParent());
+			fTagDirReferences.put(resource.getParent().getFullPath().toString(), record);
+			TaglibIndex.getInstance().addDelta(new TaglibIndexDelta(fProject, record, ITaglibIndexDelta.ADDED));
+		}
+		else {
+			if (!record.tags.contains(resource.getName())) {
+				record.tags.add(resource.getName());
+			}
+			TaglibIndex.getInstance().addDelta(new TaglibIndexDelta(fProject, record, ITaglibIndexDelta.CHANGED));
+		}
+	}
+
+	void updateTagDir(IResource tagdirResource, int deltaKind) {
+		/**
+		 * 8.4.1: tag files are loose files under /WEB-INF/tags
+		 */
+		if ((tagdirResource.getType() & IResource.FOLDER) != 0) {
+			if (_debugIndexCreation)
+				Logger.log(Logger.INFO, "creating record for directory " + tagdirResource.getFullPath()); //$NON-NLS-1$
+			TagDirRecord record = (TagDirRecord) fTagDirReferences.get(tagdirResource.getFullPath().toString());
+			if (record == null) {
+				record = createTagdirRecord((IFolder) tagdirResource);
+				fTagDirReferences.put(tagdirResource.getFullPath().toString(), record);
+				TaglibIndex.getInstance().addDelta(new TaglibIndexDelta(fProject, record, deltaKind));
+			}
+			else {
+
+			}
+		}
+		/**
+		 * 8.4.1: tag files can also be packaged in the /META-INF/tags folder
+		 * of a jar in /WEB-INF/lib/ (8.4.2: but must be mentioned in a .tld)
+		 */
+		else {
+			// these tags are merely surfaced when the TLD is modelled
+		}
+	}
+
+	/**
+	 * 
+	 * @param tld
+	 * @param deltaKind
+	 */
+	void updateTLD(IResource tld, int deltaKind) {
+		if (_debugIndexCreation)
+			Logger.log(Logger.INFO, "creating record for " + tld.getFullPath()); //$NON-NLS-1$
+		TLDRecord record = createTLDRecord(tld);
+		fTLDReferences.put(tld.getFullPath().toString(), record);
+		if (record.getURI() != null && record.getURI().length() > 0) {
+			getImplicitReferences(tld.getFullPath().toString()).put(record.getURI(), record);
+		}
+		TaglibIndex.getInstance().addDelta(new TaglibIndexDelta(fProject, record, deltaKind));
+	}
+
+	void updateWebXML(IResource webxml, int deltaKind) {
+		if (webxml.getType() != IResource.FILE)
+			return;
+		InputStream webxmlContents = null;
+		Document document = null;
+		try {
+			webxmlContents = ((IFile) webxml).getContents(false);
+			DocumentProvider provider = new DocumentProvider();
+			provider.setInputStream(webxmlContents);
+			provider.setValidating(false);
+			provider.setRootElementName("web-app"); //$NON-NLS-1$
+			provider.setBaseReference(webxml.getParent().getFullPath().toString());
+			document = provider.getDocument(false);
+		}
+		catch (CoreException e) {
+			Logger.log(Logger.ERROR_DEBUG, "", e); //$NON-NLS-1$
+		}
+		finally {
+			if (webxmlContents != null)
+				try {
+					webxmlContents.close();
+				}
+				catch (IOException e1) {
+					// ignore
+					Logger.log(Logger.ERROR_DEBUG, null, e1);
+				}
+		}
+		if (document == null)
+			return;
+		if (_debugIndexCreation)
+			Logger.log(Logger.INFO, "creating records for " + webxml.getFullPath()); //$NON-NLS-1$
+
+		WebXMLRecord webxmlRecord = new WebXMLRecord();
+		webxmlRecord.path = webxml.getFullPath();
+		fWebXMLReferences.put(webxmlRecord.getWebXML().toString(), webxmlRecord);
+		NodeList taglibs = document.getElementsByTagName(JSP12TLDNames.TAGLIB);
+		for (int iTaglib = 0; iTaglib < taglibs.getLength(); iTaglib++) {
+			String taglibUri = readTextofChild(taglibs.item(iTaglib), "taglib-uri").trim(); //$NON-NLS-1$
+			// specified location is relative to root of the web-app
+			String taglibLocation = readTextofChild(taglibs.item(iTaglib), "taglib-location").trim(); //$NON-NLS-1$
+			IPath path = null;
+			if (taglibLocation.startsWith("/")) { //$NON-NLS-1$
+				path = FacetModuleCoreSupport.resolve(new Path(webxml.getFullPath().toString()), taglibLocation);
+			}
+			else {
+				path = new Path(URIHelper.normalize(taglibLocation, webxml.getFullPath().toString(), getLocalRoot(webxml.getFullPath().toString())));
+			}
+			if (path.segmentCount() > 1) {
+				IFile resource = ResourcesPlugin.getWorkspace().getRoot().getFile(path);
+				if (resource.isAccessible()) {
+					ITaglibRecord record = null;
+					/*
+					 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=125960
+					 * 
+					 * Also support mappings to .jar files
+					 */
+					if ("jar".equalsIgnoreCase(resource.getFileExtension())) { //$NON-NLS-1$
+						JarRecord jarRecord = createJARRecord(resource);
+						String[] entries = JarUtilities.getEntryNames(resource);
+						for (int jEntry = 0; jEntry < entries.length; jEntry++) {
+							if (entries[jEntry].endsWith(".tld")) { //$NON-NLS-1$
+								if (entries[jEntry].equals(JarUtilities.JSP11_TAGLIB)) {
+									jarRecord.has11TLD = true;
+									InputStream contents = JarUtilities.getInputStream(resource, entries[jEntry]);
+									if (contents != null) {
+										TaglibInfo info = extractInfo(resource.getFullPath().toString(), contents);
+										jarRecord.info = info;
+										try {
+											contents.close();
+										}
+										catch (IOException e) {
+											Logger.log(Logger.ERROR_DEBUG, null, e);
+										}
+									}
+								}
+							}
+						}
+						record = jarRecord;
+						// the stored URI should reflect the web.xml's value
+						if (jarRecord.info == null) {
+							jarRecord.info = new TaglibInfo();
+						}
+						jarRecord.info.uri = taglibUri;
+						jarRecord.isMappedInWebXML = true;
+						if (_debugIndexCreation)
+							Logger.log(Logger.INFO, "created web.xml record for " + taglibUri + "@" + jarRecord.getLocation()); //$NON-NLS-1$ //$NON-NLS-2$
+					}
+					else {
+						TLDRecord tldRecord = createTLDRecord(resource);
+						record = tldRecord;
+						// the stored URI should reflect the web.xml's value
+						tldRecord.info.uri = taglibUri;
+						if (_debugIndexCreation)
+							Logger.log(Logger.INFO, "created web.xml record for " + taglibUri + "@" + tldRecord.getPath()); //$NON-NLS-1$ //$NON-NLS-2$
+					}
+					if (record != null) {
+						webxmlRecord.tldRecords.add(record);
+						getImplicitReferences(webxml.getFullPath().toString()).put(taglibUri, record);
+						TaglibIndex.getInstance().addDelta(new TaglibIndexDelta(fProject, record, deltaKind));
+					}
+				}
+			}
+		}
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/taglib/TaglibIndex.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/taglib/TaglibIndex.java
new file mode 100644
index 0000000..29b280b
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/taglib/TaglibIndex.java
@@ -0,0 +1,1023 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 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
+ *     
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.taglib;
+
+import java.io.File;
+import java.lang.ref.Reference;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.zip.CRC32;
+
+import org.eclipse.core.filebuffers.FileBuffers;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceChangeEvent;
+import org.eclipse.core.resources.IResourceChangeListener;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.jobs.ILock;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jdt.core.ElementChangedEvent;
+import org.eclipse.jdt.core.IElementChangedListener;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IJavaElementDelta;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jst.jsp.core.internal.JSPCorePlugin;
+import org.eclipse.jst.jsp.core.internal.Logger;
+import org.eclipse.jst.jsp.core.internal.contentmodel.tld.TLDCMDocumentManager;
+import org.eclipse.wst.sse.core.internal.util.AbstractMemoryListener;
+import org.osgi.framework.Bundle;
+import org.osgi.service.event.Event;
+
+/**
+ * A non-extendable index manager for taglibs similar to the previous J2EE
+ * ITaglibRegistry but lacking any ties to project natures. Each record
+ * returned from the index represents a single tag library descriptor.
+ * 
+ * Indexing is only persisted between sessions for entries on the Java Build
+ * Path. New ADD events will be sent to ITaglibIndexListeners during each
+ * workbench session for both cached and newly found records. REMOVE events
+ * are not fired on workbench shutdown. The record's contents should be
+ * examined for any further information.
+ * 
+ * @since 1.0
+ */
+public final class TaglibIndex {
+	class ClasspathChangeListener implements IElementChangedListener {
+		List projectsIndexed = new ArrayList(1);
+
+		public void elementChanged(ElementChangedEvent event) {
+			if (!isIndexAvailable())
+				return;
+			try {
+				LOCK.acquire();
+				if (_debugEvents) {
+					Logger.log(Logger.INFO, "TaglibIndex responding to:" + event); //$NON-NLS-1$
+				}
+				projectsIndexed.clear();
+				elementChanged(event.getDelta(), true);
+				fireCurrentDelta(event);
+			}
+			finally {
+				LOCK.release();
+			}
+		}
+
+		private void elementChanged(IJavaElementDelta delta, boolean forceUpdate) {
+			if (frameworkIsShuttingDown())
+				return;
+
+			IJavaElement element = delta.getElement();
+			if (element.getElementType() == IJavaElement.JAVA_MODEL) {
+				IJavaElementDelta[] changed = delta.getAffectedChildren();
+				for (int i = 0; i < changed.length; i++) {
+					elementChanged(changed[i], forceUpdate);
+				}
+			}
+			// Handle any changes at the project level
+			else if (element.getElementType() == IJavaElement.JAVA_PROJECT) {
+				if ((delta.getFlags() & IJavaElementDelta.F_CLASSPATH_CHANGED) != 0) {
+					IJavaElement proj = element;
+					handleClasspathChange((IJavaProject) proj, delta, forceUpdate);
+				}
+				else {
+					IJavaElementDelta[] deltas = delta.getAffectedChildren();
+					if (deltas.length == 0) {
+						if (delta.getKind() == IJavaElementDelta.REMOVED || (delta.getFlags() & IJavaElementDelta.F_CLOSED) != 0) {
+							/*
+							 * If the project is being deleted or closed, just
+							 * remove the description
+							 */
+							IJavaProject proj = (IJavaProject) element;
+							ProjectDescription description = (ProjectDescription) fProjectDescriptions.remove(proj.getProject());
+							if (description != null) {
+								if (_debugIndexCreation) {
+									Logger.log(Logger.INFO, "removing index of " + description.fProject.getName()); //$NON-NLS-1$
+								}
+								// removing the index file ensures that we
+								// don't get stale data if the project is
+								// reopened
+								removeIndexFile(proj.getProject());
+							}
+						}
+					}
+					/*
+					 * (else) Without the classpath changing, there's nothing
+					 * else to do
+					 */
+					else {
+						for (int i = 0; i < deltas.length; i++) {
+							elementChanged(deltas[i], false);
+						}
+					}
+				}
+			}
+			/*
+			 * Other modification to the classpath (such as within a classpath
+			 * container like "Web App Libraries") go to the description
+			 * itself
+			 */
+			else if ((delta.getFlags() & IJavaElementDelta.F_ADDED_TO_CLASSPATH) != 0 || (delta.getFlags() & IJavaElementDelta.F_REMOVED_FROM_CLASSPATH) != 0) {
+				IJavaProject affectedProject = element.getJavaProject();
+				if (affectedProject != null) {
+					/*
+					 * If the affected project has an index on-disk, it's
+					 * going to be invalid--we need to create/load the
+					 * description so it will be up to date [loading now and
+					 * updating is usually faster than regenerating the entire
+					 * index]. If there is no index on disk, do nothing more.
+					 */
+					File indexFile = new File(computeIndexLocation(affectedProject.getProject().getFullPath()));
+					if (indexFile.exists()) {
+						ProjectDescription affectedDescription = createDescription(affectedProject.getProject());
+						if (affectedDescription != null) {
+							affectedDescription.handleElementChanged(delta);
+						}
+					}
+					projectsIndexed.add(affectedProject.getProject());
+				}
+			}
+		}
+
+		private void handleClasspathChange(IJavaProject project, IJavaElementDelta delta, boolean forceUpdate) {
+			if (frameworkIsShuttingDown())
+				return;
+
+			try {
+				/* Handle large changes to this project's build path */
+				IResource resource = project.getCorrespondingResource();
+				if (resource.getType() == IResource.PROJECT && !projectsIndexed.contains(resource)) {
+					/*
+					 * Use get instead of create since the downstream
+					 * (upstream?) project wasn't itself modified.
+					 */
+					ProjectDescription description = null;
+					if (forceUpdate) {
+						description = createDescription((IProject) resource);
+					}
+					else {
+						description = getDescription((IProject) resource);
+					}
+					if (description != null && !frameworkIsShuttingDown()) {
+						projectsIndexed.add(resource);
+						description.queueElementChanged(delta);
+					}
+				}
+			}
+			catch (JavaModelException e) {
+				Logger.logException(e);
+			}
+		}
+	}
+
+	class ResourceChangeListener implements IResourceChangeListener {
+		public void resourceChanged(IResourceChangeEvent event) {
+			if (!isIndexAvailable())
+				return;
+			try {
+				LOCK.acquire();
+				if (_debugEvents) {
+					Logger.log(Logger.INFO, "TaglibIndex responding to:" + event + "\n" + event.getDelta()); //$NON-NLS-2$ //$NON-NLS-1$
+				}
+				switch (event.getType()) {
+					case IResourceChangeEvent.PRE_CLOSE :
+					case IResourceChangeEvent.PRE_DELETE : {
+						try {
+							// pair deltas with projects
+							IResourceDelta[] deltas = new IResourceDelta[]{event.getDelta()};
+							IProject[] projects = null;
+
+							if (deltas.length > 0) {
+								IResource resource = null;
+								if (deltas[0] != null) {
+									resource = deltas[0].getResource();
+								}
+								else {
+									resource = event.getResource();
+								}
+
+								if (resource != null) {
+									if (resource.getType() == IResource.ROOT) {
+										deltas = deltas[0].getAffectedChildren();
+										projects = new IProject[deltas.length];
+										for (int i = 0; i < deltas.length; i++) {
+											if (deltas[i].getResource().getType() == IResource.PROJECT) {
+												projects[i] = (IProject) deltas[i].getResource();
+											}
+										}
+									}
+									else {
+										projects = new IProject[1];
+										if (resource.getType() != IResource.PROJECT) {
+											projects[0] = resource.getProject();
+										}
+										else {
+											projects[0] = (IProject) resource;
+										}
+									}
+								}
+								for (int i = 0; i < projects.length; i++) {
+									if (_debugIndexCreation) {
+										Logger.log(Logger.INFO, "TaglibIndex noticed " + projects[i].getName() + " is about to be deleted/closed"); //$NON-NLS-1$ //$NON-NLS-2$
+									}
+									ProjectDescription description = (ProjectDescription) fProjectDescriptions.remove(projects[i]);
+									if (description != null) {
+										if (_debugIndexCreation) {
+											Logger.log(Logger.INFO, "removing index of " + description.fProject.getName()); //$NON-NLS-1$
+										}
+										description.clear();
+									}
+								}
+							}
+						}
+						catch (Exception e) {
+							Logger.logException("Exception while processing resource deletion", e); //$NON-NLS-1$
+						}
+					}
+					case IResourceChangeEvent.POST_CHANGE : {
+						try {
+							// pair deltas with projects
+							IResourceDelta[] deltas = new IResourceDelta[]{event.getDelta()};
+							IProject[] projects = null;
+
+							if (deltas.length > 0) {
+								IResource resource = null;
+								if (deltas[0] != null) {
+									resource = deltas[0].getResource();
+								}
+								else {
+									resource = event.getResource();
+								}
+
+								if (resource != null) {
+									if (resource.getType() == IResource.ROOT) {
+										deltas = deltas[0].getAffectedChildren();
+										projects = new IProject[deltas.length];
+										for (int i = 0; i < deltas.length; i++) {
+											if (deltas[i].getResource().getType() == IResource.PROJECT) {
+												projects[i] = (IProject) deltas[i].getResource();
+											}
+										}
+									}
+									else {
+										projects = new IProject[1];
+										if (resource.getType() != IResource.PROJECT) {
+											projects[0] = resource.getProject();
+										}
+										else {
+											projects[0] = (IProject) resource;
+										}
+									}
+								}
+								for (int i = 0; i < projects.length; i++) {
+									try {
+										if (deltas[i] != null && deltas[i].getKind() != IResourceDelta.REMOVED && projects[i].isAccessible()) {
+											ProjectDescription description = getDescription(projects[i]);
+											if (description != null && !frameworkIsShuttingDown()) {
+												deltas[i].accept(description.getVisitor());
+											}
+										}
+										if (!projects[i].isAccessible() || (deltas[i] != null && deltas[i].getKind() == IResourceDelta.REMOVED)) {
+											if (_debugIndexCreation) {
+												Logger.log(Logger.INFO, "TaglibIndex noticed " + projects[i].getName() + " was removed or is no longer accessible"); //$NON-NLS-1$ //$NON-NLS-2$
+											}
+											ProjectDescription description = (ProjectDescription) fProjectDescriptions.remove(projects[i]);
+											if (description != null) {
+												if (_debugIndexCreation) {
+													Logger.log(Logger.INFO, "removing index of " + description.fProject.getName()); //$NON-NLS-1$
+												}
+												description.clear();
+											}
+										}
+									}
+									catch (CoreException e) {
+										Logger.logException(e);
+									}
+								}
+							}
+						}
+						catch (Exception e) {
+							Logger.logException("Exception while processing resource change", e); //$NON-NLS-1$
+						}
+					}
+				}
+
+				fireCurrentDelta(event);
+			}
+			finally {
+				LOCK.release();
+			}
+		}
+	}
+
+	/**
+	 * <p>A {@link AbstractMemoryListener} that clears the {@link ProjectDescription} cache
+	 * whenever specific memory events are received.</p>
+	 * 
+	 * <p>Events:
+	 * <ul>
+	 * <li>{@link AbstractMemoryListener#SEV_SERIOUS}</li>
+	 * <li>{@link AbstractMemoryListener#SEV_CRITICAL}</li>
+	 * </ul>
+	 * </p>
+	 */
+	private class MemoryListener extends AbstractMemoryListener {
+		/**
+		 * <p>Constructor causes this listener to listen for specific memory events.</p>
+		 * <p>Events:
+		 * <ul>
+		 * <li>{@link AbstractMemoryListener#SEV_SERIOUS}</li>
+		 * <li>{@link AbstractMemoryListener#SEV_CRITICAL}</li>
+		 * </ul>
+		 * </p>
+		 */
+		MemoryListener() {
+			super(new String[] { SEV_SERIOUS, SEV_CRITICAL });
+		}
+		
+		/**
+		 * On any memory event we handle clear out the project descriptions
+		 * 
+		 * @see org.eclipse.jst.jsp.core.internal.util.AbstractMemoryListener#handleMemoryEvent(org.osgi.service.event.Event)
+		 */
+		protected void handleMemoryEvent(Event event) {
+			clearProjectDescriptions();
+		}
+		
+	}
+	
+	static final boolean _debugChangeListener = false;
+
+	static boolean _debugEvents = "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.jst.jsp.core/taglib/events")); //$NON-NLS-1$ //$NON-NLS-2$
+
+	static boolean _debugIndexCreation = "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.jst.jsp.core/taglib/indexcreation")); //$NON-NLS-1$ //$NON-NLS-2$
+
+	static final boolean _debugResolution = "true".equals(Platform.getDebugOption("org.eclipse.jst.jsp.core/taglib/resolve")); //$NON-NLS-1$ //$NON-NLS-2$
+
+	static TaglibIndex _instance = new TaglibIndex();
+
+	private boolean initialized;
+
+	private static final CRC32 checksumCalculator = new CRC32();
+
+	private static final String CLEAN = "CLEAN";
+	private static final String DIRTY = "DIRTY";
+	static boolean ENABLED = false;
+
+	static final ILock LOCK = Job.getJobManager().newLock();
+
+	/**
+	 * NOT API.
+	 * 
+	 * @param listener
+	 *            the listener to be added
+	 */
+	public static void addTaglibIndexListener(ITaglibIndexListener listener) {
+		if (getInstance().isInitialized())
+			getInstance().internalAddTaglibIndexListener(listener);
+	}
+
+	static void fireTaglibDelta(ITaglibIndexDelta delta) {
+		if (_debugEvents) {
+			Logger.log(Logger.INFO, "TaglibIndex fired delta:" + delta + " [" + delta.getAffectedChildren().length + "]\n" + ((TaglibIndexDelta) delta).trigger); //$NON-NLS-1$
+		}
+		/*
+		 * Flush any shared cache entries, the TaglibControllers should handle
+		 * updating their documents as needed.
+		 */
+		ITaglibIndexDelta[] deltas = delta.getAffectedChildren();
+		for (int i = 0; i < deltas.length; i++) {
+			ITaglibRecord taglibRecord = deltas[i].getTaglibRecord();
+			if (taglibRecord != null) {
+				Object uniqueIdentifier = TLDCMDocumentManager.getUniqueIdentifier(taglibRecord);
+				if (uniqueIdentifier != null) {
+					TLDCMDocumentManager.getSharedDocumentCache().remove(uniqueIdentifier);
+				}
+				else {
+					Logger.log(Logger.ERROR, "identifier for " + taglibRecord + " was null");
+				}
+			}
+		}
+		synchronized (TLDCMDocumentManager.getSharedDocumentCache()) {
+			Iterator values = TLDCMDocumentManager.getSharedDocumentCache().values().iterator();
+			while (values.hasNext()) {
+				Object o = values.next();
+				if (o instanceof Reference) {
+					values.remove();
+				}
+			}
+		}
+
+		if (_instance.isInitialized()) {
+			ITaglibIndexListener[] listeners = _instance.fTaglibIndexListeners;
+			if (listeners != null) {
+				for (int j = 0; j < listeners.length; j++) {
+					try {
+						listeners[j].indexChanged(delta);
+					}
+					catch (Exception e) {
+						Logger.log(Logger.WARNING, e.getMessage());
+					}
+				}
+			}
+		}
+	}
+
+
+	/**
+	 * Finds all of the visible ITaglibRecords for the given path in the
+	 * workspace. Taglib mappings from web.xml files are only visible to paths
+	 * within the web.xml's corresponding web content folder.
+	 * This method will almost certainly require a workspace lock to complete.
+	 * 
+	 * @param fullPath -
+	 *            a path within the workspace
+	 * @return All of the visible ITaglibRecords from the given path.
+	 */
+	public static ITaglibRecord[] getAvailableTaglibRecords(IPath fullPath) {
+		if (!_instance.isInitialized()) {
+			return new ITaglibRecord[0];
+		}
+		ITaglibRecord[] records = null;
+		if (getInstance().isInitialized()) {
+			records = getInstance().internalGetAvailableTaglibRecords(fullPath);
+		}
+		else {
+			records = new ITaglibRecord[0];
+		}
+		getInstance().fireCurrentDelta("enumerate: " + fullPath); //$NON-NLS-1$
+		return records;
+	}
+
+	/**
+	 * Returns the IPath considered to be the web-app root for the given path.
+	 * All resolution from the given path beginning with '/' will be relative
+	 * to the computed web-app root.
+	 * 
+	 * @deprecated - is not correct in flexible projects
+	 * @param path -
+	 *            a path under the web-app root
+	 * @return the IPath considered to be the web-app's root for the given
+	 *         path or null if one could not be determined
+	 */
+	public static IPath getContextRoot(IPath path) {
+		try {
+			LOCK.acquire();
+			if (getInstance().isInitialized()) {
+				return getInstance().internalGetContextRoot(path);
+			}
+		}
+		finally {
+			LOCK.release();
+		}
+		return null;
+	}
+
+	public static TaglibIndex getInstance() {
+		return _instance;
+	}
+
+	/**
+	 * NOT API.
+	 * 
+	 * @param listener
+	 *            the listener to be removed
+	 */
+	public static void removeTaglibIndexListener(ITaglibIndexListener listener) {
+		if (!getInstance().isInitialized())
+			return;
+		if (getInstance().isInitialized())
+			getInstance().internalRemoveTaglibIndexListener(listener);
+	}
+
+	/**
+	 * Finds a matching ITaglibRecord given the reference. Typically the
+	 * result will have to be cast to a subinterface of ITaglibRecord. This
+	 * method will almost certainly require a workspace lock to complete.
+	 * 
+	 * @param basePath
+	 *            - the workspace-relative path for IResources, full
+	 *            filesystem path otherwise
+	 * @param reference
+	 *            - the URI to lookup, for example the uri value from a taglib
+	 *            directive
+	 * @param crossProjects
+	 *            - whether to search across projects (currently ignored)
+	 * 
+	 * @return a visible ITaglibRecord or null if the reference points to no
+	 *         known tag library descriptor
+	 * 
+	 * @See ITaglibRecord
+	 */
+	public static ITaglibRecord resolve(String basePath, String reference, boolean crossProjects) {
+		ITaglibRecord result = null;
+		if (getInstance().isInitialized()) {
+			result = getInstance().internalResolve(basePath, reference, crossProjects);
+		}
+		getInstance().fireCurrentDelta("resolve: " + reference); //$NON-NLS-1$
+		if (_debugResolution) {
+			if (result == null) {
+				Logger.log(Logger.INFO, "TaglibIndex could not resolve \"" + reference + "\" from " + basePath); //$NON-NLS-1$ //$NON-NLS-2$
+			}
+			else {
+				switch (result.getRecordType()) {
+					case (ITaglibRecord.TLD) : {
+						ITLDRecord record = (ITLDRecord) result;
+						Logger.log(Logger.INFO, "TaglibIndex resolved " + basePath + ":" + reference + " = " + record.getPath()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+					}
+						break;
+					case (ITaglibRecord.JAR) : {
+						IJarRecord record = (IJarRecord) result;
+						Logger.log(Logger.INFO, "TaglibIndex resolved " + basePath + ":" + reference + " = " + record.getLocation()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+					}
+						break;
+					case (ITaglibRecord.TAGDIR) : {
+						ITagDirRecord record = (ITagDirRecord) result;
+						Logger.log(Logger.INFO, "TaglibIndex resolved " + basePath + ":" + reference + " = " + record.getPath()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+					}
+						break;
+					case (ITaglibRecord.URL) : {
+						IURLRecord record = (IURLRecord) result;
+						Logger.log(Logger.INFO, "TaglibIndex resolved " + basePath + ":" + reference + " = " + record.getURL()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+					}
+						break;
+				}
+			}
+		}
+		return result;
+	}
+
+	/**
+	 * Instructs the index to stop listening for resource and classpath
+	 * changes, and to forget all information about the workspace.
+	 */
+	public static void shutdown() {
+		try {
+			LOCK.acquire();
+			if (getInstance().isInitialized()) {
+				getInstance().stop();
+			}
+		}
+		finally {
+			LOCK.release();
+		}
+	}
+
+	/**
+	 * Instructs the index to begin listening for resource and classpath
+	 * changes.
+	 */
+	public static void startup() {
+		boolean shuttingDown = !Platform.isRunning() || Platform.getBundle(OSGI_FRAMEWORK_ID).getState() == Bundle.STOPPING;
+		if (!shuttingDown) {
+			try {
+				LOCK.acquire();
+				ENABLED = !"false".equalsIgnoreCase(System.getProperty(TaglibIndex.class.getName())); //$NON-NLS-1$
+				getInstance().initializeInstance();
+			}
+			finally {
+				LOCK.release();
+			}
+		}
+	}
+
+	private ClasspathChangeListener fClasspathChangeListener = null;
+
+	private TaglibIndexDelta fCurrentTopLevelDelta = null;
+
+	Map fProjectDescriptions = null;
+
+	private ResourceChangeListener fResourceChangeListener;
+
+	private ITaglibIndexListener[] fTaglibIndexListeners = null;
+	
+	/**
+	 * Used to keep the {@link ProjectDescription} cache clean when memory is low
+	 */
+	private MemoryListener fMemoryListener;
+
+	/** symbolic name for OSGI framework */
+	private final static String OSGI_FRAMEWORK_ID = "org.eclipse.osgi"; //$NON-NLS-1$
+
+	private TaglibIndex() {
+		super();
+	}
+
+	private void initializeInstance() {
+
+		if (isInitialized())
+			return;
+		try {
+			LOCK.acquire();
+			/*
+			 * check again, just incase it was initialized on another thread,
+			 * while we were waiting for the lock
+			 */
+			if (!isInitialized()) {
+				getWorkingLocation();
+				/*
+				 * Only consider a crash if a value exists and is DIRTY (not a
+				 * new workspace)
+				 */
+				if (DIRTY.equalsIgnoreCase(getState())) {
+					Logger.log(Logger.ERROR, "A workspace crash was detected. The previous session did not exit normally. Not using saved taglib indexes."); //$NON-NLS-3$
+					removeIndexes(false);
+				}
+
+				fProjectDescriptions = new Hashtable();
+				fResourceChangeListener = new ResourceChangeListener();
+				fClasspathChangeListener = new ClasspathChangeListener();
+				fMemoryListener = new MemoryListener();
+
+				if (ENABLED) {
+					ResourcesPlugin.getWorkspace().addResourceChangeListener(fResourceChangeListener, IResourceChangeEvent.POST_CHANGE);
+					JavaCore.addElementChangedListener(fClasspathChangeListener);
+					//register the memory listener
+					fMemoryListener.connect();
+				}
+				setIntialized(true);
+			}
+		}
+		finally {
+			LOCK.release();
+		}
+	}
+
+	/**
+	 * Adds the given delta as a child to an overall delta
+	 * 
+	 * @param delta
+	 */
+	synchronized void addDelta(ITaglibIndexDelta delta) {
+		ensureDelta(delta.getProject()).addChildDelta(delta);
+	}
+
+	/**
+	 * Based on org.eclipse.jdt.internal.core.search.indexing.IndexManager
+	 * 
+	 * @param containerPath
+	 * @return the index file location for the given workspace path
+	 */
+	String computeIndexLocation(IPath containerPath) {
+		String fileName = computeIndexName(containerPath);
+		if (_debugIndexCreation)
+			Logger.log(Logger.INFO, "-> index name for " + containerPath + " is " + fileName); //$NON-NLS-1$ //$NON-NLS-2$
+		String indexLocation = getTaglibIndexStateLocation().append(fileName).toOSString();
+		return indexLocation;
+	}
+
+	String computeIndexName(IPath containerPath) {
+		checksumCalculator.reset();
+		checksumCalculator.update(containerPath.toOSString().getBytes());
+		// use ".dat" so we're not confused with JDT indexes
+		String fileName = Long.toString(checksumCalculator.getValue()) + ".dat"; //$NON-NLS-1$
+		return fileName;
+	}
+
+	/**
+	 * @param project
+	 * @return the ProjectDescription representing the given project
+	 */
+	ProjectDescription createDescription(IProject project) {
+		if (fProjectDescriptions == null)
+			return null;
+
+		ProjectDescription description = null;
+		try {
+			LOCK.acquire();
+			description = (ProjectDescription) fProjectDescriptions.get(project);
+			if (description == null) {
+				// Once we've started indexing, we're dirty again
+				if (fProjectDescriptions.isEmpty()) {
+					setState(DIRTY);
+				}
+				description = new ProjectDescription(project, computeIndexLocation(project.getFullPath()));
+				fProjectDescriptions.put(project, description);
+			}
+		}
+		finally {
+			LOCK.release();
+		}
+		return description;
+	}
+
+	/**
+	 * Ensures that a delta exists for holding index change information
+	 */
+	private TaglibIndexDelta ensureDelta(IProject project) {
+		/*
+		 * The first delta to be added will determine which project the
+		 * top-level delta will contain.
+		 */
+		if (fCurrentTopLevelDelta == null) {
+			fCurrentTopLevelDelta = new TaglibIndexDelta(project, null, ITaglibIndexDelta.CHANGED);
+		}
+		return fCurrentTopLevelDelta;
+	}
+
+	void fireCurrentDelta(Object trigger) {
+		if (fCurrentTopLevelDelta != null) {
+			fCurrentTopLevelDelta.trigger = trigger;
+			ITaglibIndexDelta delta = fCurrentTopLevelDelta;
+			fCurrentTopLevelDelta = null;
+			fireTaglibDelta(delta);
+		}
+	}
+
+	/**
+	 * A check to see if the OSGI framework is shutting down.
+	 * 
+	 * @return true if the System Bundle is stopped (ie. the framework is
+	 *         shutting down)
+	 */
+	boolean frameworkIsShuttingDown() {
+		// in the Framework class there's a note:
+		// set the state of the System Bundle to STOPPING.
+		// this must be done first according to section 4.19.2 from the OSGi
+		// R3 spec.
+		boolean shuttingDown = !Platform.isRunning() || Platform.getBundle(OSGI_FRAMEWORK_ID).getState() == Bundle.STOPPING;
+		return shuttingDown;
+	}
+
+	ProjectDescription getDescription(IProject project) {
+		ProjectDescription description = null;
+		if (isInitialized()) {
+			description = (ProjectDescription) fProjectDescriptions.get(project);
+		}
+		return description;
+	}
+
+	private String getState() {
+		String state = JSPCorePlugin.getDefault().getPluginPreferences().getString(TaglibIndex.class.getName());
+		return state;
+	}
+
+	private IPath getTaglibIndexStateLocation() {
+		return JSPCorePlugin.getDefault().getStateLocation().append("taglibindex/");
+	}
+
+	private void internalAddTaglibIndexListener(ITaglibIndexListener listener) {
+		try {
+			LOCK.acquire();
+			if (fTaglibIndexListeners == null) {
+				fTaglibIndexListeners = new ITaglibIndexListener[]{listener};
+			}
+			else {
+				List listeners = new ArrayList(Arrays.asList(fTaglibIndexListeners));
+				if (!listeners.contains(listener)) {
+					listeners.add(listener);
+				}
+				fTaglibIndexListeners = (ITaglibIndexListener[]) listeners.toArray(new ITaglibIndexListener[0]);
+			}
+		}
+		finally {
+			LOCK.release();
+		}
+	}
+
+	private ITaglibRecord[] internalGetAvailableTaglibRecords(IPath path) {
+		ITaglibRecord[] records = new ITaglibRecord[0];
+		if (path.segmentCount() > 0) {
+			IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(path.segment(0));
+			if (project.isAccessible()) {
+				ProjectDescription description = createDescription(project);
+				List availableRecords = description.getAvailableTaglibRecords(path);
+
+				// ICatalog catalog =
+				// XMLCorePlugin.getDefault().getDefaultXMLCatalog();
+				// while (catalog != null) {
+				// ICatalogEntry[] entries = catalog.getCatalogEntries();
+				// for (int i = 0; i < entries.length; i++) {
+				// // System.out.println(entries[i].getURI());
+				// }
+				// INextCatalog[] nextCatalogs = catalog.getNextCatalogs();
+				// for (int i = 0; i < nextCatalogs.length; i++) {
+				// ICatalogEntry[] entries2 =
+				// nextCatalogs[i].getReferencedCatalog().getCatalogEntries();
+				// for (int j = 0; j < entries2.length; j++) {
+				// // System.out.println(entries2[j].getURI());
+				// }
+				// }
+				// }
+
+				records = (ITaglibRecord[]) availableRecords.toArray(records);
+			}
+		}
+		return records;
+	}
+
+	private IPath internalGetContextRoot(IPath path) {
+		IFile baseResource = FileBuffers.getWorkspaceFileAtLocation(path);
+		if (baseResource != null && baseResource.getProject().isAccessible()) {
+			IProject project = baseResource.getProject();
+			ProjectDescription description = getInstance().createDescription(project);
+			IPath rootPath = description.getLocalRoot(baseResource.getFullPath());
+			return rootPath;
+		}
+		// try to handle out-of-workspace paths
+		IPath root = path.makeAbsolute();
+		while (root.segmentCount() > 0 && !root.isRoot())
+			root = root.removeLastSegments(1);
+		return root;
+	}
+
+	private void internalRemoveTaglibIndexListener(ITaglibIndexListener listener) {
+		try {
+			LOCK.acquire();
+			if (fTaglibIndexListeners != null) {
+				List listeners = new ArrayList(Arrays.asList(fTaglibIndexListeners));
+				listeners.remove(listener);
+				fTaglibIndexListeners = (ITaglibIndexListener[]) listeners.toArray(new ITaglibIndexListener[0]);
+			}
+		}
+		finally {
+			LOCK.release();
+		}
+	}
+
+	private ITaglibRecord internalResolve(String basePath, final String reference, boolean crossProjects) {
+		IProject project = null;
+		ITaglibRecord resolved = null;
+
+		Path baseIPath = new Path(basePath);
+		IResource baseResource = FileBuffers.getWorkspaceFileAtLocation(baseIPath);
+
+		if (baseResource == null) {
+			IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
+			// Try the base path as a folder first
+			if (baseIPath.segmentCount() > 1) {
+				baseResource = workspaceRoot.getFolder(baseIPath);
+			}
+			// If not a folder, then try base path as a file
+			if (baseResource != null && !baseResource.exists() && baseIPath.segmentCount() > 1) {
+				baseResource = workspaceRoot.getFile(baseIPath);
+			}
+			if (baseResource == null && baseIPath.segmentCount() == 1) {
+				baseResource = workspaceRoot.getProject(baseIPath.segment(0));
+			}
+		}
+
+		if (baseResource == null) {
+			/*
+			 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=116529
+			 * 
+			 * This method produces a less accurate result, but doesn't
+			 * require that the file exist yet.
+			 */
+			IFile[] files = ResourcesPlugin.getWorkspace().getRoot().findFilesForLocation(baseIPath);
+			if (files.length > 0)
+				baseResource = files[0];
+		}
+		if (baseResource != null) {
+			project = ResourcesPlugin.getWorkspace().getRoot().getProject(baseIPath.segment(0));
+			if (project.isAccessible()) {
+				ProjectDescription description = createDescription(project);
+				resolved = description.resolve(basePath, reference);
+			}
+		}
+
+		return resolved;
+	}
+
+	boolean isIndexAvailable() {
+		return _instance.isInitialized() && ENABLED;
+	}
+
+	/**
+	 * Removes index file for the given project.
+	 */
+	void removeIndexFile(IProject project) {
+		File indexFile = new File(computeIndexLocation(project.getFullPath()));
+		if (indexFile.exists()) {
+			indexFile.delete();
+		}
+	}
+
+	/**
+	 * Removes index files. Used for maintenance and keeping the index folder
+	 * a manageable size.
+	 * 
+	 * @param staleOnly -
+	 *            if <b>true</b>, removes only the indexes for projects not
+	 *            open in the workspace, if <b>false</b>, removes all of the
+	 *            indexes
+	 */
+	private void removeIndexes(boolean staleOnly) {
+		File folder = getWorkingLocation();
+
+		// remove any extraneous index files
+		IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
+		List indexNames = new ArrayList(projects.length);
+		if (staleOnly) {
+			for (int i = 0; i < projects.length; i++) {
+				if (projects[i].isAccessible()) {
+					indexNames.add(computeIndexName(projects[i].getFullPath()));
+				}
+			}
+		}
+
+		if (folder.isDirectory()) {
+			File[] files = folder.listFiles();
+			for (int i = 0; files != null && i < files.length; i++) {
+				if (!indexNames.contains(files[i].getName()))
+					files[i].delete();
+			}
+		}
+	}
+
+	private void setState(String state) {
+		if (!state.equals(getState())) {
+			JSPCorePlugin.getDefault().getPluginPreferences().setValue(TaglibIndex.class.getName(), state);
+			JSPCorePlugin.getDefault().savePluginPreferences();
+		}
+	}
+
+	private void stop() {
+		if (isInitialized()) {
+			setIntialized(false);
+
+			ResourcesPlugin.getWorkspace().removeResourceChangeListener(fResourceChangeListener);
+			JavaCore.removeElementChangedListener(fClasspathChangeListener);
+			//unregister the memory listener
+			fMemoryListener.disconnect();
+
+			/*
+			 * Clearing the existing saved states helps prune dead data from
+			 * the index folder.
+			 */
+			removeIndexes(true);
+
+			clearProjectDescriptions();
+
+			setState(CLEAN);
+			fProjectDescriptions = null;
+			fResourceChangeListener = null;
+			fClasspathChangeListener = null;
+			fMemoryListener = null;
+		}
+	}
+
+	/**
+	 * Get the working location for the taglib index
+	 * @return The File representing the taglib index's working location
+	 */
+	private File getWorkingLocation() {
+		File folder = new File(getTaglibIndexStateLocation().toOSString());
+		if (!folder.isDirectory()) {
+			try {
+				folder.mkdir();
+			}
+			catch (SecurityException e) {
+			}
+		}
+		return folder;
+	}
+
+	/**
+	 * Have all of the ProjectDescriptions write their information to disk and
+	 * then clear our map of them
+	 */
+	void clearProjectDescriptions() {
+		try {
+			LOCK.acquire();
+			Iterator i = fProjectDescriptions.values().iterator();
+			while (i.hasNext()) {
+				ProjectDescription description = (ProjectDescription) i.next();
+				description.saveReferences();
+			}
+
+			fProjectDescriptions.clear();
+		} finally {
+			LOCK.release();
+		}
+	}
+
+	private boolean isInitialized() {
+		return initialized;
+	}
+
+	private void setIntialized(boolean intialized) {
+		this.initialized = intialized;
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/taglib/TaglibIndexDelta.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/taglib/TaglibIndexDelta.java
new file mode 100644
index 0000000..fc14d8b
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/taglib/TaglibIndexDelta.java
@@ -0,0 +1,148 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.taglib;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.eclipse.core.resources.IProject;
+
+public class TaglibIndexDelta implements ITaglibIndexDelta {
+	private Collection fChildren;
+	private int fExplicitKind = -1;
+	private int fImplicitKind = -1;
+	private IProject fProject;
+	private ITaglibRecord fTaglibRecord = null;
+	long time;
+	Object trigger = null;
+
+	TaglibIndexDelta(IProject project, ITaglibRecord record, int kind) {
+		fProject = project;
+		fTaglibRecord = record;
+		fExplicitKind = kind;
+		time = System.currentTimeMillis();
+	}
+
+	void addChildDelta(ITaglibIndexDelta delta) {
+		if (fChildren == null)
+			fChildren = new ArrayList();
+		fChildren.add(delta);
+		fImplicitKind = -1;
+	}
+
+	private int computeKind() {
+		int added = 0;
+		int removed = 0;
+
+		ITaglibIndexDelta[] children = (ITaglibIndexDelta[]) fChildren.toArray(new ITaglibIndexDelta[fChildren.size()]);
+		for (int i = 0; i < children.length; i++) {
+			int kind = children[i].getKind();
+			if (kind == ITaglibIndexDelta.ADDED)
+				added++;
+			if (kind == ITaglibIndexDelta.REMOVED)
+				removed++;
+			if (added > 0 && removed > 0)
+				break;
+		}
+		if (added > 0 && removed > 0) {
+			return ITaglibIndexDelta.CHANGED;
+		}
+		else if (added > 0) {
+			return ITaglibIndexDelta.ADDED;
+		}
+		else if (removed > 0) {
+			return ITaglibIndexDelta.REMOVED;
+		}
+		else {
+			return ITaglibIndexDelta.CHANGED;
+		}
+	}
+
+	public ITaglibIndexDelta[] getAffectedChildren() {
+		if (fChildren == null) {
+			return new ITaglibIndexDelta[0];
+		}
+		return (ITaglibIndexDelta[]) fChildren.toArray(new ITaglibIndexDelta[fChildren.size()]);
+	}
+
+	public int getKind() {
+		if (fChildren == null) {
+			return fExplicitKind;
+		}
+		if (fImplicitKind == -1) {
+			fImplicitKind = computeKind();
+		}
+		return fImplicitKind;
+	}
+
+	public IProject getProject() {
+		return fProject;
+	}
+
+	public ITaglibRecord getTaglibRecord() {
+		return fTaglibRecord;
+	}
+
+	public long getTime() {
+		return time;
+	}
+
+	public Object getTrigger() {
+		return trigger;
+	}
+
+	public String toString() {
+		if (fTaglibRecord != null) {
+			String string = fTaglibRecord.toString();
+			int kind = getKind();
+			switch (kind) {
+				case ITaglibIndexDelta.ADDED :
+					string = " ADDED (" + string + ")"; //$NON-NLS-1$ //$NON-NLS-2$
+					break;
+				case ITaglibIndexDelta.CHANGED :
+					string = " CHANGED (" + string + ")"; //$NON-NLS-1$ //$NON-NLS-2$
+					break;
+				case ITaglibIndexDelta.REMOVED :
+					string = " REMOVED (" + string + ")"; //$NON-NLS-1$ //$NON-NLS-2$
+					break;
+				default :
+					string = " other:" + kind + " (" + string + ")"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+					break;
+			}
+			return string;
+		}
+		else {
+			StringBuffer buffer = new StringBuffer();
+			int kind = getKind();
+			switch (kind) {
+				case ITaglibIndexDelta.ADDED :
+					buffer.append("TaglibIndexDelta(" + fProject + "):ADDED\n"); //$NON-NLS-1$
+					break;
+				case ITaglibIndexDelta.CHANGED :
+					buffer.append("TaglibIndexDelta(" + fProject + "):CHANGED\n"); //$NON-NLS-1$
+					break;
+				case ITaglibIndexDelta.REMOVED :
+					buffer.append("TaglibIndexDelta(" + fProject + "):REMOVED\n"); //$NON-NLS-1$
+					break;
+			}
+			ITaglibIndexDelta[] children = getAffectedChildren();
+			for (int i = 0; i < children.length; i++) {
+				buffer.append('\t');
+				buffer.append(children[i].toString());
+				if (i < children.length - 1) {
+					buffer.append('\n');
+				}
+			}
+			return buffer.toString();
+		}
+	}
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/text/IJSPPartitions.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/text/IJSPPartitions.java
new file mode 100644
index 0000000..dae4c3d
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/text/IJSPPartitions.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.text;
+
+
+/**
+ * This interface is not intended to be implemented.
+ * It defines the partition types for JSP.
+ * Clients should reference the partition type Strings defined here directly.
+ * 
+ * @since 1.1
+ */
+public interface IJSPPartitions {
+
+	String JSP_DEFAULT = "org.eclipse.jst.jsp.DEFAULT_JSP"; //$NON-NLS-1$
+	String JSP_COMMENT = "org.eclipse.jst.jsp.JSP_COMMENT"; //$NON-NLS-1$
+	
+	String JSP_SCRIPT_PREFIX = "org.eclipse.jst.jsp.SCRIPT."; //$NON-NLS-1$
+	String JSP_CONTENT_DELIMITER = JSP_SCRIPT_PREFIX + "DELIMITER"; //$NON-NLS-1$
+	String JSP_CONTENT_JAVA = JSP_SCRIPT_PREFIX + "JAVA"; //$NON-NLS-1$
+	String JSP_CONTENT_JAVASCRIPT = JSP_SCRIPT_PREFIX + "JAVASCRIPT"; //$NON-NLS-1$
+	String JSP_DEFAULT_EL = JSP_SCRIPT_PREFIX + "JSP_EL"; //$NON-NLS-1$
+	String JSP_DEFAULT_EL2 = JSP_SCRIPT_PREFIX + "JSP_EL2"; //$NON-NLS-1$
+	
+	String JSP_DIRECTIVE = "org.eclipse.jst.jsp.JSP_DIRECTIVE"; //$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/css/core/internal/contentmodel/JSPedCSSTaglibController.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/css/core/internal/contentmodel/JSPedCSSTaglibController.java
new file mode 100644
index 0000000..e84a5ff
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/css/core/internal/contentmodel/JSPedCSSTaglibController.java
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+
+package org.eclipse.jst.jsp.css.core.internal.contentmodel;
+
+import org.eclipse.core.filebuffers.IDocumentSetupParticipant;
+import org.eclipse.jface.text.IDocument;
+
+public class JSPedCSSTaglibController implements IDocumentSetupParticipant {
+
+	public void setup(IDocument document) {
+		// ignore TLD in content type css jsp
+	}
+
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/css/core/internal/contenttype/ContentDescriberForJSPedCSS.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/css/core/internal/contenttype/ContentDescriberForJSPedCSS.java
new file mode 100644
index 0000000..58afa6e
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/css/core/internal/contenttype/ContentDescriberForJSPedCSS.java
@@ -0,0 +1,236 @@
+/*******************************************************************************
+ * Copyright (c) 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jst.jsp.css.core.internal.contenttype;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+
+import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.core.runtime.content.IContentDescriber;
+import org.eclipse.core.runtime.content.IContentDescription;
+import org.eclipse.core.runtime.content.ITextContentDescriber;
+import org.eclipse.jst.jsp.core.internal.contenttype.JSPResourceEncodingDetector;
+import org.eclipse.jst.jsp.core.internal.provisional.contenttype.IContentDescriptionForJSP;
+import org.eclipse.wst.sse.core.internal.encoding.EncodingMemento;
+import org.eclipse.wst.sse.core.internal.encoding.IContentDescriptionExtended;
+import org.eclipse.wst.sse.core.internal.encoding.IResourceCharsetDetector;
+
+public class ContentDescriberForJSPedCSS implements ITextContentDescriber {
+	private final static QualifiedName[] SUPPORTED_OPTIONS = {IContentDescription.CHARSET, IContentDescription.BYTE_ORDER_MARK, IContentDescriptionExtended.DETECTED_CHARSET, IContentDescriptionExtended.UNSUPPORTED_CHARSET, IContentDescriptionExtended.APPROPRIATE_DEFAULT, IContentDescriptionForJSP.CONTENT_TYPE_ATTRIBUTE, IContentDescriptionForJSP.LANGUAGE_ATTRIBUTE};
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.core.runtime.content.IContentDescriber#describe(java.io.InputStream,
+	 *      org.eclipse.core.runtime.content.IContentDescription)
+	 */
+	public int describe(InputStream contents, IContentDescription description) throws IOException {
+		int result = IContentDescriber.INVALID;
+
+		// if discription is null, we are just being asked to
+		// assess contents validity
+		if (description != null) {
+			result = calculateSupportedOptions(contents, description);
+		}
+		else {
+			result = determineValidity(contents);
+		}
+
+		return result;
+	}
+
+
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.core.runtime.content.ITextContentDescriber#describe(java.io.Reader,
+	 *      org.eclipse.core.runtime.content.IContentDescription)
+	 */
+	public int describe(Reader contents, IContentDescription description) throws IOException {
+		int result = IContentDescriber.INVALID;
+
+		// if discription is null, we are just being asked to
+		// assess contents validity
+		if (description != null) {
+			result = calculateSupportedOptions(contents, description);
+		}
+		else {
+			result = determineValidity(contents);
+		}
+
+		return result;
+	}
+
+
+	public QualifiedName[] getSupportedOptions() {
+		return SUPPORTED_OPTIONS;
+	}
+
+	private int calculateSupportedOptions(InputStream contents, IContentDescription description) throws IOException {
+		int result = IContentDescriber.INDETERMINATE;
+		if (isRelevent(description)) {
+			IResourceCharsetDetector detector = getDetector();
+			detector.set(contents);
+			handleCalculations(description, detector);
+			result = IContentDescriber.VALID;
+		}
+		return result;
+	}
+
+	/**
+	 * @param contents
+	 * @param description
+	 * @throws IOException
+	 */
+	private int calculateSupportedOptions(Reader contents, IContentDescription description) throws IOException {
+		int result = IContentDescriber.INDETERMINATE;
+		if (isRelevent(description)) {
+			IResourceCharsetDetector detector = getDetector();
+			detector.set(contents);
+			handleCalculations(description, detector);
+			result = IContentDescriber.VALID;
+		}
+		return result;
+	}
+
+	private IResourceCharsetDetector getDetector() {
+		return new JSPResourceEncodingDetector();
+	}
+
+	private void handleCalculations(IContentDescription description, IResourceCharsetDetector detector) throws IOException {
+		// handle standard ones first, to be sure detector processes
+		handleStandardCalculations(description, detector);
+		// now do those specific for JSPs
+		// note: detector should always be of correct instance, but we'll
+		// check, for now.
+		if (detector instanceof JSPResourceEncodingDetector) {
+			JSPResourceEncodingDetector jspDetector = (JSPResourceEncodingDetector) detector;
+			String language = jspDetector.getLanguage();
+			if (language != null && language.length() > 0) {
+				description.setProperty(IContentDescriptionForJSP.LANGUAGE_ATTRIBUTE, language);
+			}
+			String contentTypeAttribute = jspDetector.getContentType();
+			if (contentTypeAttribute != null && contentTypeAttribute.length() > 0) {
+				description.setProperty(IContentDescriptionForJSP.CONTENT_TYPE_ATTRIBUTE, contentTypeAttribute);
+			}
+		}
+	}
+
+	private void handleDetectedSpecialCase(IContentDescription description, Object detectedCharset, Object javaCharset) {
+		if (detectedCharset != null) {
+			// Once we detected a charset, we should set the property even
+			// though it's the same as javaCharset
+			// because there are clients that rely on this property to
+			// determine if the charset is actually detected in file or not.
+			description.setProperty(IContentDescriptionExtended.DETECTED_CHARSET, detectedCharset);
+		}
+	}
+
+	/**
+	 * @param description
+	 * @param detector
+	 * @throws IOException
+	 */
+	private void handleStandardCalculations(IContentDescription description, IResourceCharsetDetector detector) throws IOException {
+		// note: if we're asked for one, we set them all. I need to be sure if
+		// called
+		// mulitiple times (one for each, say) that we don't waste time
+		// processing same
+		// content again.
+		EncodingMemento encodingMemento = ((JSPResourceEncodingDetector) detector).getEncodingMemento();
+		// TODO: I need to verify to see if this BOM work is always done
+		// by text type.
+		Object detectedByteOrderMark = encodingMemento.getUnicodeBOM();
+		if (detectedByteOrderMark != null) {
+			Object existingByteOrderMark = description.getProperty(IContentDescription.BYTE_ORDER_MARK);
+			// not sure why would ever be different, so if is different, may
+			// need to "push" up into base.
+			if (!detectedByteOrderMark.equals(existingByteOrderMark))
+				description.setProperty(IContentDescription.BYTE_ORDER_MARK, detectedByteOrderMark);
+		}
+
+
+		if (!encodingMemento.isValid()) {
+			// note: after setting here, its the mere presence of
+			// IContentDescriptionExtended.UNSUPPORTED_CHARSET
+			// in the resource's description that can be used to determine if
+			// invalid
+			// in those cases, the "detected" property contains an
+			// "appropriate default" to use.
+			description.setProperty(IContentDescriptionExtended.UNSUPPORTED_CHARSET, encodingMemento.getInvalidEncoding());
+			description.setProperty(IContentDescriptionExtended.APPROPRIATE_DEFAULT, encodingMemento.getAppropriateDefault());
+		}
+
+		Object detectedCharset = encodingMemento.getDetectedCharsetName();
+		Object javaCharset = encodingMemento.getJavaCharsetName();
+
+		// we always include detected, if its different than java
+		handleDetectedSpecialCase(description, detectedCharset, javaCharset);
+
+		if (javaCharset != null) {
+			Object existingCharset = description.getProperty(IContentDescription.CHARSET);
+			if (javaCharset.equals(existingCharset)) {
+				handleDetectedSpecialCase(description, detectedCharset, javaCharset);
+			}
+			else {
+				// we may need to add what we found, but only need to add
+				// if different from the default.
+				Object defaultCharset = detector.getSpecDefaultEncoding();
+				if (defaultCharset != null) {
+					if (!defaultCharset.equals(javaCharset)) {
+						description.setProperty(IContentDescription.CHARSET, javaCharset);
+					}
+				}
+				else {
+					// assuming if there is no spec default, we always need to
+					// add, I'm assuming
+					description.setProperty(IContentDescription.CHARSET, javaCharset);
+				}
+			}
+		}
+
+	}
+
+	/**
+	 * @param description
+	 * @return
+	 */
+	private boolean isRelevent(IContentDescription description) {
+		boolean result = false;
+		if (description == null)
+			result = false;
+		else if (description.isRequested(IContentDescription.BYTE_ORDER_MARK))
+			result = true;
+		else if (description.isRequested(IContentDescription.CHARSET))
+			result = true;
+		else if (description.isRequested(IContentDescriptionExtended.APPROPRIATE_DEFAULT))
+			result = true;
+		else if (description.isRequested(IContentDescriptionExtended.DETECTED_CHARSET))
+			result = true;
+		else if (description.isRequested(IContentDescriptionExtended.UNSUPPORTED_CHARSET))
+			result = true;
+		else if (description.isRequested(IContentDescriptionForJSP.CONTENT_TYPE_ATTRIBUTE))
+			result = true;
+		return result;
+	}
+	
+	private int determineValidity(InputStream inputStream) {
+		return IContentDescriber.INDETERMINATE;
+	}
+
+	private int determineValidity(Reader reader) {
+		return IContentDescriber.INDETERMINATE;
+	}
+
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/css/core/internal/document/IJSPCSSImportRule.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/css/core/internal/document/IJSPCSSImportRule.java
new file mode 100644
index 0000000..7f74b88
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/css/core/internal/document/IJSPCSSImportRule.java
@@ -0,0 +1,18 @@
+/*******************************************************************************
+ * Copyright (c) 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jst.jsp.css.core.internal.document;
+
+import org.eclipse.wst.css.core.internal.provisional.document.ICSSImportRule;
+
+public interface IJSPCSSImportRule extends ICSSImportRule, IJSPCSSNode {
+
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/css/core/internal/document/IJSPCSSNode.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/css/core/internal/document/IJSPCSSNode.java
new file mode 100644
index 0000000..af26755
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/css/core/internal/document/IJSPCSSNode.java
@@ -0,0 +1,19 @@
+/*******************************************************************************
+ * Copyright (c) 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jst.jsp.css.core.internal.document;
+import org.eclipse.wst.css.core.internal.provisional.document.ICSSNode;
+
+
+public interface IJSPCSSNode extends ICSSNode {
+	short JSP_NODE = 16;
+	String getCssText();
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/css/core/internal/document/JSPCSSImportRuleImpl.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/css/core/internal/document/JSPCSSImportRuleImpl.java
new file mode 100644
index 0000000..9e9dd13
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/css/core/internal/document/JSPCSSImportRuleImpl.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jst.jsp.css.core.internal.document;
+
+import org.eclipse.wst.css.core.internal.document.CSSImportRuleImpl;
+import org.eclipse.wst.css.core.internal.provisional.document.ICSSNode;
+import org.eclipse.wst.css.core.internal.util.CSSUtil;
+
+public class JSPCSSImportRuleImpl extends CSSImportRuleImpl implements IJSPCSSImportRule {
+
+	JSPCSSImportRuleImpl() {
+		super();
+	}
+	
+	JSPCSSImportRuleImpl(JSPCSSImportRuleImpl that) {
+		super(that);
+	}
+
+	
+	public ICSSNode cloneNode(boolean deep) {
+		JSPCSSImportRuleImpl cloned = new JSPCSSImportRuleImpl(this);
+
+		if (deep)
+			cloneChildNodes(cloned, deep);
+
+		return cloned;
+	}
+	public String getHref() {
+		return getAttribute(HREF);
+	}
+
+	public void setAttribute(String name, String value) {
+		if (HREF.equals(name)){
+			value = CSSUtil.extractUriContents(value);
+		}
+		super.setAttribute(name, value);
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/css/core/internal/document/JSPCSSNodeImpl.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/css/core/internal/document/JSPCSSNodeImpl.java
new file mode 100644
index 0000000..d2ba70c
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/css/core/internal/document/JSPCSSNodeImpl.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jst.jsp.css.core.internal.document;
+
+
+import org.eclipse.wst.css.core.internal.document.CSSStructuredDocumentRegionContainer;
+import org.eclipse.wst.css.core.internal.provisional.document.ICSSNode;
+
+
+class JSPCSSNodeImpl extends CSSStructuredDocumentRegionContainer implements IJSPCSSNode {
+
+
+	private String fText;
+
+	JSPCSSNodeImpl(JSPCSSNodeImpl that) {
+		super(that);
+
+	}
+
+	JSPCSSNodeImpl(String text) {
+		super();
+		fText = text;
+	}
+	
+	public ICSSNode cloneNode(boolean deep) {
+		JSPCSSNodeImpl cloned = new JSPCSSNodeImpl(this);
+
+		if (deep)
+			cloneChildNodes(cloned, deep);
+
+		return cloned;
+	}
+
+	public short getNodeType() {
+		return JSP_NODE;
+	}
+
+	public String getCssText() {
+		return fText;
+	}
+
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/css/core/internal/document/JSPedCSSModelImpl.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/css/core/internal/document/JSPedCSSModelImpl.java
new file mode 100644
index 0000000..e4da0fe
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/css/core/internal/document/JSPedCSSModelImpl.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jst.jsp.css.core.internal.document;
+
+import org.eclipse.wst.css.core.internal.document.CSSModelImpl;
+import org.eclipse.wst.css.core.internal.document.CSSModelParser;
+
+public class JSPedCSSModelImpl extends CSSModelImpl {
+	private JSPedCSSModelParser fParser;
+	
+	protected CSSModelParser getParser() {
+		if (fParser == null) {
+			if (getDocument() != null) {
+				fParser = new JSPedCSSModelParser(getDocument());
+			}
+		}
+		return fParser;
+	}
+
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/css/core/internal/document/JSPedCSSModelParser.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/css/core/internal/document/JSPedCSSModelParser.java
new file mode 100644
index 0000000..0aa723f
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/css/core/internal/document/JSPedCSSModelParser.java
@@ -0,0 +1,162 @@
+/*******************************************************************************
+ * Copyright (c) 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jst.jsp.css.core.internal.document;
+
+import java.util.regex.Pattern;
+
+import org.eclipse.jst.jsp.css.core.internal.parserz.JSPedCSSRegionContexts;
+import org.eclipse.wst.css.core.internal.document.CSSModelCreationContext;
+import org.eclipse.wst.css.core.internal.document.CSSModelParser;
+import org.eclipse.wst.css.core.internal.document.CSSNodeImpl;
+import org.eclipse.wst.css.core.internal.document.CSSStructuredDocumentRegionContainer;
+import org.eclipse.wst.css.core.internal.provisional.document.ICSSDocument;
+import org.eclipse.wst.css.core.internal.provisional.document.ICSSRuleContainer;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.internal.text.BasicStructuredDocumentRegion;
+
+
+/**
+ * 
+ */
+class JSPedCSSModelParser extends CSSModelParser {
+
+	public JSPedCSSModelParser(ICSSDocument doc) {
+		super(doc);
+	}
+	/**
+	 * 
+	 */
+	protected CSSNodeImpl insertStructuredDocumentRegion(IStructuredDocumentRegion region) {
+		CSSModelCreationContext creationContext = getCreationContext();
+		if (creationContext == null || region == null) {
+			return null;
+		}
+
+		String type = ((BasicStructuredDocumentRegion) region).getType();
+		CSSNodeImpl modified = null;
+
+		//ICSSNode target = fCreationContext.getTargetNode();
+		
+		if (type == JSPedCSSRegionContexts.CSS_JSP_DIRECTIVE){
+			
+			boolean isInclude = region.getText().indexOf("include") != -1;
+			if (isInclude){
+				modified = insertUnknownImport(region);
+			} else {
+				modified = insertUnknownRule(region);					
+			}
+		}
+
+		// post process
+		if (modified != null) {
+			if (modified instanceof CSSStructuredDocumentRegionContainer) {
+				((CSSStructuredDocumentRegionContainer) modified).propagateRangeStructuredDocumentRegion();
+			}
+		}
+
+		return modified != null ? modified : super.insertStructuredDocumentRegion(region);
+	}
+
+	private CSSNodeImpl insertUnknownImport(IStructuredDocumentRegion region) {
+		CSSModelCreationContext creationContext = getCreationContext();
+		CSSNodeImpl parent = creationContext.getTargetNode();
+		ICSSDocument sheet = parent.getOwnerDocument();
+		
+		String text = region.getText();
+		Pattern pattern = Pattern.compile(" ");
+	    String[] strs = pattern.split(text);
+	    String hrefValue = null;
+	    for (int i=0;i<strs.length;i++) {
+	    	String hrefStr = "file=\"";
+	      if (strs[i].startsWith(hrefStr)){
+				int hrefStr_length = hrefStr.length();
+				// minus 1 to avoid quote?
+				int hrefValue_length = strs[i].length() - 1;
+				if (hrefValue_length > hrefStr_length) {
+					hrefValue = strs[i].substring(hrefStr_length, hrefValue_length);
+				}
+				else {
+					/*
+					 * ISSUE: this handles cases where, e.g. "file=" has no
+					 * subsequent 'value' ... and from code in insertStructuredDocumentRegion
+					 * I believe should return null, rather than empty string, but, this may 
+					 * need some fine tuning eventually.
+					 */
+					hrefValue = null;
+				}
+	    	  break;
+	      }
+	    }
+		
+		if (hrefValue == null) {
+			return null;
+		}
+
+		JSPCSSImportRuleImpl rule = new JSPCSSImportRuleImpl();
+		rule.setOwnerDocument(sheet);
+		rule.appendChild((CSSNodeImpl)sheet.createMediaList());
+		rule.setRangeStructuredDocumentRegion(region, region);
+
+		
+		if (!isUpdateContextActive()) {
+			rule.setHref(hrefValue);//Attribute(ICSSImportRule.HREF, hrefValue);
+		}
+
+
+		// insert to tree
+		if (!isUpdateContextActive() && parent != null) {
+			//propagateRangePreInsert(sheet, rule);
+			CSSNodeImpl next = creationContext.getNextNode();
+			if (next != null) {
+				((CSSNodeImpl)sheet).insertBefore(rule, next);
+			}
+			else {
+				((CSSNodeImpl)sheet).appendChild(rule);
+			}
+		}
+		//creationContext.setTargetNode(rule);
+		return rule;
+	}
+
+	private CSSNodeImpl insertUnknownRule(IStructuredDocumentRegion flatNode) {
+		CSSModelCreationContext creationContext = getCreationContext();
+		CSSNodeImpl parent = creationContext.getTargetNode();
+		if (!isParseFloating() && !(parent instanceof ICSSRuleContainer)) {
+			return null;
+		}
+
+		JSPCSSNodeImpl rule = new JSPCSSNodeImpl(flatNode.getText());
+		rule.setOwnerDocument(parent.getOwnerDocument());
+
+		// setup flat container
+		rule.setRangeStructuredDocumentRegion(flatNode, flatNode);
+
+
+		// insert to tree
+		if (!isUpdateContextActive() && parent != null) {
+			propagateRangePreInsert(parent, rule);
+			CSSNodeImpl next = creationContext.getNextNode();
+			if (next != null) {
+				parent.insertBefore(rule, next);
+			}
+			else {
+				parent.appendChild(rule);
+			}
+		}
+
+		//creationContext.setTargetNode(parent.getOwnerDocument());
+		// TargetNext is set to null automatically
+
+		return rule;
+	}
+
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/css/core/internal/encoding/JSPedCSSDocumentLoader.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/css/core/internal/encoding/JSPedCSSDocumentLoader.java
new file mode 100644
index 0000000..b87ca7a
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/css/core/internal/encoding/JSPedCSSDocumentLoader.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jst.jsp.css.core.internal.encoding;
+
+import org.eclipse.jst.jsp.css.core.internal.parser.JSPedCSSSourceParser;
+import org.eclipse.wst.css.core.internal.encoding.CSSDocumentLoader;
+import org.eclipse.wst.sse.core.internal.document.IDocumentLoader;
+import org.eclipse.wst.sse.core.internal.ltk.parser.RegionParser;
+
+public class JSPedCSSDocumentLoader extends CSSDocumentLoader {
+public RegionParser getParser() {
+	return new JSPedCSSSourceParser();
+}
+public IDocumentLoader newInstance() {
+	return new JSPedCSSDocumentLoader();
+}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/css/core/internal/modelhandler/JSPedCSSModelLoader.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/css/core/internal/modelhandler/JSPedCSSModelLoader.java
new file mode 100644
index 0000000..60914b5
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/css/core/internal/modelhandler/JSPedCSSModelLoader.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jst.jsp.css.core.internal.modelhandler;
+
+import org.eclipse.jst.jsp.css.core.internal.document.JSPedCSSModelImpl;
+import org.eclipse.jst.jsp.css.core.internal.encoding.JSPedCSSDocumentLoader;
+import org.eclipse.wst.css.core.internal.modelhandler.CSSModelLoader;
+import org.eclipse.wst.sse.core.internal.document.IDocumentLoader;
+import org.eclipse.wst.sse.core.internal.provisional.IModelLoader;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+
+
+public class JSPedCSSModelLoader extends CSSModelLoader {
+public IStructuredModel newModel() {
+	IStructuredModel model = new JSPedCSSModelImpl();
+	return model;
+}
+public IModelLoader newInstance() {
+	return new JSPedCSSModelLoader();
+}
+public IDocumentLoader getDocumentLoader() {
+	if (documentLoaderInstance == null) {
+		documentLoaderInstance = new JSPedCSSDocumentLoader();
+	}
+	return documentLoaderInstance;
+}
+
+
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/css/core/internal/modelhandler/ModelHandlerForJSPedCSS.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/css/core/internal/modelhandler/ModelHandlerForJSPedCSS.java
new file mode 100644
index 0000000..67d1c2b
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/css/core/internal/modelhandler/ModelHandlerForJSPedCSS.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jst.jsp.css.core.internal.modelhandler;
+
+import org.eclipse.jst.jsp.css.core.internal.encoding.JSPedCSSDocumentLoader;
+import org.eclipse.wst.css.core.internal.encoding.CSSDocumentCharsetDetector;
+import org.eclipse.wst.sse.core.internal.document.IDocumentCharsetDetector;
+import org.eclipse.wst.sse.core.internal.document.IDocumentLoader;
+import org.eclipse.wst.sse.core.internal.ltk.modelhandler.AbstractModelHandler;
+import org.eclipse.wst.sse.core.internal.ltk.modelhandler.IModelHandler;
+import org.eclipse.wst.sse.core.internal.provisional.IModelLoader;
+
+
+public class ModelHandlerForJSPedCSS extends AbstractModelHandler implements IModelHandler {
+	static String AssociatedContentTypeID = "org.eclipse.jst.jsp.core.cssjspsource"; //$NON-NLS-1$
+	
+	private static String ModelHandlerID = "org.eclipse.jst.jsp.css.core.modelhandler"; //$NON-NLS-1$
+	public ModelHandlerForJSPedCSS(){
+		super();
+		setId(ModelHandlerID);
+		setAssociatedContentTypeId(AssociatedContentTypeID);
+	}
+	
+	public IModelLoader getModelLoader() {
+		return new JSPedCSSModelLoader();
+	}
+	
+	public IDocumentCharsetDetector getEncodingDetector() {
+		return new CSSDocumentCharsetDetector();
+	}
+
+	public IDocumentLoader getDocumentLoader() {
+		return new JSPedCSSDocumentLoader();
+	}
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/css/core/internal/parser/JSPedCSSSourceParser.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/css/core/internal/parser/JSPedCSSSourceParser.java
new file mode 100644
index 0000000..762a8a4
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/css/core/internal/parser/JSPedCSSSourceParser.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.css.core.internal.parser;
+
+import org.eclipse.jst.jsp.css.core.internal.parserz.JSPedCSSRegionContexts;
+import org.eclipse.wst.css.core.internal.parser.CSSRegionUtil;
+import org.eclipse.wst.css.core.internal.parser.CSSSourceParser;
+import org.eclipse.wst.css.core.internal.parser.ICSSTokenizer;
+import org.eclipse.wst.css.core.internal.parserz.CSSRegionContexts;
+import org.eclipse.wst.sse.core.internal.ltk.parser.RegionParser;
+
+
+public class JSPedCSSSourceParser extends CSSSourceParser {
+
+	private JSPedCSSTokenizer fTokenizer;
+	protected boolean mustBeStart(String type, String docRegionType) {
+		return ((type == JSPedCSSRegionContexts.CSS_JSP_COMMENT || type == JSPedCSSRegionContexts.CSS_JSP_DIRECTIVE || type == JSPedCSSRegionContexts.CSS_JSP_END || type == CSSRegionContexts.CSS_DELIMITER || type == CSSRegionContexts.CSS_LBRACE || type == CSSRegionContexts.CSS_RBRACE || type == CSSRegionContexts.CSS_IMPORT || type == CSSRegionContexts.CSS_PAGE || type == CSSRegionContexts.CSS_MEDIA || type == CSSRegionContexts.CSS_FONT_FACE || type == CSSRegionContexts.CSS_CHARSET || type == CSSRegionContexts.CSS_ATKEYWORD || type == CSSRegionContexts.CSS_DECLARATION_PROPERTY || type == CSSRegionContexts.CSS_DECLARATION_DELIMITER) || (docRegionType == CSSRegionContexts.CSS_DECLARATION_PROPERTY && type == CSSRegionContexts.CSS_S) || (!CSSRegionUtil.isSelectorBegginingType(docRegionType) && (type == CSSRegionContexts.CSS_SELECTOR_ELEMENT_NAME || type == CSSRegionContexts.CSS_SELECTOR_UNIVERSAL || type == CSSRegionContexts.CSS_SELECTOR_PSEUDO || type == CSSRegionContexts.CSS_SELECTOR_CLASS || type == CSSRegionContexts.CSS_SELECTOR_ID || type == CSSRegionContexts.CSS_SELECTOR_ATTRIBUTE_START)));
+	}
+
+	protected boolean mustBeEnd(String type) {
+		return (type == JSPedCSSRegionContexts.CSS_JSP_COMMENT || type == JSPedCSSRegionContexts.CSS_JSP_DIRECTIVE || type == JSPedCSSRegionContexts.CSS_JSP_END || type == CSSRegionContexts.CSS_DELIMITER || type == CSSRegionContexts.CSS_LBRACE || type == CSSRegionContexts.CSS_RBRACE || type == CSSRegionContexts.CSS_DECLARATION_DELIMITER);
+	}
+	
+	public ICSSTokenizer getTokenizer() {
+		if (fTokenizer == null) {
+			fTokenizer = new JSPedCSSTokenizer();
+		}
+		return fTokenizer;
+	}
+	
+	public RegionParser newInstance() {
+		return new JSPedCSSSourceParser();
+	}
+	
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/css/core/internal/parser/JSPedCSSTokenizer.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/css/core/internal/parser/JSPedCSSTokenizer.java
new file mode 100644
index 0000000..ddb22e7
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/css/core/internal/parser/JSPedCSSTokenizer.java
@@ -0,0 +1,2078 @@
+/* The following code was generated by JFlex 1.4.1 on 7/22/08 10:30 AM */
+
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.jsp.css.core.internal.parser;
+
+import java.io.CharArrayReader;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jst.jsp.css.core.internal.parserz.JSPedCSSRegionContexts;
+import org.eclipse.wst.css.core.internal.parser.CSSRegionUtil;
+import org.eclipse.wst.css.core.internal.parser.ICSSTokenizer;
+import org.eclipse.wst.css.core.internal.parser.regions.CSSTextRegionFactory;
+import org.eclipse.wst.css.core.internal.parserz.CSSTextToken;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+
+
+/**
+ * This class is a scanner generated by 
+ * <a href="http://www.jflex.de/">JFlex</a> 1.4.1
+ * on 7/22/08 10:30 AM from the specification file
+ * <tt>D:/workspaces/wtp301/workspace/org.eclipse.jst.jsp.core/DevTimeSupport/CSSJSPParser/JSPedCSSTokenizer.flex</tt>
+ */
+public class JSPedCSSTokenizer implements JSPedCSSRegionContexts, ICSSTokenizer {
+
+  /** This character denotes the end of file */
+  public static final int YYEOF = -1;
+
+  /** initial size of the lookahead buffer */
+  private static final int ZZ_BUFFERSIZE = 16384;
+
+  /** lexical states */
+  public static final int ST_JSP_EXP = 21;
+  public static final int ST_JSP_DIRECTIVE = 21;
+  public static final int ST_SELECTOR_ATTRIBUTE_NAME = 12;
+  public static final int ST_IMPORT_DELIMITER = 5;
+  public static final int ST_DECLARATION_PRE_VALUE = 18;
+  public static final int ST_SELECTOR = 10;
+  public static final int ST_CHARSET_DELIMITER = 2;
+  public static final int ST_DECLARATION_VALUE = 19;
+  public static final int ST_PAGE_PSEUDO_PAGE = 8;
+  public static final int ST_IMPORT_URI = 3;
+  public static final int ST_SELECTOR_ATTRIBUTE_END = 15;
+  public static final int ST_JSP_EL = 22;
+  public static final int ST_SELECTOR_ATTRIBUTE_OPERATOR = 13;
+  public static final int ST_JSP_DECLARATION = 21;
+  public static final int ST_DECLARATION = 16;
+  public static final int ST_PAGE_DELIMITER = 9;
+  public static final int ST_SELECTOR_ATTRIBUTE_VALUE = 14;
+  public static final int ST_MEDIA_MEDIUM = 6;
+  public static final int ST_JSP_SCRIPTLET = 20;
+  public static final int ST_CHARSET_NAME = 1;
+  public static final int ST_JSP_COMMENT = 23;
+  public static final int ST_IMPORT_MEDIUM = 4;
+  public static final int ST_DECLARATION_SEPARATOR = 17;
+  public static final int ST_FONT_FACE_DELIMITER = 9;
+  public static final int ST_MEDIA_DELIMITER = 7;
+  public static final int ST_SELECTOR_MODIFIER = 11;
+  public static final int YYINITIAL = 0;
+
+  /** 
+   * Translates characters to character classes
+   */
+  private static final String ZZ_CMAP_PACKED = 
+    "\11\0\1\11\1\17\1\0\1\4\1\20\22\0\1\6\1\40\1\10"+
+    "\1\22\1\33\1\31\1\16\1\5\1\26\1\12\1\42\1\14\1\61"+
+    "\1\13\1\15\1\41\12\1\1\65\1\54\1\30\1\37\1\32\1\21"+
+    "\1\36\1\47\1\27\1\44\1\63\1\52\1\67\1\64\1\45\1\55"+
+    "\2\2\1\25\1\56\1\70\1\60\1\57\1\2\1\24\1\50\1\53"+
+    "\1\23\5\2\1\71\1\3\1\73\1\16\1\2\1\16\1\46\1\7"+
+    "\1\43\1\62\1\51\1\66\1\64\1\45\1\55\2\2\1\25\1\56"+
+    "\1\70\1\60\1\57\1\2\1\24\1\50\1\53\1\23\5\2\1\34"+
+    "\1\72\1\35\1\72\1\0\uff80\2";
+
+  /** 
+   * Translates characters to character classes
+   */
+  private static final char [] ZZ_CMAP = zzUnpackCMap(ZZ_CMAP_PACKED);
+
+  /** 
+   * Translates DFA states to action switch labels.
+   */
+  private static final int [] ZZ_ACTION = zzUnpackAction();
+
+  private static final String ZZ_ACTION_PACKED_0 =
+    "\30\0\1\1\1\2\1\1\1\3\1\2\4\1\1\4"+
+    "\2\1\1\5\1\1\1\6\4\1\1\7\3\1\1\10"+
+    "\1\1\1\10\1\11\1\12\1\1\1\12\1\13\1\14"+
+    "\1\15\1\1\1\15\1\16\1\1\1\3\1\17\1\20"+
+    "\1\21\1\1\1\21\1\22\1\1\1\23\1\24\3\1"+
+    "\1\24\1\25\1\1\1\25\1\26\1\27\1\30\1\31"+
+    "\3\1\1\32\1\31\3\1\1\31\1\1\2\33\1\3"+
+    "\2\1\1\34\1\35\1\36\1\37\1\1\1\0\2\2"+
+    "\1\40\1\0\1\41\2\0\1\42\2\0\1\43\6\0"+
+    "\1\44\3\0\1\45\5\0\1\46\4\0\2\10\1\0"+
+    "\2\12\1\0\2\15\1\17\1\0\2\21\1\0\1\24"+
+    "\2\0\1\24\2\0\1\24\1\0\2\25\1\47\2\0"+
+    "\1\50\1\0\1\51\1\31\2\0\1\52\2\0\2\31"+
+    "\1\30\1\53\2\0\1\31\2\0\1\54\1\55\1\0"+
+    "\1\56\1\0\1\2\1\57\1\40\1\41\10\0\1\44"+
+    "\1\0\1\45\2\0\1\45\2\0\1\46\2\0\1\46"+
+    "\2\0\1\10\1\12\1\15\1\21\1\24\1\0\1\24"+
+    "\2\0\1\24\1\0\1\25\1\47\1\31\1\0\1\52"+
+    "\2\0\1\52\1\0\1\53\1\60\1\31\3\0\1\2"+
+    "\1\40\1\41\1\61\5\0\1\62\2\0\1\44\5\0"+
+    "\1\10\1\12\1\15\1\21\1\24\2\0\1\25\1\47"+
+    "\1\31\2\0\1\53\1\60\1\0\1\51\1\0\1\63"+
+    "\1\2\1\40\1\41\3\0\1\64\2\0\1\44\1\0"+
+    "\1\44\10\0\1\65\1\10\1\12\1\15\1\21\1\24"+
+    "\2\0\1\25\1\47\1\31\2\0\1\53\2\60\5\0"+
+    "\1\66\1\0\1\2\1\40\1\41\2\0\1\67\2\0"+
+    "\1\44\6\0\1\65\2\0\1\10\1\12\1\15\1\21"+
+    "\1\24\2\0\1\25\1\47\1\31\2\0\1\53\2\60"+
+    "\2\0\1\66\3\0\1\2\1\40\1\41\1\0\1\70"+
+    "\2\0\1\44\13\0\1\10\1\12\1\15\1\21\1\24"+
+    "\2\0\1\25\1\47\1\31\2\0\1\53\2\60\10\0"+
+    "\1\40\1\41\1\71\2\0\1\44\6\0\1\65\1\0"+
+    "\1\65\2\0\1\47\2\0\1\53\2\60\2\0\1\66"+
+    "\1\0\1\66\6\0\1\60\4\0\1\72\4\0\1\60"+
+    "\3\0\1\73\12\0";
+
+  private static int [] zzUnpackAction() {
+    int [] result = new int[455];
+    int offset = 0;
+    offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result);
+    return result;
+  }
+
+  private static int zzUnpackAction(String packed, int offset, int [] result) {
+    int i = 0;       /* index in packed string  */
+    int j = offset;  /* index in unpacked array */
+    int l = packed.length();
+    while (i < l) {
+      int count = packed.charAt(i++);
+      int value = packed.charAt(i++);
+      do result[j++] = value; while (--count > 0);
+    }
+    return j;
+  }
+
+
+  /** 
+   * Translates a state to a row index in the transition table
+   */
+  private static final int [] ZZ_ROWMAP = zzUnpackRowMap();
+
+  private static final String ZZ_ROWMAP_PACKED_0 =
+    "\0\0\0\74\0\170\0\264\0\360\0\u012c\0\u0168\0\u01a4"+
+    "\0\u01e0\0\u021c\0\u0258\0\u0294\0\u02d0\0\u030c\0\u0348\0\u0384"+
+    "\0\u03c0\0\u03fc\0\u0438\0\u0474\0\u04b0\0\u04ec\0\u0528\0\u0564"+
+    "\0\u05a0\0\u05dc\0\u0618\0\u0654\0\u0690\0\u06cc\0\u0708\0\u0744"+
+    "\0\u0780\0\u05a0\0\u07bc\0\u07f8\0\u05a0\0\u0834\0\u05a0\0\u0870"+
+    "\0\u08ac\0\u08e8\0\u0924\0\u05a0\0\u0960\0\u099c\0\u09d8\0\u0a14"+
+    "\0\u0a50\0\u0a8c\0\u05a0\0\u0ac8\0\u0b04\0\u0b40\0\u05a0\0\u05a0"+
+    "\0\u0b7c\0\u0bb8\0\u0bf4\0\u05a0\0\u0c30\0\u0c6c\0\u05a0\0\u05a0"+
+    "\0\u0ca8\0\u0ce4\0\u0d20\0\u05a0\0\u0d5c\0\u05a0\0\u0d98\0\u0dd4"+
+    "\0\u0e10\0\u0e4c\0\u0e88\0\u0ec4\0\u0f00\0\u0f3c\0\u05a0\0\u05a0"+
+    "\0\u0f78\0\u0fb4\0\u0ff0\0\u102c\0\u1068\0\u05a0\0\u10a4\0\u10e0"+
+    "\0\u111c\0\u1158\0\u1194\0\u11d0\0\u07f8\0\u05a0\0\u120c\0\u1248"+
+    "\0\u1284\0\u07bc\0\u05a0\0\u05a0\0\u05a0\0\u12c0\0\u0618\0\u12fc"+
+    "\0\u1338\0\u06cc\0\u1374\0\u0708\0\u13b0\0\u13ec\0\u1428\0\u1464"+
+    "\0\u0780\0\u05a0\0\u14a0\0\u14dc\0\u1518\0\u1554\0\u1590\0\u15cc"+
+    "\0\u1608\0\u1644\0\u0870\0\u1680\0\u05a0\0\u08ac\0\u16bc\0\u16f8"+
+    "\0\u0960\0\u1734\0\u05a0\0\u099c\0\u1770\0\u17ac\0\u0a50\0\u17e8"+
+    "\0\u1824\0\u0b04\0\u1860\0\u189c\0\u0bb8\0\u18d8\0\u1914\0\u05a0"+
+    "\0\u0ce4\0\u1950\0\u198c\0\u0dd4\0\u19c8\0\u0e10\0\u1a04\0\u05a0"+
+    "\0\u0e4c\0\u1a40\0\u1a7c\0\u0f00\0\u1ab8\0\u1af4\0\u1b30\0\u1b6c"+
+    "\0\u111c\0\u05a0\0\u0ff0\0\u05a0\0\u1ba8\0\u102c\0\u1be4\0\u05a0"+
+    "\0\u1068\0\u1c20\0\u1c5c\0\u1c98\0\u1cd4\0\u1158\0\u1d10\0\u1d4c"+
+    "\0\u1d88\0\u11d0\0\u1dc4\0\u05a0\0\u16f8\0\u1284\0\u05a0\0\u1e00"+
+    "\0\u1e3c\0\u05a0\0\u1e78\0\u1eb4\0\u1ef0\0\u1f2c\0\u1f68\0\u1fa4"+
+    "\0\u1fe0\0\u201c\0\u2058\0\u2094\0\u20d0\0\u210c\0\u0870\0\u2148"+
+    "\0\u2184\0\u08ac\0\u21c0\0\u21fc\0\u0960\0\u2238\0\u2274\0\u099c"+
+    "\0\u22b0\0\u22ec\0\u2328\0\u2364\0\u23a0\0\u23dc\0\u2418\0\u2454"+
+    "\0\u0e10\0\u2490\0\u24cc\0\u0e4c\0\u2508\0\u2544\0\u2580\0\u25bc"+
+    "\0\u25f8\0\u102c\0\u2634\0\u2670\0\u1068\0\u26ac\0\u26e8\0\u2724"+
+    "\0\u2760\0\u279c\0\u27d8\0\u2814\0\u2850\0\u288c\0\u28c8\0\u05a0"+
+    "\0\u2904\0\u2940\0\u297c\0\u29b8\0\u29f4\0\u05a0\0\u2a30\0\u2a6c"+
+    "\0\u2aa8\0\u2ae4\0\u2b20\0\u2b5c\0\u2b98\0\u2bd4\0\u2c10\0\u2c4c"+
+    "\0\u2c88\0\u2cc4\0\u2d00\0\u2d3c\0\u2d78\0\u2db4\0\u2df0\0\u2e2c"+
+    "\0\u2e68\0\u2ea4\0\u2ee0\0\u2f1c\0\u2f58\0\u2f94\0\u2fd0\0\u05a0"+
+    "\0\u300c\0\u3048\0\u3084\0\u30c0\0\u30fc\0\u3138\0\u05a0\0\u3174"+
+    "\0\u31b0\0\u05a0\0\u31ec\0\u3228\0\u3264\0\u32a0\0\u32dc\0\u3318"+
+    "\0\u3354\0\u3390\0\u33cc\0\u3408\0\u05a0\0\u3444\0\u3480\0\u34bc"+
+    "\0\u34f8\0\u3534\0\u3570\0\u35ac\0\u35e8\0\u3624\0\u3660\0\u369c"+
+    "\0\u36d8\0\u3714\0\u3750\0\u378c\0\u37c8\0\u3804\0\u2f94\0\u3840"+
+    "\0\u387c\0\u05a0\0\u38b8\0\u38f4\0\u3930\0\u396c\0\u39a8\0\u39e4"+
+    "\0\u05a0\0\u3a20\0\u3a5c\0\u3a98\0\u3ad4\0\u3b10\0\u3b4c\0\u3b88"+
+    "\0\u3bc4\0\u3c00\0\u3354\0\u3c3c\0\u3c78\0\u3cb4\0\u3cf0\0\u3d2c"+
+    "\0\u3d68\0\u3da4\0\u3de0\0\u3e1c\0\u3e58\0\u3e94\0\u3ed0\0\u3f0c"+
+    "\0\u3f48\0\u3f84\0\u3fc0\0\u3ffc\0\u4038\0\u4074\0\u37c8\0\u40b0"+
+    "\0\u40ec\0\u4128\0\u4164\0\u41a0\0\u41dc\0\u4218\0\u05a0\0\u4254"+
+    "\0\u4290\0\u42cc\0\u4308\0\u4344\0\u4380\0\u43bc\0\u43f8\0\u4434"+
+    "\0\u4470\0\u44ac\0\u44e8\0\u4524\0\u4560\0\u459c\0\u45d8\0\u4614"+
+    "\0\u4650\0\u468c\0\u46c8\0\u4704\0\u4740\0\u477c\0\u47b8\0\u47f4"+
+    "\0\u4830\0\u486c\0\u48a8\0\u48e4\0\u4920\0\u495c\0\u4998\0\u49d4"+
+    "\0\u4a10\0\u4a4c\0\u4a88\0\u4ac4\0\u4b00\0\u4b3c\0\u05a0\0\u4b78"+
+    "\0\u4bb4\0\u4bf0\0\u4c2c\0\u4c68\0\u4ca4\0\u4ce0\0\u4d1c\0\u4d58"+
+    "\0\u33cc\0\u4d94\0\u3408\0\u4dd0\0\u4e0c\0\u4e48\0\u4e84\0\u4ec0"+
+    "\0\u4efc\0\u4f38\0\u4f74\0\u4fb0\0\u4fec\0\u3840\0\u5028\0\u387c"+
+    "\0\u5064\0\u50a0\0\u50dc\0\u5118\0\u5154\0\u5190\0\u51cc\0\u5208"+
+    "\0\u5244\0\u5280\0\u52bc\0\u05a0\0\u52f8\0\u5334\0\u5370\0\u53ac"+
+    "\0\u05a0\0\u53e8\0\u5424\0\u5460\0\u05a0\0\u549c\0\u54d8\0\u5514"+
+    "\0\u5550\0\u558c\0\u55c8\0\u5604\0\u5640\0\u567c\0\u56b8";
+
+  private static int [] zzUnpackRowMap() {
+    int [] result = new int[455];
+    int offset = 0;
+    offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result);
+    return result;
+  }
+
+  private static int zzUnpackRowMap(String packed, int offset, int [] result) {
+    int i = 0;  /* index in packed string  */
+    int j = offset;  /* index in unpacked array */
+    int l = packed.length();
+    while (i < l) {
+      int high = packed.charAt(i++) << 16;
+      result[j++] = high | packed.charAt(i++);
+    }
+    return j;
+  }
+
+  /** 
+   * The transition table of the DFA
+   */
+  private static final int [] ZZ_TRANS = zzUnpackTrans();
+
+  private static final String ZZ_TRANS_PACKED_0 =
+    "\2\31\1\32\1\33\1\34\1\31\1\34\1\32\1\31"+
+    "\1\34\1\31\1\35\1\31\1\36\1\31\2\34\1\31"+
+    "\1\37\3\32\1\31\1\32\1\40\2\31\1\41\1\31"+
+    "\1\42\1\43\2\31\1\44\1\45\11\32\1\31\4\32"+
+    "\1\31\3\32\1\46\3\32\1\47\6\31\1\34\1\50"+
+    "\1\34\1\31\1\51\1\34\1\31\1\52\3\31\2\34"+
+    "\7\31\1\53\4\31\1\42\1\43\2\31\1\44\36\31"+
+    "\1\34\1\31\1\34\2\31\1\34\1\31\1\52\3\31"+
+    "\2\34\7\31\1\53\4\31\1\42\1\43\2\31\1\44"+
+    "\12\31\1\54\23\31\1\34\1\55\1\34\1\31\1\56"+
+    "\1\34\1\31\1\52\3\31\2\34\2\31\1\57\4\31"+
+    "\1\53\4\31\1\42\1\43\2\31\1\44\12\31\1\54"+
+    "\21\31\1\60\1\61\1\34\1\31\1\34\1\60\1\31"+
+    "\1\34\1\31\1\62\3\31\2\34\2\31\3\60\1\31"+
+    "\1\60\1\53\4\31\1\42\1\43\2\31\1\44\1\31"+
+    "\11\60\1\54\4\60\1\31\3\60\1\31\3\60\7\31"+
+    "\1\34\1\31\1\34\2\31\1\34\1\31\1\52\3\31"+
+    "\2\34\7\31\1\53\4\31\1\42\1\43\2\31\1\44"+
+    "\12\31\1\54\4\31\1\63\14\31\1\64\1\65\1\34"+
+    "\1\31\1\34\1\64\1\31\1\34\1\31\1\66\3\31"+
+    "\2\34\2\31\3\64\1\31\1\64\1\53\4\31\1\42"+
+    "\1\43\2\31\1\44\1\31\11\64\1\31\4\64\1\31"+
+    "\3\64\1\31\3\64\7\31\1\34\1\31\1\34\2\31"+
+    "\1\34\1\31\1\52\3\31\2\34\7\31\1\53\3\31"+
+    "\1\67\1\42\1\43\2\31\1\44\17\31\1\70\14\31"+
+    "\1\71\1\72\1\34\1\31\1\34\1\71\1\31\1\34"+
+    "\1\31\1\73\3\31\2\34\2\31\3\71\1\31\1\71"+
+    "\1\53\3\31\1\74\1\42\1\43\2\31\1\44\1\31"+
+    "\11\71\1\31\4\71\1\31\3\71\1\75\3\71\7\31"+
+    "\1\34\1\31\1\34\2\31\1\34\1\31\1\52\3\31"+
+    "\2\34\7\31\1\53\3\31\1\74\1\42\1\43\2\31"+
+    "\1\44\34\31\1\32\1\33\1\34\1\31\1\34\1\32"+
+    "\1\31\1\34\1\31\1\35\1\31\1\36\1\31\2\34"+
+    "\1\31\1\37\3\32\1\31\1\32\1\53\4\31\1\42"+
+    "\1\43\2\31\1\44\1\45\11\32\1\31\4\32\1\31"+
+    "\3\32\1\46\3\32\1\47\6\31\1\76\1\31\1\76"+
+    "\2\31\1\76\1\31\1\52\1\77\1\36\1\31\2\76"+
+    "\1\31\1\37\5\31\1\53\1\31\1\77\1\31\1\74"+
+    "\1\42\1\43\2\31\1\44\1\45\16\31\1\100\3\31"+
+    "\1\46\3\31\1\47\4\31\1\101\1\102\1\34\1\31"+
+    "\1\34\1\101\1\31\1\34\1\31\1\103\3\31\2\34"+
+    "\2\31\3\101\1\31\1\101\1\53\4\31\1\42\1\43"+
+    "\2\31\1\44\1\31\11\101\1\31\4\101\1\31\3\101"+
+    "\1\31\3\101\7\31\1\34\1\31\1\34\2\31\1\34"+
+    "\1\31\1\52\3\31\2\34\7\31\1\53\4\31\1\42"+
+    "\1\43\1\104\1\31\1\44\30\31\1\105\1\106\2\31"+
+    "\1\107\1\110\1\34\1\111\1\34\1\107\1\112\1\34"+
+    "\1\31\1\113\3\31\2\34\2\31\3\107\1\31\1\107"+
+    "\1\53\4\31\1\42\1\43\2\31\1\44\1\31\11\107"+
+    "\1\31\4\107\1\31\3\107\1\31\3\107\7\31\1\34"+
+    "\1\31\1\34\2\31\1\34\1\31\1\52\3\31\2\34"+
+    "\7\31\1\53\4\31\1\42\1\43\2\31\1\44\31\31"+
+    "\1\106\2\31\1\114\1\115\1\34\1\31\1\34\1\114"+
+    "\1\31\1\34\1\31\1\116\3\31\2\34\2\31\3\114"+
+    "\1\31\1\114\1\40\2\31\1\41\1\31\1\42\1\43"+
+    "\2\31\1\44\1\31\11\114\1\117\4\114\1\31\3\114"+
+    "\1\31\3\114\7\31\1\34\1\31\1\34\2\31\1\34"+
+    "\1\31\1\52\3\31\2\34\7\31\1\40\2\31\1\41"+
+    "\1\31\1\42\1\43\2\31\1\44\12\31\1\117\10\31"+
+    "\1\120\7\31\1\121\1\122\1\123\1\34\1\124\1\34"+
+    "\1\122\1\125\1\34\1\126\1\127\1\130\1\131\1\31"+
+    "\2\34\1\31\1\132\1\133\2\122\1\31\1\122\1\40"+
+    "\2\31\1\41\1\31\1\42\1\43\1\31\1\134\1\135"+
+    "\1\31\11\122\1\117\4\122\1\136\3\122\1\31\3\122"+
+    "\4\31\1\121\1\122\1\123\1\137\1\124\1\137\1\122"+
+    "\1\125\1\137\1\126\1\127\1\130\1\131\1\31\2\137"+
+    "\1\31\1\132\1\133\2\122\1\31\1\122\1\40\2\31"+
+    "\1\41\1\31\1\42\1\43\1\31\1\134\1\135\1\31"+
+    "\11\122\1\117\4\122\1\136\3\122\1\31\3\122\7\31"+
+    "\1\34\1\31\1\34\2\31\1\34\1\31\1\140\3\31"+
+    "\2\34\7\31\1\53\1\141\3\31\1\42\1\142\1\143"+
+    "\1\144\1\44\36\31\1\34\1\31\1\34\2\31\1\34"+
+    "\1\31\1\52\3\31\2\34\7\31\1\53\1\141\3\31"+
+    "\1\42\1\43\2\31\1\44\36\31\1\34\1\31\1\34"+
+    "\2\31\1\34\1\31\1\52\3\31\2\34\7\31\1\53"+
+    "\4\31\1\145\1\43\2\31\1\44\36\31\1\34\1\31"+
+    "\1\34\2\31\1\34\1\31\1\146\3\31\2\34\7\31"+
+    "\1\53\5\31\1\43\2\31\1\44\32\31\75\0\2\32"+
+    "\1\147\3\0\1\32\3\0\1\32\7\0\3\32\1\0"+
+    "\1\32\13\0\11\32\1\0\4\32\1\0\3\32\1\0"+
+    "\3\32\4\0\1\150\2\32\1\0\2\32\1\150\1\32"+
+    "\1\0\5\32\2\0\22\32\1\150\2\32\1\150\2\32"+
+    "\1\150\10\32\1\150\3\32\1\150\5\32\4\0\1\34"+
+    "\1\0\1\34\2\0\1\34\5\0\2\34\54\0\2\32"+
+    "\1\147\3\0\1\32\3\0\1\151\7\0\3\32\1\0"+
+    "\1\32\13\0\11\32\1\0\4\32\1\0\3\32\1\0"+
+    "\3\32\4\0\2\152\1\153\3\0\1\152\3\0\1\152"+
+    "\7\0\3\152\1\0\1\152\13\0\11\152\1\0\4\152"+
+    "\1\0\3\152\1\0\3\152\4\0\2\154\1\155\3\0"+
+    "\1\154\3\0\1\154\7\0\3\154\1\0\1\154\13\0"+
+    "\11\154\1\0\4\154\1\0\3\154\1\0\3\154\11\0"+
+    "\1\156\2\0\1\156\5\0\2\156\10\0\1\157\6\0"+
+    "\1\160\41\0\1\161\2\0\1\161\5\0\2\161\13\0"+
+    "\1\162\102\0\2\163\10\0\1\164\1\165\1\166\6\0"+
+    "\2\167\46\0\1\170\33\0\1\171\1\172\3\0\1\171"+
+    "\3\0\1\171\7\0\3\171\1\0\1\171\13\0\11\171"+
+    "\1\0\4\171\1\0\3\171\1\0\3\171\4\0\2\173"+
+    "\1\174\1\0\1\175\11\173\2\0\53\173\1\0\2\176"+
+    "\1\177\1\0\3\176\1\175\6\176\2\0\53\176\13\0"+
+    "\1\200\120\0\1\160\34\0\2\201\1\202\1\0\1\203"+
+    "\11\201\2\0\53\201\1\0\2\204\1\205\1\0\3\204"+
+    "\1\203\6\204\2\0\53\204\24\0\1\206\50\0\2\60"+
+    "\1\207\3\0\1\60\3\0\1\60\7\0\3\60\1\0"+
+    "\1\60\13\0\11\60\1\0\4\60\1\0\3\60\1\0"+
+    "\3\60\4\0\1\210\2\60\1\0\2\60\1\210\1\60"+
+    "\1\0\5\60\2\0\22\60\1\210\2\60\1\210\2\60"+
+    "\1\210\10\60\1\210\3\60\1\210\5\60\1\0\2\60"+
+    "\1\207\3\0\1\60\3\0\1\211\7\0\3\60\1\0"+
+    "\1\60\13\0\11\60\1\0\4\60\1\0\3\60\1\0"+
+    "\3\60\4\0\2\64\1\212\3\0\1\64\3\0\1\64"+
+    "\7\0\3\64\1\0\1\64\13\0\11\64\1\0\4\64"+
+    "\1\0\3\64\1\0\3\64\4\0\1\213\2\64\1\0"+
+    "\2\64\1\213\1\64\1\0\5\64\2\0\22\64\1\213"+
+    "\2\64\1\213\2\64\1\213\10\64\1\213\3\64\1\213"+
+    "\5\64\1\0\2\64\1\212\3\0\1\64\3\0\1\214"+
+    "\7\0\3\64\1\0\1\64\13\0\11\64\1\0\4\64"+
+    "\1\0\3\64\1\0\3\64\4\0\2\71\1\215\3\0"+
+    "\1\71\3\0\1\71\7\0\3\71\1\0\1\71\13\0"+
+    "\11\71\1\0\4\71\1\0\3\71\1\0\3\71\4\0"+
+    "\1\216\2\71\1\0\2\71\1\216\1\71\1\0\5\71"+
+    "\2\0\22\71\1\216\2\71\1\216\2\71\1\216\10\71"+
+    "\1\216\3\71\1\216\5\71\1\0\2\71\1\215\3\0"+
+    "\1\71\3\0\1\217\7\0\3\71\1\0\1\71\13\0"+
+    "\11\71\1\0\4\71\1\0\3\71\1\0\3\71\5\0"+
+    "\1\71\1\215\3\0\1\71\3\0\1\71\7\0\3\71"+
+    "\1\0\1\71\13\0\11\71\1\0\4\71\1\0\3\71"+
+    "\1\0\3\71\3\0\4\220\1\76\1\220\1\76\2\220"+
+    "\1\76\2\220\1\0\2\220\2\76\11\220\1\0\1\220"+
+    "\1\0\37\220\1\0\2\101\1\221\3\0\1\101\3\0"+
+    "\1\101\7\0\3\101\1\0\1\101\13\0\11\101\1\0"+
+    "\4\101\1\0\3\101\1\0\3\101\4\0\1\222\2\101"+
+    "\1\0\2\101\1\222\1\101\1\0\5\101\2\0\22\101"+
+    "\1\222\2\101\1\222\2\101\1\222\10\101\1\222\3\101"+
+    "\1\222\5\101\1\0\2\101\1\221\3\0\1\101\3\0"+
+    "\1\223\7\0\3\101\1\0\1\101\13\0\11\101\1\0"+
+    "\4\101\1\0\3\101\1\0\3\101\42\0\1\104\35\0"+
+    "\2\107\1\224\3\0\1\107\3\0\1\107\7\0\3\107"+
+    "\1\0\1\107\13\0\11\107\1\0\4\107\1\0\3\107"+
+    "\1\0\3\107\4\0\1\225\2\107\1\0\2\107\1\225"+
+    "\1\107\1\0\5\107\2\0\22\107\1\225\2\107\1\225"+
+    "\2\107\1\225\10\107\1\225\3\107\1\225\5\107\1\0"+
+    "\2\226\1\227\1\0\1\230\11\226\2\0\53\226\1\0"+
+    "\2\231\1\232\1\0\3\231\1\230\6\231\2\0\53\231"+
+    "\1\0\2\107\1\224\3\0\1\107\3\0\1\233\7\0"+
+    "\3\107\1\0\1\107\13\0\11\107\1\0\4\107\1\0"+
+    "\3\107\1\0\3\107\4\0\2\114\1\234\3\0\1\114"+
+    "\3\0\1\114\7\0\3\114\1\0\1\114\13\0\11\114"+
+    "\1\0\4\114\1\0\3\114\1\0\3\114\4\0\1\235"+
+    "\2\114\1\0\2\114\1\235\1\114\1\0\5\114\2\0"+
+    "\22\114\1\235\2\114\1\235\2\114\1\235\10\114\1\235"+
+    "\3\114\1\235\5\114\1\0\2\114\1\234\3\0\1\114"+
+    "\3\0\1\236\7\0\3\114\1\0\1\114\13\0\11\114"+
+    "\1\0\4\114\1\0\3\114\1\0\3\114\4\0\1\121"+
+    "\1\237\1\240\3\0\1\237\3\0\1\237\1\0\1\241"+
+    "\5\0\3\237\1\0\1\237\1\0\1\242\11\0\11\237"+
+    "\1\0\4\237\1\0\3\237\1\0\3\237\4\0\2\122"+
+    "\1\243\3\0\1\122\3\0\1\122\7\0\3\122\1\244"+
+    "\1\122\13\0\11\122\1\0\4\122\1\0\3\122\1\0"+
+    "\3\122\4\0\1\245\2\122\1\0\2\122\1\245\1\122"+
+    "\1\0\5\122\2\0\22\122\1\245\2\122\1\245\2\122"+
+    "\1\245\10\122\1\245\3\122\1\245\5\122\1\0\2\246"+
+    "\1\247\1\0\1\250\11\246\2\0\53\246\1\0\2\251"+
+    "\1\252\1\0\3\251\1\250\6\251\2\0\53\251\1\0"+
+    "\1\253\1\122\1\243\3\0\1\122\3\0\1\254\1\0"+
+    "\1\241\5\0\3\122\1\244\1\122\13\0\11\122\1\0"+
+    "\4\122\1\0\3\122\1\0\3\122\4\0\1\121\13\0"+
+    "\1\241\57\0\1\255\73\0\2\256\1\257\3\0\1\256"+
+    "\3\0\1\256\7\0\3\256\1\0\1\256\13\0\11\256"+
+    "\1\0\4\256\1\0\3\256\1\0\3\256\4\0\2\122"+
+    "\1\243\3\0\1\122\3\0\1\122\1\260\6\0\1\122"+
+    "\1\261\1\122\1\244\1\122\13\0\11\122\1\0\4\122"+
+    "\1\0\3\122\1\0\3\122\7\0\1\262\1\0\1\262"+
+    "\2\0\1\262\5\0\2\262\34\0\1\263\16\0\4\264"+
+    "\1\137\1\264\1\137\2\264\1\137\5\264\2\137\14\264"+
+    "\1\0\16\264\1\0\17\264\13\0\1\265\66\0\1\266"+
+    "\2\0\1\266\5\0\2\266\11\0\1\267\54\0\1\270"+
+    "\61\0\1\271\1\32\1\147\1\32\1\0\1\32\1\271"+
+    "\1\0\1\32\1\0\1\32\3\0\2\32\2\0\3\32"+
+    "\1\0\1\32\13\0\1\271\2\32\1\271\2\32\1\271"+
+    "\2\32\1\0\4\32\1\0\1\271\2\32\1\0\1\271"+
+    "\2\32\4\0\2\32\1\147\3\0\1\32\3\0\1\32"+
+    "\7\0\3\32\1\0\1\32\2\0\1\272\10\0\11\32"+
+    "\1\0\4\32\1\0\3\32\1\0\3\32\4\0\1\273"+
+    "\2\152\1\0\2\152\1\273\1\152\1\0\5\152\2\0"+
+    "\22\152\1\273\2\152\1\273\2\152\1\273\10\152\1\273"+
+    "\3\152\1\273\5\152\1\0\1\274\2\154\1\0\2\154"+
+    "\1\274\1\154\1\0\5\154\2\0\22\154\1\274\2\154"+
+    "\1\274\2\154\1\274\10\154\1\274\3\154\1\274\5\154"+
+    "\6\0\1\156\2\0\1\156\5\0\2\156\10\0\1\157"+
+    "\50\0\1\157\2\0\1\157\5\0\2\157\66\0\1\275"+
+    "\125\0\1\276\104\0\1\277\66\0\2\300\67\0\2\301"+
+    "\104\0\1\302\13\0\42\170\1\303\31\170\1\0\2\171"+
+    "\1\172\3\0\1\171\3\0\1\171\7\0\3\171\1\304"+
+    "\1\171\13\0\11\171\1\0\4\171\1\0\3\171\1\0"+
+    "\3\171\4\0\1\305\2\171\1\0\2\171\1\305\1\171"+
+    "\1\0\5\171\2\0\22\171\1\305\2\171\1\305\2\171"+
+    "\1\305\10\171\1\305\3\171\1\305\5\171\1\0\1\306"+
+    "\1\173\1\174\1\173\1\307\1\173\1\306\10\173\1\310"+
+    "\22\173\1\306\2\173\1\306\2\173\1\306\10\173\1\306"+
+    "\3\173\1\306\5\173\1\0\1\311\1\176\1\177\3\176"+
+    "\1\311\1\312\7\176\1\313\22\176\1\311\2\176\1\311"+
+    "\2\176\1\311\10\176\1\311\3\176\1\311\5\176\32\0"+
+    "\1\272\42\0\1\314\1\201\1\202\1\201\1\315\1\201"+
+    "\1\314\10\201\1\316\22\201\1\314\2\201\1\314\2\201"+
+    "\1\314\10\201\1\314\3\201\1\314\5\201\1\0\1\317"+
+    "\1\204\1\205\3\204\1\317\1\320\7\204\1\321\22\204"+
+    "\1\317\2\204\1\317\2\204\1\317\10\204\1\317\3\204"+
+    "\1\317\5\204\25\0\1\322\47\0\1\323\1\60\1\207"+
+    "\1\60\1\0\1\60\1\323\1\0\1\60\1\0\1\60"+
+    "\3\0\2\60\2\0\3\60\1\0\1\60\13\0\1\323"+
+    "\2\60\1\323\2\60\1\323\2\60\1\0\4\60\1\0"+
+    "\1\323\2\60\1\0\1\323\2\60\4\0\2\60\1\207"+
+    "\3\0\1\60\3\0\1\60\7\0\3\60\1\0\1\60"+
+    "\2\0\1\272\10\0\11\60\1\0\4\60\1\0\3\60"+
+    "\1\0\3\60\4\0\1\324\1\64\1\212\1\64\1\0"+
+    "\1\64\1\324\1\0\1\64\1\0\1\64\3\0\2\64"+
+    "\2\0\3\64\1\0\1\64\13\0\1\324\2\64\1\324"+
+    "\2\64\1\324\2\64\1\0\4\64\1\0\1\324\2\64"+
+    "\1\0\1\324\2\64\4\0\2\64\1\212\3\0\1\64"+
+    "\3\0\1\64\7\0\3\64\1\0\1\64\2\0\1\272"+
+    "\10\0\11\64\1\0\4\64\1\0\3\64\1\0\3\64"+
+    "\4\0\1\325\1\71\1\215\1\71\1\0\1\71\1\325"+
+    "\1\0\1\71\1\0\1\71\3\0\2\71\2\0\3\71"+
+    "\1\0\1\71\13\0\1\325\2\71\1\325\2\71\1\325"+
+    "\2\71\1\0\4\71\1\0\1\325\2\71\1\0\1\325"+
+    "\2\71\4\0\2\71\1\215\3\0\1\71\3\0\1\71"+
+    "\7\0\3\71\1\0\1\71\2\0\1\272\10\0\11\71"+
+    "\1\0\4\71\1\0\3\71\1\0\3\71\4\0\1\326"+
+    "\1\101\1\221\1\101\1\0\1\101\1\326\1\0\1\101"+
+    "\1\0\1\101\3\0\2\101\2\0\3\101\1\0\1\101"+
+    "\13\0\1\326\2\101\1\326\2\101\1\326\2\101\1\0"+
+    "\4\101\1\0\1\326\2\101\1\0\1\326\2\101\4\0"+
+    "\2\101\1\221\3\0\1\101\3\0\1\101\7\0\3\101"+
+    "\1\0\1\101\2\0\1\272\10\0\11\101\1\0\4\101"+
+    "\1\0\3\101\1\0\3\101\4\0\1\327\1\107\1\224"+
+    "\1\107\1\0\1\107\1\327\1\0\1\107\1\0\1\107"+
+    "\3\0\2\107\2\0\3\107\1\0\1\107\13\0\1\327"+
+    "\2\107\1\327\2\107\1\327\2\107\1\0\4\107\1\0"+
+    "\1\327\2\107\1\0\1\327\2\107\4\0\1\330\1\226"+
+    "\1\227\1\226\1\331\1\226\1\330\10\226\1\332\22\226"+
+    "\1\330\2\226\1\330\2\226\1\330\10\226\1\330\3\226"+
+    "\1\330\5\226\1\0\1\333\1\231\1\232\3\231\1\333"+
+    "\1\334\7\231\1\335\22\231\1\333\2\231\1\333\2\231"+
+    "\1\333\10\231\1\333\3\231\1\333\5\231\1\0\2\107"+
+    "\1\224\3\0\1\107\3\0\1\107\7\0\3\107\1\0"+
+    "\1\107\2\0\1\272\10\0\11\107\1\0\4\107\1\0"+
+    "\3\107\1\0\3\107\4\0\1\336\1\114\1\234\1\114"+
+    "\1\0\1\114\1\336\1\0\1\114\1\0\1\114\3\0"+
+    "\2\114\2\0\3\114\1\0\1\114\13\0\1\336\2\114"+
+    "\1\336\2\114\1\336\2\114\1\0\4\114\1\0\1\336"+
+    "\2\114\1\0\1\336\2\114\4\0\2\114\1\234\3\0"+
+    "\1\114\3\0\1\114\7\0\3\114\1\0\1\114\2\0"+
+    "\1\272\10\0\11\114\1\0\4\114\1\0\3\114\1\0"+
+    "\3\114\4\0\2\237\1\240\3\0\1\237\3\0\1\237"+
+    "\7\0\3\237\1\0\1\237\13\0\11\237\1\0\4\237"+
+    "\1\0\3\237\1\0\3\237\4\0\1\337\2\237\1\0"+
+    "\2\237\1\337\1\237\1\0\5\237\2\0\22\237\1\337"+
+    "\2\237\1\337\2\237\1\337\10\237\1\337\3\237\1\337"+
+    "\5\237\1\0\1\340\1\122\1\243\1\122\1\0\1\122"+
+    "\1\340\1\0\1\122\1\0\1\122\3\0\2\122\2\0"+
+    "\3\122\1\244\1\122\13\0\1\340\2\122\1\340\2\122"+
+    "\1\340\2\122\1\0\4\122\1\0\1\340\2\122\1\0"+
+    "\1\340\2\122\4\0\1\341\1\246\1\247\1\246\1\342"+
+    "\1\246\1\341\10\246\1\343\22\246\1\341\2\246\1\341"+
+    "\2\246\1\341\10\246\1\341\3\246\1\341\5\246\1\0"+
+    "\1\344\1\251\1\252\3\251\1\344\1\345\7\251\1\346"+
+    "\22\251\1\344\2\251\1\344\2\251\1\344\10\251\1\344"+
+    "\3\251\1\344\5\251\1\0\1\253\1\122\1\243\3\0"+
+    "\1\122\3\0\1\122\1\0\1\241\5\0\3\122\1\244"+
+    "\1\122\1\0\1\242\11\0\11\122\1\0\4\122\1\0"+
+    "\3\122\1\0\3\122\4\0\2\122\1\243\3\0\1\122"+
+    "\3\0\1\122\7\0\3\122\1\244\1\122\2\0\1\272"+
+    "\10\0\11\122\1\0\4\122\1\0\3\122\1\0\3\122"+
+    "\4\0\1\255\1\237\1\240\3\0\1\237\3\0\1\237"+
+    "\7\0\3\237\1\0\1\237\1\0\1\242\11\0\11\237"+
+    "\1\0\4\237\1\0\3\237\1\0\3\237\4\0\1\347"+
+    "\2\256\1\0\2\256\1\347\1\256\1\0\5\256\2\0"+
+    "\22\256\1\347\2\256\1\347\2\256\1\347\10\256\1\347"+
+    "\3\256\1\347\5\256\1\0\1\350\5\0\1\350\11\0"+
+    "\1\350\5\0\1\350\13\0\2\350\1\0\2\350\1\0"+
+    "\2\350\7\0\2\350\2\0\2\350\5\0\2\122\1\243"+
+    "\3\0\1\122\3\0\1\122\7\0\2\122\1\351\1\244"+
+    "\1\122\13\0\11\122\1\0\4\122\1\0\3\122\1\0"+
+    "\3\122\61\0\1\352\30\0\1\353\15\0\1\354\1\272"+
+    "\42\0\1\355\1\32\1\147\1\32\1\0\1\32\1\355"+
+    "\1\0\1\32\1\0\1\32\3\0\2\32\2\0\3\32"+
+    "\1\0\1\32\13\0\1\355\2\32\1\355\2\32\1\355"+
+    "\2\32\1\0\4\32\1\0\1\355\2\32\1\0\1\355"+
+    "\2\32\4\0\1\356\1\152\1\153\1\152\1\0\1\152"+
+    "\1\356\1\0\1\152\1\0\1\152\3\0\2\152\2\0"+
+    "\3\152\1\0\1\152\13\0\1\356\2\152\1\356\2\152"+
+    "\1\356\2\152\1\0\4\152\1\0\1\356\2\152\1\0"+
+    "\1\356\2\152\4\0\1\357\1\154\1\155\1\154\1\0"+
+    "\1\154\1\357\1\0\1\154\1\0\1\154\3\0\2\154"+
+    "\2\0\3\154\1\0\1\154\13\0\1\357\2\154\1\357"+
+    "\2\154\1\357\2\154\1\0\4\154\1\0\1\357\2\154"+
+    "\1\0\1\357\2\154\16\0\1\360\126\0\2\361\103\0"+
+    "\1\362\76\0\2\363\74\0\1\364\77\0\1\365\3\0"+
+    "\41\170\1\366\1\303\31\170\2\0\1\367\1\370\1\304"+
+    "\1\0\1\304\1\367\1\0\1\304\1\0\1\367\3\0"+
+    "\2\304\2\0\3\367\1\0\1\367\13\0\11\367\1\0"+
+    "\4\367\1\0\3\367\1\0\3\367\4\0\1\371\1\171"+
+    "\1\172\1\171\1\0\1\171\1\371\1\0\1\171\1\0"+
+    "\1\171\3\0\2\171\2\0\3\171\1\304\1\171\13\0"+
+    "\1\371\2\171\1\371\2\171\1\371\2\171\1\0\4\171"+
+    "\1\0\1\371\2\171\1\0\1\371\2\171\4\0\1\372"+
+    "\1\173\1\174\1\173\1\175\1\173\1\372\33\173\1\372"+
+    "\2\173\1\372\2\173\1\372\10\173\1\372\3\173\1\372"+
+    "\5\173\1\0\2\173\1\174\1\0\1\175\12\173\1\0"+
+    "\53\173\1\0\1\373\1\176\1\177\3\176\1\373\1\175"+
+    "\32\176\1\373\2\176\1\373\2\176\1\373\10\176\1\373"+
+    "\3\176\1\373\5\176\1\0\2\176\1\177\1\0\3\176"+
+    "\1\175\7\176\1\0\53\176\1\0\1\374\1\201\1\202"+
+    "\1\201\1\203\1\201\1\374\33\201\1\374\2\201\1\374"+
+    "\2\201\1\374\10\201\1\374\3\201\1\374\5\201\1\0"+
+    "\2\201\1\202\1\0\1\203\12\201\1\0\53\201\1\0"+
+    "\1\375\1\204\1\205\3\204\1\375\1\203\32\204\1\375"+
+    "\2\204\1\375\2\204\1\375\10\204\1\375\3\204\1\375"+
+    "\5\204\1\0\2\204\1\205\1\0\3\204\1\203\7\204"+
+    "\1\0\53\204\26\0\1\376\46\0\1\377\1\60\1\207"+
+    "\1\60\1\0\1\60\1\377\1\0\1\60\1\0\1\60"+
+    "\3\0\2\60\2\0\3\60\1\0\1\60\13\0\1\377"+
+    "\2\60\1\377\2\60\1\377\2\60\1\0\4\60\1\0"+
+    "\1\377\2\60\1\0\1\377\2\60\4\0\1\u0100\1\64"+
+    "\1\212\1\64\1\0\1\64\1\u0100\1\0\1\64\1\0"+
+    "\1\64\3\0\2\64\2\0\3\64\1\0\1\64\13\0"+
+    "\1\u0100\2\64\1\u0100\2\64\1\u0100\2\64\1\0\4\64"+
+    "\1\0\1\u0100\2\64\1\0\1\u0100\2\64\4\0\1\u0101"+
+    "\1\71\1\215\1\71\1\0\1\71\1\u0101\1\0\1\71"+
+    "\1\0\1\71\3\0\2\71\2\0\3\71\1\0\1\71"+
+    "\13\0\1\u0101\2\71\1\u0101\2\71\1\u0101\2\71\1\0"+
+    "\4\71\1\0\1\u0101\2\71\1\0\1\u0101\2\71\4\0"+
+    "\1\u0102\1\101\1\221\1\101\1\0\1\101\1\u0102\1\0"+
+    "\1\101\1\0\1\101\3\0\2\101\2\0\3\101\1\0"+
+    "\1\101\13\0\1\u0102\2\101\1\u0102\2\101\1\u0102\2\101"+
+    "\1\0\4\101\1\0\1\u0102\2\101\1\0\1\u0102\2\101"+
+    "\4\0\1\u0103\1\107\1\224\1\107\1\0\1\107\1\u0103"+
+    "\1\0\1\107\1\0\1\107\3\0\2\107\2\0\3\107"+
+    "\1\0\1\107\13\0\1\u0103\2\107\1\u0103\2\107\1\u0103"+
+    "\2\107\1\0\4\107\1\0\1\u0103\2\107\1\0\1\u0103"+
+    "\2\107\4\0\1\u0104\1\226\1\227\1\226\1\230\1\226"+
+    "\1\u0104\33\226\1\u0104\2\226\1\u0104\2\226\1\u0104\10\226"+
+    "\1\u0104\3\226\1\u0104\5\226\1\0\2\226\1\227\1\0"+
+    "\1\230\12\226\1\0\53\226\1\0\1\u0105\1\231\1\232"+
+    "\3\231\1\u0105\1\230\32\231\1\u0105\2\231\1\u0105\2\231"+
+    "\1\u0105\10\231\1\u0105\3\231\1\u0105\5\231\1\0\2\231"+
+    "\1\232\1\0\3\231\1\230\7\231\1\0\53\231\1\0"+
+    "\1\u0106\1\114\1\234\1\114\1\0\1\114\1\u0106\1\0"+
+    "\1\114\1\0\1\114\3\0\2\114\2\0\3\114\1\0"+
+    "\1\114\13\0\1\u0106\2\114\1\u0106\2\114\1\u0106\2\114"+
+    "\1\0\4\114\1\0\1\u0106\2\114\1\0\1\u0106\2\114"+
+    "\4\0\1\u0107\1\237\1\240\1\237\1\0\1\237\1\u0107"+
+    "\1\0\1\237\1\0\1\237\3\0\2\237\2\0\3\237"+
+    "\1\0\1\237\13\0\1\u0107\2\237\1\u0107\2\237\1\u0107"+
+    "\2\237\1\0\4\237\1\0\1\u0107\2\237\1\0\1\u0107"+
+    "\2\237\4\0\1\u0108\1\122\1\243\1\122\1\0\1\122"+
+    "\1\u0108\1\0\1\122\1\0\1\122\3\0\2\122\2\0"+
+    "\3\122\1\244\1\122\13\0\1\u0108\2\122\1\u0108\2\122"+
+    "\1\u0108\2\122\1\0\4\122\1\0\1\u0108\2\122\1\0"+
+    "\1\u0108\2\122\4\0\1\u0109\1\246\1\247\1\246\1\250"+
+    "\1\246\1\u0109\33\246\1\u0109\2\246\1\u0109\2\246\1\u0109"+
+    "\10\246\1\u0109\3\246\1\u0109\5\246\1\0\2\246\1\247"+
+    "\1\0\1\250\12\246\1\0\53\246\1\0\1\u010a\1\251"+
+    "\1\252\3\251\1\u010a\1\250\32\251\1\u010a\2\251\1\u010a"+
+    "\2\251\1\u010a\10\251\1\u010a\3\251\1\u010a\5\251\1\0"+
+    "\2\251\1\252\1\0\3\251\1\250\7\251\1\0\53\251"+
+    "\1\0\1\u010b\1\256\1\257\1\256\1\0\1\256\1\u010b"+
+    "\1\0\1\256\1\0\1\256\3\0\2\256\2\0\3\256"+
+    "\1\0\1\256\13\0\1\u010b\2\256\1\u010b\2\256\1\u010b"+
+    "\2\256\1\0\4\256\1\0\1\u010b\2\256\1\0\1\u010b"+
+    "\2\256\4\0\1\u010c\5\0\1\u010c\3\0\1\u010d\5\0"+
+    "\1\u010c\5\0\1\u010c\13\0\2\u010c\1\0\2\u010c\1\0"+
+    "\2\u010c\7\0\2\u010c\2\0\2\u010c\5\0\2\122\1\243"+
+    "\3\0\1\122\3\0\1\122\7\0\3\122\1\u010e\1\122"+
+    "\13\0\11\122\1\0\4\122\1\0\3\122\1\0\3\122"+
+    "\62\0\1\u010f\27\0\1\353\15\0\1\354\50\0\1\354"+
+    "\2\0\1\354\5\0\2\354\11\0\1\u0110\42\0\1\u0111"+
+    "\1\32\1\147\1\32\1\0\1\32\1\u0111\1\0\1\32"+
+    "\1\0\1\32\3\0\2\32\2\0\3\32\1\0\1\32"+
+    "\13\0\1\u0111\2\32\1\u0111\2\32\1\u0111\2\32\1\0"+
+    "\4\32\1\0\1\u0111\2\32\1\0\1\u0111\2\32\4\0"+
+    "\1\u0112\1\152\1\153\1\152\1\0\1\152\1\u0112\1\0"+
+    "\1\152\1\0\1\152\3\0\2\152\2\0\3\152\1\0"+
+    "\1\152\13\0\1\u0112\2\152\1\u0112\2\152\1\u0112\2\152"+
+    "\1\0\4\152\1\0\1\u0112\2\152\1\0\1\u0112\2\152"+
+    "\4\0\1\u0113\1\154\1\155\1\154\1\0\1\154\1\u0113"+
+    "\1\0\1\154\1\0\1\154\3\0\2\154\2\0\3\154"+
+    "\1\0\1\154\13\0\1\u0113\2\154\1\u0113\2\154\1\u0113"+
+    "\2\154\1\0\4\154\1\0\1\u0113\2\154\1\0\1\u0113"+
+    "\2\154\27\0\1\u0114\127\0\1\u0115\70\0\1\u0116\67\0"+
+    "\2\u0117\74\0\1\u0118\21\0\2\367\1\370\1\u0119\1\0"+
+    "\1\u0119\1\367\1\0\1\u0119\1\u011a\1\367\3\0\2\u0119"+
+    "\2\0\3\367\1\0\1\367\13\0\11\367\1\0\4\367"+
+    "\1\0\3\367\1\0\3\367\4\0\1\u011b\2\367\1\0"+
+    "\2\367\1\u011b\1\367\1\0\5\367\2\0\22\367\1\u011b"+
+    "\2\367\1\u011b\2\367\1\u011b\10\367\1\u011b\3\367\1\u011b"+
+    "\5\367\1\0\1\u011c\1\171\1\172\1\171\1\0\1\171"+
+    "\1\u011c\1\0\1\171\1\0\1\171\3\0\2\171\2\0"+
+    "\3\171\1\304\1\171\13\0\1\u011c\2\171\1\u011c\2\171"+
+    "\1\u011c\2\171\1\0\4\171\1\0\1\u011c\2\171\1\0"+
+    "\1\u011c\2\171\4\0\1\u011d\1\173\1\174\1\173\1\175"+
+    "\1\173\1\u011d\33\173\1\u011d\2\173\1\u011d\2\173\1\u011d"+
+    "\10\173\1\u011d\3\173\1\u011d\5\173\1\0\1\u011e\1\176"+
+    "\1\177\3\176\1\u011e\1\175\32\176\1\u011e\2\176\1\u011e"+
+    "\2\176\1\u011e\10\176\1\u011e\3\176\1\u011e\5\176\1\0"+
+    "\1\u011f\1\201\1\202\1\201\1\203\1\201\1\u011f\33\201"+
+    "\1\u011f\2\201\1\u011f\2\201\1\u011f\10\201\1\u011f\3\201"+
+    "\1\u011f\5\201\1\0\1\u0120\1\204\1\205\3\204\1\u0120"+
+    "\1\203\32\204\1\u0120\2\204\1\u0120\2\204\1\u0120\10\204"+
+    "\1\u0120\3\204\1\u0120\5\204\1\0\2\u0121\1\u0122\1\376"+
+    "\1\u0123\1\376\1\u0121\1\u0124\1\376\1\u0125\4\u0121\2\376"+
+    "\5\u0121\1\0\45\u0121\1\0\1\u0126\1\60\1\207\1\60"+
+    "\1\0\1\60\1\u0126\1\0\1\60\1\0\1\60\3\0"+
+    "\2\60\2\0\3\60\1\0\1\60\13\0\1\u0126\2\60"+
+    "\1\u0126\2\60\1\u0126\2\60\1\0\4\60\1\0\1\u0126"+
+    "\2\60\1\0\1\u0126\2\60\4\0\1\u0127\1\64\1\212"+
+    "\1\64\1\0\1\64\1\u0127\1\0\1\64\1\0\1\64"+
+    "\3\0\2\64\2\0\3\64\1\0\1\64\13\0\1\u0127"+
+    "\2\64\1\u0127\2\64\1\u0127\2\64\1\0\4\64\1\0"+
+    "\1\u0127\2\64\1\0\1\u0127\2\64\4\0\1\u0128\1\71"+
+    "\1\215\1\71\1\0\1\71\1\u0128\1\0\1\71\1\0"+
+    "\1\71\3\0\2\71\2\0\3\71\1\0\1\71\13\0"+
+    "\1\u0128\2\71\1\u0128\2\71\1\u0128\2\71\1\0\4\71"+
+    "\1\0\1\u0128\2\71\1\0\1\u0128\2\71\4\0\1\u0129"+
+    "\1\101\1\221\1\101\1\0\1\101\1\u0129\1\0\1\101"+
+    "\1\0\1\101\3\0\2\101\2\0\3\101\1\0\1\101"+
+    "\13\0\1\u0129\2\101\1\u0129\2\101\1\u0129\2\101\1\0"+
+    "\4\101\1\0\1\u0129\2\101\1\0\1\u0129\2\101\4\0"+
+    "\1\u012a\1\107\1\224\1\107\1\0\1\107\1\u012a\1\0"+
+    "\1\107\1\0\1\107\3\0\2\107\2\0\3\107\1\0"+
+    "\1\107\13\0\1\u012a\2\107\1\u012a\2\107\1\u012a\2\107"+
+    "\1\0\4\107\1\0\1\u012a\2\107\1\0\1\u012a\2\107"+
+    "\4\0\1\u012b\1\226\1\227\1\226\1\230\1\226\1\u012b"+
+    "\33\226\1\u012b\2\226\1\u012b\2\226\1\u012b\10\226\1\u012b"+
+    "\3\226\1\u012b\5\226\1\0\1\u012c\1\231\1\232\3\231"+
+    "\1\u012c\1\230\32\231\1\u012c\2\231\1\u012c\2\231\1\u012c"+
+    "\10\231\1\u012c\3\231\1\u012c\5\231\1\0\1\u012d\1\114"+
+    "\1\234\1\114\1\0\1\114\1\u012d\1\0\1\114\1\0"+
+    "\1\114\3\0\2\114\2\0\3\114\1\0\1\114\13\0"+
+    "\1\u012d\2\114\1\u012d\2\114\1\u012d\2\114\1\0\4\114"+
+    "\1\0\1\u012d\2\114\1\0\1\u012d\2\114\4\0\1\u012e"+
+    "\1\237\1\240\1\237\1\0\1\237\1\u012e\1\0\1\237"+
+    "\1\0\1\237\3\0\2\237\2\0\3\237\1\0\1\237"+
+    "\13\0\1\u012e\2\237\1\u012e\2\237\1\u012e\2\237\1\0"+
+    "\4\237\1\0\1\u012e\2\237\1\0\1\u012e\2\237\4\0"+
+    "\1\u012f\1\122\1\243\1\122\1\0\1\122\1\u012f\1\0"+
+    "\1\122\1\0\1\122\3\0\2\122\2\0\3\122\1\244"+
+    "\1\122\13\0\1\u012f\2\122\1\u012f\2\122\1\u012f\2\122"+
+    "\1\0\4\122\1\0\1\u012f\2\122\1\0\1\u012f\2\122"+
+    "\4\0\1\u0130\1\246\1\247\1\246\1\250\1\246\1\u0130"+
+    "\33\246\1\u0130\2\246\1\u0130\2\246\1\u0130\10\246\1\u0130"+
+    "\3\246\1\u0130\5\246\1\0\1\u0131\1\251\1\252\3\251"+
+    "\1\u0131\1\250\32\251\1\u0131\2\251\1\u0131\2\251\1\u0131"+
+    "\10\251\1\u0131\3\251\1\u0131\5\251\1\0\1\u0132\1\256"+
+    "\1\257\1\256\1\0\1\256\1\u0132\1\0\1\256\1\0"+
+    "\1\256\3\0\2\256\2\0\3\256\1\0\1\256\13\0"+
+    "\1\u0132\2\256\1\u0132\2\256\1\u0132\2\256\1\0\4\256"+
+    "\1\0\1\u0132\2\256\1\0\1\u0132\2\256\4\0\1\u0133"+
+    "\5\0\1\u0133\3\0\1\u010d\5\0\1\u0133\5\0\1\u0133"+
+    "\13\0\2\u0133\1\0\2\u0133\1\0\2\u0133\7\0\2\u0133"+
+    "\2\0\2\u0133\5\0\1\u0134\5\0\1\u0134\11\0\1\u0134"+
+    "\5\0\1\u0134\13\0\2\u0134\1\0\2\u0134\1\0\2\u0134"+
+    "\7\0\2\u0134\2\0\2\u0134\5\0\2\u0135\1\u0136\1\u0137"+
+    "\1\u0138\1\u0137\1\u0135\1\u0139\1\u0137\1\u013a\4\u0135\2\u0137"+
+    "\5\u0135\1\0\45\u0135\60\0\1\u013b\14\0\1\u013c\1\32"+
+    "\1\147\1\32\1\0\1\32\1\u013c\1\0\1\32\1\0"+
+    "\1\32\3\0\2\32\2\0\3\32\1\0\1\32\13\0"+
+    "\1\u013c\2\32\1\u013c\2\32\1\u013c\2\32\1\0\4\32"+
+    "\1\0\1\u013c\2\32\1\0\1\u013c\2\32\4\0\1\u013d"+
+    "\1\152\1\153\1\152\1\0\1\152\1\u013d\1\0\1\152"+
+    "\1\0\1\152\3\0\2\152\2\0\3\152\1\0\1\152"+
+    "\13\0\1\u013d\2\152\1\u013d\2\152\1\u013d\2\152\1\0"+
+    "\4\152\1\0\1\u013d\2\152\1\0\1\u013d\2\152\4\0"+
+    "\1\u013e\1\154\1\155\1\154\1\0\1\154\1\u013e\1\0"+
+    "\1\154\1\0\1\154\3\0\2\154\2\0\3\154\1\0"+
+    "\1\154\13\0\1\u013e\2\154\1\u013e\2\154\1\u013e\2\154"+
+    "\1\0\4\154\1\0\1\u013e\2\154\1\0\1\u013e\2\154"+
+    "\53\0\1\u013f\47\0\1\u0140\115\0\2\u0141\37\0\1\u0142"+
+    "\64\0\1\u0119\1\0\1\u0119\2\0\1\u0119\1\u011a\4\0"+
+    "\2\u0119\54\0\1\u0143\1\367\1\370\1\367\1\0\1\367"+
+    "\1\u0143\1\0\1\367\1\u011a\1\367\3\0\2\367\2\0"+
+    "\3\367\1\0\1\367\13\0\1\u0143\2\367\1\u0143\2\367"+
+    "\1\u0143\2\367\1\0\4\367\1\0\1\u0143\2\367\1\0"+
+    "\1\u0143\2\367\4\0\1\u0144\1\171\1\172\1\171\1\0"+
+    "\1\171\1\u0144\1\0\1\171\1\0\1\171\3\0\2\171"+
+    "\2\0\3\171\1\304\1\171\13\0\1\u0144\2\171\1\u0144"+
+    "\2\171\1\u0144\2\171\1\0\4\171\1\0\1\u0144\2\171"+
+    "\1\0\1\u0144\2\171\4\0\1\u0145\1\173\1\174\1\173"+
+    "\1\175\1\173\1\u0145\33\173\1\u0145\2\173\1\u0145\2\173"+
+    "\1\u0145\10\173\1\u0145\3\173\1\u0145\5\173\1\0\1\u0146"+
+    "\1\176\1\177\3\176\1\u0146\1\175\32\176\1\u0146\2\176"+
+    "\1\u0146\2\176\1\u0146\10\176\1\u0146\3\176\1\u0146\5\176"+
+    "\1\0\1\u0147\1\201\1\202\1\201\1\203\1\201\1\u0147"+
+    "\33\201\1\u0147\2\201\1\u0147\2\201\1\u0147\10\201\1\u0147"+
+    "\3\201\1\u0147\5\201\1\0\1\u0148\1\204\1\205\3\204"+
+    "\1\u0148\1\203\32\204\1\u0148\2\204\1\u0148\2\204\1\u0148"+
+    "\10\204\1\u0148\3\204\1\u0148\5\204\1\0\2\u0121\1\u0122"+
+    "\1\u0149\1\0\2\u0121\1\0\1\u0149\1\u0125\4\u0121\2\u0149"+
+    "\5\u0121\1\0\45\u0121\1\0\1\u014a\1\u0121\1\u0122\1\u0149"+
+    "\2\u0121\1\u014a\1\u0121\1\u0149\1\u014b\4\u0121\2\u0149\22\u0121"+
+    "\1\u014a\2\u0121\1\u014a\2\u0121\1\u014a\10\u0121\1\u014a\3\u0121"+
+    "\1\u014a\5\u0121\1\0\2\u0123\1\u014c\1\0\1\u0149\11\u0123"+
+    "\2\0\53\u0123\1\0\2\u0124\1\u014d\1\0\3\u0124\1\u0149"+
+    "\6\u0124\2\0\53\u0124\1\0\1\u014e\1\60\1\207\1\60"+
+    "\1\0\1\60\1\u014e\1\0\1\60\1\0\1\60\3\0"+
+    "\2\60\2\0\3\60\1\0\1\60\13\0\1\u014e\2\60"+
+    "\1\u014e\2\60\1\u014e\2\60\1\0\4\60\1\0\1\u014e"+
+    "\2\60\1\0\1\u014e\2\60\4\0\1\u014f\1\64\1\212"+
+    "\1\64\1\0\1\64\1\u014f\1\0\1\64\1\0\1\64"+
+    "\3\0\2\64\2\0\3\64\1\0\1\64\13\0\1\u014f"+
+    "\2\64\1\u014f\2\64\1\u014f\2\64\1\0\4\64\1\0"+
+    "\1\u014f\2\64\1\0\1\u014f\2\64\4\0\1\u0150\1\71"+
+    "\1\215\1\71\1\0\1\71\1\u0150\1\0\1\71\1\0"+
+    "\1\71\3\0\2\71\2\0\3\71\1\0\1\71\13\0"+
+    "\1\u0150\2\71\1\u0150\2\71\1\u0150\2\71\1\0\4\71"+
+    "\1\0\1\u0150\2\71\1\0\1\u0150\2\71\4\0\1\u0151"+
+    "\1\101\1\221\1\101\1\0\1\101\1\u0151\1\0\1\101"+
+    "\1\0\1\101\3\0\2\101\2\0\3\101\1\0\1\101"+
+    "\13\0\1\u0151\2\101\1\u0151\2\101\1\u0151\2\101\1\0"+
+    "\4\101\1\0\1\u0151\2\101\1\0\1\u0151\2\101\4\0"+
+    "\1\u0152\1\107\1\224\1\107\1\0\1\107\1\u0152\1\0"+
+    "\1\107\1\0\1\107\3\0\2\107\2\0\3\107\1\0"+
+    "\1\107\13\0\1\u0152\2\107\1\u0152\2\107\1\u0152\2\107"+
+    "\1\0\4\107\1\0\1\u0152\2\107\1\0\1\u0152\2\107"+
+    "\4\0\1\u0153\1\226\1\227\1\226\1\230\1\226\1\u0153"+
+    "\33\226\1\u0153\2\226\1\u0153\2\226\1\u0153\10\226\1\u0153"+
+    "\3\226\1\u0153\5\226\1\0\1\u0154\1\231\1\232\3\231"+
+    "\1\u0154\1\230\32\231\1\u0154\2\231\1\u0154\2\231\1\u0154"+
+    "\10\231\1\u0154\3\231\1\u0154\5\231\1\0\1\u0155\1\114"+
+    "\1\234\1\114\1\0\1\114\1\u0155\1\0\1\114\1\0"+
+    "\1\114\3\0\2\114\2\0\3\114\1\0\1\114\13\0"+
+    "\1\u0155\2\114\1\u0155\2\114\1\u0155\2\114\1\0\4\114"+
+    "\1\0\1\u0155\2\114\1\0\1\u0155\2\114\4\0\1\u0156"+
+    "\1\237\1\240\1\237\1\0\1\237\1\u0156\1\0\1\237"+
+    "\1\0\1\237\3\0\2\237\2\0\3\237\1\0\1\237"+
+    "\13\0\1\u0156\2\237\1\u0156\2\237\1\u0156\2\237\1\0"+
+    "\4\237\1\0\1\u0156\2\237\1\0\1\u0156\2\237\4\0"+
+    "\1\u0157\1\122\1\243\1\122\1\0\1\122\1\u0157\1\0"+
+    "\1\122\1\0\1\122\3\0\2\122\2\0\3\122\1\244"+
+    "\1\122\13\0\1\u0157\2\122\1\u0157\2\122\1\u0157\2\122"+
+    "\1\0\4\122\1\0\1\u0157\2\122\1\0\1\u0157\2\122"+
+    "\4\0\1\u0158\1\246\1\247\1\246\1\250\1\246\1\u0158"+
+    "\33\246\1\u0158\2\246\1\u0158\2\246\1\u0158\10\246\1\u0158"+
+    "\3\246\1\u0158\5\246\1\0\1\u0159\1\251\1\252\3\251"+
+    "\1\u0159\1\250\32\251\1\u0159\2\251\1\u0159\2\251\1\u0159"+
+    "\10\251\1\u0159\3\251\1\u0159\5\251\1\0\1\u015a\1\256"+
+    "\1\257\1\256\1\0\1\256\1\u015a\1\0\1\256\1\0"+
+    "\1\256\3\0\2\256\2\0\3\256\1\0\1\256\13\0"+
+    "\1\u015a\2\256\1\u015a\2\256\1\u015a\2\256\1\0\4\256"+
+    "\1\0\1\u015a\2\256\1\0\1\u015a\2\256\4\0\1\u015b"+
+    "\5\0\1\u015b\3\0\1\u010d\5\0\1\u015b\5\0\1\u015b"+
+    "\13\0\2\u015b\1\0\2\u015b\1\0\2\u015b\7\0\2\u015b"+
+    "\2\0\2\u015b\5\0\1\u015c\5\0\1\u015c\11\0\1\u015c"+
+    "\5\0\1\u015c\13\0\2\u015c\1\0\2\u015c\1\0\2\u015c"+
+    "\7\0\2\u015c\2\0\2\u015c\5\0\2\u0135\1\u0136\1\u015d"+
+    "\1\0\2\u0135\1\0\1\u015d\1\u013a\4\u0135\2\u015d\5\u0135"+
+    "\1\0\45\u0135\1\0\1\u015e\1\u0135\1\u0136\1\u015d\2\u0135"+
+    "\1\u015e\1\u0135\1\u015d\1\u015f\4\u0135\2\u015d\22\u0135\1\u015e"+
+    "\2\u0135\1\u015e\2\u0135\1\u015e\10\u0135\1\u015e\3\u0135\1\u015e"+
+    "\5\u0135\1\0\2\u0138\1\u0160\1\0\1\u015d\11\u0138\2\0"+
+    "\53\u0138\1\0\2\u0139\1\u0161\1\0\3\u0139\1\u015d\6\u0139"+
+    "\2\0\53\u0139\24\0\1\u0162\50\0\1\u0163\1\32\1\147"+
+    "\1\32\1\0\1\32\1\u0163\1\0\1\32\1\0\1\32"+
+    "\3\0\2\32\2\0\3\32\1\0\1\32\13\0\1\u0163"+
+    "\2\32\1\u0163\2\32\1\u0163\2\32\1\0\4\32\1\0"+
+    "\1\u0163\2\32\1\0\1\u0163\2\32\4\0\1\u0164\1\152"+
+    "\1\153\1\152\1\0\1\152\1\u0164\1\0\1\152\1\0"+
+    "\1\152\3\0\2\152\2\0\3\152\1\0\1\152\13\0"+
+    "\1\u0164\2\152\1\u0164\2\152\1\u0164\2\152\1\0\4\152"+
+    "\1\0\1\u0164\2\152\1\0\1\u0164\2\152\4\0\1\u0165"+
+    "\1\154\1\155\1\154\1\0\1\154\1\u0165\1\0\1\154"+
+    "\1\0\1\154\3\0\2\154\2\0\3\154\1\0\1\154"+
+    "\13\0\1\u0165\2\154\1\u0165\2\154\1\u0165\2\154\1\0"+
+    "\4\154\1\0\1\u0165\2\154\1\0\1\u0165\2\154\54\0"+
+    "\2\u0166\74\0\1\u0167\106\0\2\u0168\5\0\1\u0169\1\367"+
+    "\1\370\1\367\1\0\1\367\1\u0169\1\0\1\367\1\u011a"+
+    "\1\367\3\0\2\367\2\0\3\367\1\0\1\367\13\0"+
+    "\1\u0169\2\367\1\u0169\2\367\1\u0169\2\367\1\0\4\367"+
+    "\1\0\1\u0169\2\367\1\0\1\u0169\2\367\4\0\1\u016a"+
+    "\1\171\1\172\1\171\1\0\1\171\1\u016a\1\0\1\171"+
+    "\1\0\1\171\3\0\2\171\2\0\3\171\1\304\1\171"+
+    "\13\0\1\u016a\2\171\1\u016a\2\171\1\u016a\2\171\1\0"+
+    "\4\171\1\0\1\u016a\2\171\1\0\1\u016a\2\171\4\0"+
+    "\1\u016b\1\173\1\174\1\173\1\175\1\173\1\u016b\33\173"+
+    "\1\u016b\2\173\1\u016b\2\173\1\u016b\10\173\1\u016b\3\173"+
+    "\1\u016b\5\173\1\0\1\u016c\1\176\1\177\3\176\1\u016c"+
+    "\1\175\32\176\1\u016c\2\176\1\u016c\2\176\1\u016c\10\176"+
+    "\1\u016c\3\176\1\u016c\5\176\1\0\1\u016d\1\201\1\202"+
+    "\1\201\1\203\1\201\1\u016d\33\201\1\u016d\2\201\1\u016d"+
+    "\2\201\1\u016d\10\201\1\u016d\3\201\1\u016d\5\201\1\0"+
+    "\1\u016e\1\204\1\205\3\204\1\u016e\1\203\32\204\1\u016e"+
+    "\2\204\1\u016e\2\204\1\u016e\10\204\1\u016e\3\204\1\u016e"+
+    "\5\204\4\0\1\u0149\1\0\1\u0149\2\0\1\u0149\1\u0125"+
+    "\4\0\2\u0149\54\0\1\u016f\1\u0121\1\u0122\1\u0121\1\0"+
+    "\1\u0121\1\u016f\1\0\1\u0121\1\u0125\13\u0121\1\0\14\u0121"+
+    "\1\u016f\2\u0121\1\u016f\2\u0121\1\u016f\10\u0121\1\u016f\3\u0121"+
+    "\1\u016f\5\u0121\1\0\1\u0170\1\u0123\1\u014c\1\u0123\1\u0171"+
+    "\1\u0123\1\u0170\10\u0123\1\u0172\22\u0123\1\u0170\2\u0123\1\u0170"+
+    "\2\u0123\1\u0170\10\u0123\1\u0170\3\u0123\1\u0170\5\u0123\1\0"+
+    "\1\u0173\1\u0124\1\u014d\3\u0124\1\u0173\1\u0174\7\u0124\1\u0175"+
+    "\22\u0124\1\u0173\2\u0124\1\u0173\2\u0124\1\u0173\10\u0124\1\u0173"+
+    "\3\u0124\1\u0173\5\u0124\1\0\1\u0176\1\60\1\207\1\60"+
+    "\1\0\1\60\1\u0176\1\0\1\60\1\0\1\60\3\0"+
+    "\2\60\2\0\3\60\1\0\1\60\13\0\1\u0176\2\60"+
+    "\1\u0176\2\60\1\u0176\2\60\1\0\4\60\1\0\1\u0176"+
+    "\2\60\1\0\1\u0176\2\60\4\0\1\u0177\1\64\1\212"+
+    "\1\64\1\0\1\64\1\u0177\1\0\1\64\1\0\1\64"+
+    "\3\0\2\64\2\0\3\64\1\0\1\64\13\0\1\u0177"+
+    "\2\64\1\u0177\2\64\1\u0177\2\64\1\0\4\64\1\0"+
+    "\1\u0177\2\64\1\0\1\u0177\2\64\4\0\1\u0178\1\71"+
+    "\1\215\1\71\1\0\1\71\1\u0178\1\0\1\71\1\0"+
+    "\1\71\3\0\2\71\2\0\3\71\1\0\1\71\13\0"+
+    "\1\u0178\2\71\1\u0178\2\71\1\u0178\2\71\1\0\4\71"+
+    "\1\0\1\u0178\2\71\1\0\1\u0178\2\71\4\0\1\u0179"+
+    "\1\101\1\221\1\101\1\0\1\101\1\u0179\1\0\1\101"+
+    "\1\0\1\101\3\0\2\101\2\0\3\101\1\0\1\101"+
+    "\13\0\1\u0179\2\101\1\u0179\2\101\1\u0179\2\101\1\0"+
+    "\4\101\1\0\1\u0179\2\101\1\0\1\u0179\2\101\4\0"+
+    "\1\u017a\1\107\1\224\1\107\1\0\1\107\1\u017a\1\0"+
+    "\1\107\1\0\1\107\3\0\2\107\2\0\3\107\1\0"+
+    "\1\107\13\0\1\u017a\2\107\1\u017a\2\107\1\u017a\2\107"+
+    "\1\0\4\107\1\0\1\u017a\2\107\1\0\1\u017a\2\107"+
+    "\4\0\1\u017b\1\226\1\227\1\226\1\230\1\226\1\u017b"+
+    "\33\226\1\u017b\2\226\1\u017b\2\226\1\u017b\10\226\1\u017b"+
+    "\3\226\1\u017b\5\226\1\0\1\u017c\1\231\1\232\3\231"+
+    "\1\u017c\1\230\32\231\1\u017c\2\231\1\u017c\2\231\1\u017c"+
+    "\10\231\1\u017c\3\231\1\u017c\5\231\1\0\1\u017d\1\114"+
+    "\1\234\1\114\1\0\1\114\1\u017d\1\0\1\114\1\0"+
+    "\1\114\3\0\2\114\2\0\3\114\1\0\1\114\13\0"+
+    "\1\u017d\2\114\1\u017d\2\114\1\u017d\2\114\1\0\4\114"+
+    "\1\0\1\u017d\2\114\1\0\1\u017d\2\114\4\0\1\u017e"+
+    "\1\237\1\240\1\237\1\0\1\237\1\u017e\1\0\1\237"+
+    "\1\0\1\237\3\0\2\237\2\0\3\237\1\0\1\237"+
+    "\13\0\1\u017e\2\237\1\u017e\2\237\1\u017e\2\237\1\0"+
+    "\4\237\1\0\1\u017e\2\237\1\0\1\u017e\2\237\4\0"+
+    "\1\u017f\1\122\1\243\1\122\1\0\1\122\1\u017f\1\0"+
+    "\1\122\1\0\1\122\3\0\2\122\2\0\3\122\1\244"+
+    "\1\122\13\0\1\u017f\2\122\1\u017f\2\122\1\u017f\2\122"+
+    "\1\0\4\122\1\0\1\u017f\2\122\1\0\1\u017f\2\122"+
+    "\4\0\1\u0180\1\246\1\247\1\246\1\250\1\246\1\u0180"+
+    "\33\246\1\u0180\2\246\1\u0180\2\246\1\u0180\10\246\1\u0180"+
+    "\3\246\1\u0180\5\246\1\0\1\u0181\1\251\1\252\3\251"+
+    "\1\u0181\1\250\32\251\1\u0181\2\251\1\u0181\2\251\1\u0181"+
+    "\10\251\1\u0181\3\251\1\u0181\5\251\1\0\1\u0182\1\256"+
+    "\1\257\1\256\1\0\1\256\1\u0182\1\0\1\256\1\0"+
+    "\1\256\3\0\2\256\2\0\3\256\1\0\1\256\13\0"+
+    "\1\u0182\2\256\1\u0182\2\256\1\u0182\2\256\1\0\4\256"+
+    "\1\0\1\u0182\2\256\1\0\1\u0182\2\256\4\0\1\u0183"+
+    "\5\0\1\u0183\3\0\1\u010d\5\0\1\u0183\5\0\1\u0183"+
+    "\13\0\2\u0183\1\0\2\u0183\1\0\2\u0183\7\0\2\u0183"+
+    "\2\0\2\u0183\5\0\1\u0184\5\0\1\u0184\11\0\1\u0184"+
+    "\5\0\1\u0184\13\0\2\u0184\1\0\2\u0184\1\0\2\u0184"+
+    "\7\0\2\u0184\2\0\2\u0184\10\0\1\u015d\1\0\1\u015d"+
+    "\2\0\1\u015d\1\u013a\4\0\2\u015d\54\0\1\u0185\1\u0135"+
+    "\1\u0136\1\u0135\1\0\1\u0135\1\u0185\1\0\1\u0135\1\u013a"+
+    "\13\u0135\1\0\14\u0135\1\u0185\2\u0135\1\u0185\2\u0135\1\u0185"+
+    "\10\u0135\1\u0185\3\u0135\1\u0185\5\u0135\1\0\1\u0186\1\u0138"+
+    "\1\u0160\1\u0138\1\u0187\1\u0138\1\u0186\10\u0138\1\u0188\22\u0138"+
+    "\1\u0186\2\u0138\1\u0186\2\u0138\1\u0186\10\u0138\1\u0186\3\u0138"+
+    "\1\u0186\5\u0138\1\0\1\u0189\1\u0139\1\u0161\3\u0139\1\u0189"+
+    "\1\u018a\7\u0139\1\u018b\22\u0139\1\u0189\2\u0139\1\u0189\2\u0139"+
+    "\1\u0189\10\u0139\1\u0189\3\u0139\1\u0189\5\u0139\53\0\1\u018c"+
+    "\21\0\2\32\1\147\1\32\1\0\2\32\1\0\1\32"+
+    "\1\0\1\32\3\0\2\32\2\0\3\32\1\0\1\32"+
+    "\13\0\11\32\1\0\4\32\1\0\3\32\1\0\3\32"+
+    "\4\0\1\u018d\1\152\1\153\1\152\1\0\1\152\1\u018d"+
+    "\1\0\1\152\1\0\1\152\3\0\2\152\2\0\3\152"+
+    "\1\0\1\152\13\0\1\u018d\2\152\1\u018d\2\152\1\u018d"+
+    "\2\152\1\0\4\152\1\0\1\u018d\2\152\1\0\1\u018d"+
+    "\2\152\4\0\1\u018e\1\154\1\155\1\154\1\0\1\154"+
+    "\1\u018e\1\0\1\154\1\0\1\154\3\0\2\154\2\0"+
+    "\3\154\1\0\1\154\13\0\1\u018e\2\154\1\u018e\2\154"+
+    "\1\u018e\2\154\1\0\4\154\1\0\1\u018e\2\154\1\0"+
+    "\1\u018e\2\154\56\0\1\u018f\66\0\2\u0190\25\0\1\u0191"+
+    "\1\367\1\370\1\367\1\0\1\367\1\u0191\1\0\1\367"+
+    "\1\u011a\1\367\3\0\2\367\2\0\3\367\1\0\1\367"+
+    "\13\0\1\u0191\2\367\1\u0191\2\367\1\u0191\2\367\1\0"+
+    "\4\367\1\0\1\u0191\2\367\1\0\1\u0191\2\367\4\0"+
+    "\1\u0192\1\171\1\172\1\171\1\0\1\171\1\u0192\1\0"+
+    "\1\171\1\0\1\171\3\0\2\171\2\0\3\171\1\304"+
+    "\1\171\13\0\1\u0192\2\171\1\u0192\2\171\1\u0192\2\171"+
+    "\1\0\4\171\1\0\1\u0192\2\171\1\0\1\u0192\2\171"+
+    "\4\0\1\u0193\1\173\1\174\1\173\1\175\1\173\1\u0193"+
+    "\33\173\1\u0193\2\173\1\u0193\2\173\1\u0193\10\173\1\u0193"+
+    "\3\173\1\u0193\5\173\1\0\1\u0194\1\176\1\177\3\176"+
+    "\1\u0194\1\175\32\176\1\u0194\2\176\1\u0194\2\176\1\u0194"+
+    "\10\176\1\u0194\3\176\1\u0194\5\176\1\0\1\u0195\1\201"+
+    "\1\202\1\201\1\203\1\201\1\u0195\33\201\1\u0195\2\201"+
+    "\1\u0195\2\201\1\u0195\10\201\1\u0195\3\201\1\u0195\5\201"+
+    "\1\0\1\u0196\1\204\1\205\3\204\1\u0196\1\203\32\204"+
+    "\1\u0196\2\204\1\u0196\2\204\1\u0196\10\204\1\u0196\3\204"+
+    "\1\u0196\5\204\1\0\1\u0197\1\u0121\1\u0122\1\u0121\1\0"+
+    "\1\u0121\1\u0197\1\0\1\u0121\1\u0125\13\u0121\1\0\14\u0121"+
+    "\1\u0197\2\u0121\1\u0197\2\u0121\1\u0197\10\u0121\1\u0197\3\u0121"+
+    "\1\u0197\5\u0121\1\0\1\u0198\1\u0123\1\u014c\1\u0123\1\u0149"+
+    "\1\u0123\1\u0198\33\u0123\1\u0198\2\u0123\1\u0198\2\u0123\1\u0198"+
+    "\10\u0123\1\u0198\3\u0123\1\u0198\5\u0123\1\0\2\u0123\1\u014c"+
+    "\2\u0149\1\u0171\2\u0123\1\u0171\1\u0199\4\u0123\2\u0149\53\u0123"+
+    "\1\0\2\u0123\1\u014c\1\0\1\u0149\12\u0123\1\0\53\u0123"+
+    "\1\0\1\u019a\1\u0124\1\u014d\3\u0124\1\u019a\1\u0149\32\u0124"+
+    "\1\u019a\2\u0124\1\u019a\2\u0124\1\u019a\10\u0124\1\u019a\3\u0124"+
+    "\1\u019a\5\u0124\1\0\2\u0124\1\u014d\1\u0149\1\u0124\1\u0174"+
+    "\1\u0124\1\u0149\1\u0174\1\u019b\4\u0124\2\u0149\53\u0124\1\0"+
+    "\2\u0124\1\u014d\1\0\3\u0124\1\u0149\7\u0124\1\0\53\u0124"+
+    "\1\0\2\60\1\207\1\60\1\0\2\60\1\0\1\60"+
+    "\1\0\1\60\3\0\2\60\2\0\3\60\1\0\1\60"+
+    "\13\0\11\60\1\0\4\60\1\0\3\60\1\0\3\60"+
+    "\4\0\2\64\1\212\1\64\1\0\2\64\1\0\1\64"+
+    "\1\0\1\64\3\0\2\64\2\0\3\64\1\0\1\64"+
+    "\13\0\11\64\1\0\4\64\1\0\3\64\1\0\3\64"+
+    "\4\0\2\71\1\215\1\71\1\0\2\71\1\0\1\71"+
+    "\1\0\1\71\3\0\2\71\2\0\3\71\1\0\1\71"+
+    "\13\0\11\71\1\0\4\71\1\0\3\71\1\0\3\71"+
+    "\4\0\2\101\1\221\1\101\1\0\2\101\1\0\1\101"+
+    "\1\0\1\101\3\0\2\101\2\0\3\101\1\0\1\101"+
+    "\13\0\11\101\1\0\4\101\1\0\3\101\1\0\3\101"+
+    "\4\0\2\107\1\224\1\107\1\0\2\107\1\0\1\107"+
+    "\1\0\1\107\3\0\2\107\2\0\3\107\1\0\1\107"+
+    "\13\0\11\107\1\0\4\107\1\0\3\107\1\0\3\107"+
+    "\4\0\1\u019c\1\226\1\227\1\226\1\230\1\226\1\u019c"+
+    "\33\226\1\u019c\2\226\1\u019c\2\226\1\u019c\10\226\1\u019c"+
+    "\3\226\1\u019c\5\226\1\0\1\u019d\1\231\1\232\3\231"+
+    "\1\u019d\1\230\32\231\1\u019d\2\231\1\u019d\2\231\1\u019d"+
+    "\10\231\1\u019d\3\231\1\u019d\5\231\1\0\2\114\1\234"+
+    "\1\114\1\0\2\114\1\0\1\114\1\0\1\114\3\0"+
+    "\2\114\2\0\3\114\1\0\1\114\13\0\11\114\1\0"+
+    "\4\114\1\0\3\114\1\0\3\114\4\0\1\u019e\1\237"+
+    "\1\240\1\237\1\0\1\237\1\u019e\1\0\1\237\1\0"+
+    "\1\237\3\0\2\237\2\0\3\237\1\0\1\237\13\0"+
+    "\1\u019e\2\237\1\u019e\2\237\1\u019e\2\237\1\0\4\237"+
+    "\1\0\1\u019e\2\237\1\0\1\u019e\2\237\4\0\2\122"+
+    "\1\243\1\122\1\0\2\122\1\0\1\122\1\0\1\122"+
+    "\3\0\2\122\2\0\3\122\1\244\1\122\13\0\11\122"+
+    "\1\0\4\122\1\0\3\122\1\0\3\122\4\0\1\u019f"+
+    "\1\246\1\247\1\246\1\250\1\246\1\u019f\33\246\1\u019f"+
+    "\2\246\1\u019f\2\246\1\u019f\10\246\1\u019f\3\246\1\u019f"+
+    "\5\246\1\0\1\u01a0\1\251\1\252\3\251\1\u01a0\1\250"+
+    "\32\251\1\u01a0\2\251\1\u01a0\2\251\1\u01a0\10\251\1\u01a0"+
+    "\3\251\1\u01a0\5\251\1\0\1\u01a1\1\256\1\257\1\256"+
+    "\1\0\1\256\1\u01a1\1\0\1\256\1\0\1\256\3\0"+
+    "\2\256\2\0\3\256\1\0\1\256\13\0\1\u01a1\2\256"+
+    "\1\u01a1\2\256\1\u01a1\2\256\1\0\4\256\1\0\1\u01a1"+
+    "\2\256\1\0\1\u01a1\2\256\4\0\1\u01a2\5\0\1\u01a2"+
+    "\3\0\1\u010d\5\0\1\u01a2\5\0\1\u01a2\13\0\2\u01a2"+
+    "\1\0\2\u01a2\1\0\2\u01a2\7\0\2\u01a2\2\0\2\u01a2"+
+    "\5\0\1\u01a3\5\0\1\u01a3\11\0\1\u01a3\5\0\1\u01a3"+
+    "\13\0\2\u01a3\1\0\2\u01a3\1\0\2\u01a3\7\0\2\u01a3"+
+    "\2\0\2\u01a3\5\0\1\u01a4\1\u0135\1\u0136\1\u0135\1\0"+
+    "\1\u0135\1\u01a4\1\0\1\u0135\1\u013a\13\u0135\1\0\14\u0135"+
+    "\1\u01a4\2\u0135\1\u01a4\2\u0135\1\u01a4\10\u0135\1\u01a4\3\u0135"+
+    "\1\u01a4\5\u0135\1\0\1\u01a5\1\u0138\1\u0160\1\u0138\1\u015d"+
+    "\1\u0138\1\u01a5\33\u0138\1\u01a5\2\u0138\1\u01a5\2\u0138\1\u01a5"+
+    "\10\u0138\1\u01a5\3\u0138\1\u01a5\5\u0138\1\0\2\u0138\1\u0160"+
+    "\2\u015d\1\u0187\2\u0138\1\u0187\1\u01a6\4\u0138\2\u015d\53\u0138"+
+    "\1\0\2\u0138\1\u0160\1\0\1\u015d\12\u0138\1\0\53\u0138"+
+    "\1\0\1\u01a7\1\u0139\1\u0161\3\u0139\1\u01a7\1\u015d\32\u0139"+
+    "\1\u01a7\2\u0139\1\u01a7\2\u0139\1\u01a7\10\u0139\1\u01a7\3\u0139"+
+    "\1\u01a7\5\u0139\1\0\2\u0139\1\u0161\1\u015d\1\u0139\1\u018a"+
+    "\1\u0139\1\u015d\1\u018a\1\u01a8\4\u0139\2\u015d\53\u0139\1\0"+
+    "\2\u0139\1\u0161\1\0\3\u0139\1\u015d\7\u0139\1\0\53\u0139"+
+    "\46\0\2\u01a9\25\0\2\152\1\153\1\152\1\0\2\152"+
+    "\1\0\1\152\1\0\1\152\3\0\2\152\2\0\3\152"+
+    "\1\0\1\152\13\0\11\152\1\0\4\152\1\0\3\152"+
+    "\1\0\3\152\4\0\2\154\1\155\1\154\1\0\2\154"+
+    "\1\0\1\154\1\0\1\154\3\0\2\154\2\0\3\154"+
+    "\1\0\1\154\13\0\11\154\1\0\4\154\1\0\3\154"+
+    "\1\0\3\154\46\0\2\u01aa\30\0\1\u01ab\1\367\1\370"+
+    "\1\367\1\0\1\367\1\u01ab\1\0\1\367\1\u011a\1\367"+
+    "\3\0\2\367\2\0\3\367\1\0\1\367\13\0\1\u01ab"+
+    "\2\367\1\u01ab\2\367\1\u01ab\2\367\1\0\4\367\1\0"+
+    "\1\u01ab\2\367\1\0\1\u01ab\2\367\4\0\2\171\1\172"+
+    "\1\171\1\0\2\171\1\0\1\171\1\0\1\171\3\0"+
+    "\2\171\2\0\3\171\1\304\1\171\13\0\11\171\1\0"+
+    "\4\171\1\0\3\171\1\0\3\171\4\0\2\173\1\174"+
+    "\1\173\1\175\66\173\1\0\2\176\1\177\4\176\1\175"+
+    "\63\176\1\0\2\201\1\202\1\201\1\203\66\201\1\0"+
+    "\2\204\1\205\4\204\1\203\63\204\1\0\1\u01ac\1\u0121"+
+    "\1\u0122\1\u0121\1\0\1\u0121\1\u01ac\1\0\1\u0121\1\u0125"+
+    "\13\u0121\1\0\14\u0121\1\u01ac\2\u0121\1\u01ac\2\u0121\1\u01ac"+
+    "\10\u0121\1\u01ac\3\u0121\1\u01ac\5\u0121\1\0\1\u01ad\1\u0123"+
+    "\1\u014c\1\u0123\1\u0149\1\u0123\1\u01ad\33\u0123\1\u01ad\2\u0123"+
+    "\1\u01ad\2\u0123\1\u01ad\10\u0123\1\u01ad\3\u0123\1\u01ad\5\u0123"+
+    "\1\0\1\u01ae\1\u0124\1\u014d\3\u0124\1\u01ae\1\u0149\32\u0124"+
+    "\1\u01ae\2\u0124\1\u01ae\2\u0124\1\u01ae\10\u0124\1\u01ae\3\u0124"+
+    "\1\u01ae\5\u0124\1\0\2\226\1\227\1\226\1\230\66\226"+
+    "\1\0\2\231\1\232\4\231\1\230\63\231\1\0\2\237"+
+    "\1\240\1\237\1\0\2\237\1\0\1\237\1\0\1\237"+
+    "\3\0\2\237\2\0\3\237\1\0\1\237\13\0\11\237"+
+    "\1\0\4\237\1\0\3\237\1\0\3\237\4\0\2\246"+
+    "\1\247\1\246\1\250\66\246\1\0\2\251\1\252\4\251"+
+    "\1\250\63\251\1\0\2\256\1\257\1\256\1\0\2\256"+
+    "\1\0\1\256\1\0\1\256\3\0\2\256\2\0\3\256"+
+    "\1\0\1\256\13\0\11\256\1\0\4\256\1\0\3\256"+
+    "\1\0\3\256\16\0\1\u010d\61\0\1\u01af\5\0\1\u01af"+
+    "\11\0\1\u01af\5\0\1\u01af\13\0\2\u01af\1\0\2\u01af"+
+    "\1\0\2\u01af\7\0\2\u01af\2\0\2\u01af\5\0\1\u01b0"+
+    "\1\u0135\1\u0136\1\u0135\1\0\1\u0135\1\u01b0\1\0\1\u0135"+
+    "\1\u013a\13\u0135\1\0\14\u0135\1\u01b0\2\u0135\1\u01b0\2\u0135"+
+    "\1\u01b0\10\u0135\1\u01b0\3\u0135\1\u01b0\5\u0135\1\0\1\u01b1"+
+    "\1\u0138\1\u0160\1\u0138\1\u015d\1\u0138\1\u01b1\33\u0138\1\u01b1"+
+    "\2\u0138\1\u01b1\2\u0138\1\u01b1\10\u0138\1\u01b1\3\u0138\1\u01b1"+
+    "\5\u0138\1\0\1\u01b2\1\u0139\1\u0161\3\u0139\1\u01b2\1\u015d"+
+    "\32\u0139\1\u01b2\2\u0139\1\u01b2\2\u0139\1\u01b2\10\u0139\1\u01b2"+
+    "\3\u0139\1\u01b2\5\u0139\70\0\1\u01b3\54\0\2\u01b4\22\0"+
+    "\1\u01b5\1\367\1\370\1\367\1\0\1\367\1\u01b5\1\0"+
+    "\1\367\1\u011a\1\367\3\0\2\367\2\0\3\367\1\0"+
+    "\1\367\13\0\1\u01b5\2\367\1\u01b5\2\367\1\u01b5\2\367"+
+    "\1\0\4\367\1\0\1\u01b5\2\367\1\0\1\u01b5\2\367"+
+    "\4\0\1\u01b6\1\u0121\1\u0122\1\u0121\1\0\1\u0121\1\u01b6"+
+    "\1\0\1\u0121\1\u0125\13\u0121\1\0\14\u0121\1\u01b6\2\u0121"+
+    "\1\u01b6\2\u0121\1\u01b6\10\u0121\1\u01b6\3\u0121\1\u01b6\5\u0121"+
+    "\1\0\1\u01b7\1\u0123\1\u014c\1\u0123\1\u0149\1\u0123\1\u01b7"+
+    "\33\u0123\1\u01b7\2\u0123\1\u01b7\2\u0123\1\u01b7\10\u0123\1\u01b7"+
+    "\3\u0123\1\u01b7\5\u0123\1\0\1\u01b8\1\u0124\1\u014d\3\u0124"+
+    "\1\u01b8\1\u0149\32\u0124\1\u01b8\2\u0124\1\u01b8\2\u0124\1\u01b8"+
+    "\10\u0124\1\u01b8\3\u0124\1\u01b8\5\u0124\1\0\1\u01b9\5\0"+
+    "\1\u01b9\11\0\1\u01b9\5\0\1\u01b9\13\0\2\u01b9\1\0"+
+    "\2\u01b9\1\0\2\u01b9\7\0\2\u01b9\2\0\2\u01b9\5\0"+
+    "\1\u01ba\1\u0135\1\u0136\1\u0135\1\0\1\u0135\1\u01ba\1\0"+
+    "\1\u0135\1\u013a\13\u0135\1\0\14\u0135\1\u01ba\2\u0135\1\u01ba"+
+    "\2\u0135\1\u01ba\10\u0135\1\u01ba\3\u0135\1\u01ba\5\u0135\1\0"+
+    "\1\u01bb\1\u0138\1\u0160\1\u0138\1\u015d\1\u0138\1\u01bb\33\u0138"+
+    "\1\u01bb\2\u0138\1\u01bb\2\u0138\1\u01bb\10\u0138\1\u01bb\3\u0138"+
+    "\1\u01bb\5\u0138\1\0\1\u01bc\1\u0139\1\u0161\3\u0139\1\u01bc"+
+    "\1\u015d\32\u0139\1\u01bc\2\u0139\1\u01bc\2\u0139\1\u01bc\10\u0139"+
+    "\1\u01bc\3\u0139\1\u01bc\5\u0139\53\0\1\u01bd\21\0\2\367"+
+    "\1\370\1\367\1\0\2\367\1\0\1\367\1\u011a\1\367"+
+    "\3\0\2\367\2\0\3\367\1\0\1\367\13\0\11\367"+
+    "\1\0\4\367\1\0\3\367\1\0\3\367\4\0\1\u01be"+
+    "\1\u0121\1\u0122\1\u0121\1\0\1\u0121\1\u01be\1\0\1\u0121"+
+    "\1\u0125\13\u0121\1\0\14\u0121\1\u01be\2\u0121\1\u01be\2\u0121"+
+    "\1\u01be\10\u0121\1\u01be\3\u0121\1\u01be\5\u0121\1\0\1\u01bf"+
+    "\1\u0123\1\u014c\1\u0123\1\u0149\1\u0123\1\u01bf\33\u0123\1\u01bf"+
+    "\2\u0123\1\u01bf\2\u0123\1\u01bf\10\u0123\1\u01bf\3\u0123\1\u01bf"+
+    "\5\u0123\1\0\1\u01c0\1\u0124\1\u014d\3\u0124\1\u01c0\1\u0149"+
+    "\32\u0124\1\u01c0\2\u0124\1\u01c0\2\u0124\1\u01c0\10\u0124\1\u01c0"+
+    "\3\u0124\1\u01c0\5\u0124\1\0\1\u01c1\1\u0135\1\u0136\1\u0135"+
+    "\1\0\1\u0135\1\u01c1\1\0\1\u0135\1\u013a\13\u0135\1\0"+
+    "\14\u0135\1\u01c1\2\u0135\1\u01c1\2\u0135\1\u01c1\10\u0135\1\u01c1"+
+    "\3\u0135\1\u01c1\5\u0135\1\0\1\u01c2\1\u0138\1\u0160\1\u0138"+
+    "\1\u015d\1\u0138\1\u01c2\33\u0138\1\u01c2\2\u0138\1\u01c2\2\u0138"+
+    "\1\u01c2\10\u0138\1\u01c2\3\u0138\1\u01c2\5\u0138\1\0\1\u01c3"+
+    "\1\u0139\1\u0161\3\u0139\1\u01c3\1\u015d\32\u0139\1\u01c3\2\u0139"+
+    "\1\u01c3\2\u0139\1\u01c3\10\u0139\1\u01c3\3\u0139\1\u01c3\5\u0139"+
+    "\1\0\2\u0121\1\u0122\1\u0121\1\0\2\u0121\1\0\1\u0121"+
+    "\1\u0125\13\u0121\1\0\45\u0121\1\0\1\u01c4\1\u0123\1\u014c"+
+    "\1\u0123\1\u0149\1\u0123\1\u01c4\33\u0123\1\u01c4\2\u0123\1\u01c4"+
+    "\2\u0123\1\u01c4\10\u0123\1\u01c4\3\u0123\1\u01c4\5\u0123\1\0"+
+    "\1\u01c5\1\u0124\1\u014d\3\u0124\1\u01c5\1\u0149\32\u0124\1\u01c5"+
+    "\2\u0124\1\u01c5\2\u0124\1\u01c5\10\u0124\1\u01c5\3\u0124\1\u01c5"+
+    "\5\u0124\1\0\2\u0135\1\u0136\1\u0135\1\0\2\u0135\1\0"+
+    "\1\u0135\1\u013a\13\u0135\1\0\45\u0135\1\0\1\u01c6\1\u0138"+
+    "\1\u0160\1\u0138\1\u015d\1\u0138\1\u01c6\33\u0138\1\u01c6\2\u0138"+
+    "\1\u01c6\2\u0138\1\u01c6\10\u0138\1\u01c6\3\u0138\1\u01c6\5\u0138"+
+    "\1\0\1\u01c7\1\u0139\1\u0161\3\u0139\1\u01c7\1\u015d\32\u0139"+
+    "\1\u01c7\2\u0139\1\u01c7\2\u0139\1\u01c7\10\u0139\1\u01c7\3\u0139"+
+    "\1\u01c7\5\u0139\1\0\2\u0123\1\u014c\1\u0123\1\u0149\66\u0123"+
+    "\1\0\2\u0124\1\u014d\4\u0124\1\u0149\63\u0124\1\0\2\u0138"+
+    "\1\u0160\1\u0138\1\u015d\66\u0138\1\0\2\u0139\1\u0161\4\u0139"+
+    "\1\u015d\63\u0139";
+
+  private static int [] zzUnpackTrans() {
+    int [] result = new int[22260];
+    int offset = 0;
+    offset = zzUnpackTrans(ZZ_TRANS_PACKED_0, offset, result);
+    return result;
+  }
+
+  private static int zzUnpackTrans(String packed, int offset, int [] result) {
+    int i = 0;       /* index in packed string  */
+    int j = offset;  /* index in unpacked array */
+    int l = packed.length();
+    while (i < l) {
+      int count = packed.charAt(i++);
+      int value = packed.charAt(i++);
+      value--;
+      do result[j++] = value; while (--count > 0);
+    }
+    return j;
+  }
+
+
+  /* error codes */
+  private static final int ZZ_UNKNOWN_ERROR = 0;
+  private static final int ZZ_NO_MATCH = 1;
+  private static final int ZZ_PUSHBACK_2BIG = 2;
+
+  /* error messages for the codes above */
+  private static final String ZZ_ERROR_MSG[] = {
+    "Unkown internal scanner error",
+    "Error: could not match input",
+    "Error: pushback value was too large"
+  };
+
+  /**
+   * ZZ_ATTRIBUTE[aState] contains the attributes of state <code>aState</code>
+   */
+  private static final int [] ZZ_ATTRIBUTE = zzUnpackAttribute();
+
+  private static final String ZZ_ATTRIBUTE_PACKED_0 =
+    "\30\0\1\11\10\1\1\11\2\1\1\11\1\1\1\11"+
+    "\4\1\1\11\6\1\1\11\3\1\2\11\3\1\1\11"+
+    "\1\1\1\3\2\11\3\1\1\11\1\1\1\11\10\1"+
+    "\2\11\5\1\1\11\7\1\1\11\1\3\3\1\3\11"+
+    "\1\1\1\0\3\1\1\0\1\1\2\0\1\1\2\0"+
+    "\1\11\6\0\1\1\3\0\1\11\5\0\1\11\4\0"+
+    "\2\1\1\0\2\1\1\0\2\1\1\15\1\0\2\1"+
+    "\1\0\1\1\2\0\1\11\2\0\1\1\1\0\3\1"+
+    "\2\0\1\11\1\0\1\11\1\1\2\0\1\11\2\0"+
+    "\4\1\2\0\1\1\2\0\1\15\1\1\1\0\1\11"+
+    "\1\0\1\1\1\11\2\1\10\0\1\1\1\0\1\1"+
+    "\2\0\1\1\2\0\1\1\2\0\1\1\2\0\5\1"+
+    "\1\0\1\1\2\0\1\1\1\0\3\1\1\0\1\1"+
+    "\2\0\1\1\1\0\3\1\3\0\3\1\1\11\5\0"+
+    "\1\11\2\0\1\1\5\0\5\1\2\0\3\1\2\0"+
+    "\2\1\1\0\1\1\1\0\1\11\3\1\3\0\1\11"+
+    "\2\0\1\11\1\0\1\1\10\0\1\11\5\1\2\0"+
+    "\3\1\2\0\3\1\5\0\1\11\1\0\3\1\2\0"+
+    "\1\11\2\0\1\1\6\0\1\1\2\0\5\1\2\0"+
+    "\3\1\2\0\3\1\2\0\1\1\3\0\3\1\1\0"+
+    "\1\11\2\0\1\1\13\0\5\1\2\0\3\1\2\0"+
+    "\3\1\10\0\2\1\1\11\2\0\1\1\6\0\1\1"+
+    "\1\0\1\1\2\0\1\1\2\0\3\1\2\0\1\1"+
+    "\1\0\1\1\6\0\1\1\4\0\1\11\4\0\1\11"+
+    "\3\0\1\11\12\0";
+
+  private static int [] zzUnpackAttribute() {
+    int [] result = new int[455];
+    int offset = 0;
+    offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result);
+    return result;
+  }
+
+  private static int zzUnpackAttribute(String packed, int offset, int [] result) {
+    int i = 0;       /* index in packed string  */
+    int j = offset;  /* index in unpacked array */
+    int l = packed.length();
+    while (i < l) {
+      int count = packed.charAt(i++);
+      int value = packed.charAt(i++);
+      do result[j++] = value; while (--count > 0);
+    }
+    return j;
+  }
+
+  /** the input device */
+  private java.io.Reader zzReader;
+
+  /** the current state of the DFA */
+  private int zzState;
+
+  /** the current lexical state */
+  private int zzLexicalState = YYINITIAL;
+
+  /** this buffer contains the current text to be matched and is
+      the source of the yytext() string */
+  private char zzBuffer[] = new char[ZZ_BUFFERSIZE];
+
+  /** the textposition at the last accepting state */
+  private int zzMarkedPos;
+
+  /** the textposition at the last state to be included in yytext */
+  private int zzPushbackPos;
+
+  /** the current text position in the buffer */
+  private int zzCurrentPos;
+
+  /** startRead marks the beginning of the yytext() string in the buffer */
+  private int zzStartRead;
+
+  /** endRead marks the last character in the buffer, that has been read
+      from input */
+  private int zzEndRead;
+
+  /** number of newlines encountered up to the start of the matched text */
+  private int yyline;
+
+  /** the number of characters up to the start of the matched text */
+  private int yychar;
+
+  /**
+   * the number of characters from the last newline up to the start of the 
+   * matched text
+   */
+  //private int yycolumn;
+
+  /** 
+   * zzAtBOL == true <=> the scanner is currently at the beginning of a line
+   */
+  //private boolean zzAtBOL = true;
+
+  /** zzAtEOF == true <=> the scanner is at the EOF */
+  private boolean zzAtEOF;
+
+  /* user code: */
+	private final static String UNDEFINED = "undefined";
+	private String fBufferedContext = null;
+	private int fBufferedStart;
+//	private int fBufferedTextLength;
+	private int fBufferedLength;
+//	private StringBuffer fBufferedText = null;
+	private CSSTextRegionFactory fRegionFactory = CSSTextRegionFactory.getInstance();
+	private int fInitialState = YYINITIAL;
+	public final static int BUFFER_SIZE_NORMAL = 16384;
+	public final static int BUFFER_SIZE_SMALL = 256;
+	private int fInitialBufferSize = BUFFER_SIZE_NORMAL;
+
+	public void setInitialState(int state) {
+		fInitialState = state;
+	}
+	
+	public void setInitialBufferSize(int size) {
+		fInitialBufferSize = size;
+	}
+
+	/* user method */
+  	public final ITextRegion getNextToken() throws IOException {
+		String context;
+		String nextTokenType;
+		boolean spaceFollows;
+//		StringBuffer text;
+		int start;
+		int textLength;
+		int length;
+		if (fBufferedContext != null) {
+			context = fBufferedContext;
+//			text = fBufferedText;
+			start = fBufferedStart;
+			textLength = length = fBufferedLength;
+
+			fBufferedContext = null;
+		} else {
+			context = primGetNextToken();
+//			text = new StringBuffer(yytext());
+			start = yychar;
+			textLength = length = yylength();
+		}
+
+		if (context != null) {
+			if (context == CSS_JSP_SCRIPTLET || context == CSS_JSP_EL){
+				nextTokenType = primGetNextToken();
+				while (nextTokenType != CSS_JSP_END && nextTokenType != CSS_EL_END && nextTokenType != CSS_JSP_COMMENT) {
+//					text.append(yytext());
+					textLength += yylength();
+					length = textLength;
+					if (context.equals(CSS_JSP_SCRIPTLET) && (yystate() == ST_JSP_DIRECTIVE || yystate() == ST_JSP_EXP || yystate() == ST_JSP_DECLARATION)){
+						context = nextTokenType;
+					}
+
+					nextTokenType = primGetNextToken();
+					if (nextTokenType == null){
+						break;
+					}
+				}
+				// [236008] - Should not try and consider the token a
+				// comment unless  a comment was started
+				if (context == CSS_JSP_SCRIPTLET && nextTokenType == CSS_JSP_COMMENT){
+					while (nextTokenType != CSS_JSP_COMMENT_END) {
+//						text.append(yytext());
+						textLength += yylength();
+						length = textLength;
+						if (context.equals(CSS_JSP_SCRIPTLET) && yystate() == ST_JSP_COMMENT){
+							context = nextTokenType;
+						}
+
+						nextTokenType = primGetNextToken();
+						if (nextTokenType == null){
+							break;
+						}
+					}				
+					if (context == CSS_JSP_COMMENT){
+						context = CSS_COMMENT;
+					}
+				}
+				textLength += yylength();
+				length = textLength;
+				
+			}
+			if (context == UNDEFINED) {
+				// undef -> concatenate undef's
+				nextTokenType = primGetNextToken();
+				while (nextTokenType == UNDEFINED) {
+//					text.append(yytext());
+					textLength += yylength();
+					length = textLength;
+					nextTokenType = primGetNextToken();
+				}
+				fBufferedContext = nextTokenType;
+//				fBufferedText = new StringBuffer(yytext());
+				fBufferedStart = yychar;
+				fBufferedLength = yylength();
+			} else {
+				nextTokenType = null;
+				spaceFollows = false;
+				if (CSSRegionUtil.isDeclarationValueType(context)) { // declaration value can contain VALUE_S
+					nextTokenType = primGetNextToken();
+					spaceFollows = (nextTokenType == CSS_DECLARATION_VALUE_S);
+				} else if (canContainSpace(context)) {
+					nextTokenType = primGetNextToken();
+					spaceFollows = (nextTokenType == CSS_S);
+				}
+				if (nextTokenType != null) { // nextToken is retrieved
+					if (spaceFollows) {
+						// next is space -> append
+//						text.append(yytext());
+						length += yylength();
+					} else {
+						// next is NOT space -> push this for next time, return itself
+						fBufferedContext = nextTokenType;
+//						fBufferedText = new StringBuffer(yytext());
+						fBufferedStart = yychar;
+						fBufferedLength = yylength();
+					}
+				}
+			}
+		}
+
+		if (context != null) {
+			if (context == UNDEFINED) {
+				context = CSS_UNKNOWN;
+			}
+			return fRegionFactory.createRegion(context, start, textLength, length);
+		} else {
+			return null;
+		}
+  	}
+
+	/* user method */
+	/* for standalone use */
+  	public final List parseText() throws IOException {
+  		List tokens = new ArrayList();
+
+  		CSSTextToken token;
+		for (String kind = primGetNextToken(); kind != null; kind = primGetNextToken()) {
+			token = new CSSTextToken();
+			token.kind = kind;  				
+			token.start = yychar;
+			token.length = yylength();
+			token.image = yytext();
+			tokens.add(token);
+		}
+
+  		return tokens;
+  	}
+  	
+  	/* user method */
+  	private boolean canContainSpace(String type) {
+  		if (type == CSS_DELIMITER || type == CSS_RBRACE || type == CSS_DECLARATION_DELIMITER) {
+  			return false;
+  		} else {
+  			return true;
+  		}
+  	}
+
+	/* user method */
+	public final int getOffset() {
+		return yychar;
+	}
+	
+	/* user method */
+	public final boolean isEOF() {
+		return zzAtEOF;
+	}
+
+	/* user method */
+	public void reset(char[] charArray) {
+		reset(new CharArrayReader(charArray), 0);
+	}
+
+	/* user method */
+	public final void reset(java.io.Reader in, int newOffset) {
+		/** the input device */
+		zzReader = in;
+
+		/** the current state of the DFA */
+		zzState = 0;
+
+		/** the current lexical state */
+		zzLexicalState = fInitialState; //YYINITIAL;
+
+		/** this buffer contains the current text to be matched and is
+			the source of the yytext() string */
+		if (zzBuffer.length != fInitialBufferSize) {
+			zzBuffer = new char[fInitialBufferSize];
+		}
+		java.util.Arrays.fill(zzBuffer, (char)0);
+
+		/** the textposition at the last accepting state */
+		zzMarkedPos = 0;
+
+		/** the textposition at the last state to be included in yytext */
+		zzPushbackPos = 0;
+
+		/** the current text position in the buffer */
+		zzCurrentPos = 0;
+
+		/** startRead marks the beginning of the yytext() string in the buffer */
+		zzStartRead = 0;
+
+		/** endRead marks the last character in the buffer, that has been read
+			from input */
+		zzEndRead = 0;
+
+		/** number of newlines encountered up to the start of the matched text */
+		yyline = 0;
+
+		/** the number of characters up to the start of the matched text */
+		yychar = 0;
+
+		/**
+		 * the number of characters from the last newline up to the start of the 
+		 * matched text
+		 */
+		//yycolumn = 0; 
+
+		/** 
+		 * yy_atBOL == true <=> the scanner is currently at the beginning of a line
+		 */
+		//zzAtBOL = false;
+		
+		/** yy_atEOF == true <=> the scanner has returned a value for EOF */
+		zzAtEOF = false;
+
+		/* user variables */
+		//		fUndefined.delete(0, fUndefined.length());
+	}
+
+	/* user method */
+	public JSPedCSSTokenizer() {
+		super();
+	}
+	
+	private int fJSPPreviousState = fInitialState;
+	private void yyJspBegin(int newstate){
+		fJSPPreviousState = yystate();
+		yybegin(newstate);
+	}
+	private void yyJspEnd(){
+		yybegin(fJSPPreviousState);
+	}
+
+
+  /**
+   * Creates a new scanner
+   * There is also a java.io.InputStream version of this constructor.
+   *
+   * @param   in  the java.io.Reader to read input from.
+   */
+  public JSPedCSSTokenizer(java.io.Reader in) {
+    this.zzReader = in;
+  }
+
+  /**
+   * Creates a new scanner.
+   * There is also java.io.Reader version of this constructor.
+   *
+   * @param   in  the java.io.Inputstream to read input from.
+   */
+  public JSPedCSSTokenizer(java.io.InputStream in) {
+    this(new java.io.InputStreamReader(in));
+  }
+
+  /** 
+   * Unpacks the compressed character translation table.
+   *
+   * @param packed   the packed character translation table
+   * @return         the unpacked character translation table
+   */
+  private static char [] zzUnpackCMap(String packed) {
+    char [] map = new char[0x10000];
+    int i = 0;  /* index in packed string  */
+    int j = 0;  /* index in unpacked array */
+    while (i < 170) {
+      int  count = packed.charAt(i++);
+      char value = packed.charAt(i++);
+      do map[j++] = value; while (--count > 0);
+    }
+    return map;
+  }
+
+
+  /**
+   * Refills the input buffer.
+   *
+   * @return      <code>false</code>, iff there was new input.
+   * 
+   * @exception   java.io.IOException  if any I/O-Error occurs
+   */
+  private boolean zzRefill() throws java.io.IOException {
+
+    /* first: make room (if you can) */
+    if (zzStartRead > 0) {
+      System.arraycopy(zzBuffer, zzStartRead,
+                       zzBuffer, 0,
+                       zzEndRead-zzStartRead);
+
+      /* translate stored positions */
+      zzEndRead-= zzStartRead;
+      zzCurrentPos-= zzStartRead;
+      zzMarkedPos-= zzStartRead;
+      zzPushbackPos-= zzStartRead;
+      zzStartRead = 0;
+    }
+
+    /* is the buffer big enough? */
+    if (zzCurrentPos >= zzBuffer.length) {
+      /* if not: blow it up */
+      char newBuffer[] = new char[zzCurrentPos*2];
+      System.arraycopy(zzBuffer, 0, newBuffer, 0, zzBuffer.length);
+      zzBuffer = newBuffer;
+    }
+
+    /* finally: fill the buffer with new input */
+    int numRead = zzReader.read(zzBuffer, zzEndRead,
+                                            zzBuffer.length-zzEndRead);
+
+    if (numRead < 0) {
+      return true;
+    }
+    else {
+      zzEndRead+= numRead;
+      return false;
+    }
+  }
+
+    
+  /**
+   * Closes the input stream.
+   */
+  public final void yyclose() throws java.io.IOException {
+    zzAtEOF = true;            /* indicate end of file */
+    zzEndRead = zzStartRead;  /* invalidate buffer    */
+
+    if (zzReader != null)
+      zzReader.close();
+  }
+
+
+  /**
+   * Resets the scanner to read from a new input stream.
+   * Does not close the old reader.
+   *
+   * All internal variables are reset, the old input stream 
+   * <b>cannot</b> be reused (internal buffer is discarded and lost).
+   * Lexical state is set to <tt>ZZ_INITIAL</tt>.
+   *
+   * @param reader   the new input stream 
+   */
+  public final void yyreset(java.io.Reader reader) {
+    zzReader = reader;
+   // zzAtBOL  = true;
+    zzAtEOF  = false;
+    zzEndRead = zzStartRead = 0;
+    zzCurrentPos = zzMarkedPos = zzPushbackPos = 0;
+    yyline = yychar = 0;//yycolumn = 0;
+    zzLexicalState = YYINITIAL;
+  }
+
+
+  /**
+   * Returns the current lexical state.
+   */
+  public final int yystate() {
+    return zzLexicalState;
+  }
+
+
+  /**
+   * Enters a new lexical state
+   *
+   * @param newState the new lexical state
+   */
+  public final void yybegin(int newState) {
+    zzLexicalState = newState;
+  }
+
+
+  /**
+   * Returns the text matched by the current regular expression.
+   */
+  public final String yytext() {
+    return new String( zzBuffer, zzStartRead, zzMarkedPos-zzStartRead );
+  }
+
+
+  /**
+   * Returns the character at position <tt>pos</tt> from the 
+   * matched text. 
+   * 
+   * It is equivalent to yytext().charAt(pos), but faster
+   *
+   * @param pos the position of the character to fetch. 
+   *            A value from 0 to yylength()-1.
+   *
+   * @return the character at position pos
+   */
+  public final char yycharat(int pos) {
+    return zzBuffer[zzStartRead+pos];
+  }
+
+
+  /**
+   * Returns the length of the matched text region.
+   */
+  public final int yylength() {
+    return zzMarkedPos-zzStartRead;
+  }
+
+
+  /**
+   * Reports an error that occured while scanning.
+   *
+   * In a wellformed scanner (no or only correct usage of 
+   * yypushback(int) and a match-all fallback rule) this method 
+   * will only be called with things that "Can't Possibly Happen".
+   * If this method is called, something is seriously wrong
+   * (e.g. a JFlex bug producing a faulty scanner etc.).
+   *
+   * Usual syntax/scanner level error handling should be done
+   * in error fallback rules.
+   *
+   * @param   errorCode  the code of the errormessage to display
+   */
+  private void zzScanError(int errorCode) {
+    String message;
+    try {
+      message = ZZ_ERROR_MSG[errorCode];
+    }
+    catch (ArrayIndexOutOfBoundsException e) {
+      message = ZZ_ERROR_MSG[ZZ_UNKNOWN_ERROR];
+    }
+
+    throw new Error(message);
+  } 
+
+
+  /**
+   * Pushes the specified amount of characters back into the input stream.
+   *
+   * They will be read again by then next call of the scanning method
+   *
+   * @param number  the number of characters to be read again.
+   *                This number must not be greater than yylength()!
+   */
+  public void yypushback(int number)  {
+    if ( number > yylength() )
+      zzScanError(ZZ_PUSHBACK_2BIG);
+
+    zzMarkedPos -= number;
+  }
+
+
+  /**
+   * Resumes scanning until the next regular expression is matched,
+   * the end of input is encountered or an I/O-Error occurs.
+   *
+   * @return      the next token
+   * @exception   java.io.IOException  if any I/O-Error occurs
+   */
+  public String primGetNextToken() throws java.io.IOException {
+    int zzInput;
+    int zzAction;
+
+    // cached fields:
+    int zzCurrentPosL;
+    int zzMarkedPosL;
+    int zzEndReadL = zzEndRead;
+    char [] zzBufferL = zzBuffer;
+    char [] zzCMapL = ZZ_CMAP;
+
+    int [] zzTransL = ZZ_TRANS;
+    int [] zzRowMapL = ZZ_ROWMAP;
+    int [] zzAttrL = ZZ_ATTRIBUTE;
+    int zzPushbackPosL = zzPushbackPos = -1;
+    boolean zzWasPushback;
+
+    while (true) {
+      zzMarkedPosL = zzMarkedPos;
+
+      yychar+= zzMarkedPosL-zzStartRead;
+
+      boolean zzR = false;
+      for (zzCurrentPosL = zzStartRead; zzCurrentPosL < zzMarkedPosL;
+                                                             zzCurrentPosL++) {
+        switch (zzBufferL[zzCurrentPosL]) {
+        case '\u000B':
+        case '\u000C':
+        case '\u0085':
+        case '\u2028':
+        case '\u2029':
+          yyline++;
+          zzR = false;
+          break;
+        case '\r':
+          yyline++;
+          zzR = true;
+          break;
+        case '\n':
+          if (zzR)
+            zzR = false;
+          else {
+            yyline++;
+          }
+          break;
+        default:
+          zzR = false;
+        }
+      }
+
+      if (zzR) {
+        // peek one character ahead if it is \n (if we have counted one line too much)
+        boolean zzPeek;
+        if (zzMarkedPosL < zzEndReadL)
+          zzPeek = zzBufferL[zzMarkedPosL] == '\n';
+        else if (zzAtEOF)
+          zzPeek = false;
+        else {
+          boolean eof = zzRefill();
+          zzEndReadL = zzEndRead;
+          zzMarkedPosL = zzMarkedPos;
+          zzBufferL = zzBuffer;
+          if (eof) 
+            zzPeek = false;
+          else 
+            zzPeek = zzBufferL[zzMarkedPosL] == '\n';
+        }
+        if (zzPeek) yyline--;
+      }
+      zzAction = -1;
+
+      zzCurrentPosL = zzCurrentPos = zzStartRead = zzMarkedPosL;
+  
+      zzState = zzLexicalState;
+
+      zzWasPushback = false;
+
+      zzForAction: {
+        while (true) {
+    
+          if (zzCurrentPosL < zzEndReadL)
+            zzInput = zzBufferL[zzCurrentPosL++];
+          else if (zzAtEOF) {
+            zzInput = YYEOF;
+            break zzForAction;
+          }
+          else {
+            // store back cached positions
+            zzCurrentPos  = zzCurrentPosL;
+            zzMarkedPos   = zzMarkedPosL;
+            zzPushbackPos = zzPushbackPosL;
+            boolean eof = zzRefill();
+            // get translated positions and possibly new buffer
+            zzCurrentPosL  = zzCurrentPos;
+            zzMarkedPosL   = zzMarkedPos;
+            zzBufferL      = zzBuffer;
+            zzEndReadL     = zzEndRead;
+            zzPushbackPosL = zzPushbackPos;
+            if (eof) {
+              zzInput = YYEOF;
+              break zzForAction;
+            }
+            else {
+              zzInput = zzBufferL[zzCurrentPosL++];
+            }
+          }
+          int zzNext = zzTransL[ zzRowMapL[zzState] + zzCMapL[zzInput] ];
+          if (zzNext == -1) break zzForAction;
+          zzState = zzNext;
+
+          int zzAttributes = zzAttrL[zzState];
+          if ( (zzAttributes & 2) == 2 )
+            zzPushbackPosL = zzCurrentPosL;
+
+          if ( (zzAttributes & 1) == 1 ) {
+            zzWasPushback = (zzAttributes & 4) == 4;
+            zzAction = zzState;
+            zzMarkedPosL = zzCurrentPosL;
+            if ( (zzAttributes & 8) == 8 ) break zzForAction;
+          }
+
+        }
+      }
+
+      // store back cached position
+      zzMarkedPos = zzMarkedPosL;
+      if (zzWasPushback)
+        zzMarkedPos = zzPushbackPosL;
+
+      switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) {
+        case 38: 
+          { yybegin(ST_IMPORT_MEDIUM); return CSS_STRING;
+          }
+        case 60: break;
+        case 39: 
+          { yybegin(ST_DECLARATION_VALUE); return CSS_DECLARATION_VALUE_DIMENSION;
+          }
+        case 61: break;
+        case 44: 
+          { return CSS_DECLARATION_VALUE_S;
+          }
+        case 62: break;
+        case 41: 
+          { yybegin(ST_DECLARATION_VALUE); return CSS_DECLARATION_VALUE_FUNCTION;
+          }
+        case 63: break;
+        case 19: 
+          { yybegin(ST_SELECTOR_MODIFIER); return CSS_SELECTOR_ATTRIBUTE_END;
+          }
+        case 64: break;
+        case 1: 
+          { return UNDEFINED;
+          }
+        case 65: break;
+        case 8: 
+          { yybegin(ST_IMPORT_DELIMITER); return CSS_MEDIUM;
+          }
+        case 66: break;
+        case 42: 
+          { yybegin(ST_DECLARATION_VALUE); return CSS_DECLARATION_VALUE_STRING;
+          }
+        case 67: break;
+        case 32: 
+          { yybegin(ST_SELECTOR_MODIFIER); return CSS_SELECTOR_CLASS;
+          }
+        case 68: break;
+        case 11: 
+          { yybegin(YYINITIAL); return CSS_LBRACE;
+          }
+        case 69: break;
+        case 4: 
+          { yybegin(YYINITIAL); return CSS_RBRACE;
+          }
+        case 70: break;
+        case 10: 
+          { yybegin(ST_MEDIA_DELIMITER); return CSS_MEDIUM;
+          }
+        case 71: break;
+        case 9: 
+          { yybegin(ST_IMPORT_MEDIUM); return CSS_MEDIA_SEPARATOR;
+          }
+        case 72: break;
+        case 23: 
+          { yybegin(ST_DECLARATION_PRE_VALUE); return CSS_DECLARATION_SEPARATOR;
+          }
+        case 73: break;
+        case 58: 
+          { yybegin(ST_FONT_FACE_DELIMITER); return CSS_FONT_FACE;
+          }
+        case 74: break;
+        case 57: 
+          { yybegin(ST_CHARSET_NAME); return CSS_CHARSET;
+          }
+        case 75: break;
+        case 31: 
+          { yyJspEnd(); return CSS_EL_END;
+          }
+        case 76: break;
+        case 46: 
+          { yyJspEnd();  return CSS_JSP_END;
+          }
+        case 77: break;
+        case 53: 
+          { yybegin(ST_IMPORT_MEDIUM); return CSS_URI;
+          }
+        case 78: break;
+        case 18: 
+          { yybegin(ST_SELECTOR_ATTRIBUTE_VALUE); return CSS_SELECTOR_ATTRIBUTE_OPERATOR;
+          }
+        case 79: break;
+        case 47: 
+          { return CSS_CDC;
+          }
+        case 80: break;
+        case 14: 
+          { yybegin(ST_DECLARATION); return CSS_LBRACE;
+          }
+        case 81: break;
+        case 5: 
+          { yybegin(ST_SELECTOR_MODIFIER); return CSS_SELECTOR_UNIVERSAL;
+          }
+        case 82: break;
+        case 6: 
+          { yybegin(ST_SELECTOR_ATTRIBUTE_NAME); return CSS_SELECTOR_ATTRIBUTE_START;
+          }
+        case 83: break;
+        case 49: 
+          { return CSS_CDO;
+          }
+        case 84: break;
+        case 7: 
+          { yybegin(YYINITIAL); return CSS_DELIMITER;
+          }
+        case 85: break;
+        case 17: 
+          { yybegin(ST_SELECTOR_ATTRIBUTE_OPERATOR); return CSS_SELECTOR_ATTRIBUTE_NAME;
+          }
+        case 86: break;
+        case 43: 
+          { yybegin(ST_DECLARATION_VALUE); return CSS_DECLARATION_VALUE_HASH;
+          }
+        case 87: break;
+        case 52: 
+          { yybegin(ST_PAGE_PSEUDO_PAGE); return CSS_PAGE;
+          }
+        case 88: break;
+        case 2: 
+          { yybegin(ST_SELECTOR_MODIFIER); return CSS_SELECTOR_ELEMENT_NAME;
+          }
+        case 89: break;
+        case 37: 
+          { yybegin(ST_CHARSET_DELIMITER); return CSS_STRING;
+          }
+        case 90: break;
+        case 35: 
+          { yyJspBegin(ST_JSP_EL);  return CSS_JSP_EL;
+          }
+        case 91: break;
+        case 24: 
+          { yybegin(ST_DECLARATION_VALUE); return CSS_DECLARATION_VALUE_NUMBER;
+          }
+        case 92: break;
+        case 15: 
+          { yybegin(ST_SELECTOR); return CSS_SELECTOR_COMBINATOR;
+          }
+        case 93: break;
+        case 48: 
+          { yybegin(ST_DECLARATION_VALUE); return CSS_DECLARATION_VALUE_UNICODE_RANGE;
+          }
+        case 94: break;
+        case 40: 
+          { yybegin(ST_DECLARATION_VALUE); return CSS_DECLARATION_VALUE_PERCENTAGE;
+          }
+        case 95: break;
+        case 12: 
+          { yybegin(ST_MEDIA_MEDIUM); return CSS_MEDIA_SEPARATOR;
+          }
+        case 96: break;
+        case 25: 
+          { yybegin(ST_DECLARATION_VALUE); return CSS_DECLARATION_VALUE_IDENT;
+          }
+        case 97: break;
+        case 13: 
+          { yybegin(ST_PAGE_DELIMITER); return CSS_PAGE_SELECTOR;
+          }
+        case 98: break;
+        case 27: 
+          { yybegin(ST_DECLARATION_VALUE); return CSS_DECLARATION_VALUE_OPERATOR;
+          }
+        case 99: break;
+        case 50: 
+          { return CSS_COMMENT;
+          }
+        case 100: break;
+        case 59: 
+          { yybegin(ST_DECLARATION_VALUE); return CSS_DECLARATION_VALUE_IMPORTANT;
+          }
+        case 101: break;
+        case 20: 
+          { yybegin(ST_SELECTOR_ATTRIBUTE_END); return CSS_SELECTOR_ATTRIBUTE_VALUE;
+          }
+        case 102: break;
+        case 16: 
+          { yybegin(ST_SELECTOR); return CSS_SELECTOR_SEPARATOR;
+          }
+        case 103: break;
+        case 3: 
+          { return CSS_S;
+          }
+        case 104: break;
+        case 51: 
+          { yyJspEnd(); return CSS_JSP_COMMENT_END;
+          }
+        case 105: break;
+        case 33: 
+          { yybegin(ST_SELECTOR_MODIFIER); return CSS_SELECTOR_ID;
+          }
+        case 106: break;
+        case 30: 
+          { yybegin(ST_JSP_DECLARATION); return CSS_JSP_DECL;
+          }
+        case 107: break;
+        case 56: 
+          { yybegin(ST_IMPORT_URI); return CSS_IMPORT;
+          }
+        case 108: break;
+        case 26: 
+          { yybegin(ST_DECLARATION_VALUE); return CSS_DECLARATION_VALUE_PARENTHESIS_CLOSE;
+          }
+        case 109: break;
+        case 55: 
+          { yybegin(ST_MEDIA_MEDIUM); return CSS_MEDIA;
+          }
+        case 110: break;
+        case 29: 
+          { yybegin(ST_JSP_EXP); return CSS_JSP_EXP;
+          }
+        case 111: break;
+        case 22: 
+          { yybegin(ST_DECLARATION); return CSS_DECLARATION_DELIMITER;
+          }
+        case 112: break;
+        case 36: 
+          { yybegin(ST_SELECTOR_MODIFIER); return CSS_SELECTOR_PSEUDO;
+          }
+        case 113: break;
+        case 21: 
+          { yybegin(ST_DECLARATION_SEPARATOR); return CSS_DECLARATION_PROPERTY;
+          }
+        case 114: break;
+        case 45: 
+          { yybegin(ST_JSP_COMMENT); return CSS_JSP_COMMENT;
+          }
+        case 115: break;
+        case 34: 
+          { yyJspBegin(ST_JSP_SCRIPTLET);  return CSS_JSP_SCRIPTLET;
+          }
+        case 116: break;
+        case 54: 
+          { yybegin(ST_DECLARATION_VALUE); return CSS_DECLARATION_VALUE_URI;
+          }
+        case 117: break;
+        case 28: 
+          { yybegin(ST_JSP_DIRECTIVE); return CSS_JSP_DIRECTIVE;
+          }
+        case 118: break;
+        default: 
+          if (zzInput == YYEOF && zzStartRead == zzCurrentPos) {
+            zzAtEOF = true;
+            return null;
+          } 
+          else {
+            zzScanError(ZZ_NO_MATCH);
+          }
+      }
+    }
+  }
+
+
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/css/core/internal/parserz/JSPedCSSRegionContexts.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/css/core/internal/parserz/JSPedCSSRegionContexts.java
new file mode 100644
index 0000000..9e1b16e
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/css/core/internal/parserz/JSPedCSSRegionContexts.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.jst.jsp.css.core.internal.parserz;
+
+import org.eclipse.wst.css.core.internal.parserz.CSSRegionContexts;
+
+public interface JSPedCSSRegionContexts extends CSSRegionContexts {	
+	public static final String CSS_JSP_EXP = "CSS_JSP_EXP"; //$NON-NLS-1$
+	public static final String CSS_JSP_EL = CSSRegionContexts.CSS_FOREIGN_ELEMENT; //$NON-NLS-1$
+	public static final String CSS_JSP_SCRIPTLET = "CSS_JSP_SCRIPTLET"; //$NON-NLS-1$
+	public static final String CSS_JSP_DIRECTIVE = "CSS_JSP_DIRECTIVE"; //$NON-NLS-1$
+	public static final String CSS_JSP_DECL = "CSS_JSP_DECL"; //$NON-NLS-1$
+	public static final String CSS_JSP_END = "CSS_JSP_END"; //$NON-NLS-1$
+	public static final String CSS_EL_END = "CSS_EL_END"; //$NON-NLS-1$
+	public static final String CSS_JSP_COMMENT_END = "CSS_JSP_COMMENT_END"; //$NON-NLS-1$
+	public static final String CSS_JSP_COMMENT = "CSS_JSP_COMMENT"; //$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.wst.html.core/.classpath b/bundles/org.eclipse.wst.html.core/.classpath
new file mode 100644
index 0000000..2c6f8c1
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/.classpath
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins">
+		<accessrules>
+			<accessrule kind="accessible" pattern="org/w3c/dom/css/**/*"/>
+			<accessrule kind="accessible" pattern="org/eclipse/wst/**"/>
+		</accessrules>
+	</classpathentry>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.4"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/bundles/org.eclipse.wst.html.core/.cvsignore b/bundles/org.eclipse.wst.html.core/.cvsignore
new file mode 100644
index 0000000..02ca6cb
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/.cvsignore
@@ -0,0 +1,8 @@
+bin
+htmlmodel.jar
+temp.folder
+dev.properties
+build.xml
+@dot
+src.zip
+javaCompiler...args
diff --git a/bundles/org.eclipse.wst.html.core/.options b/bundles/org.eclipse.wst.html.core/.options
new file mode 100644
index 0000000..e66a59f
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/.options
@@ -0,0 +1,2 @@
+org.eclipse.wst.html.core/debug=true
+org.eclipse.wst.html.core/debug/tracefilter=
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.html.core/.project b/bundles/org.eclipse.wst.html.core/.project
new file mode 100644
index 0000000..13a9fac
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.wst.html.core</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.ManifestBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.SchemaBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.PluginNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
diff --git a/bundles/org.eclipse.wst.html.core/.settings/org.eclipse.core.resources.prefs b/bundles/org.eclipse.wst.html.core/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..afa5c91
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+#Tue Apr 04 03:36:32 EDT 2006
+eclipse.preferences.version=1
+encoding/<project>=ISO-8859-1
diff --git a/bundles/org.eclipse.wst.html.core/.settings/org.eclipse.core.runtime.prefs b/bundles/org.eclipse.wst.html.core/.settings/org.eclipse.core.runtime.prefs
new file mode 100644
index 0000000..7ec5750
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/.settings/org.eclipse.core.runtime.prefs
@@ -0,0 +1,3 @@
+#Mon Apr 17 01:48:39 EDT 2006
+eclipse.preferences.version=1
+line.separator=\r\n
diff --git a/bundles/org.eclipse.wst.html.core/.settings/org.eclipse.jdt.core.prefs b/bundles/org.eclipse.wst.html.core/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..0667e35
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,79 @@
+#Wed Mar 28 03:23:07 EDT 2007
+eclipse.preferences.version=1
+org.eclipse.jdt.core.builder.cleanOutputFolder=clean
+org.eclipse.jdt.core.builder.duplicateResourceTask=warning
+org.eclipse.jdt.core.builder.invalidClasspath=ignore
+org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch
+org.eclipse.jdt.core.circularClasspath=error
+org.eclipse.jdt.core.classpath.exclusionPatterns=enabled
+org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=disabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.2
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.4
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.doc.comment.support=enabled
+org.eclipse.jdt.core.compiler.maxProblemPerUnit=100
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=warning
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.deprecation=ignore
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=enabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=warning
+org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=ignore
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=error
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=error
+org.eclipse.jdt.core.compiler.problem.invalidJavadoc=ignore
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=private
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=error
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=enabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public
+org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=enabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=private
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=error
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=error
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=error
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=enabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=error
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=ignore
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=error
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedImport=error
+org.eclipse.jdt.core.compiler.problem.unusedLabel=error
+org.eclipse.jdt.core.compiler.problem.unusedLocal=error
+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=error
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.3
+org.eclipse.jdt.core.incompatibleJDKLevel=ignore
+org.eclipse.jdt.core.incompleteClasspath=error
diff --git a/bundles/org.eclipse.wst.html.core/.settings/org.eclipse.jdt.ui.prefs b/bundles/org.eclipse.wst.html.core/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000..301c7ad
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,4 @@
+#Mon Apr 17 01:48:39 EDT 2006
+eclipse.preferences.version=1
+internal.default.compliance=default
+org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8"?>\r\n<templates/>
diff --git a/bundles/org.eclipse.wst.html.core/.settings/org.eclipse.ltk.core.refactoring.prefs b/bundles/org.eclipse.wst.html.core/.settings/org.eclipse.ltk.core.refactoring.prefs
new file mode 100644
index 0000000..c59368c
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/.settings/org.eclipse.ltk.core.refactoring.prefs
@@ -0,0 +1,3 @@
+#Tue Apr 04 03:36:32 EDT 2006
+eclipse.preferences.version=1
+org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false
diff --git a/bundles/org.eclipse.wst.html.core/.settings/org.eclipse.pde.prefs b/bundles/org.eclipse.wst.html.core/.settings/org.eclipse.pde.prefs
new file mode 100644
index 0000000..061cd53
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/.settings/org.eclipse.pde.prefs
@@ -0,0 +1,16 @@
+#Mon Apr 17 02:01:33 EDT 2006

+compilers.incompatible-environment=0

+compilers.p.build=0

+compilers.p.deprecated=1

+compilers.p.illegal-att-value=0

+compilers.p.no-required-att=0

+compilers.p.not-externalized-att=0

+compilers.p.unknown-attribute=0

+compilers.p.unknown-class=0

+compilers.p.unknown-element=0

+compilers.p.unknown-resource=0

+compilers.p.unresolved-ex-points=0

+compilers.p.unresolved-import=0

+compilers.p.unused-element-or-attribute=0

+compilers.use-project=true

+eclipse.preferences.version=1

diff --git a/bundles/org.eclipse.wst.html.core/META-INF/MANIFEST.MF b/bundles/org.eclipse.wst.html.core/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..287cb52
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/META-INF/MANIFEST.MF
@@ -0,0 +1,40 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %pluginName
+Bundle-SymbolicName: org.eclipse.wst.html.core; singleton:=true
+Bundle-Version: 1.1.406.qualifier
+Bundle-Activator: org.eclipse.wst.html.core.internal.HTMLCorePlugin
+Bundle-Vendor: %providerName
+Bundle-Localization: plugin
+Export-Package: org.eclipse.wst.html.core.internal;x-internal:=true,
+ org.eclipse.wst.html.core.internal.cleanup;x-internal:=true,
+ org.eclipse.wst.html.core.internal.commentelement.handlers;x-internal:=true,
+ org.eclipse.wst.html.core.internal.contentmodel;x-internal:=true,
+ org.eclipse.wst.html.core.internal.contentmodel.chtml;x-internal:=true,
+ org.eclipse.wst.html.core.internal.contentmodel.ssi;x-internal:=true,
+ org.eclipse.wst.html.core.internal.contentproperties;x-internal:=true,
+ org.eclipse.wst.html.core.internal.contenttype;x-internal:=true,
+ org.eclipse.wst.html.core.internal.document;x-internal:=true,
+ org.eclipse.wst.html.core.internal.encoding;x-internal:=true,
+ org.eclipse.wst.html.core.internal.format;x-internal:=true,
+ org.eclipse.wst.html.core.internal.htmlcss;x-internal:=true,
+ org.eclipse.wst.html.core.internal.modelhandler;x-internal:=true,
+ org.eclipse.wst.html.core.internal.modelquery;x-internal:=true,
+ org.eclipse.wst.html.core.internal.preferences;x-internal:=true,
+ org.eclipse.wst.html.core.internal.provisional;x-internal:=true,
+ org.eclipse.wst.html.core.internal.provisional.contenttype;x-internal:=true,
+ org.eclipse.wst.html.core.internal.provisional.text;x-internal:=true,
+ org.eclipse.wst.html.core.internal.text;x-internal:=true,
+ org.eclipse.wst.html.core.internal.validate;x-internal:=true,
+ org.eclipse.wst.html.core.text
+Import-Package: com.ibm.icu.util; version="3.8"
+Require-Bundle: org.eclipse.core.resources;bundle-version="[3.5.0,4.0.0)",
+ org.eclipse.core.runtime;bundle-version="[3.5.0,4.0.0)",
+ org.eclipse.wst.common.uriresolver;bundle-version="[1.1.301,1.2.0)",
+ org.eclipse.wst.sse.core;bundle-version="[1.1.500,1.2.0)",
+ org.eclipse.wst.xml.core;bundle-version="[1.1.500,1.2.0)",
+ org.eclipse.wst.css.core;bundle-version="[1.1.400,1.2.0)",
+ org.eclipse.core.filebuffers;bundle-version="[3.5.0,4.0.0)",
+ org.eclipse.wst.common.modulecore;bundle-version="[1.2.0,2.0.0)";resolution:=optional
+Bundle-ActivationPolicy: lazy;exclude:="org.eclipse.wst.html.core.internal.contenttype,org.eclipse.wst.html.core.internal.provisional.contenttype"
+Bundle-RequiredExecutionEnvironment: J2SE-1.4
diff --git a/bundles/org.eclipse.wst.html.core/about.html b/bundles/org.eclipse.wst.html.core/about.html
new file mode 100644
index 0000000..2199df3
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/about.html
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
+<HTML>
+
+<head>
+<title>About</title>
+<meta http-equiv=Content-Type content="text/html; charset=ISO-8859-1">
+</head>
+
+<BODY lang="EN-US">
+
+<H3>About This Content</H3>
+
+<P>June, 2008</P>
+
+<H3>License</H3>
+
+<P>The Eclipse Foundation makes available all content in this plug-in 
+("Content"). Unless otherwise indicated below, the Content is provided to you 
+under the terms and conditions of the Eclipse Public License Version 1.0 
+("EPL"). A copy of the EPL is available at
+<A href="http://www.eclipse.org/org/documents/epl-v10.php">http://www.eclipse.org/org/documents/epl-v10.php</A>. 
+For purposes of the EPL, "Program" will mean the Content.</P>
+
+<P>If you did not receive this Content directly from the Eclipse Foundation, the 
+Content is being redistributed by another party ("Redistributor") and different 
+terms and conditions may apply to your use of any object code in the Content. 
+Check the RedistributorÂ’s license that was provided with the Content. If no such 
+license exists, contact the Redistributor. Unless otherwise indicated below, the 
+terms and conditions of the EPL still apply to any source code in the Content 
+and such source code may be obtained at
+<A href="http://www.eclipse.org/">http://www.eclipse.org/</A>.</P>
+
+</BODY>
+</HTML>
diff --git a/bundles/org.eclipse.wst.html.core/build.properties b/bundles/org.eclipse.wst.html.core/build.properties
new file mode 100644
index 0000000..5c655fd
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/build.properties
@@ -0,0 +1,22 @@
+###############################################################################
+# Copyright (c) 2004, 2005 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
+###############################################################################
+bin.includes = plugin.xml,\
+               .options,\
+               data/,\
+               plugin.properties,\
+               META-INF/,\
+               .,\
+               about.html
+bin.excludes = bin/**,\
+               @dot/**,\
+               temp.folder/**
+src.includes = component.xml
+source.. = src/
diff --git a/bundles/org.eclipse.wst.html.core/component.xml b/bundles/org.eclipse.wst.html.core/component.xml
new file mode 100644
index 0000000..8565aec
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/component.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<component xmlns="http://eclipse.org/wtp/releng/tools/component-model" name="org.eclipse.wst.html">
+	<component-depends unrestricted="true"></component-depends>
+	<plugin id="org.eclipse.wst.html.core" fragment="false" />
+	<plugin id="org.eclipse.wst.html.standard.dtds" fragment="false" />
+	<plugin id="org.eclipse.wst.html.ui" fragment="false" />
+	<description url="http://eclipse.org/webtools/wst/components/html/overview.html" />
+	<package name="org.eclipse.wst.html.ui" api="false">
+		<type name="StructuredTextViewerConfigurationHTML" subclass="true" instantiate="true" />
+	</package>
+	<package name="org.eclipse.wst.html.ui.views.contentoutline" api="false">
+		<type name="HTMLContentOutlineConfiguration" subclass="true" instantiate="true" />
+	</package>
+	<plugin id="org.eclipse.wst.html.ui.infopop" fragment="false" />
+</component>
diff --git a/bundles/org.eclipse.wst.html.core/data/htmref.properties b/bundles/org.eclipse.wst.html.core/data/htmref.properties
new file mode 100644
index 0000000..9cd460d
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/data/htmref.properties
@@ -0,0 +1,108 @@
+###############################################################################
+# Copyright (c) 2004 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
+###############################################################################
+
+ATagInfo=A link if the href attribute is present, and the target for a link if the name attribute is present
+ABBRTagInfo=An abbreviation (for example, WWW, HTTP)
+ACRONYMTagInfo=An acronym (for example, SCUBA)
+ADDRESSTagInfo=Address information for the author of the page
+APPLETTagInfo=A Java applet
+AREATagInfo=Defines a client-side image map area
+BTagInfo=Displays contained text as bold
+BASETagInfo=The base URI for the page, to be used when calculating relative paths
+BASEFONTTagInfo=The base font size for the page
+BDOTagInfo=Overrides default bidirectional display. For use with bidirectional languages.
+BIGTagInfo=Displays contained text as large
+BGSOUNDTagInfo=Defines a sound file for the page. Not supported by W3C HTML 4.01.
+BLINKTagInfo=Displays text as blinking. Not supported by W3C HTML 4.01.
+BLOCKQUOTETagInfo=A long quotation
+BODYTagInfo=The document body. Contains all the content for the page.
+BRTagInfo=Forces a line break
+BUTTONTagInfo=Defines a push button
+CAPTIONTagInfo=Defines a table caption
+CENTERTagInfo=Displays contained text centered. Equivalent to DIV with align=center.
+CITETagInfo=A citation
+CODETagInfo=A computer code fragment
+COLTagInfo=A table column
+COLGROUPTagInfo=A group of table columns
+DDTagInfo=A definition or description in a definition or description list
+DELTagInfo=Displays text as deleted
+DFNTagInfo=A definition
+DIRTagInfo=A directory listing
+DIVTagInfo=A generic container, which can be used for defining language or style for the contents
+DLTagInfo=A definition or description list
+DTTagInfo=A term or subject in a definition or description list
+EMTagInfo=Displays text emphasized (generally italicized)
+EMBEDTagInfo=Defines an embedded plug-in. Not supported by W3C HTML 4.01.
+FIELDSETTagInfo=Defines a form control group
+FONTTagInfo=Displays text in the given font
+FORMTagInfo=Defines an interactive form
+FRAMETagInfo=Defines a frame within the current window
+FRAMESETTagInfo=Defines a frameset that divides the window into frames
+H1TagInfo=A top-level heading
+H2TagInfo=A second-level heading
+H3TagInfo=A third-level heading
+H4TagInfo=A fourth-level heading
+H5TagInfo=A fifth-level heading
+H6TagInfo=A sixth-level heading
+HEADTagInfo=Contains metadata and window title information for the document
+HRTagInfo=A horizontal rule
+HTMLTagInfo=The root element for the document.
+ITagInfo=Displays text as italic
+IFRAMETagInfo=Defines an inline subwindow
+IMGTagInfo=Displays the referenced image as embedded content
+INPUTTagInfo=Defines a form control for user input
+INSTagInfo=Defines inserted text
+ISINDEXTagInfo=Defines a single line prompt
+KBDTagInfo=Defines text to be entered by the user
+LABELTagInfo=Defines the label for a form field
+LEGENDTagInfo=Defines the label for a set of form fields
+LITagInfo=Defines a list item within a list
+LINKTagInfo=A media-independent link
+MAPTagInfo=Defines a client-side image map
+MARQUEETagInfo=Displays text as scrolling. Not supported by W3C HTML 4.01.
+MENUTagInfo=Defines a menu list
+METATagInfo=Defines metadata information for the document
+NOBRTagInfo=Overrides and prevents line breaks. Not supported by W3C HTML 4.01.
+NOFRAMESTagInfo=Provides information to display if the current browser does not support frames
+NOSCRIPTTagInfo=Provides information to display if the current browser does not support scripting
+OBJECTTagInfo=Defines a generic embedded object
+OLTagInfo=An ordered list
+OPTGROUPTagInfo=An option group
+OPTIONTagInfo=A selectable choice
+PTagInfo=A paragraph
+PARAMTagInfo=A named property value
+PRETagInfo=Preformatted text
+QTagInfo=A short inline quotation
+STagInfo=Display text in strike-through style
+SAMPTagInfo=Sample program output, scripts, etc. Displays in monospace font.
+SCRIPTTagInfo=Script statements
+SELECTTagInfo=An option selector
+SMALLTagInfo=Displays text as small
+SPANTagInfo=A generic container, which can be used for defining language or style for the contents
+STRIKETagInfo=Display text in strike-through style
+STRONGTagInfo=Displays text as strongly emphasized (generally bold)
+STYLETagInfo=Defines a style for the contained information
+SUBTagInfo=Display as subscript
+SUPTagInfo=Display as superscript
+TABLETagInfo=Defines a table
+TBODYTagInfo=The body of the table
+TDTagInfo=A cell within a table
+TEXTAREATagInfo=A multi-line text field
+TFOOTTagInfo=A table footer
+THTagInfo=A table header cell
+THEADTagInfo=A table header
+TITLETagInfo=The document title, displayed in the browser's title bar
+TRTagInfo=A table row
+TTTagInfo=Displays text in teletype or monospaced text style
+UTagInfo=Displays text as underlined
+ULTagInfo=An unordered list
+VARTagInfo=An instance of a variable or program argument
+WBRTagInfo=Allows a line break within <B>&lt;NOBR&gt;</B> tag. Not supported by W3C HTML 4.01.
diff --git a/bundles/org.eclipse.wst.html.core/data/htmref.xml b/bundles/org.eclipse.wst.html.core/data/htmref.xml
new file mode 100644
index 0000000..c7bcd64
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/data/htmref.xml
@@ -0,0 +1,306 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 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
+ *******************************************************************************/
+ -->
+<abstractGrammarAnnotations propertiesLocation="htmref" caseSensitive="false">
+    <annotation spec="A">
+        <property name="tagInfo">%ATagInfo</property>
+    </annotation>
+    <annotation spec="ABBR">
+        <property name="tagInfo">%ABBRTagInfo</property>
+    </annotation>
+    <annotation spec="ACRONYM">
+        <property name="tagInfo">%ACRONYMTagInfo</property>
+    </annotation>
+    <annotation spec="ADDRESS">
+        <property name="tagInfo">%ADDRESSTagInfo</property>
+    </annotation>
+    <annotation spec="APPLET">
+        <property name="tagInfo">%APPLETTagInfo</property>
+    </annotation>
+    <annotation spec="AREA">
+        <property name="tagInfo">%AREATagInfo</property>
+    </annotation>
+    <annotation spec="B">
+        <property name="tagInfo">%BTagInfo</property>
+    </annotation>
+    <annotation spec="BASE">
+        <property name="tagInfo">%BASETagInfo</property>
+    </annotation>
+    <annotation spec="BASEFONT">
+        <property name="tagInfo">%BASEFONTTagInfo</property>
+    </annotation>
+    <annotation spec="BDO">
+        <property name="tagInfo">%BDOTagInfo</property>
+    </annotation>
+    <annotation spec="BGSOUND">
+        <property name="tagInfo">%BGSOUNDTagInfo</property>
+    </annotation>
+    <annotation spec="BIG">
+        <property name="tagInfo">%BIGTagInfo</property>
+    </annotation>
+    <annotation spec="BLINK">
+        <property name="tagInfo">%BLINKTagInfo</property>
+    </annotation>
+    <annotation spec="BLOCKQUOTE">
+        <property name="tagInfo">%BLOCKQUOTETagInfo</property>
+    </annotation>
+    <annotation spec="BODY">
+        <property name="tagInfo">%BODYTagInfo</property>
+    </annotation>
+    <annotation spec="BR">
+        <property name="tagInfo">%BRTagInfo</property>
+    </annotation>
+    <annotation spec="BUTTON">
+        <property name="tagInfo">%BUTTONTagInfo</property>
+    </annotation>
+    <annotation spec="CAPTION">
+        <property name="tagInfo">%CAPTIONTagInfo</property>
+    </annotation>
+    <annotation spec="CENTER">
+        <property name="tagInfo">%CENTERTagInfo</property>
+    </annotation>
+    <annotation spec="CITE">
+        <property name="tagInfo">%CITETagInfo</property>
+    </annotation>
+    <annotation spec="CODE">
+        <property name="tagInfo">%CODETagInfo</property>
+    </annotation>
+    <annotation spec="COL">
+        <property name="tagInfo">%COLTagInfo</property>
+    </annotation>
+    <annotation spec="COLGROUP">
+        <property name="tagInfo">%COLGROUPTagInfo</property>
+    </annotation>
+    <annotation spec="DD">
+        <property name="tagInfo">%DDTagInfo</property>
+    </annotation>
+    <annotation spec="DEL">
+        <property name="tagInfo">%DELTagInfo</property>
+    </annotation>
+    <annotation spec="DFN">
+        <property name="tagInfo">%DFNTagInfo</property>
+    </annotation>
+    <annotation spec="DIR">
+        <property name="tagInfo">%DIRTagInfo</property>
+    </annotation>
+    <annotation spec="DIV">
+        <property name="tagInfo">%DIVTagInfo</property>
+    </annotation>
+    <annotation spec="DL">
+        <property name="tagInfo">%DLTagInfo</property>
+    </annotation>
+    <annotation spec="DT">
+        <property name="tagInfo">%DTTagInfo</property>
+    </annotation>
+    <annotation spec="EM">
+        <property name="tagInfo">%EMTagInfo</property>
+    </annotation>
+    <annotation spec="EMBED">
+        <property name="tagInfo">%EMBEDTagInfo</property>
+    </annotation>
+    <annotation spec="FIELDSET">
+        <property name="tagInfo">%FIELDSETTagInfo</property>
+    </annotation>
+    <annotation spec="FONT">
+        <property name="tagInfo">%FONTTagInfo</property>
+    </annotation>
+    <annotation spec="FORM">
+        <property name="tagInfo">%FORMTagInfo</property>
+    </annotation>
+    <annotation spec="FRAME">
+        <property name="tagInfo">%FRAMETagInfo</property>
+    </annotation>
+    <annotation spec="FRAMESET">
+        <property name="tagInfo">%FRAMESETTagInfo</property>
+    </annotation>
+    <annotation spec="H1">
+        <property name="tagInfo">%H1TagInfo</property>
+    </annotation>
+    <annotation spec="H2">
+        <property name="tagInfo">%H2TagInfo</property>
+    </annotation>
+    <annotation spec="H3">
+        <property name="tagInfo">%H3TagInfo</property>
+    </annotation>
+    <annotation spec="H4">
+        <property name="tagInfo">%H4TagInfo</property>
+    </annotation>
+    <annotation spec="H5">
+        <property name="tagInfo">%H5TagInfo</property>
+    </annotation>
+    <annotation spec="H6">
+        <property name="tagInfo">%H6TagInfo</property>
+    </annotation>
+    <annotation spec="HEAD">
+        <property name="tagInfo">%HEADTagInfo</property>
+    </annotation>
+    <annotation spec="HR">
+        <property name="tagInfo">%HRTagInfo</property>
+    </annotation>
+    <annotation spec="HTML">
+        <property name="tagInfo">%HTMLTagInfo</property>
+    </annotation>
+    <annotation spec="I">
+        <property name="tagInfo">%ITagInfo</property>
+    </annotation>
+    <annotation spec="IFRAME">
+        <property name="tagInfo">%IFRAMETagInfo</property>
+    </annotation>
+    <annotation spec="IMG">
+        <property name="tagInfo">%IMGTagInfo</property>
+    </annotation>
+    <annotation spec="INPUT">
+        <property name="tagInfo">%INPUTTagInfo</property>
+    </annotation>
+    <annotation spec="INS">
+        <property name="tagInfo">%INSTagInfo</property>
+    </annotation>
+    <annotation spec="ISINDEX">
+        <property name="tagInfo">%ISINDEXTagInfo</property>
+    </annotation>
+    <annotation spec="KBD">
+        <property name="tagInfo">%KBDTagInfo</property>
+    </annotation>
+    <annotation spec="LABEL">
+        <property name="tagInfo">%LABELTagInfo</property>
+    </annotation>
+    <annotation spec="LEGEND">
+        <property name="tagInfo">%LEGENDTagInfo</property>
+    </annotation>
+    <annotation spec="LI">
+        <property name="tagInfo">%LITagInfo</property>
+    </annotation>
+    <annotation spec="LINK">
+        <property name="tagInfo">%LINKTagInfo</property>
+    </annotation>
+    <annotation spec="MAP">
+        <property name="tagInfo">%MAPTagInfo</property>
+    </annotation>
+    <annotation spec="MARQUEE">
+        <property name="tagInfo">%MARQUEETagInfo</property>
+    </annotation>
+    <annotation spec="MENU">
+        <property name="tagInfo">%MENUTagInfo</property>
+    </annotation>
+    <annotation spec="META">
+        <property name="tagInfo">%METATagInfo</property>
+    </annotation>
+    <annotation spec="NOBR">
+        <property name="tagInfo">%NOBRTagInfo</property>
+    </annotation>
+    <annotation spec="NOFRAMES">
+        <property name="tagInfo">%NOFRAMESTagInfo</property>
+    </annotation>
+    <annotation spec="NOSCRIPT">
+        <property name="tagInfo">%NOSCRIPTTagInfo</property>
+    </annotation>
+    <annotation spec="OBJECT">
+        <property name="tagInfo">%OBJECTTagInfo</property>
+    </annotation>
+    <annotation spec="OL">
+        <property name="tagInfo">%OLTagInfo</property>
+    </annotation>
+    <annotation spec="OPTGROUP">
+        <property name="tagInfo">%OPTGROUPTagInfo</property>
+    </annotation>
+    <annotation spec="OPTION">
+        <property name="tagInfo">%OPTIONTagInfo</property>
+    </annotation>
+    <annotation spec="P">
+        <property name="tagInfo">%PTagInfo</property>
+    </annotation>
+    <annotation spec="PARAM">
+        <property name="tagInfo">%PARAMTagInfo</property>
+    </annotation>
+    <annotation spec="PRE">
+        <property name="tagInfo">%PRETagInfo</property>
+    </annotation>
+    <annotation spec="Q">
+        <property name="tagInfo">%QTagInfo</property>
+    </annotation>
+    <annotation spec="S">
+        <property name="tagInfo">%STagInfo</property>
+    </annotation>
+    <annotation spec="SAMP">
+        <property name="tagInfo">%SAMPTagInfo</property>
+    </annotation>
+    <annotation spec="SCRIPT">
+        <property name="tagInfo">%SCRIPTTagInfo</property>
+    </annotation>
+    <annotation spec="SELECT">
+        <property name="tagInfo">%SELECTTagInfo</property>
+    </annotation>
+    <annotation spec="SMALL">
+        <property name="tagInfo">%SMALLTagInfo</property>
+    </annotation>
+    <annotation spec="SPAN">
+        <property name="tagInfo">%SPANTagInfo</property>
+    </annotation>
+    <annotation spec="STRIKE">
+        <property name="tagInfo">%STRIKETagInfo</property>
+    </annotation>
+    <annotation spec="STRONG">
+        <property name="tagInfo">%STRONGTagInfo</property>
+    </annotation>
+    <annotation spec="STYLE">
+        <property name="tagInfo">%STYLETagInfo</property>
+    </annotation>
+    <annotation spec="SUB">
+        <property name="tagInfo">%SUBTagInfo</property>
+    </annotation>
+    <annotation spec="SUP">
+        <property name="tagInfo">%SUPTagInfo</property>
+    </annotation>
+    <annotation spec="TABLE">
+        <property name="tagInfo">%TABLETagInfo</property>
+    </annotation>
+    <annotation spec="TBODY">
+        <property name="tagInfo">%TBODYTagInfo</property>
+    </annotation>
+    <annotation spec="TD">
+        <property name="tagInfo">%TDTagInfo</property>
+    </annotation>
+    <annotation spec="TEXTAREA">
+        <property name="tagInfo">%TEXTAREATagInfo</property>
+    </annotation>
+    <annotation spec="TFOOT">
+        <property name="tagInfo">%TFOOTTagInfo</property>
+    </annotation>
+    <annotation spec="TH">
+        <property name="tagInfo">%THTagInfo</property>
+    </annotation>
+    <annotation spec="THEAD">
+        <property name="tagInfo">%THEADTagInfo</property>
+    </annotation>
+    <annotation spec="TITLE">
+        <property name="tagInfo">%TITLETagInfo</property>
+    </annotation>
+    <annotation spec="TR">
+        <property name="tagInfo">%TRTagInfo</property>
+    </annotation>
+    <annotation spec="TT">
+        <property name="tagInfo">%TTTagInfo</property>
+    </annotation>
+    <annotation spec="U">
+        <property name="tagInfo">%UTagInfo</property>
+    </annotation>
+    <annotation spec="UL">
+        <property name="tagInfo">%ULTagInfo</property>
+    </annotation>
+    <annotation spec="VAR">
+        <property name="tagInfo">%VARTagInfo</property>
+    </annotation>
+    <annotation spec="WBR">
+        <property name="tagInfo">%WBRTagInfo</property>
+    </annotation>
+</abstractGrammarAnnotations>
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.html.core/plugin.properties b/bundles/org.eclipse.wst.html.core/plugin.properties
new file mode 100644
index 0000000..14b6fdc
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/plugin.properties
@@ -0,0 +1,16 @@
+###############################################################################
+# 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
+###############################################################################
+providerName=Eclipse Web Tools Platform
+pluginName=Structured Source HTML Model
+Structured_HTML_Document_Factory_Extension.name=Structured HTML Document Factory Extension
+HTML_Content_Type_Extension_Element.name=HTML
+_taskMarker.name=HTML Task
+_validationMarker.name=HTML Problem
diff --git a/bundles/org.eclipse.wst.html.core/plugin.xml b/bundles/org.eclipse.wst.html.core/plugin.xml
new file mode 100644
index 0000000..6c0bae8
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/plugin.xml
@@ -0,0 +1,213 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+<plugin>
+
+	<extension point="org.eclipse.wst.sse.core.modelHandler">
+		<modelHandler
+			default="no"
+			class="org.eclipse.wst.html.core.internal.modelhandler.ModelHandlerForHTML"
+			associatedContentTypeId="org.eclipse.wst.html.core.htmlsource"
+			id="org.eclipse.wst.html.core.internal.modelhandler">
+		</modelHandler>
+	</extension>
+
+	<extension point="org.eclipse.wst.sse.core.embeddedTypeHandler">
+		<embeddedTypeHandler
+			class="org.eclipse.wst.html.core.internal.modelhandler.EmbeddedHTML">
+		</embeddedTypeHandler>
+	</extension>
+
+	<extension point="org.eclipse.wst.sse.core.taskscanner">
+		<scanner
+			id="org.eclipse.wst.html.core.internal.tasks.HTMLFileTaskScanner"
+			class="org.eclipse.wst.xml.core.internal.tasks.XMLFileTaskScanner:org.eclipse.wst.html.core.taskMarker"
+			contentTypeIds="org.eclipse.wst.html.core.htmlsource" />
+	</extension>
+	<extension
+		id="taskMarker"
+		name="%_taskMarker.name"
+		point="org.eclipse.core.resources.markers">
+		<super type="org.eclipse.core.resources.taskmarker"/>
+		<persistent value="true"/>
+	</extension>
+    <extension
+       id="validationMarker"
+        name="%_validationMarker.name"
+        point="org.eclipse.core.resources.markers">
+      <super type="org.eclipse.wst.validation.problemmarker"/>
+      <persistent value="true"/>
+    </extension>
+
+	<extension
+		point="org.eclipse.core.filebuffers.documentCreation"
+		id="org.eclipse.wst.html.core.documentfactories"
+		name="%Structured_HTML_Document_Factory_Extension.name">
+		<factory
+			contentTypeId="org.eclipse.wst.html.core.htmlsource"
+			class="org.eclipse.wst.sse.core.internal.filebuffers.BasicStructuredDocumentFactory" />
+	</extension>
+
+	<extension point="org.eclipse.wst.sse.core.commentElementHandler">
+		<handler-custom
+			commenttype="xml"
+			class="org.eclipse.wst.html.core.internal.commentelement.handlers.CommentElementHandlerForSSI">
+			<startwith prefix="#"></startwith>
+		</handler-custom>
+	</extension>
+
+	<extension point="org.eclipse.team.core.fileTypes">
+		<fileTypes
+			type="text"
+			extension="html">
+		</fileTypes>
+		<fileTypes
+			type="text"
+			extension="htm">
+		</fileTypes>
+		<fileTypes
+			type="text"
+			extension="xhtml">
+		</fileTypes>
+		<fileTypes
+			type="text"
+			extension="htpl">
+		</fileTypes>
+		<fileTypes
+			type="text"
+			extension="wml">
+		</fileTypes>
+		<fileTypes
+			type="text"
+			extension="shtml">
+		</fileTypes>
+		<fileTypes
+			type="text"
+			extension="shtm">
+		</fileTypes>
+	</extension>
+
+	<extension point="org.eclipse.wst.sse.core.formatProcessors">
+		<processor
+			class="org.eclipse.wst.html.core.internal.format.HTMLFormatProcessorImpl"
+			contentTypeId="org.eclipse.wst.html.core.htmlsource">
+		</processor>
+	</extension>
+
+	<!-- Extension point for taghelp documentation -->
+	<extension point="org.eclipse.wst.xml.core.annotationFiles">
+		<annotationFile
+			location="data/htmref.xml"
+			publicId="-//W3C//DTD XHTML 1.0 Strict//EN">
+		</annotationFile>
+		<annotationFile
+			location="data/htmref.xml"
+			publicId="-//W3C//DTD XHTML 1.0 Transitional//EN">
+		</annotationFile>
+		<annotationFile
+			location="data/htmref.xml"
+			publicId="-//W3C//DTD XHTML 1.0 Frameset//EN">
+		</annotationFile>
+		<annotationFile
+			location="data/htmref.xml"
+			publicId="-//W3C//DTD XHTML Basic 1.0//EN">
+		</annotationFile>
+		<annotationFile
+			location="data/htmref.xml"
+			publicId="-//W3C//DTD XHTML 1.1//EN">
+		</annotationFile>
+		<annotationFile
+			location="data/htmref.xml"
+			publicId="-//WAPFORUM//DTD XHTML Mobile 1.0//EN">
+		</annotationFile>
+	</extension>
+
+	<extension point="org.eclipse.core.contenttype.contentTypes">
+		<content-type
+			file-extensions="html,htm,xhtml,htpl,wml,shtml,shtm"
+			priority="high"
+			name="%HTML_Content_Type_Extension_Element.name"
+			id="htmlsource"
+			base-type="org.eclipse.core.runtime.text">
+			<!-- note: no default-charset for HTML, should use 'platform' -->
+			<describer
+				class="org.eclipse.wst.html.core.internal.contenttype.ContentDescriberForHTML" />
+		</content-type>
+	</extension>
+
+<!-- moved to where the dtd's are contributed
+
+	<extension point="org.eclipse.wst.sse.core.documentTypes">
+		<documentType
+			elementName="html"
+			displayName="XHTML 1.0 Strict"
+			namespaceURI="http://www.w3.org/1999/xhtml"
+			isXHTML="true"
+			hasFrameset="false"
+			publicID="-//W3C//DTD XHTML 1.0 Strict//EN"
+			systemID="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+		</documentType>
+		<documentType
+			elementName="html"
+			displayName="XHTML 1.0 Transitional"
+			namespaceURI="http://www.w3.org/1999/xhtml"
+			isXHTML="true"
+			hasFrameset="false"
+			publicID="-//W3C//DTD XHTML 1.0 Transitional//EN"
+			defaultXHTML="true"
+			systemID="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+		</documentType>
+		<documentType
+			elementName="html"
+			displayName="XHTML 1.0 Frameset"
+			namespaceURI="http://www.w3.org/1999/xhtml"
+			isXHTML="true"
+			hasFrameset="true"
+			publicID="-//W3C//DTD XHTML 1.0 Frameset//EN"
+			systemID="http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
+		</documentType>
+		<documentType
+			elementName="html"
+			displayName="XHTML Basic 1.0"
+			namespaceURI="http://www.w3.org/1999/xhtml"
+			isXHTML="true"
+			hasFrameset="false"
+			publicID="-//W3C//DTD XHTML Basic 1.0//EN"
+			systemID="http://www.w3.org/TR/xhtml-basic/xhtml-basic10.dtd">
+		</documentType>
+		<documentType
+			elementName="html"
+			displayName="XHTML 1.1"
+			namespaceURI="http://www.w3.org/1999/xhtml"
+			isXHTML="true"
+			hasFrameset="false"
+			publicID="-//W3C//DTD XHTML 1.1//EN"
+			systemID="http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+		</documentType>
+		<documentType
+			elementName="html"
+			displayName="XHTML MP 1.0"
+			namespaceURI="http://www.w3.org/1999/xhtml"
+			isXHTML="true"
+			hasFrameset="false"
+			publicID="-//WAPFORUM//DTD XHTML Mobile 1.0//EN"
+			systemID="http://www.wapforum.org/DTD/xhtml-mobile10.dtd">
+		</documentType>
+		<documentType
+			elementName="wml"
+			displayName="WML 1.3"
+			namespaceURI=""
+			isWML="true"
+			hasFrameset="false"
+			publicID="-//WAPFORUM//DTD WML 1.3//EN"
+			defaultWML="true"
+			systemID="http://www.wapforum.org/DTD/wml13.dtd">
+		</documentType>
+	</extension>
+-->
+	<!-- initialize html core preferences -->
+	<extension point="org.eclipse.core.runtime.preferences">
+		<initializer
+			class="org.eclipse.wst.html.core.internal.preferences.HTMLCorePreferenceInitializer" />
+	</extension>
+
+</plugin>
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/HTMLContentBuilder.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/HTMLContentBuilder.java
new file mode 100644
index 0000000..ce33f1d
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/HTMLContentBuilder.java
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal;
+
+
+
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.wst.html.core.internal.preferences.HTMLCorePreferenceNames;
+import org.eclipse.wst.html.core.internal.provisional.HTMLCMProperties;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.DOMContentBuilderImpl;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+public class HTMLContentBuilder extends DOMContentBuilderImpl {
+
+	private int fTagCase;
+	private int fAttrCase;
+
+	/**
+	 * DOMContentBuilder constructor comment.
+	 * @param document org.w3c.dom.Document
+	 */
+	public HTMLContentBuilder(Document document) {
+		super(document);
+		Preferences prefs = HTMLCorePlugin.getDefault().getPluginPreferences();
+		fTagCase = prefs.getInt(HTMLCorePreferenceNames.TAG_NAME_CASE);
+		fAttrCase = prefs.getInt(HTMLCorePreferenceNames.ATTR_NAME_CASE);
+		//	Element caseSettings = HTMLPreferenceManager.getHTMLInstance().getElement(PreferenceNames.PREFERRED_CASE);
+		//	fTagCase = caseSettings.getAttribute(PreferenceNames.TAGNAME);
+		//	fAttrCase = caseSettings.getAttribute(PreferenceNames.ATTRIBUTENAME);
+	}
+
+	public String computeName(CMNode cmnode, Node parent) {
+		String name = super.computeName(cmnode, parent);
+		// don't change the case unless we're certain it is meaningless
+		//	if (cmnode instanceof HTMLCMNode && ((HTMLCMNode) cmnode).shouldIgnoreCase()) {
+		if (shouldIgnoreCase(cmnode)) {
+			if (cmnode.getNodeType() == CMNode.ELEMENT_DECLARATION) {
+				if (fTagCase == HTMLCorePreferenceNames.LOWER)
+					name = name.toLowerCase();
+				else if (fTagCase == HTMLCorePreferenceNames.UPPER)
+					name = name.toUpperCase();
+				// else do nothing
+			}
+			else if (cmnode.getNodeType() == CMNode.ATTRIBUTE_DECLARATION) {
+				if (fAttrCase == HTMLCorePreferenceNames.LOWER)
+					name = name.toLowerCase();
+				else if (fAttrCase == HTMLCorePreferenceNames.UPPER)
+					name = name.toUpperCase();
+				// else do nothing
+			}
+		}
+		return name;
+
+	}
+
+	private boolean shouldIgnoreCase(CMNode cmnode) {
+		if (!cmnode.supports(HTMLCMProperties.SHOULD_IGNORE_CASE))
+			return false;
+		return ((Boolean) cmnode.getProperty(HTMLCMProperties.SHOULD_IGNORE_CASE)).booleanValue();
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/HTMLCoreMessages.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/HTMLCoreMessages.java
new file mode 100644
index 0000000..f2f93b1
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/HTMLCoreMessages.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 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 - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Strings used by HTML Core
+ * 
+ * @plannedfor 1.0
+ */
+public class HTMLCoreMessages extends NLS {
+	private static final String BUNDLE_NAME = "org.eclipse.wst.html.core.internal.HTMLCorePluginResources";//$NON-NLS-1$
+
+	public static String No_error__UI_;
+	public static String Undefined_attribute_name___ERROR_;
+	public static String Undefined_attribute_value__ERROR_;
+	public static String Multiple_values_specified__ERROR_;
+	public static String Attribute_name___0___uses__ERROR_;
+	public static String Invalid_attribute_name___0_ERROR_;
+	public static String Invalid_attribute___0____ERROR_;
+	public static String Invalid_location_of_tag____ERROR_;
+	public static String Duplicate_tag___0____ERROR_;
+	public static String No_start_tag____0_____ERROR_;
+	public static String No_end_tag_____0_____ERROR_;
+	public static String End_tag_____0____not_neede_ERROR_;
+	public static String Unknown_tag___0____ERROR_;
+	public static String Tag_name___0___uses_wrong__ERROR_;
+	public static String Invalid_tag_name___0____ERROR_;
+	public static String Invalid_JSP_directive___0__ERROR_;
+	public static String Invalid_text_string___0____ERROR_;
+	public static String Invalid_character_used_in__ERROR_;
+	public static String Unknown_error__ERROR_;
+	public static String Start_tag____0____not_clos_ERROR_;
+	public static String End_tag_____0____not_close_ERROR_;
+	public static String Attribute_value___0___uses_ERROR_;
+	public static String Comment_not_closed__ERROR_;
+	public static String DOCTYPE_declaration_not_cl_ERROR_;
+	public static String Processing_instruction_not_ERROR_;
+	public static String CDATA_section_not_closed__ERROR_;
+	public static String _ERROR_Tag___0___should_be_an_empty_element_tag_1;
+	public static String _ERROR_Attribute_value___0___not_closed__1;
+	public static String HTMLContentPropertiesManager_Updating;
+	public static String HTMLContentPropertiesManager_Problems_Updating;
+	public static String _ERROR_Resource_not_found_0;
+	public static String Obsolete_attribute_name___ERROR_;
+	public static String Obsolete_tag___ERROR_;
+
+	static {
+		// load message values from bundle file
+		NLS.initializeMessages(BUNDLE_NAME, HTMLCoreMessages.class);
+	}
+	
+	private HTMLCoreMessages() {
+		// cannot create new instance
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/HTMLCorePlugin.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/HTMLCorePlugin.java
new file mode 100644
index 0000000..d1a486b
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/HTMLCorePlugin.java
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal;
+
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.Plugin;
+import org.eclipse.wst.html.core.internal.contentproperties.HTMLContentPropertiesManager;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The main plugin class to be used in the desktop.
+ */
+public class HTMLCorePlugin extends Plugin {
+	// The shared instance.
+	private static HTMLCorePlugin plugin;
+
+	/**
+	 * The constructor.
+	 */
+	public HTMLCorePlugin() {
+		super();
+		plugin = this;
+	}
+
+	/**
+	 * Returns the shared instance.
+	 */
+	public static HTMLCorePlugin getDefault() {
+		return plugin;
+	}
+
+	/**
+	 * Returns the workspace instance.
+	 */
+	public static IWorkspace getWorkspace() {
+		return ResourcesPlugin.getWorkspace();
+	}
+
+	public void start(BundleContext context) throws Exception {
+		super.start(context);
+
+		// listen for resource changes to update content properties keys
+		HTMLContentPropertiesManager.startup();
+	}
+
+	public void stop(BundleContext context) throws Exception {
+		// stop listenning for resource changes to update content properties
+		// keys
+		HTMLContentPropertiesManager.shutdown();
+
+		super.stop(context);
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/HTMLCorePluginResources.properties b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/HTMLCorePluginResources.properties
new file mode 100644
index 0000000..7301451
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/HTMLCorePluginResources.properties
@@ -0,0 +1,45 @@
+###############################################################################
+# 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
+###############################################################################
+No_error__UI_=No error.
+Undefined_attribute_name___ERROR_=Undefined attribute name ({0}).
+Undefined_attribute_value__ERROR_=Undefined attribute value ({0}).
+Multiple_values_specified__ERROR_=Multiple values specified for an attribute ({0}).
+Attribute_name___0___uses__ERROR_=Attribute name ({0}) uses wrong case character.
+Invalid_attribute_name___0_ERROR_=Invalid attribute name ({0}).
+Invalid_attribute___0____ERROR_=Invalid attribute ({0}).
+Invalid_location_of_tag____ERROR_=Invalid location of tag ({0}).
+Duplicate_tag___0____ERROR_=Duplicate tag ({0}).
+No_start_tag____0_____ERROR_=No start tag (<{0}>).
+No_end_tag_____0_____ERROR_=No end tag (</{0}>).
+End_tag_____0____not_neede_ERROR_=End tag (</{0}>) not needed.
+Unknown_tag___0____ERROR_=Unknown tag ({0}).
+Tag_name___0___uses_wrong__ERROR_=Tag name ({0}) uses wrong case character.
+Invalid_tag_name___0____ERROR_=Invalid tag name ({0}).
+Invalid_JSP_directive___0__ERROR_=Invalid JSP directive ({0}).
+Invalid_text_string___0____ERROR_=Invalid text string ({0}).
+Invalid_character_used_in__ERROR_=Invalid character used in text string ({0}).
+Unknown_error__ERROR_=Unknown error.
+Start_tag____0____not_clos_ERROR_=Start tag (<{0}>) not closed.
+End_tag_____0____not_close_ERROR_=End tag (</{0}>) not closed.
+Attribute_value___0___uses_ERROR_=Attribute value ({0}) uses wrong case character.
+Comment_not_closed__ERROR_=Comment not closed.
+DOCTYPE_declaration_not_cl_ERROR_=DOCTYPE declaration not closed.
+Processing_instruction_not_ERROR_=Processing instruction not closed.
+CDATA_section_not_closed__ERROR_=CDATA section not closed.
+# From here, the new messages are added for V5
+_ERROR_Tag___0___should_be_an_empty_element_tag_1=Tag ({0}) should be an empty-element tag.
+_ERROR_Attribute_value___0___not_closed__1=Attribute value ({0}) not closed.
+#
+HTMLContentPropertiesManager_Updating=Updating Web Content Settings
+HTMLContentPropertiesManager_Problems_Updating=Problem saving Web Content Settings for {0}
+_ERROR_Resource_not_found_0=Resource not found: {0}
+Obsolete_attribute_name___ERROR_=Attribute ({0}) is obsolete. Its use is discouraged in HTML5 documents.
+Obsolete_tag___ERROR_=Element ({0}) is obsolete. Its use is discouraged in HTML5 documents.
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/Logger.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/Logger.java
new file mode 100644
index 0000000..c547950
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/Logger.java
@@ -0,0 +1,144 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal;
+
+import com.ibm.icu.util.StringTokenizer;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.osgi.framework.Bundle;
+
+/**
+ * Small convenience class to log messages to plugin's log file and also, if desired,
+ * the console. This class should only be used by classes in this plugin. Other
+ * plugins should make their own copy, with appropriate ID.
+ */
+public class Logger {
+	private static final String PLUGIN_ID = "org.eclipse.wst.html.core"; //$NON-NLS-1$
+
+	private static final String TRACEFILTER_LOCATION = "/debug/tracefilter"; //$NON-NLS-1$
+
+	public static final int OK = IStatus.OK; // 0
+	public static final int INFO = IStatus.INFO; // 1
+	public static final int WARNING = IStatus.WARNING; // 2
+	public static final int ERROR = IStatus.ERROR; // 4
+
+	public static final int OK_DEBUG = 200 + OK;
+	public static final int INFO_DEBUG = 200 + INFO;
+	public static final int WARNING_DEBUG = 200 + WARNING;
+	public static final int ERROR_DEBUG = 200 + ERROR;
+
+	/**
+	 * Adds message to log.
+	 * @param level severity level of the message (OK, INFO, WARNING, ERROR, OK_DEBUG, INFO_DEBUG, WARNING_DEBUG, ERROR_DEBUG)
+	 * @param message text to add to the log
+	 * @param exception exception thrown
+	 */
+	protected static void _log(int level, String message, Throwable exception) {
+		if (level == OK_DEBUG || level == INFO_DEBUG || level == WARNING_DEBUG || level == ERROR_DEBUG) {
+			if (!isDebugging())
+				return;
+		}
+
+		int severity = IStatus.OK;
+		switch (level) {
+			case INFO_DEBUG :
+			case INFO :
+				severity = IStatus.INFO;
+				break;
+			case WARNING_DEBUG :
+			case WARNING :
+				severity = IStatus.WARNING;
+				break;
+			case ERROR_DEBUG :
+			case ERROR :
+				severity = IStatus.ERROR;
+		}
+		message = (message != null) ? message : "null"; //$NON-NLS-1$
+		Status statusObj = new Status(severity, PLUGIN_ID, severity, message, exception);
+		Bundle bundle = Platform.getBundle(PLUGIN_ID);
+		if (bundle != null) 
+			Platform.getLog(bundle).log(statusObj);
+	}
+
+	/**
+	 * Prints message to log if category matches /debug/tracefilter option.
+	 * @param message text to print
+	 * @param category category of the message, to be compared with /debug/tracefilter
+	 */
+	protected static void _trace(String category, String message, Throwable exception) {
+		if (isTracing(category)) {
+			message = (message != null) ? message : "null"; //$NON-NLS-1$
+			Status statusObj = new Status(IStatus.OK, PLUGIN_ID, IStatus.OK, message, exception);
+			Bundle bundle = Platform.getBundle(PLUGIN_ID);
+			if (bundle != null) 
+				Platform.getLog(bundle).log(statusObj);
+		}
+	}
+
+	/**
+	 * @return true if the platform is debugging
+	 */
+	public static boolean isDebugging() {
+		return Platform.inDebugMode();
+	}
+
+	/**
+	 * Determines if currently tracing a category
+	 * @param category
+	 * @return true if tracing category, false otherwise
+	 */
+	public static boolean isTracing(String category) {
+		if (!isDebugging())
+			return false;
+
+		String traceFilter = Platform.getDebugOption(PLUGIN_ID + TRACEFILTER_LOCATION);
+		if (traceFilter != null) {
+			StringTokenizer tokenizer = new StringTokenizer(traceFilter, ","); //$NON-NLS-1$
+			while (tokenizer.hasMoreTokens()) {
+				String cat = tokenizer.nextToken().trim();
+				if (category.equals(cat)) {
+					return true;
+				}
+			}
+		}
+		return false;
+	}
+
+	public static void log(int level, String message) {
+		_log(level, message, null);
+	}
+
+	public static void log(int level, String message, Throwable exception) {
+		_log(level, message, exception);
+	}
+
+	public static void logException(String message, Throwable exception) {
+		_log(ERROR, message, exception);
+	}
+
+	public static void logException(Throwable exception) {
+		_log(ERROR, exception.getMessage(), exception);
+	}
+
+	public static void traceException(String category, String message, Throwable exception) {
+		_trace(category, message, exception);
+	}
+
+	public static void traceException(String category, Throwable exception) {
+		_trace(category, exception.getMessage(), exception);
+	}
+
+	public static void trace(String category, String message) {
+		_trace(category, message, null);
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/cleanup/AbstractNodeCleanupHandler.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/cleanup/AbstractNodeCleanupHandler.java
new file mode 100644
index 0000000..b435610
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/cleanup/AbstractNodeCleanupHandler.java
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.cleanup;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.wst.html.core.internal.HTMLCorePlugin;
+import org.eclipse.wst.html.core.internal.preferences.HTMLCorePreferenceNames;
+import org.eclipse.wst.sse.core.internal.cleanup.IStructuredCleanupHandler;
+import org.eclipse.wst.sse.core.internal.cleanup.IStructuredCleanupPreferences;
+import org.eclipse.wst.sse.core.internal.cleanup.StructuredCleanupPreferences;
+import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentEvent;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
+
+abstract class AbstractNodeCleanupHandler implements IStructuredCleanupHandler {
+
+	protected IStructuredCleanupPreferences fCleanupPreferences = null;
+	protected IProgressMonitor fProgressMonitor = null;
+
+	public void setCleanupPreferences(IStructuredCleanupPreferences cleanupPreferences) {
+
+		fCleanupPreferences = cleanupPreferences;
+	}
+
+
+	public IStructuredCleanupPreferences getCleanupPreferences() {
+		if (fCleanupPreferences == null) {
+			fCleanupPreferences = new StructuredCleanupPreferences();
+	
+			Preferences preferences = getModelPreferences();
+			if (preferences != null) {
+				fCleanupPreferences.setTagNameCase(preferences.getInt(HTMLCorePreferenceNames.CLEANUP_TAG_NAME_CASE));
+				fCleanupPreferences.setAttrNameCase(preferences.getInt(HTMLCorePreferenceNames.CLEANUP_ATTR_NAME_CASE));
+				fCleanupPreferences.setCompressEmptyElementTags(preferences.getBoolean(HTMLCorePreferenceNames.COMPRESS_EMPTY_ELEMENT_TAGS));
+				fCleanupPreferences.setInsertRequiredAttrs(preferences.getBoolean(HTMLCorePreferenceNames.INSERT_REQUIRED_ATTRS));
+				fCleanupPreferences.setInsertMissingTags(preferences.getBoolean(HTMLCorePreferenceNames.INSERT_MISSING_TAGS));
+				fCleanupPreferences.setQuoteAttrValues(preferences.getBoolean(HTMLCorePreferenceNames.QUOTE_ATTR_VALUES));
+				fCleanupPreferences.setFormatSource(preferences.getBoolean(HTMLCorePreferenceNames.FORMAT_SOURCE));
+				fCleanupPreferences.setConvertEOLCodes(preferences.getBoolean(HTMLCorePreferenceNames.CONVERT_EOL_CODES));
+				fCleanupPreferences.setEOLCode(preferences.getString(HTMLCorePreferenceNames.CLEANUP_EOL_CODE));
+			}
+		}
+
+		return fCleanupPreferences;
+	}
+
+
+	public void setProgressMonitor(IProgressMonitor progressMonitor) {
+
+		fProgressMonitor = progressMonitor;
+	}
+
+	static protected StructuredDocumentEvent replaceSource(IDOMModel model, Object requester, int offset, int length, String source) {
+
+		StructuredDocumentEvent result = null;
+		if (model == null)
+			return result;
+		IStructuredDocument structuredDocument = model.getStructuredDocument();
+		if (structuredDocument == null)
+			return result;
+		if (source == null)
+			source = new String();
+		if (structuredDocument.containsReadOnly(offset, length))
+			return result;
+		if (requester == null) {
+			requester = structuredDocument;
+		}
+		return structuredDocument.replaceText(requester, offset, length, source);
+	}
+
+	protected Preferences getModelPreferences() {
+		return HTMLCorePlugin.getDefault().getPluginPreferences();
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/cleanup/CSSTextNodeCleanupHandler.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/cleanup/CSSTextNodeCleanupHandler.java
new file mode 100644
index 0000000..7a2b246
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/cleanup/CSSTextNodeCleanupHandler.java
@@ -0,0 +1,91 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.cleanup;
+
+
+
+import org.eclipse.wst.css.core.internal.formatter.CSSSourceFormatter;
+import org.eclipse.wst.css.core.internal.formatter.CSSSourceFormatterFactory;
+import org.eclipse.wst.css.core.internal.provisional.adapters.IStyleSheetAdapter;
+import org.eclipse.wst.css.core.internal.provisional.document.ICSSModel;
+import org.eclipse.wst.css.core.internal.provisional.document.ICSSNode;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapter;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.w3c.dom.Node;
+
+// nakamori_TODO: check and remove
+
+public class CSSTextNodeCleanupHandler extends AbstractNodeCleanupHandler {
+
+	public Node cleanup(Node node) {
+		if (node == null)
+			return node;
+		IDOMModel model = ((IDOMNode) node).getModel();
+		if (model == null)
+			return node;
+		IStructuredDocument structuredDocument = model.getStructuredDocument();
+		if (structuredDocument == null)
+			return node;
+		if ( !getCleanupPreferences().getFormatSource())
+			return node;
+		
+		String content = getCSSContent(node);
+		if (content == null)
+			return node;
+
+		int offset = ((IDOMNode) node).getStartOffset();
+		int length = ((IDOMNode) node).getEndOffset() - offset;
+		replaceSource(model, this, offset, length, content);
+		return (IDOMNode) model.getIndexedRegion(offset);
+	}
+
+	/**
+	 */
+	private String getCSSContent(Node text) {
+		ICSSModel model = getCSSModel(text);
+		if (model == null)
+			return null;
+		ICSSNode document = model.getDocument();
+		if (document == null)
+			return null;
+		INodeNotifier notifier = (INodeNotifier) document;
+		CSSSourceFormatter formatter = (CSSSourceFormatter) notifier.getAdapterFor(CSSSourceFormatter.class);
+		// try another way to get formatter
+		if (formatter == null)
+			formatter = CSSSourceFormatterFactory.getInstance().getSourceFormatter(notifier);
+		if (formatter == null)
+			return null;
+		StringBuffer buffer = formatter.cleanup(document);
+		if (buffer == null)
+			return null;
+		return buffer.toString();
+	}
+
+	/**
+	 */
+	private ICSSModel getCSSModel(Node text) {
+		if (text == null)
+			return null;
+		INodeNotifier notifier = (INodeNotifier) text.getParentNode();
+		if (notifier == null)
+			return null;
+		INodeAdapter adapter = notifier.getAdapterFor(IStyleSheetAdapter.class);
+		if (adapter == null)
+			return null;
+		if (!(adapter instanceof IStyleSheetAdapter))
+			return null;
+		IStyleSheetAdapter styleAdapter = (IStyleSheetAdapter) adapter;
+		return styleAdapter.getModel();
+	}
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/cleanup/ElementNodeCleanupHandler.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/cleanup/ElementNodeCleanupHandler.java
new file mode 100644
index 0000000..9f37d31
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/cleanup/ElementNodeCleanupHandler.java
@@ -0,0 +1,762 @@
+/*******************************************************************************
+ * 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
+ *     David Carver (Intalion) - Cleanup Repeated Conditional check in isXMLType method
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.cleanup;
+
+
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.text.edits.InsertEdit;
+import org.eclipse.text.edits.MultiTextEdit;
+import org.eclipse.wst.css.core.internal.formatter.CSSSourceFormatter;
+import org.eclipse.wst.css.core.internal.formatter.CSSSourceFormatterFactory;
+import org.eclipse.wst.css.core.internal.provisional.adapters.IStyleDeclarationAdapter;
+import org.eclipse.wst.css.core.internal.provisional.document.ICSSModel;
+import org.eclipse.wst.css.core.internal.provisional.document.ICSSNode;
+import org.eclipse.wst.html.core.internal.Logger;
+import org.eclipse.wst.html.core.internal.preferences.HTMLCorePreferenceNames;
+import org.eclipse.wst.sse.core.internal.cleanup.IStructuredCleanupHandler;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapter;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+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.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.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.modelquery.ModelQueryUtil;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMAttr;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
+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.provisional.document.ISourceGenerator;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+// nakamori_TODO: check and remove CSS formatting
+
+public class ElementNodeCleanupHandler extends AbstractNodeCleanupHandler {
+
+	/** Non-NLS strings */
+	protected static final String START_TAG_OPEN = "<"; //$NON-NLS-1$
+	protected static final String END_TAG_OPEN = "</"; //$NON-NLS-1$
+	protected static final String TAG_CLOSE = ">"; //$NON-NLS-1$
+	protected static final String EMPTY_TAG_CLOSE = "/>"; //$NON-NLS-1$
+	protected static final String SINGLE_QUOTES = "''"; //$NON-NLS-1$
+	protected static final String DOUBLE_QUOTES = "\"\""; //$NON-NLS-1$
+	protected static final char SINGLE_QUOTE = '\''; //$NON-NLS-1$
+	protected static final char DOUBLE_QUOTE = '\"'; //$NON-NLS-1$
+
+	public Node cleanup(Node node) {
+		IDOMNode renamedNode = (IDOMNode) cleanupChildren(node);
+
+		// call quoteAttrValue() first so it will close any unclosed attr
+		// quoteAttrValue() will return the new start tag if there is a
+		// structure change
+		renamedNode = quoteAttrValue(renamedNode);
+
+		// insert tag close if missing
+		// if node is not comment tag
+		// and not implicit tag
+		if (!((IDOMElement) renamedNode).isCommentTag() && (renamedNode.getStartStructuredDocumentRegion() != null)) {
+			IDOMModel structuredModel = renamedNode.getModel();
+
+			// save start offset before insertTagClose()
+			// or else renamedNode.getStartOffset() will be zero if
+			// renamedNode replaced by insertTagClose()
+			int startTagStartOffset = renamedNode.getStartOffset();
+
+			// for start tag
+			IStructuredDocumentRegion startTagStructuredDocumentRegion = renamedNode.getStartStructuredDocumentRegion();
+			insertTagClose(structuredModel, startTagStructuredDocumentRegion);
+
+			// update renamedNode and startTagStructuredDocumentRegion after
+			// insertTagClose()
+			renamedNode = (IDOMNode) structuredModel.getIndexedRegion(startTagStartOffset);
+			startTagStructuredDocumentRegion = renamedNode.getStartStructuredDocumentRegion();
+
+			// for end tag
+			IStructuredDocumentRegion endTagStructuredDocumentRegion = renamedNode.getEndStructuredDocumentRegion();
+			if (endTagStructuredDocumentRegion != startTagStructuredDocumentRegion)
+				insertTagClose(structuredModel, endTagStructuredDocumentRegion);
+		}
+
+		// call insertMissingTags() next, it will generate implicit tags if
+		// there are any
+		// insertMissingTags() will return the new missing start tag if one is
+		// missing
+		// then compress any empty element tags
+		// applyTagNameCase() will return the renamed node.
+		// The renamed/new node will be saved and returned to caller when all
+		// cleanup is done.
+		renamedNode = insertMissingTags(renamedNode);
+		renamedNode = compressEmptyElementTag(renamedNode);
+		renamedNode = insertRequiredAttrs(renamedNode);
+		renamedNode = applyTagNameCase(renamedNode);
+		applyAttrNameCase(renamedNode);
+		cleanupCSSAttrValue(renamedNode);
+
+		return renamedNode;
+	}
+
+	/**
+	 * Checks if cleanup should modify case. Returns true case should be
+	 * preserved, false otherwise.
+	 * 
+	 * @param element
+	 * @return true if element is case sensitive, false otherwise
+	 */
+	private boolean shouldPreserveCase(IDOMElement element) {
+		// case option can be applied to no namespace tags
+		return !element.isGlobalTag();
+		/*
+		 * ModelQueryAdapter mqadapter = (ModelQueryAdapter)
+		 * element.getAdapterFor(ModelQueryAdapter.class); ModelQuery mq =
+		 * null; CMNode nodedecl = null; if (mqadapter != null) mq =
+		 * mqadapter.getModelQuery(); if (mq != null) nodedecl =
+		 * mq.getCMNode(node); // if a Node isn't recognized as HTML or is and
+		 * cares about case, do not alter it // if (nodedecl == null ||
+		 * (nodedecl instanceof HTMLCMNode && ((HTMLCMNode)
+		 * nodedecl).shouldIgnoreCase())) if (!
+		 * nodedecl.supports(HTMLCMProperties.SHOULD_IGNORE_CASE)) return
+		 * false; return
+		 * ((Boolean)cmnode.getProperty(HTMLCMProperties.SHOULD_IGNORE_CASE)).booleanValue();
+		 */
+	}
+
+	/**
+	 * Checks if cleanup should force modifying element name to all lowercase.
+	 * 
+	 * @param element
+	 * @return true if cleanup should lowercase element name, false otherwise
+	 */
+	private boolean isXMLTag(IDOMElement element) {
+		return element.isXMLTag();
+	}
+
+	protected void applyAttrNameCase(IDOMNode node) {
+		IDOMElement element = (IDOMElement) node;
+		if (element.isCommentTag())
+			return; // do nothing
+
+		int attrNameCase = HTMLCorePreferenceNames.ASIS;
+		if (!shouldPreserveCase(element)) {
+			if (isXMLTag(element))
+				attrNameCase = HTMLCorePreferenceNames.LOWER;
+			else
+				attrNameCase = getCleanupPreferences().getAttrNameCase();
+		}
+
+		NamedNodeMap attributes = node.getAttributes();
+		int attributesLength = attributes.getLength();
+
+		for (int i = 0; i < attributesLength; i++) {
+			IDOMNode eachAttr = (IDOMNode) attributes.item(i);
+			if (hasNestedRegion(eachAttr.getNameRegion()))
+				continue;
+			String oldAttrName = eachAttr.getNodeName();
+			String newAttrName = oldAttrName;
+			/*
+			 * 254961 - all HTML tag names and attribute names should be in
+			 * English even for HTML files in other languages like Japanese or
+			 * Turkish. English locale should be used to convert between
+			 * uppercase and lowercase (otherwise "link" would be converted to
+			 * Turkish "I Overdot Capital").
+			 */
+			if (attrNameCase == HTMLCorePreferenceNames.LOWER)
+				newAttrName = oldAttrName.toLowerCase(Locale.US);
+			else if (attrNameCase == HTMLCorePreferenceNames.UPPER)
+				newAttrName = oldAttrName.toUpperCase(Locale.US);
+
+			if (newAttrName.compareTo(oldAttrName) != 0) {
+				int attrNameStartOffset = eachAttr.getStartOffset();
+				int attrNameLength = oldAttrName.length();
+
+				IDOMModel structuredModel = node.getModel();
+				IStructuredDocument structuredDocument = structuredModel.getStructuredDocument();
+				replaceSource(structuredModel, structuredDocument, attrNameStartOffset, attrNameLength, newAttrName);
+			}
+		}
+	}
+
+	/**
+	 * True if container has nested regions, meaning container is probably too
+	 * complicated (like JSP regions) to validate with this validator.
+	 */
+	private boolean hasNestedRegion(ITextRegion container) {
+		if (!(container instanceof ITextRegionContainer))
+			return false;
+		ITextRegionList regions = ((ITextRegionContainer) container).getRegions();
+		if (regions == null)
+			return false;
+		return true;
+	}
+
+	protected IDOMNode applyTagNameCase(IDOMNode node) {
+		IDOMElement element = (IDOMElement) node;
+		if (element.isCommentTag())
+			return node; // do nothing
+
+		int tagNameCase = HTMLCorePreferenceNames.ASIS;
+
+		if (!shouldPreserveCase(element)) {
+			if (isXMLTag(element))
+				tagNameCase = HTMLCorePreferenceNames.LOWER;
+			else
+				tagNameCase = getCleanupPreferences().getTagNameCase();
+		}
+
+		String oldTagName = node.getNodeName();
+		String newTagName = oldTagName;
+		IDOMNode newNode = node;
+
+		/*
+		 * 254961 - all HTML tag names and attribute names should be in
+		 * English even for HTML files in other languages like Japanese or
+		 * Turkish. English locale should be used to convert between uppercase
+		 * and lowercase (otherwise "link" would be converted to Turkish "I
+		 * Overdot Capital").
+		 */
+		if (tagNameCase == HTMLCorePreferenceNames.LOWER)
+			newTagName = oldTagName.toLowerCase(Locale.US);
+		else if (tagNameCase == HTMLCorePreferenceNames.UPPER)
+			newTagName = oldTagName.toUpperCase(Locale.US);
+
+		IDOMModel structuredModel = node.getModel();
+		IStructuredDocument structuredDocument = structuredModel.getStructuredDocument();
+
+		IStructuredDocumentRegion startTagStructuredDocumentRegion = node.getStartStructuredDocumentRegion();
+		if (startTagStructuredDocumentRegion != null) {
+			ITextRegionList regions = startTagStructuredDocumentRegion.getRegions();
+			if (regions != null && regions.size() > 0) {
+				ITextRegion startTagNameRegion = regions.get(1);
+				int startTagNameStartOffset = startTagStructuredDocumentRegion.getStartOffset(startTagNameRegion);
+				int startTagNameLength = startTagStructuredDocumentRegion.getTextEndOffset(startTagNameRegion) - startTagNameStartOffset;
+
+				replaceSource(structuredModel, structuredDocument, startTagNameStartOffset, startTagNameLength, newTagName);
+				newNode = (IDOMNode) structuredModel.getIndexedRegion(startTagNameStartOffset); // save
+				// new
+				// node
+			}
+		}
+
+		IStructuredDocumentRegion endTagStructuredDocumentRegion = node.getEndStructuredDocumentRegion();
+		if (endTagStructuredDocumentRegion != null) {
+			ITextRegionList regions = endTagStructuredDocumentRegion.getRegions();
+			if (regions != null && regions.size() > 0) {
+				ITextRegion endTagNameRegion = regions.get(1);
+				int endTagNameStartOffset = endTagStructuredDocumentRegion.getStartOffset(endTagNameRegion);
+				int endTagNameLength = endTagStructuredDocumentRegion.getTextEndOffset(endTagNameRegion) - endTagNameStartOffset;
+
+				if (startTagStructuredDocumentRegion != endTagStructuredDocumentRegion)
+					replaceSource(structuredModel, structuredDocument, endTagNameStartOffset, endTagNameLength, newTagName);
+			}
+		}
+
+		return newNode;
+	}
+
+	protected Node cleanupChildren(Node node) {
+		Node parentNode = node;
+
+		if (node != null) {
+			Node childNode = node.getFirstChild();
+			HTMLCleanupHandlerFactory factory = HTMLCleanupHandlerFactory.getInstance();
+			while (childNode != null) {
+				// cleanup this child node
+				IStructuredCleanupHandler cleanupHandler = factory.createHandler(childNode, getCleanupPreferences());
+				childNode = cleanupHandler.cleanup(childNode);
+
+				// get new parent node
+				parentNode = childNode.getParentNode();
+
+				// get next child node
+				childNode = childNode.getNextSibling();
+			}
+		}
+
+		return parentNode;
+	}
+
+	/**
+	 */
+	protected void cleanupCSSAttrValue(IDOMNode node) {
+		if (node == null || node.getNodeType() != Node.ELEMENT_NODE)
+			return;
+		IDOMElement element = (IDOMElement) node;
+		if (!element.isGlobalTag())
+			return;
+
+		Attr attr = element.getAttributeNode("style"); //$NON-NLS-1$
+		if (attr == null)
+			return;
+		String value = getCSSValue(attr);
+		if (value == null)
+			return;
+		String oldValue = ((IDOMNode) attr).getValueSource();
+		if (oldValue != null && value.equals(oldValue))
+			return;
+		attr.setValue(value);
+	}
+
+	/**
+	 */
+	private ICSSModel getCSSModel(Attr attr) {
+		if (attr == null)
+			return null;
+		INodeNotifier notifier = (INodeNotifier) attr.getOwnerElement();
+		if (notifier == null)
+			return null;
+		INodeAdapter adapter = notifier.getAdapterFor(IStyleDeclarationAdapter.class);
+		if (adapter == null)
+			return null;
+		if (!(adapter instanceof IStyleDeclarationAdapter))
+			return null;
+		IStyleDeclarationAdapter styleAdapter = (IStyleDeclarationAdapter) adapter;
+		return styleAdapter.getModel();
+	}
+
+	/**
+	 */
+	private String getCSSValue(Attr attr) {
+		ICSSModel model = getCSSModel(attr);
+		if (model == null)
+			return null;
+		ICSSNode document = model.getDocument();
+		if (document == null)
+			return null;
+		INodeNotifier notifier = (INodeNotifier) document;
+		CSSSourceFormatter formatter = (CSSSourceFormatter) notifier.getAdapterFor(CSSSourceFormatter.class);
+		// try another way to get formatter
+		if (formatter == null)
+			formatter = CSSSourceFormatterFactory.getInstance().getSourceFormatter(notifier);
+		if (formatter == null)
+			return null;
+		StringBuffer buffer = formatter.cleanup(document);
+		if (buffer == null)
+			return null;
+		return buffer.toString();
+	}
+
+	private boolean isEmptyElement(IDOMElement element) {
+		Document document = element.getOwnerDocument();
+		if (document == null)
+			// undefined tag, return default
+			return false;
+
+		ModelQuery modelQuery = ModelQueryUtil.getModelQuery(document);
+		if (modelQuery == null)
+			// undefined tag, return default
+			return false;
+
+		CMElementDeclaration decl = modelQuery.getCMElementDeclaration(element);
+		if (decl == null)
+			// undefined tag, return default
+			return false;
+
+		return (decl.getContentType() == CMElementDeclaration.EMPTY);
+	}
+
+	protected IDOMNode insertEndTag(IDOMNode node) {
+		IDOMElement element = (IDOMElement) node;
+
+		int startTagStartOffset = node.getStartOffset();
+		IDOMModel structuredModel = node.getModel();
+		IDOMNode newNode = null;
+
+		if (element.isCommentTag()) {
+			// do nothing
+		}
+		else if (isEmptyElement(element)) {
+			IStructuredDocument structuredDocument = structuredModel.getStructuredDocument();
+			IStructuredDocumentRegion startStructuredDocumentRegion = node.getStartStructuredDocumentRegion();
+			ITextRegionList regions = startStructuredDocumentRegion.getRegions();
+			ITextRegion lastRegion = regions.get(regions.size() - 1);
+			replaceSource(structuredModel, structuredDocument, startStructuredDocumentRegion.getStartOffset(lastRegion), lastRegion.getLength(), EMPTY_TAG_CLOSE);
+
+			if (regions.size() > 1) {
+				ITextRegion regionBeforeTagClose = regions.get(regions.size() - 1 - 1);
+
+				// insert a space separator before tag close if the previous
+				// region does not have extra spaces
+				if (regionBeforeTagClose.getTextLength() == regionBeforeTagClose.getLength())
+					replaceSource(structuredModel, structuredDocument, startStructuredDocumentRegion.getStartOffset(lastRegion), 0, " "); //$NON-NLS-1$
+			}
+		}
+		else {
+			String tagName = node.getNodeName();
+			String endTag = END_TAG_OPEN.concat(tagName).concat(TAG_CLOSE);
+
+			IDOMNode lastChild = (IDOMNode) node.getLastChild();
+			int endTagStartOffset = 0;
+			if (lastChild != null)
+				// if this node has children, insert the end tag after the
+				// last child
+				endTagStartOffset = lastChild.getEndOffset();
+			else
+				// if this node does not has children, insert the end tag
+				// after the start tag
+				endTagStartOffset = node.getEndOffset();
+
+			IStructuredDocument structuredDocument = structuredModel.getStructuredDocument();
+			replaceSource(structuredModel, structuredDocument, endTagStartOffset, 0, endTag);
+		}
+
+		newNode = (IDOMNode) structuredModel.getIndexedRegion(startTagStartOffset); // save
+		// new
+		// node
+
+		return newNode;
+	}
+
+	protected IDOMNode insertMissingTags(IDOMNode node) {
+		boolean insertMissingTags = getCleanupPreferences().getInsertMissingTags();
+		IDOMNode newNode = node;
+
+		if (insertMissingTags) {
+			IStructuredDocumentRegion startTagStructuredDocumentRegion = node.getStartStructuredDocumentRegion();
+			if (startTagStructuredDocumentRegion == null) {
+				// implicit start tag; generate tag for it
+				newNode = insertStartTag(node);
+				startTagStructuredDocumentRegion = newNode.getStartStructuredDocumentRegion();
+			}
+
+			IStructuredDocumentRegion endTagStructuredDocumentRegion = newNode.getEndStructuredDocumentRegion();
+
+			ITextRegionList regionList = startTagStructuredDocumentRegion.getRegions();
+			if (startTagStructuredDocumentRegion != null && regionList != null && regionList.get(regionList.size() - 1).getType() == DOMRegionContext.XML_EMPTY_TAG_CLOSE) {
+
+			}
+			else {
+				if (startTagStructuredDocumentRegion == null) {
+					// start tag missing
+					if (isStartTagRequired(newNode))
+						newNode = insertStartTag(newNode);
+				}
+				else if (endTagStructuredDocumentRegion == null) {
+					// end tag missing
+					if (isEndTagRequired(newNode))
+						newNode = insertEndTag(newNode);
+				}
+			}
+		}
+
+		return newNode;
+	}
+
+	protected IDOMNode insertStartTag(IDOMNode node) {
+		IDOMElement element = (IDOMElement) node;
+		if (element.isCommentTag())
+			return node; // do nothing
+
+		IDOMNode newNode = null;
+
+		String tagName = node.getNodeName();
+		String startTag = START_TAG_OPEN.concat(tagName).concat(TAG_CLOSE);
+		int startTagStartOffset = node.getStartOffset();
+
+		IDOMModel structuredModel = node.getModel();
+		IStructuredDocument structuredDocument = structuredModel.getStructuredDocument();
+		replaceSource(structuredModel, structuredDocument, startTagStartOffset, 0, startTag);
+		newNode = (IDOMNode) structuredModel.getIndexedRegion(startTagStartOffset); // save
+		// new
+		// node
+
+		return newNode;
+	}
+
+	protected void insertTagClose(IDOMModel structuredModel, IStructuredDocumentRegion flatNode) {
+		if ((flatNode != null) && (flatNode.getRegions() != null)) {
+			ITextRegionList regionList = flatNode.getRegions();
+			ITextRegion lastRegion = regionList.get(regionList.size() - 1);
+			if (lastRegion != null) {
+				String regionType = lastRegion.getType();
+				if ((regionType != DOMRegionContext.XML_EMPTY_TAG_CLOSE) && (regionType != DOMRegionContext.XML_TAG_CLOSE)) {
+					IStructuredDocument structuredDocument = structuredModel.getStructuredDocument();
+
+					// insert ">" after lastRegion of flatNode
+					// as in "<a</a>" if flatNode is for start tag, or in
+					// "<a></a" if flatNode is for end tag
+					replaceSource(structuredModel, structuredDocument, flatNode.getTextEndOffset(lastRegion), 0, ">"); //$NON-NLS-1$
+				}
+			}
+		}
+	}
+
+	protected boolean isEndTagRequired(IDOMNode node) {
+		if (node == null)
+			return false;
+		return node.isContainer();
+	}
+
+	/**
+	 * The end tags of HTML EMPTY content type, such as IMG, and HTML
+	 * undefined tags are parsed separately from the start tags. So inserting
+	 * the missing start tag is useless and even harmful.
+	 */
+	protected boolean isStartTagRequired(IDOMNode node) {
+		if (node == null)
+			return false;
+		return node.isContainer();
+	}
+
+	protected boolean isXMLType(IDOMModel structuredModel) {
+		boolean result = false;
+
+		if (structuredModel != null) {
+			IDOMDocument document = structuredModel.getDocument();
+
+			if (document != null)
+				result = document.isXMLType();
+		}
+
+		return result;
+	}
+
+	protected IDOMNode quoteAttrValue(IDOMNode node) {
+		IDOMElement element = (IDOMElement) node;
+		if (element.isCommentTag())
+			return node; // do nothing
+
+		boolean quoteAttrValues = getCleanupPreferences().getQuoteAttrValues();
+		IDOMNode newNode = node;
+
+		if (quoteAttrValues) {
+			NamedNodeMap attributes = newNode.getAttributes();
+			int attributesLength = attributes.getLength();
+			ISourceGenerator generator = node.getModel().getGenerator();
+
+			for (int i = 0; i < attributesLength; i++) {
+				attributes = newNode.getAttributes();
+				attributesLength = attributes.getLength();
+				IDOMAttr eachAttr = (IDOMAttr) attributes.item(i);
+				// ITextRegion oldAttrValueRegion = eachAttr.getValueRegion();
+				String oldAttrValue = eachAttr.getValueRegionText();
+				if (oldAttrValue == null) {
+					IDOMModel structuredModel = node.getModel();
+					if (isXMLType(structuredModel)) {
+						// TODO: Kit, please check. Is there any way to not
+						// rely on getting regions from attributes?
+						String newAttrValue = "=\"" + eachAttr.getNameRegionText() + "\""; //$NON-NLS-1$ //$NON-NLS-2$
+
+						IStructuredDocument structuredDocument = structuredModel.getStructuredDocument();
+						replaceSource(structuredModel, structuredDocument, eachAttr.getNameRegionEndOffset(), 0, newAttrValue);
+						newNode = (IDOMNode) structuredModel.getIndexedRegion(node.getStartOffset()); // save
+						// new
+						// node
+					}
+				}
+				else {
+
+					char quote = StringUtils.isQuoted(oldAttrValue) ? oldAttrValue.charAt(0) : DOUBLE_QUOTE;
+					String newAttrValue = generator.generateAttrValue(eachAttr, quote);
+
+					// There is a problem in
+					// StructuredDocumentRegionUtil.getAttrValue(ITextRegion)
+					// when the region is instanceof ContextRegion.
+					// Workaround for now...
+					if (oldAttrValue.length() == 1) {
+						char firstChar = oldAttrValue.charAt(0);
+						if (firstChar == SINGLE_QUOTE)
+							newAttrValue = SINGLE_QUOTES;
+						else if (firstChar == DOUBLE_QUOTE)
+							newAttrValue = DOUBLE_QUOTES;
+					}
+
+					if (newAttrValue != null) {
+						if (newAttrValue.compareTo(oldAttrValue) != 0) {
+							int attrValueStartOffset = eachAttr.getValueRegionStartOffset();
+							int attrValueLength = oldAttrValue.length();
+							int startTagStartOffset = node.getStartOffset();
+
+							IDOMModel structuredModel = node.getModel();
+							IStructuredDocument structuredDocument = structuredModel.getStructuredDocument();
+							replaceSource(structuredModel, structuredDocument, attrValueStartOffset, attrValueLength, newAttrValue);
+							newNode = (IDOMNode) structuredModel.getIndexedRegion(startTagStartOffset); // save
+							// new
+							// node
+						}
+					}
+				}
+			}
+		}
+
+		return newNode;
+	}
+
+	private IDOMNode insertRequiredAttrs(IDOMNode node) {
+		boolean insertRequiredAttrs = getCleanupPreferences().getInsertRequiredAttrs();
+		IDOMNode newNode = node;
+
+		if (insertRequiredAttrs) {
+			List requiredAttrs = getRequiredAttrs(newNode);
+			if (requiredAttrs.size() > 0) {
+				NamedNodeMap currentAttrs = node.getAttributes();
+				List insertAttrs = new ArrayList();
+				if (currentAttrs.getLength() == 0)
+					insertAttrs.addAll(requiredAttrs);
+				else {
+					for (int i = 0; i < requiredAttrs.size(); i++) {
+						String requiredAttrName = ((CMAttributeDeclaration) requiredAttrs.get(i)).getAttrName();
+						boolean found = false;
+						for (int j = 0; j < currentAttrs.getLength(); j++) {
+							String currentAttrName = currentAttrs.item(j).getNodeName();
+							if (requiredAttrName.compareToIgnoreCase(currentAttrName) == 0) {
+								found = true;
+								break;
+							}
+						}
+						if (!found)
+							insertAttrs.add(requiredAttrs.get(i));
+					}
+				}
+				if (insertAttrs.size() > 0) {
+					IStructuredDocumentRegion startStructuredDocumentRegion = newNode.getStartStructuredDocumentRegion();
+					int index = startStructuredDocumentRegion.getEndOffset();
+					ITextRegion lastRegion = startStructuredDocumentRegion.getLastRegion();
+					if (lastRegion.getType() == DOMRegionContext.XML_TAG_CLOSE) {
+						index--;
+						lastRegion = startStructuredDocumentRegion.getRegionAtCharacterOffset(index - 1);
+					}
+					else if (lastRegion.getType() == DOMRegionContext.XML_EMPTY_TAG_CLOSE) {
+						index = index - 2;
+						lastRegion = startStructuredDocumentRegion.getRegionAtCharacterOffset(index - 1);
+					}
+					MultiTextEdit multiTextEdit = new MultiTextEdit();
+					try {
+						for (int i = insertAttrs.size() - 1; i >= 0; i--) {
+							CMAttributeDeclaration attrDecl = (CMAttributeDeclaration) insertAttrs.get(i);
+							String requiredAttributeName = attrDecl.getAttrName();
+							String defaultValue = attrDecl.getDefaultValue();
+							if (defaultValue == null)
+								defaultValue = ""; //$NON-NLS-1$
+							String nameAndDefaultValue = " "; //$NON-NLS-1$
+							if (i == 0 && lastRegion.getLength() > lastRegion.getTextLength())
+								nameAndDefaultValue = ""; //$NON-NLS-1$
+							nameAndDefaultValue += requiredAttributeName + "=\"" + defaultValue + "\""; //$NON-NLS-1$ //$NON-NLS-2$
+							multiTextEdit.addChild(new InsertEdit(index, nameAndDefaultValue));
+							// BUG3381: MultiTextEdit applies all child
+							// TextEdit's basing on offsets
+							// in the document before the first TextEdit, not
+							// after each
+							// child TextEdit. Therefore, do not need to
+							// advance the index.
+							// index += nameAndDefaultValue.length();
+						}
+						multiTextEdit.apply(newNode.getStructuredDocument());
+					}
+					catch (BadLocationException e) {
+						// log or now, unless we find reason not to
+						Logger.log(Logger.INFO, e.getMessage());
+					}
+				}
+			}
+		}
+
+		return newNode;
+	}
+
+
+	protected ModelQuery getModelQuery(Node node) {
+		ModelQuery result = null;
+		if (node.getNodeType() == Node.DOCUMENT_NODE) {
+			result = ModelQueryUtil.getModelQuery((Document) node);
+		}
+		else {
+			result = ModelQueryUtil.getModelQuery(node.getOwnerDocument());
+		}
+		return result;
+	}
+
+	protected List getRequiredAttrs(Node node) {
+		List result = new ArrayList();
+
+		ModelQuery modelQuery = getModelQuery(node);
+		if (modelQuery != null) {
+			CMElementDeclaration elementDecl = modelQuery.getCMElementDeclaration((Element) node);
+			if (elementDecl != null) {
+				CMNamedNodeMap attrMap = elementDecl.getAttributes();
+				Iterator it = attrMap.iterator();
+				CMAttributeDeclaration attr = null;
+				while (it.hasNext()) {
+					attr = (CMAttributeDeclaration) it.next();
+					if (attr.getUsage() == CMAttributeDeclaration.REQUIRED) {
+						result.add(attr);
+					}
+				}
+			}
+		}
+
+		return result;
+	}
+
+	/**
+	 * <p>Compress empty element tags if the prefence is set to do so</p>
+	 * 
+	 * @copyof org.eclipse.wst.xml.core.internal.cleanup.ElementNodeCleanupHandler#compressEmptyElementTag
+	 * 
+	 * @param node the {@link IDOMNode} to possible compress
+	 * @return the compressed node if the given node should be compressed, else the node as it was given
+	 */
+	private IDOMNode compressEmptyElementTag(IDOMNode node) {
+		boolean compressEmptyElementTags = getCleanupPreferences().getCompressEmptyElementTags();
+		IDOMNode newNode = node;
+
+		IStructuredDocumentRegion startTagStructuredDocumentRegion = newNode.getFirstStructuredDocumentRegion();
+		IStructuredDocumentRegion endTagStructuredDocumentRegion = newNode.getLastStructuredDocumentRegion();
+
+		//only compress tags if they are empty
+		if ((compressEmptyElementTags && startTagStructuredDocumentRegion != endTagStructuredDocumentRegion &&
+				startTagStructuredDocumentRegion != null)) {
+
+			//only compress end tags if its XHTML or not a container
+			if(isXMLTag((IDOMElement)newNode) || !newNode.isContainer()) {
+				ITextRegionList regions = startTagStructuredDocumentRegion.getRegions();
+				ITextRegion lastRegion = regions.get(regions.size() - 1);
+				// format children and end tag if not empty element tag
+				if (lastRegion.getType() != DOMRegionContext.XML_EMPTY_TAG_CLOSE) {
+					NodeList childNodes = newNode.getChildNodes();
+					if (childNodes == null || childNodes.getLength() == 0 || (childNodes.getLength() == 1 && (childNodes.item(0)).getNodeType() == Node.TEXT_NODE && ((childNodes.item(0)).getNodeValue().trim().length() == 0))) {
+						IDOMModel structuredModel = newNode.getModel();
+						IStructuredDocument structuredDocument = structuredModel.getStructuredDocument();
+
+						int startTagStartOffset = newNode.getStartOffset();
+						int offset = endTagStructuredDocumentRegion.getStart();
+						int length = endTagStructuredDocumentRegion.getLength();
+						structuredDocument.replaceText(structuredDocument, offset, length, ""); //$NON-NLS-1$
+						newNode = (IDOMNode) structuredModel.getIndexedRegion(startTagStartOffset); // save
+
+						offset = startTagStructuredDocumentRegion.getStart() + lastRegion.getStart();
+						structuredDocument.replaceText(structuredDocument, offset, 0, "/"); //$NON-NLS-1$
+						newNode = (IDOMNode) structuredModel.getIndexedRegion(startTagStartOffset); // save
+					}
+				}
+			}
+		}
+
+		return newNode;
+	}
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/cleanup/HTMLCleanupHandlerFactory.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/cleanup/HTMLCleanupHandlerFactory.java
new file mode 100644
index 0000000..8dfc778
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/cleanup/HTMLCleanupHandlerFactory.java
@@ -0,0 +1,104 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.cleanup;
+
+
+
+import org.eclipse.wst.sse.core.internal.cleanup.IStructuredCleanupHandler;
+import org.eclipse.wst.sse.core.internal.cleanup.IStructuredCleanupPreferences;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+import org.w3c.dom.Node;
+
+// nakamori_TODO: check and remove CSS formatting
+
+class HTMLCleanupHandlerFactory {
+
+
+
+	private static HTMLCleanupHandlerFactory fInstance = null;
+
+	static synchronized HTMLCleanupHandlerFactory getInstance() {
+		if (fInstance == null) {
+			fInstance = new HTMLCleanupHandlerFactory();
+		}
+		return fInstance;
+	}
+
+	private HTMLCleanupHandlerFactory() {
+		super();
+	}
+
+	IStructuredCleanupHandler createHandler(Node node, IStructuredCleanupPreferences cleanupPreferences) {
+		short nodeType = node.getNodeType();
+		IStructuredCleanupHandler handler = null;
+		switch (nodeType) {
+			case Node.ELEMENT_NODE : {
+				if (isXMLTag(node))
+					handler = new ElementNodeCleanupHandler();
+				else
+					handler = new JSPElementNodeCleanupHandler();
+				break;
+			}
+			case Node.TEXT_NODE : {
+				if (isParentStyleTag(node))
+					handler = new CSSTextNodeCleanupHandler();
+				else
+					handler = new NodeCleanupHandler();
+				break;
+			}
+			default : {
+				handler = new NodeCleanupHandler();
+			}
+		}
+
+		handler.setCleanupPreferences(cleanupPreferences);
+
+		return handler;
+	}
+	
+	private boolean isXMLTag(Node node) {
+		if(node instanceof IDOMNode) {
+			IStructuredDocumentRegion region = ((IDOMNode) node).getFirstStructuredDocumentRegion();
+			return (DOMRegionContext.XML_TAG_NAME == region.getType());
+		}
+		return false;
+	}
+
+	private boolean isParentStyleTag(Node node) {
+		if (node == null)
+			return false;
+		if (node.getNodeType() != Node.TEXT_NODE)
+			return false;
+		if (!(node instanceof IDOMNode))
+			return false;
+		IStructuredDocumentRegion flatNode = ((IDOMNode) node).getFirstStructuredDocumentRegion();
+		if (flatNode == null)
+			return false;
+		if (flatNode.getType() != DOMRegionContext.BLOCK_TEXT)
+			return false;
+
+		// check if the parent is STYLE element
+		Node parent = node.getParentNode();
+		if (parent == null)
+			return false;
+		if (parent.getNodeType() != Node.ELEMENT_NODE)
+			return false;
+		String name = parent.getNodeName();
+		if (name == null)
+			return false;
+		if (!name.equalsIgnoreCase("STYLE"))//$NON-NLS-1$
+			return false;
+		return true;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/cleanup/HTMLCleanupProcessorImpl.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/cleanup/HTMLCleanupProcessorImpl.java
new file mode 100644
index 0000000..94b2929
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/cleanup/HTMLCleanupProcessorImpl.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.cleanup;
+
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.wst.html.core.internal.HTMLCorePlugin;
+import org.eclipse.wst.html.core.internal.format.HTMLFormatProcessorImpl;
+import org.eclipse.wst.html.core.internal.preferences.HTMLCorePreferenceNames;
+import org.eclipse.wst.html.core.internal.provisional.contenttype.ContentTypeIdForHTML;
+import org.eclipse.wst.sse.core.internal.cleanup.AbstractStructuredCleanupProcessor;
+import org.eclipse.wst.sse.core.internal.cleanup.IStructuredCleanupHandler;
+import org.eclipse.wst.sse.core.internal.cleanup.IStructuredCleanupPreferences;
+import org.eclipse.wst.sse.core.internal.cleanup.StructuredCleanupPreferences;
+import org.eclipse.wst.sse.core.internal.format.IStructuredFormatProcessor;
+import org.w3c.dom.Node;
+
+public class HTMLCleanupProcessorImpl extends AbstractStructuredCleanupProcessor {
+	private IStructuredCleanupPreferences fCleanupPreferences = null;
+	
+	protected String getContentType() {
+		return ContentTypeIdForHTML.ContentTypeID_HTML;
+	}
+
+	protected IStructuredCleanupHandler getCleanupHandler(Node node) {
+		return HTMLCleanupHandlerFactory.getInstance().createHandler(node, getCleanupPreferences());
+	}
+
+	public IStructuredCleanupPreferences getCleanupPreferences() {
+		if (fCleanupPreferences == null) {
+			fCleanupPreferences = new StructuredCleanupPreferences();
+
+			Preferences preferences = getModelPreferences();
+			if (preferences != null) {
+				fCleanupPreferences.setTagNameCase(preferences.getInt(HTMLCorePreferenceNames.CLEANUP_TAG_NAME_CASE));
+				fCleanupPreferences.setAttrNameCase(preferences.getInt(HTMLCorePreferenceNames.CLEANUP_ATTR_NAME_CASE));
+				fCleanupPreferences.setCompressEmptyElementTags(preferences.getBoolean(HTMLCorePreferenceNames.COMPRESS_EMPTY_ELEMENT_TAGS));
+				fCleanupPreferences.setInsertRequiredAttrs(preferences.getBoolean(HTMLCorePreferenceNames.INSERT_REQUIRED_ATTRS));
+				fCleanupPreferences.setInsertMissingTags(preferences.getBoolean(HTMLCorePreferenceNames.INSERT_MISSING_TAGS));
+				fCleanupPreferences.setQuoteAttrValues(preferences.getBoolean(HTMLCorePreferenceNames.QUOTE_ATTR_VALUES));
+				fCleanupPreferences.setFormatSource(preferences.getBoolean(HTMLCorePreferenceNames.FORMAT_SOURCE));
+				fCleanupPreferences.setConvertEOLCodes(preferences.getBoolean(HTMLCorePreferenceNames.CONVERT_EOL_CODES));
+				fCleanupPreferences.setEOLCode(preferences.getString(HTMLCorePreferenceNames.CLEANUP_EOL_CODE));
+			}
+		}
+
+		return fCleanupPreferences;
+	}
+	
+	protected IStructuredFormatProcessor getFormatProcessor() {
+		return new HTMLFormatProcessorImpl();
+	}
+
+	protected Preferences getModelPreferences() {
+		return HTMLCorePlugin.getDefault().getPluginPreferences();
+	}
+	
+	protected void refreshCleanupPreferences() {
+		fCleanupPreferences = null;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/cleanup/JSPElementNodeCleanupHandler.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/cleanup/JSPElementNodeCleanupHandler.java
new file mode 100644
index 0000000..a289144
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/cleanup/JSPElementNodeCleanupHandler.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.cleanup;
+
+
+
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.w3c.dom.Node;
+
+public class JSPElementNodeCleanupHandler extends ElementNodeCleanupHandler {
+
+	public Node cleanup(Node node) {
+		/* <jsp:root> should cleanup its descendant nodes */
+		if(node instanceof IDOMNode) {
+			IStructuredDocumentRegion region = ((IDOMNode) node).getFirstStructuredDocumentRegion();
+			if("JSP_ROOT_TAG_NAME".equals(region.getType())) //$NON-NLS-1$
+				return super.cleanup(node);
+		}
+		return node;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/cleanup/NodeCleanupHandler.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/cleanup/NodeCleanupHandler.java
new file mode 100644
index 0000000..c31f34e
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/cleanup/NodeCleanupHandler.java
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.cleanup;
+
+
+
+import org.w3c.dom.Node;
+
+public class NodeCleanupHandler extends AbstractNodeCleanupHandler {
+
+	public Node cleanup(Node node) {
+		return node;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/commentelement/handlers/CommentElementHandlerForSSI.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/commentelement/handlers/CommentElementHandlerForSSI.java
new file mode 100644
index 0000000..3a528bc
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/commentelement/handlers/CommentElementHandlerForSSI.java
@@ -0,0 +1,150 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.commentelement.handlers;
+
+
+
+import org.eclipse.wst.xml.core.internal.commentelement.CommentElementHandler;
+import org.eclipse.wst.xml.core.internal.commentelement.util.CommentElementFactory;
+import org.eclipse.wst.xml.core.internal.commentelement.util.TagScanner;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.modelquery.ModelQueryUtil;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
+import org.eclipse.wst.xml.core.internal.provisional.document.ISourceGenerator;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+
+public class CommentElementHandlerForSSI implements CommentElementHandler {
+
+	public Element createElement(Document document, String data, boolean isJSPTag) {
+		ModelQuery modelQuery = ModelQueryUtil.getModelQuery(document);
+		if (modelQuery == null) {
+			return null;
+		}
+		CMDocument cm = modelQuery.getCorrespondingCMDocument(document);
+		if (cm == null) {
+			return null;
+		}
+		CMNamedNodeMap map = cm.getElements();
+		if (map == null) {
+			return null;
+		}
+
+		TagScanner scanner = new TagScanner(data, 1);
+		String name = scanner.nextName();
+		if (name == null) {
+			return null;
+		}
+		StringBuffer buffer = new StringBuffer(name.length() + 4);
+		buffer.append(SSI_PREFIX);
+		buffer.append(':');
+		buffer.append(name);
+		String tagName = buffer.toString();
+		// check if valid (defined) SSI tag or not
+		if (map.getNamedItem(tagName) == null) {
+			return null;
+		}
+
+		CommentElementFactory factory = new CommentElementFactory(document, isJSPTag, this);
+		Element element = factory.create(tagName, CommentElementFactory.IS_START);
+
+		// set attributes
+		String attrName = scanner.nextName();
+		while (attrName != null) {
+			String attrValue = scanner.nextValue();
+			Attr attr = document.createAttribute(attrName);
+			if (attr != null) {
+				if (attrValue != null)
+					attr.setValue(attrValue);
+				element.setAttributeNode(attr);
+			}
+			attrName = scanner.nextName();
+		}
+		return element;
+	}
+
+	public String generateStartTagContent(IDOMElement element) {
+		ISourceGenerator generator = element.getModel().getGenerator();
+		StringBuffer buffer = new StringBuffer();
+
+		buffer.append('#');
+		buffer.append(element.getLocalName());
+
+		NamedNodeMap attributes = element.getAttributes();
+		int length = attributes.getLength();
+		for (int i = 0; i < length; i++) {
+			Attr attr = (Attr) attributes.item(i);
+			if (attr == null) {
+				continue;
+			}
+			buffer.append(' ');
+			String attrName = generator.generateAttrName(attr);
+			if (attrName != null) {
+				buffer.append(attrName);
+			}
+			String attrValue = generator.generateAttrValue(attr);
+			if (attrValue != null) {
+				// attr name only for HTML boolean and JSP
+				buffer.append('=');
+				buffer.append(attrValue);
+			}
+		}
+
+		return buffer.toString();
+	}
+
+	public String generateEndTagContent(IDOMElement element) {
+		return null; // always empty
+	}
+
+	public boolean isEmpty() {
+		return true;
+	}
+
+	public boolean isCommentElement(IDOMElement element) {
+		if (element == null) {
+			return false;
+		}
+		Document document = element.getOwnerDocument();
+		ModelQuery modelQuery = ModelQueryUtil.getModelQuery(document);
+		if (modelQuery == null) {
+			return false;
+		}
+		CMDocument cm = modelQuery.getCorrespondingCMDocument(document);
+		if (cm == null) {
+			return false;
+		}
+		CMNamedNodeMap map = cm.getElements();
+		if (map == null) {
+			return false;
+		}
+		String prefix = element.getPrefix();
+		if (prefix == null || !prefix.equals(SSI_PREFIX)) {
+			return false;
+		}
+		String tagName = element.getTagName();
+		if (tagName.length() <= 4) {
+			return false;
+		}
+		if (map.getNamedItem(tagName) == null) {
+			return false;
+		}
+		else {
+			return true;
+		}
+	}
+
+	private static final String SSI_PREFIX = "ssi";//$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/AttributeCollection.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/AttributeCollection.java
new file mode 100644
index 0000000..fa77f0e
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/AttributeCollection.java
@@ -0,0 +1,1691 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.util.Arrays;
+import java.util.Iterator;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ * Factory for attribute declarations.
+ */
+class AttributeCollection extends CMNamedNodeMapImpl implements HTML40Namespace {
+
+	/** bodycolors. */
+	private static final String[] BODYCOLORS = {ATTR_NAME_BGCOLOR, ATTR_NAME_TEXT, ATTR_NAME_LINK, ATTR_NAME_VLINK, ATTR_NAME_ALINK};
+	/** coreattrs. */
+	private static final String[] CORE = {ATTR_NAME_ID, ATTR_NAME_CLASS, ATTR_NAME_STYLE, ATTR_NAME_TITLE};
+	/** events. */
+	private static final String[] EVENTS = {ATTR_NAME_ONCLICK, ATTR_NAME_ONDBLCLICK, ATTR_NAME_ONMOUSEDOWN, ATTR_NAME_ONMOUSEUP, ATTR_NAME_ONMOUSEOVER, ATTR_NAME_ONMOUSEMOVE, ATTR_NAME_ONMOUSEOUT, ATTR_NAME_ONKEYPRESS, ATTR_NAME_ONKEYDOWN, ATTR_NAME_ONKEYUP, ATTR_NAME_ONHELP};
+	/** i18n. lang, dir */
+	private static final String[] I18N = {ATTR_NAME_LANG, ATTR_NAME_DIR};
+	/** cellhaligh. */
+	private static final String[] CELLHALIGN = {ATTR_NAME_CHAR, ATTR_NAME_CHAROFF};
+
+	/**
+	 * constructor.
+	 */
+	public AttributeCollection() {
+		super();
+	}
+
+	/**
+	 * Create an attribute declaration.
+	 * 
+	 * @param attrName
+	 *            java.lang.String
+	 */
+	protected HTMLAttrDeclImpl create(String attrName) {
+		HTMLAttrDeclImpl attr = null;
+		HTMLCMDataTypeImpl atype = null;
+
+		if (attrName.equalsIgnoreCase(ATTR_NAME_ABBR)) {
+			// (abbr %Text; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.TEXT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ABBR, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ACCEPT)) {
+			// (accept %ContentTypes; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.CONTENT_TYPE);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ACCEPT, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ACCEPT_CHARSET)) {
+			// (accept-charset %Charsets;; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.CHARSETS);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ACCEPT_CHARSET, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ACTION)) {
+			// (action %URI #REQUIRED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.URI);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ACTION, atype, CMAttributeDeclaration.REQUIRED);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ARCHIVE)) {
+			// (archive CDATA #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ARCHIVE, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ACCESSKEY)) {
+			// (accesskey %Character; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.CHARACTER);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ACCESSKEY, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ALINK)) {
+			// (alink %Color; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.COLOR);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ALINK, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ALT)) {
+			// (alt %Text; #REQUIRED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.TEXT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ALT, atype, CMAttributeDeclaration.REQUIRED);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_AUTOSTART)) {
+			// (autostart (true|false) #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_VALUE_TRUE, ATTR_VALUE_FALSE};
+			atype.setEnumValues(values);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_AUTOSTART, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_AUTOPLAY)) {
+			// (autoplay (true|false) #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_VALUE_TRUE, ATTR_VALUE_FALSE};
+			atype.setEnumValues(values);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_AUTOPLAY, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_AUTOSIZE)) {
+			// (autosize (true|false) #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_VALUE_TRUE, ATTR_VALUE_FALSE};
+			atype.setEnumValues(values);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_AUTOSIZE, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_AXIS)) {
+			// (axis CDATA #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_AXIS, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_BACKGROUND)) {
+			// (background %URI; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.URI);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_BACKGROUND, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_BEHAVIOR)) {
+			// (behavior (scroll|slide|alternate) scroll)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_VALUE_SCROLL, ATTR_VALUE_SLIDE, ATTR_VALUE_ALTERNATE};
+			atype.setEnumValues(values);
+			atype.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, ATTR_VALUE_SCROLL);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_BEHAVIOR, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_BGCOLOR)) {
+			// (bgcolor %Color; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.COLOR);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_BGCOLOR, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_BORDER)) {
+			// (border %Pixels; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.PIXELS);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_BORDER, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_CELLSPACING)) {
+			// (cellspacing %Length; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.LENGTH);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_CELLSPACING, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_CELLPADDING)) {
+			// (cellpadding %Length; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.LENGTH);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_CELLPADDING, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_CGI)) {
+			// (cgi %URI; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.URI);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_CGI, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_CHAR)) {
+			// (char %Character; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.CHARACTER);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_CHAR, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_CHAROFF)) {
+			// (charoff %Length; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.LENGTH);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_CHAROFF, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_CHARSET)) {
+			// (charset %Charset; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.CHARSET);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_CHARSET, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_CITE)) {
+			// (cite %URI; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.URI);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_CITE, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_CLASS)) {
+			// (class CDATA #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_CLASS, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_CLASSID)) {
+			// (classid %URI #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.URI);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_CLASSID, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_CMD)) {
+			// (cmd CDATA #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_CMD, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_CHECKED)) {
+			// (checked (checked) #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_NAME_CHECKED};
+			atype.setEnumValues(values);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_CHECKED, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_CLEAR)) {
+			// (clear (left | all | right | none) none)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_VALUE_LEFT, ATTR_VALUE_ALL, ATTR_VALUE_RIGHT, ATTR_VALUE_NONE};
+			atype.setEnumValues(values);
+			atype.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, ATTR_VALUE_NONE);
+
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_CLEAR, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_CODE)) {
+			// (code CDATA #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_CODE, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_CODEBASE)) {
+			// (codebase %URI; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.URI);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_CODEBASE, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_CODETYPE)) {
+			// (codetype %CotentType; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.CONTENT_TYPE);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_CODETYPE, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_COLOR)) {
+			// (color %Color; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.COLOR);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_COLOR, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_COMPACT)) {
+			// (compact (compact) #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_NAME_COMPACT};
+			atype.setEnumValues(values);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_COMPACT, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_COLS)) {
+			// (cols NUMBER #REQUIRED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.NUMBER);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_COLS, atype, CMAttributeDeclaration.REQUIRED);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_COLSPAN)) {
+			// (colspan NUMBER 1)
+			atype = new HTMLCMDataTypeImpl(CMDataType.NUMBER);
+			atype.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, ATTR_VALUE_1);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_COLSPAN, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_CONTENT)) {
+			// (content CDATA #REQUIRED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_CONTENT, atype, CMAttributeDeclaration.REQUIRED);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_CONTROLLER)) {
+			// (controller (true|false) true)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_VALUE_TRUE, ATTR_VALUE_FALSE};
+			atype.setEnumValues(values);
+			atype.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, ATTR_VALUE_TRUE);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_CONTROLLER, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_COORDS)) {
+			// (coords %Coords; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.COORDS);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_COORDS, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_DATA)) {
+			// (data %URI; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.URI);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_DATA, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_DATETIME)) {
+			// (datetime %Datetime; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.DATETIME);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_DATETIME, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_DATAPAGESIZE)) {
+			// (datapagesize CDATA #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_DATAPAGESIZE, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_DECLARE)) {
+			// (declare (declare) #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_NAME_DECLARE};
+			atype.setEnumValues(values);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_DECLARE, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_DEFER)) {
+			// (defer (defer) #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_NAME_DEFER};
+			atype.setEnumValues(values);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_DEFER, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_DIR)) {
+			// (dir (ltr|rtl) #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_VALUE_LTR, ATTR_VALUE_RTL};
+			atype.setEnumValues(values);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_DIR, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_DIRECTION)) {
+			// (direction (left|right|up|down) left)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_VALUE_LEFT, ATTR_VALUE_RIGHT, ATTR_VALUE_UP, ATTR_VALUE_DOWN};
+			atype.setEnumValues(values);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_DIRECTION, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_DIRECTKEY)) {
+			// (directkey %Character; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.CHARACTER);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_DIRECTKEY, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_DISABLED)) {
+			// (disabled (disabled) #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			// boolean attribute must have the same value as its name.
+			String[] values = {ATTR_NAME_DISABLED};
+			atype.setEnumValues(values);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_DISABLED, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ENCTYPE)) {
+			// (enctype %ContentType; "application/x-www-form-urlencoded")
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.CONTENT_TYPE);
+			atype.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, ATTR_VALUE_WWW_FORM_URLENCODED);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ENCTYPE, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ERRMSG)) {
+			// (errmsg CDATA #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ERRMSG, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_EVENT)) {
+			// (event CDATA #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_EVENT, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_FACE)) {
+			// (face CDATA #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_FACE, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_FILE)) {
+			// (file %URI; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.URI);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_FILE, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_FOR)) {
+			// (for %URI; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.URI);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_FOR, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_FRAME)) {
+			// (frame %TFrame; #IMPLIED)
+			// %TFrame; is
+			// (void|above|below|hsides|lhs|rhs|vsides|box|border).
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_VALUE_VOID, ATTR_VALUE_ABOVE, ATTR_VALUE_BELOW, ATTR_VALUE_HSIDES, ATTR_VALUE_LHS, ATTR_VALUE_RHS, ATTR_VALUE_VSIDES, ATTR_VALUE_BOX, ATTR_VALUE_BORDER};
+			atype.setEnumValues(values);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_FRAME, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_FRAMEBORDER)) {
+			// (frameborder (1|0) 1)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_VALUE_1, ATTR_VALUE_0};
+			atype.setEnumValues(values);
+			atype.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, ATTR_VALUE_1);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_FRAMEBORDER, atype, CMAttributeDeclaration.OPTIONAL);
+
+			// <<D215684
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_FRAMESPACING)) {
+			// (framespacing CDATA; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_FRAMESPACING, atype, CMAttributeDeclaration.OPTIONAL);
+			// D215684
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_HEADERS)) {
+			// (HEADERS IDREFS; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.IDREFS);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_HEADERS, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_HEIGHT)) {
+			// (height %Length; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.LENGTH);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_HEIGHT, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_HIDDEN)) {
+			// (hidden CDATA #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_HIDDEN, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_HREF)) {
+			// (href %URI; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.URI);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_HREF, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_HREFLANG)) {
+			// (hreflang %LanguageCode; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.LANGUAGE_CODE);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_HREFLANG, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_HSPACE)) {
+			// (hspace %Pixels; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.PIXELS);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_HSPACE, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_HTTP_EQUIV)) {
+			// (http-equiv NAME #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.NAME);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_HTTP_EQUIV, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ID)) {
+			// (id ID #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ID);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ID, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ISMAP)) {
+			// (ismap (ismap) #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_NAME_ISMAP};
+			atype.setEnumValues(values);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ISMAP, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ISTYLE)) {
+			// (istyle CDATA #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ISTYLE, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_LABEL)) {
+			// (label %Text; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.TEXT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_LABEL, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_LANG)) {
+			// (lang %LanguageCode; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.LANGUAGE_CODE);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_LANG, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_LANGUAGE)) {
+			// (language %CDATA; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_LANGUAGE, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_LINK)) {
+			// (link %Color; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.COLOR);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_LINK, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_LONGDESC)) {
+			// (longdesc %URI; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.URI);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_LONGDESC, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_LOOP)) {
+			// (loop CDATA #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_LOOP, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_MACRO)) {
+			// (macro CDATA #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_MACRO, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_MAPFILE)) {
+			// (mapfile %URI; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.URI);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_MAPFILE, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_MARGINWIDTH)) {
+			// (marginwidth %Pixels; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.PIXELS);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_MARGINWIDTH, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_MARGINHEIGHT)) {
+			// (marginheight %Pixels; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.PIXELS);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_MARGINHEIGHT, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_MAXLENGTH)) {
+			// (maxlength NUMBER #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.NUMBER);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_MAXLENGTH, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_MAYSCRIPT)) {
+			// (mayscript (mayscript) #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_NAME_MAYSCRIPT};
+			atype.setEnumValues(values);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_MAYSCRIPT, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_MEDIA)) {
+			// (media %MediaDesc; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.MEDIA_DESC);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_MEDIA, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_METHOD)) {
+			// (method (GET|POST) GET)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_VALUE_GET, ATTR_VALUE_POST};
+			atype.setEnumValues(values);
+			atype.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, ATTR_VALUE_GET);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_METHOD, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_MULTIPLE)) {
+			// (multiple (multiple) #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_NAME_MULTIPLE};
+			atype.setEnumValues(values);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_MULTIPLE, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_NAME)) {
+			// (name CDATA #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_NAME, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_NOHREF)) {
+			// (nohref (nohref) #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_NAME_NOHREF};
+			atype.setEnumValues(values);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_NOHREF, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_NORESIZE)) {
+			// (noresize (noresize) #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_NAME_NORESIZE};
+			atype.setEnumValues(values);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_NORESIZE, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_NOSHADE)) {
+			// (noshade (noshade) #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_NAME_NOSHADE};
+			atype.setEnumValues(values);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_NOSHADE, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_NOWRAP)) {
+			// (nowrap (nowrap) #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_NAME_NOWRAP};
+			atype.setEnumValues(values);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_NOWRAP, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_OBJECT)) {
+			// (object CDATA #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_NAME_OBJECT};
+			atype.setEnumValues(values);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_OBJECT, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONBLUR)) {
+			// (onblur %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONBLUR, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONCLICK)) {
+			// (onclick %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONCLICK, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONCHANGE)) {
+			// (onchange %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONCHANGE, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONDBLCLICK)) {
+			// (ondblclick %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONDBLCLICK, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONFOCUS)) {
+			// (onfocus %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONFOCUS, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONHELP)) {
+			// (onhelp %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONHELP, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONKEYPRESS)) {
+			// (onkeypress %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONKEYPRESS, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONKEYDOWN)) {
+			// (onkeydown %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONKEYDOWN, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONKEYUP)) {
+			// (onkyeup %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONKEYUP, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONLOAD)) {
+			// (onload %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONLOAD, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONMOUSEDOWN)) {
+			// (onmousedown %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONMOUSEDOWN, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONMOUSEUP)) {
+			// (onmouseup %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONMOUSEUP, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONMOUSEOVER)) {
+			// (onmouseover %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONMOUSEOVER, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONMOUSEMOVE)) {
+			// (onmousemove %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONMOUSEMOVE, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONMOUSEOUT)) {
+			// (onmouseout %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONMOUSEOUT, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONRESET)) {
+			// (onreset %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONRESET, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONSELECT)) {
+			// (onselect %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONSELECT, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONSUBMIT)) {
+			// (onsubmit %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONSUBMIT, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONUNLOAD)) {
+			// (onunload %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONUNLOAD, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_PALETTE)) {
+			// (palette CDATA; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_PALETTE, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_PANEL)) {
+			// (panel CDATA; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_PANEL, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_PLAYCOUNT)) {
+			// (playcount NUMBER; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.NUMBER);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_PLAYCOUNT, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_PROFILE)) {
+			// (profile %URI; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.URI);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_PROFILE, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_PROMPT)) {
+			// (prompt %Text; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.TEXT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_PROMPT, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_READONLY)) {
+			// (readonly (readonly) #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_NAME_READONLY};
+			atype.setEnumValues(values);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_READONLY, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_REPEAT)) {
+			// (repeat CDATA #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_REPEAT, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_REL)) {
+			// (rel %LinkTypes; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.LINK_TYPES);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_REL, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_REV)) {
+			// (rev %LinkTypes; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.LINK_TYPES);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_REV, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ROWS)) {
+			// (rows NUMBER #REQUIRED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.NUMBER);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ROWS, atype, CMAttributeDeclaration.REQUIRED);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ROWSPAN)) {
+			// (rowspan NUMBER 1)
+			atype = new HTMLCMDataTypeImpl(CMDataType.NUMBER);
+			atype.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, ATTR_VALUE_1);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ROWSPAN, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_RULES)) {
+			// (rules %TRules; #IMPLIED)
+			// %TRules; is (none | groups | rows | cols | all).
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_VALUE_NONE, ATTR_VALUE_GROUPS, ATTR_VALUE_ROWS, ATTR_VALUE_COLS, ATTR_VALUE_ALL};
+			atype.setEnumValues(values);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_RULES, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_SCALE)) {
+			// (scale CDATA #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_SCALE, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_SCHEME)) {
+			// (scheme CDATA #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_SCHEME, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_SELECTED)) {
+			// (selected (selected) #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_NAME_SELECTED};
+			atype.setEnumValues(values);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_SELECTED, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_SCOPE)) {
+			// (SCOPE %Scope; #IMPLIED)
+			// %Scope; is (row|col|rowgroup|colgroup)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_VALUE_ROW, ATTR_VALUE_COL, ATTR_VALUE_ROWGROUP, ATTR_VALUE_COLGROUP};
+			atype.setEnumValues(values);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_SCOPE, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_SCROLLAMOUNT)) {
+			// (scrollamount NUMBER #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.NUMBER);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_SCROLLAMOUNT, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_SCROLLDELAY)) {
+			// (scrolldelay NUMBER #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.NUMBER);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_SCROLLDELAY, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_SCROLLING)) {
+			// (scrolling (yes|no|auto) auto)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_VALUE_YES, ATTR_VALUE_NO, ATTR_VALUE_AUTO};
+			atype.setEnumValues(values);
+			atype.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, ATTR_VALUE_AUTO);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_SCROLLING, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_SHAPE)) {
+			// (shape %Shape; rect): %Shape; is (rect|circle|poly|default).
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_VALUE_RECT, ATTR_VALUE_CIRCLE, ATTR_VALUE_POLY, ATTR_VALUE_DEFAULT};
+			atype.setEnumValues(values);
+			atype.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, ATTR_VALUE_RECT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_SHAPE, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_SHOWCONTROLS)) {
+			// (showcontrols (true|false) #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_VALUE_TRUE, ATTR_VALUE_FALSE};
+			atype.setEnumValues(values);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_SHOWCONTROLS, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_SIZE)) {
+			// (size %Pixels; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.PIXELS);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_SIZE, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_SIZEFMT)) {
+			// (sizefmt CDATA #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_SIZEFMT, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_SPAN)) {
+			// (span NUMBER 1)
+			atype = new HTMLCMDataTypeImpl(CMDataType.NUMBER);
+			atype.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, ATTR_VALUE_1);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_SPAN, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_SRC)) {
+			// (src %URI; #IMPLIED)
+			// NOTE: "src" attributes are defined in several elements.
+			// The definition of IMG is different from others.
+			// So, it should be locally defined.
+			atype = new HTMLCMDataTypeImpl(CMDataType.URI);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_SRC, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_START)) {
+			// (start NUMBER #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.NUMBER);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_START, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_STANDBY)) {
+			// (standby %Text; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.TEXT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_STANDBY, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_STYLE)) {
+			// (style %StyleSheet; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.STYLE_SHEET);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_STYLE, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_SUMMARY)) {
+			// (summary %Text; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.TEXT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_SUMMARY, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_TABINDEX)) {
+			// (tabindex NUMBER #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.NUMBER);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_TABINDEX, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_TARGET)) {
+			// (target %FrameTarget; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.FRAME_TARGET);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_TARGET, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_TEXT)) {
+			// (text %Color; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.COLOR);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_TEXT, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_TEXTFOCUS)) {
+			// (textfocus CDATA #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_TEXTFOCUS, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_TITLE)) {
+			// (title %Text; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.TEXT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_TITLE, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_TIMEFMT)) {
+			// (timefmt CDATA #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_TIMEFMT, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_TRUESPEED)) {
+			// (truespeed (truespeed) #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_NAME_TRUESPEED};
+			atype.setEnumValues(values);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_TRUESPEED, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_TYPE)) {
+			// (type %CotentType; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.CONTENT_TYPE);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_TYPE, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_USEMAP)) {
+			// (usemap %URI; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.URI);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_USEMAP, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_VALIGN)) {
+			// (valign (top|middle|bottom|baseline) #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_VALUE_TOP, ATTR_VALUE_MIDDLE, ATTR_VALUE_BOTTOM, ATTR_VALUE_BASELINE};
+			atype.setEnumValues(values);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_VALIGN, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_VALUE)) {
+			// (value CDATA #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_VALUE, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_VALUETYPE)) {
+			// (valuetype (DATA|REF|OBJECT) DATA)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_VALUE_DATA, ATTR_VALUE_REF, ATTR_VALUE_OBJECT};
+			atype.setEnumValues(values);
+			atype.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, ATTR_VALUE_DATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_VALUETYPE, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_VAR)) {
+			// (var CDATA #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_VAR, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_VERSION)) {
+			// (version CDATA #FIXED '%HTML.Version;)
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			atype.setImpliedValue(CMDataType.IMPLIED_VALUE_FIXED, ATTR_VALUE_VERSION_TRANSITIONAL);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_VERSION, atype, CMAttributeDeclaration.FIXED);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_VIRTUAL)) {
+			// (virtual %URI; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.URI);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_VIRTUAL, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_VLINK)) {
+			// (vlink %Color; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.COLOR);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_VLINK, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_VOLUME)) {
+			// (volume CDATA #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_VOLUME, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_WIDTH)) {
+			// (width %Length; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.LENGTH);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_WIDTH, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_VSPACE)) {
+			// (vspace %Pixels; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.PIXELS);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_VSPACE, atype, CMAttributeDeclaration.OPTIONAL);
+
+			// <<D205514
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_TOPMARGIN)) {
+			// (topmargin, CDATA, #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_TOPMARGIN, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_BOTTOMMARGIN)) {
+			// (bottommargin, CDATA, #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_BOTTOMMARGIN, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_LEFTMARGIN)) {
+			// (leftmargin, CDATA, #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_LEFTMARGIN, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_RIGHTMARGIN)) {
+			// (rightmargin, CDATA, #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_RIGHTMARGIN, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_BORDERCOLOR)) {
+			// (bordercolor, %Color; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.COLOR);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_BORDERCOLOR, atype, CMAttributeDeclaration.OPTIONAL);
+			// D205514
+
+		}
+		else {
+			// unknown attribute; maybe error.
+			// should warn.
+			attr = null;
+		}
+
+		return attr;
+	}
+
+	/**
+	 * Get align attribute which has %CAlign; as values.. At this time
+	 * (4/19/2001), it is identical to %LAlign;.
+	 * 
+	 */
+	public static final HTMLAttrDeclImpl createAlignForCaption() {
+		// align (local)
+		HTMLCMDataTypeImpl atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+		// set enum values
+		String[] values = {ATTR_VALUE_TOP, ATTR_VALUE_BOTTOM, ATTR_VALUE_LEFT, ATTR_VALUE_RIGHT};
+		atype.setEnumValues(values);
+
+		HTMLAttrDeclImpl attr = new HTMLAttrDeclImpl(ATTR_NAME_ALIGN, atype, CMAttributeDeclaration.OPTIONAL);
+		return attr;
+	}
+
+	/**
+	 * Get align attribute which has %IAlign; as values..
+	 */
+	public static final HTMLAttrDeclImpl createAlignForImage() {
+		// align (local)
+		HTMLCMDataTypeImpl atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+		// set enum values
+		String[] values = {ATTR_VALUE_TOP, ATTR_VALUE_MIDDLE, ATTR_VALUE_BOTTOM, ATTR_VALUE_LEFT, ATTR_VALUE_RIGHT};
+		atype.setEnumValues(values);
+
+		HTMLAttrDeclImpl attr = new HTMLAttrDeclImpl(ATTR_NAME_ALIGN, atype, CMAttributeDeclaration.OPTIONAL);
+		return attr;
+	}
+
+	/**
+	 * Get align attribute which has %LAlign; as values..
+	 */
+	public static final HTMLAttrDeclImpl createAlignForLegend() {
+		// align (local)
+		HTMLCMDataTypeImpl atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+		// set enum values
+		String[] values = {ATTR_VALUE_TOP, ATTR_VALUE_BOTTOM, ATTR_VALUE_LEFT, ATTR_VALUE_RIGHT};
+		atype.setEnumValues(values);
+
+		HTMLAttrDeclImpl attr = new HTMLAttrDeclImpl(ATTR_NAME_ALIGN, atype, CMAttributeDeclaration.OPTIONAL);
+		return attr;
+	}
+
+	/**
+	 * Create an attribute declaration for <code>align</code> in several
+	 * elements, like <code>P</code>, <code>DIV</code>. The values are
+	 * different from attributes those have the same name in other elements (<code>IMG</code>
+	 * and <code>TABLE</code>). So, it can't treat as global attributes.
+	 * <strong>NOTE: These attribute declaration has no owner CMDocument
+	 * instance.</strong>
+	 */
+	public static final HTMLAttrDeclImpl createAlignForParagraph() {
+		HTMLCMDataTypeImpl atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+		// set enum values: left|center|right|justify
+		String[] values = {ATTR_VALUE_LEFT, ATTR_VALUE_CENTER, ATTR_VALUE_RIGHT, ATTR_VALUE_JUSTIFY};
+		atype.setEnumValues(values);
+
+		HTMLAttrDeclImpl attr = new HTMLAttrDeclImpl(ATTR_NAME_ALIGN, atype, CMAttributeDeclaration.OPTIONAL);
+		return attr;
+	}
+
+	/**
+	 * Get %attrs; declarations. %attrs; consists of %coreattrs;, %i18n, and
+	 * %events;.
+	 */
+	public void getAttrs(CMNamedNodeMapImpl declarations) {
+		// %coreattrs;
+		Iterator names = Arrays.asList(CORE).iterator();
+		getDeclarations(declarations, names);
+		// %i18n;
+		names = Arrays.asList(I18N).iterator();
+		getDeclarations(declarations, names);
+		// %events;
+		names = Arrays.asList(EVENTS).iterator();
+		getDeclarations(declarations, names);
+	}
+
+	/**
+	 * Get %bodycolors; declarations.
+	 */
+	public void getBodycolors(CMNamedNodeMapImpl declarations) {
+		Iterator names = Arrays.asList(BODYCOLORS).iterator();
+		getDeclarations(declarations, names);
+	}
+
+	/**
+	 * Get %cellhalign; declarations. %cellhaligh; consists of: - (align
+	 * (left|center|right|justify|char) #IMPLIED) - (char %Character;
+	 * #IMPLIED) - (charoff %Length; #IMPLIED)
+	 */
+	public void getCellhalign(CMNamedNodeMapImpl declarations) {
+		// (align (left|center|right|justify|char) #IMPLIED) should be defined
+		// locally.
+		HTMLCMDataTypeImpl atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+		// set enum values
+		String[] values = {ATTR_VALUE_LEFT, ATTR_VALUE_CENTER, ATTR_VALUE_RIGHT, ATTR_VALUE_JUSTIFY, ATTR_VALUE_CHAR};
+		atype.setEnumValues(values);
+
+		HTMLAttrDeclImpl attr = new HTMLAttrDeclImpl(ATTR_NAME_ALIGN, atype, CMAttributeDeclaration.OPTIONAL);
+		declarations.putNamedItem(ATTR_NAME_ALIGN, attr);
+
+		// the rest.
+		Iterator names = Arrays.asList(CELLHALIGN).iterator();
+		getDeclarations(declarations, names);
+	}
+
+	/**
+	 * Get %cellvalign; declarations. %cellhaligh; is: - (valign
+	 * (top|middle|bottom|baseline) #IMPLIED)
+	 */
+	public void getCellvalign(CMNamedNodeMapImpl declarations) {
+		HTMLAttributeDeclaration dec = getDeclaration(ATTR_NAME_VALIGN);
+		if (dec != null)
+			declarations.putNamedItem(ATTR_NAME_VALIGN, dec);
+	}
+
+	/**
+	 * Get %coreattrs; declarations.
+	 */
+	public void getCore(CMNamedNodeMapImpl declarations) {
+		Iterator names = Arrays.asList(CORE).iterator();
+		getDeclarations(declarations, names);
+	}
+
+	/**
+	 * Get a global attribute declaration.
+	 * 
+	 * @param attrName
+	 *            java.lang.String
+	 */
+	public HTMLAttributeDeclaration getDeclaration(String attrName) {
+		CMNode cmnode = getNamedItem(attrName);
+		if (cmnode != null)
+			return (HTMLAttributeDeclaration) cmnode; // already exists.
+
+		HTMLAttrDeclImpl dec = create(attrName);
+		if (dec != null)
+			putNamedItem(attrName, dec);
+
+		return dec;
+	}
+
+	/**
+	 * Get declarations which are specified by names.
+	 * 
+	 * @param names
+	 *            java.util.Iterator
+	 */
+	public void getDeclarations(CMNamedNodeMapImpl declarations, Iterator names) {
+		while (names.hasNext()) {
+			String attrName = (String) names.next();
+			HTMLAttributeDeclaration dec = getDeclaration(attrName);
+			if (dec != null)
+				declarations.putNamedItem(attrName, dec);
+		}
+	}
+
+	/**
+	 * Get %events; declarations.
+	 */
+	public void getEvents(CMNamedNodeMapImpl declarations) {
+		Iterator names = Arrays.asList(EVENTS).iterator();
+		getDeclarations(declarations, names);
+	}
+
+	/**
+	 * Get %i18n; declarations.
+	 */
+	public void getI18n(CMNamedNodeMapImpl declarations) {
+		Iterator names = Arrays.asList(I18N).iterator();
+		getDeclarations(declarations, names);
+	}
+	
+	/**
+	 * create declarations.
+	 */
+	public void createAttributeDeclarations(String elementName, CMNamedNodeMapImpl attributes) {
+		 /* (type %InputType; TEXT) ... should be defined locally.
+		 * (name CDATA #IMPLIED)
+		 * (value CDATA #IMPLIED)
+		 * (checked (checked) #IMPLIED)
+		 * (disabled (disabled) #IMPLIED)
+		 * (readonly (readonly) #IMPLIED)
+		 * (size CDATA #IMPLIED) ... should be defined locally.
+		 * (maxlength NUMBER #IMPLIED)
+		 * (src %URI; #IMPLIED)
+		 * (alt CDATA #IMPLIED) ... should be defined locally.
+		 * (usemap %URI; #IMPLIED)
+		 * (ismap (ismap) #IMPLIED)
+		 * (tabindex NUMBER #IMPLIED)
+		 * (accesskey %Character; #IMPLIED)
+		 * (onfocus %Script; #IMPLIED)
+		 * (onblur %Script; #IMPLIED)
+		 * (onselect %Script; #IMPLIED)
+		 * (onchange %Script; #IMPLIED)
+		 * (accept %ContentTypes; #IMPLIED)
+		 * (align %IAlign; #IMPLIED) ... should be defined locally.
+		 * (istyle CDATA #IMPLIED)
+		 * <<D215684
+		 * (width CDATA; #IMPLIED)
+		 * (height CDATA; #IMPLIED)
+		 * (border CDATA; #IMPLIED)
+		 * D215684
+		 */
+		if (elementName.equals(HTML40Namespace.ElementName.INPUT)){
+			HTMLCMDataTypeImpl atype = null;
+			HTMLAttrDeclImpl attr = null;
+			// (type %InputType; TEXT) ... should be defined locally.
+			// NOTE: %InputType is ENUM;
+			// (text | password | checkbox | radio | submit | reset |
+			//  file | hidden | image | button)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_VALUE_TEXT, ATTR_VALUE_PASSWORD, ATTR_VALUE_CHECKBOX, ATTR_VALUE_RADIO, ATTR_VALUE_SUBMIT, ATTR_VALUE_RESET, ATTR_VALUE_FILE, ATTR_VALUE_HIDDEN, ATTR_VALUE_IMAGE, ATTR_VALUE_BUTTON};
+			atype.setEnumValues(values);
+			atype.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, ATTR_VALUE_TEXT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_TYPE, atype, CMAttributeDeclaration.OPTIONAL);
+			attributes.putNamedItem(ATTR_NAME_TYPE, attr);
+
+			// (size CDATA #IMPLIED) ... should be defined locally.
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_SIZE, atype, CMAttributeDeclaration.OPTIONAL);
+			attributes.putNamedItem(ATTR_NAME_SIZE, attr);
+
+			// (alt CDATA #IMPLIED) ... should be defined locally.
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ALT, atype, CMAttributeDeclaration.OPTIONAL);
+			attributes.putNamedItem(ATTR_NAME_ALT, attr);
+
+			// (align %IAlign; #IMPLIED) ... should be defined locally.
+			attr = AttributeCollection.createAlignForImage();
+			attributes.putNamedItem(ATTR_NAME_ALIGN, attr);
+
+			// the rest.
+			String[] names = {ATTR_NAME_NAME, ATTR_NAME_VALUE, ATTR_NAME_CHECKED, ATTR_NAME_DISABLED, ATTR_NAME_READONLY, ATTR_NAME_SIZE, ATTR_NAME_MAXLENGTH, ATTR_NAME_SRC, ATTR_NAME_ALT, ATTR_NAME_USEMAP, ATTR_NAME_ISMAP, ATTR_NAME_TABINDEX, ATTR_NAME_ACCESSKEY, ATTR_NAME_ONFOCUS, ATTR_NAME_ONBLUR, ATTR_NAME_ONSELECT, ATTR_NAME_ONCHANGE, ATTR_NAME_ACCEPT, ATTR_NAME_ALIGN, ATTR_NAME_ISTYLE,
+			//<<D215684
+						ATTR_NAME_WIDTH, ATTR_NAME_HEIGHT, ATTR_NAME_BORDER
+			//<D215684
+			};
+			getDeclarations(attributes, Arrays.asList(names).iterator());
+		}
+		 /* (charset %Charset; #IMPLIED)
+		 * (href %URI; #IMPLIED)
+		 * (hreflang %LanguageCode; #IMPLIED)
+		 * (type %ContentType; #IMPLIED): should be defined locally.
+		 * (rel %LinkTypes; #IMPLIED)
+		 * (rev %LinkTypes; #IMPLIED)
+		 * (media %MediaDesc; #IMPLIED)
+		 * (target %FrameTarget; #IMPLIED)
+		 */
+		else if (elementName.equals(HTML40Namespace.ElementName.LINK)){
+			String[] names = {ATTR_NAME_CHARSET, ATTR_NAME_HREF, ATTR_NAME_HREFLANG, ATTR_NAME_REL, ATTR_NAME_REV, ATTR_NAME_MEDIA, ATTR_NAME_TARGET};
+			getDeclarations(attributes, Arrays.asList(names).iterator());
+
+			// (type %ContentType; #IMPLIED)
+			HTMLCMDataTypeImpl atype = new HTMLCMDataTypeImpl(HTMLCMDataType.CONTENT_TYPE);
+			HTMLAttrDeclImpl attr = new HTMLAttrDeclImpl(ATTR_NAME_TYPE, atype, CMAttributeDeclaration.OPTIONAL);
+			attributes.putNamedItem(ATTR_NAME_TYPE, attr);
+		
+		}
+		/* (charset %Charset; #IMPLIED)
+		 * (type %ContentType; #IMPLIED)
+		 * (name CDATA #IMPLIED)
+		 * (href %URI; #IMPLIED)
+		 * (hreflang %LanguageCode; #IMPLIED)
+		 * (target %FrameTarget; #IMPLIED)
+		 * (rel %LinkTypes; #IMPLIED)
+		 * (rev %LinkTypes; #IMPLIED)
+		 * (accesskey %Character; #IMPLIED)
+		 * (directkey %Character; #IMPLIED)
+		 * (shape %Shape; rect)
+		 * (coords %Coords; #IMPLIED)
+		 * (tabindex NUMBER #IMPLIED)
+		 * (onfocus %Script; #IMPLIED)
+		 * (onblur %Script; #IMPLIED) 
+		 */
+		else if (elementName.equals(HTML40Namespace.ElementName.A)){
+			String[] names = {ATTR_NAME_CHARSET, ATTR_NAME_TYPE, ATTR_NAME_NAME, ATTR_NAME_HREF, ATTR_NAME_HREFLANG, ATTR_NAME_TARGET, ATTR_NAME_REL, ATTR_NAME_REV, ATTR_NAME_ACCESSKEY, ATTR_NAME_DIRECTKEY, ATTR_NAME_SHAPE, ATTR_NAME_COORDS, ATTR_NAME_TABINDEX, ATTR_NAME_ONFOCUS, ATTR_NAME_ONBLUR};
+			getDeclarations(attributes, Arrays.asList(names).iterator());
+		
+		}
+		/*
+		 * (shape %Shape; rect)
+		 * (coords %Coords; #IMPLIED)
+		 * (href %URI; #IMPLIED)
+		 * (target %FrameTarget; #IMPLIED)
+		 * (nohref (nohref) #IMPLIED)
+		 * (alt %Text; #REQUIRED)
+		 * (tabindex NUMBER #IMPLIED)
+		 * (accesskey %Character; #IMPLIED)
+		 * (onfocus %Script; #IMPLIED)
+		 * (onblur %Script; #IMPLIED)
+		 */
+		else if (elementName.equals(HTML40Namespace.ElementName.AREA)){
+			String[] names = {ATTR_NAME_SHAPE, ATTR_NAME_COORDS, ATTR_NAME_HREF, ATTR_NAME_TARGET, ATTR_NAME_NOHREF, ATTR_NAME_ALT, ATTR_NAME_TABINDEX, ATTR_NAME_ACCESSKEY, ATTR_NAME_ONFOCUS, ATTR_NAME_ONBLUR};
+			getDeclarations(attributes, Arrays.asList(names).iterator());
+		}
+		/*
+		 *  %i18n;
+		 * (http-equiv NAME #IMPLIED)
+		 * (name NAME #IMPLIED) ... should be defined locally.
+		 * (content CDATA #REQUIRED)
+		 * (scheme CDATA #IMPLIED)
+		 */
+		else if (elementName.equals(HTML40Namespace.ElementName.META)){
+			// %i18n;
+			getI18n(attributes);
+
+			// (name NAME #IMPLIED) ... should be defined locally.
+			HTMLCMDataTypeImpl atype = new HTMLCMDataTypeImpl(HTMLCMDataType.NAME);
+			HTMLAttrDeclImpl attr = new HTMLAttrDeclImpl(ATTR_NAME_NAME, atype, CMAttributeDeclaration.OPTIONAL);
+			attributes.putNamedItem(ATTR_NAME_NAME, attr);
+
+			String[] names = {ATTR_NAME_HTTP_EQUIV, ATTR_NAME_CONTENT, ATTR_NAME_SCHEME};
+			getDeclarations(attributes, Arrays.asList(names).iterator());
+		}
+		/*
+		 * (src %URI; #REQUIRED): should be defined locally.
+		 * (alt %Text; #REQUIRED)
+		 * (longdesc %URI; #IMPLIED)
+		 * (name CDATA #IMPLIED)
+		 * (height %Length; #IMPLIED)
+		 * (width %Length; #IMPLIED)
+		 * (usemap %URI; #IMPLIED)
+		 * (ismap (ismap) #IMPLIED)
+		 * (align %IAlign; #IMPLIED): should be defined locally.
+		 * (border %Pixels; #IMPLIED)
+		 * (hspace %Pixels; #IMPLIED)
+		 * (vspace %Pixels; #IMPLIED)
+		 * (mapfile %URI; #IMPLIED)
+	 
+		 */
+		else if (elementName.equals(HTML40Namespace.ElementName.IMG)){
+			// (src %URI; #REQUIRED): should be defined locally.
+			HTMLCMDataTypeImpl atype = null;
+			HTMLAttrDeclImpl attr = null;
+			atype = new HTMLCMDataTypeImpl(CMDataType.URI);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_SRC, atype, CMAttributeDeclaration.REQUIRED);
+			attributes.putNamedItem(ATTR_NAME_SRC, attr);
+
+			String[] names = {ATTR_NAME_ALT, ATTR_NAME_LONGDESC, ATTR_NAME_NAME, ATTR_NAME_HEIGHT, ATTR_NAME_WIDTH, ATTR_NAME_USEMAP, ATTR_NAME_ISMAP, ATTR_NAME_BORDER, ATTR_NAME_HSPACE, ATTR_NAME_VSPACE, ATTR_NAME_MAPFILE};
+			getDeclarations(attributes, Arrays.asList(names).iterator());
+
+			// align (local); should be defined locally.
+			attr = AttributeCollection.createAlignForImage();
+			attributes.putNamedItem(ATTR_NAME_ALIGN, attr);
+		
+		}
+		/*
+		 * (id ID #IMPLIED)
+		 * (name CDATA #REQUIRED) ... should be defined locally.
+		 * (value CDATA #IMPLIED)
+		 * (valuetype (DATA|REF|OBJECT) DATA)
+		 * (type %ContentType; #IMPLIED)
+		 */
+		else if (elementName.equals(HTML40Namespace.ElementName.PARAM)){
+			String[] names = {ATTR_NAME_ID, ATTR_NAME_VALUE, ATTR_NAME_VALUETYPE, ATTR_NAME_TYPE};
+			getDeclarations(attributes, Arrays.asList(names).iterator());
+
+			// (name CDATA #REQUIRED) ... should be defined locally.
+			HTMLCMDataTypeImpl atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			HTMLAttrDeclImpl attr = new HTMLAttrDeclImpl(ATTR_NAME_NAME, atype, CMAttributeDeclaration.REQUIRED);
+			attributes.putNamedItem(ATTR_NAME_NAME, attr);
+		}
+		/*
+		 * %reserved; ... empty
+		 * (name CDATA #IMPLIED)
+		 * (rows NUMBER #REQUIRED)
+		 * (cols NUMBER #REQUIRED)
+		 * (disabled (disabled) #IMPLIED)
+		 * (readonly (readonly) #IMPLIED)
+		 * (tabindex NUMBER #IMPLIED)
+		 * (accesskey %Character; #IMPLIED)
+		 * (onfocus %Script; #IMPLIED)
+		 * (onblur %Script; #IMPLIED)
+		 * (onselect %Script; #IMPLIED)
+		 * (onchange %Script; #IMPLIED)
+		 * (istyle CDATA #IMPLIED)
+		 */
+		else if (elementName.equals(HTML40Namespace.ElementName.TEXTAREA)){
+			String[] names = {ATTR_NAME_NAME, ATTR_NAME_ROWS, ATTR_NAME_COLS, ATTR_NAME_DISABLED, ATTR_NAME_READONLY, ATTR_NAME_TABINDEX, ATTR_NAME_ACCESSKEY, ATTR_NAME_ONFOCUS, ATTR_NAME_ONBLUR, ATTR_NAME_ONSELECT, ATTR_NAME_ONCHANGE, ATTR_NAME_ISTYLE};
+			getDeclarations(attributes, Arrays.asList(names).iterator());
+		}
+		/*
+		 * (charset %Charset; #IMPLIED)
+		 * (type %ContentType; #REQUIRED) ... should be defined locally.
+		 * (language CDATA #IMPLIED)
+		 * (src %URI; #IMPLIED)
+		 * (defer (defer) #IMPLIED)
+		 * (event CDATA #IMPLIED)
+		 * (for %URI; #IMPLIED)
+		 */
+		else if (elementName.equals(HTML40Namespace.ElementName.SCRIPT)){
+			String[] names = {ATTR_NAME_CHARSET, ATTR_NAME_LANGUAGE, ATTR_NAME_SRC, ATTR_NAME_DEFER, ATTR_NAME_EVENT, ATTR_NAME_FOR};
+			getDeclarations(attributes, Arrays.asList(names).iterator());
+
+			// (type %ContentType; #REQUIRED) ... should be defined locally.
+			HTMLCMDataTypeImpl atype = new HTMLCMDataTypeImpl(HTMLCMDataType.CONTENT_TYPE);
+			atype.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, "text/javascript"); //$NON-NLS-1$
+			HTMLAttrDeclImpl attr = new HTMLAttrDeclImpl(ATTR_NAME_TYPE, atype, CMAttributeDeclaration.REQUIRED);
+			attributes.putNamedItem(ATTR_NAME_TYPE, attr);
+		
+		}
+		/*
+		 *  %i18n;
+		 * (type %ContentType; #REQUIRED) ... should be defined locally.
+		 * (media %MediaDesc; #IMPLIED)
+		 * (title %Text; #IMPLIED)
+		 */
+		else if (elementName.equals(HTML40Namespace.ElementName.STYLE)){
+			// %i18n;
+			getI18n(attributes);
+
+			String[] names = {ATTR_NAME_MEDIA, ATTR_NAME_TITLE};
+			getDeclarations(attributes, Arrays.asList(names).iterator());
+			// (type %ContentType; #REQUIRED) ... should be defined locally.
+			HTMLCMDataTypeImpl atype = new HTMLCMDataTypeImpl(HTMLCMDataType.CONTENT_TYPE);
+			atype.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, "text/css"); //$NON-NLS-1$
+			HTMLAttrDeclImpl attr = new HTMLAttrDeclImpl(ATTR_NAME_TYPE, atype, CMAttributeDeclaration.REQUIRED);
+			attributes.putNamedItem(ATTR_NAME_TYPE, attr);
+		
+		}
+		/*
+		 * %reserved;
+		 * (name CDATA #IMPLIED)
+		 * (size NUMBER #IMPLIED) ... should be defined locally.
+		 * (multiple (multiple) #IMPLIED)
+		 * (disabled (disabled) #IMPLIED)
+		 * (tabindex NUMBER #IMPLIED)
+		 * (onfocus %Script; #IMPLIED)
+		 * (onblur %Script; #IMPLIED)
+		 * (onchange %Script; #IMPLIED)
+		 */
+		else if (elementName.equals(HTML40Namespace.ElementName.SELECT)){
+			// (size NUMBER #IMPLIED) ... should be defined locally.
+			HTMLCMDataTypeImpl atype = new HTMLCMDataTypeImpl(CMDataType.NUMBER);
+			HTMLAttrDeclImpl attr = new HTMLAttrDeclImpl(ATTR_NAME_SIZE, atype, CMAttributeDeclaration.OPTIONAL);
+			attributes.putNamedItem(ATTR_NAME_SIZE, attr);
+
+			String[] names = {ATTR_NAME_NAME, ATTR_NAME_MULTIPLE, ATTR_NAME_DISABLED, ATTR_NAME_TABINDEX, ATTR_NAME_ONFOCUS, ATTR_NAME_ONBLUR, ATTR_NAME_ONCHANGE};
+			getDeclarations(attributes, Arrays.asList(names).iterator());
+		
+		}
+		/*
+		 * 	(type %LIStyle; #IMPLIED) ... should be defined locally.
+		 * (value NUMBER #IMPLIED) ... should be defined locally.
+		 */
+		else if (elementName.equals(HTML40Namespace.ElementName.LI)){
+			// (type %LIStyle; #IMPLIED) ... should be defined locally.
+			HTMLCMDataTypeImpl atype = new HTMLCMDataTypeImpl(HTMLCMDataType.LI_STYLE);
+			HTMLAttrDeclImpl attr = new HTMLAttrDeclImpl(ATTR_NAME_TYPE, atype, CMAttributeDeclaration.OPTIONAL);
+			attributes.putNamedItem(ATTR_NAME_TYPE, attr);
+
+			// (value NUMBER #IMPLIED) ... should be defined locally.
+			atype = new HTMLCMDataTypeImpl(CMDataType.NUMBER);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_VALUE, atype, CMAttributeDeclaration.OPTIONAL);
+			attributes.putNamedItem(ATTR_NAME_VALUE, attr);
+		
+		}
+		/*
+		 * (type %OLStyle; #IMPLIED) ... should be defined locally.
+		 * (compact (compact) #IMPLIED)
+		 * (start NUMBER #IMPLIED)
+		 */
+		else if (elementName.equals(HTML40Namespace.ElementName.OL)){
+			// (type %OLStyle; #IMPLIED) ... should be defined locally.
+			HTMLCMDataTypeImpl atype = new HTMLCMDataTypeImpl(HTMLCMDataType.OL_STYLE);
+			HTMLAttrDeclImpl attr = new HTMLAttrDeclImpl(ATTR_NAME_TYPE, atype, CMAttributeDeclaration.OPTIONAL);
+			attributes.putNamedItem(ATTR_NAME_TYPE, attr);
+
+			// the rest.
+			String[] names = {ATTR_NAME_COMPACT, ATTR_NAME_START};
+			getDeclarations(attributes, Arrays.asList(names).iterator());
+		
+		}
+		/**
+		 * %coreattrs;
+		 * (longdesc %URI; #IMPLIED)
+		 * (name CDATA #IMPLIED)
+		 * (src %URI; #IMPLIED)
+		 * (frameborder (1|0) 1)
+		 * (marginwidth %Pixels; #IMPLIED)
+		 * (marginheight %Pixels; #IMPLIED)
+		 * (scrolling (yes|no|auto) auto)
+		 * (align %IAlign; #IMPLIED) ... should be defined locally.
+		 * (height %Length; #IMPLIED)
+		 * (width %Length; #IMPLIED)
+		 */
+		else if (elementName.equals(HTML40Namespace.ElementName.IFRAME)){
+			// %coreattrs;
+			getCore(attributes);
+
+			String[] names = {ATTR_NAME_LONGDESC, ATTR_NAME_NAME, ATTR_NAME_SRC, ATTR_NAME_FRAMEBORDER, ATTR_NAME_MARGINWIDTH, ATTR_NAME_MARGINHEIGHT, ATTR_NAME_SCROLLING, ATTR_NAME_HEIGHT, ATTR_NAME_WIDTH};
+			getDeclarations(attributes, Arrays.asList(names).iterator());
+
+			// align
+			HTMLAttrDeclImpl attr = AttributeCollection.createAlignForImage();
+			if (attr != null)
+				attributes.putNamedItem(ATTR_NAME_ALIGN, attr);
+		
+		}
+		/*
+		 * %i18n attrs
+		 * %version
+		 */
+		else if (elementName.equals(HTML40Namespace.ElementName.HTML)){
+			// %i18n;
+			getI18n(attributes);
+			// version
+			HTMLAttributeDeclaration adec = getDeclaration(ATTR_NAME_VERSION);
+			if (adec != null)
+				attributes.putNamedItem(ATTR_NAME_VERSION, adec);
+		
+		}
+		/*
+		 * (compact (compact) #IMPLIED)
+	 	 */
+		else if (elementName.equals(HTML40Namespace.ElementName.MENU)){
+			String[] names = {ATTR_NAME_COMPACT};
+			getDeclarations(attributes, Arrays.asList(names).iterator());
+		
+		}
+		/*
+		 * %reserved; ... empty.
+		 * (name CDATA #IMPLIED)
+		 * (value CDATA #IMPLIED)
+		 * (type (button|submit|reset) submit) ... should be defined locally.
+		 * (disabled (disabled) #IMPLIED)
+		 * (tabindex NUMBER #IMPLIED)
+		 * (accesskey %Character; #IMPLIED)
+		 * (onfocus %Script; #IMPLIED)
+		 * (onblur %Script; #IMPLIED)
+	 	 */
+		else if (elementName.equals(HTML40Namespace.ElementName.BUTTON)){
+			String[] names = {ATTR_NAME_NAME, ATTR_NAME_VALUE, ATTR_NAME_DISABLED, ATTR_NAME_TABINDEX, ATTR_NAME_ACCESSKEY, ATTR_NAME_ONFOCUS, ATTR_NAME_ONBLUR};
+			getDeclarations(attributes, Arrays.asList(names).iterator());
+
+			// (type (button|submit|reset) submit) ... should be defined locally.
+			HTMLCMDataTypeImpl atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_VALUE_BUTTON, ATTR_VALUE_SUBMIT, ATTR_VALUE_RESET};
+			atype.setEnumValues(values);
+
+			HTMLAttrDeclImpl attr = new HTMLAttrDeclImpl(ATTR_NAME_TYPE, atype, CMAttributeDeclaration.OPTIONAL);
+			attributes.putNamedItem(ATTR_NAME_TYPE, attr);
+		
+		}
+		/*
+		 * %reserved;
+		 * (summary %Text; #IMPLIED)
+		 * (width %Length; #IMPLIED)
+		 * (border %Pixels; #IMPLIED)
+		 * (frame %TFrame; #IMPLIED)
+		 * (rules %TRules; #IMPLIED)
+		 * (cellspacing %Length; #IMPLIED)
+		 * (cellpadding %Length; #IMPLIED)
+		 * (align %TAlign; #IMPLIED)
+		 * (bgcolor %Color; #IMPLIED)
+		 * (datapagesize CDATA #IMPLIED)
+		 * (height %Pixels; #IMPLIED)
+		 * (background %URI; #IMPLIED)
+		 * (bordercolor %Color #IMPLIED) ... D205514
+		 */
+		else if (elementName.equals(HTML40Namespace.ElementName.TABLE)){
+			// %reserved;
+			// ... %reserved; is empty in the current DTD.
+
+			String[] names = {ATTR_NAME_SUMMARY, ATTR_NAME_WIDTH, ATTR_NAME_BORDER, ATTR_NAME_FRAME, ATTR_NAME_RULES, ATTR_NAME_CELLSPACING, ATTR_NAME_CELLPADDING, ATTR_NAME_BGCOLOR, ATTR_NAME_DATAPAGESIZE, ATTR_NAME_HEIGHT, ATTR_NAME_BACKGROUND, ATTR_NAME_BORDERCOLOR // D205514
+			};
+			getDeclarations(attributes, Arrays.asList(names).iterator());
+
+			// align (local)
+			HTMLCMDataTypeImpl atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] alignValues = {ATTR_VALUE_LEFT, ATTR_VALUE_CENTER, ATTR_VALUE_RIGHT};
+			atype.setEnumValues(alignValues);
+			HTMLAttrDeclImpl adec = new HTMLAttrDeclImpl(ATTR_NAME_ALIGN, atype, CMAttributeDeclaration.OPTIONAL);
+			attributes.putNamedItem(ATTR_NAME_ALIGN, adec);
+			
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CMContentImpl.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CMContentImpl.java
new file mode 100644
index 0000000..07973a5
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CMContentImpl.java
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMContent;
+
+
+
+/**
+ * Implementation of CMContent for HTML CM.
+ */
+abstract class CMContentImpl extends CMNodeImpl implements CMContent {
+
+	public static final int UNBOUNDED = -1;
+	/**  -1: it's UNBOUNDED. */
+	private int maxOccur = UNBOUNDED;
+	/**  0: it's OPTIONAL, 1, it's REQUIRED. */
+	private int minOccur = 0;
+
+	/**
+	 * The primary consturctor.
+	 * Use this one for usual cases.<br>
+	 */
+	public CMContentImpl(String name, int min, int max) {
+		super(name);
+		minOccur = min;
+		maxOccur = max;
+	}
+
+	/**
+	 * getMaxOccur method
+	 * @return int
+	 *
+	 * If -1, it's UNBOUNDED.
+	 */
+	public int getMaxOccur() {
+		return maxOccur;
+	}
+
+	/**
+	 * getMinOccur method
+	 * @return int
+	 *
+	 * If 0, it's OPTIONAL.
+	 * If 1, it's REQUIRED.
+	 */
+	public int getMinOccur() {
+		return minOccur;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CMGroupImpl.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CMGroupImpl.java
new file mode 100644
index 0000000..0108c61
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CMGroupImpl.java
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNodeList;
+
+/**
+ */
+class CMGroupImpl extends CMContentImpl implements CMGroup {
+
+	private int operator = CMGroup.SEQUENCE;
+	private CMNodeListImpl children = null;
+
+	/**
+	 * CMGroupImpl constructor comment.
+	 */
+	public CMGroupImpl(int op, int minOccur, int maxOccur) {
+		super(null, minOccur, maxOccur);
+		switch (op) {
+			case CMGroup.ALL :
+			case CMGroup.CHOICE :
+			case CMGroup.SEQUENCE :
+				operator = op;
+				break;
+			default :
+				// should warn.
+				break;
+		}
+	}
+
+	/**
+	 * @return org.eclipse.wst.xml.core.internal.contentmodel.CMNode
+	 * @param org.eclipse.wst.xml.core.internal.contentmodel.CMNode
+	 */
+	protected CMNode appendChild(CMNode child) {
+		if (child == null)
+			return null;
+		if (children == null)
+			children = new CMNodeListImpl();
+		return children.appendNode(child);
+	}
+
+	/**
+	 * @return org.eclipse.wst.xml.core.internal.contentmodel.CMNodeList
+	 */
+	public CMNodeList getChildNodes() {
+		return children;
+	}
+
+	/**
+	 * getNodeType method
+	 * @return int
+	 *
+	 * Returns one of :
+	 * ELEMENT_DECLARATION, ATTRIBUTE_DECLARATION, GROUP, ENTITY_DECLARATION.
+	 */
+	public int getNodeType() {
+		return CMNode.GROUP;
+	}
+
+	/**
+	 * getOperation method
+	 * @return int
+	 *
+	 * Returns one of :
+	 * ALONE (a), SEQUENCE (a,b), CHOICE (a|b), ALL (a&b).
+	 */
+	public int getOperator() {
+		return operator;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CMNamedNodeMapImpl.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CMNamedNodeMapImpl.java
new file mode 100644
index 0000000..f8a5e60
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CMNamedNodeMapImpl.java
@@ -0,0 +1,114 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Locale;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ * An implementation of the CMNamedNodeMap interface. This class is intented
+ * to be used as a container of attribute declarations. If someone wants to
+ * use this class for other purpose, he must pay attention to the fact that
+ * this class is tolerant of the key name case. That is, this class does not
+ * distinguish "name", "NAME", and "Name" as a key name.
+ */
+class CMNamedNodeMapImpl implements CMNamedNodeMap {
+
+	private Hashtable items = null;
+
+	/**
+	 */
+	public CMNamedNodeMapImpl() {
+		super();
+		items = new Hashtable();
+	}
+
+	/**
+	 * getLength method
+	 * 
+	 * @return int
+	 */
+	public int getLength() {
+		return items.size();
+	}
+
+	/**
+	 * getNamedItem method
+	 * 
+	 * @return CMNode <code>null</code> for unknown keys.
+	 * @param name
+	 *            java.lang.String
+	 */
+	public CMNode getNamedItem(String name) {
+		String cookedName = makeCanonicalForm(name);
+		if (!items.containsKey(cookedName))
+			return null;
+		return (CMNode) items.get(cookedName);
+	}
+
+	/**
+	 * item method
+	 * 
+	 * @return CMNode
+	 * @param index
+	 *            int
+	 */
+	public CMNode item(int index) {
+		Iterator iter = iterator();
+		while (iter.hasNext()) {
+			CMNode node = (CMNode) iter.next();
+			if (--index < 0)
+				return node;
+		}
+		return null;
+	}
+
+	/**
+	 * @return java.util.Iterator
+	 */
+	public Iterator iterator() {
+		return items.values().iterator();
+	}
+
+	/**
+	 * @return java.lang.String
+	 * @param rawForm
+	 *            java.lang.String
+	 */
+	private String makeCanonicalForm(String raw) {
+		// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=100152
+		// we are able to "cheat" here a little and use US Locale
+		// to get a good cononical form, since we are using this only
+		// for HTML and JSP standard tags.
+		// Long term, for similar needs with XML 1.1 (for example)
+		// we should use a class such as com.ibm.icu.text.Normalizer
+		return raw.toUpperCase(Locale.US);
+	}
+
+	/**
+	 * @param key
+	 *            java.lang.String
+	 * @param item
+	 *            java.lang.String
+	 */
+	void putNamedItem(String name, CMNode item) {
+		String cookedName = makeCanonicalForm(name);
+		if (items.containsKey(cookedName))
+			return; // already registered.
+		items.put(cookedName, item);
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CMNamespaceImpl.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CMNamespaceImpl.java
new file mode 100644
index 0000000..6ef737a
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CMNamespaceImpl.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ * CMNamespace implementation.
+ */
+class CMNamespaceImpl extends CMNodeImpl implements CMNamespace {
+
+	private java.lang.String prefix = null;
+
+	/**
+	 * CMNamespaceImpl constructor comment.
+	 */
+	public CMNamespaceImpl(String uri, String pfx) {
+		super(uri);
+		prefix = pfx;
+	}
+
+	/**
+	 * getNodeType method
+	 * @return int
+	 *
+	 * Returns one of :
+	 *
+	 */
+	public int getNodeType() {
+		return CMNode.NAME_SPACE;
+	}
+
+	/**
+	 * getPrefix method
+	 * @return java.lang.String
+	 */
+	public String getPrefix() {
+		return prefix;
+	}
+
+	/**
+	 * getURI method
+	 * @return java.lang.String
+	 */
+	public String getURI() {
+		return getNodeName();
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CMNodeImpl.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CMNodeImpl.java
new file mode 100644
index 0000000..2f6eb44
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CMNodeImpl.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+import org.eclipse.wst.html.core.internal.provisional.HTMLCMProperties;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+
+
+/**
+ */
+abstract class CMNodeImpl implements CMNode {
+
+	private java.lang.String name = null;
+
+	/**
+	 * CMNodeImpl constructor comment.
+	 */
+	public CMNodeImpl(String nm) {
+		super();
+		name = nm;
+	}
+
+	/**
+	 * getNodeName method
+	 * @return java.lang.String
+	 */
+	public String getNodeName() {
+		return name;
+	}
+
+	/**
+	 * getProperty method
+	 * @return java.lang.Object
+	 *
+	 * Returns the object property desciped by the propertyName
+	 *
+	 */
+	public Object getProperty(String propertyName) {
+		if (propertyName.equals(HTMLCMProperties.IS_XHTML))
+			return new Boolean(false);
+		return null;
+	}
+
+	/**
+	 * supports method
+	 * @return boolean
+	 *
+	 * Returns true if the CMNode supports a specified property
+	 *
+	 */
+	public boolean supports(String propertyName) {
+		if (propertyName.equals(HTMLCMProperties.IS_XHTML))
+			return true;
+		return false;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CMNodeListImpl.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CMNodeListImpl.java
new file mode 100644
index 0000000..08bf21a
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CMNodeListImpl.java
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNodeList;
+
+/**
+ * Analog of dom.NodeList for CM.
+ * So, the implementation is very similar to
+ * NodeListImpl<br>
+ */
+class CMNodeListImpl implements CMNodeList {
+
+	private java.util.Vector nodes = null;
+
+	/**
+	 * CMNodeListImpl constructor comment.
+	 */
+	public CMNodeListImpl() {
+		super();
+		nodes = new java.util.Vector();
+	}
+
+	/**
+	 * @return org.eclipse.wst.xml.core.internal.contentmodel.CMNode
+	 * @param node org.eclipse.wst.xml.core.internal.contentmodel.CMNode
+	 */
+	protected CMNode appendNode(CMNode node) {
+		nodes.addElement(node);
+		return node;
+	}
+
+	/**
+	 * getLength method
+	 * @return int
+	 */
+	public int getLength() {
+		return nodes.size();
+	}
+
+	/**
+	 * item method
+	 * @return CMNode
+	 * @param index int
+	 */
+	public CMNode item(int index) {
+		if (index < 0 || index >= nodes.size())
+			return null;
+		return (CMNode) nodes.elementAt(index);
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/ComplexTypeDefinition.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/ComplexTypeDefinition.java
new file mode 100644
index 0000000..91dba7c
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/ComplexTypeDefinition.java
@@ -0,0 +1,75 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+
+/**
+ * This class is intended to represent a complex type definition
+ * in XML Schema.<br>
+ */
+abstract class ComplexTypeDefinition {
+
+	protected CMGroupImpl content = null;
+	protected ElementCollection collection = null;
+	protected String primaryCandidateName = null;
+
+	/**
+	 * ComplexTypeDefinition constructor comment.
+	 */
+	public ComplexTypeDefinition(ElementCollection elementCollection) {
+		super();
+		collection = elementCollection;
+		createContent();
+	}
+
+	/**
+	 * Create an actual content model.
+	 * This method should be called once and only once in the constructor.<br>
+	 */
+	protected abstract void createContent();
+
+	/**
+	 * @return org.eclipse.wst.xml.core.internal.contentmodel.CMGroup
+	 */
+	public CMGroup getContent() {
+		return content;
+	}
+
+	/**
+	 * @return int; Should be one of ANY, EMPTY, ELEMENT, MIXED, PCDATA, CDATA,
+	 * those are defined in CMElementDeclaration.
+	 */
+	/* NOTE: Do we need LOGICAL type?
+	 * -- 3/7/2001
+	 */
+	public abstract int getContentType();
+
+	/**
+	 * Get content hint.
+	 */
+	public HTMLElementDeclaration getPrimaryCandidate() {
+		if (primaryCandidateName == null)
+			return null;
+		return (HTMLElementDeclaration) collection.getNamedItem(primaryCandidateName);
+	}
+
+	/**
+	 * Name of complex type definition.
+	 * Each singleton must know its own name.
+	 * All names should be defined in
+	 * {@link <code>ComplexTypeDefinitionFactory</code>} as constants.<br>
+	 * @return java.lang.String
+	 */
+	public abstract String getTypeName();
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/ComplexTypeDefinitionFactory.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/ComplexTypeDefinitionFactory.java
new file mode 100644
index 0000000..51d693d
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/ComplexTypeDefinitionFactory.java
@@ -0,0 +1,230 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+/**
+ * Factory of ComplexTypeDefinition.
+ */
+final class ComplexTypeDefinitionFactory {
+
+	private static ComplexTypeDefinitionFactory instance = null;
+	private java.util.Hashtable definitions = null;
+	// constants for complex type name
+	/** for ADDRESS. */
+	public final static String CTYPE_ADDRESS = "CTYPE_ADDRESS";//$NON-NLS-1$
+	/** CDATA content. No ComplexTypeDefinition instance shuld be created. */
+	public final static String CTYPE_CDATA = "CTYPE_CDATA";//$NON-NLS-1$
+	/** col group content. COL* */
+	public final static String CTYPE_COLUMN_GROUP = "CTYPE_COLUMN_GROUP";//$NON-NLS-1$
+	/** for DL. */
+	public final static String CTYPE_DEFINITION_LIST = "CTYPE_DEFINITION_LIST";//$NON-NLS-1$
+	/** for DETAILS */
+	public final static String CTYPE_DETAILS_CONTAINER = "CTYPE_DETAILS_CONTAINER";//$NON-NLS-1$
+	/** for EMBED. */
+	public final static String CTYPE_EMBED = "CTYPE_EMBED";//$NON-NLS-1$
+	/** empty content. No ComplexTypeDefinition instance should be created. */
+	public final static String CTYPE_EMPTY = "CTYPE_EMPTY";//$NON-NLS-1$
+	/** for FIELDSET. */
+	public final static String CTYPE_FIELDSET = "CTYPE_FIELDSET";//$NON-NLS-1$
+	/** for FRAMESET. */
+	public final static String CTYPE_FRAMESET = "CTYPE_FRAMESET";//$NON-NLS-1$
+	/** flow content. (%flow;)* */
+	public final static String CTYPE_FLOW_CONTAINER = "CTYPE_FLOW_CONTAINER";//$NON-NLS-1$
+	/** html content. HEAD, (FRAMESET|BODY) */
+	public final static String CTYPE_HTML = "CTYPE_HTML";//$NON-NLS-1$
+	/** head content. TITLE & ISINDEX? & BASE? */
+	public final static String CTYPE_HEAD = "CTYPE_HEAD";//$NON-NLS-1$
+	/** inline content. (%inline;)* */
+	public final static String CTYPE_INLINE_CONTAINER = "CTYPE_INLINE_CONTAINER";//$NON-NLS-1$
+	/** list item container. (LI)+ */
+	public final static String CTYPE_LI_CONTAINER = "CTYPE_LI_CONTAINER";//$NON-NLS-1$
+	/** for MAP. */
+	public final static String CTYPE_MAP = "CTYPE_MAP";//$NON-NLS-1$
+	/** noframes content. */
+	public final static String CTYPE_NOFRAMES_CONTENT = "CTYPE_NOFRAMES_CONTENT";//$NON-NLS-1$
+	/** for OPTGROUP. */
+	public final static String CTYPE_OPTION_CONTAINER = "CTYPE_OPTION_CONTAINER";//$NON-NLS-1$
+	/** param container. For OBJECT/APPLET. */
+	public final static String CTYPE_PARAM_CONTAINER = "CTYPE_PARAM_CONTAINER";//$NON-NLS-1$
+	/** PCDATA content. No ComplexTypeDefinition instance shuld be created. */
+	public final static String CTYPE_PCDATA = "CTYPE_PCDATA";//$NON-NLS-1$
+	/** for SELECT. */
+	public final static String CTYPE_SELECT = "CTYPE_SELECT";//$NON-NLS-1$
+	/** table content. CAPTION?, (COL*|COLGROUP*), THEAD?, TFOOT?, TBODY+ */
+	public final static String CTYPE_TABLE = "CTYPE_TABLE";//$NON-NLS-1$
+	/** table cell contaier. (TH|TD)+ */
+	public final static String CTYPE_TCELL_CONTAINER = "CTYPE_TCELL_CONTAINER";//$NON-NLS-1$
+	/** table record container. (TR)+ */
+	public final static String CTYPE_TR_CONTAINER = "CTYPE_TR_CONTAINER";//$NON-NLS-1$
+	/** heading group container. (H1|h2|H3|H4|H5|H6)+ */
+	public final static String CTYPE_HEADING_CONTAINER = "CTYPE_HGROUP_CONTAINER"; //$NON-NLS-1$
+	/** media content. (AUDIO|VIDEO) */
+	public final static String CTYPE_MEDIA_ELEMENT = "CTYPE_MEDIA";//$NON-NLS-1$
+	/** for DATALIST. */
+	public final static String CTYPE_DATALIST = "CTYPE_DATALIST";//$NON-NLS-1$
+	/** for FIGURE. */
+	public final static String CTYPE_FIGURE = "CTYPE_FIGURE";//$NON-NLS-1$
+	/** for RUBY. */
+	public final static String CTYPE_RUBY = "CTYPE_RUBY";//$NON-NLS-1$
+	
+	/**
+	 * ComplexTypeDefinitionFactory constructor comment.
+	 */
+	private ComplexTypeDefinitionFactory() {
+		super();
+		definitions = new java.util.Hashtable();
+	}
+
+	/**
+	 * Factory method for ComplexTypeDefinition.
+	 * Each instance created in this method must be registered into
+	 * the map with its name.
+	 * @param definitionName java.lang.String
+	 * @param elementCollection ElementCollection
+	 */
+	public ComplexTypeDefinition createTypeDefinition(String definitionName, ElementCollection elementCollection) {
+		ComplexTypeDefinition[] defs = null;
+		if (definitions.containsKey(definitionName)) {
+			defs =  (ComplexTypeDefinition[]) definitions.get(definitionName);
+			for (int i = 0; i < defs.length; i++) {
+				if (defs[i].collection == elementCollection)
+					return defs[i];
+			}
+		}
+		else {
+			// initialize a new definition
+			defs = new ComplexTypeDefinition[0];
+		}
+
+		ComplexTypeDefinition def = null;
+		if (definitionName == CTYPE_ADDRESS) {
+			def = new CtdAddress(elementCollection);
+
+		}
+		else if (definitionName == CTYPE_COLUMN_GROUP) {
+			def = new CtdColumnGroup(elementCollection);
+
+		}
+		else if (definitionName == CTYPE_DATALIST) {
+			def = new CtdDatalist(elementCollection);
+
+		}
+		else if (definitionName == CTYPE_DEFINITION_LIST) {
+			def = new CtdDl(elementCollection);
+
+		}
+		else if (definitionName == CTYPE_DETAILS_CONTAINER) {
+			def = new CtdDetails(elementCollection);
+		}
+		else if (definitionName == CTYPE_EMBED) {
+			def = new CtdEmbed(elementCollection);
+
+		}
+		else if (definitionName == CTYPE_FIELDSET) {
+			def = new CtdFieldset(elementCollection);
+
+		}
+		else if (definitionName == CTYPE_FIGURE) {
+			def = new CtdFigure(elementCollection);
+
+		}
+		else if (definitionName == CTYPE_FLOW_CONTAINER) {
+			def = new CtdFlowContainer(elementCollection);
+
+		}
+		else if (definitionName == CTYPE_FRAMESET) {
+			def = new CtdFrameset(elementCollection);
+
+		}
+		else if (definitionName == CTYPE_HEAD) {
+			def = new CtdHead(elementCollection);
+
+		}
+		else if (definitionName == CTYPE_HEADING_CONTAINER) {
+			def = new CtdHeadingContainer(elementCollection);
+		}
+		else if (definitionName == CTYPE_HTML) {
+			def = new CtdHtml(elementCollection);
+
+		}
+		else if (definitionName == CTYPE_INLINE_CONTAINER) {
+			def = new CtdInlineContainer(elementCollection);
+
+		}
+		else if (definitionName == CTYPE_LI_CONTAINER) {
+			def = new CtdLiContainer(elementCollection);
+
+		}
+		else if (definitionName == CTYPE_MAP) {
+			def = new CtdMap(elementCollection);
+
+		}
+		else if (definitionName == CTYPE_MEDIA_ELEMENT) {
+			def = new CtdMediaElement(elementCollection);
+			
+		}
+		else if (definitionName == CTYPE_NOFRAMES_CONTENT) {
+			def = new CtdNoframesContent(elementCollection);
+
+		}
+		else if (definitionName == CTYPE_OPTION_CONTAINER) {
+			def = new CtdOptionContainer(elementCollection);
+
+		}
+		else if (definitionName == CTYPE_PARAM_CONTAINER) {
+			def = new CtdParamContainer(elementCollection);
+
+		}
+		else if (definitionName == CTYPE_RUBY) {
+			def = new CtdRuby(elementCollection);
+
+		}
+		else if (definitionName == CTYPE_SELECT) {
+			def = new CtdSelect(elementCollection);
+
+		}
+		else if (definitionName == CTYPE_TABLE) {
+			def = new CtdTable(elementCollection);
+
+		}
+		else if (definitionName == CTYPE_TCELL_CONTAINER) {
+			def = new CtdTableCellContainer(elementCollection);
+
+		}
+		else if (definitionName == CTYPE_TR_CONTAINER) {
+			def = new CtdTrContainer(elementCollection);
+
+		}
+		else {
+			def = null;
+		}
+		if (def == null)
+			return null; // fail to create.
+		ComplexTypeDefinition[] temp = defs;
+		defs = new ComplexTypeDefinition[defs.length + 1];
+		System.arraycopy(temp, 0, defs, 0, temp.length);
+		defs[temp.length] = def;
+		definitions.put(definitionName, defs);
+		return def;
+	}
+
+	/**
+	 * For singleton.
+	 */
+	public synchronized static ComplexTypeDefinitionFactory getInstance() {
+		if (instance != null)
+			return instance;
+		instance = new ComplexTypeDefinitionFactory();
+		return instance;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdAddress.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdAddress.java
new file mode 100644
index 0000000..76847d0
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdAddress.java
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ * for ADDRESS.
+ */
+final class CtdAddress extends ComplexTypeDefinition {
+
+	/**
+	 * @param elementCollection ElementCollection
+	 */
+	public CtdAddress(ElementCollection elementCollection) {
+		super(elementCollection);
+	}
+
+	/**
+	 * ((%inline) | P)*.
+	 */
+	protected void createContent() {
+		if (content != null)
+			return; // already created.
+		if (collection == null)
+			return;
+
+		// ( | )*
+		content = new CMGroupImpl(CMGroup.CHOICE, 0, CMContentImpl.UNBOUNDED);
+		// (%inline)
+		CMGroupImpl inlines = new CMGroupImpl(CMGroup.CHOICE, 1, 1);
+		if (inlines == null)
+			return;
+		collection.getInline(inlines);
+		content.appendChild(inlines);
+		// P
+		CMNode p = collection.getNamedItem(HTML40Namespace.ElementName.P);
+		if (p != null)
+			content.appendChild(p);
+	}
+
+	/**
+	 * ((%inline) | P)*.
+	 * Because %inline; contains #PCDATA, the type is MIXED.
+	 * @return int; Should be one of ANY, EMPTY, ELEMENT, MIXED, PCDATA, CDATA,
+	 * those are defined in CMElementDeclaration.
+	 */
+	public int getContentType() {
+		return CMElementDeclaration.MIXED;
+	}
+
+	/**
+	 * @return java.lang.String
+	 */
+	public String getTypeName() {
+		return ComplexTypeDefinitionFactory.CTYPE_ADDRESS;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdColumnGroup.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdColumnGroup.java
new file mode 100644
index 0000000..623399d
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdColumnGroup.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ * COL group.
+ * (COL)*
+ */
+final class CtdColumnGroup extends ComplexTypeDefinition {
+
+	/**
+	 * @param elementCollection ElementCollection
+	 */
+	public CtdColumnGroup(ElementCollection elementCollection) {
+		super(elementCollection);
+	}
+
+	/**
+	 * (COL)*
+	 */
+	protected void createContent() {
+		if (content != null)
+			return; // already created.
+		if (collection == null)
+			return;
+
+		// ( )*
+		content = new CMGroupImpl(CMGroup.SEQUENCE, 0, CMContentImpl.UNBOUNDED);
+		// COL
+		CMNode dec = collection.getNamedItem(HTML40Namespace.ElementName.COL);
+		if (dec != null)
+			content.appendChild(dec);
+	}
+
+	/**
+	 * (COL)*
+	 * @return int; Should be one of ANY, EMPTY, ELEMENT, MIXED, PCDATA, CDATA,
+	 * those are defined in CMElementDeclaration.
+	 */
+	public int getContentType() {
+		return CMElementDeclaration.ELEMENT;
+	}
+
+	/**
+	 * Name of complex type definition.
+	 * Each singleton must know its own name.
+	 * All names should be defined in
+	 * {@link <code>ComplexTypeDefinitionFactory</code>} as constants.<br>
+	 * @return java.lang.String
+	 */
+	public String getTypeName() {
+		return ComplexTypeDefinitionFactory.CTYPE_COLUMN_GROUP;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdDatalist.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdDatalist.java
new file mode 100644
index 0000000..457debf
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdDatalist.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ * for DATALIST.
+ */
+final class CtdDatalist extends ComplexTypeDefinition {
+
+	/**
+	 * @param elementCollection ElementCollection
+	 */
+	public CtdDatalist(ElementCollection elementCollection) {
+		super(elementCollection);
+		primaryCandidateName = HTML40Namespace.ElementName.OPTION;
+	}
+
+	/**
+	 * (OPTION)+.
+	 */
+	protected void createContent() {
+		if (content != null)
+			return; // already created.
+		if (collection == null)
+			return;
+
+	
+		content = new CMGroupImpl(CMGroup.CHOICE, 1, CMContentImpl.UNBOUNDED);
+		// OPTION
+		CMNode dec = collection.getNamedItem(HTML40Namespace.ElementName.OPTION);
+		if (dec != null)
+			content.appendChild(dec);
+	}
+
+	/**
+	 * (OPTION)+.
+	 * @return int; Should be one of ANY, EMPTY, ELEMENT, MIXED, PCDATA, CDATA,
+	 * those are defined in CMElementDeclaration.
+	 */
+	public int getContentType() {
+		return CMElementDeclaration.ELEMENT;
+	}
+
+	/**
+	 * @return java.lang.String
+	 */
+	public String getTypeName() {
+		return ComplexTypeDefinitionFactory.CTYPE_DATALIST;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdDetails.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdDetails.java
new file mode 100644
index 0000000..914d5db
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdDetails.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML50Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+public class CtdDetails extends ComplexTypeDefinition {
+
+	public CtdDetails(ElementCollection elementCollection) {
+		super(elementCollection);
+		primaryCandidateName = HTML50Namespace.ElementName.SUMMARY;
+	}
+
+	protected void createContent() {
+		if (content != null)
+			return; // already created.
+		if (collection == null)
+			return;
+
+		content = new CMGroupImpl(CMGroup.SEQUENCE, 1, 1);
+		// summary
+		CMNode dec = collection.getNamedItem(HTML50Namespace.ElementName.SUMMARY);
+		if (dec != null)
+			content.appendChild(dec);
+
+		CMGroupImpl group = new CMGroupImpl(CMGroup.CHOICE, 1, CMContentImpl.UNBOUNDED);
+		content.appendChild(group);
+		collection.getFlow(group);
+	}
+
+	public int getContentType() {
+		return CMElementDeclaration.ELEMENT;
+	}
+
+	public String getTypeName() {
+		return ComplexTypeDefinitionFactory.CTYPE_DETAILS_CONTAINER;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdDl.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdDl.java
new file mode 100644
index 0000000..626eb8f
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdDl.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ * for DL.
+ */
+final class CtdDl extends ComplexTypeDefinition {
+
+	/**
+	 * @param elementCollection ElementCollection
+	 */
+	public CtdDl(ElementCollection elementCollection) {
+		super(elementCollection);
+		primaryCandidateName = HTML40Namespace.ElementName.DT;
+	}
+
+	/**
+	 * (DT | DD)+
+	 */
+	protected void createContent() {
+		if (content != null)
+			return; // already created.
+		if (collection == null)
+			return;
+
+		// ( | )+
+		content = new CMGroupImpl(CMGroup.CHOICE, 1, CMContentImpl.UNBOUNDED);
+		// DT
+		CMNode dec = collection.getNamedItem(HTML40Namespace.ElementName.DT);
+		if (dec != null)
+			content.appendChild(dec);
+		// DD
+		dec = collection.getNamedItem(HTML40Namespace.ElementName.DD);
+		if (dec != null)
+			content.appendChild(dec);
+	}
+
+	/**
+	 * (DT | DD)+.
+	 * @return int; Should be one of ANY, EMPTY, ELEMENT, MIXED, PCDATA, CDATA,
+	 * those are defined in CMElementDeclaration.
+	 */
+	public int getContentType() {
+		return CMElementDeclaration.ELEMENT;
+	}
+
+	/**
+	 * @return java.lang.String
+	 */
+	public String getTypeName() {
+		return ComplexTypeDefinitionFactory.CTYPE_DEFINITION_LIST;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdEmbed.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdEmbed.java
new file mode 100644
index 0000000..da5e725
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdEmbed.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ * for EMBED.
+ */
+final class CtdEmbed extends ComplexTypeDefinition {
+
+	/**
+	 * @param elementCollection ElementCollection
+	 */
+	public CtdEmbed(ElementCollection elementCollection) {
+		super(elementCollection);
+		primaryCandidateName = HTML40Namespace.ElementName.NOEMBED;
+	}
+
+	/**
+	 * (NOEMBED).
+	 */
+	protected void createContent() {
+		if (content != null)
+			return; // already created.
+		if (collection == null)
+			return;
+
+		// ( )
+		content = new CMGroupImpl(CMGroup.SEQUENCE, 1, 1);
+		// NOEMBED
+		CMNode noembed = collection.getNamedItem(HTML40Namespace.ElementName.NOEMBED);
+		if (noembed != null)
+			content.appendChild(noembed);
+	}
+
+	/**
+	 * (NOEMBED).
+	 * @return int; Should be one of ANY, EMPTY, ELEMENT, MIXED, PCDATA, CDATA,
+	 * those are defined in CMElementDeclaration.
+	 */
+	public int getContentType() {
+		return CMElementDeclaration.ELEMENT;
+	}
+
+	/**
+	 * @return java.lang.String
+	 */
+	public String getTypeName() {
+		return ComplexTypeDefinitionFactory.CTYPE_EMBED;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdFieldset.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdFieldset.java
new file mode 100644
index 0000000..b4f2dfd
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdFieldset.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ * for FIELDSET.
+ */
+final class CtdFieldset extends ComplexTypeDefinition {
+
+	/**
+	 * @param elementCollection ElementCollection
+	 */
+	public CtdFieldset(ElementCollection elementCollection) {
+		super(elementCollection);
+		primaryCandidateName = HTML40Namespace.ElementName.LEGEND;
+	}
+
+	/**
+	 * (#PCDATA, LEGEND, (%flow;)*)
+	 */
+	protected void createContent() {
+		if (content != null)
+			return; // already created.
+		if (collection == null)
+			return;
+
+		// ( , , )
+		content = new CMGroupImpl(CMGroup.SEQUENCE, 1, 1);
+		// #PCDATA
+		// ...??
+
+		// LEGEND
+		CMNode dec = collection.getNamedItem(HTML40Namespace.ElementName.LEGEND);
+		if (dec != null)
+			content.appendChild(dec);
+		// (%flow;)*
+		CMGroupImpl flows = new CMGroupImpl(CMGroup.CHOICE, 0, CMContentImpl.UNBOUNDED);
+		if (flows == null)
+			return;
+		collection.getFlow(flows);
+		content.appendChild(flows);
+	}
+
+	/**
+	 * (#PCDATA, LEGEND, (%flow;)*)
+	 * @return int; Should be one of ANY, EMPTY, ELEMENT, MIXED, PCDATA, CDATA,
+	 * those are defined in CMElementDeclaration.
+	 */
+	public int getContentType() {
+		return CMElementDeclaration.MIXED;
+	}
+
+	/**
+	 * @return java.lang.String
+	 */
+	public String getTypeName() {
+		return ComplexTypeDefinitionFactory.CTYPE_FIELDSET;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdFigure.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdFigure.java
new file mode 100644
index 0000000..165054f
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdFigure.java
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.html.core.internal.provisional.HTML50Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ * for FIGURE.
+ */
+final class CtdFigure extends ComplexTypeDefinition {
+
+	/**
+	 * @param elementCollection ElementCollection
+	 */
+	public CtdFigure(ElementCollection elementCollection) {
+		super(elementCollection);
+		primaryCandidateName = HTML50Namespace.ElementName.FIGCAPTION;
+	}
+
+	/**
+	 * (FIGCAPTION)+.
+	 */
+	protected void createContent() {
+		if (content != null)
+			return; // already created.
+		if (collection == null)
+			return;
+
+		// ( | )+
+		content = new CMGroupImpl(CMGroup.CHOICE, 1, 1);
+		
+		CMGroupImpl group1 = new CMGroupImpl(CMGroup.SEQUENCE, 1, 1);
+		if (group1 != null){
+			content.appendChild(group1);
+		}
+		// FIGCAPTION, FLOW
+		CMNode dec = collection.getNamedItem(HTML50Namespace.ElementName.FIGCAPTION);
+		if (dec != null)
+			group1.appendChild(dec);
+		CMGroupImpl flowgroup = new CMGroupImpl(CMGroup.SEQUENCE, 1, 1);
+		group1.appendChild(flowgroup);
+		collection.getFlow(flowgroup);
+		
+		CMGroupImpl group2 = new CMGroupImpl(CMGroup.SEQUENCE, 1, 1);
+		if (group2 != null){
+			content.appendChild(group2);
+		}
+		// FLOW , FIGCAPTION
+		CMGroupImpl flowgroup2 = new CMGroupImpl(CMGroup.SEQUENCE, 1, 1);
+		group2.appendChild(flowgroup2);
+		collection.getFlow(flowgroup2);
+		CMNode dec1 = collection.getNamedItem(HTML50Namespace.ElementName.FIGCAPTION);
+		if (dec1 != null)
+			group2.appendChild(dec1);
+		//FLOW
+		CMGroupImpl group3 = new CMGroupImpl(CMGroup.SEQUENCE, 1, 1);
+		if (group3 != null){
+			content.appendChild(group3);
+			
+		}
+		collection.getFlow(group3);
+
+	}
+
+	/**
+	 * (FIGCAPTION)+.
+	 * @return int; Should be one of ANY, EMPTY, ELEMENT, MIXED, PCDATA, CDATA,
+	 * those are defined in CMElementDeclaration.
+	 */
+	public int getContentType() {
+		return CMElementDeclaration.ELEMENT;
+	}
+
+	/**
+	 * @return java.lang.String
+	 */
+	public String getTypeName() {
+		return ComplexTypeDefinitionFactory.CTYPE_FIGURE;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdFlowContainer.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdFlowContainer.java
new file mode 100644
index 0000000..6c7a08b
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdFlowContainer.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+
+/**
+ * Complex type definition for containers of <code>%flow;</code>.
+ */
+final class CtdFlowContainer extends ComplexTypeDefinition {
+
+	/**
+	 */
+	public CtdFlowContainer(ElementCollection elementCollection) {
+		super(elementCollection);
+	}
+
+	/**
+	 * (%flow;)*
+	 */
+	protected void createContent() {
+		if (content != null)
+			return; // already created.
+		if (collection == null)
+			return;
+
+		content = new CMGroupImpl(CMGroup.CHOICE, 0, CMContentImpl.UNBOUNDED);
+		collection.getFlow(content);
+	}
+
+	public int getContentType() {
+		return CMElementDeclaration.MIXED;
+	}
+
+	public String getTypeName() {
+		return ComplexTypeDefinitionFactory.CTYPE_FLOW_CONTAINER;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdFrameset.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdFrameset.java
new file mode 100644
index 0000000..03da4b4
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdFrameset.java
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ * for FRAMESET.
+ * ((FRAMESET | FRAME)+ & NOFRAMES?)
+ */
+final class CtdFrameset extends ComplexTypeDefinition {
+
+	/**
+	 * @param elementCollection ElementCollection
+	 */
+	public CtdFrameset(ElementCollection elementCollection) {
+		super(elementCollection);
+		primaryCandidateName = HTML40Namespace.ElementName.FRAME;
+	}
+
+	/**
+	 * ((FRAMESET | FRAME)+ & NOFRAMES?).
+	 * --> ((FRAMESET | FRAME)+ & (NOFRAMES)?)
+	 */
+	protected void createContent() {
+		if (content != null)
+			return; // already created.
+		if (collection == null)
+			return;
+
+		// ( & )
+		content = new CMGroupImpl(CMGroup.ALL, 1, 1);
+
+		// ( | )+
+		CMGroupImpl group = new CMGroupImpl(CMGroup.CHOICE, 1, CMContentImpl.UNBOUNDED);
+		if (group == null)
+			return;
+		content.appendChild(group);
+
+		// FRAMESET
+		CMNode dec = collection.getNamedItem(HTML40Namespace.ElementName.FRAMESET);
+		if (dec != null)
+			group.appendChild(dec);
+		// FRAME
+		dec = collection.getNamedItem(HTML40Namespace.ElementName.FRAME);
+		if (dec != null)
+			group.appendChild(dec);
+
+		// ( )?
+		group = new CMGroupImpl(CMGroup.SEQUENCE, 0, 1);
+		if (group == null)
+			return;
+		content.appendChild(group);
+
+		// NOFRAMES
+		dec = collection.getNamedItem(HTML40Namespace.ElementName.NOFRAMES);
+		if (dec != null)
+			group.appendChild(dec);
+	}
+
+	/**
+	 * ((FRAMESET | FRAME)+ & NOFRAMES?)
+	 * @return int; Should be one of ANY, EMPTY, ELEMENT, MIXED, PCDATA, CDATA,
+	 * those are defined in CMElementDeclaration.
+	 */
+	public int getContentType() {
+		return CMElementDeclaration.ELEMENT;
+	}
+
+	/**
+	 * Name of complex type definition.
+	 * Each singleton must know its own name.
+	 * All names should be defined in
+	 * {@link <code>ComplexTypeDefinitionFactory</code>} as constants.<br>
+	 * @return java.lang.String
+	 */
+	public String getTypeName() {
+		return ComplexTypeDefinitionFactory.CTYPE_FRAMESET;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdHead.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdHead.java
new file mode 100644
index 0000000..48bc24f
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdHead.java
@@ -0,0 +1,175 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.util.Arrays;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ * Complex type definition for the head content.
+ * Content Model: (TITLE & ISINDEX? & BASE?)
+ */
+final class CtdHead extends ComplexTypeDefinition {
+
+	/**
+	 */
+	public CtdHead(ElementCollection elementCollection) {
+		super(elementCollection);
+		primaryCandidateName = HTML40Namespace.ElementName.TITLE;
+	}
+
+	/**
+	 * for HEAD.
+	 * To avoid using inclusion, the content model comes from the XHTML 1.0.
+	 *
+	 * (%head.misc;, ((title, %head.misc;, (base, %head.misc;)?) | (base, %head.misc;, (title, %head.misc;))))
+	 * And %head.misc; is:
+	 * (script|style|meta|link|object|isindex)*
+	 *
+	 * 0: (%head.misc, A)
+	 * A: (B | C)
+	 * B: (title, %head.misc;, D)
+	 * C: (base, %head.misc;, E)
+	 * D: (base, %head.misc;)?
+	 * E: (title, %head.misc;)
+	 */
+	protected void createContent() {
+		if (content != null)
+			return; // already created.
+		if (collection == null)
+			return;
+
+		// At 1st, create %head.misc; content.
+		// %head.misc;
+		//   ( | )*
+		CMGroupImpl misc = new CMGroupImpl(CMGroup.CHOICE, 0, CMContentImpl.UNBOUNDED);
+		if (misc == null)
+			return;
+		String[] names = {HTML40Namespace.ElementName.SCRIPT, HTML40Namespace.ElementName.STYLE, HTML40Namespace.ElementName.META, HTML40Namespace.ElementName.LINK, HTML40Namespace.ElementName.OBJECT, HTML40Namespace.ElementName.ISINDEX};
+		collection.getDeclarations(misc, Arrays.asList(names).iterator());
+		// 2nd, get a title
+		CMNode title = collection.getNamedItem(HTML40Namespace.ElementName.TITLE);
+		// 3rd, get a base
+		CMNode base = collection.getNamedItem(HTML40Namespace.ElementName.BASE);
+		if (title == null || base == null)
+			return;
+
+		// Top level content is a sequence of %head.misc; and A.
+		// 0: (%head.misc;, A)
+		//   create a sequence
+		content = new CMGroupImpl(CMGroup.SEQUENCE, 1, 1);
+		if (content == null)
+			return;
+		//   append %head.misc;
+		content.appendChild(misc);
+		//   create A and append it to the top level.
+		{
+			// A is a choice of B and C.
+			// A: (B | C)
+			//   create a choice
+			CMGroupImpl gA = new CMGroupImpl(CMGroup.CHOICE, 1, 1);
+			if (gA == null)
+				return;
+			//   append A to the top level.
+			content.appendChild(gA);
+
+			// create B and append it to A
+			{
+				// B is a sequence of title, %head.misc;, and D.
+				// B: (title, %head.misc;, D)
+				//   create a sequence
+				CMGroupImpl gB = new CMGroupImpl(CMGroup.SEQUENCE, 1, 1);
+				if (gB == null)
+					return;
+				//   append B to A.
+				gA.appendChild(gB);
+
+				//   append title to B
+				gB.appendChild(title);
+				//   append %head.misc; to B
+				gB.appendChild(misc);
+				//   create D and append it to B.
+				{
+					// D is a sequence of base, %head.misc;.
+					// D: (base, %head.misc;)?
+					//   create a sequence
+					CMGroupImpl gD = new CMGroupImpl(CMGroup.SEQUENCE, 0, 1);
+					if (gD == null)
+						return;
+					//   append D to B.
+					gB.appendChild(gD);
+
+					//   append base to D
+					gD.appendChild(base);
+					//   append %head.misc; to D.
+					gD.appendChild(misc);
+				}
+			}
+			// create C and append it to A
+			{
+				// C is a sequence of base, %head.misc;, and E
+				// C: (base, %head.misc;, E)
+				//   create a sequence
+				CMGroupImpl gC = new CMGroupImpl(CMGroup.SEQUENCE, 1, 1);
+				if (gC == null)
+					return;
+				//   append C to A.
+				gA.appendChild(gC);
+
+				//   append base to C
+				gC.appendChild(base);
+				//   append %head.misc; to C
+				gC.appendChild(misc);
+
+				//   create E and append it to C.
+				{
+					// E is a sequence of title and %head.misc;.
+					// E: (title, %head.misc;)
+					//   create a sequence
+					CMGroupImpl gE = new CMGroupImpl(CMGroup.SEQUENCE, 1, 1);
+					if (gE == null)
+						return;
+					//   append E to C.
+					gC.appendChild(gE);
+
+					//   append title to E
+					gE.appendChild(title);
+					//   append %head.misc; to E.
+					gE.appendChild(misc);
+				}
+			}
+		}
+	}
+
+	/**
+	 * Element content.
+	 */
+	public int getContentType() {
+		return CMElementDeclaration.ELEMENT;
+	}
+
+	/**
+	 * Name of complex type definition.
+	 * Each singleton must know its own name.
+	 * All names should be defined in
+	 * {@link <code>ComplexTypeDefinitionFactory</code>} as constants.<br>
+	 * @return java.lang.String
+	 */
+	public String getTypeName() {
+		return ComplexTypeDefinitionFactory.CTYPE_HEAD;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdHeadingContainer.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdHeadingContainer.java
new file mode 100644
index 0000000..e7fdba7
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdHeadingContainer.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *******************************************************************************/
+
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+
+
+public class CtdHeadingContainer extends ComplexTypeDefinition {
+
+	/**
+	 * @param elementCollection ElementCollection
+	 */
+	public CtdHeadingContainer(ElementCollection elementCollection) {
+		super(elementCollection);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.html.core.internal.contentmodel.ComplexTypeDefinition#createContent()
+	 */
+	protected void createContent() {
+		if (content != null)
+			return; // already created.
+		if (collection == null)
+			return;
+		// ( )*
+		content = new CMGroupImpl(CMGroup.CHOICE, 1, CMContentImpl.UNBOUNDED);
+		// H1|H2|H3|H4|H5|H6
+		 collection.getHeading(content);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.html.core.internal.contentmodel.ComplexTypeDefinition#getContentType()
+	 */
+	public int getContentType() {
+		return CMElementDeclaration.ELEMENT;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.html.core.internal.contentmodel.ComplexTypeDefinition#getTypeName()
+	 */
+	public String getTypeName() {
+		return ComplexTypeDefinitionFactory.CTYPE_HEADING_CONTAINER;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdHtml.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdHtml.java
new file mode 100644
index 0000000..ca7295b
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdHtml.java
@@ -0,0 +1,382 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.util.Arrays;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.html.core.internal.provisional.HTML50Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ * Complex type definition for <code>HTML</code>.<br>
+ * Content Model:
+ * HEAD, (FRAMESET|BODY)<br>
+ */
+final class CtdHtml extends ComplexTypeDefinition {
+
+	/**
+	 */
+	public CtdHtml(ElementCollection elementCollection) {
+		super(elementCollection);
+		primaryCandidateName = HTML40Namespace.ElementName.HEAD;
+	}
+
+	/**
+	 * (%html.content;).
+	 * %html.content; is HEAD, (FRAMESET | BODY).
+	 */
+	protected void createContent() {
+		if (content != null)
+			return; // already created.
+		if (collection == null)
+			return;
+
+		// ( )
+		content = new CMGroupImpl(CMGroup.SEQUENCE, 1, 1);
+		if (content == null)
+			return;
+
+		// HEAD
+		CMNode edec = collection.getNamedItem(HTML40Namespace.ElementName.HEAD);
+		if (edec != null)
+			content.appendChild(edec);
+
+		// ( | )
+		CMGroupImpl group = new CMGroupImpl(CMGroup.CHOICE, 1, 1);
+		content.appendChild(group);
+
+		// FRAMESET, BODY
+		String[] names = {HTML40Namespace.ElementName.FRAMESET, HTML40Namespace.ElementName.BODY};
+		collection.getDeclarations(group, Arrays.asList(names).iterator());
+
+		// since BODY start and end are omissable
+		// adding valid children of BODY here under HTML
+		// https://bugs.eclipse.org/bugs/show_bug.cgi?id=97342
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.MAP);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.PRE);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.BDO);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.INPUT);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.P);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.NOSCRIPT);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.I);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.BUTTON);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.LABEL);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.U);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.H6);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.CENTER);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.BASEFONT);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.S);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.BLOCKQUOTE);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.H3);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.UL);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.B);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.SELECT);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.Q);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.STRIKE);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.SCRIPT);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.ABBR);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.BIG);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.H1);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.IMG);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.ACRONYM);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.DEL);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.NOFRAMES);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.TEXTAREA);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.H2);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.FONT);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.OBJECT);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.KBD);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.IFRAME);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.HR);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.H4);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.DIR);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.SAMP);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.INS);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.H5);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.SUP);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.A);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.DFN);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.ISINDEX);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.DL);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.VAR);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.FIELDSET);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.TABLE);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.BR);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.TT);
+		if (edec != null)
+			content.appendChild(edec);
+
+		edec = collection.getNamedItem(HTML40Namespace.ElementName.APPLET);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.OL);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.SMALL);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.CITE);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.FORM);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.DIV);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.CODE);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.SPAN);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.SUB);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.EM);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.MENU);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.ADDRESS);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML40Namespace.ElementName.STRONG);
+		if (edec != null)
+			content.appendChild(edec);
+		edec = collection.getNamedItem(HTML50Namespace.ElementName.ARTICLE);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML50Namespace.ElementName.ASIDE);
+		if (edec != null)
+			content.appendChild(edec);
+		edec = collection.getNamedItem(HTML50Namespace.ElementName.NAV);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML50Namespace.ElementName.SECTION);
+		if (edec != null)
+			content.appendChild(edec);
+		edec = collection.getNamedItem(HTML50Namespace.ElementName.AUDIO);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML50Namespace.ElementName.VIDEO);
+		if (edec != null)
+			content.appendChild(edec);
+		edec = collection.getNamedItem(HTML50Namespace.ElementName.CANVAS);
+		if (edec != null)
+			content.appendChild(edec);
+
+	    edec = collection.getNamedItem(HTML50Namespace.ElementName.COMMAND);
+		if (edec != null)
+			content.appendChild(edec);
+		
+	    edec = collection.getNamedItem(HTML50Namespace.ElementName.HEADER);
+		if (edec != null)
+			content.appendChild(edec);
+		
+	    edec = collection.getNamedItem(HTML50Namespace.ElementName.FOOTER);
+		if (edec != null)
+			content.appendChild(edec);
+		
+	    edec = collection.getNamedItem(HTML50Namespace.ElementName.MARK);
+		if (edec != null)
+			content.appendChild(edec);
+		
+		edec = collection.getNamedItem(HTML50Namespace.ElementName.FIGURE);
+		if (edec != null)
+			content.appendChild(edec);
+		edec = collection.getNamedItem(HTML50Namespace.ElementName.RUBY);
+		if (edec != null)
+			content.appendChild(edec);
+	}
+
+	/**
+	 * Element content.
+	 */
+	public int getContentType() {
+		return CMElementDeclaration.ELEMENT;
+	}
+
+	public String getTypeName() {
+		return ComplexTypeDefinitionFactory.CTYPE_HTML;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdInlineContainer.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdInlineContainer.java
new file mode 100644
index 0000000..7fbfeab
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdInlineContainer.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+
+/**
+ * Complex type definition for (%inline;)*.
+ */
+final class CtdInlineContainer extends ComplexTypeDefinition {
+
+	/**
+	 * @param elementCollection ElementCollection
+	 */
+	public CtdInlineContainer(ElementCollection elementCollection) {
+		super(elementCollection);
+	}
+
+	/**
+	 * (%inline)*.
+	 */
+	protected void createContent() {
+		if (content != null)
+			return; // already created.
+		if (collection == null)
+			return;
+
+		content = new CMGroupImpl(CMGroup.CHOICE, 0, CMContentImpl.UNBOUNDED);
+		collection.getInline(content);
+	}
+
+	public int getContentType() {
+		return CMElementDeclaration.MIXED;
+	}
+
+	public String getTypeName() {
+		return ComplexTypeDefinitionFactory.CTYPE_INLINE_CONTAINER;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdLiContainer.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdLiContainer.java
new file mode 100644
index 0000000..5ccb079
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdLiContainer.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ * List item container.
+ * (LI)+
+ */
+final class CtdLiContainer extends ComplexTypeDefinition {
+
+	/**
+	 * @param elemenCollection ElementCollection
+	 */
+	public CtdLiContainer(ElementCollection elementCollection) {
+		super(elementCollection);
+		primaryCandidateName = HTML40Namespace.ElementName.LI;
+	}
+
+	/**
+	 * (LI)+.
+	 */
+	protected void createContent() {
+		if (content != null)
+			return; // already created.
+		if (collection == null)
+			return;
+
+		// (LI)+
+		content = new CMGroupImpl(CMGroup.SEQUENCE, 1, CMContentImpl.UNBOUNDED);
+		CMNode li = collection.getNamedItem(HTML40Namespace.ElementName.LI);
+		if (li != null)
+			content.appendChild(li);
+	}
+
+	/**
+	 * ELEMENT content.<br>
+	 * @return int; Should be one of ANY, EMPTY, ELEMENT, MIXED, PCDATA, CDATA,
+	 * those are defined in CMElementDeclaration.
+	 */
+	public int getContentType() {
+		return CMElementDeclaration.ELEMENT;
+	}
+
+	/**
+	 * Name of complex type definition.
+	 * Each singleton must know its own name.
+	 * All names should be defined in
+	 * {@link <code>ComplexTypeDefinitionFactory</code>} as constants.<br>
+	 * @return java.lang.String
+	 */
+	public String getTypeName() {
+		return ComplexTypeDefinitionFactory.CTYPE_LI_CONTAINER;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdMap.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdMap.java
new file mode 100644
index 0000000..3ff2a16
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdMap.java
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ * for MAP.
+ */
+final class CtdMap extends ComplexTypeDefinition {
+
+	/**
+	 * @param elementCollection ElementCollection
+	 */
+	public CtdMap(ElementCollection elementCollection) {
+		super(elementCollection);
+		primaryCandidateName = HTML40Namespace.ElementName.AREA;
+	}
+
+	/**
+	 * ((%block;) | AREA)+.
+	 */
+	protected void createContent() {
+		if (content != null)
+			return; // already created.
+		if (collection == null)
+			return;
+
+		// ( | )+
+		content = new CMGroupImpl(CMGroup.CHOICE, 1, CMContentImpl.UNBOUNDED);
+		// (%block;)
+		CMGroupImpl blocks = new CMGroupImpl(CMGroup.CHOICE, 1, 1);
+		if (blocks == null)
+			return;
+		collection.getBlock(blocks);
+		content.appendChild(blocks);
+		// AREA
+		CMNode area = collection.getNamedItem(HTML40Namespace.ElementName.AREA);
+		if (area != null)
+			content.appendChild(area);
+	}
+
+	/**
+	 * ((%block;) | AREA)+.
+	 * Because %block; consists of elements only, the type is ELEMENT.
+	 * @return int; Should be one of ANY, EMPTY, ELEMENT, MIXED, PCDATA, CDATA,
+	 * those are defined in CMElementDeclaration.
+	 */
+	public int getContentType() {
+		return CMElementDeclaration.ELEMENT;
+	}
+
+	/**
+	 * @return java.lang.String
+	 */
+	public String getTypeName() {
+		return ComplexTypeDefinitionFactory.CTYPE_MAP;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdMediaElement.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdMediaElement.java
new file mode 100644
index 0000000..95cb598
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdMediaElement.java
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML50Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+
+public class CtdMediaElement extends ComplexTypeDefinition {
+
+	/**
+	 * @param elementCollection ElementCollection
+	 */
+	public CtdMediaElement(ElementCollection elementCollection) {
+		super(elementCollection);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.html.core.internal.contentmodel.ComplexTypeDefinition#createContent()
+	 */
+	protected void createContent() {
+		if (content != null)
+			return; // already created.
+		if (collection == null)
+			return;
+		// ( )*
+		content = new CMGroupImpl(CMGroup.SEQUENCE,0, 1);
+		//source
+		CMNode source = collection.getNamedItem(HTML50Namespace.ElementName.SOURCE);
+		if (source != null)
+			content.appendChild(source);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.html.core.internal.contentmodel.ComplexTypeDefinition#getContentType()
+	 */
+	public int getContentType() {
+		return CMElementDeclaration.ELEMENT;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.html.core.internal.contentmodel.ComplexTypeDefinition#getTypeName()
+	 */
+	public String getTypeName() {
+		return ComplexTypeDefinitionFactory.CTYPE_MEDIA_ELEMENT;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdNoframesContent.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdNoframesContent.java
new file mode 100644
index 0000000..d193a6c
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdNoframesContent.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ * for NOFRAMES.
+ */
+final class CtdNoframesContent extends ComplexTypeDefinition {
+
+	/**
+	 * @param elementCollection ElementCollection
+	 */
+	public CtdNoframesContent(ElementCollection elementCollection) {
+		super(elementCollection);
+		primaryCandidateName = HTML40Namespace.ElementName.BODY;
+	}
+
+	/**
+	 * (BODY).
+	 */
+	protected void createContent() {
+		if (content != null)
+			return; // already created.
+		if (collection == null)
+			return;
+
+		// ( )
+		content = new CMGroupImpl(CMGroup.SEQUENCE, 1, 1);
+		// BODY
+		CMNode dec = collection.getNamedItem(HTML40Namespace.ElementName.BODY);
+		if (dec != null)
+			content.appendChild(dec);
+	}
+
+	/**
+	 * (BODY)
+	 * @return int; Should be one of ANY, EMPTY, ELEMENT, MIXED, PCDATA, CDATA,
+	 * those are defined in CMElementDeclaration.
+	 */
+	public int getContentType() {
+		return CMElementDeclaration.ELEMENT;
+	}
+
+	/**
+	 * @return java.lang.String
+	 */
+	public String getTypeName() {
+		return ComplexTypeDefinitionFactory.CTYPE_NOFRAMES_CONTENT;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdOptionContainer.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdOptionContainer.java
new file mode 100644
index 0000000..b53480a
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdOptionContainer.java
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ * OPTION container.
+ * (OPTION)+
+ */
+final class CtdOptionContainer extends ComplexTypeDefinition {
+
+	/**
+	 * @param elementCollection ElementCollection
+	 */
+	public CtdOptionContainer(ElementCollection elementCollection) {
+		super(elementCollection);
+		primaryCandidateName = HTML40Namespace.ElementName.OPTION;
+	}
+
+	/**
+	 * (OPTION)+.
+	 */
+	protected void createContent() {
+		if (content != null)
+			return; // already created.
+		if (collection == null)
+			return;
+
+		// ( )+
+		content = new CMGroupImpl(CMGroup.SEQUENCE, 1, CMContentImpl.UNBOUNDED);
+		// OPTION
+		CMNode dec = collection.getNamedItem(HTML40Namespace.ElementName.OPTION);
+		if (dec != null)
+			content.appendChild(dec);
+	}
+
+	/**
+	 * (OPTION)+
+	 * @return int; Should be one of ANY, EMPTY, ELEMENT, MIXED, PCDATA, CDATA,
+	 * those are defined in CMElementDeclaration.
+	 */
+	public int getContentType() {
+		return CMElementDeclaration.ELEMENT;
+	}
+
+	/**
+	 * Name of complex type definition.
+	 * Each singleton must know its own name.
+	 * All names should be defined in
+	 * {@link <code>ComplexTypeDefinitionFactory</code>} as constants.<br>
+	 * @return java.lang.String
+	 */
+	public String getTypeName() {
+		return ComplexTypeDefinitionFactory.CTYPE_OPTION_CONTAINER;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdParamContainer.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdParamContainer.java
new file mode 100644
index 0000000..4eb45b4
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdParamContainer.java
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ * PARAM container.  For OBJECT and APPLET.
+ */
+final class CtdParamContainer extends ComplexTypeDefinition {
+
+	/**
+	 * @param elementCollection ElementCollection
+	 */
+	public CtdParamContainer(ElementCollection elementCollection) {
+		super(elementCollection);
+	}
+
+	/**
+	 * (PARAM | %flow;)*.
+	 */
+	protected void createContent() {
+		if (content != null)
+			return; // already created.
+		if (collection == null)
+			return;
+
+		// ( | )*
+		content = new CMGroupImpl(CMGroup.CHOICE, 0, CMContentImpl.UNBOUNDED);
+		// PARAM
+		CMNode param = collection.getNamedItem(HTML40Namespace.ElementName.PARAM);
+		if (param != null)
+			content.appendChild(param);
+		// %flow;
+		CMGroupImpl flows = new CMGroupImpl(CMGroup.CHOICE, 1, 1);
+		if (flows == null)
+			return;
+		collection.getInline(flows);
+		collection.getBlock(flows);
+		content.appendChild(flows);
+	}
+
+	/**
+	 * (PARAM | %flow;)*.
+	 * Because %flow; contains #PCDATA, the type is MIXED.
+	 * @return int; Should be one of ANY, EMPTY, ELEMENT, MIXED, PCDATA, CDATA,
+	 * those are defined in CMElementDeclaration.
+	 */
+	public int getContentType() {
+		return CMElementDeclaration.MIXED;
+	}
+
+	/**
+	 * @return java.lang.String
+	 */
+	public String getTypeName() {
+		return ComplexTypeDefinitionFactory.CTYPE_PARAM_CONTAINER;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdRuby.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdRuby.java
new file mode 100644
index 0000000..9ec37d0
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdRuby.java
@@ -0,0 +1,94 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.html.core.internal.provisional.HTML50Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ * for RUBY.
+ */
+final class CtdRuby extends ComplexTypeDefinition {
+
+	/**
+	 * @param elementCollection ElementCollection
+	 */
+	public CtdRuby(ElementCollection elementCollection) {
+		super(elementCollection);
+		primaryCandidateName = HTML50Namespace.ElementName.RT;
+	}
+
+	/**
+	 * (RT)+.
+	 */
+	protected void createContent() {
+		if (content != null)
+			return; // already created.
+		if (collection == null)
+			return;
+
+	
+		content = new CMGroupImpl(CMGroup.SEQUENCE, 1, CMContentImpl.UNBOUNDED);
+		
+		CMGroupImpl phraseGroup = new CMGroupImpl(CMGroup.CHOICE, 0, CMContentImpl.UNBOUNDED);
+		if (phraseGroup == null)
+			return;
+		content.appendChild(phraseGroup);
+		collection.getPhrase(phraseGroup);
+		
+		CMGroupImpl rtrpgroup = new CMGroupImpl(CMGroup.CHOICE, 1, 1);
+		if (rtrpgroup == null)
+			return;
+		content.appendChild(rtrpgroup);
+		
+		//RT
+		CMNode dec = collection.getNamedItem(HTML50Namespace.ElementName.RT);
+		if (dec != null)
+			rtrpgroup.appendChild(dec);
+		
+		CMGroupImpl rpgroup = new CMGroupImpl(CMGroup.SEQUENCE, 1, 1);
+		if (rpgroup == null)
+			return;
+		rtrpgroup.appendChild(rpgroup);
+		
+		// RP
+		dec = collection.getNamedItem(HTML50Namespace.ElementName.RP);
+		if (dec != null)
+			rpgroup.appendChild(dec);
+		// RT
+		dec = collection.getNamedItem(HTML50Namespace.ElementName.RT);
+		if (dec != null)
+			rpgroup.appendChild(dec);
+		dec = collection.getNamedItem(HTML50Namespace.ElementName.RP);
+		if (dec != null)
+			rpgroup.appendChild(dec);
+	}
+
+	/**
+	 * (RT)+.
+	 * @return int; Should be one of ANY, EMPTY, ELEMENT, MIXED, PCDATA, CDATA,
+	 * those are defined in CMElementDeclaration.
+	 */
+	public int getContentType() {
+		return CMElementDeclaration.ELEMENT;
+	}
+
+	/**
+	 * @return java.lang.String
+	 */
+	public String getTypeName() {
+		return ComplexTypeDefinitionFactory.CTYPE_RUBY;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdSelect.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdSelect.java
new file mode 100644
index 0000000..b1d1284
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdSelect.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ * for SELECT.
+ */
+final class CtdSelect extends ComplexTypeDefinition {
+
+	/**
+	 * @param elementCollection ElementCollection
+	 */
+	public CtdSelect(ElementCollection elementCollection) {
+		super(elementCollection);
+		primaryCandidateName = HTML40Namespace.ElementName.OPTION;
+	}
+
+	/**
+	 * (OPTGROUP | OPTION)+.
+	 */
+	protected void createContent() {
+		if (content != null)
+			return; // already created.
+		if (collection == null)
+			return;
+
+		// ( | )+
+		content = new CMGroupImpl(CMGroup.CHOICE, 1, CMContentImpl.UNBOUNDED);
+		// OPTGROUP
+		CMNode dec = collection.getNamedItem(HTML40Namespace.ElementName.OPTGROUP);
+		if (dec != null)
+			content.appendChild(dec);
+		// OPTION
+		dec = collection.getNamedItem(HTML40Namespace.ElementName.OPTION);
+		if (dec != null)
+			content.appendChild(dec);
+	}
+
+	/**
+	 * (OPTGROUP | OPTION)+.
+	 * @return int; Should be one of ANY, EMPTY, ELEMENT, MIXED, PCDATA, CDATA,
+	 * those are defined in CMElementDeclaration.
+	 */
+	public int getContentType() {
+		return CMElementDeclaration.ELEMENT;
+	}
+
+	/**
+	 * @return java.lang.String
+	 */
+	public String getTypeName() {
+		return ComplexTypeDefinitionFactory.CTYPE_SELECT;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdTable.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdTable.java
new file mode 100644
index 0000000..7fd73d5
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdTable.java
@@ -0,0 +1,140 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ * for TABLE.
+ * (CAPTION?, (COL*|COLGROUP*), THEAD?, TFOOT?, TBODY+, TR+)
+ */
+final class CtdTable extends ComplexTypeDefinition {
+
+	/**
+	 * @param elementCollection ElementCollection
+	 */
+	public CtdTable(ElementCollection elementCollection) {
+		super(elementCollection);
+		primaryCandidateName = HTML40Namespace.ElementName.TBODY;
+	}
+
+	/**
+	 * (CAPTION?, (COL*|COLGROUP*), THEAD?, TFOOT?, TBODY+)
+	 * --> ((CAPTION)?, ((COL)* | (COLGROUP)*), (THEAD)?, (TFOOT)?, (TBODY)+, (TR)+)
+	 */
+	protected void createContent() {
+		if (content != null)
+			return; // already created.
+		if (collection == null)
+			return;
+
+		// ( , , , ,)
+		content = new CMGroupImpl(CMGroup.SEQUENCE, 1, 1);
+
+		// (CAPTION)?
+		//     ( )?
+		CMGroupImpl wrap = new CMGroupImpl(CMGroup.SEQUENCE, 0, 1);
+		if (wrap == null)
+			return;
+		content.appendChild(wrap);
+		//     CAPTION
+		CMNode dec = collection.getNamedItem(HTML40Namespace.ElementName.CAPTION);
+		if (dec != null)
+			wrap.appendChild(dec);
+
+		// ((COL)* | (COLGROUP)*)
+		//     ( | )
+		CMGroupImpl group = new CMGroupImpl(CMGroup.CHOICE, 1, 1);
+		if (group == null)
+			return;
+		content.appendChild(group);
+		//         (COL)*
+		wrap = new CMGroupImpl(CMGroup.SEQUENCE, 0, CMContentImpl.UNBOUNDED);
+		if (wrap == null)
+			return;
+		group.appendChild(wrap);
+		dec = collection.getNamedItem(HTML40Namespace.ElementName.COL);
+		if (dec != null)
+			wrap.appendChild(dec);
+		//         (COLGROUP)*
+		wrap = new CMGroupImpl(CMGroup.SEQUENCE, 0, CMContentImpl.UNBOUNDED);
+		if (wrap == null)
+			return;
+		group.appendChild(wrap);
+		dec = collection.getNamedItem(HTML40Namespace.ElementName.COLGROUP);
+		if (dec != null)
+			wrap.appendChild(dec);
+
+		// (THEAD)?
+		wrap = new CMGroupImpl(CMGroup.SEQUENCE, 0, 1);
+		if (wrap == null)
+			return;
+		content.appendChild(wrap);
+		dec = collection.getNamedItem(HTML40Namespace.ElementName.THEAD);
+		if (dec != null)
+			wrap.appendChild(dec);
+
+		// (TFOOT)?
+		wrap = new CMGroupImpl(CMGroup.SEQUENCE, 0, 1);
+		if (wrap == null)
+			return;
+		content.appendChild(wrap);
+		dec = collection.getNamedItem(HTML40Namespace.ElementName.TFOOT);
+		if (dec != null)
+			wrap.appendChild(dec);
+
+		// (TBODY)+
+		// TBODY has optional start and end tags
+		wrap = new CMGroupImpl(CMGroup.SEQUENCE, 0, CMContentImpl.UNBOUNDED);
+		if (wrap == null)
+			return;
+		content.appendChild(wrap);
+		dec = collection.getNamedItem(HTML40Namespace.ElementName.TBODY);
+		if (dec != null)
+			wrap.appendChild(dec);
+
+		// https://bugs.eclipse.org/bugs/show_bug.cgi?id=96101
+		// TBODY start and end tag are optional, so TR should be allowed here
+		// (TR)+
+		wrap = new CMGroupImpl(CMGroup.SEQUENCE, 1, CMContentImpl.UNBOUNDED);
+		if (wrap == null)
+			return;
+		content.appendChild(wrap);
+		dec = collection.getNamedItem(HTML40Namespace.ElementName.TR);
+		if (dec != null)
+			wrap.appendChild(dec);
+	}
+
+	/**
+	 * ((FRAMESET | FRAME)+ & NOFRAMES?)
+	 * @return int; Should be one of ANY, EMPTY, ELEMENT, MIXED, PCDATA, CDATA,
+	 * those are defined in CMElementDeclaration.
+	 */
+	public int getContentType() {
+		return CMElementDeclaration.ELEMENT;
+	}
+
+	/**
+	 * Name of complex type definition.
+	 * Each singleton must know its own name.
+	 * All names should be defined in
+	 * {@link <code>ComplexTypeDefinitionFactory</code>} as constants.<br>
+	 * @return java.lang.String
+	 */
+	public String getTypeName() {
+		return ComplexTypeDefinitionFactory.CTYPE_TABLE;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdTableCellContainer.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdTableCellContainer.java
new file mode 100644
index 0000000..a207876
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdTableCellContainer.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ * Table cell container.
+ * (TH | TD)+
+ */
+final class CtdTableCellContainer extends ComplexTypeDefinition {
+
+	/**
+	 * @param elementCollection ElementCollection
+	 */
+	public CtdTableCellContainer(ElementCollection elementCollection) {
+		super(elementCollection);
+		primaryCandidateName = HTML40Namespace.ElementName.TD;
+	}
+
+	/**
+	 * (TH | TD)+.
+	 */
+	protected void createContent() {
+		if (content != null)
+			return; // already created.
+		if (collection == null)
+			return;
+
+		// ( )+
+		content = new CMGroupImpl(CMGroup.CHOICE, 1, CMContentImpl.UNBOUNDED);
+		// TH
+		CMNode dec = collection.getNamedItem(HTML40Namespace.ElementName.TH);
+		if (dec != null)
+			content.appendChild(dec);
+		// TD
+		dec = collection.getNamedItem(HTML40Namespace.ElementName.TD);
+		if (dec != null)
+			content.appendChild(dec);
+	}
+
+	/**
+	 * (TH | TD)+
+	 * @return int; Should be one of ANY, EMPTY, ELEMENT, MIXED, PCDATA, CDATA,
+	 * those are defined in CMElementDeclaration.
+	 */
+	public int getContentType() {
+		return CMElementDeclaration.ELEMENT;
+	}
+
+	/**
+	 * Name of complex type definition.
+	 * Each singleton must know its own name.
+	 * All names should be defined in
+	 * {@link <code>ComplexTypeDefinitionFactory</code>} as constants.<br>
+	 * @return java.lang.String
+	 */
+	public String getTypeName() {
+		return ComplexTypeDefinitionFactory.CTYPE_TCELL_CONTAINER;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdTrContainer.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdTrContainer.java
new file mode 100644
index 0000000..734c204
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/CtdTrContainer.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ * Table record container.
+ * (TR)+
+ */
+final class CtdTrContainer extends ComplexTypeDefinition {
+
+	/**
+	 * @param elementCollection ElementCollection
+	 */
+	public CtdTrContainer(ElementCollection elementCollection) {
+		super(elementCollection);
+		primaryCandidateName = HTML40Namespace.ElementName.TR;
+	}
+
+	/**
+	 * (TR)+.
+	 */
+	protected void createContent() {
+		if (content != null)
+			return; // already created.
+		if (collection == null)
+			return;
+
+		// (TR)+
+		content = new CMGroupImpl(CMGroup.SEQUENCE, 1, CMContentImpl.UNBOUNDED);
+		CMNode tr = collection.getNamedItem(HTML40Namespace.ElementName.TR);
+		if (tr != null)
+			content.appendChild(tr);
+	}
+
+	/**
+	 * ELEMENT content.<br>
+	 * @return int; Should be one of ANY, EMPTY, ELEMENT, MIXED, PCDATA, CDATA,
+	 * those are defined in CMElementDeclaration.
+	 */
+	public int getContentType() {
+		return CMElementDeclaration.ELEMENT;
+	}
+
+	/**
+	 * Name of complex type definition.
+	 * Each singleton must know its own name.
+	 * All names should be defined in
+	 * {@link <code>ComplexTypeDefinitionFactory</code>} as constants.<br>
+	 * @return java.lang.String
+	 */
+	public String getTypeName() {
+		return ComplexTypeDefinitionFactory.CTYPE_TR_CONTAINER;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/DeclCollection.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/DeclCollection.java
new file mode 100644
index 0000000..d5aab54
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/DeclCollection.java
@@ -0,0 +1,244 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Locale;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ */
+abstract class DeclCollection implements CMNamedNodeMap {
+
+
+	protected class DualMap {
+		public DualMap() {
+			super();
+		}
+
+		public DualMap(Object[] objects) {
+			super();
+			initialize(objects);
+		}
+
+		public int size() {
+			return table.length;
+		}
+
+		public Object getValue(int key) {
+			if (!isValidIndex(key))
+				return null;
+			return table[key];
+		}
+
+		public int getKey(Object value) {
+			Integer keyObj = (Integer) map.get(value);
+			if (keyObj == null)
+				return ID_UNKNOWN;
+			return keyObj.intValue();
+		}
+
+		protected void initialize(Object[] objects) {
+			if (objects == null)
+				return;
+			table = objects;
+			map = new HashMap();
+			for (int key = 0; key < objects.length; key++) {
+				Object value = table[key];
+				map.put(value, new Integer(key));
+			}
+		}
+
+		private Object[] table = null;
+		private HashMap map = null;
+
+		private boolean isValidIndex(int index) {
+			return index >= 0 && index < table.length;
+		}
+	}
+
+	protected class TolerantStringDualMap extends DualMap {
+		public TolerantStringDualMap(String[] names) {
+			super();
+			Object[] objects = new Object[names.length];
+			for (int i = 0; i < names.length; i++) {
+				objects[i] = makeCanonicalForm(names[i]);
+			}
+			initialize(objects);
+		}
+
+		public int getKey(Object value) {
+			try {
+				String name = (String) value;
+				return super.getKey(makeCanonicalForm(name));
+			}
+			catch (ClassCastException e) {
+				return ID_UNKNOWN;
+			}
+		}
+
+		private String makeCanonicalForm(String raw) {
+			// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=100152
+			// we are able to "cheat" here a little and use US Locale 
+			// to get a good cononical form, since we are using this only 
+			// for HTML and JSP standard tags. 
+			// Long term, for similar needs with XML 1.1 (for example)
+			// we should use a class such as com.ibm.icu.text.Normalizer
+			return raw.toUpperCase(Locale.US);
+		}
+	}
+
+	private class DeclIterator implements Iterator {
+		public DeclIterator() {
+			maxid = fDecls.length - 1;
+		}
+
+		public boolean hasNext() {
+			return id < maxid;
+		}
+
+		public Object next() {
+			if (!hasNext())
+				return null;
+			return item(++id);
+		}
+
+		public void remove() { /* nothing should be done. */
+		}
+
+		private int id = -1;
+		private int maxid = -1;
+	}
+
+	CMNode[] fDecls = null;
+	protected final static boolean STRICT_CASE = false;
+	protected final static boolean TOLERANT_CASE = true;
+	protected final static int ID_UNKNOWN = -1;
+	private DualMap fMap = null;
+
+	/**
+	 */
+	public DeclCollection(String[] names, boolean tolerant) {
+		super();
+		fDecls = new CMNode[names.length];
+		if (tolerant) {
+			fMap = new TolerantStringDualMap(names);
+		}
+		else {
+			fMap = new DualMap(names);
+		}
+	}
+
+	/**
+	 * @return org.eclipse.wst.xml.core.internal.contentmodel.CMNode
+	 * @param id int
+	 */
+	protected abstract CMNode create(String name);
+
+	/**
+	 */
+	public CMNamedNodeMap getDeclarations(String[] names) {
+		CMNamedNodeMapImpl map = new CMNamedNodeMapImpl();
+		for (int i = 0; i < names.length; i++) {
+			String name = names[i];
+			CMNode node = getNamedItem(name);
+			if (node == null)
+				continue;
+			map.putNamedItem(name, node);
+		}
+		return map;
+	}
+
+	/**
+	 * @param names java.util.Iterator
+	 */
+	public void getDeclarations(CMGroupImpl group, Iterator names) {
+		while (names.hasNext()) {
+			String entityName = (String) names.next();
+			CMNode dec = getNamedItem(entityName);
+			if (dec != null)
+				group.appendChild(dec);
+		}
+	}
+
+	/**
+	 * Map name to id.
+	 * @return int
+	 * @param name java.lang.String
+	 */
+	protected int getID(String name) {
+		return fMap.getKey(name);
+	}
+
+	/**
+	 * getLength method
+	 * @return int
+	 */
+	public int getLength() {
+		return fDecls.length;
+	}
+
+	/**
+	 * @return java.lang.String
+	 * @param id int
+	 */
+	protected String getName(int id) {
+		return (String) fMap.getValue(id);
+	}
+
+	/**
+	 * getNamedItem method
+	 * @return CMNode
+	 * @param name java.lang.String
+	 */
+	public CMNode getNamedItem(String name) {
+		int id = getID(name);
+		if (!isValidID(id))
+			return null;
+		return item(id);
+	}
+
+	/**
+	 * @return boolean
+	 * @param id int
+	 */
+	private boolean isValidID(int id) {
+		return id >= 0 && id < fDecls.length;
+	}
+
+	/**
+	 * item method
+	 * @return CMNode
+	 * @param index int
+	 */
+	public CMNode item(int index) {
+		if (!isValidID(index))
+			return null;
+		CMNode decl = fDecls[index];
+		if (decl != null)
+			return decl; // already exist.
+
+		decl = create(getName(index));
+		fDecls[index] = decl;
+		return decl;
+	}
+
+	/**
+	 */
+	public Iterator iterator() {
+		return new DeclIterator();
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/ElementCollection.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/ElementCollection.java
new file mode 100644
index 0000000..92ddfdf
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/ElementCollection.java
@@ -0,0 +1,889 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.lang.reflect.Field;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Vector;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ * Factory for element declarations.
+ */
+class ElementCollection extends DeclCollection implements org.eclipse.wst.html.core.internal.provisional.HTML40Namespace.ElementName {
+
+
+	// Element IDs
+	protected static class Ids {
+		public static final int ID_A = 0;
+		public static final int ID_ABBR = 1;
+		public static final int ID_ACRONYM = 2;
+		public static final int ID_ADDRESS = 3;
+		public static final int ID_APPLET = 4;
+		public static final int ID_AREA = 5;
+		public static final int ID_B = 6;
+		public static final int ID_BASE = 7;
+		public static final int ID_BASEFONT = 8;
+		public static final int ID_BDO = 9;
+		public static final int ID_BIG = 10;
+		public static final int ID_BLINK = 11;
+		public static final int ID_BLOCKQUOTE = 12;
+		public static final int ID_BODY = 13;
+		public static final int ID_BR = 14;
+		public static final int ID_BUTTON = 15;
+		public static final int ID_CAPTION = 16;
+		public static final int ID_CENTER = 17;
+		public static final int ID_CITE = 18;
+		public static final int ID_CODE = 19;
+		public static final int ID_COL = 20;
+		public static final int ID_COLGROUP = 21;
+		public static final int ID_DD = 22;
+		public static final int ID_DEL = 23;
+		public static final int ID_DFN = 24;
+		public static final int ID_DIR = 25;
+		public static final int ID_DIV = 26;
+		public static final int ID_DL = 27;
+		public static final int ID_DT = 28;
+		public static final int ID_EM = 29;
+		public static final int ID_EMBED = 30;
+		public static final int ID_FIELDSET = 31;
+		public static final int ID_FONT = 32;
+		public static final int ID_FORM = 33;
+		public static final int ID_FRAME = 34;
+		public static final int ID_FRAMESET = 35;
+		public static final int ID_H1 = 36;
+		public static final int ID_H2 = 37;
+		public static final int ID_H3 = 38;
+		public static final int ID_H4 = 39;
+		public static final int ID_H5 = 40;
+		public static final int ID_H6 = 41;
+		public static final int ID_HEAD = 42;
+		public static final int ID_HR = 43;
+		public static final int ID_HTML = 44;
+		public static final int ID_I = 45;
+		public static final int ID_IFRAME = 46;
+		public static final int ID_IMG = 47;
+		public static final int ID_INPUT = 48;
+		public static final int ID_INS = 49;
+		public static final int ID_ISINDEX = 50;
+		public static final int ID_KBD = 51;
+		public static final int ID_LABEL = 52;
+		public static final int ID_LEGEND = 53;
+		public static final int ID_LI = 54;
+		public static final int ID_LINK = 55;
+		public static final int ID_MAP = 56;
+		public static final int ID_MENU = 57;
+		public static final int ID_META = 58;
+		public static final int ID_NOEMBED = 59;
+		public static final int ID_NOFRAMES = 60;
+		public static final int ID_NOSCRIPT = 61;
+		public static final int ID_OBJECT = 62;
+		public static final int ID_OL = 63;
+		public static final int ID_OPTGROUP = 64;
+		public static final int ID_OPTION = 65;
+		public static final int ID_P = 66;
+		public static final int ID_PARAM = 67;
+		public static final int ID_PRE = 68;
+		public static final int ID_Q = 69;
+		public static final int ID_S = 70;
+		public static final int ID_SAMP = 71;
+		public static final int ID_SCRIPT = 72;
+		public static final int ID_SELECT = 73;
+		public static final int ID_SMALL = 74;
+		public static final int ID_SPAN = 75;
+		public static final int ID_STRIKE = 76;
+		public static final int ID_STRONG = 77;
+		public static final int ID_STYLE = 78;
+		public static final int ID_SUB = 79;
+		public static final int ID_SUP = 80;
+		public static final int ID_TABLE = 81;
+		public static final int ID_TBODY = 82;
+		public static final int ID_TD = 83;
+		public static final int ID_TEXTAREA = 84;
+		public static final int ID_TFOOT = 85;
+		public static final int ID_TH = 86;
+		public static final int ID_THEAD = 87;
+		public static final int ID_TITLE = 88;
+		public static final int ID_TR = 89;
+		public static final int ID_TT = 90;
+		public static final int ID_U = 91;
+		public static final int ID_UL = 92;
+		public static final int ID_VAR = 93;
+		public static final int ID_MARQUEE = 94;
+		public static final int ID_SSI_CONFIG = 95;
+		public static final int ID_SSI_ECHO = 96;
+		public static final int ID_SSI_EXEC = 97;
+		public static final int ID_SSI_FSIZE = 98;
+		public static final int ID_SSI_FLASTMOD = 99;
+		public static final int ID_SSI_INCLUDE = 100;
+		public static final int ID_SSI_PRINTENV = 101;
+		public static final int ID_SSI_SET = 102;
+		// <<D205513
+		public static final int ID_BGSOUND = 103;
+		public static final int ID_NOBR = 104;
+		public static final int ID_WBR = 105;
+
+		// D205513
+
+		public static int getNumOfIds() {
+			if (numofids != -1)
+				return numofids;
+
+			// NOTE: If the reflection is too slow, this method should
+			// just return the literal value, like 105.
+			// -- 5/25/2001
+			Class clazz = Ids.class;
+			Field[] fields = clazz.getFields();
+			numofids = 0;
+			for (int i = 0; i < fields.length; i++) {
+				String name = fields[i].getName();
+				if (name.startsWith("ID_"))//$NON-NLS-1$
+					numofids++;
+			}
+			return numofids;
+		}
+
+		// chache the result of the reflection.
+		private static int numofids = -1;
+	}
+
+	/** %fontstyle;. TT | I | B | U | S | STRIKE | BIG | SMALL | BLINK */
+	private static final String[] FONTSTYLE = {TT, I, B, U, S, STRIKE, BIG, SMALL, BLINK};
+	/** %formctl;. INPUT | SELECT | TEXTAREA | LABEL | BUTTON */
+	private static final String[] FORMCTL = {INPUT, SELECT, TEXTAREA, LABEL, BUTTON};
+	/** %phrase;.
+	 * EM | STRONG | DFN | CODE | SAMP | KBD | VAR | CITE | ABBR | ACRONYM
+	 */
+	private static final String[] PHRASE = {EM, STRONG, DFN, CODE, SAMP, KBD, VAR, CITE, ABBR, ACRONYM};
+	/** %special;.
+	 * A | IMG | APPLET | OBJECT | FONT | BASEFONT | BR | SCRIPT |
+	 * MAP | Q | SUB | SUP | SPAN | BDO | IFRAME | EMBED | MARQUEE |
+	 * D2W | SUBMIT
+	 * WBR | NOBR | BGSOUND
+	 */
+	private static final String[] SPECIAL = {A, IMG, APPLET, OBJECT, FONT, BASEFONT, BR, WBR, // D205513
+				SCRIPT, MAP, Q, SUB, SUP, SPAN, BDO, IFRAME, EMBED, BGSOUND, // D205513
+				MARQUEE, NOBR // D205513
+	};
+	/** %heading;. H[1-6] */
+	private static final String[] HEADING = {H1, H2, H3, H4, H5, H6};
+	/** %list;. UL | OL | DIR | MENU */
+	private static final String[] LIST = {UL, OL, DIR, MENU};
+	/** %preformatted;. PRE */
+	private static final String[] PREFORMATTED = {PRE};
+	protected AttributeCollection attributeCollection = null;
+	private static String[] fNames = null;
+
+	/**
+	 */
+	public ElementCollection(AttributeCollection collection) {
+		super(getNames(), TOLERANT_CASE);
+		attributeCollection = collection;
+	}
+
+	public ElementCollection(String[] names, AttributeCollection collection) {
+		super(names, TOLERANT_CASE);
+		attributeCollection = collection;
+	}
+
+	/**
+	 * Actually creates HTMLElementDeclaration instance.
+	 * @return HTMLElementDeclaration
+	 */
+	protected CMNode create(String elementName) {
+		HTMLElemDeclImpl edec = null;
+
+		if (elementName.equalsIgnoreCase(A)) {
+			edec = new HedA(this);
+		}
+		else if (elementName.equalsIgnoreCase(ABBR)) {
+			edec = new HedPhrase(ABBR, this);
+
+		}
+		else if (elementName.equalsIgnoreCase(ACRONYM)) {
+			edec = new HedPhrase(ACRONYM, this);
+
+		}
+		else if (elementName.equalsIgnoreCase(ADDRESS)) {
+			edec = new HedADDRESS(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(APPLET)) {
+			edec = new HedAPPLET(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(AREA)) {
+			edec = new HedAREA(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(B)) {
+			edec = new HedFontStyle(B, this);
+
+		}
+		else if (elementName.equalsIgnoreCase(BASE)) {
+			edec = new HedBASE(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(BASEFONT)) {
+			edec = new HedBASEFONT(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(BDO)) {
+			edec = new HedBDO(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(BIG)) {
+			edec = new HedFontStyle(BIG, this);
+
+		}
+		else if (elementName.equalsIgnoreCase(BLINK)) {
+			edec = new HedFontStyle(BLINK, this);
+
+		}
+		else if (elementName.equalsIgnoreCase(BLOCKQUOTE)) {
+			edec = new HedBLOCKQUOTE(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(BODY)) {
+			edec = new HedBODY(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(BR)) {
+			edec = new HedBR(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(BUTTON)) {
+			edec = new HedBUTTON(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(CAPTION)) {
+			edec = new HedCAPTION(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(CENTER)) {
+			edec = new HedCENTER(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(CITE)) {
+			edec = new HedPhrase(CITE, this);
+
+		}
+		else if (elementName.equalsIgnoreCase(CODE)) {
+			edec = new HedPhrase(CODE, this);
+
+		}
+		else if (elementName.equalsIgnoreCase(COL)) {
+			edec = new HedCOL(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(COLGROUP)) {
+			edec = new HedCOLGROUP(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(DD)) {
+			edec = new HedDD(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(DEL)) {
+			edec = new HedMarkChanges(DEL, this);
+
+		}
+		else if (elementName.equalsIgnoreCase(DFN)) {
+			edec = new HedPhrase(DFN, this);
+
+		}
+		else if (elementName.equalsIgnoreCase(DIR)) {
+			edec = new HedMENU(DIR, this);
+
+		}
+		else if (elementName.equalsIgnoreCase(DIV)) {
+			edec = new HedDIV(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(DL)) {
+			edec = new HedDL(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(DT)) {
+			edec = new HedDT(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(EM)) {
+			edec = new HedPhrase(EM, this);
+
+		}
+		else if (elementName.equalsIgnoreCase(EMBED)) {
+			edec = new HedEMBED(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(FIELDSET)) {
+			edec = new HedFIELDSET(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(FONT)) {
+			edec = new HedFONT(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(FORM)) {
+			edec = new HedFORM(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(FRAME)) {
+			edec = new HedFRAME(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(FRAMESET)) {
+			edec = new HedFRAMESET(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(H1)) {
+			edec = new HedHeading(H1, this);
+
+		}
+		else if (elementName.equalsIgnoreCase(H2)) {
+			edec = new HedHeading(H2, this);
+
+		}
+		else if (elementName.equalsIgnoreCase(H3)) {
+			edec = new HedHeading(H3, this);
+
+		}
+		else if (elementName.equalsIgnoreCase(H4)) {
+			edec = new HedHeading(H4, this);
+
+		}
+		else if (elementName.equalsIgnoreCase(H5)) {
+			edec = new HedHeading(H5, this);
+
+		}
+		else if (elementName.equalsIgnoreCase(H6)) {
+			edec = new HedHeading(H6, this);
+
+		}
+		else if (elementName.equalsIgnoreCase(HEAD)) {
+			edec = new HedHEAD(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(HR)) {
+			edec = new HedHR(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(HTML)) {
+			edec = new HedHTML(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(I)) {
+			edec = new HedFontStyle(I, this);
+
+		}
+		else if (elementName.equalsIgnoreCase(IFRAME)) {
+			edec = new HedIFRAME(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(IMG)) {
+			edec = new HedIMG(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(INPUT)) {
+			edec = new HedINPUT(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(INS)) {
+			edec = new HedMarkChanges(INS, this);
+
+		}
+		else if (elementName.equalsIgnoreCase(ISINDEX)) {
+			edec = new HedISINDEX(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(KBD)) {
+			edec = new HedPhrase(KBD, this);
+
+		}
+		else if (elementName.equalsIgnoreCase(LABEL)) {
+			edec = new HedLABEL(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(LEGEND)) {
+			edec = new HedLEGEND(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(LI)) {
+			edec = new HedLI(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(LINK)) {
+			edec = new HedLINK(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(MAP)) {
+			edec = new HedMAP(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(MARQUEE)) {
+			edec = new HedMARQUEE(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(MENU)) {
+			edec = new HedMENU(MENU, this);
+
+		}
+		else if (elementName.equalsIgnoreCase(META)) {
+			edec = new HedMETA(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(NOEMBED)) {
+			edec = new HedNOEMBED(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(NOFRAMES)) {
+			edec = new HedNOFRAMES(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(NOSCRIPT)) {
+			edec = new HedNOSCRIPT(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(OBJECT)) {
+			edec = new HedOBJECT(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(OL)) {
+			edec = new HedOL(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(OPTGROUP)) {
+			edec = new HedOPTGROUP(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(OPTION)) {
+			edec = new HedOPTION(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(P)) {
+			edec = new HedP(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(PARAM)) {
+			edec = new HedPARAM(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(PRE)) {
+			edec = new HedPRE(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(Q)) {
+			edec = new HedQ(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(S)) {
+			edec = new HedFontStyle(S, this);
+
+		}
+		else if (elementName.equalsIgnoreCase(SAMP)) {
+			edec = new HedPhrase(SAMP, this);
+
+		}
+		else if (elementName.equalsIgnoreCase(SCRIPT)) {
+			edec = new HedSCRIPT(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(SELECT)) {
+			edec = new HedSELECT(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(SMALL)) {
+			edec = new HedFontStyle(SMALL, this);
+
+		}
+		else if (elementName.equalsIgnoreCase(SPAN)) {
+			edec = new HedSPAN(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(STRIKE)) {
+			edec = new HedFontStyle(STRIKE, this);
+
+		}
+		else if (elementName.equalsIgnoreCase(STRONG)) {
+			edec = new HedPhrase(STRONG, this);
+
+		}
+		else if (elementName.equalsIgnoreCase(STYLE)) {
+			edec = new HedSTYLE(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(SUB)) {
+			edec = new HedScripts(SUB, this);
+
+		}
+		else if (elementName.equalsIgnoreCase(SUP)) {
+			edec = new HedScripts(SUP, this);
+
+		}
+		else if (elementName.equalsIgnoreCase(TABLE)) {
+			edec = new HedTABLE(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(TBODY)) {
+			edec = new HedTableBody(TBODY, this);
+
+		}
+		else if (elementName.equalsIgnoreCase(TD)) {
+			edec = new HedTableCell(TD, this);
+
+		}
+		else if (elementName.equalsIgnoreCase(TEXTAREA)) {
+			edec = new HedTEXTAREA(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(TFOOT)) {
+			edec = new HedTableBody(TFOOT, this);
+
+		}
+		else if (elementName.equalsIgnoreCase(TH)) {
+			edec = new HedTableCell(TH, this);
+
+		}
+		else if (elementName.equalsIgnoreCase(THEAD)) {
+			edec = new HedTableBody(THEAD, this);
+
+		}
+		else if (elementName.equalsIgnoreCase(TITLE)) {
+			edec = new HedTITLE(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(TR)) {
+			edec = new HedTR(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(TT)) {
+			edec = new HedFontStyle(TT, this);
+
+		}
+		else if (elementName.equalsIgnoreCase(U)) {
+			edec = new HedFontStyle(U, this);
+
+		}
+		else if (elementName.equalsIgnoreCase(UL)) {
+			edec = new HedUL(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(VAR)) {
+			edec = new HedPhrase(VAR, this);
+
+		}
+		else if (elementName.equalsIgnoreCase(SSI_CONFIG)) {
+			edec = new HedSSIConfig(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(SSI_ECHO)) {
+			edec = new HedSSIEcho(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(SSI_EXEC)) {
+			edec = new HedSSIExec(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(SSI_FSIZE)) {
+			edec = new HedSSIFsize(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(SSI_FLASTMOD)) {
+			edec = new HedSSIFlastmod(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(SSI_INCLUDE)) {
+			edec = new HedSSIInclude(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(SSI_PRINTENV)) {
+			edec = new HedSSIPrintenv(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(SSI_SET)) {
+			edec = new HedSSISet(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(BGSOUND)) {
+			edec = new HedBGSOUND(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(NOBR)) {
+			edec = new HedNOBR(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(WBR)) {
+			edec = new HedWBR(this);
+
+		} // unknown
+		else {
+			// NOTE: We don't define the UNKNOWN element declaration.
+			// <code>null</code> for a declaration is a sign of
+			// the target element is unknown.
+			// -- 3/9/2001
+			edec = null;
+		}
+		return edec;
+	}
+
+	public AttributeCollection getAttributeCollection() {
+		return attributeCollection;
+	}
+
+	public Collection getNamesOfBlock() {
+		// P, DL, DIV, CENTER, NOSCRIPT, NOFRAMES, BLOCKQUOTE, FORM, ISINDEX, HR,
+		// TABLE, FIELDSET, ADDRESS
+		String[] blockMisc = {P, DL, DIV, CENTER, NOSCRIPT, NOFRAMES, BLOCKQUOTE, FORM, ISINDEX, HR, TABLE, FIELDSET, ADDRESS};
+		Vector names = new Vector(Arrays.asList(blockMisc));
+		// %heading;
+		names.addAll(Arrays.asList(HEADING));
+		// %list;
+		names.addAll(Arrays.asList(LIST));
+		// %preformatted;
+		names.addAll(Arrays.asList(PREFORMATTED));
+
+		return names;
+	}
+
+	/**
+	 * %block;.
+	 * %block; is:
+	 * P | %heading; | %list; | %preformatted; | DL | DIV | CENTER |
+	 * NOSCRIPT | NOFRAMES | BLOCKQUOTE | FORM | ISINDEX | HR |
+	 * TABLE | FIELDSET | ADDRESS.<br>
+	 * @param group CMGroupImpl Return values.
+	 */
+	public final void getBlock(CMGroupImpl group) {
+		if (group == null)
+			return;
+		getDeclarations(group, getNamesOfBlock().iterator());
+	}
+
+	/**
+	 * Create element declarations and store them
+	 * into a <code>CMGroupImpl</code> instance.
+	 * @param group CMGroupImpl Return values.
+	 */
+	public void getFlow(CMGroupImpl group) {
+		if (group == null)
+			return;
+		getBlock(group);
+		getInline(group);
+	}
+
+	/**
+	 * Create element declarations and store them into a <code>CMGroupImpl</code>
+	 * instance.<br>
+	 * @param group CMGroupImpl Return values.
+	 */
+	public void getFontstyle(CMGroupImpl group) {
+		if (group == null)
+			return;
+		getDeclarations(group, Arrays.asList(FONTSTYLE).iterator());
+	}
+
+	/**
+	 * Create element declarations and store them into a <code>CMGroupImpl</code>
+	 * instance.<br>
+	 * @param group CMGroupImpl Return values.
+	 */
+	public void getFormctrl(CMGroupImpl group) {
+		if (group == null)
+			return;
+		getDeclarations(group, Arrays.asList(FORMCTL).iterator());
+	}
+
+	/**
+	 * %heading;.
+	 * @param group CMGroupImpl Return values.
+	 */
+	public void getHeading(CMGroupImpl group) {
+		if (group == null)
+			return;
+
+		getDeclarations(group, Arrays.asList(HEADING).iterator());
+	}
+
+	/**
+	 * Create element declarations and store them
+	 * into a <code>CMGroupImpl</code> instance.
+	 * @param group CMGroupImpl Return values.
+	 */
+	public void getInline(CMGroupImpl group) {
+		if (group == null)
+			return;
+		getFontstyle(group);
+		getPhrase(group);
+		getSpecial(group);
+		getFormctrl(group);
+	}
+
+	/**
+	 * %list;.
+	 * @param group CMGroupImpl Return values.
+	 */
+	public void getList(CMGroupImpl group) {
+		if (group == null)
+			return;
+
+		getDeclarations(group, Arrays.asList(LIST).iterator());
+	}
+
+	/**
+	 * Create element declarations and store them into a <code>CMGroupImpl</code>
+	 * instance.<br>
+	 * @param group CMGroupImpl Return values.
+	 */
+	public void getPhrase(CMGroupImpl group) {
+		if (group == null)
+			return;
+		getDeclarations(group, Arrays.asList(PHRASE).iterator());
+	}
+
+	/**
+	 * %preformatted;
+	 * @param group CMGroupImpl Return values.
+	 */
+	public void getPreformatted(CMGroupImpl group) {
+		if (group == null)
+			return;
+
+		getDeclarations(group, Arrays.asList(PREFORMATTED).iterator());
+	}
+
+	/**
+	 * Create element declarations and store them into a <code>CMGroupImpl</code>
+	 * instance.<br>
+	 * @param group CMGroupImpl Return values.
+	 */
+	public void getSpecial(CMGroupImpl group) {
+		if (group == null)
+			return;
+		getDeclarations(group, Arrays.asList(SPECIAL).iterator());
+	}
+
+	private static String[] getNames() {
+		if (fNames == null) {
+			fNames = new String[Ids.getNumOfIds()];
+			fNames[Ids.ID_A] = A;
+			fNames[Ids.ID_ABBR] = ABBR;
+			fNames[Ids.ID_ACRONYM] = ACRONYM;
+			fNames[Ids.ID_ADDRESS] = ADDRESS;
+			fNames[Ids.ID_APPLET] = APPLET;
+			fNames[Ids.ID_AREA] = AREA;
+			fNames[Ids.ID_B] = B;
+			fNames[Ids.ID_BASE] = BASE;
+			fNames[Ids.ID_BASEFONT] = BASEFONT;
+			fNames[Ids.ID_BDO] = BDO;
+			fNames[Ids.ID_BIG] = BIG;
+			fNames[Ids.ID_BLINK] = BLINK;
+			fNames[Ids.ID_BLOCKQUOTE] = BLOCKQUOTE;
+			fNames[Ids.ID_BODY] = BODY;
+			fNames[Ids.ID_BR] = BR;
+			fNames[Ids.ID_BUTTON] = BUTTON;
+			fNames[Ids.ID_CAPTION] = CAPTION;
+			fNames[Ids.ID_CENTER] = CENTER;
+			fNames[Ids.ID_CITE] = CITE;
+			fNames[Ids.ID_CODE] = CODE;
+			fNames[Ids.ID_COL] = COL;
+			fNames[Ids.ID_COLGROUP] = COLGROUP;
+			fNames[Ids.ID_DD] = DD;
+			fNames[Ids.ID_DEL] = DEL;
+			fNames[Ids.ID_DFN] = DFN;
+			fNames[Ids.ID_DIR] = DIR;
+			fNames[Ids.ID_DIV] = DIV;
+			fNames[Ids.ID_DL] = DL;
+			fNames[Ids.ID_DT] = DT;
+			fNames[Ids.ID_EM] = EM;
+			fNames[Ids.ID_EMBED] = EMBED;
+			fNames[Ids.ID_FIELDSET] = FIELDSET;
+			fNames[Ids.ID_FONT] = FONT;
+			fNames[Ids.ID_FORM] = FORM;
+			fNames[Ids.ID_FRAME] = FRAME;
+			fNames[Ids.ID_FRAMESET] = FRAMESET;
+			fNames[Ids.ID_H1] = H1;
+			fNames[Ids.ID_H2] = H2;
+			fNames[Ids.ID_H3] = H3;
+			fNames[Ids.ID_H4] = H4;
+			fNames[Ids.ID_H5] = H5;
+			fNames[Ids.ID_H6] = H6;
+			fNames[Ids.ID_HEAD] = HEAD;
+			fNames[Ids.ID_HR] = HR;
+			fNames[Ids.ID_HTML] = HTML;
+			fNames[Ids.ID_I] = I;
+			fNames[Ids.ID_IFRAME] = IFRAME;
+			fNames[Ids.ID_IMG] = IMG;
+			fNames[Ids.ID_INPUT] = INPUT;
+			fNames[Ids.ID_INS] = INS;
+			fNames[Ids.ID_ISINDEX] = ISINDEX;
+			fNames[Ids.ID_KBD] = KBD;
+			fNames[Ids.ID_LABEL] = LABEL;
+			fNames[Ids.ID_LEGEND] = LEGEND;
+			fNames[Ids.ID_LI] = LI;
+			fNames[Ids.ID_LINK] = LINK;
+			fNames[Ids.ID_MAP] = MAP;
+			fNames[Ids.ID_MENU] = MENU;
+			fNames[Ids.ID_META] = META;
+			fNames[Ids.ID_NOEMBED] = NOEMBED;
+			fNames[Ids.ID_NOFRAMES] = NOFRAMES;
+			fNames[Ids.ID_NOSCRIPT] = NOSCRIPT;
+			fNames[Ids.ID_OBJECT] = OBJECT;
+			fNames[Ids.ID_OL] = OL;
+			fNames[Ids.ID_OPTGROUP] = OPTGROUP;
+			fNames[Ids.ID_OPTION] = OPTION;
+			fNames[Ids.ID_P] = P;
+			fNames[Ids.ID_PARAM] = PARAM;
+			fNames[Ids.ID_PRE] = PRE;
+			fNames[Ids.ID_Q] = Q;
+			fNames[Ids.ID_S] = S;
+			fNames[Ids.ID_SAMP] = SAMP;
+			fNames[Ids.ID_SCRIPT] = SCRIPT;
+			fNames[Ids.ID_SELECT] = SELECT;
+			fNames[Ids.ID_SMALL] = SMALL;
+			fNames[Ids.ID_SPAN] = SPAN;
+			fNames[Ids.ID_STRIKE] = STRIKE;
+			fNames[Ids.ID_STRONG] = STRONG;
+			fNames[Ids.ID_STYLE] = STYLE;
+			fNames[Ids.ID_SUB] = SUB;
+			fNames[Ids.ID_SUP] = SUP;
+			fNames[Ids.ID_TABLE] = TABLE;
+			fNames[Ids.ID_TBODY] = TBODY;
+			fNames[Ids.ID_TD] = TD;
+			fNames[Ids.ID_TEXTAREA] = TEXTAREA;
+			fNames[Ids.ID_TFOOT] = TFOOT;
+			fNames[Ids.ID_TH] = TH;
+			fNames[Ids.ID_THEAD] = THEAD;
+			fNames[Ids.ID_TITLE] = TITLE;
+			fNames[Ids.ID_TR] = TR;
+			fNames[Ids.ID_TT] = TT;
+			fNames[Ids.ID_U] = U;
+			fNames[Ids.ID_UL] = UL;
+			fNames[Ids.ID_VAR] = VAR;
+			fNames[Ids.ID_MARQUEE] = MARQUEE;
+			fNames[Ids.ID_SSI_CONFIG] = SSI_CONFIG;
+			fNames[Ids.ID_SSI_ECHO] = SSI_ECHO;
+			fNames[Ids.ID_SSI_EXEC] = SSI_EXEC;
+			fNames[Ids.ID_SSI_FSIZE] = SSI_FSIZE;
+			fNames[Ids.ID_SSI_FLASTMOD] = SSI_FLASTMOD;
+			fNames[Ids.ID_SSI_INCLUDE] = SSI_INCLUDE;
+			fNames[Ids.ID_SSI_PRINTENV] = SSI_PRINTENV;
+			fNames[Ids.ID_SSI_SET] = SSI_SET;
+			fNames[Ids.ID_BGSOUND] = BGSOUND;
+			fNames[Ids.ID_NOBR] = NOBR;
+			fNames[Ids.ID_WBR] = WBR;
+		}
+		return fNames;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/EntityCollection.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/EntityCollection.java
new file mode 100644
index 0000000..dda7041
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/EntityCollection.java
@@ -0,0 +1,837 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.lang.reflect.Field;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ * Factory for entity declarations.
+ */
+final class EntityCollection extends DeclCollection implements org.eclipse.wst.html.core.internal.provisional.HTML40Namespace.EntityName {
+
+
+	private static class Ids {
+		public static final int ID_AACUTE_L = 0;
+		public static final int ID_AACUTE_U = 1;
+		public static final int ID_ACIRC_L = 2;
+		public static final int ID_ACIRC_U = 3;
+		public static final int ID_ACUTE = 4;
+		public static final int ID_AELIG_L = 5;
+		public static final int ID_AELIG_U = 6;
+		public static final int ID_AGRAVE_L = 7;
+		public static final int ID_AGRAVE_U = 8;
+		public static final int ID_ALEFSYM = 9;
+		public static final int ID_ALPHA_L = 10;
+		public static final int ID_ALPHA_U = 11;
+		public static final int ID_AMP = 12;
+		public static final int ID_AND = 13;
+		public static final int ID_ANG = 14;
+		public static final int ID_ARING_L = 15;
+		public static final int ID_ARING_U = 16;
+		public static final int ID_ASYMP = 17;
+		public static final int ID_ATILDE_L = 18;
+		public static final int ID_ATILDE_U = 19;
+		public static final int ID_AUML_L = 20;
+		public static final int ID_AUML_U = 21;
+		public static final int ID_BDQUO = 22;
+		public static final int ID_BETA_L = 23;
+		public static final int ID_BETA_U = 24;
+		public static final int ID_BRVBAR = 25;
+		public static final int ID_BULL = 26;
+		public static final int ID_CAP = 27;
+		public static final int ID_CCEDIL_L = 28;
+		public static final int ID_CCEDIL_U = 29;
+		public static final int ID_CEDIL = 30;
+		public static final int ID_CENT = 31;
+		public static final int ID_CHI_L = 32;
+		public static final int ID_CHI_U = 33;
+		public static final int ID_CIRC = 34;
+		public static final int ID_CLUBS = 35;
+		public static final int ID_CONG = 36;
+		public static final int ID_COPY = 37;
+		public static final int ID_CRARR = 38;
+		public static final int ID_CUP = 39;
+		public static final int ID_CURREN = 40;
+		public static final int ID_DAGGER_L = 41;
+		public static final int ID_DAGGER_U = 42;
+		public static final int ID_DARR_L = 43;
+		public static final int ID_DARR_U = 44;
+		public static final int ID_DEG = 45;
+		public static final int ID_DELTA_L = 46;
+		public static final int ID_DELTA_U = 47;
+		public static final int ID_DIAMS = 48;
+		public static final int ID_DIVIDE = 49;
+		public static final int ID_EACUTE_L = 50;
+		public static final int ID_EACUTE_U = 51;
+		public static final int ID_ECIRC_L = 52;
+		public static final int ID_ECIRC_U = 53;
+		public static final int ID_EGRAVE_L = 54;
+		public static final int ID_EGRAVE_U = 55;
+		public static final int ID_EMPTY = 56;
+		public static final int ID_EMSP = 57;
+		public static final int ID_ENSP = 58;
+		public static final int ID_EPSILON_L = 59;
+		public static final int ID_EPSILON_U = 60;
+		public static final int ID_EQUIV = 61;
+		public static final int ID_ETA_L = 62;
+		public static final int ID_ETA_U = 63;
+		public static final int ID_ETH_L = 64;
+		public static final int ID_ETH_U = 65;
+		public static final int ID_EUML_L = 66;
+		public static final int ID_EUML_U = 67;
+		public static final int ID_EURO = 68;
+		public static final int ID_EXIST = 69;
+		public static final int ID_FNOF = 70;
+		public static final int ID_FORALL = 71;
+		public static final int ID_FRAC12 = 72;
+		public static final int ID_FRAC14 = 73;
+		public static final int ID_FRAC34 = 74;
+		public static final int ID_FRASL = 75;
+		public static final int ID_GAMMA_L = 76;
+		public static final int ID_GAMMA_U = 77;
+		public static final int ID_GE = 78;
+		public static final int ID_GT = 79;
+		public static final int ID_HARR_L = 80;
+		public static final int ID_HARR_U = 81;
+		public static final int ID_HEARTS = 82;
+		public static final int ID_HELLIP = 83;
+		public static final int ID_IACUTE_L = 84;
+		public static final int ID_IACUTE_U = 85;
+		public static final int ID_ICIRC_L = 86;
+		public static final int ID_ICIRC_U = 87;
+		public static final int ID_IEXCL = 88;
+		public static final int ID_IGRAVE_L = 89;
+		public static final int ID_IGRAVE_U = 90;
+		public static final int ID_IMAGE = 91;
+		public static final int ID_INFIN = 92;
+		public static final int ID_INT = 93;
+		public static final int ID_IOTA_L = 94;
+		public static final int ID_IOTA_U = 95;
+		public static final int ID_IQUEST = 96;
+		public static final int ID_ISIN = 97;
+		public static final int ID_IUML_L = 98;
+		public static final int ID_IUML_U = 99;
+		public static final int ID_KAPPA_L = 100;
+		public static final int ID_KAPPA_U = 101;
+		public static final int ID_LAMBDA_L = 102;
+		public static final int ID_LAMBDA_U = 103;
+		public static final int ID_LANG = 104;
+		public static final int ID_LAQUO = 105;
+		public static final int ID_LARR_L = 106;
+		public static final int ID_LARR_U = 107;
+		public static final int ID_LCEIL = 108;
+		public static final int ID_LDQUO = 109;
+		public static final int ID_LE = 110;
+		public static final int ID_LFLOOR = 111;
+		public static final int ID_LOWAST = 112;
+		public static final int ID_LOZ = 113;
+		public static final int ID_LRM = 114;
+		public static final int ID_LSAQUO = 115;
+		public static final int ID_LSQUO = 116;
+		public static final int ID_LT = 117;
+		public static final int ID_MACR = 118;
+		public static final int ID_MDASH = 119;
+		public static final int ID_MICRO = 120;
+		public static final int ID_MIDDOT = 121;
+		public static final int ID_MINUS = 122;
+		public static final int ID_MU_L = 123;
+		public static final int ID_MU_U = 124;
+		public static final int ID_NABLA = 125;
+		public static final int ID_NBSP = 126;
+		public static final int ID_NDASH = 127;
+		public static final int ID_NE = 128;
+		public static final int ID_NI = 129;
+		public static final int ID_NOT = 130;
+		public static final int ID_NOTIN = 131;
+		public static final int ID_NSUB = 132;
+		public static final int ID_NTILDE_L = 133;
+		public static final int ID_NTILDE_U = 134;
+		public static final int ID_NU_L = 135;
+		public static final int ID_NU_U = 136;
+		public static final int ID_OACUTE_L = 137;
+		public static final int ID_OACUTE_U = 138;
+		public static final int ID_OCIRC_L = 139;
+		public static final int ID_OCIRC_U = 140;
+		public static final int ID_OELIG_L = 141;
+		public static final int ID_OELIG_U = 142;
+		public static final int ID_OGRAVE_L = 143;
+		public static final int ID_OGRAVE_U = 144;
+		public static final int ID_OLINE = 145;
+		public static final int ID_OMEGA_L = 146;
+		public static final int ID_OMEGA_U = 147;
+		public static final int ID_OMICRON_L = 148;
+		public static final int ID_OMICRON_U = 149;
+		public static final int ID_OPLUS = 150;
+		public static final int ID_OR = 151;
+		public static final int ID_ORDF = 152;
+		public static final int ID_ORDM = 153;
+		public static final int ID_OSLASH_L = 154;
+		public static final int ID_OSLASH_U = 155;
+		public static final int ID_OTILDE_L = 156;
+		public static final int ID_OTILDE_U = 157;
+		public static final int ID_OTIMES = 158;
+		public static final int ID_OUML_L = 159;
+		public static final int ID_OUML_U = 160;
+		public static final int ID_PARA = 161;
+		public static final int ID_PART = 162;
+		public static final int ID_PERMIL = 163;
+		public static final int ID_PERP = 164;
+		public static final int ID_PHI_L = 165;
+		public static final int ID_PHI_U = 166;
+		public static final int ID_PIV = 167;
+		public static final int ID_PI_L = 168;
+		public static final int ID_PI_U = 169;
+		public static final int ID_PLUSMN = 170;
+		public static final int ID_POUND = 171;
+		public static final int ID_PRIME_L = 172;
+		public static final int ID_PRIME_U = 173;
+		public static final int ID_PROD = 174;
+		public static final int ID_PROP = 175;
+		public static final int ID_PSI_L = 176;
+		public static final int ID_PSI_U = 177;
+		public static final int ID_QUOT = 178;
+		public static final int ID_RADIC = 179;
+		public static final int ID_RANG = 180;
+		public static final int ID_RAQUO = 181;
+		public static final int ID_RARR_L = 182;
+		public static final int ID_RARR_U = 183;
+		public static final int ID_RCEIL = 184;
+		public static final int ID_RDQUO = 185;
+		public static final int ID_REAL = 186;
+		public static final int ID_REG = 187;
+		public static final int ID_RFLOOR = 188;
+		public static final int ID_RHO_L = 189;
+		public static final int ID_RHO_U = 190;
+		public static final int ID_RLM = 191;
+		public static final int ID_RSAQUO = 192;
+		public static final int ID_RSQUO = 193;
+		public static final int ID_SBQUO = 194;
+		public static final int ID_SCARON_L = 195;
+		public static final int ID_SCARON_U = 196;
+		public static final int ID_SDOT = 197;
+		public static final int ID_SECT = 198;
+		public static final int ID_SHY = 199;
+		public static final int ID_SIGMAF = 200;
+		public static final int ID_SIGMA_L = 201;
+		public static final int ID_SIGMA_U = 202;
+		public static final int ID_SIM = 203;
+		public static final int ID_SPADES = 204;
+		public static final int ID_SUB = 205;
+		public static final int ID_SUBE = 206;
+		public static final int ID_SUM = 207;
+		public static final int ID_SUP = 208;
+		public static final int ID_SUP1 = 209;
+		public static final int ID_SUP2 = 210;
+		public static final int ID_SUP3 = 211;
+		public static final int ID_SUPE = 212;
+		public static final int ID_SZLIG = 213;
+		public static final int ID_TAU_L = 214;
+		public static final int ID_TAU_U = 215;
+		public static final int ID_THERE4 = 216;
+		public static final int ID_THETASYM = 217;
+		public static final int ID_THETA_L = 218;
+		public static final int ID_THETA_U = 219;
+		public static final int ID_THINSP = 220;
+		public static final int ID_THORN_L = 221;
+		public static final int ID_THORN_U = 222;
+		public static final int ID_TILDE = 223;
+		public static final int ID_TIMES = 224;
+		public static final int ID_TRADE = 225;
+		public static final int ID_UACUTE_L = 226;
+		public static final int ID_UACUTE_U = 227;
+		public static final int ID_UARR_L = 228;
+		public static final int ID_UARR_U = 229;
+		public static final int ID_UCIRC_L = 230;
+		public static final int ID_UCIRC_U = 231;
+		public static final int ID_UGRAVE_L = 232;
+		public static final int ID_UGRAVE_U = 233;
+		public static final int ID_UML = 234;
+		public static final int ID_UPSIH = 235;
+		public static final int ID_UPSILON_L = 236;
+		public static final int ID_UPSILON_U = 237;
+		public static final int ID_UUML_L = 238;
+		public static final int ID_UUML_U = 239;
+		public static final int ID_WEIERP = 240;
+		public static final int ID_XI_L = 241;
+		public static final int ID_XI_U = 242;
+		public static final int ID_YACUTE_L = 243;
+		public static final int ID_YACUTE_U = 244;
+		public static final int ID_YEN = 245;
+		public static final int ID_YUML_L = 246;
+		public static final int ID_YUML_U = 247;
+		public static final int ID_ZETA_L = 248;
+		public static final int ID_ZETA_U = 249;
+		public static final int ID_ZWJ = 250;
+		public static final int ID_ZWNJ = 251;
+
+		public static int getNumOfIds() {
+			if (numofids != -1)
+				return numofids;
+
+			// NOTE: If the reflection is too slow, this method should
+			// just return the literal value, like 252.
+			// -- 5/24/2001
+			Class clazz = Ids.class;
+			Field[] fields = clazz.getFields();
+			numofids = 0;
+			for (int i = 0; i < fields.length; i++) {
+				String name = fields[i].getName();
+				if (name.startsWith("ID_"))//$NON-NLS-1$
+					numofids++;
+			}
+			return numofids;
+		}
+
+		// chache the result of the reflection.
+		private static int numofids = -1;
+	}
+
+	private static String[] names = null;
+
+	static {
+		names = new String[Ids.getNumOfIds()];
+		names[Ids.ID_AACUTE_L] = AACUTE_L;
+		names[Ids.ID_AACUTE_U] = AACUTE_U;
+		names[Ids.ID_ACIRC_L] = ACIRC_L;
+		names[Ids.ID_ACIRC_U] = ACIRC_U;
+		names[Ids.ID_ACUTE] = ACUTE;
+		names[Ids.ID_AELIG_L] = AELIG_L;
+		names[Ids.ID_AELIG_U] = AELIG_U;
+		names[Ids.ID_AGRAVE_L] = AGRAVE_L;
+		names[Ids.ID_AGRAVE_U] = AGRAVE_U;
+		names[Ids.ID_ALEFSYM] = ALEFSYM;
+		names[Ids.ID_ALPHA_L] = ALPHA_L;
+		names[Ids.ID_ALPHA_U] = ALPHA_U;
+		names[Ids.ID_AMP] = AMP;
+		names[Ids.ID_AND] = AND;
+		names[Ids.ID_ANG] = ANG;
+		names[Ids.ID_ARING_L] = ARING_L;
+		names[Ids.ID_ARING_U] = ARING_U;
+		names[Ids.ID_ASYMP] = ASYMP;
+		names[Ids.ID_ATILDE_L] = ATILDE_L;
+		names[Ids.ID_ATILDE_U] = ATILDE_U;
+		names[Ids.ID_AUML_L] = AUML_L;
+		names[Ids.ID_AUML_U] = AUML_U;
+		names[Ids.ID_BDQUO] = BDQUO;
+		names[Ids.ID_BETA_L] = BETA_L;
+		names[Ids.ID_BETA_U] = BETA_U;
+		names[Ids.ID_BRVBAR] = BRVBAR;
+		names[Ids.ID_BULL] = BULL;
+		names[Ids.ID_CAP] = CAP;
+		names[Ids.ID_CCEDIL_L] = CCEDIL_L;
+		names[Ids.ID_CCEDIL_U] = CCEDIL_U;
+		names[Ids.ID_CEDIL] = CEDIL;
+		names[Ids.ID_CENT] = CENT;
+		names[Ids.ID_CHI_L] = CHI_L;
+		names[Ids.ID_CHI_U] = CHI_U;
+		names[Ids.ID_CIRC] = CIRC;
+		names[Ids.ID_CLUBS] = CLUBS;
+		names[Ids.ID_CONG] = CONG;
+		names[Ids.ID_COPY] = COPY;
+		names[Ids.ID_CRARR] = CRARR;
+		names[Ids.ID_CUP] = CUP;
+		names[Ids.ID_CURREN] = CURREN;
+		names[Ids.ID_DAGGER_L] = DAGGER_L;
+		names[Ids.ID_DAGGER_U] = DAGGER_U;
+		names[Ids.ID_DARR_L] = DARR_L;
+		names[Ids.ID_DARR_U] = DARR_U;
+		names[Ids.ID_DEG] = DEG;
+		names[Ids.ID_DELTA_L] = DELTA_L;
+		names[Ids.ID_DELTA_U] = DELTA_U;
+		names[Ids.ID_DIAMS] = DIAMS;
+		names[Ids.ID_DIVIDE] = DIVIDE;
+		names[Ids.ID_EACUTE_L] = EACUTE_L;
+		names[Ids.ID_EACUTE_U] = EACUTE_U;
+		names[Ids.ID_ECIRC_L] = ECIRC_L;
+		names[Ids.ID_ECIRC_U] = ECIRC_U;
+		names[Ids.ID_EGRAVE_L] = EGRAVE_L;
+		names[Ids.ID_EGRAVE_U] = EGRAVE_U;
+		names[Ids.ID_EMPTY] = EMPTY;
+		names[Ids.ID_EMSP] = EMSP;
+		names[Ids.ID_ENSP] = ENSP;
+		names[Ids.ID_EPSILON_L] = EPSILON_L;
+		names[Ids.ID_EPSILON_U] = EPSILON_U;
+		names[Ids.ID_EQUIV] = EQUIV;
+		names[Ids.ID_ETA_L] = ETA_L;
+		names[Ids.ID_ETA_U] = ETA_U;
+		names[Ids.ID_ETH_L] = ETH_L;
+		names[Ids.ID_ETH_U] = ETH_U;
+		names[Ids.ID_EUML_L] = EUML_L;
+		names[Ids.ID_EUML_U] = EUML_U;
+		names[Ids.ID_EURO] = EURO;
+		names[Ids.ID_EXIST] = EXIST;
+		names[Ids.ID_FNOF] = FNOF;
+		names[Ids.ID_FORALL] = FORALL;
+		names[Ids.ID_FRAC12] = FRAC12;
+		names[Ids.ID_FRAC14] = FRAC14;
+		names[Ids.ID_FRAC34] = FRAC34;
+		names[Ids.ID_FRASL] = FRASL;
+		names[Ids.ID_GAMMA_L] = GAMMA_L;
+		names[Ids.ID_GAMMA_U] = GAMMA_U;
+		names[Ids.ID_GE] = GE;
+		names[Ids.ID_GT] = GT;
+		names[Ids.ID_HARR_L] = HARR_L;
+		names[Ids.ID_HARR_U] = HARR_U;
+		names[Ids.ID_HEARTS] = HEARTS;
+		names[Ids.ID_HELLIP] = HELLIP;
+		names[Ids.ID_IACUTE_L] = IACUTE_L;
+		names[Ids.ID_IACUTE_U] = IACUTE_U;
+		names[Ids.ID_ICIRC_L] = ICIRC_L;
+		names[Ids.ID_ICIRC_U] = ICIRC_U;
+		names[Ids.ID_IEXCL] = IEXCL;
+		names[Ids.ID_IGRAVE_L] = IGRAVE_L;
+		names[Ids.ID_IGRAVE_U] = IGRAVE_U;
+		names[Ids.ID_IMAGE] = IMAGE;
+		names[Ids.ID_INFIN] = INFIN;
+		names[Ids.ID_INT] = INT;
+		names[Ids.ID_IOTA_L] = IOTA_L;
+		names[Ids.ID_IOTA_U] = IOTA_U;
+		names[Ids.ID_IQUEST] = IQUEST;
+		names[Ids.ID_ISIN] = ISIN;
+		names[Ids.ID_IUML_L] = IUML_L;
+		names[Ids.ID_IUML_U] = IUML_U;
+		names[Ids.ID_KAPPA_L] = KAPPA_L;
+		names[Ids.ID_KAPPA_U] = KAPPA_U;
+		names[Ids.ID_LAMBDA_L] = LAMBDA_L;
+		names[Ids.ID_LAMBDA_U] = LAMBDA_U;
+		names[Ids.ID_LANG] = LANG;
+		names[Ids.ID_LAQUO] = LAQUO;
+		names[Ids.ID_LARR_L] = LARR_L;
+		names[Ids.ID_LARR_U] = LARR_U;
+		names[Ids.ID_LCEIL] = LCEIL;
+		names[Ids.ID_LDQUO] = LDQUO;
+		names[Ids.ID_LE] = LE;
+		names[Ids.ID_LFLOOR] = LFLOOR;
+		names[Ids.ID_LOWAST] = LOWAST;
+		names[Ids.ID_LOZ] = LOZ;
+		names[Ids.ID_LRM] = LRM;
+		names[Ids.ID_LSAQUO] = LSAQUO;
+		names[Ids.ID_LSQUO] = LSQUO;
+		names[Ids.ID_LT] = LT;
+		names[Ids.ID_MACR] = MACR;
+		names[Ids.ID_MDASH] = MDASH;
+		names[Ids.ID_MICRO] = MICRO;
+		names[Ids.ID_MIDDOT] = MIDDOT;
+		names[Ids.ID_MINUS] = MINUS;
+		names[Ids.ID_MU_L] = MU_L;
+		names[Ids.ID_MU_U] = MU_U;
+		names[Ids.ID_NABLA] = NABLA;
+		names[Ids.ID_NBSP] = NBSP;
+		names[Ids.ID_NDASH] = NDASH;
+		names[Ids.ID_NE] = NE;
+		names[Ids.ID_NI] = NI;
+		names[Ids.ID_NOT] = NOT;
+		names[Ids.ID_NOTIN] = NOTIN;
+		names[Ids.ID_NSUB] = NSUB;
+		names[Ids.ID_NTILDE_L] = NTILDE_L;
+		names[Ids.ID_NTILDE_U] = NTILDE_U;
+		names[Ids.ID_NU_L] = NU_L;
+		names[Ids.ID_NU_U] = NU_U;
+		names[Ids.ID_OACUTE_L] = OACUTE_L;
+		names[Ids.ID_OACUTE_U] = OACUTE_U;
+		names[Ids.ID_OCIRC_L] = OCIRC_L;
+		names[Ids.ID_OCIRC_U] = OCIRC_U;
+		names[Ids.ID_OELIG_L] = OELIG_L;
+		names[Ids.ID_OELIG_U] = OELIG_U;
+		names[Ids.ID_OGRAVE_L] = OGRAVE_L;
+		names[Ids.ID_OGRAVE_U] = OGRAVE_U;
+		names[Ids.ID_OLINE] = OLINE;
+		names[Ids.ID_OMEGA_L] = OMEGA_L;
+		names[Ids.ID_OMEGA_U] = OMEGA_U;
+		names[Ids.ID_OMICRON_L] = OMICRON_L;
+		names[Ids.ID_OMICRON_U] = OMICRON_U;
+		names[Ids.ID_OPLUS] = OPLUS;
+		names[Ids.ID_OR] = OR;
+		names[Ids.ID_ORDF] = ORDF;
+		names[Ids.ID_ORDM] = ORDM;
+		names[Ids.ID_OSLASH_L] = OSLASH_L;
+		names[Ids.ID_OSLASH_U] = OSLASH_U;
+		names[Ids.ID_OTILDE_L] = OTILDE_L;
+		names[Ids.ID_OTILDE_U] = OTILDE_U;
+		names[Ids.ID_OTIMES] = OTIMES;
+		names[Ids.ID_OUML_L] = OUML_L;
+		names[Ids.ID_OUML_U] = OUML_U;
+		names[Ids.ID_PARA] = PARA;
+		names[Ids.ID_PART] = PART;
+		names[Ids.ID_PERMIL] = PERMIL;
+		names[Ids.ID_PERP] = PERP;
+		names[Ids.ID_PHI_L] = PHI_L;
+		names[Ids.ID_PHI_U] = PHI_U;
+		names[Ids.ID_PIV] = PIV;
+		names[Ids.ID_PI_L] = PI_L;
+		names[Ids.ID_PI_U] = PI_U;
+		names[Ids.ID_PLUSMN] = PLUSMN;
+		names[Ids.ID_POUND] = POUND;
+		names[Ids.ID_PRIME_L] = PRIME_L;
+		names[Ids.ID_PRIME_U] = PRIME_U;
+		names[Ids.ID_PROD] = PROD;
+		names[Ids.ID_PROP] = PROP;
+		names[Ids.ID_PSI_L] = PSI_L;
+		names[Ids.ID_PSI_U] = PSI_U;
+		names[Ids.ID_QUOT] = QUOT;
+		names[Ids.ID_RADIC] = RADIC;
+		names[Ids.ID_RANG] = RANG;
+		names[Ids.ID_RAQUO] = RAQUO;
+		names[Ids.ID_RARR_L] = RARR_L;
+		names[Ids.ID_RARR_U] = RARR_U;
+		names[Ids.ID_RCEIL] = RCEIL;
+		names[Ids.ID_RDQUO] = RDQUO;
+		names[Ids.ID_REAL] = REAL;
+		names[Ids.ID_REG] = REG;
+		names[Ids.ID_RFLOOR] = RFLOOR;
+		names[Ids.ID_RHO_L] = RHO_L;
+		names[Ids.ID_RHO_U] = RHO_U;
+		names[Ids.ID_RLM] = RLM;
+		names[Ids.ID_RSAQUO] = RSAQUO;
+		names[Ids.ID_RSQUO] = RSQUO;
+		names[Ids.ID_SBQUO] = SBQUO;
+		names[Ids.ID_SCARON_L] = SCARON_L;
+		names[Ids.ID_SCARON_U] = SCARON_U;
+		names[Ids.ID_SDOT] = SDOT;
+		names[Ids.ID_SECT] = SECT;
+		names[Ids.ID_SHY] = SHY;
+		names[Ids.ID_SIGMAF] = SIGMAF;
+		names[Ids.ID_SIGMA_L] = SIGMA_L;
+		names[Ids.ID_SIGMA_U] = SIGMA_U;
+		names[Ids.ID_SIM] = SIM;
+		names[Ids.ID_SPADES] = SPADES;
+		names[Ids.ID_SUB] = SUB;
+		names[Ids.ID_SUBE] = SUBE;
+		names[Ids.ID_SUM] = SUM;
+		names[Ids.ID_SUP] = SUP;
+		names[Ids.ID_SUP1] = SUP1;
+		names[Ids.ID_SUP2] = SUP2;
+		names[Ids.ID_SUP3] = SUP3;
+		names[Ids.ID_SUPE] = SUPE;
+		names[Ids.ID_SZLIG] = SZLIG;
+		names[Ids.ID_TAU_L] = TAU_L;
+		names[Ids.ID_TAU_U] = TAU_U;
+		names[Ids.ID_THERE4] = THERE4;
+		names[Ids.ID_THETASYM] = THETASYM;
+		names[Ids.ID_THETA_L] = THETA_L;
+		names[Ids.ID_THETA_U] = THETA_U;
+		names[Ids.ID_THINSP] = THINSP;
+		names[Ids.ID_THORN_L] = THORN_L;
+		names[Ids.ID_THORN_U] = THORN_U;
+		names[Ids.ID_TILDE] = TILDE;
+		names[Ids.ID_TIMES] = TIMES;
+		names[Ids.ID_TRADE] = TRADE;
+		names[Ids.ID_UACUTE_L] = UACUTE_L;
+		names[Ids.ID_UACUTE_U] = UACUTE_U;
+		names[Ids.ID_UARR_L] = UARR_L;
+		names[Ids.ID_UARR_U] = UARR_U;
+		names[Ids.ID_UCIRC_L] = UCIRC_L;
+		names[Ids.ID_UCIRC_U] = UCIRC_U;
+		names[Ids.ID_UGRAVE_L] = UGRAVE_L;
+		names[Ids.ID_UGRAVE_U] = UGRAVE_U;
+		names[Ids.ID_UML] = UML;
+		names[Ids.ID_UPSIH] = UPSIH;
+		names[Ids.ID_UPSILON_L] = UPSILON_L;
+		names[Ids.ID_UPSILON_U] = UPSILON_U;
+		names[Ids.ID_UUML_L] = UUML_L;
+		names[Ids.ID_UUML_U] = UUML_U;
+		names[Ids.ID_WEIERP] = WEIERP;
+		names[Ids.ID_XI_L] = XI_L;
+		names[Ids.ID_XI_U] = XI_U;
+		names[Ids.ID_YACUTE_L] = YACUTE_L;
+		names[Ids.ID_YACUTE_U] = YACUTE_U;
+		names[Ids.ID_YEN] = YEN;
+		names[Ids.ID_YUML_L] = YUML_L;
+		names[Ids.ID_YUML_U] = YUML_U;
+		names[Ids.ID_ZETA_L] = ZETA_L;
+		names[Ids.ID_ZETA_U] = ZETA_U;
+		names[Ids.ID_ZWJ] = ZWJ;
+		names[Ids.ID_ZWNJ] = ZWNJ;
+	}
+	private static char[] values = null;
+
+	static {
+		values = new char[Ids.getNumOfIds()];
+		values[Ids.ID_AACUTE_L] = 225;
+		values[Ids.ID_AACUTE_U] = 193;
+		values[Ids.ID_ACIRC_L] = 226;
+		values[Ids.ID_ACIRC_U] = 194;
+		values[Ids.ID_ACUTE] = 180;
+		values[Ids.ID_AELIG_L] = 230;
+		values[Ids.ID_AELIG_U] = 198;
+		values[Ids.ID_AGRAVE_L] = 224;
+		values[Ids.ID_AGRAVE_U] = 192;
+		values[Ids.ID_ALEFSYM] = 8501;
+		values[Ids.ID_ALPHA_L] = 945;
+		values[Ids.ID_ALPHA_U] = 913;
+		values[Ids.ID_AMP] = 38;
+		values[Ids.ID_AND] = 8743;
+		values[Ids.ID_ANG] = 8736;
+		values[Ids.ID_ARING_L] = 229;
+		values[Ids.ID_ARING_U] = 197;
+		values[Ids.ID_ASYMP] = 8776;
+		values[Ids.ID_ATILDE_L] = 227;
+		values[Ids.ID_ATILDE_U] = 195;
+		values[Ids.ID_AUML_L] = 228;
+		values[Ids.ID_AUML_U] = 196;
+		values[Ids.ID_BDQUO] = 8222;
+		values[Ids.ID_BETA_L] = 946;
+		values[Ids.ID_BETA_U] = 914;
+		values[Ids.ID_BRVBAR] = 166;
+		values[Ids.ID_BULL] = 8226;
+		values[Ids.ID_CAP] = 8745;
+		values[Ids.ID_CCEDIL_L] = 231;
+		values[Ids.ID_CCEDIL_U] = 199;
+		values[Ids.ID_CEDIL] = 184;
+		values[Ids.ID_CENT] = 162;
+		values[Ids.ID_CHI_L] = 967;
+		values[Ids.ID_CHI_U] = 935;
+		values[Ids.ID_CIRC] = 710;
+		values[Ids.ID_CLUBS] = 9827;
+		values[Ids.ID_CONG] = 8773;
+		values[Ids.ID_COPY] = 169;
+		values[Ids.ID_CRARR] = 8629;
+		values[Ids.ID_CUP] = 8746;
+		values[Ids.ID_CURREN] = 164;
+		values[Ids.ID_DAGGER_L] = 8224;
+		values[Ids.ID_DAGGER_U] = 8225;
+		values[Ids.ID_DARR_L] = 8595;
+		values[Ids.ID_DARR_U] = 8659;
+		values[Ids.ID_DEG] = 176;
+		values[Ids.ID_DELTA_L] = 948;
+		values[Ids.ID_DELTA_U] = 916;
+		values[Ids.ID_DIAMS] = 9830;
+		values[Ids.ID_DIVIDE] = 247;
+		values[Ids.ID_EACUTE_L] = 233;
+		values[Ids.ID_EACUTE_U] = 201;
+		values[Ids.ID_ECIRC_L] = 234;
+		values[Ids.ID_ECIRC_U] = 202;
+		values[Ids.ID_EGRAVE_L] = 232;
+		values[Ids.ID_EGRAVE_U] = 200;
+		values[Ids.ID_EMPTY] = 8709;
+		values[Ids.ID_EMSP] = 8195;
+		values[Ids.ID_ENSP] = 8194;
+		values[Ids.ID_EPSILON_L] = 949;
+		values[Ids.ID_EPSILON_U] = 917;
+		values[Ids.ID_EQUIV] = 8801;
+		values[Ids.ID_ETA_L] = 951;
+		values[Ids.ID_ETA_U] = 919;
+		values[Ids.ID_ETH_L] = 240;
+		values[Ids.ID_ETH_U] = 208;
+		values[Ids.ID_EUML_L] = 235;
+		values[Ids.ID_EUML_U] = 203;
+		values[Ids.ID_EURO] = 8364;
+		values[Ids.ID_EXIST] = 8707;
+		values[Ids.ID_FNOF] = 402;
+		values[Ids.ID_FORALL] = 8704;
+		values[Ids.ID_FRAC12] = 189;
+		values[Ids.ID_FRAC14] = 188;
+		values[Ids.ID_FRAC34] = 190;
+		values[Ids.ID_FRASL] = 8260;
+		values[Ids.ID_GAMMA_L] = 947;
+		values[Ids.ID_GAMMA_U] = 915;
+		values[Ids.ID_GE] = 8805;
+		values[Ids.ID_GT] = 62;
+		values[Ids.ID_HARR_L] = 8596;
+		values[Ids.ID_HARR_U] = 8660;
+		values[Ids.ID_HEARTS] = 9829;
+		values[Ids.ID_HELLIP] = 8230;
+		values[Ids.ID_IACUTE_L] = 237;
+		values[Ids.ID_IACUTE_U] = 205;
+		values[Ids.ID_ICIRC_L] = 238;
+		values[Ids.ID_ICIRC_U] = 206;
+		values[Ids.ID_IEXCL] = 161;
+		values[Ids.ID_IGRAVE_L] = 236;
+		values[Ids.ID_IGRAVE_U] = 204;
+		values[Ids.ID_IMAGE] = 8465;
+		values[Ids.ID_INFIN] = 8734;
+		values[Ids.ID_INT] = 8747;
+		values[Ids.ID_IOTA_L] = 953;
+		values[Ids.ID_IOTA_U] = 921;
+		values[Ids.ID_IQUEST] = 191;
+		values[Ids.ID_ISIN] = 8712;
+		values[Ids.ID_IUML_L] = 239;
+		values[Ids.ID_IUML_U] = 207;
+		values[Ids.ID_KAPPA_L] = 954;
+		values[Ids.ID_KAPPA_U] = 922;
+		values[Ids.ID_LAMBDA_L] = 955;
+		values[Ids.ID_LAMBDA_U] = 923;
+		values[Ids.ID_LANG] = 9001;
+		values[Ids.ID_LAQUO] = 171;
+		values[Ids.ID_LARR_L] = 8592;
+		values[Ids.ID_LARR_U] = 8656;
+		values[Ids.ID_LCEIL] = 8968;
+		values[Ids.ID_LDQUO] = 8220;
+		values[Ids.ID_LE] = 8804;
+		values[Ids.ID_LFLOOR] = 8970;
+		values[Ids.ID_LOWAST] = 8727;
+		values[Ids.ID_LOZ] = 9674;
+		values[Ids.ID_LRM] = 8206;
+		values[Ids.ID_LSAQUO] = 8249;
+		values[Ids.ID_LSQUO] = 8216;
+		values[Ids.ID_LT] = 60;
+		values[Ids.ID_MACR] = 175;
+		values[Ids.ID_MDASH] = 8212;
+		values[Ids.ID_MICRO] = 181;
+		values[Ids.ID_MIDDOT] = 183;
+		values[Ids.ID_MINUS] = 8722;
+		values[Ids.ID_MU_L] = 956;
+		values[Ids.ID_MU_U] = 924;
+		values[Ids.ID_NABLA] = 8711;
+		values[Ids.ID_NBSP] = 160;
+		values[Ids.ID_NDASH] = 8211;
+		values[Ids.ID_NE] = 8800;
+		values[Ids.ID_NI] = 8715;
+		values[Ids.ID_NOT] = 172;
+		values[Ids.ID_NOTIN] = 8713;
+		values[Ids.ID_NSUB] = 8836;
+		values[Ids.ID_NTILDE_L] = 241;
+		values[Ids.ID_NTILDE_U] = 209;
+		values[Ids.ID_NU_L] = 957;
+		values[Ids.ID_NU_U] = 925;
+		values[Ids.ID_OACUTE_L] = 243;
+		values[Ids.ID_OACUTE_U] = 211;
+		values[Ids.ID_OCIRC_L] = 244;
+		values[Ids.ID_OCIRC_U] = 212;
+		values[Ids.ID_OELIG_L] = 339;
+		values[Ids.ID_OELIG_U] = 338;
+		values[Ids.ID_OGRAVE_L] = 242;
+		values[Ids.ID_OGRAVE_U] = 210;
+		values[Ids.ID_OLINE] = 8254;
+		values[Ids.ID_OMEGA_L] = 969;
+		values[Ids.ID_OMEGA_U] = 937;
+		values[Ids.ID_OMICRON_L] = 959;
+		values[Ids.ID_OMICRON_U] = 927;
+		values[Ids.ID_OPLUS] = 8853;
+		values[Ids.ID_OR] = 8744;
+		values[Ids.ID_ORDF] = 170;
+		values[Ids.ID_ORDM] = 186;
+		values[Ids.ID_OSLASH_L] = 248;
+		values[Ids.ID_OSLASH_U] = 216;
+		values[Ids.ID_OTILDE_L] = 245;
+		values[Ids.ID_OTILDE_U] = 213;
+		values[Ids.ID_OTIMES] = 8855;
+		values[Ids.ID_OUML_L] = 246;
+		values[Ids.ID_OUML_U] = 214;
+		values[Ids.ID_PARA] = 182;
+		values[Ids.ID_PART] = 8706;
+		values[Ids.ID_PERMIL] = 8240;
+		values[Ids.ID_PERP] = 8869;
+		values[Ids.ID_PHI_L] = 966;
+		values[Ids.ID_PHI_U] = 934;
+		values[Ids.ID_PIV] = 982;
+		values[Ids.ID_PI_L] = 960;
+		values[Ids.ID_PI_U] = 928;
+		values[Ids.ID_PLUSMN] = 177;
+		values[Ids.ID_POUND] = 163;
+		values[Ids.ID_PRIME_L] = 8242;
+		values[Ids.ID_PRIME_U] = 8243;
+		values[Ids.ID_PROD] = 8719;
+		values[Ids.ID_PROP] = 8733;
+		values[Ids.ID_PSI_L] = 968;
+		values[Ids.ID_PSI_U] = 936;
+		values[Ids.ID_QUOT] = 34;
+		values[Ids.ID_RADIC] = 8730;
+		values[Ids.ID_RANG] = 9002;
+		values[Ids.ID_RAQUO] = 187;
+		values[Ids.ID_RARR_L] = 8594;
+		values[Ids.ID_RARR_U] = 8658;
+		values[Ids.ID_RCEIL] = 8969;
+		values[Ids.ID_RDQUO] = 8221;
+		values[Ids.ID_REAL] = 8476;
+		values[Ids.ID_REG] = 174;
+		values[Ids.ID_RFLOOR] = 8971;
+		values[Ids.ID_RHO_L] = 961;
+		values[Ids.ID_RHO_U] = 929;
+		values[Ids.ID_RLM] = 8207;
+		values[Ids.ID_RSAQUO] = 8250;
+		values[Ids.ID_RSQUO] = 8217;
+		values[Ids.ID_SBQUO] = 8218;
+		values[Ids.ID_SCARON_L] = 353;
+		values[Ids.ID_SCARON_U] = 352;
+		values[Ids.ID_SDOT] = 8901;
+		values[Ids.ID_SECT] = 167;
+		values[Ids.ID_SHY] = 173;
+		values[Ids.ID_SIGMAF] = 962;
+		values[Ids.ID_SIGMA_L] = 963;
+		values[Ids.ID_SIGMA_U] = 931;
+		values[Ids.ID_SIM] = 8764;
+		values[Ids.ID_SPADES] = 9824;
+		values[Ids.ID_SUB] = 8834;
+		values[Ids.ID_SUBE] = 8838;
+		values[Ids.ID_SUM] = 8721;
+		values[Ids.ID_SUP] = 8835;
+		values[Ids.ID_SUP1] = 185;
+		values[Ids.ID_SUP2] = 178;
+		values[Ids.ID_SUP3] = 179;
+		values[Ids.ID_SUPE] = 8839;
+		values[Ids.ID_SZLIG] = 223;
+		values[Ids.ID_TAU_L] = 964;
+		values[Ids.ID_TAU_U] = 932;
+		values[Ids.ID_THERE4] = 8756;
+		values[Ids.ID_THETASYM] = 977;
+		values[Ids.ID_THETA_L] = 952;
+		values[Ids.ID_THETA_U] = 920;
+		values[Ids.ID_THINSP] = 8201;
+		values[Ids.ID_THORN_L] = 254;
+		values[Ids.ID_THORN_U] = 222;
+		values[Ids.ID_TILDE] = 732;
+		values[Ids.ID_TIMES] = 215;
+		values[Ids.ID_TRADE] = 8482;
+		values[Ids.ID_UACUTE_L] = 250;
+		values[Ids.ID_UACUTE_U] = 218;
+		values[Ids.ID_UARR_L] = 8593;
+		values[Ids.ID_UARR_U] = 8657;
+		values[Ids.ID_UCIRC_L] = 251;
+		values[Ids.ID_UCIRC_U] = 219;
+		values[Ids.ID_UGRAVE_L] = 249;
+		values[Ids.ID_UGRAVE_U] = 217;
+		values[Ids.ID_UML] = 168;
+		values[Ids.ID_UPSIH] = 978;
+		values[Ids.ID_UPSILON_L] = 965;
+		values[Ids.ID_UPSILON_U] = 933;
+		values[Ids.ID_UUML_L] = 252;
+		values[Ids.ID_UUML_U] = 220;
+		values[Ids.ID_WEIERP] = 8472;
+		values[Ids.ID_XI_L] = 958;
+		values[Ids.ID_XI_U] = 926;
+		values[Ids.ID_YACUTE_L] = 253;
+		values[Ids.ID_YACUTE_U] = 221;
+		values[Ids.ID_YEN] = 165;
+		values[Ids.ID_YUML_L] = 255;
+		values[Ids.ID_YUML_U] = 376;
+		values[Ids.ID_ZETA_L] = 950;
+		values[Ids.ID_ZETA_U] = 918;
+		values[Ids.ID_ZWJ] = 8205;
+		values[Ids.ID_ZWNJ] = 8204;
+	}
+
+	/**
+	 */
+	public EntityCollection() {
+		super(names, STRICT_CASE);
+	}
+
+	/**
+	 * Create an entity declaration.
+	 * @return org.eclipse.wst.xml.core.internal.contentmodel.CMNode
+	 * @param attrName java.lang.String
+	 */
+	protected CMNode create(String entityName) {
+		int id = getID(entityName);
+		if (id == ID_UNKNOWN)
+			return null;
+
+		String value = String.valueOf(values[id]);
+		HTMLEntityDeclImpl dec = new HTMLEntityDeclImpl(entityName, value);
+
+		return dec;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/H5CMDocImpl.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/H5CMDocImpl.java
new file mode 100644
index 0000000..e16c9dd
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/H5CMDocImpl.java
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ * CMDocument implementation for the HTML.
+ */
+class H5CMDocImpl extends CMNodeImpl implements HTMLCMDocument {
+
+	/** Namespace for all names of elements, entities and attributes. */
+	private CMNamespaceImpl namespace = null;
+	private HTML5ElementCollection elements = null;
+	private EntityCollection entities = null;
+	private AttributeCollection attributes = null;
+
+	/**
+	 */
+	public H5CMDocImpl(String docTypeName, CMNamespaceImpl targetNamespace) {
+		super(docTypeName);
+		namespace = targetNamespace;
+		
+		attributes = new HTML5AttributeCollection();
+		elements = new HTML5ElementCollection(attributes);
+		entities = new EntityCollection();
+	}
+
+	AttributeCollection getAttributes() {
+		return attributes;
+	}
+
+	public HTMLElementDeclaration getElementDeclaration(String elementName) {
+		if (elements == null)
+			return null;
+		return (HTMLElementDeclaration) elements.getNamedItem(elementName);
+	}
+
+	/**
+	 * @see org.eclipse.wst.xml.core.internal.contentmodel.CMDocument
+	 */
+	public CMNamedNodeMap getElements() {
+		return elements;
+	}
+
+	/**
+	 * @see org.eclipse.wst.xml.core.internal.contentmodel.CMDocument
+	 */
+	public CMNamedNodeMap getEntities() {
+		return entities;
+	}
+
+	public HTMLEntityDeclaration getEntityDeclaration(String entityName) {
+		if (entities == null)
+			return null;
+		return (HTMLEntityDeclaration) entities.getNamedItem(entityName);
+	}
+
+	/**
+	 * @see org.eclipse.wst.xml.core.internal.contentmodel.CMDocument
+	 */
+	public CMNamespace getNamespace() {
+		return namespace;
+	}
+
+	/**
+	 * @see CMNode
+	 */
+	public int getNodeType() {
+		return CMNode.DOCUMENT;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HCMDocImpl.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HCMDocImpl.java
new file mode 100644
index 0000000..0ba233a
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HCMDocImpl.java
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ * CMDocument implementation for the HTML.
+ */
+class HCMDocImpl extends CMNodeImpl implements HTMLCMDocument {
+
+	/** Namespace for all names of elements, entities and attributes. */
+	private CMNamespaceImpl namespace = null;
+	private ElementCollection elements = null;
+	private EntityCollection entities = null;
+	private AttributeCollection attributes = null;
+
+	/**
+	 */
+	public HCMDocImpl(String docTypeName, CMNamespaceImpl targetNamespace) {
+		super(docTypeName);
+		namespace = targetNamespace;
+		attributes = new AttributeCollection();
+		elements = new ElementCollection(attributes);
+		entities = new EntityCollection();
+	}
+
+	AttributeCollection getAttributes() {
+		return attributes;
+	}
+
+	public HTMLElementDeclaration getElementDeclaration(String elementName) {
+		if (elements == null)
+			return null;
+		return (HTMLElementDeclaration) elements.getNamedItem(elementName);
+	}
+
+	/**
+	 * @see org.eclipse.wst.xml.core.internal.contentmodel.CMDocument
+	 */
+	public CMNamedNodeMap getElements() {
+		return elements;
+	}
+
+	/**
+	 * @see org.eclipse.wst.xml.core.internal.contentmodel.CMDocument
+	 */
+	public CMNamedNodeMap getEntities() {
+		return entities;
+	}
+
+	public HTMLEntityDeclaration getEntityDeclaration(String entityName) {
+		if (entities == null)
+			return null;
+		return (HTMLEntityDeclaration) entities.getNamedItem(entityName);
+	}
+
+	/**
+	 * @see org.eclipse.wst.xml.core.internal.contentmodel.CMDocument
+	 */
+	public CMNamespace getNamespace() {
+		return namespace;
+	}
+
+	/**
+	 * @see CMNode
+	 */
+	public int getNodeType() {
+		return CMNode.DOCUMENT;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HTML5AttributeCollection.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HTML5AttributeCollection.java
new file mode 100644
index 0000000..d086aa6
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HTML5AttributeCollection.java
@@ -0,0 +1,1326 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+import java.util.Arrays;
+import java.util.Iterator;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.html.core.internal.provisional.HTML50Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+
+public class HTML5AttributeCollection extends AttributeCollection implements HTML50Namespace {
+	/** html5 core attribs */
+	private static final String[] CORE = {ATTR_NAME_ACCESSKEY, ATTR_NAME_CLASS, ATTR_NAME_CONTENT_EDITABLE, ATTR_NAME_CONTEXT_MENU, ATTR_NAME_DIR, ATTR_NAME_DRAGGABLE, ATTR_NAME_HIDDEN, ATTR_NAME_ID, ATTR_NAME_LANG, ATTR_NAME_SPELLCHECK,ATTR_NAME_STYLE, ATTR_NAME_TABINDEX, ATTR_NAME_TITLE};
+	/** events for HTML5. */
+	private static final String[] EVENTS = {ATTR_NAME_ONABORT, ATTR_NAME_ONBLUR, ATTR_NAME_ONCAN_PLAY, ATTR_NAME_ONCAN_PLAY_THROUGH, ATTR_NAME_ONCHANGE, ATTR_NAME_ONCLICK, ATTR_NAME_ONCONTEXT_MENU, ATTR_NAME_ONDBLCLICK, ATTR_NAME_ONDRAG, ATTR_NAME_ONDRAG_END, ATTR_NAME_ONDRAG_ENTER, ATTR_NAME_ONDRAG_LEAVE, 
+		ATTR_NAME_ONDRAG_OVER, ATTR_NAME_ONDRAG_START, ATTR_NAME_ONDROP, ATTR_NAME_ONDURATION_CHANGE, ATTR_NAME_ONEMPTIED, ATTR_NAME_ONENDED, ATTR_NAME_ONERROR, ATTR_NAME_ONFOCUS, ATTR_NAME_ONFORM_CHANGE, ATTR_NAME_ONFORM_INPUT, ATTR_NAME_ONINVALID,ATTR_NAME_ONKEYPRESS, ATTR_NAME_ONKEYDOWN, ATTR_NAME_ONKEYUP, 
+		ATTR_NAME_ONLOAD, ATTR_NAME_ONLOAD_START, ATTR_NAME_ONLOADED_DATA, ATTR_NAME_ONLOADED_METADATA, ATTR_NAME_ONMOUSEDOWN, ATTR_NAME_ONMOUSEUP, ATTR_NAME_ONMOUSEOVER, ATTR_NAME_ONMOUSEMOVE, ATTR_NAME_ONMOUSEOUT, ATTR_NAME_ONMOUSE_WHEEL, ATTR_NAME_ONPAUSE, ATTR_NAME_ONPLAY, ATTR_NAME_ONPLAYING, ATTR_NAME_ONPROGRESS,
+		ATTR_NAME_ONRATE_CHANGE, ATTR_NAME_ONREADY_STATE_CHANGE, ATTR_NAME_ONSCROLL, ATTR_NAME_ONSEEKED, ATTR_NAME_ONSEEKING, ATTR_NAME_ONSELECT, ATTR_NAME_ONSHOW, ATTR_NAME_ONSTALLED, ATTR_NAME_ONSUBMIT, ATTR_NAME_ONSUSPEND, ATTR_NAME_ONTIME_UPDATE, ATTR_NAME_ONVOLUME_UPDATE, ATTR_NAME_ONWAITING};
+
+	protected HTMLAttrDeclImpl create(String attrName) {
+		HTMLAttrDeclImpl attr = null;
+		HTMLCMDataTypeImpl atype = null;
+		if (attrName.equalsIgnoreCase(ATTR_NAME_AUTOFOCUS)) {
+			// (disabled (disabled) #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			// boolean attribute must have the same value as its name.
+			String[] values = {ATTR_NAME_AUTOFOCUS};
+			atype.setEnumValues(values);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_AUTOFOCUS, atype, CMAttributeDeclaration.OPTIONAL);
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_CONTENT_EDITABLE)) {
+			// (contenteditable (EMPTY|TRUE|FALSE|INHERIT) TRUE)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_VALUE_EMPTY, ATTR_VALUE_TRUE, ATTR_VALUE_FALSE, ATTR_VALUE_INHERIT};
+			atype.setEnumValues(values);
+			atype.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, ATTR_VALUE_TRUE);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_CONTENT_EDITABLE, atype, CMAttributeDeclaration.OPTIONAL);
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_CHALLENGE)) {
+			// (challenge CDATA; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_CHALLENGE, atype, CMAttributeDeclaration.OPTIONAL);
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_CONTEXT_MENU)) {
+			// (contextmenu, CDATA, IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_CONTEXT_MENU, atype, CMAttributeDeclaration.OPTIONAL);
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_DRAGGABLE)) {
+			// (draggable (TRUE|FALSE|AUTO) TRUE)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_VALUE_TRUE, ATTR_VALUE_FALSE, ATTR_VALUE_AUTO};
+			atype.setEnumValues(values);
+			atype.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, ATTR_VALUE_FALSE);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_DRAGGABLE, atype, CMAttributeDeclaration.OPTIONAL);
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_FORM)) {
+			// (form CDATA; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_FORM, atype, CMAttributeDeclaration.OPTIONAL);
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_KEYTYPE)) {
+			// (keytype CDATA; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_KEYTYPE, atype, CMAttributeDeclaration.OPTIONAL);
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_LOW)) {
+			atype = new HTMLCMDataTypeImpl(CMDataType.NUMBER);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_LOW, atype, CMAttributeDeclaration.OPTIONAL);
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_HIGH)) {
+			atype = new HTMLCMDataTypeImpl(CMDataType.NUMBER);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_HIGH, atype, CMAttributeDeclaration.OPTIONAL);
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_OPTIMUM)) {
+			atype = new HTMLCMDataTypeImpl(CMDataType.NUMBER);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_OPTIMUM, atype, CMAttributeDeclaration.OPTIONAL);
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_MIN)) {
+			atype = new HTMLCMDataTypeImpl(CMDataType.NUMBER);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_MIN, atype, CMAttributeDeclaration.OPTIONAL);
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_MAX)) {
+			atype = new HTMLCMDataTypeImpl(CMDataType.NUMBER);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_MAX, atype, CMAttributeDeclaration.OPTIONAL);
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_OPEN)) {
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			atype.setEnumValues(new String[] { ATTR_NAME_OPEN });
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_OPEN, atype, CMAttributeDeclaration.OPTIONAL);
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_PUBDATE)) {
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			atype.setEnumValues(new String[] { ATTR_NAME_PUBDATE });
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_PUBDATE, atype, CMAttributeDeclaration.OPTIONAL);
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_SPELLCHECK)) {
+			// (spellcheck (EMPTY|TRUE|FALSE) TRUE)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_VALUE_EMPTY, ATTR_VALUE_TRUE, ATTR_VALUE_FALSE};
+			atype.setEnumValues(values);
+			atype.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, ATTR_VALUE_FALSE);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_SPELLCHECK, atype, CMAttributeDeclaration.OPTIONAL);
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONABORT)) {
+			// (onabort %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONABORT, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONCAN_PLAY)) {
+			// (oncanplay %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONCAN_PLAY, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONCAN_PLAY_THROUGH)) {
+			// (oncanplaythrough %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONCAN_PLAY_THROUGH, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONCHANGE)) {
+			// (onchange %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONCHANGE, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONCONTEXT_MENU)) {
+			// (onacontextmenu %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONCONTEXT_MENU, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONDRAG)) {
+			// (onadrag %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONDRAG, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONDRAG_END)) {
+			// (ondragend %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONDRAG_END, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONDRAG_ENTER)) {
+			// (ondragenter %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONDRAG_ENTER, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONDRAG_LEAVE)) {
+			// (ondragleave %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONDRAG_LEAVE, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONDRAG_OVER)) {
+			// (ondragover %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONDRAG_OVER, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONDRAG_START)) {
+			// (ondragstart %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONDRAG_START, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONDROP)) {
+			// (ondrop %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONDROP, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONDURATION_CHANGE)) {
+			// (ondurationchange %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONDURATION_CHANGE, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONEMPTIED)) {
+			// (onemptied %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONEMPTIED, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONENDED)) {
+			// (onended %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONENDED, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONERROR)) {
+			// (onerror %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONERROR, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONFOCUS)) {
+			// (onfocus %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONFOCUS, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONFORM_CHANGE)) {
+			// (onformchange %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONFORM_CHANGE, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONFORM_INPUT)) {
+			// (onforminput %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONFORM_INPUT, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONINPUT)) {
+			// (oninput %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONINPUT, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONINVALID)) {
+			// (oninvalid %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONINVALID, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONLOAD)) {
+			// (onload %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONLOAD, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONLOAD_START)) {
+			// (onloadstart %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONLOAD_START, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONLOADED_DATA)) {
+			// (onloadeddata %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONLOADED_DATA, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONLOADED_METADATA)) {
+			// (onloadedmetadata %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONLOADED_METADATA, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONMOUSE_WHEEL)) {
+			// (onmousewheel %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONMOUSE_WHEEL, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONPLAY)) {
+			// (onplay %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONPLAY, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONPLAYING)) {
+			// (onplaying %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONPLAYING, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONPAUSE)) {
+			// (onpause %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONPAUSE, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONPROGRESS)) {
+			// (onprogress %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONPROGRESS, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONRATE_CHANGE)) {
+			// (onratechange %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONRATE_CHANGE, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONREADY_STATE_CHANGE)) {
+			// (onreadystatechange %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONREADY_STATE_CHANGE, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONSCROLL)) {
+			// (onscroll %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONSCROLL, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONSEEKED)) {
+			// (onseeked %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONSEEKED, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONSEEKING)) {
+			// (onseeking %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONSEEKING, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONSELECT)) {
+			// (onselect %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONSELECT, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONSHOW)) {
+			// (onshow %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONSHOW, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONSTALLED)) {
+			// (onstalled %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONSTALLED, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONSUBMIT)) {
+			// (onsubmit %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONSUBMIT, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONSUSPEND)) {
+			// (onsuspend %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONSUSPEND, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONTIME_UPDATE)) {
+			// (ontimeupdate %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONTIME_UPDATE, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONVOLUME_UPDATE)) {
+			// (onvolumeupdate %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONVOLUME_UPDATE, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ONWAITING)) {
+			// (onwaiting %Script; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.SCRIPT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ONWAITING, atype, CMAttributeDeclaration.OPTIONAL);
+		}
+		else {
+			attr = super.create(attrName);
+		}
+		return attr;
+	}
+
+	public void getAttrs(CMNamedNodeMapImpl declarations) {
+		// %coreattrs;
+		getCore(declarations);
+		// %events;
+		getEvents(declarations);
+	}
+
+	public void getCore(CMNamedNodeMapImpl declarations) {
+		Iterator names = Arrays.asList(CORE).iterator();
+		getDeclarations(declarations, names);
+	}
+
+	public void getEvents(CMNamedNodeMapImpl declarations) {
+		Iterator names = Arrays.asList(EVENTS).iterator();
+		getDeclarations(declarations, names);
+	}
+	
+	public void createAttributeDeclarations(String elementName, CMNamedNodeMapImpl attributes) {
+		/* (type %InputType; TEXT) ... should be defined locally.
+		 * (name CDATA #IMPLIED)
+		 * (value CDATA #IMPLIED)
+		 * (checked (checked) #IMPLIED)
+		 * (disabled (disabled) #IMPLIED)
+		 * (readonly (readonly) #IMPLIED)
+		 * (size CDATA #IMPLIED) ... should be defined locally.
+		 * (maxlength NUMBER #IMPLIED)
+		 * (src %URI; #IMPLIED)
+		 * (alt CDATA #IMPLIED) ... should be defined locally.
+		 * (accept %ContentTypes; #IMPLIED)
+		 * (width CDATA; #IMPLIED)
+		 * (height CDATA; #IMPLIED)
+		 * (autocomplete Boolean; #IMPLIED)
+		 * (autofocus Boolean; #IMPLIED)
+		 * (form CDATA; #IMPLIED)
+		 * (formaction)
+		 * (formenctype)
+		 * (formmethod)
+		 * (formnovalidate)
+		 * (formtarget)
+		 * (list)
+		 * (max)
+		 * (min)
+		 * (multiple)
+		 * (pattern)
+		 * (placeholder CDATA #IMPLIED)
+		 * (required)
+		 * (step)
+		 * discouraged tags :- 
+		 * (usemap %URI; #IMPLIED)
+		 * (ismap (ismap) #IMPLIED)
+		 */
+		if (elementName.equals(HTML40Namespace.ElementName.INPUT)){
+			HTMLCMDataTypeImpl atype = null;
+			HTMLAttrDeclImpl attr = null;
+			// (type %InputType; TEXT) ... should be defined locally.
+			// NOTE: %InputType is ENUM;
+			// (text | password | checkbox | radio | submit | reset |
+			//  file | hidden | image | button
+			//  color| date | time | datetime | datetime-local | month | week| email| 
+			//  number | range | search | tel)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_VALUE_TEXT, ATTR_VALUE_PASSWORD, ATTR_VALUE_CHECKBOX, ATTR_VALUE_RADIO, ATTR_VALUE_SUBMIT, ATTR_VALUE_RESET, ATTR_VALUE_FILE, ATTR_VALUE_HIDDEN, ATTR_VALUE_IMAGE, ATTR_VALUE_BUTTON,
+					 ATTR_VALUE_COLOR, ATTR_VALUE_DATE, ATTR_VALUE_DATETIME, ATTR_VALUE_DATETIME_LOCAL, ATTR_VALUE_EMAIL, ATTR_VALUE_MONTH, ATTR_VALUE_NUMBER_STRING, ATTR_VALUE_RANGE, ATTR_VALUE_SEARCH, ATTR_VALUE_TEL, ATTR_VALUE_TIME};
+			atype.setEnumValues(values);
+			atype.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, ATTR_VALUE_TEXT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_TYPE, atype, CMAttributeDeclaration.OPTIONAL);
+			attributes.putNamedItem(ATTR_NAME_TYPE, attr);
+
+			// (size CDATA #IMPLIED) ... should be defined locally.
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_SIZE, atype, CMAttributeDeclaration.OPTIONAL);
+			attributes.putNamedItem(ATTR_NAME_SIZE, attr);
+
+			// (alt CDATA #IMPLIED) ... should be defined locally.
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ALT, atype, CMAttributeDeclaration.OPTIONAL);
+			attributes.putNamedItem(ATTR_NAME_ALT, attr);
+			
+			
+			// (type %autocomeplete; ) ... should be defined locally.
+			// NOTE: %autocomeplete is ENUM;
+			// (on | off)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] autoCompleteValues = {ATTR_VALUE_ON, ATTR_VALUE_OFF};
+			atype.setEnumValues(autoCompleteValues);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_AUTOCOMPLETE, atype, CMAttributeDeclaration.OPTIONAL);
+			attributes.putNamedItem(ATTR_NAME_AUTOCOMPLETE, attr);
+
+			
+			// (form CDATA #IMPLIED) ... should be defined locally.
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_FORM, atype, CMAttributeDeclaration.OPTIONAL);
+			attributes.putNamedItem(ATTR_NAME_FORM, attr);
+			
+			
+			// (formaction URI #IMPLIED) ... should be defined locally.
+			atype = new HTMLCMDataTypeImpl(CMDataType.URI);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_FORMACTION, atype, CMAttributeDeclaration.OPTIONAL);
+			attributes.putNamedItem(ATTR_NAME_FORMACTION, attr);
+
+			
+			// (type %formmethod; GET) ... should be defined locally.
+			// NOTE: %formmethod is ENUM;
+			// (GET|POST|PUT|DELETE)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] formMethodValues = {ATTR_VALUE_GET, ATTR_VALUE_POST, ATTR_VALUE_PUT, ATTR_VALUE_DELETE};
+			atype.setEnumValues(formMethodValues);
+			atype.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, ATTR_VALUE_GET);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_FORMMETHOD, atype, CMAttributeDeclaration.OPTIONAL);
+			attributes.putNamedItem(ATTR_NAME_FORMMETHOD, attr);
+
+			// (type %formenctype; GET) ... should be defined locally.
+			// NOTE: %formenctype is ENUM;
+			// (application/x-www-form-urlencoded| multipart/form-data| text/plain)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] formEncTypeValues = {ATTR_VALUE_WWW_FORM_URLENCODED, ATTR_VALUE_FORM_DATA, ATTR_VALUE_PLAIN};
+			atype.setEnumValues(formEncTypeValues);
+			atype.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, ATTR_VALUE_WWW_FORM_URLENCODED);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_FORMENCTYPE, atype, CMAttributeDeclaration.OPTIONAL);
+			attributes.putNamedItem(ATTR_NAME_FORMENCTYPE, attr);
+
+			// (formtarget BROWSEING CONTEXT #IMPLIED) ... should be defined locally.
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.BROWSING_CONTEXT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_FORMTARGET, atype, CMAttributeDeclaration.OPTIONAL);
+			attributes.putNamedItem(ATTR_NAME_FORMTARGET, attr);
+			
+			// (formtnovalidate  #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			// boolean attribute must have the same value as its name.
+			String[] formNoValidateValues = {ATTR_NAME_FORMNOVALIDATE};
+			atype.setEnumValues(formNoValidateValues);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_FORMNOVALIDATE, atype, CMAttributeDeclaration.OPTIONAL);
+			attributes.putNamedItem(ATTR_NAME_FORMNOVALIDATE, attr);
+
+		
+			// (list ID #IMPLIED) ... should be defined locally.
+			atype = new HTMLCMDataTypeImpl(CMDataType.ID);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_LIST, atype, CMAttributeDeclaration.OPTIONAL);
+			attributes.putNamedItem(ATTR_NAME_LIST, attr);
+
+			// (min CDATA #IMPLIED) ... should be defined locally.
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_MIN, atype, CMAttributeDeclaration.OPTIONAL);
+			attributes.putNamedItem(ATTR_NAME_MIN, attr);
+
+			// (max CDATA #IMPLIED) ... should be defined locally.
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_MAX, atype, CMAttributeDeclaration.OPTIONAL);
+			attributes.putNamedItem(ATTR_NAME_MAX, attr);
+
+			// (maxlength NUMBER #IMPLIED) ... should be defined locally.
+			atype = new HTMLCMDataTypeImpl(CMDataType.NUMBER);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_MAXLENGTH, atype, CMAttributeDeclaration.OPTIONAL);
+			attributes.putNamedItem(ATTR_NAME_MAXLENGTH, attr);
+
+			// (multiple  #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			// boolean attribute must have the same value as its name.
+			String[] multipleValues = {ATTR_NAME_MULTIPLE};
+			atype.setEnumValues(multipleValues);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_MULTIPLE, atype, CMAttributeDeclaration.OPTIONAL);
+			attributes.putNamedItem(ATTR_NAME_MULTIPLE, attr);
+
+		
+			// (step CDATA #IMPLIED) ... should be defined locally.
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_STEP, atype, CMAttributeDeclaration.OPTIONAL);
+			attributes.putNamedItem(ATTR_NAME_STEP, attr);
+
+			// (placeholder CDATA #IMPLIED) ... should be defined locally.
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.TEXT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_PLACEHOLDER, atype, CMAttributeDeclaration.OPTIONAL);
+			attributes.putNamedItem(ATTR_NAME_PLACEHOLDER, attr);
+
+			// (pattern CDATA #IMPLIED) ... should be defined locally.
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_PATTERN, atype, CMAttributeDeclaration.OPTIONAL);
+			attributes.putNamedItem(ATTR_NAME_PATTERN, attr);
+
+			// (required  #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			// boolean attribute must have the same value as its name.
+			String[] requiredValues = {ATTR_NAME_REQUIRED};
+			atype.setEnumValues(requiredValues);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_REQUIRED, atype, CMAttributeDeclaration.OPTIONAL);
+			attributes.putNamedItem(ATTR_NAME_REQUIRED, attr);
+
+			String[] names = {ATTR_NAME_NAME, ATTR_NAME_VALUE, ATTR_NAME_CHECKED, ATTR_NAME_DISABLED, ATTR_NAME_READONLY, ATTR_NAME_SIZE, ATTR_NAME_MAXLENGTH, ATTR_NAME_SRC, ATTR_NAME_ALT, ATTR_NAME_ACCEPT, //<<D215684
+						ATTR_NAME_WIDTH, ATTR_NAME_HEIGHT,			//<D215684
+				//html5
+						ATTR_NAME_AUTOFOCUS
+			};
+			getDeclarations(attributes, Arrays.asList(names).iterator());
+			//discouraged
+			// (ismap (ismap) #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] ismapValues = {ATTR_NAME_ISMAP};
+			atype.setEnumValues(ismapValues);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ISMAP, atype, CMAttributeDeclaration.OPTIONAL);
+			attr.obsolete(true);
+			attributes.putNamedItem(ATTR_NAME_ISMAP, attr);
+			
+			// (usemap %URI; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.URI);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_USEMAP, atype, CMAttributeDeclaration.OPTIONAL);
+			attr.obsolete(true);
+			attributes.putNamedItem(ATTR_NAME_USEMAP, attr);
+
+			
+			getDeclarations(attributes, Arrays.asList(names).iterator());
+		}
+		/* (href %URI; #IMPLIED)
+		 * (hreflang %LanguageCode; #IMPLIED)
+		 * (type %ContentType; #IMPLIED): should be defined locally.
+		 * (rel %LinkTypes; #IMPLIED)
+		 * (media %MediaDesc; #IMPLIED)
+		 * // discouraged
+		 * (charset %Charset; #IMPLIED)
+		 * (rev %LinkTypes; #IMPLIED)
+		 * (target %FrameTarget; #IMPLIED)
+		 */
+		else if (elementName.equals(HTML40Namespace.ElementName.LINK)){
+			String[] names = { ATTR_NAME_TYPE, ATTR_NAME_HREF, ATTR_NAME_HREFLANG, ATTR_NAME_REL,  ATTR_NAME_MEDIA};
+			getDeclarations(attributes, Arrays.asList(names).iterator());
+
+			// (sizes %Pixels; #IMPLIED)
+			HTMLCMDataTypeImpl atype = new HTMLCMDataTypeImpl(HTMLCMDataType.PIXELS);
+			HTMLAttrDeclImpl attr = new HTMLAttrDeclImpl(ATTR_NAME_SIZES, atype, CMAttributeDeclaration.OPTIONAL);
+			attributes.putNamedItem(ATTR_NAME_SIZES, attr);
+			
+			//discouraged
+			// (charset %Charset; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.CHARSET);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_CHARSET, atype, CMAttributeDeclaration.OPTIONAL);
+			attr.obsolete(true);
+			attributes.putNamedItem(ATTR_NAME_CHARSET, attr);
+			
+			// (rev %LinkTypes; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.LINK_TYPES);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_REV, atype, CMAttributeDeclaration.OPTIONAL);
+			attr.obsolete(true);
+			attributes.putNamedItem(ATTR_NAME_REV, attr);
+			
+			// (target %FrameTarget; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.FRAME_TARGET);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_TARGET, atype, CMAttributeDeclaration.OPTIONAL);
+			attr.obsolete(true);
+			attributes.putNamedItem(ATTR_NAME_TARGET, attr);
+			
+		}
+		/* (type %ContentType; #IMPLIED)
+		 * (href %URI; #IMPLIED)
+		 * (hreflang %LanguageCode; #IMPLIED)
+		 * (target %FrameTarget; #IMPLIED)
+		 * (rel %LinkTypes; #IMPLIED)
+		 * (media %media_desc; #IMPLIED
+		 * //discouraged
+		 * (charset %Charset; #IMPLIED)
+		 * (name CDATA #IMPLIED)
+		 * (rev %LinkTypes; #IMPLIED)
+		 * (directkey %Character; #IMPLIED)
+		 * (shape %Shape; rect)
+		 * (coords %Coords; #IMPLIED)
+		 */
+		else if (elementName.equals(HTML40Namespace.ElementName.A)){
+			String[] names = { ATTR_NAME_MEDIA, ATTR_NAME_TYPE, ATTR_NAME_HREF, ATTR_NAME_HREFLANG, ATTR_NAME_REL, ATTR_NAME_TARGET};
+			getDeclarations(attributes, Arrays.asList(names).iterator());
+			
+			
+			//discouraged
+			// (charset %Charset; #IMPLIED)
+			HTMLCMDataTypeImpl atype = new HTMLCMDataTypeImpl(HTMLCMDataType.CHARSET);
+			HTMLAttrDeclImpl attr = new HTMLAttrDeclImpl(ATTR_NAME_CHARSET, atype, CMAttributeDeclaration.OPTIONAL);
+			attr.obsolete(true);
+			attributes.putNamedItem(ATTR_NAME_CHARSET, attr);
+			
+			// (rev %LinkTypes; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.LINK_TYPES);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_REV, atype, CMAttributeDeclaration.OPTIONAL);
+			attr.obsolete(true);
+			attributes.putNamedItem(ATTR_NAME_REV, attr);
+			
+			// (directkey %Character; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.CHARACTER);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_DIRECTKEY, atype, CMAttributeDeclaration.OPTIONAL);
+			attr.obsolete(true);
+			attributes.putNamedItem(ATTR_NAME_DIRECTKEY, attr);
+			
+			// (shape %Shape; rect): %Shape; is (rect|circle|poly|default).
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_VALUE_RECT, ATTR_VALUE_CIRCLE, ATTR_VALUE_POLY, ATTR_VALUE_DEFAULT};
+			atype.setEnumValues(values);
+			atype.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, ATTR_VALUE_RECT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_SHAPE, atype, CMAttributeDeclaration.OPTIONAL);
+			attr.obsolete(true);
+			attributes.putNamedItem(ATTR_NAME_SHAPE, attr);
+			
+			// (coords %Coords; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.COORDS);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_COORDS, atype, CMAttributeDeclaration.OPTIONAL);
+			attr.obsolete(true);
+			attributes.putNamedItem(ATTR_NAME_COORDS, attr);
+			
+			// (name CDATA #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_NAME, atype, CMAttributeDeclaration.OPTIONAL);
+			attr.obsolete(true);
+			attributes.putNamedItem(ATTR_NAME_NAME, attr);
+	
+		}
+		/*
+		 * (shape %Shape; rect)
+		 * (coords %Coords; #IMPLIED)
+		 * (href %URI; #IMPLIED)
+		 * (target %FrameTarget; #IMPLIED)
+		 * (alt %Text; #REQUIRED)
+		 * (media %media_desc; #IMPLIED)
+		 * (rel %LinkTypes; #IMPLIED)
+		 * (type %ContentType; #IMPLIED)
+		 * //disocuraged
+		 * (nohref (nohref) #IMPLIED)
+		 */
+		else if (elementName.equals(HTML40Namespace.ElementName.AREA)){
+			// (media %MediaDesc; #IMPLIED)
+			String[] names = {ATTR_NAME_TYPE, ATTR_NAME_MEDIA, ATTR_NAME_SHAPE, ATTR_NAME_COORDS, ATTR_NAME_HREF, ATTR_NAME_HREFLANG, ATTR_NAME_TARGET, ATTR_NAME_ALT, ATTR_NAME_REL};
+			getDeclarations(attributes, Arrays.asList(names).iterator());
+			
+			// (nohref (nohref) #IMPLIED)
+			HTMLCMDataTypeImpl atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_NAME_NOHREF};
+			atype.setEnumValues(values);
+			HTMLAttrDeclImpl attr = new HTMLAttrDeclImpl(ATTR_NAME_NOHREF, atype, CMAttributeDeclaration.OPTIONAL);
+			attr.obsolete(true);
+			attributes.putNamedItem(ATTR_NAME_NOHREF, attr);
+		
+		}
+		/*
+		 *  %globalattrs;
+		 * (http-equiv NAME #IMPLIED)
+		 * (name NAME #IMPLIED) ... should be defined locally.
+		 * (content CDATA #REQUIRED)
+		 * (charset %Charset; #IMPLIED)
+		 *  //discouraged
+		 * (scheme CDATA #IMPLIED)
+		 */
+		else if (elementName.equals(HTML40Namespace.ElementName.META)){
+			// globalattrs;
+			getAttrs(attributes);
+
+			// (name NAME #IMPLIED) ... should be defined locally.
+			HTMLCMDataTypeImpl atype = new HTMLCMDataTypeImpl(HTMLCMDataType.NAME);
+			HTMLAttrDeclImpl attr = new HTMLAttrDeclImpl(ATTR_NAME_NAME, atype, CMAttributeDeclaration.OPTIONAL);
+			attributes.putNamedItem(ATTR_NAME_NAME, attr);
+
+			// (content CDATA #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_CONTENT, atype, CMAttributeDeclaration.OPTIONAL);
+			attributes.putNamedItem(ATTR_NAME_CONTENT, attr);
+			
+			String[] names = {ATTR_NAME_HTTP_EQUIV, ATTR_NAME_CHARSET};
+			getDeclarations(attributes, Arrays.asList(names).iterator());
+			
+			// discouraged
+			// (scheme CDATA #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_SCHEME, atype, CMAttributeDeclaration.OPTIONAL);
+			attr.obsolete(true);
+			attributes.putNamedItem(ATTR_NAME_SCHEME, attr);
+			
+		}
+		/*
+		 * (src %URI; #REQUIRED): should be defined locally.
+		 * (alt %Text; #REQUIRED)
+		 * (usemap %URI; #IMPLIED)
+		 * (ismap (ismap) #IMPLIED)
+		 *  // discouraged
+		 * (longdesc %URI; #IMPLIED)
+		 * (name CDATA #IMPLIED)
+		 * (height %Length; #IMPLIED)
+		 * (width %Length; #IMPLIED)
+		 * (align %IAlign; #IMPLIED): should be defined locally.
+		 * (border %Pixels; #IMPLIED)
+		 * (hspace %Pixels; #IMPLIED)
+		 * (vspace %Pixels; #IMPLIED)
+		 * (mapfile %URI; #IMPLIED)
+	 
+		 */
+		else if (elementName.equals(HTML40Namespace.ElementName.IMG)){
+			// (src %URI; #REQUIRED): should be defined locally.
+			HTMLCMDataTypeImpl atype = null;
+			HTMLAttrDeclImpl attr = null;
+			atype = new HTMLCMDataTypeImpl(CMDataType.URI);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_SRC, atype, CMAttributeDeclaration.REQUIRED);
+			attributes.putNamedItem(ATTR_NAME_SRC, attr);
+
+			String[] names = {ATTR_NAME_ALT, ATTR_NAME_LONGDESC, ATTR_NAME_NAME, ATTR_NAME_HEIGHT, ATTR_NAME_WIDTH, ATTR_NAME_USEMAP, ATTR_NAME_ISMAP, ATTR_NAME_BORDER, ATTR_NAME_HSPACE, ATTR_NAME_VSPACE, ATTR_NAME_MAPFILE};
+			getDeclarations(attributes, Arrays.asList(names).iterator());
+
+			// align (local); should be defined locally.
+			attr = AttributeCollection.createAlignForImage();
+			attributes.putNamedItem(ATTR_NAME_ALIGN, attr);
+		
+		}
+		/*
+		 * (name CDATA #REQUIRED) ... should be defined locally.
+		 * (value CDATA #IMPLIED)
+		 * global attributes
+		 */
+		else if (elementName.equals(HTML40Namespace.ElementName.PARAM)){
+			
+			// (name CDATA #REQUIRED) ... should be defined locally.
+			HTMLCMDataTypeImpl atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			HTMLAttrDeclImpl attr = new HTMLAttrDeclImpl(ATTR_NAME_NAME, atype, CMAttributeDeclaration.REQUIRED);
+			attributes.putNamedItem(ATTR_NAME_NAME, attr);
+			
+			// (value CDATA #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_VALUE, atype, CMAttributeDeclaration.OPTIONAL);
+			attributes.putNamedItem(ATTR_NAME_VALUE, attr);
+			
+			// gloabl attrs
+			getAttrs(attributes);
+		}
+		/*
+		 * (autofocus Boolean; #IMPLIED)
+		 * (form CDATA; #IMPLIED)
+		 * (placeholder CDATA #IMPLIED)
+		 * (name CDATA #IMPLIED)
+		 * (rows NUMBER #REQUIRED)
+		 * (cols NUMBER #REQUIRED)
+		 * (disabled (disabled) #IMPLIED)
+		 * (readonly (readonly) #IMPLIED)
+		 * (maxlength NUMBER; #IMPLIED)
+		 * (wrap ENUM; #IMPLIED)
+		 *  //discouraged
+		 * (istyle CDATA #IMPLIED)
+		 */
+		else if (elementName.equals(HTML40Namespace.ElementName.TEXTAREA)){
+			String[] names = {ATTR_NAME_MAXLENGTH, ATTR_NAME_FORM, ATTR_NAME_AUTOFOCUS, ATTR_NAME_NAME, ATTR_NAME_ROWS, ATTR_NAME_COLS, ATTR_NAME_DISABLED, ATTR_NAME_READONLY};
+			getDeclarations(attributes, Arrays.asList(names).iterator());
+			
+			// (placeholder CDATA #IMPLIED) ... should be defined locally.
+			HTMLCMDataTypeImpl atype = new HTMLCMDataTypeImpl(HTMLCMDataType.TEXT);
+			HTMLAttrDeclImpl attr = new HTMLAttrDeclImpl(ATTR_NAME_PLACEHOLDER, atype, CMAttributeDeclaration.OPTIONAL);
+			attributes.putNamedItem(ATTR_NAME_PLACEHOLDER, attr);
+			
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_VALUE_SOFT, ATTR_VALUE_HARD};
+			atype.setEnumValues(values);
+			atype.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, ATTR_VALUE_SOFT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_WRAP, atype, CMAttributeDeclaration.OPTIONAL);
+			attributes.putNamedItem(ATTR_NAME_WRAP, attr);
+			
+			// discouraged
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ISTYLE, atype, CMAttributeDeclaration.OPTIONAL);
+			attr.obsolete(true);
+			attributes.putNamedItem(ATTR_NAME_ISTYLE, attr);
+		}
+		/*
+		 * (charset %Charset; #IMPLIED)
+		 * (type %ContentType; #REQUIRED) ... should be defined locally.
+		 * (asynch boolean #IMPLIED)
+		 * (src %URI; #IMPLIED)
+		 * (defer (defer) #IMPLIED)
+		 *  // discouraged
+		 * (language CDATA #IMPLIED)
+		 * (event CDATA #IMPLIED)
+		 * (for %URI; #IMPLIED)
+		 */
+		else if (elementName.equals(HTML40Namespace.ElementName.SCRIPT)){
+			String[] names = {ATTR_NAME_CHARSET,  ATTR_NAME_SRC, ATTR_NAME_DEFER};
+			getDeclarations(attributes, Arrays.asList(names).iterator());
+
+			// (type %ContentType; #REQUIRED) ... should be defined locally.
+			HTMLCMDataTypeImpl atype = new HTMLCMDataTypeImpl(HTMLCMDataType.CONTENT_TYPE);
+			atype.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, "text/javascript"); //$NON-NLS-1$
+			HTMLAttrDeclImpl attr = new HTMLAttrDeclImpl(ATTR_NAME_TYPE, atype, CMAttributeDeclaration.REQUIRED);
+			attributes.putNamedItem(ATTR_NAME_TYPE, attr);
+			
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_NAME_ASYNC};
+			atype.setEnumValues(values);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ASYNC, atype, CMAttributeDeclaration.OPTIONAL);
+			attributes.putNamedItem(ATTR_NAME_ASYNC, attr);
+			
+			
+			// discouraged
+			// (language %CDATA; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_LANGUAGE, atype, CMAttributeDeclaration.OPTIONAL);
+			attr.obsolete(true);
+			attributes.putNamedItem(ATTR_NAME_LANGUAGE, attr);
+			
+			// (event CDATA #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_EVENT, atype, CMAttributeDeclaration.OPTIONAL);
+			attr.obsolete(true);
+			attributes.putNamedItem(ATTR_NAME_EVENT, attr);
+			
+			// (for %URI; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.URI);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_FOR, atype, CMAttributeDeclaration.OPTIONAL);
+			attr.obsolete(true);
+			attributes.putNamedItem(ATTR_NAME_FOR, attr);
+		
+		}
+		/*
+		 *  %attrs;
+		 * (type %ContentType; #REQUIRED) ... should be defined locally.
+		 * (media %MediaDesc; #IMPLIED)
+		 * (scoped boolean; #implied)
+		 */
+		else if (elementName.equals(HTML40Namespace.ElementName.STYLE)){
+			// %i18n;
+			getAttrs(attributes);
+
+			String[] names = {ATTR_NAME_MEDIA};
+			getDeclarations(attributes, Arrays.asList(names).iterator());
+			// (type %ContentType; #REQUIRED) ... should be defined locally.
+			HTMLCMDataTypeImpl atype = new HTMLCMDataTypeImpl(HTMLCMDataType.CONTENT_TYPE);
+			atype.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, "text/css"); //$NON-NLS-1$
+			HTMLAttrDeclImpl attr = new HTMLAttrDeclImpl(ATTR_NAME_TYPE, atype, CMAttributeDeclaration.REQUIRED);
+			attributes.putNamedItem(ATTR_NAME_TYPE, attr);
+			
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_NAME_SCOPED};
+			atype.setEnumValues(values);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_SCOPED, atype, CMAttributeDeclaration.OPTIONAL);
+			attributes.putNamedItem(ATTR_NAME_SCOPED, attr);
+		}
+		/*
+		 * %reserved;
+		 * (name CDATA #IMPLIED)
+		 * (size NUMBER #IMPLIED) ... should be defined locally.
+		 * (multiple (multiple) #IMPLIED)
+		 * (disabled (disabled) #IMPLIED)
+		 * (autofocus Boolean; #IMPLIED)
+		 * (form CDATA; #IMPLIED)
+		 */
+		else if (elementName.equals(HTML40Namespace.ElementName.SELECT)){
+			// (size NUMBER #IMPLIED) ... should be defined locally.
+			HTMLCMDataTypeImpl atype = new HTMLCMDataTypeImpl(CMDataType.NUMBER);
+			HTMLAttrDeclImpl attr = new HTMLAttrDeclImpl(ATTR_NAME_SIZE, atype, CMAttributeDeclaration.OPTIONAL);
+			attributes.putNamedItem(ATTR_NAME_SIZE, attr);
+
+			String[] names = {ATTR_NAME_FORM, ATTR_NAME_AUTOFOCUS,ATTR_NAME_NAME, ATTR_NAME_MULTIPLE, ATTR_NAME_DISABLED, ATTR_NAME_TABINDEX, ATTR_NAME_ONFOCUS, ATTR_NAME_ONBLUR, ATTR_NAME_ONCHANGE};
+			getDeclarations(attributes, Arrays.asList(names).iterator());
+		
+		}
+		/*
+		 * (value NUMBER #IMPLIED) ... should be defined locally.
+		 *  //discouraged
+		 *  (type %LIStyle; #IMPLIED) ... should be defined locally.
+		 */
+		else if (elementName.equals(HTML40Namespace.ElementName.LI)){
+			// (type %LIStyle; #IMPLIED) ... should be defined locally.
+			HTMLCMDataTypeImpl atype = new HTMLCMDataTypeImpl(HTMLCMDataType.LI_STYLE);
+			HTMLAttrDeclImpl attr = new HTMLAttrDeclImpl(ATTR_NAME_TYPE, atype, CMAttributeDeclaration.OPTIONAL);
+			attr.obsolete(true);
+			attributes.putNamedItem(ATTR_NAME_TYPE, attr);
+
+			// (value NUMBER #IMPLIED) ... should be defined locally.
+			atype = new HTMLCMDataTypeImpl(CMDataType.NUMBER);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_VALUE, atype, CMAttributeDeclaration.OPTIONAL);
+			attributes.putNamedItem(ATTR_NAME_VALUE, attr);
+		
+		}
+		/*
+		 * (start NUMBER #IMPLIED)
+		 * (reversed BOOLEAN; IMPLIED)
+		 *   //discouraged
+		 * (type %OLStyle; #IMPLIED) ... should be defined locally.
+		 * (compact (compact) #IMPLIED)
+		 */
+		else if (elementName.equals(HTML40Namespace.ElementName.OL)){
+
+			String[] names = { ATTR_NAME_START};
+			getDeclarations(attributes, Arrays.asList(names).iterator());
+			
+			HTMLCMDataTypeImpl atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_NAME_REVERSED};
+			atype.setEnumValues(values);
+			HTMLAttrDeclImpl attr = new HTMLAttrDeclImpl(ATTR_NAME_REVERSED, atype, CMAttributeDeclaration.OPTIONAL);
+			attributes.putNamedItem(ATTR_NAME_REVERSED, attr);
+			
+			//discouraged 
+			// (type %OLStyle; #IMPLIED) ... should be defined locally.
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.OL_STYLE);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_TYPE, atype, CMAttributeDeclaration.OPTIONAL);
+			attr.obsolete(true);
+			attributes.putNamedItem(ATTR_NAME_TYPE, attr);
+			
+			// (compact (compact) #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] compactValues = {ATTR_NAME_COMPACT};
+			atype.setEnumValues(compactValues);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_COMPACT, atype, CMAttributeDeclaration.OPTIONAL);
+			attr.obsolete(true);
+			attributes.putNamedItem(ATTR_NAME_COMPACT, attr);
+		}
+		/**
+		 * %attrs;
+		 * (src %URI; #IMPLIED)
+		 * (srcdoc %CONTENT_TYPE; #IMPLIED)
+		 * (seamless BOOLEAN; #IMPLIED)
+		 * (sandbox CDATA; #IMPLED)
+		 * (height %Length; #IMPLIED)
+		 * (width %Length; #IMPLIED)
+		 * (name CDATA #IMPLIED)
+		 * //discouraged
+		 * (longdesc %URI; #IMPLIED)
+		 * (frameborder (1|0) 1)
+		 * (marginwidth %Pixels; #IMPLIED)
+		 * (marginheight %Pixels; #IMPLIED)
+		 * (scrolling (yes|no|auto) auto)
+		 * (align %IAlign; #IMPLIED) ... should be defined locally.
+		 */
+		else if (elementName.equals(HTML40Namespace.ElementName.IFRAME)){
+			// %attrs;
+			getAttrs(attributes);
+			
+			//srcdoc
+			HTMLCMDataTypeImpl atype = new HTMLCMDataTypeImpl(HTMLCMDataType.CONTENT_TYPE);
+			HTMLAttrDeclImpl attr = new HTMLAttrDeclImpl(ATTR_NAME_SRCDOC, atype, CMAttributeDeclaration.OPTIONAL);
+			attributes.putNamedItem(ATTR_NAME_SRCDOC, attr);
+
+			// (seamless (seamless) #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] compactValues = {ATTR_NAME_SEAMLESS};
+			atype.setEnumValues(compactValues);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_SEAMLESS, atype, CMAttributeDeclaration.OPTIONAL);
+			attributes.putNamedItem(ATTR_NAME_SEAMLESS, attr);
+		
+			//sandbox
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_SANDBOX, atype, CMAttributeDeclaration.OPTIONAL);
+			attributes.putNamedItem(ATTR_NAME_SANDBOX, attr);
+			
+			
+			String[] names = { ATTR_NAME_NAME, ATTR_NAME_SRC, ATTR_NAME_HEIGHT, ATTR_NAME_WIDTH};
+			getDeclarations(attributes, Arrays.asList(names).iterator());
+
+			//discouraged
+			// (marginwidth %Pixels; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.PIXELS);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_MARGINWIDTH, atype, CMAttributeDeclaration.OPTIONAL);
+			attr.obsolete(true);
+			attributes.putNamedItem(ATTR_NAME_MARGINWIDTH, attr);
+			
+			// (marginheight %Pixels; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.PIXELS);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_MARGINHEIGHT, atype, CMAttributeDeclaration.OPTIONAL);
+			attr.obsolete(true);
+			attributes.putNamedItem(ATTR_NAME_MARGINHEIGHT, attr);
+			
+			// (scrolling (yes|no|auto) auto)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_VALUE_YES, ATTR_VALUE_NO, ATTR_VALUE_AUTO};
+			atype.setEnumValues(values);
+			atype.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, ATTR_VALUE_AUTO);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_SCROLLING, atype, CMAttributeDeclaration.OPTIONAL);
+			attr.obsolete(true);
+			attributes.putNamedItem(ATTR_NAME_SCROLLING, attr);
+
+			// (frameborder (1|0) 1)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] frameValues = {ATTR_VALUE_1, ATTR_VALUE_0};
+			atype.setEnumValues(frameValues);
+			atype.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, ATTR_VALUE_1);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_FRAMEBORDER, atype, CMAttributeDeclaration.OPTIONAL);
+			attr.obsolete(true);
+			attributes.putNamedItem(ATTR_NAME_FRAMEBORDER, attr);
+			
+			// (longdesc %URI; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.URI);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_LONGDESC, atype, CMAttributeDeclaration.OPTIONAL);
+			attr.obsolete(true);
+			attributes.putNamedItem(ATTR_NAME_LONGDESC, attr);
+			
+			
+			// align
+			attr = AttributeCollection.createAlignForImage();
+			if (attr != null)
+				attr.obsolete(true);
+				attributes.putNamedItem(ATTR_NAME_ALIGN, attr);
+		}
+		/*
+		 * (%attrs)
+		 * (manisfest %URI; #IMPLIED)
+		 * (xmlns %URI; #IMPLIED)
+		 * //discouraged
+		 * (version CDATA #FIXED '%HTML.Version;)
+		 */
+		else if (elementName.equals(HTML40Namespace.ElementName.HTML)){
+			// %attrs;
+			getAttrs(attributes);
+			// (manisfest %URI; #IMPLIED)
+			HTMLCMDataTypeImpl atype = new HTMLCMDataTypeImpl(CMDataType.URI);
+			HTMLAttrDeclImpl attr = new HTMLAttrDeclImpl(ATTR_NAME_MANIFEST, atype, CMAttributeDeclaration.OPTIONAL);
+			attributes.putNamedItem(ATTR_NAME_MANIFEST, attr);
+			
+			// (version CDATA #FIXED '%HTML.Version;)
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			atype.setImpliedValue(CMDataType.IMPLIED_VALUE_FIXED, ATTR_VALUE_VERSION_TRANSITIONAL);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_VERSION, atype, CMAttributeDeclaration.FIXED);
+			attr.obsolete(true);
+			attributes.putNamedItem(ATTR_NAME_VERSION, attr);
+			
+			// (xmlns CDATA #FIXED '%xmlns;)
+			atype = new HTMLCMDataTypeImpl(CMDataType.URI);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_XMLNS, atype, CMAttributeDeclaration.OPTIONAL);
+			attributes.putNamedItem(ATTR_NAME_XMLNS, attr);
+		}
+		/*
+		 * (type enum; (context | toolbar | list))
+		 * (label %Text; #IMPLIED)
+		 *  //discouraged
+		 * (compact (compact) #IMPLIED)
+	 	 */
+		else if (elementName.equals(HTML40Namespace.ElementName.MENU)){
+			// (type %menuType; list) ... should be defined locally is ENUM.
+			//  (context | toolbar | list)
+			HTMLCMDataTypeImpl atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_VALUE_CONTEXT, ATTR_VALUE_TOOLBAR, ATTR_VALUE_LIST};
+			atype.setEnumValues(values);
+			atype.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, ATTR_VALUE_LIST);
+			HTMLAttrDeclImpl attr = new HTMLAttrDeclImpl(ATTR_NAME_TYPE, atype, CMAttributeDeclaration.OPTIONAL);
+			attributes.putNamedItem(ATTR_NAME_TYPE, attr);
+
+			// (label %Text; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.TEXT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_LABEL, atype, CMAttributeDeclaration.OPTIONAL);
+			attributes.putNamedItem(ATTR_NAME_LABEL, attr);
+
+			// (compact (compact) #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] compactValues = {ATTR_NAME_COMPACT};
+			atype.setEnumValues(compactValues);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_COMPACT, atype, CMAttributeDeclaration.OPTIONAL);
+			attr.obsolete(true);
+			attributes.putNamedItem(ATTR_NAME_COMPACT, attr);
+		}
+		/*
+		 * (type %button; TEXT) ... should be defined locally.
+		 * (name CDATA #IMPLIED)
+		 * (value CDATA #IMPLIED)
+		 * (disabled (disabled) #IMPLIED)
+		 * (autofocus Boolean; #IMPLIED)
+		 * (form CDATA; #IMPLIED)
+		 * (formaction)
+		 * (formenctype)
+		 * (formmethod)
+		 * (formnovalidate)
+		 * (formtarget)
+		 */
+		else if (elementName.equals(HTML40Namespace.ElementName.BUTTON)){
+			// (type (button|submit|reset) submit) ... should be defined locally.
+			HTMLCMDataTypeImpl atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_VALUE_BUTTON, ATTR_VALUE_SUBMIT, ATTR_VALUE_RESET};
+			atype.setEnumValues(values);
+			HTMLAttrDeclImpl attr = new HTMLAttrDeclImpl(ATTR_NAME_TYPE, atype, CMAttributeDeclaration.OPTIONAL);
+			attributes.putNamedItem(ATTR_NAME_TYPE, attr);
+			
+
+			String[] names = {ATTR_NAME_NAME, ATTR_NAME_VALUE, ATTR_NAME_DISABLED,
+				//html5
+						ATTR_NAME_AUTOFOCUS
+			};
+			getDeclarations(attributes, Arrays.asList(names).iterator());
+			
+			// (form CDATA #IMPLIED) ... should be defined locally.
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_FORM, atype, CMAttributeDeclaration.OPTIONAL);
+			attributes.putNamedItem(ATTR_NAME_FORM, attr);
+			
+			
+			// (formaction URI #IMPLIED) ... should be defined locally.
+			atype = new HTMLCMDataTypeImpl(CMDataType.URI);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_FORMACTION, atype, CMAttributeDeclaration.OPTIONAL);
+			attributes.putNamedItem(ATTR_NAME_FORMACTION, attr);
+
+			
+			// (type %formmethod; GET) ... should be defined locally.
+			// NOTE: %formmethod is ENUM;
+			// (GET|POST|PUT|DELETE)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] formMethodValues = {ATTR_VALUE_GET, ATTR_VALUE_POST, ATTR_VALUE_PUT, ATTR_VALUE_DELETE};
+			atype.setEnumValues(formMethodValues);
+			atype.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, ATTR_VALUE_GET);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_FORMMETHOD, atype, CMAttributeDeclaration.OPTIONAL);
+			attributes.putNamedItem(ATTR_NAME_FORMMETHOD, attr);
+
+			// (type %formenctype; GET) ... should be defined locally.
+			// NOTE: %formenctype is ENUM;
+			// (application/x-www-form-urlencoded| multipart/form-data| text/plain)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] formEncTypeValues = {ATTR_VALUE_WWW_FORM_URLENCODED, ATTR_VALUE_FORM_DATA, ATTR_VALUE_PLAIN};
+			atype.setEnumValues(formEncTypeValues);
+			atype.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, ATTR_VALUE_WWW_FORM_URLENCODED);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_FORMENCTYPE, atype, CMAttributeDeclaration.OPTIONAL);
+			attributes.putNamedItem(ATTR_NAME_FORMENCTYPE, attr);
+
+			// (formtarget BROWSEING CONTEXT #IMPLIED) ... should be defined locally.
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.BROWSING_CONTEXT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_FORMTARGET, atype, CMAttributeDeclaration.OPTIONAL);
+			attributes.putNamedItem(ATTR_NAME_FORMTARGET, attr);
+			
+			// (formtnovalidate  #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			// boolean attribute must have the same value as its name.
+			String[] formNoValidateValues = {ATTR_NAME_FORMNOVALIDATE};
+			atype.setEnumValues(formNoValidateValues);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_FORMNOVALIDATE, atype, CMAttributeDeclaration.OPTIONAL);
+			attributes.putNamedItem(ATTR_NAME_FORMNOVALIDATE, attr);
+
+		}
+		/*
+		 * (name CDATA #IMPLIED)
+		 * (disabled (disabled) #IMPLIED)
+		 * (form CDATA; #IMPLIED)
+		 */
+		else if (elementName.equals(HTML40Namespace.ElementName.FIELDSET)){
+			// (form CDATA #IMPLIED) ... should be defined locally.
+			HTMLCMDataTypeImpl atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			HTMLAttrDeclImpl attr = new HTMLAttrDeclImpl(ATTR_NAME_FORM, atype, CMAttributeDeclaration.OPTIONAL);
+			attributes.putNamedItem(ATTR_NAME_FORM, attr);
+			
+			String[] names = {ATTR_NAME_NAME, ATTR_NAME_DISABLED };
+			getDeclarations(attributes, Arrays.asList(names).iterator());
+				
+		}
+		/*
+		 * (summary %Text; #IMPLIED)
+		 *  //discouraged
+		 * %reserved;
+		 * (width %Length; #IMPLIED)
+		 * (border %Pixels; #IMPLIED)
+		 * (frame %TFrame; #IMPLIED)
+		 * (rules %TRules; #IMPLIED)
+		 * (cellspacing %Length; #IMPLIED)
+		 * (cellpadding %Length; #IMPLIED)
+		 * (align %TAlign; #IMPLIED)
+		 * (bgcolor %Color; #IMPLIED)
+		 * (datapagesize CDATA #IMPLIED)
+		 * (height %Pixels; #IMPLIED)
+		 * (background %URI; #IMPLIED)
+		 * (bordercolor %Color #IMPLIED) ... D205514
+		 */
+		else if (elementName.equals(HTML40Namespace.ElementName.TABLE)){
+			// %reserved;
+			// ... %reserved; is empty in the current DTD.
+
+			String[] names = {ATTR_NAME_SUMMARY};
+			getDeclarations(attributes, Arrays.asList(names).iterator());
+
+			// align (local)
+			HTMLCMDataTypeImpl atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] alignValues = {ATTR_VALUE_LEFT, ATTR_VALUE_CENTER, ATTR_VALUE_RIGHT};
+			atype.setEnumValues(alignValues);
+			HTMLAttrDeclImpl attr = new HTMLAttrDeclImpl(ATTR_NAME_ALIGN, atype, CMAttributeDeclaration.OPTIONAL);
+			attr.obsolete(true);
+			attributes.putNamedItem(ATTR_NAME_ALIGN, attr);
+			
+			// (width %Length; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.LENGTH);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_WIDTH, atype, CMAttributeDeclaration.OPTIONAL);
+			attr.obsolete(true);
+			attributes.putNamedItem(ATTR_NAME_WIDTH, attr);
+			
+			// (border %Pixels; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.PIXELS);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_BORDER, atype, CMAttributeDeclaration.OPTIONAL);
+			attr.obsolete(true);
+			attributes.putNamedItem(ATTR_NAME_BORDER, attr);
+			
+			// (frame %TFrame; #IMPLIED)
+			// %TFrame; is
+			// (void|above|below|hsides|lhs|rhs|vsides|box|border).
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_VALUE_VOID, ATTR_VALUE_ABOVE, ATTR_VALUE_BELOW, ATTR_VALUE_HSIDES, ATTR_VALUE_LHS, ATTR_VALUE_RHS, ATTR_VALUE_VSIDES, ATTR_VALUE_BOX, ATTR_VALUE_BORDER};
+			atype.setEnumValues(values);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_FRAME, atype, CMAttributeDeclaration.OPTIONAL);
+			attr.obsolete(true);
+			attributes.putNamedItem(ATTR_NAME_FRAME, attr);
+			
+			// (rules %TRules; #IMPLIED)
+			// %TRules; is (none | groups | rows | cols | all).
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] ruleValues = {ATTR_VALUE_NONE, ATTR_VALUE_GROUPS, ATTR_VALUE_ROWS, ATTR_VALUE_COLS, ATTR_VALUE_ALL};
+			atype.setEnumValues(ruleValues);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_RULES, atype, CMAttributeDeclaration.OPTIONAL);
+			attr.obsolete(true);
+			attributes.putNamedItem(ATTR_NAME_RULES, attr);
+			
+			// (cellspacing %Length; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.LENGTH);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_CELLSPACING, atype, CMAttributeDeclaration.OPTIONAL);
+			attr.obsolete(true);
+			attributes.putNamedItem(ATTR_NAME_CELLSPACING, attr);
+			
+			// (cellpadding %Length; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.LENGTH);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_CELLPADDING, atype, CMAttributeDeclaration.OPTIONAL);
+			attr.obsolete(true);
+			attributes.putNamedItem(ATTR_NAME_CELLPADDING, attr);
+			
+			// (bgcolor %Color; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.COLOR);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_BGCOLOR, atype, CMAttributeDeclaration.OPTIONAL);
+			attr.obsolete(true);
+			attributes.putNamedItem(ATTR_NAME_BGCOLOR, attr);
+			
+			// (datapagesize CDATA #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_DATAPAGESIZE, atype, CMAttributeDeclaration.OPTIONAL);
+			attr.obsolete(true);
+			attributes.putNamedItem(ATTR_NAME_DATAPAGESIZE, attr);
+			
+			// (height %Length; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.LENGTH);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_HEIGHT, atype, CMAttributeDeclaration.OPTIONAL);
+			attr.obsolete(true);
+			attributes.putNamedItem(ATTR_NAME_HEIGHT, attr);
+			
+			// (background %URI; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.URI);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_BACKGROUND, atype, CMAttributeDeclaration.OPTIONAL);
+			attr.obsolete(true);
+			attributes.putNamedItem(ATTR_NAME_BACKGROUND, attr);
+			
+			// (bordercolor, %Color; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.COLOR);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_BORDERCOLOR, atype, CMAttributeDeclaration.OPTIONAL);
+			attr.obsolete(true);
+			attributes.putNamedItem(ATTR_NAME_BORDERCOLOR, attr);
+			
+			
+		}
+	}
+	
+	public static String[] getGlobalAttributeList(){
+		return CORE;
+	}
+	
+	public static String[] getGlobalEventList(){
+		return EVENTS;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HTML5ElementCollection.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HTML5ElementCollection.java
new file mode 100644
index 0000000..9e2d4b8
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HTML5ElementCollection.java
@@ -0,0 +1,577 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.lang.reflect.Field;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Vector;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML50Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ * Factory for element declarations.
+ */
+class HTML5ElementCollection extends ElementCollection implements org.eclipse.wst.html.core.internal.provisional.HTML50Namespace.ElementName {
+
+
+	// Element IDs
+	private static class Ids50 extends Ids {
+		// <<D205513
+		
+		public static final int ID_ARTICLE =106;
+		public static final int ID_ASIDE =107;
+		public static final int ID_AUDIO =108;
+		public static final int ID_CANVAS =109;
+		public static final int ID_COMMAND =110;
+		public static final int ID_DATALIST =111;
+		public static final int ID_DETAILS = 112;
+		public static final int ID_FIGURE =113;
+		public static final int ID_FIGCAPTION = 114;
+		public static final int ID_FOOTER =115;
+		public static final int ID_HEADER = 116;
+		public static final int ID_HGROUP =117;
+		public static final int ID_KEYGEN =118;
+		public static final int ID_MARK =119;
+		public static final int ID_MATH =120;
+		public static final int ID_METER =121;
+		public static final int ID_NAV =122;
+		public static final int ID_OUTPUT =123;
+		public static final int ID_PROGRESS =124;
+		public static final int ID_RP = 125;
+		public static final int ID_RT = 126;
+		public static final int ID_RUBY =127;
+		public static final int ID_SECTION =128;
+		public static final int ID_SOURCE = 129;
+		public static final int ID_SUMMARY = 130;
+		public static final int ID_SVG =131;
+		public static final int ID_TIME =132;
+		public static final int ID_VIDEO =133;
+
+		// D205513
+
+		public static int getNumOfIds() {
+			if (numofids != -1)
+				return numofids;
+
+			// NOTE: If the reflection is too slow, this method should
+			// just return the literal value, like 105.
+			// -- 5/25/2001
+			Class clazz = Ids50.class;
+			Field[] fields = clazz.getFields();
+			numofids = 0;
+			for (int i = 0; i < fields.length; i++) {
+				String name = fields[i].getName();
+				if (name.startsWith("ID_"))//$NON-NLS-1$
+					numofids++;
+			}
+			return numofids;
+		}
+
+		// chache the result of the reflection.
+		private static int numofids = -1;
+	}
+
+	/** %fontstyle;. TT | I | B | U | S | STRIKE | BIG | SMALL | BLINK */
+	private static final String[] FONTSTYLE = {TT, I, B, U, S, STRIKE, BIG, SMALL, BLINK};
+	/** %formctl;. INPUT | SELECT | TEXTAREA | LABEL | BUTTON */
+	private static final String[] FORMCTL = {INPUT, SELECT, TEXTAREA, LABEL, BUTTON, DATALIST};
+	/** %phrase;.
+	 * EM | STRONG | DFN | CODE | SAMP | KBD | VAR | CITE | ABBR | ACRONYM | MARK
+	 */	private static final String[] PHRASE = {KEYGEN, EM, STRONG, DFN, CODE, SAMP, KBD, VAR, CITE, ABBR, ACRONYM, MARK};
+	/** %special;.
+	 * A | IMG | APPLET | OBJECT | FONT | BASEFONT | BR | SCRIPT |
+	 * MAP | Q | SUB | SUP | SPAN | BDO | IFRAME | EMBED | MARQUEE |
+	 * D2W | SUBMIT
+	 * WBR | NOBR | BGSOUND
+	 */
+	private static final String[] SPECIAL = {A, IMG, APPLET, OBJECT, FONT, BASEFONT, BR, WBR, // D205513
+				SCRIPT, MAP, Q, SUB, SUP, SPAN, BDO, IFRAME, EMBED, BGSOUND, // D205513
+				MARQUEE, NOBR, // D205513
+				OUTPUT, TIME, METER, PROGRESS,
+				COMMAND
+	};
+	/** %heading;. H[1-6] */
+	private static final String[] HEADING = {H1, H2, H3, H4, H5, H6};
+	/** %list;. UL | OL | DIR | MENU */
+	private static final String[] LIST = {UL, OL, DIR, MENU};
+	/** %preformatted;. PRE */
+	private static final String[] PREFORMATTED = {PRE};
+	/** %sectioning;. ARTICLE | ASIDE | NAV | SECTION */
+	private static final String[] SECTIONING = { ARTICLE, ASIDE, NAV, SECTION };
+
+	/** %embedded;. AUDIO|CANVAS|EMBED|IFRAME|IMG|MATH|OBJECT|SVG|VIDEO */
+	private static final String[] EMBEDDED = { AUDIO, CANVAS, EMBED, IFRAME, IMG, MATH, OBJECT, SVG, VIDEO};
+
+    private static String[] fNames = null;
+
+	/**
+	 */
+	public HTML5ElementCollection(AttributeCollection collection) {
+		super(getNames(), collection);
+		attributeCollection = collection;
+	}
+
+	/**
+	 * Actually creates HTMLElementDeclaration instance.
+	 * @return HTMLElementDeclaration
+	 */
+	protected CMNode create(String elementName) {
+		CMNode edec = null;
+
+		if (elementName.equalsIgnoreCase(ACRONYM)) {
+			edec = new HedPhrase(ACRONYM, this);
+			((HTMLElemDeclImpl) edec).obsolete(true);
+		}
+		else if (elementName.equalsIgnoreCase(APPLET)) {
+			edec = new HedAPPLET(this);
+			((HTMLElemDeclImpl) edec).obsolete(true);
+		}
+		else if (elementName.equalsIgnoreCase(ARTICLE)) {
+			edec = new HedSectioning(ARTICLE, this);
+
+		}
+		else if (elementName.equalsIgnoreCase(ASIDE)) {
+			edec = new HedSectioning(ASIDE, this);
+
+		}
+		else if (elementName.equalsIgnoreCase(AUDIO)) {
+			edec = new HedMediaElement(AUDIO, this);
+
+		}
+		else if (elementName.equalsIgnoreCase(BASEFONT)) {
+			edec = new HedBASEFONT(this);
+			((HTMLElemDeclImpl) edec).obsolete(true);
+		}
+		else if (elementName.equalsIgnoreCase(BIG)) {
+			edec = new HedFontStyle(BIG, this);
+			((HTMLElemDeclImpl) edec).obsolete(true);
+		}
+		else if (elementName.equalsIgnoreCase(CANVAS)) {
+			edec = new HedCANVAS(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(CENTER)) {
+			edec = new HedCENTER(this);
+			((HTMLElemDeclImpl) edec).obsolete(true);
+		}
+		else if (elementName.equalsIgnoreCase(COMMAND)) {
+			edec = new HedCOMMAND(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(DATALIST)) {
+			edec = new HedDATALIST(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(DETAILS)) {
+			edec = new HedDETAILS(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(DIR)) {
+			edec = new HedMENU(DIR, this);
+			((HTMLElemDeclImpl) edec).obsolete(true);
+		}
+		else if (elementName.equalsIgnoreCase(FIGCAPTION)) {
+			edec = new HedFIGCAPTION(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(FIGURE)) {
+			edec = new HedFIGURE(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(FOOTER)) {
+			edec = new HedHEADER(HTML50Namespace.ElementName.FOOTER ,this);
+
+		}
+		else if (elementName.equalsIgnoreCase(FRAME)) {
+			edec = new HedFRAME(this);
+			((HTMLElemDeclImpl) edec).obsolete(true);
+		}
+		else if (elementName.equalsIgnoreCase(FRAMESET)) {
+			edec = new HedFRAMESET(this);
+			((HTMLElemDeclImpl) edec).obsolete(true);
+		}
+		else if (elementName.equalsIgnoreCase(HEADER)) {
+			edec = new HedHEADER(HTML50Namespace.ElementName.HEADER ,this);
+		}
+		else if (elementName.equalsIgnoreCase(HGROUP)) {
+			edec = new HedHGROUP(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(ISINDEX)) {
+			edec = new HedISINDEX(this);
+			((HTMLElemDeclImpl) edec).obsolete(true);
+		}
+		else if (elementName.equalsIgnoreCase(KEYGEN)) {
+			edec = new HedKEYGEN(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(MARK)) {
+			edec = new HedPhrase(HTML50Namespace.ElementName.MARK,this);
+
+		}
+		else if (elementName.equalsIgnoreCase(MATH)) {
+			edec = new HedMath(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(METER)) {
+			edec = new HedMETER(this);
+		}
+		else if (elementName.equalsIgnoreCase(NAV)) {
+			edec = new HedSectioning(NAV, this);
+		}
+		else if (elementName.equalsIgnoreCase(NOFRAMES)) {
+			edec = new HedNOFRAMES(this);
+			((HTMLElemDeclImpl) edec).obsolete(true);
+		}
+		else if (elementName.equalsIgnoreCase(OUTPUT)) {
+			edec = new HedOUTPUT(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(PROGRESS)) {
+			edec = new HedPROGRESS(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(RP)) {
+			edec = new HedRP(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(RT)) {
+			edec = new HedRT(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(RUBY)) {
+			edec = new HedRUBY(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(S)) {
+			edec = new HedFontStyle(S, this);
+			((HTMLElemDeclImpl) edec).obsolete(true);
+		}
+		else if (elementName.equalsIgnoreCase(SECTION)) {
+			edec = new HedSectioning(SECTION, this);
+
+		}
+		else if (elementName.equalsIgnoreCase(SOURCE)) {
+			edec = new HedSOURCE(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(STRIKE)) {
+			edec = new HedFontStyle(STRIKE, this);
+			((HTMLElemDeclImpl) edec).obsolete(true);
+		}
+		else if (elementName.equalsIgnoreCase(SUMMARY)) {
+			edec = new HedSUMMARY(this);
+		}
+		else if (elementName.equalsIgnoreCase(SVG)) {
+			edec = new HedSVG(this);
+		}
+		else if (elementName.equalsIgnoreCase(TIME)) {
+			edec = new HedTIME(this);
+		}
+		else if (elementName.equalsIgnoreCase(TT)) {
+			edec = new HedFontStyle(TT, this);
+			((HTMLElemDeclImpl) edec).obsolete(true);
+		}
+		else if (elementName.equalsIgnoreCase(U)) {
+			edec = new HedFontStyle(U, this);
+			((HTMLElemDeclImpl) edec).obsolete(true);
+		}
+		else if (elementName.equalsIgnoreCase(VIDEO)) {
+			edec = new HedVIDEO(this);
+
+		}
+		// unknown
+		else {
+			// NOTE: We don't define the UNKNOWN element declaration.
+			// <code>null</code> for a declaration is a sign of
+			// the target element is unknown.
+			// -- 3/9/2001
+			edec = super.create(elementName);
+		}
+		return edec;
+	}
+
+	public AttributeCollection getAttributeCollection() {
+		return attributeCollection;
+	}
+
+	public final Collection getNamesOfBlock() {
+		// P, DL, DIV, CENTER, NOSCRIPT, NOFRAMES, BLOCKQUOTE, FORM, ISINDEX, HR,
+		// TABLE, FIELDSET, ADDRESS, RUBY, FIGURE
+		String[] blockMisc = {HEADER, FOOTER, HGROUP, P, DL, DIV, CENTER, NOSCRIPT, NOFRAMES, BLOCKQUOTE, FORM, ISINDEX, HR, TABLE, FIELDSET, ADDRESS, RUBY, FIGURE};
+		Vector names = new Vector(Arrays.asList(blockMisc));
+		// %heading;
+		names.addAll(Arrays.asList(HEADING));
+		// %list;
+		names.addAll(Arrays.asList(LIST));
+		// %preformatted;
+		names.addAll(Arrays.asList(PREFORMATTED));
+
+		
+		return names;
+	}
+
+	
+	public final void getSectioning(CMGroupImpl group) {
+		if (group == null)
+			return;
+		getDeclarations(group, Arrays.asList(SECTIONING).iterator());
+	}
+	
+	public void getEmbedded(CMGroupImpl group) {
+		if (group == null)
+			return;
+		getDeclarations(group, Arrays.asList(EMBEDDED).iterator());
+	}
+
+	public void getFlow(CMGroupImpl group) {
+		if (group == null)
+			return;
+		super.getFlow(group);
+		getSectioning(group);
+		CMNode node = getNamedItem(DETAILS);
+		if (node != null) {
+			group.appendChild(node);
+		}
+	}
+
+	public void getInline(CMGroupImpl group) {
+		if (group == null)
+			return;
+		super.getInline(group);
+		getEmbedded(group);
+	}
+
+	/**
+	 * Create element declarations and store them into a <code>CMGroupImpl</code>
+	 * instance.<br>
+	 * @param group CMGroupImpl Return values.
+	 */
+	public final void getFontstyle(CMGroupImpl group) {
+		if (group == null)
+			return;
+		getDeclarations(group, Arrays.asList(FONTSTYLE).iterator());
+	}
+
+	/**
+	 * Create element declarations and store them into a <code>CMGroupImpl</code>
+	 * instance.<br>
+	 * @param group CMGroupImpl Return values.
+	 */
+	public final void getFormctrl(CMGroupImpl group) {
+		if (group == null)
+			return;
+		getDeclarations(group, Arrays.asList(FORMCTL).iterator());
+	}
+
+	/**
+	 * %heading;.
+	 * @param group CMGroupImpl Return values.
+	 */
+	public final void getHeading(CMGroupImpl group) {
+		if (group == null)
+			return;
+
+		getDeclarations(group, Arrays.asList(HEADING).iterator());
+	}
+
+	
+
+	/**
+	 * %list;.
+	 * @param group CMGroupImpl Return values.
+	 */
+	public final void getList(CMGroupImpl group) {
+		if (group == null)
+			return;
+
+		getDeclarations(group, Arrays.asList(LIST).iterator());
+	}
+
+	/**
+	 * Create element declarations and store them into a <code>CMGroupImpl</code>
+	 * instance.<br>
+	 * @param group CMGroupImpl Return values.
+	 */
+	public final void getPhrase(CMGroupImpl group) {
+		if (group == null)
+			return;
+		getDeclarations(group, Arrays.asList(PHRASE).iterator());
+	}
+
+	/**
+	 * %preformatted;
+	 * @param group CMGroupImpl Return values.
+	 */
+	public final void getPreformatted(CMGroupImpl group) {
+		if (group == null)
+			return;
+
+		getDeclarations(group, Arrays.asList(PREFORMATTED).iterator());
+	}
+
+	/**
+	 * Create element declarations and store them into a <code>CMGroupImpl</code>
+	 * instance.<br>
+	 * @param group CMGroupImpl Return values.
+	 */
+	public final void getSpecial(CMGroupImpl group) {
+		if (group == null)
+			return;
+		getDeclarations(group, Arrays.asList(SPECIAL).iterator());
+	}
+
+	private static String[] getNames() {
+		if (fNames == null) {
+			fNames = new String[Ids50.getNumOfIds()];
+			fNames[Ids.ID_A] = A;
+			fNames[Ids.ID_ABBR] = ABBR;
+			fNames[Ids.ID_ACRONYM] = ACRONYM;
+			fNames[Ids.ID_ADDRESS] = ADDRESS;
+			fNames[Ids.ID_APPLET] = APPLET;
+			fNames[Ids.ID_AREA] = AREA;
+			fNames[Ids50.ID_ARTICLE] = ARTICLE;
+			fNames[Ids50.ID_ASIDE] = ASIDE;
+			fNames[Ids50.ID_AUDIO] = AUDIO;
+			fNames[Ids.ID_B] = B;
+			fNames[Ids.ID_BASE] = BASE;
+			fNames[Ids.ID_BASEFONT] = BASEFONT;
+			fNames[Ids.ID_BDO] = BDO;
+			fNames[Ids.ID_BIG] = BIG;
+			fNames[Ids.ID_BLINK] = BLINK;
+			fNames[Ids.ID_BLOCKQUOTE] = BLOCKQUOTE;
+			fNames[Ids.ID_BODY] = BODY;
+			fNames[Ids.ID_BR] = BR;
+			fNames[Ids.ID_BUTTON] = BUTTON;
+			fNames[Ids.ID_CAPTION] = CAPTION;
+			fNames[Ids50.ID_CANVAS] = CANVAS;
+			fNames[Ids.ID_CENTER] = CENTER;
+			fNames[Ids.ID_CITE] = CITE;
+			fNames[Ids.ID_CODE] = CODE;
+			fNames[Ids.ID_COL] = COL;
+			fNames[Ids.ID_COLGROUP] = COLGROUP;
+			fNames[Ids50.ID_COMMAND] = COMMAND;
+			fNames[Ids50.ID_DATALIST] = DATALIST;
+			fNames[Ids50.ID_DETAILS] = DETAILS;
+			fNames[Ids.ID_DD] = DD;
+			fNames[Ids.ID_DEL] = DEL;
+			fNames[Ids.ID_DFN] = DFN;
+			fNames[Ids.ID_DIR] = DIR;
+			fNames[Ids.ID_DIV] = DIV;
+			fNames[Ids.ID_DL] = DL;
+			fNames[Ids.ID_DT] = DT;
+			fNames[Ids.ID_EM] = EM;
+			fNames[Ids.ID_EMBED] = EMBED;
+			fNames[Ids.ID_FIELDSET] = FIELDSET;
+			fNames[Ids50.ID_FIGURE] = FIGURE;
+			fNames[Ids50.ID_FIGCAPTION] = FIGCAPTION;
+			fNames[Ids.ID_FONT] = FONT;
+			fNames[Ids.ID_FORM] = FORM;
+			fNames[Ids50.ID_FOOTER] = FOOTER;
+			fNames[Ids.ID_FRAME] = FRAME;
+			fNames[Ids.ID_FRAMESET] = FRAMESET;
+			fNames[Ids.ID_H1] = H1;
+			fNames[Ids.ID_H2] = H2;
+			fNames[Ids.ID_H3] = H3;
+			fNames[Ids.ID_H4] = H4;
+			fNames[Ids.ID_H5] = H5;
+			fNames[Ids.ID_H6] = H6;
+			fNames[Ids.ID_HEAD] = HEAD;
+			fNames[Ids50.ID_HEADER] = HEADER;
+			fNames[Ids50.ID_HGROUP] = HGROUP;
+			fNames[Ids.ID_HR] = HR;
+			fNames[Ids.ID_HTML] = HTML;
+			fNames[Ids.ID_I] = I;
+			fNames[Ids.ID_IFRAME] = IFRAME;
+			fNames[Ids.ID_IMG] = IMG;
+			fNames[Ids.ID_INPUT] = INPUT;
+			fNames[Ids.ID_INS] = INS;
+			fNames[Ids.ID_ISINDEX] = ISINDEX;
+			fNames[Ids.ID_KBD] = KBD;
+			fNames[Ids50.ID_KEYGEN] = KEYGEN;
+			fNames[Ids.ID_LABEL] = LABEL;
+			fNames[Ids.ID_LEGEND] = LEGEND;
+			fNames[Ids.ID_LI] = LI;
+			fNames[Ids.ID_LINK] = LINK;
+			fNames[Ids.ID_MAP] = MAP;
+			fNames[Ids50.ID_MARK] = MARK;
+			fNames[Ids.ID_MARQUEE] = MARQUEE;
+			fNames[Ids50.ID_MATH] = MATH;
+			fNames[Ids.ID_MENU] = MENU;
+			fNames[Ids.ID_META] = META;
+			fNames[Ids50.ID_METER] = METER;
+			fNames[Ids50.ID_NAV] = NAV;
+			fNames[Ids.ID_NOEMBED] = NOEMBED;
+			fNames[Ids.ID_NOFRAMES] = NOFRAMES;
+			fNames[Ids.ID_NOSCRIPT] = NOSCRIPT;
+			fNames[Ids.ID_OBJECT] = OBJECT;
+			fNames[Ids.ID_OL] = OL;
+			fNames[Ids.ID_OPTGROUP] = OPTGROUP;
+			fNames[Ids.ID_OPTION] = OPTION;
+			fNames[Ids50.ID_OUTPUT] = OUTPUT;
+			fNames[Ids.ID_P] = P;
+			fNames[Ids.ID_PARAM] = PARAM;
+			fNames[Ids.ID_PRE] = PRE;
+			fNames[Ids50.ID_PROGRESS] = PROGRESS;
+			fNames[Ids.ID_Q] = Q;
+			fNames[Ids50.ID_RP] = RP;
+			fNames[Ids50.ID_RT] = RT;
+			fNames[Ids50.ID_RUBY] = RUBY;
+			fNames[Ids.ID_S] = S;
+			fNames[Ids.ID_SAMP] = SAMP;
+			fNames[Ids.ID_SCRIPT] = SCRIPT;
+			fNames[Ids50.ID_SECTION] = SECTION;
+			fNames[Ids.ID_SELECT] = SELECT;
+			fNames[Ids.ID_SMALL] = SMALL;
+			fNames[Ids50.ID_SOURCE] = SOURCE;
+			fNames[Ids.ID_SPAN] = SPAN;
+			fNames[Ids.ID_STRIKE] = STRIKE;
+			fNames[Ids.ID_STRONG] = STRONG;
+			fNames[Ids.ID_STYLE] = STYLE;
+			fNames[Ids50.ID_SUMMARY] = SUMMARY;
+			fNames[Ids.ID_SUB] = SUB;
+			fNames[Ids.ID_SUP] = SUP;
+			fNames[Ids50.ID_SVG] = SVG;
+			fNames[Ids.ID_TABLE] = TABLE;
+			fNames[Ids.ID_TBODY] = TBODY;
+			fNames[Ids.ID_TD] = TD;
+			fNames[Ids.ID_TEXTAREA] = TEXTAREA;
+			fNames[Ids.ID_TFOOT] = TFOOT;
+			fNames[Ids.ID_TH] = TH;
+			fNames[Ids.ID_THEAD] = THEAD;
+			fNames[Ids50.ID_TIME] = TIME;
+			fNames[Ids.ID_TITLE] = TITLE;
+			fNames[Ids.ID_TR] = TR;
+			fNames[Ids.ID_TT] = TT;
+			fNames[Ids.ID_U] = U;
+			fNames[Ids.ID_UL] = UL;
+			fNames[Ids.ID_VAR] = VAR;
+			fNames[Ids50.ID_VIDEO] = VIDEO;
+			fNames[Ids.ID_WBR] = WBR;
+			fNames[Ids.ID_SSI_CONFIG] = SSI_CONFIG;
+			fNames[Ids.ID_SSI_ECHO] = SSI_ECHO;
+			fNames[Ids.ID_SSI_EXEC] = SSI_EXEC;
+			fNames[Ids.ID_SSI_FSIZE] = SSI_FSIZE;
+			fNames[Ids.ID_SSI_FLASTMOD] = SSI_FLASTMOD;
+			fNames[Ids.ID_SSI_INCLUDE] = SSI_INCLUDE;
+			fNames[Ids.ID_SSI_PRINTENV] = SSI_PRINTENV;
+			fNames[Ids.ID_SSI_SET] = SSI_SET;
+			fNames[Ids.ID_BGSOUND] = BGSOUND;
+			fNames[Ids.ID_NOBR] = NOBR;
+			fNames[Ids.ID_WBR] = WBR;
+		}
+		return fNames;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HTMLAttrDeclImpl.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HTMLAttrDeclImpl.java
new file mode 100644
index 0000000..9c85e4a
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HTMLAttrDeclImpl.java
@@ -0,0 +1,134 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import org.eclipse.wst.html.core.internal.provisional.HTMLCMProperties;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ * Implementation class of {@link <code>HTMLAttributeDeclaration</code>} interface.<br>
+ */
+class HTMLAttrDeclImpl extends CMNodeImpl implements HTMLAttributeDeclaration {
+
+	private HTMLCMDataTypeImpl type = null;
+	private int usage = 0;
+	private boolean is_obsolete = false;
+
+
+	/**
+	 */
+	public HTMLAttrDeclImpl(String attrName, HTMLCMDataTypeImpl valueType, int valueUsage) {
+		super(attrName);
+		this.type = valueType;
+
+		switch (valueUsage) {
+			case OPTIONAL :
+			case REQUIRED :
+			case FIXED :
+			case PROHIBITED :
+				this.usage = valueUsage;
+				break;
+			default :
+				// should warn...
+				this.usage = OPTIONAL; // fall back
+				break;
+		}
+	}
+
+	/**
+	 * getAttrName method
+	 * @return java.lang.String
+	 */
+	public String getAttrName() {
+		return getNodeName();
+	}
+
+	/**
+	 * getAttrType method
+	 * @return CMDataType
+	 */
+	public CMDataType getAttrType() {
+		return type;
+	}
+
+	/**
+	 * @deprecated by superinterface
+	 */
+	public String getDefaultValue() {
+		if (type.getImpliedValueKind() != CMDataType.IMPLIED_VALUE_DEFAULT)
+			return null;
+		return type.getImpliedValue();
+	}
+
+	/**
+	 * @deprecated by superinterface
+	 */
+	public Enumeration getEnumAttr() {
+		Vector v = new Vector(Arrays.asList(type.getEnumeratedValues()));
+		return v.elements();
+	}
+
+	/**
+	 * getNodeType method
+	 * @return int
+	 *
+	 * Returns one of :
+	 * ELEMENT_DECLARATION, ATTRIBUTE_DECLARATION, GROUP, ENTITY_DECLARATION.
+	 */
+	public int getNodeType() {
+		return CMNode.ATTRIBUTE_DECLARATION;
+	}
+
+	/**
+	 * @return int
+	 */
+	public int getUsage() {
+		return usage;
+	}
+
+	/**
+	 */
+	public boolean supports(String propertyName) {
+		if (propertyName.equals(HTMLCMProperties.SHOULD_IGNORE_CASE))
+			return true;
+		else if (propertyName.equals(HTMLCMProperties.IS_SCRIPTABLE))
+			return true;
+		else if (propertyName.equals(HTMLCMProperties.IS_OBSOLETE))
+			return is_obsolete;
+		
+		return super.supports(propertyName);
+	}
+
+	/**
+	 */
+	public Object getProperty(String propertyName) {
+		if (propertyName.equals(HTMLCMProperties.SHOULD_IGNORE_CASE))
+			return new Boolean(true);
+		else if (propertyName.equals(HTMLCMProperties.IS_SCRIPTABLE)) {
+			return getAttrType().getDataTypeName() == HTMLCMDataType.SCRIPT ? new Boolean(true) : new Boolean(false);
+		}
+		else if (propertyName.equals(HTMLCMProperties.IS_OBSOLETE))
+			return new Boolean(is_obsolete);
+		
+		return super.getProperty(propertyName);
+	}
+	
+	public void obsolete(boolean is_obsolete){
+		this.is_obsolete = is_obsolete;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HTMLAttributeDeclaration.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HTMLAttributeDeclaration.java
new file mode 100644
index 0000000..80adfe3
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HTMLAttributeDeclaration.java
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+
+
+
+/**
+ * This interface is intended to be a public interface which has
+ * interfaces defined in both of {@link <code>CMAttributeDeclaration</code>}
+ * and {@link <code>HTMLCMNode</code>}.<br>
+ */
+public interface HTMLAttributeDeclaration extends CMAttributeDeclaration {
+	String IS_HTML = "isHTML"; //$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HTMLCMDataType.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HTMLCMDataType.java
new file mode 100644
index 0000000..3c94c47
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HTMLCMDataType.java
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+
+/**
+ * HTML extension for data types.
+ */
+public interface HTMLCMDataType extends CMDataType {
+
+	/** Boolean; it should be defined in CMDataType. */
+	public static final String BOOLEAN = "BOOLEAN"; //$NON-NLS-1$
+	public static final String COLOR = "COLOR"; //$NON-NLS-1$
+	public static final String EVENT = "EVENT"; //$NON-NLS-1$
+	public static final String IDREFS = "IDREFS"; //$NON-NLS-1$
+	/** Name; it should be defined in CMDataType. */
+	public static final String NAME = "NAME"; //$NON-NLS-1$
+	// Following types are just aliases.
+	/** %Character; == CDATA */
+	public static final String CHARACTER = CMDataType.CDATA;
+	/** %Charset; == CDATA */
+	public static final String CHARSET = CMDataType.CDATA;
+	/** %Charsets; == CDATA */
+	public static final String CHARSETS = CMDataType.CDATA;
+	/** %ContentType; == CDATA */
+	public static final String CONTENT_TYPE = CMDataType.CDATA;
+	/** %Coords; == CDATA */
+	public static final String COORDS = CMDataType.CDATA;
+	/** %Datetime; == CDATA */
+	public static final String DATETIME = CMDataType.CDATA;
+	/** %FrameTarget; == CDATA */
+	public static final String FRAME_TARGET = CMDataType.CDATA;
+	/** %LanguageCode; == NAME */
+	public static final String LANGUAGE_CODE = NAME;
+	/** %Length; == CDATA */
+	public static final String LENGTH = CMDataType.CDATA;
+	/** %LinkTypes; == CDATA */
+	public static final String LINK_TYPES = CMDataType.CDATA;
+	/** %LIStyle; == CDATA */
+	public static final String LI_STYLE = CMDataType.CDATA;
+	/** %MediaDesc; == CDATA */
+	public static final String MEDIA_DESC = CMDataType.CDATA;
+	/** %MultiLength; == CDATA */
+	public static final String MULTI_LENGTH = CMDataType.CDATA;
+	/** %OLStyle; == CDATA */
+	public static final String OL_STYLE = CMDataType.CDATA;
+	/** %Pixles; == CDATA */
+	public static final String PIXELS = CMDataType.CDATA;
+	/** %Script; == EVENT */
+	public static final String SCRIPT = EVENT;
+	/** %StyleSheet; == EVENT */
+	public static final String STYLE_SHEET = CMDataType.CDATA;
+	/** %Text; == CDATA */
+	public static final String TEXT = CMDataType.CDATA;
+	/** %MediaType; == CDATA */
+	public static final String MEDIA_TYPE = CMDataType.CDATA;
+	/** %BrowsingContext; == CDATA */
+	public static final String BROWSING_CONTEXT = CMDataType.CDATA;
+	
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HTMLCMDataTypeImpl.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HTMLCMDataTypeImpl.java
new file mode 100644
index 0000000..6e50c74
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HTMLCMDataTypeImpl.java
@@ -0,0 +1,125 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+
+
+/**
+ */
+class HTMLCMDataTypeImpl extends CMNodeImpl implements HTMLCMDataType {
+
+	private int impliedValueKind = IMPLIED_VALUE_NONE;
+	private String impliedValue = null;
+	private final static String[] emptyArray = new String[0];
+	private String[] enumValues = emptyArray;
+	private String instanceValue = null;
+
+	/**
+	 * HTMLCMDataTypeImpl constructor comment.
+	 * @param nm java.lang.String
+	 */
+	public HTMLCMDataTypeImpl(String typeName) {
+		super(typeName);
+	}
+
+	/**
+	 * HTMLCMDataTypeImpl constructor comment.
+	 * @param nm java.lang.String
+	 */
+	public HTMLCMDataTypeImpl(String typeName, String instanceValue) {
+		super(typeName);
+		this.instanceValue = instanceValue;
+	}
+
+	/**
+	 * getTypeName method
+	 * @return java.lang.String
+	 *
+	 * This method returns a suitable default value that can be used when an instance of the data type is created.
+	 * This returns null of a suitable default is not available.
+	 */
+	public String generateInstanceValue() {
+		return instanceValue;
+	}
+
+	/**
+	 * @see org.eclipse.wst.xml.core.internal.contentmodel.CMDataType
+	 */
+	public String getDataTypeName() {
+		return getNodeName();
+	}
+
+	/**
+	 * getTypeName method
+	 * @return java.lang.String[]
+	 *
+	 */
+	public String[] getEnumeratedValues() {
+		return enumValues;
+	}
+
+	/**
+	 * getTypeName method
+	 * @return java.lang.String  
+	 *
+	 * Returns the implied value or null if none exists.
+	 */
+	public String getImpliedValue() {
+		return impliedValue;
+	}
+
+	/**
+	 * getImpliedValueKind method
+	 * @return int
+	 *
+	 * Returns one of :
+	 * IMPLIED_VALUE_NONE, IMPLIED_VALUE_FIXED, IMPLIED_VALUE_DEFAULT.
+	 */
+	public int getImpliedValueKind() {
+		return impliedValueKind;
+	}
+
+	/**
+	 * @see org.eclipse.wst.xml.core.internal.contentmodel.CMNode
+	 */
+	public int getNodeType() {
+		return CMNode.DATA_TYPE;
+	}
+
+	/**
+	 */
+	void setEnumValues(String[] values) {
+		enumValues = new String[values.length];
+		for (int i = 0; i < values.length; i++) {
+			enumValues[i] = values[i];
+		}
+	}
+
+	/**
+	 * package scope.
+	 */
+	void setImpliedValue(int kind, String value) {
+		switch (kind) {
+			case IMPLIED_VALUE_FIXED :
+			case IMPLIED_VALUE_DEFAULT :
+				impliedValueKind = kind;
+				impliedValue = value;
+				break;
+			case IMPLIED_VALUE_NONE :
+			default :
+				impliedValueKind = IMPLIED_VALUE_NONE;
+				impliedValue = null; // maybe a null string?
+				break;
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HTMLCMDocument.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HTMLCMDocument.java
new file mode 100644
index 0000000..af6c7d9
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HTMLCMDocument.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+
+
+
+/**
+ * HTML extension for CMDocument.
+ * This interface provides some short hand methods to get declarations
+ * by a name.
+ */
+public interface HTMLCMDocument extends CMDocument {
+
+	/**
+	 * A short hand method to get a element declaration for a HTML element.<br>
+	 * @param elementName java.lang.String
+	 */
+	HTMLElementDeclaration getElementDeclaration(String elementName);
+
+	/**
+	 * A short hand method to get a entity declaration of HTML documents.<br>
+	 * @param entityName java.lang.String
+	 */
+	HTMLEntityDeclaration getEntityDeclaration(String entityName);
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HTMLCMDocumentFactory.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HTMLCMDocumentFactory.java
new file mode 100644
index 0000000..7b9f634
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HTMLCMDocumentFactory.java
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.util.Arrays;
+import java.util.Hashtable;
+import java.util.List;
+
+import org.eclipse.wst.html.core.internal.contentmodel.chtml.CHCMDocImpl;
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.html.core.internal.provisional.HTML50Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.provisional.contentmodel.CMDocType;
+
+/**
+ * INodeAdapter factory for HTML and JSP documents.
+ */
+public final class HTMLCMDocumentFactory {
+
+	private static Hashtable cmdocs = new Hashtable();
+	private static List supportedCMtypes = Arrays.asList(new Object[]{CMDocType.HTML_DOC_TYPE, CMDocType.CHTML_DOC_TYPE, CMDocType.JSP11_DOC_TYPE, CMDocType.JSP12_DOC_TYPE, CMDocType.JSP20_DOC_TYPE, CMDocType.TAG20_DOC_TYPE, CMDocType.JSP21_DOC_TYPE, CMDocType.HTML5_DOC_TYPE});
+
+	private static JCMDocImpl jsp11doc = null;
+
+	/**
+	 * HTMLCMAdapterFactory constructor.
+	 */
+	private HTMLCMDocumentFactory() {
+		super();
+	}
+
+	/**
+	 * @return org.eclipse.wst.xml.core.internal.contentmodel.CMDocument
+	 * @param cmtype
+	 *            java.lang.String
+	 */
+	public static CMDocument getCMDocument(String cmtype) {
+		Object obj = cmdocs.get(cmtype);
+		if (obj == null && cmtype != null) {
+			if (supportedCMtypes.contains(cmtype)) {
+				obj = doCreateCMDocument(cmtype);
+				cmdocs.put(cmtype, obj);
+			}
+		}
+
+		return (CMDocument) obj;
+	}
+
+	private static Object doCreateCMDocument(String cmtype) {
+		if (CMDocType.HTML_DOC_TYPE.equals(cmtype)) {
+			CMNamespaceImpl h40ns = new CMNamespaceImpl(HTML40Namespace.HTML40_URI, HTML40Namespace.HTML40_TAG_PREFIX);
+			HCMDocImpl html40doc = new HCMDocImpl(CMDocType.HTML_DOC_TYPE, h40ns);
+			return html40doc;
+		}
+
+		else if (CMDocType.HTML5_DOC_TYPE.equals(cmtype)) {
+			CMNamespaceImpl h50ns = new CMNamespaceImpl(HTML50Namespace.HTML50_URI, HTML50Namespace.HTML50_TAG_PREFIX);
+			H5CMDocImpl html50doc = new H5CMDocImpl(CMDocType.HTML5_DOC_TYPE, h50ns);
+			return html50doc;
+		}
+		
+		else if (CMDocType.JSP20_DOC_TYPE.equals(cmtype)) {
+			CMNamespaceImpl j20ns = new CMNamespaceImpl(JSP20Namespace.JSP20_URI, JSP11Namespace.JSP_TAG_PREFIX);
+			JCM20DocImpl jsp20doc = new JCM20DocImpl(CMDocType.JSP20_DOC_TYPE, j20ns);
+			return jsp20doc;
+		}
+
+		else if (CMDocType.JSP21_DOC_TYPE.equals(cmtype)) {
+			CMNamespaceImpl j21ns = new CMNamespaceImpl(JSP21Namespace.JSP21_URI, JSP11Namespace.JSP_TAG_PREFIX);
+			JCM21DocImpl jsp21doc = new JCM21DocImpl(CMDocType.JSP21_DOC_TYPE, j21ns);
+			return jsp21doc;
+		}
+
+		else if (CMDocType.TAG20_DOC_TYPE.equals(cmtype)) {
+			CMNamespaceImpl j20ns = new CMNamespaceImpl(JSP20Namespace.JSP20_URI, JSP11Namespace.JSP_TAG_PREFIX);
+			TagCMDocImpl tag20doc = new TagCMDocImpl(CMDocType.TAG20_DOC_TYPE, j20ns);
+			return tag20doc;
+		}
+
+		else if (CMDocType.JSP11_DOC_TYPE.equals(cmtype) || CMDocType.JSP12_DOC_TYPE.equals(cmtype)) {
+			if (jsp11doc == null) {
+				CMNamespaceImpl j11ns = new CMNamespaceImpl(JSP11Namespace.JSP11_URI, JSP11Namespace.JSP_TAG_PREFIX);
+				jsp11doc = new JCMDocImpl(CMDocType.JSP11_DOC_TYPE, j11ns);
+			}
+			return jsp11doc;
+		}
+
+		else if (CMDocType.CHTML_DOC_TYPE.equals(cmtype)) {
+			CMNamespaceImpl cH40ns = new CMNamespaceImpl(HTML40Namespace.HTML40_URI, HTML40Namespace.HTML40_TAG_PREFIX);
+			CHCMDocImpl chtmldoc = new CHCMDocImpl(CMDocType.CHTML_DOC_TYPE, cH40ns);
+			return chtmldoc;
+		}
+
+		return null;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HTMLCMNode.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HTMLCMNode.java
new file mode 100644
index 0000000..a3623ec
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HTMLCMNode.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+/**
+ * In HTML Documents, name and value of an attribute/element/entity
+ * should be treated ignoring theirs case.  However, in XML documents,
+ * they should be distinguished with sensitiveness of their case.
+ * CMNode is basically designed to represent DTDs or Schemas for XML
+ * documents.  So, it doesn't have interfaces to retrieve such information.
+ * However, declarations in the HTML CM should provide such information.
+ * This intermediate interface is intended to provide whether ignore cases
+ * or not.<br>
+ */
+interface HTMLCMNode extends org.eclipse.wst.xml.core.internal.contentmodel.CMNode {
+
+	/**
+	 * Returns <code>true</code>, if declaration is for HTML attribute/element/entity.
+	 * Otherwise, returns <code>false</code>.
+	 * @return boolean
+	 */
+	boolean shouldIgnoreCase();
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HTMLElemDeclImpl.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HTMLElemDeclImpl.java
new file mode 100644
index 0000000..3f5a9b7
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HTMLElemDeclImpl.java
@@ -0,0 +1,377 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.util.Iterator;
+
+import org.eclipse.wst.html.core.internal.provisional.HTMLCMProperties;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMContent;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ * Base class for all Hed???? classes.
+ */
+abstract class HTMLElemDeclImpl extends CMContentImpl implements HTMLElementDeclaration, HTMLPropertyDeclaration {
+
+	// DTD
+	protected CMNamedNodeMapImpl attributes = null;
+	protected String typeDefinitionName = ComplexTypeDefinitionFactory.CTYPE_EMPTY;
+	/** Never access this field directly.  Instead, use getComplexTypeDefinition method. */
+	private ComplexTypeDefinition typeDefinition = null;
+	protected CMGroupImpl inclusion = null;
+	protected CMGroupImpl exclusion = null;
+	// advanced information
+	protected CMNamedNodeMap prohibitedAncestors = null;
+	protected int correctionType = CORRECT_NONE;
+	protected int formatType = FORMAT_HTML;
+	protected int layoutType = LAYOUT_NONE;
+	protected int omitType = OMIT_NONE;
+	protected boolean keepSpaces = false;
+	protected boolean indentChild = false;
+	protected ElementCollection elementCollection = null;
+	protected AttributeCollection attributeCollection = null;
+	private boolean is_obsolete = false;
+	protected final static CMNamedNodeMap EMPTY_MAP = new CMNamedNodeMap() {
+		public int getLength() {
+			return 0;
+		}
+
+		public CMNode getNamedItem(String name) {
+			return null;
+		}
+
+		public CMNode item(int index) {
+			return null;
+		}
+
+		public Iterator iterator() {
+			return new Iterator() {
+				public boolean hasNext() {
+					return false;
+				}
+
+				public Object next() {
+					return null;
+				}
+
+				public void remove() {
+				}
+			};
+		}
+	};
+
+	/**
+	 * HTMLElemDeclImpl constructor.
+	 * In the HTML DTD, an element declaration has no specification
+	 * for its occurrence.  Occurrence is specifed in content model, like
+	 * <code>(LI)+</code>.  To avoid confusion (and complexity),
+	 * occurrence of an element declaration is always 1 (it means, min = 1 and
+	 * max = 1).  Instead, occurrence of CMGroup represents actual occurrence
+	 * of the content.
+	 * <br>
+	 * @param name java.lang.String
+	 */
+	public HTMLElemDeclImpl(String elementName, ElementCollection collection) {
+		super(elementName, 1, 1);
+		elementCollection = collection;
+		attributeCollection = collection.getAttributeCollection();
+	}
+
+	/**
+	 */
+	protected abstract void createAttributeDeclarations();
+
+	private ComplexTypeDefinition createComplexTypeDefinition() {
+		if (typeDefinitionName.equals(ComplexTypeDefinitionFactory.CTYPE_CDATA) || typeDefinitionName.equals(ComplexTypeDefinitionFactory.CTYPE_EMPTY) || typeDefinitionName.equals(ComplexTypeDefinitionFactory.CTYPE_PCDATA))
+			return null;
+
+		ComplexTypeDefinitionFactory factory = ComplexTypeDefinitionFactory.getInstance();
+		if (factory == null)
+			return null; // fatal error.
+
+		ComplexTypeDefinition def = factory.createTypeDefinition(typeDefinitionName, elementCollection);
+		return def;
+	}
+
+	/**
+	 * Get an attribute declaration.
+	 */
+	public HTMLAttributeDeclaration getAttributeDeclaration(String attrName) {
+		if (attributes == null) {
+			createAttributeDeclarations();
+			if (attributes == null)
+				return null; // fail to create
+		}
+
+		CMNode cmnode = attributes.getNamedItem(attrName);
+		if (cmnode == null) {
+			return null;
+		}
+		else {
+			return (HTMLAttributeDeclaration) cmnode; // already exists.
+		}
+	}
+
+	/**
+	 * @see org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration
+	 */
+	public CMNamedNodeMap getAttributes() {
+		if (attributes == null)
+			createAttributeDeclarations(); // lazy eval.
+		return attributes;
+	}
+
+	/**
+	 * Get an instance of complex type definition.
+	 */
+	private ComplexTypeDefinition getComplexTypeDefinition() {
+		if (typeDefinition == null)
+			typeDefinition = createComplexTypeDefinition();
+		return typeDefinition;
+	}
+
+	/**
+	 * Content.<br>
+	 * Element declarations which type is EMPTY or CDATA (maybe PCDATA)
+	 * <strong>MUST</strong> override this method and always return null.
+	 * This default implementation always tries to create a complex type definition
+	 * instance and access to it.
+	 * <br>
+	 * @see org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration
+	 */
+	public CMContent getContent() {
+		ComplexTypeDefinition def = getComplexTypeDefinition(); // lazy eval.
+		return (def != null) ? def.getContent() : null;
+	}
+
+	/**
+	 * Content type.<br>
+	 * Element declarations which type is EMPTY or CDATA (maybe PCDATA)
+	 * <strong>MUST</strong> override this method and return an appropriate type.
+	 * This default implementation always tries to create a complex type definition
+	 * instance and access to it.
+	 * <br>
+	 * @see org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration
+	 */
+	public int getContentType() {
+		ComplexTypeDefinition def = getComplexTypeDefinition(); // lazy eval.
+		return (def != null) ? def.getContentType() : CMElementDeclaration.CDATA;
+	}
+
+	/**
+	 * @see HTMLElementDeclaration#getCorrectionType
+	 */
+	public int getCorrectionType() {
+		return correctionType;
+	}
+
+	/**
+	 * HTML element doesn't have any data type.  So, this method always
+	 * returns <code>null</code>.<br>
+	 * @see org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration
+	 */
+	public CMDataType getDataType() {
+		return null;
+	}
+
+	/**
+	 * @see org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration
+	 */
+	public String getElementName() {
+		return getNodeName();
+	}
+
+	/**
+	 * Exclusion.
+	 * Almost elements don't have a exclusion.
+	 * Only classes those have exclusion should override this method.
+	 */
+	public CMContent getExclusion() {
+		return null;
+	}
+
+	/**
+	 * Default format type is <code>FORMAT_HTML</code>.<br>
+	 */
+	public int getFormatType() {
+		return formatType;
+	}
+
+	/**
+	 * Inclusion.
+	 * Almost elements don't have a inclusion.
+	 * Only classes those have inclusion should override this method.
+	 */
+	public CMContent getInclusion() {
+		return null;
+	}
+
+	/**
+	 */
+	public int getLayoutType() {
+		return layoutType;
+	}
+
+	/**
+	 * Line break hint is strongly related to layout type.
+	 * Indeed, in the C++DOM, it is determined from layout type only.
+	 * So, this implementation, as the default implementation for all declarations,
+	 * also determines from layout type only.<br>
+	 * @return int
+	 */
+	public int getLineBreakHint() {
+		switch (getLayoutType()) {
+			case HTMLElementDeclaration.LAYOUT_BLOCK :
+				return HTMLElementDeclaration.BREAK_BEFORE_START_AND_AFTER_END;
+			case HTMLElementDeclaration.LAYOUT_BREAK :
+				return HTMLElementDeclaration.BREAK_AFTER_START;
+			case HTMLElementDeclaration.LAYOUT_HIDDEN :
+				return HTMLElementDeclaration.BREAK_BEFORE_START_AND_AFTER_END;
+			default :
+				return HTMLElementDeclaration.BREAK_NONE;
+		}
+	}
+
+	/**
+	 * No HTML element has local elements.  So, this method always
+	 * returns an empty map.
+	 * @see org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration
+	 */
+	public CMNamedNodeMap getLocalElements() {
+		return EMPTY_MAP;
+	}
+
+	/**
+	 * @see org.eclipse.wst.xml.core.internal.contentmodel.CMNode
+	 */
+	public int getNodeType() {
+		return CMNode.ELEMENT_DECLARATION;
+	}
+
+	/**
+	 */
+	public int getOmitType() {
+		return omitType;
+	}
+
+	/**
+	 */
+	public CMNamedNodeMap getProhibitedAncestors() {
+		return EMPTY_MAP;
+	}
+
+	/**
+	 */
+	public boolean supports(String propertyName) {
+		if (propertyName.equals(HTMLCMProperties.SHOULD_IGNORE_CASE)) {
+			return true;
+		}
+		else if (propertyName.equals(HTMLCMProperties.CONTENT_HINT)) {
+			ComplexTypeDefinition def = getComplexTypeDefinition();
+			return (def != null);
+		}
+		if (propertyName.equals(HTMLCMProperties.IS_OBSOLETE)) {
+			return is_obsolete;
+		}
+		else {
+			PropertyProvider pp = PropertyProviderFactory.getProvider(propertyName);
+			if (pp == null)
+				return false;
+			return pp.supports(this);
+		}
+
+	}
+
+	/**
+	 */
+	public Object getProperty(String propertyName) {
+		if (propertyName.equals(HTMLCMProperties.SHOULD_IGNORE_CASE)) {
+			return new Boolean(true);
+		}
+		else if (propertyName.equals(HTMLCMProperties.CONTENT_HINT)) {
+			ComplexTypeDefinition def = getComplexTypeDefinition();
+			return (def != null) ? def.getPrimaryCandidate() : null;
+		}
+		else if (propertyName.equals(HTMLCMProperties.IS_OBSOLETE)){
+			return new Boolean(is_obsolete);
+		}
+		else {
+			PropertyProvider pp = PropertyProviderFactory.getProvider(propertyName);
+			if (pp == null)
+				return null;
+			return pp.get(this);
+		}
+	}
+
+	/**
+	 * Return element names which terminates this element.<br>
+	 * @return java.util.Iterator
+	 */
+	protected Iterator getTerminators() {
+		return null;
+	}
+
+	/**
+	 * return true when the element is a JSP element.
+	 */
+	public boolean isJSP() {
+		return false;
+	}
+
+	/**
+	 * In some elements, such as APPLET, a source generator should indent child
+	 * elements that their parents.  That is, a source generator should generate
+	 * source  of APPLET and PARAMS like this:
+	 * <PRE>
+	 *   &lt;APPLET ...&gt;
+	 *     &lt;PARAM ... &gt;
+	 *     &lt;PARAM ... &gt;
+	 *   &lt;/APPLET&gt;
+	 * <PRE>
+	 * @return boolean
+	 */
+	public boolean shouldIndentChildSource() {
+		return indentChild;
+	}
+
+	/**
+	 * Most of elements can compact spaces in their child text nodes.
+	 * Some special elements should keep them in their source.
+	 * @return boolean
+	 */
+	public boolean shouldKeepSpaces() {
+		return keepSpaces;
+	}
+
+	/**
+	 * @return boolean
+	 */
+	public boolean shouldTerminateAt(HTMLElementDeclaration nextElement) {
+		Iterator i = getTerminators();
+		if (i == null)
+			return false;
+		String nextName = nextElement.getElementName();
+		while (i.hasNext()) {
+			if (nextName.equals(i.next()))
+				return true;
+		}
+		return false;
+	}
+	
+	public void obsolete(boolean is_obsolete){
+		this.is_obsolete = is_obsolete;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HTMLElementDeclaration.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HTMLElementDeclaration.java
new file mode 100644
index 0000000..8dbf0c8
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HTMLElementDeclaration.java
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+
+/**
+ * This interface is intended to be a public interface which has
+ * interfaces defined in both of {@link <code>CMElementDeclaration</code>}
+ * and {@link <code>HTMLCMNode</code>}.<br>
+ * In addition to this, some interfaces are added to this interface,
+ * those are specially to HTML elements.<br>
+ */
+public interface HTMLElementDeclaration extends CMElementDeclaration {
+
+	/** Tag ommission; Not ommisible. */
+	int OMIT_NONE = 0;
+	/** Tag ommission; Both tags are ommisible. */
+	int OMIT_BOTH = 1;
+	/** Tag ommission; The end tag is ommisible. */
+	int OMIT_END = 2;
+	/** Tag ommission; The end tag is ommitted when created. */
+	int OMIT_END_DEFAULT = 3;
+	/** Tag ommission; The end tag must be omitted. */
+	int OMIT_END_MUST = 4;
+	/** Line Break; No break. */
+	int BREAK_NONE = 10;
+	/** Line Break; Break after the start tag. */
+	int BREAK_AFTER_START = 11;
+	/** Line Break; Break both before the start tagn and after the end tag. */
+	int BREAK_BEFORE_START_AND_AFTER_END = 12;
+	/* Layout */
+	/** initial value; the value should never returns to client programs. */
+	int LAYOUT_NONE = 100;
+	int LAYOUT_BLOCK = 101;
+	int LAYOUT_WRAP = 102;
+	/** No wrap object; like IMG, APPLET,... */
+	int LAYOUT_OBJECT = 103;
+	/** BR */
+	int LAYOUT_BREAK = 104;
+	/** Hidden object; like HTML or HEAD */
+	int LAYOUT_HIDDEN = 105;
+	/* Correction */
+	/** Correct; No correct. */
+	int CORRECT_NONE = 1000;
+	/** Correct; Meaningless when the content is empty. */
+	int CORRECT_EMPTY = 1001;
+	/** Correct; Meaningless when no attribut is set. */
+	int CORRECT_NEUTRAL = 1002;
+	/** Correct; Meaningless when same element is nested. */
+	int CORRECT_DUPLICATED = 1003;
+	/** Format; HTML */
+	int FORMAT_HTML = 10000;
+	/** Format; SSI */
+	int FORMAT_SSI = 10001;
+	/** Format; JSP script */
+	int FORMAT_JSP_SCRIPT = 10002;
+	/** Format; JSP directive */
+	int FORMAT_JSP_DIRECTIVE = 10003;
+	/** Format; XML */
+	int FORMAT_XML = 10004;
+	/** Format; MW */
+	int FORMAT_MW = 10005;
+
+	/**
+	 * A short hand method to get an attribute declaration of a HTML element.
+	 * @param attrName java.lang.String
+	 */
+	HTMLAttributeDeclaration getAttributeDeclaration(String attrName);
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HTMLEntityDeclImpl.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HTMLEntityDeclImpl.java
new file mode 100644
index 0000000..d43db28
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HTMLEntityDeclImpl.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+import org.eclipse.wst.html.core.internal.provisional.HTMLCMProperties;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+
+
+/**
+ */
+class HTMLEntityDeclImpl extends CMNodeImpl implements HTMLEntityDeclaration {
+
+	private java.lang.String value = null;
+
+	/**
+	 * CMEntityDeclImpl constructor comment.
+	 * @param entityName java.lang.String; Entity name.
+	 * @param entityValue java.lang.String; Value string.
+	 */
+	public HTMLEntityDeclImpl(String entityName, String entityValue) {
+		super(entityName);
+		value = entityValue;
+	}
+
+	/**
+	 * getName method
+	 * @return java.lang.String
+	 */
+	public String getName() {
+		return getNodeName();
+	}
+
+	/**
+	 * Get CMNode type.<br>
+	 * @return int; Always return ENTITY_DECLARATION.
+	 */
+	public int getNodeType() {
+		return CMNode.ENTITY_DECLARATION;
+	}
+
+	/**
+	 * getValue method
+	 * @return java.lang.String
+	 */
+	public String getValue() {
+		return value;
+	}
+
+	/**
+	 */
+	public boolean supports(String propertyName) {
+		if (propertyName.equals(HTMLCMProperties.SHOULD_IGNORE_CASE))
+			return true;
+		return super.supports(propertyName);
+	}
+
+	/**
+	 * Entities in HTML documents are always treated with ignoring cases.
+	 * Because no special entities are defined in JSP 1.0, this method
+	 * can always return <code>true</code>.<br>
+	 */
+	public Object getProperty(String propertyName) {
+		if (propertyName.equals(HTMLCMProperties.SHOULD_IGNORE_CASE))
+			return new Boolean(true);
+		return super.getProperty(propertyName);
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HTMLEntityDeclaration.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HTMLEntityDeclaration.java
new file mode 100644
index 0000000..1f7b2d3
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HTMLEntityDeclaration.java
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+/**
+ * This interface is intended to be a public interface which has
+ * interfaces defined in both of {@link <code>CMEntityDeclaration</code>}
+ * and {@link <code>HTMLCMNode</code>}.<br>
+ */
+public interface HTMLEntityDeclaration extends org.eclipse.wst.xml.core.internal.contentmodel.CMEntityDeclaration {
+
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HTMLPropertyDeclaration.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HTMLPropertyDeclaration.java
new file mode 100644
index 0000000..448bfb3
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HTMLPropertyDeclaration.java
@@ -0,0 +1,102 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMContent;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+
+/**
+ * This interface is commonly used in declaration implementation, and internal use.
+ * Use getProperty() method for public use.
+ */
+public interface HTMLPropertyDeclaration {
+	/**
+	 * To determin the type, look up the following keywords in C++DOM/DTDParser.cpp:
+	 * <ul>
+	 *   <li>CORRECT_DUPLICATED - <code>GROUP_NODUP</code></li>
+	 *   <li>CORRECT_EMPTY - <code>GROUP_COMPACT</code></li>
+	 *   <li>CORRECT_NEUTRAL - <code>GROUP_NEUTRAL</code></li>
+	 *   <li>CORRECT_NONE - <code>(N/A)</code></li>
+	 * </ul>
+	 * @return int
+	 */
+	int getCorrectionType();
+	/**
+	 * Get the list of declarations those should be excluded from the content.<br>
+	 * @return org.eclipse.wst.xml.core.internal.contentmodel.CMContent
+	 */
+	CMContent getExclusion();
+	/**
+	 * To determin the type, see the following files in the C++DOM:
+	 *   ElementType.cpp - ElementType#setGroup().
+	 *   Element.cpp - Element#getStartTag().
+	 * @return int
+	 */
+	int getFormatType();
+	/**
+	 * Get the list of declarations those should be included into the content.<br>
+	 * @return org.eclipse.wst.xml.core.internal.contentmodel.CMContent
+	 */
+	CMContent getInclusion();
+	/**
+	 * To determin the type, look up the following keywords in C++DOM/DTDParser.cpp:
+	 * <ul>
+	 *   <li>LAYOUT_BLOCK - <code>GROUP_BLOCK</code></li>
+	 *   <li>LAYOUT_BREAK - <code>GROUP_BREAK</code></li>
+	 *   <li>LAYOUT_HIDDEN - <code>GROUP_HIDDEN</code></li>
+	 *   <li>LAYOUT_NONE - <code>(N/A)</code></li>
+	 *   <li>LAYOUT_OBJECT - <code>GROUP_NOWRAP</code></li>
+	 *   <li>LAYOUT_WRAP - <code>(N/A)</code></li>
+	 * </ul>
+	 * @return int
+	 */
+	int getLayoutType();
+	/**
+	 * To determine the type, see <code>Element::isBreakingBeforeElement()</code>
+	 * and <code>Element::isBreakingAfterElement()</code> defined in C++DOM/Element.cpp.<br>
+	 * @return int
+	 */
+	int getLineBreakHint();
+	/**
+	 * To determine the type, Check the HTML DTD.
+	 * And look up <code>GROUP_NOEND</code> in C++DOM/DTDParser.cpp.<br>
+	 * @return int
+	 */
+	int getOmitType();
+	/**
+	 * @return org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap
+	 */
+	CMNamedNodeMap getProhibitedAncestors();
+	/**
+	 * return true when the element is a JSP element.
+	 */
+	boolean isJSP();
+	/**
+	 * @return boolean
+	 */
+	boolean shouldIndentChildSource();
+	/**
+	 * Some elements should keep spaces in its child text nodes.
+	 * For example, PRE and TEXTAREA.  This method returns true,
+	 * if a target element is one of such elements.
+	 * @return boolean
+	 */
+	boolean shouldKeepSpaces();
+	/**
+	 * Returns <code>true</code>, if <code>nextElement</code> terminates
+	 * the current element.
+	 * Some elements like <code>P</code> terminates other <code>P</code>.
+	 * That is, when <code>&lt;P&gt;</code> appears at the next to <code>P</code>,
+	 * which end tags is omitted, it represents not only the beginning of the
+	 * new <code>P</code> element but also the end of the previous <code>P</code>.
+	 */
+	boolean shouldTerminateAt(HTMLElementDeclaration nextElement);
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedA.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedA.java
new file mode 100644
index 0000000..270fc91
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedA.java
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMContent;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ * A.
+ */
+final class HedA extends HedInlineContainer {
+
+	/**
+	 */
+	public HedA(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.A, collection);
+		// CORRECT_EMPTY - GROUP_COMPACT
+		correctionType = CORRECT_EMPTY;
+	}
+
+	/**
+	 * %attrs;
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+
+		//different sets of attributes for html 4 & 5
+		attributeCollection.createAttributeDeclarations(HTML40Namespace.ElementName.A, attributes);
+	
+	}
+
+	/**
+	 * Exclusion.
+	 * <code>A</code> has the exclusion.
+	 * It is <code>A</code> itself.
+	 */
+	public CMContent getExclusion() {
+		if (exclusion != null)
+			return exclusion; // already created.
+		if (elementCollection == null)
+			return null;
+
+		exclusion = new CMGroupImpl(CMGroup.CHOICE, 1, 1);
+		CMNode a = elementCollection.getNamedItem(HTML40Namespace.ElementName.A);
+		if (a != null)
+			exclusion.appendChild(a);
+
+		return exclusion;
+	}
+
+	/**
+	 */
+	public CMNamedNodeMap getProhibitedAncestors() {
+		if (prohibitedAncestors != null)
+			return prohibitedAncestors;
+
+		String[] names = {HTML40Namespace.ElementName.A, HTML40Namespace.ElementName.BUTTON};
+		prohibitedAncestors = elementCollection.getDeclarations(names);
+
+		return prohibitedAncestors;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedADDRESS.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedADDRESS.java
new file mode 100644
index 0000000..b4913f4
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedADDRESS.java
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+
+/**
+ * ADDRESS.
+ */
+final class HedADDRESS extends HTMLElemDeclImpl {
+
+	/**
+	 */
+	public HedADDRESS(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.ADDRESS, collection);
+		typeDefinitionName = ComplexTypeDefinitionFactory.CTYPE_ADDRESS;
+		correctionType = CORRECT_EMPTY;
+		layoutType = LAYOUT_BLOCK;
+	}
+
+	/**
+	 * %attrs;
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+	}
+
+	/**
+	 */
+	public CMNamedNodeMap getProhibitedAncestors() {
+		if (prohibitedAncestors != null)
+			return prohibitedAncestors;
+
+		String[] names = {HTML40Namespace.ElementName.DIR, HTML40Namespace.ElementName.MENU};
+		prohibitedAncestors = elementCollection.getDeclarations(names);
+
+		return prohibitedAncestors;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedAPPLET.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedAPPLET.java
new file mode 100644
index 0000000..9a546f7
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedAPPLET.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.util.Arrays;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+
+
+/**
+ * APPLET.
+ */
+final class HedAPPLET extends HTMLElemDeclImpl {
+
+	/**
+	 */
+	public HedAPPLET(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.APPLET, collection);
+		typeDefinitionName = ComplexTypeDefinitionFactory.CTYPE_PARAM_CONTAINER;
+		layoutType = LAYOUT_OBJECT;
+		indentChild = true;
+	}
+
+	/**
+	 * %coreattrs;
+	 * (codebase %URI; #IMPLIED)
+	 * (archive CDATA #IMPLIED)
+	 * (code CDATA #IMPLIED)
+	 * (object CDATA #IMPLIED)
+	 * (alt %Text; #IMPLIED) ... should be defined locally.
+	 * (name CDATA #IMPLIED)
+	 * (width %Length; #REQUIRED)
+	 * (height %Length; #REQUIRED)
+	 * (align %IAlign; #IMPLIED)
+	 * (hspace %Pixels; #IMPLIED)
+	 * (vspace %Pixels; #IMPLIED)
+	 * (mayscript (mayscript) #IMPLIED)
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %coreattrs;
+		attributeCollection.getCore(attributes);
+
+		String[] names = {HTML40Namespace.ATTR_NAME_CODEBASE, HTML40Namespace.ATTR_NAME_ARCHIVE, HTML40Namespace.ATTR_NAME_CODE, HTML40Namespace.ATTR_NAME_OBJECT, HTML40Namespace.ATTR_NAME_ALT, HTML40Namespace.ATTR_NAME_NAME, HTML40Namespace.ATTR_NAME_WIDTH, HTML40Namespace.ATTR_NAME_HEIGHT, HTML40Namespace.ATTR_NAME_HSPACE, HTML40Namespace.ATTR_NAME_VSPACE, HTML40Namespace.ATTR_NAME_MAYSCRIPT};
+		attributeCollection.getDeclarations(attributes, Arrays.asList(names).iterator());
+
+		// %align; ... should be defined locally.
+		HTMLAttrDeclImpl attr = AttributeCollection.createAlignForImage();
+		if (attr != null)
+			attributes.putNamedItem(HTML40Namespace.ATTR_NAME_ALIGN, attr);
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedAREA.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedAREA.java
new file mode 100644
index 0000000..322e65c
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedAREA.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+
+
+/**
+ * AREA.
+ */
+final class HedAREA extends HedEmpty {
+
+	/**
+	 */
+	public HedAREA(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.AREA, collection);
+		// LAYOUT_HIDDEN.
+		// Because, AREA is GROUP_HIDDEN in the C++DOM/DTDParser.cpp.
+		layoutType = LAYOUT_HIDDEN;
+	}
+
+	/**
+	 * AREA.
+	 * %attrs;
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+
+		//different sets of attributes for html 4 & 5
+		attributeCollection.createAttributeDeclarations(HTML40Namespace.ElementName.AREA, attributes);
+	
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedBASE.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedBASE.java
new file mode 100644
index 0000000..e528814
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedBASE.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.util.Arrays;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+
+
+/**
+ * BASE.
+ */
+final class HedBASE extends HedEmpty {
+
+	/**
+	 */
+	public HedBASE(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.BASE, collection);
+		// LAYOUT_HIDDEN.
+		// Because, BASE is GROUP_HIDDEN in the C++DOM/DTDParser.cpp.
+		layoutType = LAYOUT_HIDDEN;
+	}
+
+	/**
+	 * BASE.
+	 * (href %URI; #IMPLIED)
+	 * (target %FrameTarget; #IMPLIED)
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		String[] names = {HTML40Namespace.ATTR_NAME_HREF, HTML40Namespace.ATTR_NAME_TARGET};
+		attributeCollection.getDeclarations(attributes, Arrays.asList(names).iterator());
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedBASEFONT.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedBASEFONT.java
new file mode 100644
index 0000000..2c9109b
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedBASEFONT.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.util.Arrays;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+
+/**
+ * BASEFONT.
+ */
+final class HedBASEFONT extends HedEmpty {
+
+	/**
+	 */
+	public HedBASEFONT(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.BASEFONT, collection);
+		// LAYOUT_OBJECT - GROUP_NOWRAP.
+		layoutType = LAYOUT_OBJECT;
+	}
+
+	/**
+	 * BASEFONT.
+	 * (id ID #IMPLIED)
+	 * (size CDATA #REQUIRED) ... should be localy defined.
+	 * (color %Color; #IMPLIED)
+	 * (face CDATA #IMPLIED)
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		String[] names = {HTML40Namespace.ATTR_NAME_ID, HTML40Namespace.ATTR_NAME_COLOR, HTML40Namespace.ATTR_NAME_FACE};
+		attributeCollection.getDeclarations(attributes, Arrays.asList(names).iterator());
+
+		// (size CDATA #REQUIRED) ... should be localy defined.
+		HTMLCMDataTypeImpl atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+		HTMLAttrDeclImpl attr = new HTMLAttrDeclImpl(HTML40Namespace.ATTR_NAME_SIZE, atype, CMAttributeDeclaration.REQUIRED);
+		attributes.putNamedItem(HTML40Namespace.ATTR_NAME_SIZE, attr);
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedBDO.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedBDO.java
new file mode 100644
index 0000000..bcee51f
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedBDO.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.util.Arrays;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+
+/**
+ * BDO.
+ */
+final class HedBDO extends HedInlineContainer {
+
+	/**
+	 */
+	public HedBDO(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.BDO, collection);
+		// CORRECT_EMPTY - GROUP_COMPACT
+		correctionType = CORRECT_EMPTY;
+	}
+
+	/**
+	 * %coreattrs;
+	 * (lang %LanguageCode; #IMPLIED)
+	 * (dir (ltr|rtl) #REQUIRED) ... should be defined locally.
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %coreattrs;
+		attributeCollection.getCore(attributes);
+
+		String[] names = {HTML40Namespace.ATTR_NAME_LANG};
+		attributeCollection.getDeclarations(attributes, Arrays.asList(names).iterator());
+
+		//  (dir (ltr|rtl) #REQUIRED) ... should be defined locally.
+		HTMLCMDataTypeImpl atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+		String[] values = {HTML40Namespace.ATTR_VALUE_LTR, HTML40Namespace.ATTR_VALUE_RTL};
+		atype.setEnumValues(values);
+
+		HTMLAttrDeclImpl attr = new HTMLAttrDeclImpl(HTML40Namespace.ATTR_NAME_DIR, atype, CMAttributeDeclaration.REQUIRED);
+		attributes.putNamedItem(HTML40Namespace.ATTR_NAME_DIR, attr);
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedBGSOUND.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedBGSOUND.java
new file mode 100644
index 0000000..3e731d8
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedBGSOUND.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+
+
+
+final class HedBGSOUND extends HedEmpty {
+
+	public HedBGSOUND(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.BGSOUND, collection);
+		layoutType = LAYOUT_OBJECT;
+	}
+
+	/**
+	 * (src, CDATA, #IMPLIED)
+	 * (loop, CDATA, #IMPLIED)
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return;
+		if (attributeCollection == null)
+			return; // fatal
+		attributes = new CMNamedNodeMapImpl();
+		// src
+		HTMLAttributeDeclaration attr = attributeCollection.getDeclaration(HTML40Namespace.ATTR_NAME_SRC);
+		if (attr != null)
+			attributes.putNamedItem(HTML40Namespace.ATTR_NAME_SRC, attr);
+		// loop
+		HTMLCMDataTypeImpl atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+		atype.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, HTML40Namespace.ATTR_VALUE_INFINITE);
+		attr = new HTMLAttrDeclImpl(HTML40Namespace.ATTR_NAME_LOOP, atype, CMAttributeDeclaration.OPTIONAL);
+		if (attr != null)
+			attributes.putNamedItem(HTML40Namespace.ATTR_NAME_LOOP, attr);
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedBLOCKQUOTE.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedBLOCKQUOTE.java
new file mode 100644
index 0000000..d1cb608
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedBLOCKQUOTE.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.util.Arrays;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+
+/**
+ * BLOCKQUOTE.
+ */
+final class HedBLOCKQUOTE extends HedFlowContainer {
+
+	/**
+	 */
+	public HedBLOCKQUOTE(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.BLOCKQUOTE, collection);
+		correctionType = CORRECT_EMPTY;
+		layoutType = LAYOUT_BLOCK;
+	}
+
+	/**
+	 * %attrs;
+	 * (cite %URI; #IMPLIED) 
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+
+		String[] names = {HTML40Namespace.ATTR_NAME_CITE};
+		attributeCollection.getDeclarations(attributes, Arrays.asList(names).iterator());
+	}
+
+	/**
+	 */
+	public CMNamedNodeMap getProhibitedAncestors() {
+		if (prohibitedAncestors != null)
+			return prohibitedAncestors;
+
+		String[] names = {HTML40Namespace.ElementName.DIR, HTML40Namespace.ElementName.MENU};
+		prohibitedAncestors = elementCollection.getDeclarations(names);
+
+		return prohibitedAncestors;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedBODY.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedBODY.java
new file mode 100644
index 0000000..3324a9a
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedBODY.java
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.util.Arrays;
+import java.util.Iterator;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMContent;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+
+/**
+ * BODY.
+ */
+final class HedBODY extends HedFlowContainer {
+
+	private static String[] terminators = {HTML40Namespace.ElementName.HEAD, HTML40Namespace.ElementName.BODY, HTML40Namespace.ElementName.FRAMESET, HTML40Namespace.ElementName.HTML};
+
+	/**
+	 */
+	public HedBODY(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.BODY, collection);
+		layoutType = LAYOUT_BLOCK;
+		omitType = OMIT_BOTH;
+	}
+
+	/**
+	 * %attrs;
+	 * %bodycolors;
+	 * (onload %Script; #IMPLIED)
+	 * (onunload %Script; #IMPLIED)
+	 * (background %URI; #IMPLIED)
+	 * (marginwidth %Pixels; #IMPLIED) ... D205514
+	 * (marginheight %Pixels; #IMPLIED) .. D205514
+	 * (topmargin, CDATA, #IMPLIED) ...... D205514
+	 * (bottommargin, CDATA, #IMPLIED) ... D205514
+	 * (leftmargin, CDATA, #IMPLIED) ..... D205514
+	 * (rightmargin, CDATA, #IMPLIED) .... D205514
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+		// %bodycolors;
+		attributeCollection.getBodycolors(attributes);
+
+		String[] names = {HTML40Namespace.ATTR_NAME_ONLOAD, HTML40Namespace.ATTR_NAME_ONUNLOAD, HTML40Namespace.ATTR_NAME_BACKGROUND,
+		// <<D205514
+					HTML40Namespace.ATTR_NAME_MARGINWIDTH, HTML40Namespace.ATTR_NAME_MARGINHEIGHT, HTML40Namespace.ATTR_NAME_TOPMARGIN, HTML40Namespace.ATTR_NAME_BOTTOMMARGIN, HTML40Namespace.ATTR_NAME_LEFTMARGIN, HTML40Namespace.ATTR_NAME_RIGHTMARGIN
+		// D205514
+		};
+		attributeCollection.getDeclarations(attributes, Arrays.asList(names).iterator());
+	}
+
+	/**
+	 * Inclusion.
+	 * "Lazy eval."<br>
+	 * @return org.eclipse.wst.xml.core.internal.contentmodel.CMContent
+	 */
+	public CMContent getInclusion() {
+		if (inclusion != null)
+			return inclusion; // already created.
+		if (elementCollection == null)
+			return null;
+
+		// (INS|DEL)
+		inclusion = new CMGroupImpl(CMGroup.CHOICE, 1, 1);
+		String[] names = {HTML40Namespace.ElementName.INS, HTML40Namespace.ElementName.DEL};
+		elementCollection.getDeclarations(inclusion, Arrays.asList(names).iterator());
+		return inclusion;
+	}
+
+	/**
+	 * BODY has terminators.
+	 * @return java.util.Iterator
+	 */
+	protected Iterator getTerminators() {
+		return Arrays.asList(terminators).iterator();
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedBR.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedBR.java
new file mode 100644
index 0000000..45fa6ce
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedBR.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+
+
+
+/**
+ * BR.
+ */
+final class HedBR extends HedEmpty {
+
+	/**
+	 */
+	public HedBR(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.BR, collection);
+		// LAYOUT_BREAK.
+		// Because, BR is GROUP_BREAK in the C++DOM/DTDParser.cpp.
+		layoutType = LAYOUT_BREAK;
+	}
+
+	/**
+	 * BR.
+	 * %coreattrs;
+	 * (clear (left | all | right | none) none)
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %coreattrs;
+		attributeCollection.getCore(attributes);
+		// clear
+		HTMLAttributeDeclaration attr = attributeCollection.getDeclaration(HTML40Namespace.ATTR_NAME_CLEAR);
+		if (attr != null)
+			attributes.putNamedItem(HTML40Namespace.ATTR_NAME_CLEAR, attr);
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedBUTTON.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedBUTTON.java
new file mode 100644
index 0000000..6ace2cb
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedBUTTON.java
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.util.Arrays;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMContent;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+
+/**
+ * BUTTON.
+ */
+final class HedBUTTON extends HedFlowContainer {
+
+	/**
+	 */
+	public HedBUTTON(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.BUTTON, collection);
+		layoutType = LAYOUT_BLOCK;
+	}
+
+	/**
+	 * %attrs;
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+		
+		//different sets of attributes for html 4 & 5
+		attributeCollection.createAttributeDeclarations(HTML40Namespace.ElementName.BUTTON, attributes);
+	
+	}
+
+	/**
+	 * Exclusion.
+	 * <code>FORM</code> has the exclusion.
+	 * It is <code>FORM</code> itself.
+	 */
+	public CMContent getExclusion() {
+		if (exclusion != null)
+			return exclusion; // already created.
+		if (elementCollection == null)
+			return null; // fatal
+
+		exclusion = new CMGroupImpl(CMGroup.CHOICE, 1, 1);
+		String[] names = {HTML40Namespace.ElementName.A, HTML40Namespace.ElementName.FORM, HTML40Namespace.ElementName.ISINDEX, HTML40Namespace.ElementName.FIELDSET, HTML40Namespace.ElementName.IFRAME};
+		elementCollection.getDeclarations(exclusion, Arrays.asList(names).iterator());
+		elementCollection.getFormctrl(exclusion);
+
+		return exclusion;
+	}
+
+	/**
+	 */
+	public CMNamedNodeMap getProhibitedAncestors() {
+		if (prohibitedAncestors != null)
+			return prohibitedAncestors;
+
+		String[] names = {HTML40Namespace.ElementName.BUTTON};
+		prohibitedAncestors = elementCollection.getDeclarations(names);
+
+		return prohibitedAncestors;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedCANVAS.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedCANVAS.java
new file mode 100644
index 0000000..453fb1c
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedCANVAS.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+import java.util.Arrays;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.html.core.internal.provisional.HTML50Namespace;
+
+
+
+/**
+ * CANVAS.
+ */
+final class HedCANVAS extends HTMLElemDeclImpl {
+
+	/**
+	 */
+	public HedCANVAS(ElementCollection collection) {
+		super(HTML50Namespace.ElementName.CANVAS, collection);
+		layoutType = LAYOUT_BLOCK;
+	}
+
+	/**
+	 * %attrs;
+	 * (height, width)
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+		
+		
+		String[] names = { HTML40Namespace.ATTR_NAME_WIDTH, HTML40Namespace.ATTR_NAME_HEIGHT };
+		attributeCollection.getDeclarations(attributes, Arrays.asList(names).iterator());
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedCAPTION.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedCAPTION.java
new file mode 100644
index 0000000..82b07dc
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedCAPTION.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+
+
+
+/**
+ * CAPTION.
+ */
+final class HedCAPTION extends HedInlineContainer {
+
+	/**
+	 */
+	public HedCAPTION(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.CAPTION, collection);
+		layoutType = LAYOUT_BLOCK;
+	}
+
+	/**
+	 * %attrs;
+	 * (align %CAlign; #IMPLIED) ... should be defined locally.
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+
+		HTMLAttrDeclImpl attr = AttributeCollection.createAlignForCaption();
+		if (attr != null)
+			attributes.putNamedItem(HTML40Namespace.ATTR_NAME_ALIGN, attr);
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedCENTER.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedCENTER.java
new file mode 100644
index 0000000..9d5184f
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedCENTER.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+
+/**
+ * CENTER.
+ */
+final class HedCENTER extends HedFlowContainer {
+
+	/**
+	 */
+	public HedCENTER(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.CENTER, collection);
+		layoutType = LAYOUT_BLOCK;
+	}
+
+	/**
+	 * %attrs;
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+	}
+
+	/**
+	 */
+	public CMNamedNodeMap getProhibitedAncestors() {
+		if (prohibitedAncestors != null)
+			return prohibitedAncestors;
+
+		String[] names = {HTML40Namespace.ElementName.DIR, HTML40Namespace.ElementName.MENU};
+		prohibitedAncestors = elementCollection.getDeclarations(names);
+
+		return prohibitedAncestors;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedCOL.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedCOL.java
new file mode 100644
index 0000000..14f3226
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedCOL.java
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.util.Arrays;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+
+/**
+ * COL.
+ */
+final class HedCOL extends HedEmpty {
+
+	/**
+	 */
+	public HedCOL(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.COL, collection);
+		// LAYOUT_BLOCK.
+		// Because, COL is GROUP_BLOCK in the C++DOM/DTDParser.cpp.
+		layoutType = LAYOUT_BLOCK;
+	}
+
+	/**
+	 * COL.
+	 * %attrs;
+	 * (span NUMBER 1)
+	 * (width %MultiLength; #IMPLIED) ... should be defined locally.
+	 * %cellhalign;
+	 * %cellvalign;
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+
+		// (span NUMBER 1)
+		String[] names = {HTML40Namespace.ATTR_NAME_SPAN};
+		attributeCollection.getDeclarations(attributes, Arrays.asList(names).iterator());
+
+		// (width %MultiLength; #IMPLIED) ... should be defined locally.
+		HTMLCMDataTypeImpl atype = new HTMLCMDataTypeImpl(HTMLCMDataType.MULTI_LENGTH);
+		HTMLAttrDeclImpl attr = new HTMLAttrDeclImpl(HTML40Namespace.ATTR_NAME_WIDTH, atype, CMAttributeDeclaration.OPTIONAL);
+		attributes.putNamedItem(HTML40Namespace.ATTR_NAME_WIDTH, attr);
+
+		// %cellhalign;
+		attributeCollection.getCellhalign(attributes);
+		// %cellvalign;
+		attributeCollection.getCellvalign(attributes);
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedCOLGROUP.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedCOLGROUP.java
new file mode 100644
index 0000000..bd2e74f
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedCOLGROUP.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.util.Arrays;
+import java.util.Iterator;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+
+/**
+ * COLGROUP.
+ */
+final class HedCOLGROUP extends HTMLElemDeclImpl {
+
+	private static String[] terminators = {HTML40Namespace.ElementName.COLGROUP, HTML40Namespace.ElementName.CAPTION, HTML40Namespace.ElementName.THEAD, HTML40Namespace.ElementName.TBODY, HTML40Namespace.ElementName.TFOOT, HTML40Namespace.ElementName.TR};
+
+	public HedCOLGROUP(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.COLGROUP, collection);
+		typeDefinitionName = ComplexTypeDefinitionFactory.CTYPE_COLUMN_GROUP;
+		layoutType = LAYOUT_BLOCK;
+		omitType = OMIT_END;
+		indentChild = true;
+	}
+
+	/**
+	 * %attrs;
+	 * (span NUMBER 1)
+	 * (width %MultiLength; #IMPLIED) ... should be defined locally.
+	 * %cellhalign;
+	 * %cellvalign;
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+		// %cellhalign;
+		attributeCollection.getCellhalign(attributes);
+		// %cellvalign;
+		attributeCollection.getCellvalign(attributes);
+
+		String[] names = {HTML40Namespace.ATTR_NAME_SPAN};
+		attributeCollection.getDeclarations(attributes, Arrays.asList(names).iterator());
+
+		// (width %MultiLength; #IMPLIED) ... should be defined locally.
+		HTMLCMDataTypeImpl atype = new HTMLCMDataTypeImpl(HTMLCMDataType.MULTI_LENGTH);
+		HTMLAttrDeclImpl attr = new HTMLAttrDeclImpl(HTML40Namespace.ATTR_NAME_WIDTH, atype, CMAttributeDeclaration.OPTIONAL);
+		attributes.putNamedItem(HTML40Namespace.ATTR_NAME_WIDTH, attr);
+	}
+
+	/**
+	 * LI has terminators.
+	 * @return java.util.Iterator
+	 */
+	protected Iterator getTerminators() {
+		return Arrays.asList(terminators).iterator();
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedCOMMAND.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedCOMMAND.java
new file mode 100644
index 0000000..3fc7c03
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedCOMMAND.java
@@ -0,0 +1,94 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.html.core.internal.provisional.HTML50Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+
+/**
+ * COMMAND.
+ */
+final class HedCOMMAND extends HTMLElemDeclImpl {
+
+	/**
+	 */
+	public HedCOMMAND(ElementCollection collection) {
+		super(HTML50Namespace.ElementName.COMMAND, collection);
+		layoutType = LAYOUT_OBJECT;
+	}
+
+	/**
+	 * COMMAND.
+	 * %attrs;
+	 * // (type %CommandTYPE; command | checkbox|radio) 
+	 * // (label %CDATA; #REQUIRED) 
+	 * // (icon %URI; #OPTIONAL) 
+	 * // (disabled %BOOLEAN; #OPTIONAL) 
+	 * // (checked %BOOLEAN; #OPTIONAL) 
+	 * // (radiogroup %TEXT; #OPTIONAL) 
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+
+		HTMLCMDataTypeImpl atype = null;
+		HTMLAttrDeclImpl attr = null;
+		// (type %CommandTYPE; command | checkbox|radio) 
+		// NOTE: %InputType is ENUM;
+		atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+		String[] values = {HTML50Namespace.ATTR_VALUE_COMMAND, HTML40Namespace.ATTR_VALUE_CHECKBOX, HTML40Namespace.ATTR_VALUE_RADIO};
+		atype.setEnumValues(values);
+		atype.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, HTML50Namespace.ATTR_VALUE_COMMAND);
+		attr = new HTMLAttrDeclImpl(HTML40Namespace.ATTR_NAME_TYPE, atype, CMAttributeDeclaration.OPTIONAL);
+		attributes.putNamedItem(HTML40Namespace.ATTR_NAME_TYPE, attr);
+		
+		// (label %CDATA; #REQUIRED) 
+		atype = new HTMLCMDataTypeImpl(HTMLCMDataType.TEXT);
+		attr = new HTMLAttrDeclImpl(HTML40Namespace.ATTR_NAME_LABEL, atype, CMAttributeDeclaration.REQUIRED);
+		attributes.putNamedItem(HTML40Namespace.ATTR_NAME_LABEL, attr);
+
+		// (icon %URI; #OPTIONAL) 
+		atype = new HTMLCMDataTypeImpl(CMDataType.URI);
+		attr = new HTMLAttrDeclImpl(HTML50Namespace.ATTR_NAME_ICON, atype, CMAttributeDeclaration.OPTIONAL);
+		attributes.putNamedItem(HTML50Namespace.ATTR_NAME_ICON, attr);
+
+		
+		// (disabled %BOOLEAN; #OPTIONAL) 
+		atype = new HTMLCMDataTypeImpl(HTMLCMDataType.BOOLEAN);
+		atype.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, HTML40Namespace.ATTR_VALUE_FALSE);
+		attr = new HTMLAttrDeclImpl(HTML40Namespace.ATTR_NAME_DISABLED, atype, CMAttributeDeclaration.OPTIONAL);
+		attributes.putNamedItem(HTML40Namespace.ATTR_NAME_DISABLED, attr);
+
+		// (checked %BOOLEAN; #OPTIONAL) 
+		atype = new HTMLCMDataTypeImpl(HTMLCMDataType.BOOLEAN);
+		atype.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, HTML40Namespace.ATTR_VALUE_FALSE);
+		attr = new HTMLAttrDeclImpl(HTML40Namespace.ATTR_NAME_CHECKED, atype, CMAttributeDeclaration.OPTIONAL);
+		attributes.putNamedItem(HTML40Namespace.ATTR_NAME_CHECKED, attr);
+
+		// (radiogroup %TEXT; #OPTIONAL) 
+		atype = new HTMLCMDataTypeImpl(HTMLCMDataType.TEXT);
+		attr = new HTMLAttrDeclImpl(HTML50Namespace.ATTR_NAME_RADIOGROUP, atype, CMAttributeDeclaration.OPTIONAL);
+		attributes.putNamedItem(HTML50Namespace.ATTR_NAME_RADIOGROUP, attr);
+
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedDATALIST.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedDATALIST.java
new file mode 100644
index 0000000..ba671c6
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedDATALIST.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.html.core.internal.provisional.HTML50Namespace;
+
+/**
+ * DATALIST.
+ */
+final class HedDATALIST extends HTMLElemDeclImpl {
+
+	/**
+	 */
+	public HedDATALIST(ElementCollection collection) {
+		super(HTML50Namespace.ElementName.DATALIST, collection);
+		typeDefinitionName = ComplexTypeDefinitionFactory.CTYPE_DATALIST;
+		layoutType = LAYOUT_OBJECT;
+		indentChild = true;
+	}
+
+	/**
+	 * %attrs;
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedDD.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedDD.java
new file mode 100644
index 0000000..6004f84
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedDD.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.util.Arrays;
+import java.util.Iterator;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+
+
+/**
+ * DD.
+ */
+final class HedDD extends HedFlowContainer {
+
+	private static String[] terminators = {HTML40Namespace.ElementName.DT, HTML40Namespace.ElementName.DD};
+
+	/**
+	 */
+	public HedDD(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.DD, collection);
+		correctionType = CORRECT_EMPTY;
+		layoutType = LAYOUT_BLOCK;
+		omitType = OMIT_END_DEFAULT;
+	}
+
+	/**
+	 * %attrs;
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+	}
+
+	/**
+	 * DD has terminators.
+	 * @return java.util.Iterator
+	 */
+	protected Iterator getTerminators() {
+		return Arrays.asList(terminators).iterator();
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedDETAILS.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedDETAILS.java
new file mode 100644
index 0000000..a4e8f01
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedDETAILS.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML50Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+public class HedDETAILS extends HTMLElemDeclImpl {
+
+	public HedDETAILS(ElementCollection collection) {
+		super(HTML50Namespace.ElementName.DETAILS, collection);
+		typeDefinitionName = ComplexTypeDefinitionFactory.CTYPE_DETAILS_CONTAINER;
+	}
+
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+
+		CMNode node = attributeCollection.getDeclaration(HTML50Namespace.ATTR_NAME_OPEN);
+		if (node != null)
+			attributes.putNamedItem(HTML50Namespace.ATTR_NAME_OPEN, node);
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedDIV.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedDIV.java
new file mode 100644
index 0000000..b2cd2bc
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedDIV.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+
+/**
+ * DIV.
+ */
+final class HedDIV extends HedFlowContainer {
+
+	/**
+	 */
+	public HedDIV(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.DIV, collection);
+		layoutType = LAYOUT_BLOCK;
+	}
+
+	/**
+	 * %attrs;
+	 * %align;
+	 * %reserved;
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+		// %align;
+		HTMLAttrDeclImpl attr = AttributeCollection.createAlignForParagraph();
+		if (attr != null)
+			attributes.putNamedItem(HTML40Namespace.ATTR_NAME_ALIGN, attr);
+		// %reserved; ... empty
+	}
+
+	/**
+	 */
+	public CMNamedNodeMap getProhibitedAncestors() {
+		if (prohibitedAncestors != null)
+			return prohibitedAncestors;
+
+		String[] names = {HTML40Namespace.ElementName.DIR, HTML40Namespace.ElementName.MENU};
+		prohibitedAncestors = elementCollection.getDeclarations(names);
+
+		return prohibitedAncestors;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedDL.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedDL.java
new file mode 100644
index 0000000..a45f2f8
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedDL.java
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.util.Arrays;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+
+/**
+ * DL.
+ */
+final class HedDL extends HTMLElemDeclImpl {
+
+	/**
+	 */
+	public HedDL(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.DL, collection);
+		typeDefinitionName = ComplexTypeDefinitionFactory.CTYPE_DEFINITION_LIST;
+		correctionType = CORRECT_EMPTY;
+		layoutType = LAYOUT_BLOCK;
+		indentChild = true;
+	}
+
+	/**
+	 * %arrays;
+	 * (compact (compact) #IMPLIED)
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+
+		String[] names = {HTML40Namespace.ATTR_NAME_COMPACT};
+		attributeCollection.getDeclarations(attributes, Arrays.asList(names).iterator());
+	}
+
+	/**
+	 */
+	public CMNamedNodeMap getProhibitedAncestors() {
+		if (prohibitedAncestors != null)
+			return prohibitedAncestors;
+
+		String[] names = {HTML40Namespace.ElementName.DIR, HTML40Namespace.ElementName.MENU};
+		prohibitedAncestors = elementCollection.getDeclarations(names);
+
+		return prohibitedAncestors;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedDT.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedDT.java
new file mode 100644
index 0000000..c4797fb
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedDT.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.util.Arrays;
+import java.util.Iterator;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+
+
+/**
+ * DT.
+ */
+final class HedDT extends HedInlineContainer {
+
+	private static String[] terminators = {HTML40Namespace.ElementName.DT, HTML40Namespace.ElementName.DD};
+
+	/**
+	 */
+	public HedDT(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.DT, collection);
+		correctionType = CORRECT_EMPTY;
+		layoutType = LAYOUT_BLOCK;
+		omitType = OMIT_END_DEFAULT;
+	}
+
+	/**
+	 * %attrs;
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+	}
+
+	/**
+	 * DT has terminators.
+	 * @return java.util.Iterator
+	 */
+	protected Iterator getTerminators() {
+		return Arrays.asList(terminators).iterator();
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedEMBED.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedEMBED.java
new file mode 100644
index 0000000..c1e301d
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedEMBED.java
@@ -0,0 +1,94 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.util.Arrays;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+
+/**
+ * EMBED.
+ */
+final class HedEMBED extends HTMLElemDeclImpl {
+
+	/**
+	 */
+	public HedEMBED(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.EMBED, collection);
+		typeDefinitionName = ComplexTypeDefinitionFactory.CTYPE_EMBED;
+		layoutType = LAYOUT_OBJECT;
+		omitType = OMIT_END_DEFAULT;
+	}
+
+	/**
+	 * %coreattrs;
+	 * %events;
+	 * (src %URI; #REQUIRED) ... should be defined locally.
+	 * (height %Length; #IMPLIED)
+	 * (width %Length; #IMPLIED)
+	 * (align %IAlign; #IMPLIED) ... should be defined locally.
+	 * (hspace %Pixels; #IMPLIED)
+	 * (vspace %Pixels; #IMPLIED)
+	 * (loop CDATA #IMPLIED)
+	 * (hidden CDATA #IMPLIED)
+	 * (volume CDATA #IMPLIED)
+	 * (autostart (true|false) #IMPLIED)
+	 * (autoplay (true|false) #IMPLIED)
+	 * (autosize (true|false) #IMPLIED)
+	 * (controller (true|false) true)
+	 * (scale CDATA #IMPLIED)
+	 * (showcontrols (true|false) #IMPLIED)
+	 * (playcount NUMBER #IMPLIED)
+	 * (repeat CDATA #IMPLIED)
+	 * (panel CDATA #IMPLIED)
+	 * (text CDATA #IMPLIED)
+	 * (palette CDATA #IMPLIED)
+	 * (textfocus CDATA #IMPLIED)
+	 * (type CDATA #IMPLIED) ... should be defined locally.
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %coreattrs;
+		attributeCollection.getCore(attributes);
+		// %events;
+		attributeCollection.getEvents(attributes);
+
+		String[] names = {HTML40Namespace.ATTR_NAME_HEIGHT, HTML40Namespace.ATTR_NAME_WIDTH, HTML40Namespace.ATTR_NAME_HSPACE, HTML40Namespace.ATTR_NAME_VSPACE, HTML40Namespace.ATTR_NAME_LOOP, HTML40Namespace.ATTR_NAME_HIDDEN, HTML40Namespace.ATTR_NAME_VOLUME, HTML40Namespace.ATTR_NAME_AUTOSTART, HTML40Namespace.ATTR_NAME_AUTOPLAY, HTML40Namespace.ATTR_NAME_AUTOSIZE, HTML40Namespace.ATTR_NAME_CONTROLLER, HTML40Namespace.ATTR_NAME_SCALE, HTML40Namespace.ATTR_NAME_SHOWCONTROLS, HTML40Namespace.ATTR_NAME_PLAYCOUNT, HTML40Namespace.ATTR_NAME_REPEAT, HTML40Namespace.ATTR_NAME_PANEL, HTML40Namespace.ATTR_NAME_TEXT, HTML40Namespace.ATTR_NAME_PALETTE, HTML40Namespace.ATTR_NAME_TEXTFOCUS};
+		attributeCollection.getDeclarations(attributes, Arrays.asList(names).iterator());
+
+		HTMLCMDataTypeImpl atype = null;
+		HTMLAttrDeclImpl attr = null;
+		// (src %URI; #REQUIRED) ... should be defined locally.
+		atype = new HTMLCMDataTypeImpl(CMDataType.URI);
+		attr = new HTMLAttrDeclImpl(HTML40Namespace.ATTR_NAME_SRC, atype, CMAttributeDeclaration.REQUIRED);
+		attributes.putNamedItem(HTML40Namespace.ATTR_NAME_SRC, attr);
+
+		// (align %IAlign; #IMPLIED) ... should be defined locally.
+		attr = AttributeCollection.createAlignForImage();
+		if (attr != null)
+			attributes.putNamedItem(HTML40Namespace.ATTR_NAME_ALIGN, attr);
+
+		// (type CDATA #IMPLIED) ... should be defined locally.
+		atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+		attr = new HTMLAttrDeclImpl(HTML40Namespace.ATTR_NAME_TYPE, atype, CMAttributeDeclaration.OPTIONAL);
+		attributes.putNamedItem(HTML40Namespace.ATTR_NAME_TYPE, attr);
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedEmpty.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedEmpty.java
new file mode 100644
index 0000000..4a24b80
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedEmpty.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMContent;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+
+/**
+ * Base class for EMPTY type element declarations.
+ */
+abstract class HedEmpty extends HTMLElemDeclImpl {
+
+	/**
+	 */
+	public HedEmpty(String elementName, ElementCollection collection) {
+		super(elementName, collection);
+		typeDefinitionName = ComplexTypeDefinitionFactory.CTYPE_EMPTY;
+		// EMPTY type has no end tag.
+		omitType = OMIT_END_MUST;
+	}
+
+	/**
+	 * Content.<br>
+	 * EMPTY type always returns <code>null</code>.
+	 * <br>
+	 * @return org.eclipse.wst.xml.core.internal.contentmodel.CMContent
+	 */
+	public CMContent getContent() {
+		return null;
+	}
+
+	/**
+	 * Content type.<br>
+	 * @see org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration
+	 */
+	public int getContentType() {
+		return CMElementDeclaration.EMPTY;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedFIELDSET.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedFIELDSET.java
new file mode 100644
index 0000000..3e0d7ff
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedFIELDSET.java
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+
+/**
+ * FIELDSET.
+ */
+final class HedFIELDSET extends HTMLElemDeclImpl {
+
+	/**
+	 */
+	public HedFIELDSET(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.FIELDSET, collection);
+		typeDefinitionName = ComplexTypeDefinitionFactory.CTYPE_FIELDSET;
+		layoutType = LAYOUT_BLOCK;
+	}
+
+	/**
+	 * %attrs;
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+		//different sets of attributes for html 4 & 5
+		attributeCollection.createAttributeDeclarations(HTML40Namespace.ElementName.FIELDSET, attributes);
+	
+	}
+
+	/**
+	 */
+	public CMNamedNodeMap getProhibitedAncestors() {
+		if (prohibitedAncestors != null)
+			return prohibitedAncestors;
+
+		String[] names = {HTML40Namespace.ElementName.BUTTON, HTML40Namespace.ElementName.DIR, HTML40Namespace.ElementName.MENU};
+		prohibitedAncestors = elementCollection.getDeclarations(names);
+
+		return prohibitedAncestors;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedFIGCAPTION.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedFIGCAPTION.java
new file mode 100644
index 0000000..9b6162c
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedFIGCAPTION.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML50Namespace;
+
+public class HedFIGCAPTION extends HedFlowContainer {
+	public HedFIGCAPTION(ElementCollection collection) {
+		super(HTML50Namespace.ElementName.FIGCAPTION, collection);
+		layoutType = LAYOUT_HIDDEN;
+	}
+
+	/**
+	 * Article.
+	 * %attrs;
+	 * Global attributes
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedFIGURE.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedFIGURE.java
new file mode 100644
index 0000000..87a4610
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedFIGURE.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.html.core.internal.provisional.HTML50Namespace;
+
+/**
+ * FIGURE.
+ */
+final class HedFIGURE extends HTMLElemDeclImpl {
+
+	/**
+	 */
+	public HedFIGURE(ElementCollection collection) {
+		super(HTML50Namespace.ElementName.FIGURE, collection);
+		typeDefinitionName = ComplexTypeDefinitionFactory.CTYPE_FIGURE;
+		layoutType = LAYOUT_BLOCK;
+		indentChild = true;
+	}
+
+	/**
+	 * %attrs;
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+
+	}
+	
+
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedFONT.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedFONT.java
new file mode 100644
index 0000000..61dd455
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedFONT.java
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.util.Arrays;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+
+/**
+ * FONT.
+ */
+final class HedFONT extends HedInlineContainer {
+
+	/**
+	 */
+	public HedFONT(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.FONT, collection);
+		// CORRECT_EMPTY - GROUP_COMPACT
+		correctionType = CORRECT_EMPTY;
+	}
+
+	/**
+	 * %coreattrs;
+	 * %i18n;
+	 * (size CDATA #IMPLIED) ... should be defined locally.
+	 * (color %Color; #IMPLIED)
+	 * (face CDATA #IMPLIED)
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %coreattrs;
+		attributeCollection.getCore(attributes);
+		// %i18n;
+		attributeCollection.getI18n(attributes);
+
+		String[] names = {HTML40Namespace.ATTR_NAME_COLOR, HTML40Namespace.ATTR_NAME_FACE};
+		attributeCollection.getDeclarations(attributes, Arrays.asList(names).iterator());
+
+		// (size CDATA #IMPLIED) ... should be defined locally.
+		HTMLCMDataTypeImpl atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+		HTMLAttrDeclImpl attr = new HTMLAttrDeclImpl(HTML40Namespace.ATTR_NAME_SIZE, atype, CMAttributeDeclaration.OPTIONAL);
+		attributes.putNamedItem(HTML40Namespace.ATTR_NAME_SIZE, attr);
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedFORM.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedFORM.java
new file mode 100644
index 0000000..9986faa
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedFORM.java
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.util.Arrays;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMContent;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ * FORM.
+ */
+final class HedFORM extends HedFlowContainer {
+
+	/**
+	 */
+	public HedFORM(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.FORM, collection);
+		layoutType = LAYOUT_BLOCK;
+	}
+
+	/**
+	 * %attrs;
+	 * (action %URI; #REQUIRED)
+	 * (method (GET|POST) GET)
+	 * (enctype %ContentType; "application/x-www-form-urlencoded")
+	 * (accept %ContentTypes; #IMPLIED)
+	 * (name CDATA #IMPLIED)
+	 * (onsubmit %Script; #IMPLIED)
+	 * (onreset %Script; #IMPLIED)
+	 * (target %FrameTarget; #IMPLIED)
+	 * (accept-charset %Charsets; #IMPLIED)
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+
+		String[] names = {HTML40Namespace.ATTR_NAME_ACTION, HTML40Namespace.ATTR_NAME_METHOD, HTML40Namespace.ATTR_NAME_ENCTYPE, HTML40Namespace.ATTR_NAME_ACCEPT, HTML40Namespace.ATTR_NAME_NAME, HTML40Namespace.ATTR_NAME_ONSUBMIT, HTML40Namespace.ATTR_NAME_ONRESET, HTML40Namespace.ATTR_NAME_TARGET, HTML40Namespace.ATTR_NAME_ACCEPT_CHARSET};
+		attributeCollection.getDeclarations(attributes, Arrays.asList(names).iterator());
+	}
+
+	/**
+	 * Exclusion.
+	 * <code>FORM</code> has the exclusion.
+	 * It is <code>FORM</code> itself.
+	 */
+	public CMContent getExclusion() {
+		if (exclusion != null)
+			return exclusion; // already created.
+		if (elementCollection == null)
+			return null; // fatal
+
+		exclusion = new CMGroupImpl(CMGroup.CHOICE, 1, 1);
+		CMNode form = elementCollection.getNamedItem(HTML40Namespace.ElementName.FORM);
+		if (form != null)
+			exclusion.appendChild(form);
+
+		return exclusion;
+	}
+
+	/**
+	 */
+	public CMNamedNodeMap getProhibitedAncestors() {
+		if (prohibitedAncestors != null)
+			return prohibitedAncestors;
+
+		String[] names = {HTML40Namespace.ElementName.BUTTON, HTML40Namespace.ElementName.DIR, HTML40Namespace.ElementName.FORM, HTML40Namespace.ElementName.MENU};
+		prohibitedAncestors = elementCollection.getDeclarations(names);
+
+		return prohibitedAncestors;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedFRAME.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedFRAME.java
new file mode 100644
index 0000000..768fe24
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedFRAME.java
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.util.Arrays;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+
+
+/**
+ * FRAME.
+ */
+final class HedFRAME extends HedEmpty {
+
+	/**
+	 */
+	public HedFRAME(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.FRAME, collection);
+		// LAYOUT_HIDDEN.
+		// Because, FRAME is GROUP_HIDDEN in the C++DOM/DTDParser.cpp.
+		layoutType = LAYOUT_HIDDEN;
+	}
+
+	/**
+	 * FRAME.
+	 * %coreattrs;
+	 * (longdesc %URI; #IMPLIED)
+	 * (name CDATA #IMPLIED)
+	 * (src %URI; #IMPLIED)
+	 * (frameborder (1|0) 1)
+	 * (marginwidth %Pixels; #IMPLIED)
+	 * (marginheight %Pixels; #IMPLIED)
+	 * (noresize (noresize) #IMPLIED)
+	 * (scrolling (yes|no|auto) auto)
+	 * (bordercolor %Color #IMPLIED) ... D205514
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %coreattrs;
+		attributeCollection.getCore(attributes);
+
+		String[] names = {HTML40Namespace.ATTR_NAME_LONGDESC, HTML40Namespace.ATTR_NAME_NAME, HTML40Namespace.ATTR_NAME_SRC, HTML40Namespace.ATTR_NAME_FRAMEBORDER, HTML40Namespace.ATTR_NAME_MARGINWIDTH, HTML40Namespace.ATTR_NAME_MARGINHEIGHT, HTML40Namespace.ATTR_NAME_NORESIZE, HTML40Namespace.ATTR_NAME_SCROLLING, HTML40Namespace.ATTR_NAME_BORDERCOLOR // D20554
+		};
+		attributeCollection.getDeclarations(attributes, Arrays.asList(names).iterator());
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedFRAMESET.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedFRAMESET.java
new file mode 100644
index 0000000..66000dc
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedFRAMESET.java
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.util.Arrays;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+
+/**
+ * FRAMESET.
+ */
+final class HedFRAMESET extends HTMLElemDeclImpl {
+
+	/**
+	 */
+	public HedFRAMESET(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.FRAMESET, collection);
+		typeDefinitionName = ComplexTypeDefinitionFactory.CTYPE_FRAMESET;
+		layoutType = LAYOUT_HIDDEN;
+		indentChild = true;
+	}
+
+	/**
+	 * %coreattrs;
+	 * (rows %MultiLengths; #IMPLIED) ... should be defined locally.
+	 * (cols %MultiLengths; #IMPLIED) ... should be defined locally.
+	 * (onload %Script; #IMPLIED)
+	 * (onunload %Script; #IMPLIED)
+	 * (frameborder (yes|no) #IMPLIED) ... should be defined locally.
+	 * (border %Pixels; #IMPLIED)
+	 * (bordercolor %Color #IMPLIED) ... D205514
+	 * (framespacing CDATA #IMPLIED) ... D215684
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getCore(attributes);
+
+		String[] names = {HTML40Namespace.ATTR_NAME_ONLOAD, HTML40Namespace.ATTR_NAME_ONUNLOAD, HTML40Namespace.ATTR_NAME_BORDER, HTML40Namespace.ATTR_NAME_BORDERCOLOR, // D205514
+					HTML40Namespace.ATTR_NAME_FRAMESPACING // D215684
+		};
+		attributeCollection.getDeclarations(attributes, Arrays.asList(names).iterator());
+
+		HTMLCMDataTypeImpl atype = null;
+		HTMLAttrDeclImpl attr = null;
+		// (rows %MultiLengths; #IMPLIED) ... should be defined locally.
+		atype = new HTMLCMDataTypeImpl(HTMLCMDataType.MULTI_LENGTH);
+		attr = new HTMLAttrDeclImpl(HTML40Namespace.ATTR_NAME_ROWS, atype, CMAttributeDeclaration.OPTIONAL);
+		attributes.putNamedItem(HTML40Namespace.ATTR_NAME_ROWS, attr);
+
+		// (cols %MultiLengths; #IMPLIED) ... should be defined locally.
+		attr = new HTMLAttrDeclImpl(HTML40Namespace.ATTR_NAME_COLS, atype, CMAttributeDeclaration.OPTIONAL);
+		attributes.putNamedItem(HTML40Namespace.ATTR_NAME_COLS, attr);
+
+		// (frameborder (yes|no) #IMPLIED) ... should be defined locally.
+		atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+		String[] values = {HTML40Namespace.ATTR_VALUE_YES, HTML40Namespace.ATTR_VALUE_NO};
+		atype.setEnumValues(values);
+		attr = new HTMLAttrDeclImpl(HTML40Namespace.ATTR_NAME_FRAMEBORDER, atype, CMAttributeDeclaration.OPTIONAL);
+		attributes.putNamedItem(HTML40Namespace.ATTR_NAME_FRAMEBORDER, attr);
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedFlowContainer.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedFlowContainer.java
new file mode 100644
index 0000000..bf211b2
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedFlowContainer.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+/**
+ * Base class for (%flow;)* containers.
+ */
+abstract class HedFlowContainer extends HTMLElemDeclImpl {
+
+	/**
+	 */
+	public HedFlowContainer(String elementName, ElementCollection collection) {
+		super(elementName, collection);
+		typeDefinitionName = ComplexTypeDefinitionFactory.CTYPE_FLOW_CONTAINER;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedFontStyle.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedFontStyle.java
new file mode 100644
index 0000000..d86b142
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedFontStyle.java
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+
+/**
+ * %fontstyle;
+ */
+final class HedFontStyle extends HedInlineContainer {
+
+	/**
+	 */
+	public HedFontStyle(String elementName, ElementCollection collection) {
+		super(elementName, collection);
+		if (elementName.equalsIgnoreCase(HTML40Namespace.ElementName.BIG) || elementName.equalsIgnoreCase(HTML40Namespace.ElementName.SMALL)) {
+			correctionType = CORRECT_EMPTY;
+		}
+		else { // B, I, U, ...
+			correctionType = CORRECT_DUPLICATED;
+		}
+	}
+
+	/**
+	 * %attrs;
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+	}
+
+	/**
+	 */
+	public CMNamedNodeMap getProhibitedAncestors() {
+		String myName = getElementName();
+		if (!myName.equalsIgnoreCase(HTML40Namespace.ElementName.BIG) && !myName.equalsIgnoreCase(HTML40Namespace.ElementName.SMALL))
+			return EMPTY_MAP;
+		if (prohibitedAncestors != null)
+			return prohibitedAncestors;
+
+		String[] names = {HTML40Namespace.ElementName.PRE};
+		prohibitedAncestors = elementCollection.getDeclarations(names);
+
+		return prohibitedAncestors;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedHEAD.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedHEAD.java
new file mode 100644
index 0000000..691a061
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedHEAD.java
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.util.Arrays;
+import java.util.Iterator;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+
+
+/**
+ * HTML.
+ */
+final class HedHEAD extends HTMLElemDeclImpl {
+
+	private static String[] terminators = {HTML40Namespace.ElementName.HEAD, HTML40Namespace.ElementName.BODY, HTML40Namespace.ElementName.FRAMESET, HTML40Namespace.ElementName.HTML};
+
+	/**
+	 */
+	public HedHEAD(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.HEAD, collection);
+		typeDefinitionName = ComplexTypeDefinitionFactory.CTYPE_HEAD;
+		layoutType = LAYOUT_HIDDEN;
+		omitType = OMIT_BOTH;
+	}
+
+	/**
+	 * Create all attribute declarations.
+	 * This method is called once in the constructor of the super class.
+	 * The <code>HEAD</code> element may have the following attributes:
+	 * <table>
+	 * <tbody>
+	 *   <tr>
+	 *     <th>NAME</th><th>TYPE</th><th>USAGE</th><th>DEFAULT (INITIAL) VALUE</th><th>MEMO</th>
+	 *   </tr>
+	 *   <tr>
+	 *     <td>%i18n;</td><td>-</td><td>-</td><td>-</td><td>-</td>
+	 *   </tr>
+	 *   <tr>
+	 *     <td>profile</td><td>URI</td><td>#IMPLIED</td><td>N/A</td><td>-</td>
+	 *   </tr>
+	 * </tbody>
+	 * </table>
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %i18n;
+		attributeCollection.getI18n(attributes);
+		// profile
+		HTMLAttributeDeclaration adec = attributeCollection.getDeclaration(HTML40Namespace.ATTR_NAME_PROFILE);
+		if (adec != null)
+			attributes.putNamedItem(HTML40Namespace.ATTR_NAME_PROFILE, adec);
+	}
+
+	/**
+	 * HEAD has terminators.
+	 * @return java.util.Iterator
+	 */
+	protected Iterator getTerminators() {
+		return Arrays.asList(terminators).iterator();
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedHEADER.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedHEADER.java
new file mode 100644
index 0000000..5e72a35
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedHEADER.java
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML50Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMContent;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+public class HedHEADER extends HedFlowContainer {
+
+	public HedHEADER(String name, ElementCollection collection) {
+		super(name, collection);
+	}
+
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+	}
+
+	/**
+	 * Exclusion.
+	 * <code>HEADER</code> has the exclusion.
+	 * It is <code>HEADER</code> and <code>FOOTER</code>.
+	 */
+	public CMContent getExclusion() {
+		if (exclusion != null)
+			return exclusion; // already created.
+		if (elementCollection == null)
+			return null; // fatal
+
+		exclusion = new CMGroupImpl(CMGroup.CHOICE, 1, 1);
+		CMNode node = elementCollection.getNamedItem(HTML50Namespace.ElementName.HEADER);
+		if (node != null)
+			exclusion.appendChild(node);
+		node = elementCollection.getNamedItem(HTML50Namespace.ElementName.FOOTER);
+		if (node != null)
+			exclusion.appendChild(node);
+
+		return exclusion;
+	}
+
+	/**
+	 */
+	public CMNamedNodeMap getProhibitedAncestors() {
+		if (prohibitedAncestors != null)
+			return prohibitedAncestors;
+
+		String[] names = {HTML50Namespace.ElementName.HEADER, HTML50Namespace.ElementName.FOOTER};
+		prohibitedAncestors = elementCollection.getDeclarations(names);
+
+		return prohibitedAncestors;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedHGROUP.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedHGROUP.java
new file mode 100644
index 0000000..3bb51a4
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedHGROUP.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.html.core.internal.provisional.HTML50Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+
+public class HedHGROUP extends HTMLElemDeclImpl {
+
+	public HedHGROUP(ElementCollection collection) {
+		super(HTML50Namespace.ElementName.HGROUP, collection);
+		typeDefinitionName = ComplexTypeDefinitionFactory.CTYPE_HEADING_CONTAINER;
+		correctionType = CORRECT_EMPTY;
+		layoutType = LAYOUT_BLOCK;
+		indentChild = true;
+	}
+
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+	}
+
+	/**
+	 */
+	public CMNamedNodeMap getProhibitedAncestors() {
+		if (prohibitedAncestors != null)
+			return prohibitedAncestors;
+
+		String[] names = {HTML40Namespace.ElementName.DIR, HTML40Namespace.ElementName.MENU};
+		prohibitedAncestors = elementCollection.getDeclarations(names);
+
+		return prohibitedAncestors;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedHR.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedHR.java
new file mode 100644
index 0000000..868b5c7
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedHR.java
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.util.Arrays;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+
+/**
+ * HR.
+ */
+final class HedHR extends HedEmpty {
+
+	/**
+	 */
+	public HedHR(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.HR, collection);
+		layoutType = LAYOUT_BLOCK;
+	}
+
+	/**
+	 * %attrs
+	 * (align (left|center|right) #IMPLIED) ... should be defined locally.
+	 * (noshade (noshade) #IMPLIED)
+	 * (size %Pixels; #IMPLIED)
+	 * (width %Length; #IMPLIED)
+	 * (color %Color; #IMPLIED) ... D205514
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+
+		// (align (left|center|right) #IMPLIED) ... should be defined locally.
+		HTMLCMDataTypeImpl atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+		String[] values = {HTML40Namespace.ATTR_VALUE_LEFT, HTML40Namespace.ATTR_VALUE_CENTER, HTML40Namespace.ATTR_VALUE_RIGHT};
+		atype.setEnumValues(values);
+		HTMLAttrDeclImpl attr = new HTMLAttrDeclImpl(HTML40Namespace.ATTR_NAME_ALIGN, atype, CMAttributeDeclaration.OPTIONAL);
+		attributes.putNamedItem(HTML40Namespace.ATTR_NAME_ALIGN, attr);
+
+		// the rest.
+		String[] names = {HTML40Namespace.ATTR_NAME_NOSHADE, HTML40Namespace.ATTR_NAME_SIZE, HTML40Namespace.ATTR_NAME_WIDTH, HTML40Namespace.ATTR_NAME_COLOR // D205514
+		};
+		attributeCollection.getDeclarations(attributes, Arrays.asList(names).iterator());
+	}
+
+	/**
+	 */
+	public CMNamedNodeMap getProhibitedAncestors() {
+		if (prohibitedAncestors != null)
+			return prohibitedAncestors;
+
+		String[] names = {HTML40Namespace.ElementName.DIR, HTML40Namespace.ElementName.MENU};
+		prohibitedAncestors = elementCollection.getDeclarations(names);
+
+		return prohibitedAncestors;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedHTML.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedHTML.java
new file mode 100644
index 0000000..e393d04
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedHTML.java
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.util.Arrays;
+import java.util.Iterator;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+
+
+/**
+ * HTML.
+ */
+final class HedHTML extends HTMLElemDeclImpl {
+
+	private static String[] terminators = {HTML40Namespace.ElementName.HTML};
+
+	/**
+	 */
+	public HedHTML(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.HTML, collection);
+		typeDefinitionName = ComplexTypeDefinitionFactory.CTYPE_HTML;
+		layoutType = LAYOUT_HIDDEN;
+		omitType = OMIT_BOTH;
+	}
+
+	/**
+	 * Create all attribute declarations.
+	 * This method is called once in the constructor of the super class.
+	 * The <code>HTML</code> element may have the following attributes:
+	 * <table>
+	 * <tbody>
+	 *   <tr>
+	 *     <th>NAME</th><th>TYPE</th><th>USAGE</th><th>DEFAULT (INITIAL) VALUE</th><th>MEMO</th>
+	 *   </tr>
+	 *   <tr>
+	 *     <td><code>%i18n;</code></td><td>-</td><td>-</td><td>-</td>
+	 *     <td>{@link PDCMDocImpl#getAttrDeclarationsI18n}</td>
+	 *   </tr>
+	 *   <tr>
+	 *     <td>version</td><td>CDATA</td><td>#FIXED</td>
+	 *     <td>{@link HTML_VERSION_TRANSITIONAL}</td><td>deplecated in HTML4.01</td>
+	 *   </tr>
+	 * </tbody>
+	 * </table>
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		//different sets of attributes for html 4 & 5
+		attributeCollection.createAttributeDeclarations(HTML40Namespace.ElementName.HTML, attributes);
+	
+		}
+
+	/**
+	 * HTML has terminators.
+	 * @return java.util.Iterator
+	 */
+	protected Iterator getTerminators() {
+		return Arrays.asList(terminators).iterator();
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedHeading.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedHeading.java
new file mode 100644
index 0000000..6a17c16
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedHeading.java
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+
+/**
+ * H[1-6].
+ */
+final class HedHeading extends HedInlineContainer {
+
+	/**
+	 */
+	public HedHeading(String elementName, ElementCollection collection) {
+		super(elementName, collection);
+		correctionType = CORRECT_EMPTY;
+		layoutType = LAYOUT_BLOCK;
+	}
+
+	/**
+	 * Create all attribute declarations.
+	 * This method is called once in the constructor of the super class.
+	 * The <code>H1</code> element may have the following attributes:
+	 * <table>
+	 * <tbody>
+	 *   <tr>
+	 *     <th>NAME</th><th>TYPE</th><th>USAGE</th><th>DEFAULT (INITIAL) VALUE</th><th>MEMO</th>
+	 *   </tr>
+	 *   <tr>
+	 *     <td>%attrs;</td><td>-</td><td>-</td><td>-</td><td>-</td>
+	 *   </tr>
+	 *   <tr>
+	 *     <td>%align;</td><td>-</td><td>-</td><td>-</td><td>-</td>
+	 *   </tr>
+	 * </tbody>
+	 * </table>
+	 * <p><b>%align;</b> means <code>align (left|center|right|justify) #IMPLIED</code>.
+	 * Unfortunately, this <code>align</code> is different from one in
+	 * <code>IMG</code> or <code>TABLE</code>.  So, the attribute declaration
+	 * of <code>align</code> should be localy created and it shouldn't be registered
+	 * in a <code>HCMDocImpl</code> instance.</p>
+	 * <p>However, %align is used in sevaral times.  I wouldn't write same code
+	 * in many times.  So, I add a new utility method into <code>CMUtil</code>
+	 * to create the attribute declaration.</p>
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+		// align
+		HTMLAttrDeclImpl attr = AttributeCollection.createAlignForParagraph();
+		if (attr != null)
+			attributes.putNamedItem(HTML40Namespace.ATTR_NAME_ALIGN, attr);
+	}
+
+	/**
+	 */
+	public CMNamedNodeMap getProhibitedAncestors() {
+		if (prohibitedAncestors != null)
+			return prohibitedAncestors;
+
+		String[] names = {HTML40Namespace.ElementName.DIR, HTML40Namespace.ElementName.MENU};
+		prohibitedAncestors = elementCollection.getDeclarations(names);
+
+		return prohibitedAncestors;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedIFRAME.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedIFRAME.java
new file mode 100644
index 0000000..0e4c564
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedIFRAME.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+
+/**
+ * IFRAME.
+ */
+final class HedIFRAME extends HedFlowContainer {
+
+	/**
+	 */
+	public HedIFRAME(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.IFRAME, collection);
+		layoutType = LAYOUT_OBJECT;
+	}
+
+	
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		//different sets of attributes for html 4 & 5
+		attributeCollection.createAttributeDeclarations(HTML40Namespace.ElementName.IFRAME, attributes);
+	
+	}
+
+	/**
+	 */
+	public CMNamedNodeMap getProhibitedAncestors() {
+		if (prohibitedAncestors != null)
+			return prohibitedAncestors;
+
+		String[] names = {HTML40Namespace.ElementName.BUTTON};
+		prohibitedAncestors = elementCollection.getDeclarations(names);
+
+		return prohibitedAncestors;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedIMG.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedIMG.java
new file mode 100644
index 0000000..b719416
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedIMG.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+
+/**
+ * IMG.
+ */
+final class HedIMG extends HedEmpty {
+
+	/**
+	 */
+	public HedIMG(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.IMG, collection);
+		layoutType = LAYOUT_OBJECT;
+	}
+
+	/**
+	 * IMG.
+	 * %attrs;
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+
+		//different sets of attributes for html 4 & 5
+		attributeCollection.createAttributeDeclarations(HTML40Namespace.ElementName.IMG, attributes);
+	
+	}
+
+	/**
+	 */
+	public CMNamedNodeMap getProhibitedAncestors() {
+		if (prohibitedAncestors != null)
+			return prohibitedAncestors;
+
+		String[] names = {HTML40Namespace.ElementName.PRE};
+		prohibitedAncestors = elementCollection.getDeclarations(names);
+
+		return prohibitedAncestors;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedINPUT.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedINPUT.java
new file mode 100644
index 0000000..9080201
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedINPUT.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+
+/**
+ * INPUT.
+ */
+final class HedINPUT extends HedEmpty {
+
+	/**
+	 */
+	public HedINPUT(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.INPUT, collection);
+		layoutType = LAYOUT_OBJECT;
+	}
+
+	/**
+	 * INPUT.
+	 * %attrs;
+	
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+
+		//different sets of attributes for html 4 & 5
+		attributeCollection.createAttributeDeclarations(HTML40Namespace.ElementName.INPUT, attributes);
+	}
+
+	/**
+	 */
+	public CMNamedNodeMap getProhibitedAncestors() {
+		if (prohibitedAncestors != null)
+			return prohibitedAncestors;
+
+		String[] names = {HTML40Namespace.ElementName.BUTTON};
+		prohibitedAncestors = elementCollection.getDeclarations(names);
+
+		return prohibitedAncestors;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedISINDEX.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedISINDEX.java
new file mode 100644
index 0000000..8c744d6
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedISINDEX.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+
+/**
+ * ISINDEX.
+ */
+final class HedISINDEX extends HedEmpty {
+
+	/**
+	 */
+	public HedISINDEX(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.ISINDEX, collection);
+		layoutType = LAYOUT_BLOCK;
+	}
+
+	/**
+	 * ISINDEX.
+	 * %coreattrs;
+	 * %i18n;
+	 * (prompt %Text; #IMPLIED)
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %coreattrs;
+		attributeCollection.getCore(attributes);
+		// %i18n;
+		attributeCollection.getI18n(attributes);
+
+		HTMLAttributeDeclaration attr = attributeCollection.getDeclaration(HTML40Namespace.ATTR_NAME_PROMPT);
+		if (attr != null)
+			attributes.putNamedItem(HTML40Namespace.ATTR_NAME_PROMPT, attr);
+	}
+
+	/**
+	 */
+	public CMNamedNodeMap getProhibitedAncestors() {
+		if (prohibitedAncestors != null)
+			return prohibitedAncestors;
+
+		String[] names = {HTML40Namespace.ElementName.BUTTON, HTML40Namespace.ElementName.DIR, HTML40Namespace.ElementName.MENU};
+		prohibitedAncestors = elementCollection.getDeclarations(names);
+
+		return prohibitedAncestors;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedInlineContainer.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedInlineContainer.java
new file mode 100644
index 0000000..dd08221
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedInlineContainer.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+/**
+ * Base class for (%inline;)* containers.
+ */
+abstract class HedInlineContainer extends HTMLElemDeclImpl {
+
+	/**
+	 * HedInlineContainer.
+	 * @param elementName java.lang.String
+	 * @param collection ElementCollection
+	 */
+	public HedInlineContainer(String elementName, ElementCollection collection) {
+		super(elementName, collection);
+		typeDefinitionName = ComplexTypeDefinitionFactory.CTYPE_INLINE_CONTAINER;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedKEYGEN.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedKEYGEN.java
new file mode 100644
index 0000000..c84b30a
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedKEYGEN.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+import java.util.Arrays;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.html.core.internal.provisional.HTML50Namespace;
+
+public class HedKEYGEN extends HedEmpty {
+
+	public HedKEYGEN(ElementCollection collection) {
+		super(HTML50Namespace.ElementName.KEYGEN, collection);
+		layoutType = LAYOUT_OBJECT;
+	}
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		attributeCollection.getAttrs(attributes);
+
+		String[] names = { HTML50Namespace.ATTR_NAME_AUTOFOCUS, HTML50Namespace.ATTR_NAME_CHALLENGE, HTML40Namespace.ATTR_NAME_DISABLED, HTML50Namespace.ATTR_NAME_FORM, HTML50Namespace.ATTR_NAME_KEYTYPE, HTML40Namespace.ATTR_NAME_NAME};
+		attributeCollection.getDeclarations(attributes, Arrays.asList(names).iterator());
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedLABEL.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedLABEL.java
new file mode 100644
index 0000000..e001032
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedLABEL.java
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.util.Arrays;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMContent;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ * LABEL.
+ */
+final class HedLABEL extends HedInlineContainer {
+
+	/**
+	 */
+	public HedLABEL(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.LABEL, collection);
+	}
+
+	/**
+	 * %attrs;
+	 * (for IDREF #IMPLIED) ... should be defined locally.
+	 * (accesskey %Character; #IMPLIED)
+	 * (onfocus %Script; #IMPLIED)
+	 * (onblur %Script; #IMPLIED)
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+
+		// (for IDREF #IMPLIED) ... should be defined locally.
+		HTMLCMDataTypeImpl atype = new HTMLCMDataTypeImpl(CMDataType.IDREF);
+		HTMLAttrDeclImpl attr = new HTMLAttrDeclImpl(HTML40Namespace.ATTR_NAME_FOR, atype, CMAttributeDeclaration.OPTIONAL);
+		attributes.putNamedItem(HTML40Namespace.ATTR_NAME_FOR, attr);
+
+		String[] names = {HTML40Namespace.ATTR_NAME_ACCESSKEY, HTML40Namespace.ATTR_NAME_ONFOCUS, HTML40Namespace.ATTR_NAME_ONBLUR};
+		attributeCollection.getDeclarations(attributes, Arrays.asList(names).iterator());
+	}
+
+	/**
+	 * Exclusion.
+	 * <code>LABEL</code> has the exclusion.
+	 * It is <code>LABEL</code> itself.
+	 */
+	public CMContent getExclusion() {
+		if (exclusion != null)
+			return exclusion; // already created.
+		if (elementCollection == null)
+			return null;
+
+		exclusion = new CMGroupImpl(CMGroup.CHOICE, 1, 1);
+		CMNode label = elementCollection.getNamedItem(HTML40Namespace.ElementName.LABEL);
+		if (label != null)
+			exclusion.appendChild(label);
+
+		return exclusion;
+	}
+
+	/**
+	 */
+	public CMNamedNodeMap getProhibitedAncestors() {
+		if (prohibitedAncestors != null)
+			return prohibitedAncestors;
+
+		String[] names = {HTML40Namespace.ElementName.BUTTON, HTML40Namespace.ElementName.LABEL};
+		prohibitedAncestors = elementCollection.getDeclarations(names);
+
+		return prohibitedAncestors;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedLEGEND.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedLEGEND.java
new file mode 100644
index 0000000..5e3928b
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedLEGEND.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.util.Arrays;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+
+
+/**
+ * LEGEND.
+ */
+final class HedLEGEND extends HedInlineContainer {
+
+	/**
+	 */
+	public HedLEGEND(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.LEGEND, collection);
+	}
+
+	/**
+	 * (accesskey %Character; #IMPLIED)
+	 * (align %LAlign; #IMPLIED) ... shuld be defined locally.
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+
+		String[] names = {HTML40Namespace.ATTR_NAME_ACCESSKEY};
+		attributeCollection.getDeclarations(attributes, Arrays.asList(names).iterator());
+
+		// align
+		HTMLAttrDeclImpl attr = AttributeCollection.createAlignForLegend();
+		if (attr != null)
+			attributes.putNamedItem(HTML40Namespace.ATTR_NAME_ALIGN, attr);
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedLI.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedLI.java
new file mode 100644
index 0000000..a413193
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedLI.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.util.Arrays;
+import java.util.Iterator;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+
+/**
+ * LI.
+ */
+final class HedLI extends HedFlowContainer {
+
+	private static String[] terminators = {HTML40Namespace.ElementName.LI};
+
+	/**
+	 */
+	public HedLI(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.LI, collection);
+		layoutType = LAYOUT_BLOCK;
+		omitType = OMIT_END_DEFAULT;
+	}
+
+	/**
+	 * %attrs;
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+
+		//different sets of attributes for html 4 & 5
+		attributeCollection.createAttributeDeclarations(HTML40Namespace.ElementName.LI, attributes);
+	
+	}
+
+	/**
+	 * LI has terminators.
+	 * @return java.util.Iterator
+	 */
+	protected Iterator getTerminators() {
+		return Arrays.asList(terminators).iterator();
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedLINK.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedLINK.java
new file mode 100644
index 0000000..4c28bbe
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedLINK.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+
+/**
+ * LINK.
+ */
+final class HedLINK extends HedEmpty {
+
+	/**
+	 */
+	public HedLINK(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.LINK, collection);
+		layoutType = LAYOUT_HIDDEN;
+	}
+
+	/**
+	 * LINK.
+	 * %attrs;
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+
+		// different sets of attributes for html 4 & 5
+		attributeCollection.createAttributeDeclarations(HTML40Namespace.ElementName.LINK, attributes);
+		
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedListItemContainer.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedListItemContainer.java
new file mode 100644
index 0000000..a7ccf63
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedListItemContainer.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+/**
+ * Base class for list item container declarations.
+ * - OL, UL, MENU, DIR.
+ */
+abstract class HedListItemContainer extends HTMLElemDeclImpl {
+
+	/**
+	 */
+	public HedListItemContainer(String elementName, ElementCollection collection) {
+		super(elementName, collection);
+		typeDefinitionName = ComplexTypeDefinitionFactory.CTYPE_LI_CONTAINER;
+		correctionType = CORRECT_EMPTY;
+		layoutType = LAYOUT_BLOCK;
+		indentChild = true;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedMAP.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedMAP.java
new file mode 100644
index 0000000..2a3c2a7
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedMAP.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+
+
+
+/**
+ * MAP.
+ */
+final class HedMAP extends HTMLElemDeclImpl {
+
+	/**
+	 */
+	public HedMAP(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.MAP, collection);
+		typeDefinitionName = ComplexTypeDefinitionFactory.CTYPE_MAP;
+		layoutType = LAYOUT_OBJECT;
+		indentChild = true;
+	}
+
+	/**
+	 * %attrs;
+	 * (name CDATA #REQUIRED) ... should be defined locally
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+
+		// (name CDATA #REQUIRED) ... should be defined locally
+		HTMLCMDataTypeImpl atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+		HTMLAttrDeclImpl attr = new HTMLAttrDeclImpl(HTML40Namespace.ATTR_NAME_NAME, atype, CMAttributeDeclaration.REQUIRED);
+		attributes.putNamedItem(HTML40Namespace.ATTR_NAME_NAME, attr);
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedMARQUEE.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedMARQUEE.java
new file mode 100644
index 0000000..f8653e2
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedMARQUEE.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.util.Arrays;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+
+/**
+ * MARQUEE.
+ */
+final class HedMARQUEE extends HedFlowContainer {
+
+	/**
+	 */
+	public HedMARQUEE(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.MARQUEE, collection);
+		layoutType = LAYOUT_OBJECT;
+	}
+
+	/**
+	 * %attrs;
+	 * (behavior (scroll|slide|alternate) scroll)
+	 * (bgcolor %Color; #IMPLIED)
+	 * (direction (left|right|up|down) left)
+	 * (height CDATA #IMPLIED) ... should be defined locally.
+	 * (hspace NUMBER #IMPLIED) ... should be defined locally.
+	 * (loop CDATA #IMPLIED)
+	 * (scrollamount NUMBER #IMPLIED)
+	 * (scrolldelay NUMBER #IMPLIED)
+	 * (vspace NUMBER #IMPLIED) ... should be defined locally.
+	 * (width CDATA #IMPLIED) ... should be defined locally.
+	 * (truespeed (truespeed) #IMPLIED)
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+
+		String[] names = {HTML40Namespace.ATTR_NAME_BEHAVIOR, HTML40Namespace.ATTR_NAME_BGCOLOR, HTML40Namespace.ATTR_NAME_DIRECTION, HTML40Namespace.ATTR_NAME_LOOP, HTML40Namespace.ATTR_NAME_SCROLLAMOUNT, HTML40Namespace.ATTR_NAME_SCROLLDELAY, HTML40Namespace.ATTR_NAME_TRUESPEED};
+		attributeCollection.getDeclarations(attributes, Arrays.asList(names).iterator());
+
+		HTMLCMDataTypeImpl atype = null;
+		HTMLAttrDeclImpl attr = null;
+		// (height CDATA #IMPLIED) ... should be defined locally.
+		atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+		attr = new HTMLAttrDeclImpl(HTML40Namespace.ATTR_NAME_HEIGHT, atype, CMAttributeDeclaration.OPTIONAL);
+		attributes.putNamedItem(HTML40Namespace.ATTR_NAME_HEIGHT, attr);
+
+		// (width CDATA #IMPLIED) ... should be defined locally.
+		attr = new HTMLAttrDeclImpl(HTML40Namespace.ATTR_NAME_WIDTH, atype, CMAttributeDeclaration.OPTIONAL);
+		attributes.putNamedItem(HTML40Namespace.ATTR_NAME_WIDTH, attr);
+
+		// (hspace NUMBER #IMPLIED) ... should be defined locally.
+		atype = new HTMLCMDataTypeImpl(CMDataType.NUMBER);
+		attr = new HTMLAttrDeclImpl(HTML40Namespace.ATTR_NAME_HSPACE, atype, CMAttributeDeclaration.OPTIONAL);
+		attributes.putNamedItem(HTML40Namespace.ATTR_NAME_HSPACE, attr);
+
+		// (vspace NUMBER #IMPLIED) ... should be defined locally.
+		attr = new HTMLAttrDeclImpl(HTML40Namespace.ATTR_NAME_VSPACE, atype, CMAttributeDeclaration.OPTIONAL);
+		attributes.putNamedItem(HTML40Namespace.ATTR_NAME_VSPACE, attr);
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedMENU.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedMENU.java
new file mode 100644
index 0000000..812af9b
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedMENU.java
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.util.Arrays;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMContent;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+
+/**
+ * MENU/DIR.
+ */
+final class HedMENU extends HedListItemContainer {
+
+	/**
+	 */
+	public HedMENU(String elementName, ElementCollection collection) {
+		super(elementName, collection);
+	}
+
+	/**
+	 * MENU/DIR.
+	*/
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+
+		//different sets of attributes for html 4 & 5
+		attributeCollection.createAttributeDeclarations(HTML40Namespace.ElementName.MENU, attributes);
+	}
+
+	/**
+	 * Exclusion.
+	 * <code>MENU/DIR</code> has the exclusion.
+	 * It is <code>%block;</code>.
+	 * %block; is:
+	 * P | %heading; | %list; | %preformatted; | DL | DIV | CENTER |
+	 * NOSCRIPT | NOFRAMES | BLOCKQUOTE | FORM | ISINDEX | HR |
+	 * TABLE | FIELDSET | ADDRESS.
+	 * %heading; is: H1 | H2 | H3 | H4 | H5 | H6.
+	 * %list; is : UL | OL | DIR | MENU.
+	 * %preformatted; is PRE.
+	 */
+	public CMContent getExclusion() {
+		if (exclusion != null)
+			return exclusion; // already created.
+		if (elementCollection == null)
+			return null;
+
+		// %block;
+		exclusion = new CMGroupImpl(CMGroup.CHOICE, 1, 1);
+		String[] names = {HTML40Namespace.ElementName.P, HTML40Namespace.ElementName.H1, HTML40Namespace.ElementName.H2, HTML40Namespace.ElementName.H3, HTML40Namespace.ElementName.H4, HTML40Namespace.ElementName.H5, HTML40Namespace.ElementName.H6, HTML40Namespace.ElementName.UL, HTML40Namespace.ElementName.OL, HTML40Namespace.ElementName.DIR, HTML40Namespace.ElementName.MENU, HTML40Namespace.ElementName.PRE, HTML40Namespace.ElementName.DL, HTML40Namespace.ElementName.DIV, HTML40Namespace.ElementName.CENTER, HTML40Namespace.ElementName.NOSCRIPT, HTML40Namespace.ElementName.NOFRAMES, HTML40Namespace.ElementName.BLOCKQUOTE, HTML40Namespace.ElementName.FORM, HTML40Namespace.ElementName.ISINDEX, HTML40Namespace.ElementName.HR, HTML40Namespace.ElementName.TABLE, HTML40Namespace.ElementName.FIELDSET, HTML40Namespace.ElementName.ADDRESS};
+		elementCollection.getDeclarations(exclusion, Arrays.asList(names).iterator());
+		return exclusion;
+	}
+
+	/**
+	 */
+	public CMNamedNodeMap getProhibitedAncestors() {
+		if (prohibitedAncestors != null)
+			return prohibitedAncestors;
+
+		String[] names = {HTML40Namespace.ElementName.DIR, HTML40Namespace.ElementName.MENU};
+		prohibitedAncestors = elementCollection.getDeclarations(names);
+
+		return prohibitedAncestors;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedMETA.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedMETA.java
new file mode 100644
index 0000000..92554ea
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedMETA.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+
+/**
+ * META.
+ */
+final class HedMETA extends HedEmpty {
+
+	/**
+	 */
+	public HedMETA(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.META, collection);
+		layoutType = LAYOUT_HIDDEN;
+	}
+
+	/**
+	 * META.
+
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+		
+		//different sets of attributes for html 4 & 5
+		attributeCollection.createAttributeDeclarations(HTML40Namespace.ElementName.META, attributes);
+	
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedMETER.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedMETER.java
new file mode 100644
index 0000000..c79e9e9
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedMETER.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+import java.util.Arrays;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.html.core.internal.provisional.HTML50Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMContent;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+public class HedMETER extends HedInlineContainer {
+
+	public HedMETER(ElementCollection collection) {
+		super(HTML50Namespace.ElementName.METER, collection);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.html.core.internal.contentmodel.HTMLElemDeclImpl#createAttributeDeclarations()
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+		attributeCollection.getAttrs(attributes);
+
+		String[] names = { HTML50Namespace.ATTR_NAME_MIN, HTML50Namespace.ATTR_NAME_MAX, HTML50Namespace.ATTR_NAME_LOW, HTML50Namespace.ATTR_NAME_HIGH, HTML50Namespace.ATTR_NAME_OPTIMUM, HTML50Namespace.ATTR_NAME_FORM };
+		attributeCollection.getDeclarations(attributes, Arrays.asList(names).iterator());
+
+		HTMLCMDataTypeImpl atype = new HTMLCMDataTypeImpl(CMDataType.NUMBER);
+		HTMLAttrDeclImpl decl = new HTMLAttrDeclImpl(HTML40Namespace.ATTR_NAME_VALUE, atype, CMAttributeDeclaration.REQUIRED);
+		attributes.putNamedItem(HTML40Namespace.ATTR_NAME_VALUE, decl);
+	}
+
+	public CMContent getExclusion() {
+		if (exclusion != null)
+			return exclusion; // already created.
+		if (elementCollection == null)
+			return null;
+
+		exclusion = new CMGroupImpl(CMGroup.CHOICE, 1, 1);
+		CMNode meter = elementCollection.getNamedItem(HTML50Namespace.ElementName.METER);
+		if (meter != null)
+			exclusion.appendChild(meter);
+
+		return exclusion;
+	}
+
+	public CMNamedNodeMap getProhibitedAncestors() {
+		if (prohibitedAncestors != null)
+			return prohibitedAncestors;
+
+		String[] names = {HTML50Namespace.ElementName.METER};
+		prohibitedAncestors = elementCollection.getDeclarations(names);
+
+		return prohibitedAncestors;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedMarkChanges.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedMarkChanges.java
new file mode 100644
index 0000000..92c3d0c
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedMarkChanges.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.util.Arrays;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+
+
+/**
+ * (INS|DEL)
+ */
+final class HedMarkChanges extends HedFlowContainer {
+
+	/**
+	 */
+	public HedMarkChanges(String elementName, ElementCollection collection) {
+		super(elementName, collection);
+	}
+
+	/**
+	 * %attrs;
+	 * (cite %URI; #IMPLIED)
+	 * (datetime %Datetime; #IMPLIED) 
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+
+		String[] names = {HTML40Namespace.ATTR_NAME_CITE, HTML40Namespace.ATTR_NAME_DATETIME};
+		attributeCollection.getDeclarations(attributes, Arrays.asList(names).iterator());
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedMath.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedMath.java
new file mode 100644
index 0000000..154dbfa
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedMath.java
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.util.Arrays;
+import java.util.Iterator;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML50Namespace;
+
+
+/**
+ * Math.
+ */
+final class HedMath extends HTMLElemDeclImpl {
+
+	private static String[] terminators = {HTML50Namespace.ElementName.MATH};
+
+	/**
+	 */
+	public HedMath(ElementCollection collection) {
+		super(HTML50Namespace.ElementName.MATH, collection);
+		layoutType = LAYOUT_OBJECT;
+	}
+
+	/**
+	 * Create all attribute declarations.
+	 * MathML namespace
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+	}
+
+	/**
+	 * MATH has terminators.
+	 * @return java.util.Iterator
+	 */
+	protected Iterator getTerminators() {
+		return Arrays.asList(terminators).iterator();
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedMediaElement.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedMediaElement.java
new file mode 100644
index 0000000..d36aa40
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedMediaElement.java
@@ -0,0 +1,95 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.html.core.internal.provisional.HTML50Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+
+/**
+ * EMBED.
+ */
+class HedMediaElement extends HTMLElemDeclImpl {
+
+	/**
+	 */
+	public HedMediaElement(String elementName, ElementCollection collection) {
+		super(elementName, collection);
+		typeDefinitionName = ComplexTypeDefinitionFactory.CTYPE_MEDIA_ELEMENT;
+		layoutType = LAYOUT_OBJECT;
+		indentChild = true;
+	}
+
+	/**
+	 * MediaElement
+	 * %attrs;
+	 * (src %URI; #REQUIRED): should be defined locally.
+	 * (preload %CDATA; #IMPLIED) 
+	 * (autoplay %ENUM; #IMPLIED) 
+	 * (loop %ENUM; #IMPLIED)
+	 * (controls %MediaType; #IMPLIED)
+	 * Global attributes
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+	
+		// (src %URI; #REQUIRED): should be defined locally.
+		HTMLCMDataTypeImpl atype = null;
+		HTMLAttrDeclImpl attr = null;
+		atype = new HTMLCMDataTypeImpl(CMDataType.URI);
+		attr = new HTMLAttrDeclImpl(HTML40Namespace.ATTR_NAME_SRC, atype, CMAttributeDeclaration.REQUIRED);
+		attributes.putNamedItem(HTML40Namespace.ATTR_NAME_SRC, attr);
+
+		//(preload %CDATA; #IMPLIED) ENUM
+		// (none | metadata | auto)
+		atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+		String[] values = {HTML40Namespace.ATTR_VALUE_NONE, HTML50Namespace.ATTR_VALUE_METADATA, HTML40Namespace.ATTR_VALUE_AUTO, HTML50Namespace.ATTR_VALUE_EMPTY};
+		atype.setEnumValues(values);
+		atype.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, HTML40Namespace.ATTR_VALUE_AUTO);
+		attr = new HTMLAttrDeclImpl(HTML50Namespace.ATTR_NAME_PRELOAD, atype, CMAttributeDeclaration.OPTIONAL);
+		attributes.putNamedItem(HTML50Namespace.ATTR_NAME_PRELOAD, attr);
+
+		// (autoplay (boolean) #IMPLIED)
+		atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+		String[] autoPlayValues = {HTML50Namespace.ATTR_NAME_AUTOPLAY};
+		atype.setEnumValues(autoPlayValues);
+		attr = new HTMLAttrDeclImpl(HTML50Namespace.ATTR_NAME_AUTOPLAY, atype, CMAttributeDeclaration.OPTIONAL);
+		attributes.putNamedItem(HTML50Namespace.ATTR_NAME_AUTOPLAY, attr);
+
+		// (loop (boolean) #IMPLIED)
+		atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+		String[] loopValues = {HTML50Namespace.ATTR_NAME_LOOP};
+		atype.setEnumValues(loopValues);
+		attr = new HTMLAttrDeclImpl(HTML50Namespace.ATTR_NAME_LOOP, atype, CMAttributeDeclaration.OPTIONAL);
+		attributes.putNamedItem(HTML50Namespace.ATTR_NAME_LOOP, attr);
+
+		// (controls (boolean) #IMPLIED)
+		atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+		String[] controlValues = {HTML50Namespace.ATTR_NAME_CONTROLS};
+		atype.setEnumValues(controlValues);
+		attr = new HTMLAttrDeclImpl(HTML50Namespace.ATTR_NAME_CONTROLS, atype, CMAttributeDeclaration.OPTIONAL);
+		attributes.putNamedItem(HTML50Namespace.ATTR_NAME_CONTROLS, attr);
+
+		
+		// global attributes
+		attributeCollection.getAttrs(attributes);
+	}
+}
+
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedNOBR.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedNOBR.java
new file mode 100644
index 0000000..42adbd1
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedNOBR.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+
+
+/**
+ * NOBR -- not standard tag but it is commonly used.
+ */
+final class HedNOBR extends HedInlineContainer {
+
+
+	public HedNOBR(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.NOBR, collection);
+		correctionType = HTMLElementDeclaration.CORRECT_DUPLICATED;
+	}
+
+	protected void createAttributeDeclarations() {
+		// No attributes is defined.
+		if (attributes != null)
+			return;
+		attributes = new CMNamedNodeMapImpl();
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedNOEMBED.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedNOEMBED.java
new file mode 100644
index 0000000..ed71166
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedNOEMBED.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+
+
+
+/**
+ * NOEMBED.
+ */
+final class HedNOEMBED extends HedFlowContainer {
+
+	/**
+	 */
+	public HedNOEMBED(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.NOEMBED, collection);
+	}
+
+	/**
+	 * %coreattrs;
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %coreattrs;
+		attributeCollection.getCore(attributes);
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedNOFRAMES.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedNOFRAMES.java
new file mode 100644
index 0000000..2ad931b
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedNOFRAMES.java
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMContent;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ * NOFRAMES.
+ */
+final class HedNOFRAMES extends HTMLElemDeclImpl {
+
+	/**
+	 */
+	public HedNOFRAMES(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.NOFRAMES, collection);
+		typeDefinitionName = ComplexTypeDefinitionFactory.CTYPE_NOFRAMES_CONTENT;
+		layoutType = LAYOUT_HIDDEN;
+	}
+
+	/**
+	 * %attrs;
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+	}
+
+	/**
+	 * Exclusion.
+	 * <code>NOFRAMES</code> has the exclusion.
+	 * It is <code>NOFRAMES</code> itself.
+	 */
+	public CMContent getExclusion() {
+		if (exclusion != null)
+			return exclusion; // already created.
+		if (elementCollection == null)
+			return null;
+
+		exclusion = new CMGroupImpl(CMGroup.CHOICE, 1, 1);
+		CMNode label = elementCollection.getNamedItem(HTML40Namespace.ElementName.NOFRAMES);
+		if (label != null)
+			exclusion.appendChild(label);
+
+		return exclusion;
+	}
+
+	/**
+	 */
+	public CMNamedNodeMap getProhibitedAncestors() {
+		if (prohibitedAncestors != null)
+			return prohibitedAncestors;
+
+		String[] names = {HTML40Namespace.ElementName.DIR, HTML40Namespace.ElementName.MENU, HTML40Namespace.ElementName.NOFRAMES};
+		prohibitedAncestors = elementCollection.getDeclarations(names);
+
+		return prohibitedAncestors;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedNOSCRIPT.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedNOSCRIPT.java
new file mode 100644
index 0000000..2747c23
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedNOSCRIPT.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+
+/**
+ * NOSCRIPT.
+ */
+final class HedNOSCRIPT extends HedFlowContainer {
+
+	/**
+	 */
+	public HedNOSCRIPT(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.NOSCRIPT, collection);
+		layoutType = LAYOUT_BLOCK;
+	}
+
+	/**
+	 * %attrs;
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+	}
+
+	/**
+	 */
+	public CMNamedNodeMap getProhibitedAncestors() {
+		if (prohibitedAncestors != null)
+			return prohibitedAncestors;
+
+		String[] names = {HTML40Namespace.ElementName.DIR, HTML40Namespace.ElementName.MENU};
+		prohibitedAncestors = elementCollection.getDeclarations(names);
+
+		return prohibitedAncestors;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedOBJECT.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedOBJECT.java
new file mode 100644
index 0000000..ad48e2f
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedOBJECT.java
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.util.Arrays;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+
+/**
+ * OBJECT.
+ */
+final class HedOBJECT extends HTMLElemDeclImpl {
+
+	/**
+	 */
+	public HedOBJECT(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.OBJECT, collection);
+		typeDefinitionName = ComplexTypeDefinitionFactory.CTYPE_PARAM_CONTAINER;
+		layoutType = LAYOUT_OBJECT;
+		indentChild = true;
+	}
+
+	/**
+	 * %attrs;
+	 * %reserved; ... empty.
+	 * (declare (declare) #IMPLIED)
+	 * (classid %URI; #IMPLIED)
+	 * (codebase %URI; #IMPLIED)
+	 * (data %URI; #IMPLIED)
+	 * (type %ContentType; #IMPLIED)
+	 * (codetype %ContentType; #IMPLIED)
+	 * (archive CDATA #IMPLIED)
+	 * (standby %Text; #IMPLIED)
+	 * (height %Length; #IMPLIED)
+	 * (width %Length; #IMPLIED)
+	 * (usemap %URI; #IMPLIED)
+	 * (name CDATA #IMPLIED)
+	 * (tabindex NUMBER #IMPLIED)
+	 * (align %IAlign; #IMPLIED) ... should be defined locally.
+	 * (border %Pixels; #IMPLIED)
+	 * (hspace %Pixels; #IMPLIED)
+	 * (vspace %Pixels; #IMPLIED)
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+		// %reserved; ... empty.
+
+		String[] names = {HTML40Namespace.ATTR_NAME_DECLARE, HTML40Namespace.ATTR_NAME_CLASSID, HTML40Namespace.ATTR_NAME_CODEBASE, HTML40Namespace.ATTR_NAME_DATA, HTML40Namespace.ATTR_NAME_TYPE, HTML40Namespace.ATTR_NAME_CODETYPE, HTML40Namespace.ATTR_NAME_ARCHIVE, HTML40Namespace.ATTR_NAME_STANDBY, HTML40Namespace.ATTR_NAME_HEIGHT, HTML40Namespace.ATTR_NAME_WIDTH, HTML40Namespace.ATTR_NAME_USEMAP, HTML40Namespace.ATTR_NAME_NAME, HTML40Namespace.ATTR_NAME_TABINDEX, HTML40Namespace.ATTR_NAME_BORDER, HTML40Namespace.ATTR_NAME_HSPACE, HTML40Namespace.ATTR_NAME_VSPACE};
+		attributeCollection.getDeclarations(attributes, Arrays.asList(names).iterator());
+		// %align; ... should be defined locally.
+		HTMLAttrDeclImpl attr = AttributeCollection.createAlignForImage();
+		if (attr != null)
+			attributes.putNamedItem(HTML40Namespace.ATTR_NAME_ALIGN, attr);
+	}
+
+	/**
+	 */
+	public CMNamedNodeMap getProhibitedAncestors() {
+		if (prohibitedAncestors != null)
+			return prohibitedAncestors;
+
+		String[] names = {HTML40Namespace.ElementName.PRE};
+		prohibitedAncestors = elementCollection.getDeclarations(names);
+
+		return prohibitedAncestors;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedOL.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedOL.java
new file mode 100644
index 0000000..6c6d50c
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedOL.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+
+/**
+ * OL.
+ */
+final class HedOL extends HedListItemContainer {
+
+	/**
+	 */
+	public HedOL(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.OL, collection);
+	}
+
+	/**
+	 * OL.
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+
+		//different sets of attributes for html 4 & 5
+		attributeCollection.createAttributeDeclarations(HTML40Namespace.ElementName.OL, attributes);
+	
+	}
+
+	/**
+	 */
+	public CMNamedNodeMap getProhibitedAncestors() {
+		if (prohibitedAncestors != null)
+			return prohibitedAncestors;
+
+		String[] names = {HTML40Namespace.ElementName.DIR, HTML40Namespace.ElementName.MENU};
+		prohibitedAncestors = elementCollection.getDeclarations(names);
+
+		return prohibitedAncestors;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedOPTGROUP.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedOPTGROUP.java
new file mode 100644
index 0000000..87a3fc3
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedOPTGROUP.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.util.Arrays;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+
+/**
+ * OPTGROUP.
+ */
+final class HedOPTGROUP extends HTMLElemDeclImpl {
+
+	/**
+	 */
+	public HedOPTGROUP(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.OPTGROUP, collection);
+		typeDefinitionName = ComplexTypeDefinitionFactory.CTYPE_OPTION_CONTAINER;
+		layoutType = LAYOUT_HIDDEN;
+		indentChild = true;
+	}
+
+	/**
+	 * %attrs;
+	 * (disabled (disabled) #IMPLIED)
+	 * (label %Text; #REQUIRED) ... should be defined locally.
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+		// (disabled (disabled) #IMPLIED)
+		String[] names = {HTML40Namespace.ATTR_NAME_DISABLED};
+		attributeCollection.getDeclarations(attributes, Arrays.asList(names).iterator());
+
+		// (label %Text; #REQUIRED) ... should be defined locally.
+		HTMLCMDataTypeImpl atype = new HTMLCMDataTypeImpl(HTMLCMDataType.TEXT);
+		HTMLAttrDeclImpl attr = new HTMLAttrDeclImpl(HTML40Namespace.ATTR_NAME_LABEL, atype, CMAttributeDeclaration.REQUIRED);
+		attributes.putNamedItem(HTML40Namespace.ATTR_NAME_LABEL, attr);
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedOPTION.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedOPTION.java
new file mode 100644
index 0000000..b225ee8
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedOPTION.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.util.Arrays;
+import java.util.Iterator;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+
+
+/**
+ * OPTION.
+ */
+final class HedOPTION extends HedPcdata {
+
+	private static String[] terminators = {HTML40Namespace.ElementName.OPTION};
+
+	/**
+	 */
+	public HedOPTION(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.OPTION, collection);
+		layoutType = LAYOUT_HIDDEN;
+		omitType = OMIT_END;
+	}
+
+	/**
+	 * OPTION.
+	 * %attrs;
+	 * (selected (selected) #IMPLIED)
+	 * (disabled (disabled) #IMPLIED)
+	 * (label %Text; #IMPLIED)
+	 * (value CDATA #IMPLIED)
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+
+		String[] names = {HTML40Namespace.ATTR_NAME_SELECTED, HTML40Namespace.ATTR_NAME_DISABLED, HTML40Namespace.ATTR_NAME_LABEL, HTML40Namespace.ATTR_NAME_VALUE};
+		attributeCollection.getDeclarations(attributes, Arrays.asList(names).iterator());
+	}
+
+	/**
+	 * OPTION has terminators.
+	 * @return java.util.Iterator
+	 */
+	protected Iterator getTerminators() {
+		return Arrays.asList(terminators).iterator();
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedOUTPUT.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedOUTPUT.java
new file mode 100644
index 0000000..fc172e1
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedOUTPUT.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+import java.util.Arrays;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.html.core.internal.provisional.HTML50Namespace;
+
+public class HedOUTPUT extends HedInlineContainer {
+
+	public HedOUTPUT(ElementCollection collection) {
+		super(HTML50Namespace.ElementName.OUTPUT, collection);
+	}
+
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+
+		String[] names = { HTML40Namespace.ATTR_NAME_FOR, HTML50Namespace.ATTR_NAME_FORM, HTML40Namespace.ATTR_NAME_NAME};
+		attributeCollection.getDeclarations(attributes, Arrays.asList(names).iterator());
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedP.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedP.java
new file mode 100644
index 0000000..70feed7
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedP.java
@@ -0,0 +1,104 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Vector;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+
+/**
+ * P.
+ */
+final class HedP extends HedInlineContainer {
+
+	private static Collection terminators = null;
+
+	/**
+	 */
+	public HedP(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.P, collection);
+		correctionType = CORRECT_EMPTY;
+		layoutType = LAYOUT_BLOCK;
+		omitType = OMIT_END;
+	}
+
+	/**
+	 * Create all attribute declarations.
+	 * This method is called once in the constructor of the super class.
+	 * The <code>P</code> element may have the following attributes:
+	 * <table>
+	 * <tbody>
+	 *   <tr>
+	 *     <th>NAME</th><th>TYPE</th><th>USAGE</th><th>DEFAULT (INITIAL) VALUE</th><th>MEMO</th>
+	 *   </tr>
+	 *   <tr>
+	 *     <td>%attrs;</td><td>-</td><td>-</td><td>-</td><td>-</td>
+	 *   </tr>
+	 *   <tr>
+	 *     <td>%align;</td><td>-</td><td>-</td><td>-</td><td>-</td>
+	 *   </tr>
+	 * </tbody>
+	 * </table>
+	 * <p><b>%align;</b> means <code>align (left|center|right|justify) #IMPLIED</code>.
+	 * Unfortunately, this <code>align</code> is different from one in
+	 * <code>IMG</code> or <code>TABLE</code>.  So, the attribute declaration
+	 * of <code>align</code> should be localy created and it shouldn't be registered
+	 * in a <code>HCMDocImpl</code> instance.</p>
+	 * <p>However, %align is used in sevaral times.  I wouldn't write same code
+	 * in many times.  So, I add a new utility method into <code>CMUtil</code>
+	 * to create the attribute declaration.</p>
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+		attributes = new CMNamedNodeMapImpl();
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+		// align
+		HTMLAttrDeclImpl adec = AttributeCollection.createAlignForParagraph();
+		attributes.putNamedItem(HTML40Namespace.ATTR_NAME_ALIGN, adec);
+	}
+
+	/**
+	 */
+	public CMNamedNodeMap getProhibitedAncestors() {
+		if (prohibitedAncestors != null)
+			return prohibitedAncestors;
+		String[] names = {HTML40Namespace.ElementName.DIR, HTML40Namespace.ElementName.MENU};
+		prohibitedAncestors = elementCollection.getDeclarations(names);
+		return prohibitedAncestors;
+	}
+
+	/**
+	 * Return names of terminators.
+	 * <code>P</code> has terminators.
+	 * @return java.util.Iterator
+	 */
+	protected Iterator getTerminators() {
+		if (terminators != null)
+			return terminators.iterator();
+		//<<D217982
+		terminators = new Vector();
+		terminators.addAll(elementCollection.getNamesOfBlock());
+		terminators.add(HTML40Namespace.ElementName.LI);
+		terminators.add(HTML40Namespace.ElementName.DT);
+		terminators.add(HTML40Namespace.ElementName.DD);
+		//D217982
+		return terminators.iterator();
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedPARAM.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedPARAM.java
new file mode 100644
index 0000000..1bcea7e
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedPARAM.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+
+/**
+ * PARAM.
+ */
+final class HedPARAM extends HedEmpty {
+
+	/**
+	 */
+	public HedPARAM(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.PARAM, collection);
+		layoutType = LAYOUT_HIDDEN;
+	}
+
+	/**
+	 * PARAM.
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		//different sets of attributes for html 4 & 5
+		attributeCollection.createAttributeDeclarations(HTML40Namespace.ElementName.PARAM, attributes);
+	
+		
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedPRE.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedPRE.java
new file mode 100644
index 0000000..2ba3479
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedPRE.java
@@ -0,0 +1,91 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.util.Arrays;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMContent;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+
+/**
+ * PRE.
+ */
+final class HedPRE extends HedInlineContainer {
+
+	/**
+	 * PRE element should keep spaces in its source.
+	 */
+	public HedPRE(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.PRE, collection);
+		// CORRECT_EMPTY - GROUP_COMPACT
+		correctionType = CORRECT_EMPTY;
+
+		keepSpaces = true;
+	}
+
+	/**
+	 * %attrs;
+	 * (width NUMBER #IMPLIED) ... should be defined locally.
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+		// (width NUMBER #IMPLIED) ... should be defined locally.
+		HTMLCMDataTypeImpl atype = new HTMLCMDataTypeImpl(CMDataType.NUMBER);
+		HTMLAttrDeclImpl attr = new HTMLAttrDeclImpl(HTML40Namespace.ATTR_NAME_WIDTH, atype, CMAttributeDeclaration.OPTIONAL);
+		attributes.putNamedItem(HTML40Namespace.ATTR_NAME_WIDTH, attr);
+	}
+
+	/**
+	 * Exclusion.
+	 * <code>PRE</code> has the exclusion.
+	 * It is <code>%pre.exclusion;</code>.
+	 * %pre.exclusion is:
+	 * IMG | OBJECT | APPLET | BIG | SMALL | SUB | SUP | FONT | BASEFONT
+	 */
+	public CMContent getExclusion() {
+		if (exclusion != null)
+			return exclusion; // already created.
+		if (elementCollection == null)
+			return null;
+
+		exclusion = new CMGroupImpl(CMGroup.CHOICE, 1, 1);
+		String[] names = {HTML40Namespace.ElementName.IMG, HTML40Namespace.ElementName.OBJECT, HTML40Namespace.ElementName.APPLET, HTML40Namespace.ElementName.BIG, HTML40Namespace.ElementName.SMALL, HTML40Namespace.ElementName.SUB, HTML40Namespace.ElementName.SUP, HTML40Namespace.ElementName.FONT, HTML40Namespace.ElementName.BASEFONT};
+		elementCollection.getDeclarations(exclusion, Arrays.asList(names).iterator());
+
+		return exclusion;
+	}
+
+	/**
+	 */
+	public CMNamedNodeMap getProhibitedAncestors() {
+		if (prohibitedAncestors != null)
+			return prohibitedAncestors;
+
+		String[] names = {HTML40Namespace.ElementName.DIR, HTML40Namespace.ElementName.MENU};
+		prohibitedAncestors = elementCollection.getDeclarations(names);
+
+		return prohibitedAncestors;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedPROGRESS.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedPROGRESS.java
new file mode 100644
index 0000000..223c129
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedPROGRESS.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+import java.util.Arrays;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.html.core.internal.provisional.HTML50Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMContent;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+public class HedPROGRESS extends HedInlineContainer {
+
+	public HedPROGRESS(ElementCollection collection) {
+		super(HTML50Namespace.ElementName.PROGRESS, collection);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.html.core.internal.contentmodel.HTMLElemDeclImpl#createAttributeDeclarations()
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+		attributeCollection.getAttrs(attributes);
+
+		String[] names = { HTML40Namespace.ATTR_NAME_VALUE, HTML50Namespace.ATTR_NAME_MAX, HTML50Namespace.ATTR_NAME_FORM };
+		attributeCollection.getDeclarations(attributes, Arrays.asList(names).iterator());
+	}
+
+	public CMContent getExclusion() {
+		if (exclusion != null)
+			return exclusion;
+		if (elementCollection == null)
+			return null;
+
+		exclusion = new CMGroupImpl(CMGroup.CHOICE, 1, 1);
+		CMNode progress = elementCollection.getNamedItem(HTML50Namespace.ElementName.PROGRESS);
+		if (progress != null) {
+			exclusion.appendChild(progress);
+		}
+		return exclusion;
+	}
+
+	public CMNamedNodeMap getProhibitedAncestors() {
+		if (prohibitedAncestors == null) {
+			String[] names = { HTML50Namespace.ElementName.PROGRESS };
+			prohibitedAncestors = elementCollection.getDeclarations(names);
+		}
+		return prohibitedAncestors;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedPcdata.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedPcdata.java
new file mode 100644
index 0000000..5561495
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedPcdata.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMContent;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+
+/**
+ * Base class for PCDATA type element declarations.<br>
+ */
+abstract class HedPcdata extends HTMLElemDeclImpl {
+
+	/**
+	 */
+	public HedPcdata(String elementName, ElementCollection collection) {
+		super(elementName, collection);
+		typeDefinitionName = ComplexTypeDefinitionFactory.CTYPE_PCDATA;
+	}
+
+	/**
+	 * Content.<br>
+	 * PCDATA type always returns <code>null</code>.
+	 * <br>
+	 * @return org.eclipse.wst.xml.core.internal.contentmodel.CMContent
+	 */
+	public CMContent getContent() {
+		return null;
+	}
+
+	/**
+	 * Content type.<br>
+	 * @see org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration
+	 */
+	public int getContentType() {
+		return CMElementDeclaration.PCDATA;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedPhrase.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedPhrase.java
new file mode 100644
index 0000000..0e680d5
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedPhrase.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+/**
+ * %phrase;
+ */
+final class HedPhrase extends HedInlineContainer {
+
+	/**
+	 */
+	public HedPhrase(String elementName, ElementCollection collection) {
+		super(elementName, collection);
+		correctionType = HTMLElementDeclaration.CORRECT_DUPLICATED;
+	}
+
+	/**
+	 * %attrs;
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedQ.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedQ.java
new file mode 100644
index 0000000..185b757
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedQ.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.util.Arrays;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+
+
+/**
+ * Q.
+ */
+final class HedQ extends HedInlineContainer {
+
+	/**
+	 */
+	public HedQ(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.Q, collection);
+		correctionType = CORRECT_DUPLICATED;
+	}
+
+	/**
+	 * %attrs;
+	 * (cite %URI; #IMPLIED) 
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+
+		String[] names = {HTML40Namespace.ATTR_NAME_CITE};
+		attributeCollection.getDeclarations(attributes, Arrays.asList(names).iterator());
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedRP.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedRP.java
new file mode 100644
index 0000000..e31a9bc
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedRP.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.util.Arrays;
+import java.util.Iterator;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML50Namespace;
+
+
+/**
+ * RP.
+ */
+final class HedRP extends HedPcdata {
+
+	private static String[] terminators = {HTML50Namespace.ElementName.RP};
+
+	/**
+	 */
+	public HedRP(ElementCollection collection) {
+		super(HTML50Namespace.ElementName.RP, collection);
+		layoutType = LAYOUT_HIDDEN;
+	}
+
+	/**
+	 * OPTION.
+	 * %attrs;
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+
+	}
+
+	/**
+	 * OPTION has terminators.
+	 * @return java.util.Iterator
+	 */
+	protected Iterator getTerminators() {
+		return Arrays.asList(terminators).iterator();
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedRT.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedRT.java
new file mode 100644
index 0000000..aba4a38
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedRT.java
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.util.Arrays;
+import java.util.Iterator;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML50Namespace;
+
+
+/**
+ * RT.
+ */
+final class HedRT extends HedPcdata {
+
+	private static String[] terminators = {HTML50Namespace.ElementName.RT};
+
+	/**
+	 */
+	public HedRT(ElementCollection collection) {
+		super(HTML50Namespace.ElementName.RT, collection);
+		layoutType = LAYOUT_BLOCK;
+
+	}
+
+	/**
+	 * OPTION.
+	 * %attrs;
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+
+	}
+
+	/**
+	 * OPTION has terminators.
+	 * @return java.util.Iterator
+	 */
+	protected Iterator getTerminators() {
+		return Arrays.asList(terminators).iterator();
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedRUBY.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedRUBY.java
new file mode 100644
index 0000000..6686a25
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedRUBY.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.html.core.internal.provisional.HTML50Namespace;
+
+/**
+ * RUBY.
+ */
+final class HedRUBY extends HTMLElemDeclImpl {
+
+	/**
+	 */
+	public HedRUBY(ElementCollection collection) {
+		super(HTML50Namespace.ElementName.RUBY, collection);
+		typeDefinitionName = ComplexTypeDefinitionFactory.CTYPE_RUBY;
+		layoutType = LAYOUT_BLOCK;
+		indentChild = true;
+	}
+
+	/**
+	 * %attrs;
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedSCRIPT.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedSCRIPT.java
new file mode 100644
index 0000000..2af1317
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedSCRIPT.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMContent;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+
+/**
+ * SCRIPT.
+ */
+final class HedSCRIPT extends HTMLElemDeclImpl {
+
+	/**
+	 */
+	public HedSCRIPT(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.SCRIPT, collection);
+		typeDefinitionName = ComplexTypeDefinitionFactory.CTYPE_CDATA;
+		layoutType = LAYOUT_OBJECT;
+	}
+
+	/**
+	 * SCRIPT.
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		//different sets of attributes for html 4 & 5
+		attributeCollection.createAttributeDeclarations(HTML40Namespace.ElementName.SCRIPT, attributes);
+	
+	}
+
+	/**
+	 * <code>SCRIPT</code> is CDATA type.
+	 * So, the method always returns <code>null</code>.
+	 * <br>
+	 * @return org.eclipse.wst.xml.core.internal.contentmodel.CMContent
+	 */
+	public CMContent getContent() {
+		return null;
+	}
+
+	/**
+	 * CDATA content.<br>
+	 * @return int
+	 */
+	public int getContentType() {
+		return CMElementDeclaration.CDATA;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedSELECT.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedSELECT.java
new file mode 100644
index 0000000..a0de442
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedSELECT.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+
+/**
+ * SELECT.
+ */
+final class HedSELECT extends HTMLElemDeclImpl {
+
+	/**
+	 */
+	public HedSELECT(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.SELECT, collection);
+		typeDefinitionName = ComplexTypeDefinitionFactory.CTYPE_SELECT;
+		layoutType = LAYOUT_OBJECT;
+		indentChild = true;
+	}
+
+	/**
+	 * %attrs;
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+		
+		//different sets of attributes for html 4 & 5
+		attributeCollection.createAttributeDeclarations(HTML40Namespace.ElementName.SELECT, attributes);
+	
+
+	}
+
+	/**
+	 */
+	public CMNamedNodeMap getProhibitedAncestors() {
+		if (prohibitedAncestors != null)
+			return prohibitedAncestors;
+
+		String[] names = {HTML40Namespace.ElementName.BUTTON};
+		prohibitedAncestors = elementCollection.getDeclarations(names);
+
+		return prohibitedAncestors;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedSOURCE.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedSOURCE.java
new file mode 100644
index 0000000..647a9d4
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedSOURCE.java
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.util.Arrays;
+import java.util.Iterator;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.html.core.internal.provisional.HTML50Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+
+/**
+ * SOURCE.
+ */
+final class HedSOURCE extends HTMLElemDeclImpl {
+
+	private static String[] terminators = {HTML50Namespace.ElementName.SOURCE};
+
+	/**
+	 */
+	public HedSOURCE(ElementCollection collection) {
+		super(HTML50Namespace.ElementName.SOURCE, collection);
+		typeDefinitionName = ComplexTypeDefinitionFactory.CTYPE_CDATA;
+		layoutType = LAYOUT_HIDDEN;
+	}
+
+	/**
+	 * SOURCE
+	 * %attrs;
+	 * (src %URI; #REQUIRED): should be defined locally.
+	 * (type %ContentType; #IMPLIED) 
+	 * (media %MediaType; #IMPLIED) 
+	 * Global attributes
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+	
+		// (src %URI; #REQUIRED): should be defined locally.
+		HTMLCMDataTypeImpl atype = null;
+		HTMLAttrDeclImpl attr = null;
+		atype = new HTMLCMDataTypeImpl(CMDataType.URI);
+		attr = new HTMLAttrDeclImpl(HTML40Namespace.ATTR_NAME_SRC, atype, CMAttributeDeclaration.REQUIRED);
+		attributes.putNamedItem(HTML40Namespace.ATTR_NAME_SRC, attr);
+
+		// (type %ContentType; #IMPLIED) 
+		atype = new HTMLCMDataTypeImpl(HTMLCMDataType.CONTENT_TYPE);
+		attr = new HTMLAttrDeclImpl(HTML40Namespace.ATTR_NAME_TYPE, atype, CMAttributeDeclaration.OPTIONAL);
+		attributes.putNamedItem(HTML40Namespace.ATTR_NAME_TYPE, attr);
+		
+
+		// (media %MediaType; #IMPLIED) 
+		atype = new HTMLCMDataTypeImpl(HTMLCMDataType.MEDIA_TYPE);
+		atype.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, HTML40Namespace.ATTR_VALUE_ALL);
+		attr = new HTMLAttrDeclImpl(HTML40Namespace.ATTR_NAME_MEDIA, atype, CMAttributeDeclaration.OPTIONAL);
+		attributes.putNamedItem(HTML40Namespace.ATTR_NAME_MEDIA, attr);
+		
+		
+		// global attributes
+		attributeCollection.getAttrs(attributes);
+	}
+	
+	/**
+	 * SOURCE has terminators.
+	 * @return java.util.Iterator
+	 */
+	protected Iterator getTerminators() {
+		return Arrays.asList(terminators).iterator();
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedSPAN.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedSPAN.java
new file mode 100644
index 0000000..42932f6
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedSPAN.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+
+
+
+/**
+ * SPAN.
+ */
+final class HedSPAN extends HedInlineContainer {
+
+	/**
+	 * SPAN.
+	 */
+	public HedSPAN(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.SPAN, collection);
+	}
+
+	/**
+	 * %attrs;
+	 * %reserved; ... empty.
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedSSIBase.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedSSIBase.java
new file mode 100644
index 0000000..46c7a80
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedSSIBase.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+import org.eclipse.wst.html.core.internal.provisional.HTMLCMProperties;
+
+
+
+/**
+ * Base class for SSI declarations.
+ */
+abstract class HedSSIBase extends HedEmpty {
+
+	/**
+	 */
+	public HedSSIBase(String elementName, ElementCollection collection) {
+		super(elementName, collection);
+		layoutType = LAYOUT_OBJECT;
+	}
+
+	/**
+	 */
+	public int getFormatType() {
+		return HTMLElementDeclaration.FORMAT_SSI;
+	}
+
+	/**
+	 */
+	public boolean supports(String propName) {
+		if (propName.equals(HTMLCMProperties.IS_SSI))
+			return true;
+		return super.supports(propName);
+	}
+
+	/*
+	 */
+	public Object getProperty(String propName) {
+		if (propName.equals(HTMLCMProperties.IS_SSI))
+			return new Boolean(true);
+		return super.getProperty(propName);
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedSSIConfig.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedSSIConfig.java
new file mode 100644
index 0000000..b8406a9
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedSSIConfig.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.util.Arrays;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+
+
+/**
+ * SSI:CONFIG.
+ */
+final class HedSSIConfig extends HedSSIBase {
+
+	/**
+	 */
+	public HedSSIConfig(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.SSI_CONFIG, collection);
+	}
+
+	/**
+	 * SSI:CONFIG.
+	 * (errmsg CDATA #IMPLIED)
+	 * (sizefmt CDATA #IMPLIED)
+	 * (timefmt CDATA #IMPLIED)
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		String[] names = {HTML40Namespace.ATTR_NAME_ERRMSG, HTML40Namespace.ATTR_NAME_SIZEFMT, HTML40Namespace.ATTR_NAME_TIMEFMT};
+		attributeCollection.getDeclarations(attributes, Arrays.asList(names).iterator());
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedSSIEcho.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedSSIEcho.java
new file mode 100644
index 0000000..4738812
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedSSIEcho.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.util.Arrays;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+
+
+/**
+ * SSI:ECHO.
+ */
+final class HedSSIEcho extends HedSSIBase {
+
+	/**
+	 */
+	public HedSSIEcho(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.SSI_ECHO, collection);
+	}
+
+	/**
+	 * SSI:ECHO
+	 * (var CDATA #IMPLIED)
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		String[] names = {HTML40Namespace.ATTR_NAME_VAR};
+		attributeCollection.getDeclarations(attributes, Arrays.asList(names).iterator());
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedSSIExec.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedSSIExec.java
new file mode 100644
index 0000000..2824d57
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedSSIExec.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.util.Arrays;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+
+
+/**
+ * SSI:EXEC.
+ */
+final class HedSSIExec extends HedSSIBase {
+
+	/**
+	 */
+	public HedSSIExec(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.SSI_EXEC, collection);
+	}
+
+	/**
+	 * SSI:EXEC
+	 * (cgi %URI; #IMPLIED)
+	 * (cmd CDATA #IMPLIED)
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		String[] names = {HTML40Namespace.ATTR_NAME_CGI, HTML40Namespace.ATTR_NAME_CMD};
+		attributeCollection.getDeclarations(attributes, Arrays.asList(names).iterator());
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedSSIFlastmod.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedSSIFlastmod.java
new file mode 100644
index 0000000..50ebdf9
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedSSIFlastmod.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.util.Arrays;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+
+
+/**
+ * SSI:FLASTMOD.
+ */
+final class HedSSIFlastmod extends HedSSIBase {
+
+	/**
+	 */
+	public HedSSIFlastmod(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.SSI_FLASTMOD, collection);
+	}
+
+	/**
+	 * SSI:FLASTMOD
+	 * (file %URI; #IMPLIED)
+	 * (virtual %URI #IMPLIED)
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		String[] names = {HTML40Namespace.ATTR_NAME_FILE, HTML40Namespace.ATTR_NAME_VIRTUAL};
+		attributeCollection.getDeclarations(attributes, Arrays.asList(names).iterator());
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedSSIFsize.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedSSIFsize.java
new file mode 100644
index 0000000..f2bdbf0
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedSSIFsize.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.util.Arrays;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+
+
+/**
+ * SSI:FSIZE.
+ */
+final class HedSSIFsize extends HedSSIBase {
+
+	/**
+	 */
+	public HedSSIFsize(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.SSI_FSIZE, collection);
+	}
+
+	/**
+	 * SSI:FSIZE
+	 * (file %URI; #IMPLIED)
+	 * (virtual %URI #IMPLIED)
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		String[] names = {HTML40Namespace.ATTR_NAME_FILE, HTML40Namespace.ATTR_NAME_VIRTUAL};
+		attributeCollection.getDeclarations(attributes, Arrays.asList(names).iterator());
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedSSIInclude.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedSSIInclude.java
new file mode 100644
index 0000000..63224d8
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedSSIInclude.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.util.Arrays;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+
+
+/**
+ * SSI:INCLUDE.
+ */
+final class HedSSIInclude extends HedSSIBase {
+
+	/**
+	 */
+	public HedSSIInclude(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.SSI_INCLUDE, collection);
+	}
+
+	/**
+	 * SSI:INCLUDE
+	 * (file %URI; #IMPLIED)
+	 * (virtual %URI #IMPLIED)
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		String[] names = {HTML40Namespace.ATTR_NAME_FILE, HTML40Namespace.ATTR_NAME_VIRTUAL};
+		attributeCollection.getDeclarations(attributes, Arrays.asList(names).iterator());
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedSSIPrintenv.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedSSIPrintenv.java
new file mode 100644
index 0000000..bc10b56
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedSSIPrintenv.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+
+/**
+ * SSI:PRINTENV.
+ */
+final class HedSSIPrintenv extends HedSSIBase {
+
+	/**
+	 */
+	public HedSSIPrintenv(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.SSI_PRINTENV, collection);
+	}
+
+	/**
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+	}
+
+	/**
+	 * SSI:PRINTENV has no attributes.  So, this method should
+	 * always return <code>null</code>.
+	 * Note: Since somebody doesn't expect null is returned, return the empty attribute
+	 * like a custom tag which doesn't have attributes
+	 */
+	public CMNamedNodeMap getAttributes() {
+		return super.getAttributes();
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedSSISet.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedSSISet.java
new file mode 100644
index 0000000..182b85c
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedSSISet.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.util.Arrays;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+
+
+/**
+ * SSI:SET.
+ */
+final class HedSSISet extends HedSSIBase {
+
+	/**
+	 */
+	public HedSSISet(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.SSI_SET, collection);
+	}
+
+	/**
+	 * SSI:SET
+	 * (var CDATA #IMPLIED)
+	 * (value CDATA #IMPLIED)
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		String[] names = {HTML40Namespace.ATTR_NAME_VAR, HTML40Namespace.ATTR_NAME_VALUE};
+		attributeCollection.getDeclarations(attributes, Arrays.asList(names).iterator());
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedSTYLE.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedSTYLE.java
new file mode 100644
index 0000000..da0c3ed
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedSTYLE.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMContent;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+
+/**
+ * STYLE.
+ */
+final class HedSTYLE extends HTMLElemDeclImpl {
+
+	/**
+	 */
+	public HedSTYLE(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.STYLE, collection);
+		typeDefinitionName = ComplexTypeDefinitionFactory.CTYPE_CDATA;
+		layoutType = LAYOUT_HIDDEN;
+	}
+
+	/**
+	 * STYLE
+	*/
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+		
+		//different sets of attributes for html 4 & 5
+		attributeCollection.createAttributeDeclarations(HTML40Namespace.ElementName.STYLE, attributes);
+	
+		
+	}
+
+	/**
+	 * Content.<br>
+	 * <code>STYLE</code> is CDATA content type.  So, it always returns <code>null</code>.
+	 * @return org.eclipse.wst.xml.core.internal.contentmodel.CMContent
+	 */
+	public CMContent getContent() {
+		return null;
+	}
+
+	/**
+	 * CDATA content.<br>
+	 * @return int
+	 */
+	public int getContentType() {
+		return CMElementDeclaration.CDATA;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedSUMMARY.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedSUMMARY.java
new file mode 100644
index 0000000..c2b3e82
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedSUMMARY.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML50Namespace;
+
+public class HedSUMMARY extends HedInlineContainer {
+
+	public HedSUMMARY(ElementCollection collection) {
+		super(HTML50Namespace.ElementName.SUMMARY, collection);
+	}
+
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedSVG.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedSVG.java
new file mode 100644
index 0000000..0515172
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedSVG.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.util.Arrays;
+import java.util.Iterator;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML50Namespace;
+
+
+/**
+ * SVG.
+ */
+final class HedSVG extends HTMLElemDeclImpl {
+
+	private static String[] terminators = {HTML50Namespace.ElementName.SVG};
+
+	/**
+	 */
+	public HedSVG(ElementCollection collection) {
+		super(HTML50Namespace.ElementName.SVG, collection);
+		layoutType = LAYOUT_OBJECT;
+	}
+
+	/**
+	 * Create all attribute declarations.
+	 * SVG namespace
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		attributeCollection.getAttrs(attributes);
+	}
+
+	/**
+	 * SVG has terminators.
+	 * @return java.util.Iterator
+	 */
+	protected Iterator getTerminators() {
+		return Arrays.asList(terminators).iterator();
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedScripts.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedScripts.java
new file mode 100644
index 0000000..76bf70e
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedScripts.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+
+/**
+ * SUB and SUP.
+ */
+final class HedScripts extends HedInlineContainer {
+
+	/**
+	 */
+	public HedScripts(String elementName, ElementCollection collection) {
+		super(elementName, collection);
+		correctionType = CORRECT_EMPTY;
+	}
+
+	/**
+	 * %attrs;
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+	}
+
+	/**
+	 */
+	public CMNamedNodeMap getProhibitedAncestors() {
+		if (prohibitedAncestors != null)
+			return prohibitedAncestors;
+
+		String[] names = {HTML40Namespace.ElementName.PRE};
+		prohibitedAncestors = elementCollection.getDeclarations(names);
+
+		return prohibitedAncestors;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedSectioning.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedSectioning.java
new file mode 100644
index 0000000..07a7209
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedSectioning.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+public class HedSectioning extends HedFlowContainer {
+	public HedSectioning(String elementName, ElementCollection collection) {
+		super(elementName, collection);
+		layoutType = LAYOUT_BLOCK;
+		correctionType = CORRECT_EMPTY;
+	}
+
+	/**
+	 * Article.
+	 * %attrs;
+	 * Global attributes
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedTABLE.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedTABLE.java
new file mode 100644
index 0000000..426cd78
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedTABLE.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+
+/**
+ * TABLE.
+ */
+final class HedTABLE extends HTMLElemDeclImpl {
+
+	/**
+	 */
+	public HedTABLE(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.TABLE, collection);
+		typeDefinitionName = ComplexTypeDefinitionFactory.CTYPE_TABLE;
+		layoutType = LAYOUT_BLOCK;
+		indentChild = true;
+	}
+
+	/**
+	 * TABLE.
+	 * %attrs;
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+		
+		//different sets of attributes for html 4 & 5
+		attributeCollection.createAttributeDeclarations(HTML40Namespace.ElementName.TABLE, attributes);
+		
+	}
+
+	/**
+	 */
+	public CMNamedNodeMap getProhibitedAncestors() {
+		if (prohibitedAncestors != null)
+			return prohibitedAncestors;
+
+		String[] names = {HTML40Namespace.ElementName.DIR, HTML40Namespace.ElementName.MENU};
+		prohibitedAncestors = elementCollection.getDeclarations(names);
+
+		return prohibitedAncestors;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedTEXTAREA.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedTEXTAREA.java
new file mode 100644
index 0000000..1b5ba41
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedTEXTAREA.java
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+
+/**
+ * TEXTAREA.
+ */
+final class HedTEXTAREA extends HedPcdata {
+
+	/**
+	 * TEXTAREA should keep spaces in its source.
+	 */
+	public HedTEXTAREA(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.TEXTAREA, collection);
+		layoutType = LAYOUT_OBJECT;
+
+		keepSpaces = true;
+	}
+
+	/**
+	 * TEXTAREA.
+	 * %attrs;
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+		//different sets of attributes for html 4 & 5
+		attributeCollection.createAttributeDeclarations(HTML40Namespace.ElementName.TEXTAREA, attributes);
+	
+		}
+
+	/**
+	 */
+	public CMNamedNodeMap getProhibitedAncestors() {
+		if (prohibitedAncestors != null)
+			return prohibitedAncestors;
+
+		String[] names = {HTML40Namespace.ElementName.BUTTON};
+		prohibitedAncestors = elementCollection.getDeclarations(names);
+
+		return prohibitedAncestors;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedTIME.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedTIME.java
new file mode 100644
index 0000000..ec8191c
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedTIME.java
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+import java.util.Arrays;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.html.core.internal.provisional.HTML50Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMContent;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+public class HedTIME extends HedInlineContainer {
+
+	public HedTIME(ElementCollection collection) {
+		super(HTML50Namespace.ElementName.TIME, collection);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.html.core.internal.contentmodel.HTMLElemDeclImpl#createAttributeDeclarations()
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+		attributeCollection.getAttrs(attributes);
+
+		String[] names = { HTML40Namespace.ATTR_NAME_DATETIME, HTML50Namespace.ATTR_NAME_PUBDATE };
+		attributeCollection.getDeclarations(attributes, Arrays.asList(names).iterator());
+
+	}
+
+	public CMContent getExclusion() {
+		if (exclusion != null)
+			return exclusion; // already created.
+		if (elementCollection == null)
+			return null;
+
+		exclusion = new CMGroupImpl(CMGroup.CHOICE, 1, 1);
+		CMNode time = elementCollection.getNamedItem(HTML50Namespace.ElementName.TIME);
+		if (time != null)
+			exclusion.appendChild(time);
+
+		return exclusion;
+	}
+
+	public CMNamedNodeMap getProhibitedAncestors() {
+		if (prohibitedAncestors != null)
+			return prohibitedAncestors;
+
+		String[] names = {HTML50Namespace.ElementName.TIME};
+		prohibitedAncestors = elementCollection.getDeclarations(names);
+		return prohibitedAncestors;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedTITLE.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedTITLE.java
new file mode 100644
index 0000000..6919004
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedTITLE.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.util.Arrays;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMContent;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+
+/**
+ * TITLE.
+ */
+final class HedTITLE extends HedPcdata {
+
+	/**
+	 */
+	public HedTITLE(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.TITLE, collection);
+		layoutType = LAYOUT_HIDDEN;
+	}
+
+	/**
+	 * TITLE.
+	 * %i18n;
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %i18n;
+		attributeCollection.getI18n(attributes);
+	}
+
+	/**
+	 * Exclusion.
+	 * <code>TITLE</code> has the exclusion.
+	 * It is <code>%head.misc;</code>.
+	 * %head.misc; is <code>SCRIPT|STYLE|META|LINK|OBJECT</code>.
+	 */
+	public CMContent getExclusion() {
+		if (exclusion != null)
+			return exclusion; // already created.
+		if (elementCollection == null)
+			return null;
+
+		// (SCRIPT|STYLE|META|LINK|OBJECT)
+		exclusion = new CMGroupImpl(CMGroup.CHOICE, 1, 1);
+
+		String[] names = {HTML40Namespace.ElementName.SCRIPT, HTML40Namespace.ElementName.STYLE, HTML40Namespace.ElementName.META, HTML40Namespace.ElementName.LINK, HTML40Namespace.ElementName.OBJECT};
+		elementCollection.getDeclarations(exclusion, Arrays.asList(names).iterator());
+		return exclusion;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedTR.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedTR.java
new file mode 100644
index 0000000..d68a54a
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedTR.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.util.Arrays;
+import java.util.Iterator;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+
+
+/**
+ * TR.
+ */
+final class HedTR extends HTMLElemDeclImpl {
+
+	private static String[] terminators = {HTML40Namespace.ElementName.TR};
+
+	/**
+	 */
+	public HedTR(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.TR, collection);
+		typeDefinitionName = ComplexTypeDefinitionFactory.CTYPE_TCELL_CONTAINER;
+		layoutType = LAYOUT_BLOCK;
+		omitType = OMIT_END;
+		indentChild = true;
+	}
+
+	/**
+	 * %attrs;
+	 * %cellhalign;
+	 * %cellvalign;
+	 * (bgcolor %Color; #IMPLIED)
+	 * (background %URI; #IMPLIED)
+	 * (bordercolor %Color #IMPLIED) ... D205514
+	 * (height %Length #IMPLIED) bug2246
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+		// %cellhalign;
+		attributeCollection.getCellhalign(attributes);
+		// %cellvalign;
+		attributeCollection.getCellvalign(attributes);
+
+		String[] names = {HTML40Namespace.ATTR_NAME_BGCOLOR, HTML40Namespace.ATTR_NAME_BACKGROUND, HTML40Namespace.ATTR_NAME_BORDERCOLOR, HTML40Namespace.ATTR_NAME_HEIGHT // D205514
+		};
+		attributeCollection.getDeclarations(attributes, Arrays.asList(names).iterator());
+	}
+
+	/**
+	 * TR has terminators.
+	 * @return java.util.Iterator
+	 */
+	protected Iterator getTerminators() {
+		return Arrays.asList(terminators).iterator();
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedTableBody.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedTableBody.java
new file mode 100644
index 0000000..f66eeef
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedTableBody.java
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.util.Arrays;
+import java.util.Iterator;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+
+
+/**
+ * THEAD/TFOOT/TBODY
+ */
+final class HedTableBody extends HTMLElemDeclImpl {
+
+	private static String[] terminators = {HTML40Namespace.ElementName.CAPTION, HTML40Namespace.ElementName.COL, HTML40Namespace.ElementName.COLGROUP, HTML40Namespace.ElementName.THEAD, HTML40Namespace.ElementName.TBODY, HTML40Namespace.ElementName.TFOOT};
+
+	/**
+	 */
+	public HedTableBody(String elementName, ElementCollection collection) {
+		super(elementName, collection);
+		typeDefinitionName = ComplexTypeDefinitionFactory.CTYPE_TR_CONTAINER;
+		correctionType = CORRECT_EMPTY;
+		layoutType = LAYOUT_BLOCK;
+		if (elementName == HTML40Namespace.ElementName.TBODY) {
+			omitType = OMIT_BOTH;
+		}
+		else {
+			omitType = OMIT_END;
+		}
+		indentChild = true;
+	}
+
+	/**
+	 * TBODY/TFOOT/THEAD
+	 * %attrs;
+	 * %cellhalign;
+	 * %cellvalign;
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+		// %cellhalign;
+		attributeCollection.getCellhalign(attributes);
+		// %cellvalign;
+		attributeCollection.getCellvalign(attributes);
+	}
+
+	/**
+	 * THEAD, TFOOT and TBODY have terminators.
+	 * @return java.util.Iterator
+	 */
+	protected Iterator getTerminators() {
+		return Arrays.asList(terminators).iterator();
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedTableCell.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedTableCell.java
new file mode 100644
index 0000000..14fcb49
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedTableCell.java
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.util.Arrays;
+import java.util.Iterator;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+
+
+/**
+ * (TH | TD).
+ */
+final class HedTableCell extends HedFlowContainer {
+
+	private static String[] terminators = {HTML40Namespace.ElementName.TR, HTML40Namespace.ElementName.TH, HTML40Namespace.ElementName.TD};
+
+	/**
+	 */
+	public HedTableCell(String elementName, ElementCollection collection) {
+		super(elementName, collection);
+		layoutType = LAYOUT_BLOCK;
+		omitType = OMIT_END;
+	}
+
+	/**
+	 * %attrs;
+	 * (abbr %Text; #IMPLIED)
+	 * (axis CDATA #IMPLIED)
+	 * (headers IDREFS #IMPLIED)
+	 * (scope %Scope; #IMPLIED)
+	 * (rowspan NUMBER 1)
+	 * (colspan NUMBER 1)
+	 * %cellhalign;
+	 * %cellvalign;
+	 * (nowrap (nowrap) #IMPLIED)
+	 * (bgcolor %Color; #IMPLIED)
+	 * (width %Length; #IMPLIED)
+	 * (height %Length; #IMPLIED)
+	 * (background %URI; #IMPLIED)
+	 * (bordercolor %Color #IMPLIED) ... D205514
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+		// %cellhalign;
+		attributeCollection.getCellhalign(attributes);
+		// %cellvalign;
+		attributeCollection.getCellvalign(attributes);
+
+		String[] names = {HTML40Namespace.ATTR_NAME_ABBR, HTML40Namespace.ATTR_NAME_AXIS, HTML40Namespace.ATTR_NAME_HEADERS, HTML40Namespace.ATTR_NAME_SCOPE, HTML40Namespace.ATTR_NAME_ROWSPAN, HTML40Namespace.ATTR_NAME_COLSPAN, HTML40Namespace.ATTR_NAME_NOWRAP, HTML40Namespace.ATTR_NAME_BGCOLOR, HTML40Namespace.ATTR_NAME_WIDTH, HTML40Namespace.ATTR_NAME_HEIGHT, HTML40Namespace.ATTR_NAME_BACKGROUND, HTML40Namespace.ATTR_NAME_BORDERCOLOR // D205514
+		};
+		attributeCollection.getDeclarations(attributes, Arrays.asList(names).iterator());
+	}
+
+	/**
+	 * TH and TD have terminators.
+	 * @return java.util.Iterator
+	 */
+	protected Iterator getTerminators() {
+		return Arrays.asList(terminators).iterator();
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedUL.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedUL.java
new file mode 100644
index 0000000..041c5a5
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedUL.java
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.util.Arrays;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+
+/**
+ * UL.
+ */
+final class HedUL extends HedListItemContainer {
+
+	/**
+	 */
+	public HedUL(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.UL, collection);
+	}
+
+	/**
+	 * UL.
+	 * (type %ULStyle; #IMPLIED) ... should be defined locally.
+	 * (compact (compact) #IMPLIED)
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+
+		// (type %ULStyle; #IMPLIED) ... should be defined locally.
+		// %ULStyle; is (disc|square|circle).
+		HTMLCMDataTypeImpl atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+		String[] values = {HTML40Namespace.ATTR_VALUE_DISC, HTML40Namespace.ATTR_VALUE_SQUARE, HTML40Namespace.ATTR_VALUE_CIRCLE};
+		atype.setEnumValues(values);
+		HTMLAttrDeclImpl attr = new HTMLAttrDeclImpl(HTML40Namespace.ATTR_NAME_TYPE, atype, CMAttributeDeclaration.OPTIONAL);
+		attributes.putNamedItem(HTML40Namespace.ATTR_NAME_TYPE, attr);
+
+		// the rest.
+		String[] names = {HTML40Namespace.ATTR_NAME_COMPACT};
+		attributeCollection.getDeclarations(attributes, Arrays.asList(names).iterator());
+	}
+
+	/**
+	 */
+	public CMNamedNodeMap getProhibitedAncestors() {
+		if (prohibitedAncestors != null)
+			return prohibitedAncestors;
+
+		String[] names = {HTML40Namespace.ElementName.DIR, HTML40Namespace.ElementName.MENU};
+		prohibitedAncestors = elementCollection.getDeclarations(names);
+
+		return prohibitedAncestors;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedVIDEO.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedVIDEO.java
new file mode 100644
index 0000000..98eb444
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedVIDEO.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+import java.util.Arrays;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.html.core.internal.provisional.HTML50Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+
+
+
+
+/**
+ * VIDEO.
+ */
+final class HedVIDEO extends HedMediaElement {
+
+	
+	public HedVIDEO(ElementCollection collection) {
+		super(HTML50Namespace.ElementName.VIDEO, collection);
+	}
+
+	/**
+	 * MediaElement
+	 * %attrs;
+	 * (src %URI; #REQUIRED): should be defined locally.
+	 * (preload %CDATA; #IMPLIED) 
+	 * (autoplay %ENUM; #IMPLIED) 
+	 * (loop %ENUM; #IMPLIED)
+	 * (controls %MediaType; #IMPLIED)
+	 * (poster %URI; OPTIONAL)
+	 * (height %Length; #IMPLIED)
+	 * (width %Length; #IMPLIED)
+	 * Global attributes
+	 */
+	protected void createAttributeDeclarations() {
+		super.createAttributeDeclarations();
+		
+		// (poster %URI; #optional): should be defined locally.
+		
+		HTMLCMDataTypeImpl atype = null;
+		HTMLAttrDeclImpl attr = null;
+		atype = new HTMLCMDataTypeImpl(CMDataType.URI);
+		attr = new HTMLAttrDeclImpl(HTML50Namespace.ATTR_NAME_POSTER, atype, CMAttributeDeclaration.OPTIONAL);
+		attributes.putNamedItem(HTML50Namespace.ATTR_NAME_POSTER, attr);
+		
+		// height , width
+		String[] names = {HTML40Namespace.ATTR_NAME_HEIGHT, HTML40Namespace.ATTR_NAME_WIDTH};
+		attributeCollection.getDeclarations(attributes, Arrays.asList(names).iterator());
+
+
+		
+	}
+}
+
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedWBR.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedWBR.java
new file mode 100644
index 0000000..f958fe7
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/HedWBR.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+
+
+
+final class HedWBR extends HedEmpty {
+
+	public HedWBR(ElementCollection collection) {
+		super(HTML40Namespace.ElementName.WBR, collection);
+		// LAYOUT_BREAK.
+		// same as BR.
+		layoutType = LAYOUT_BREAK;
+	}
+
+	protected void createAttributeDeclarations() {
+		// No attributes is defined.
+		if (attributes != null)
+			return;
+		attributes = new CMNamedNodeMapImpl();
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/JCM20DocImpl.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/JCM20DocImpl.java
new file mode 100644
index 0000000..767b594
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/JCM20DocImpl.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+
+/**
+ * Implementation of CMDocument for JSP 2.0.
+ */
+class JCM20DocImpl extends JCMDocImpl {
+	/**
+	 * JCM20DocImpl constructor comment.
+	 */
+	public JCM20DocImpl(String docTypeName, CMNamespaceImpl targetNamespace) {
+		super(docTypeName, targetNamespace, new JSP20ElementCollection());
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/JCM21DocImpl.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/JCM21DocImpl.java
new file mode 100644
index 0000000..ba9e0cd
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/JCM21DocImpl.java
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+class JCM21DocImpl extends JCMDocImpl {
+	/**
+	 * JCM21DocImpl constructor comment.
+	 */
+	public JCM21DocImpl(String docTypeName, CMNamespaceImpl targetNamespace) {
+		super(docTypeName, targetNamespace, new JSP21ElementCollection());
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/JCMDocImpl.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/JCMDocImpl.java
new file mode 100644
index 0000000..b5fe4da
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/JCMDocImpl.java
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ * Implementation of CMDocument for JSP 1.1 and JSP 1.2.
+ */
+class JCMDocImpl extends CMNodeImpl implements JSPCMDocument {
+
+	/** Namespace for all names of elements, entities and attributes. */
+	private CMNamespaceImpl namespace = null;
+	private JSPElementCollection elements = null;
+
+	/**
+	 * HCMDocImpl constructor comment.
+	 */
+	public JCMDocImpl(String docTypeName, CMNamespaceImpl targetNamespace) {
+		this(docTypeName, targetNamespace, new JSPElementCollection());
+	}
+
+	JCMDocImpl(String docTypeName, CMNamespaceImpl targetNamespace, JSPElementCollection collection) {
+		super(docTypeName);
+		namespace = targetNamespace;
+		elements = collection;
+	}
+
+	public HTMLElementDeclaration getElementDeclaration(String elementName) {
+		if (elements == null)
+			return null;
+		return (HTMLElementDeclaration) elements.getNamedItem(elementName);
+	}
+
+	/**
+	 * @see org.eclipse.wst.xml.core.internal.contentmodel.CMDocument
+	 */
+	public CMNamedNodeMap getElements() {
+		return elements;
+	}
+
+	/**
+	 * @see org.eclipse.wst.xml.core.internal.contentmodel.CMDocument
+	 */
+	public CMNamedNodeMap getEntities() {
+		return null;
+	}
+
+	public HTMLEntityDeclaration getEntityDeclaration(String entityName) {
+		return null;
+	}
+
+	/**
+	 * @see org.eclipse.wst.xml.core.internal.contentmodel.CMDocument
+	 */
+	public org.eclipse.wst.xml.core.internal.contentmodel.CMNamespace getNamespace() {
+		return namespace;
+	}
+
+	/**
+	 * @see org.eclipse.wst.xml.core.internal.contentmodel.CMNode
+	 */
+	public int getNodeType() {
+		return CMNode.DOCUMENT;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/JSP11Namespace.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/JSP11Namespace.java
new file mode 100644
index 0000000..4d1a9b8
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/JSP11Namespace.java
@@ -0,0 +1,112 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+/**
+ * JSP 1.1 Namespace. Note, this interface was 
+ * copied form JSP core packages. One implication 
+ * is that extra care is needed in using '==' instead 
+ * of '.equals'.
+ */
+public interface JSP11Namespace {
+
+	public static interface ElementName {
+		// Element names
+		public static final String SCRIPTLET = "jsp:scriptlet"; //$NON-NLS-1$
+		public static final String EXPRESSION = "jsp:expression"; //$NON-NLS-1$
+		public static final String DECLARATION = "jsp:declaration"; //$NON-NLS-1$
+		public static final String DIRECTIVE_PAGE = "jsp:directive.page"; //$NON-NLS-1$
+		public static final String DIRECTIVE_INCLUDE = "jsp:directive.include"; //$NON-NLS-1$
+		public static final String DIRECTIVE_TAGLIB = "jsp:directive.taglib"; //$NON-NLS-1$
+		public static final String USEBEAN = "jsp:useBean"; //$NON-NLS-1$
+		public static final String SETPROPERTY = "jsp:setProperty"; //$NON-NLS-1$
+		public static final String GETPROPERTY = "jsp:getProperty"; //$NON-NLS-1$
+		public static final String INCLUDE = "jsp:include"; //$NON-NLS-1$
+		public static final String FORWARD = "jsp:forward"; //$NON-NLS-1$
+		public static final String PLUGIN = "jsp:plugin"; //$NON-NLS-1$
+		public static final String PARAMS = "jsp:params"; //$NON-NLS-1$
+		public static final String FALLBACK = "jsp:fallback"; //$NON-NLS-1$
+		public static final String PARAM = "jsp:param"; //$NON-NLS-1$
+		public static final String ROOT = "jsp:root"; //$NON-NLS-1$
+		public static final String TEXT = "jsp:text"; //$NON-NLS-1$
+	}
+
+	public static final String JSP11_URI = ""; //$NON-NLS-1$
+	public static final String JSP_TAG_PREFIX = "jsp"; //$NON-NLS-1$
+	// attribute names
+	//   directive.page
+	public static final String ATTR_NAME_LANGUAGE = "language"; //$NON-NLS-1$
+	public static final String ATTR_NAME_EXTENDS = "extends"; //$NON-NLS-1$
+	public static final String ATTR_NAME_CONTENT_TYPE = "contentType"; //$NON-NLS-1$
+	public static final String ATTR_NAME_IMPORT = "import"; //$NON-NLS-1$
+	public static final String ATTR_NAME_SESSION = "session"; //$NON-NLS-1$
+	public static final String ATTR_NAME_BUFFER = "buffer"; //$NON-NLS-1$
+	public static final String ATTR_NAME_AUTOFLUSH = "autoFlush"; //$NON-NLS-1$
+	public static final String ATTR_NAME_IS_THREAD_SAFE = "isThreadSafe"; //$NON-NLS-1$
+	public static final String ATTR_NAME_INFO = "info"; //$NON-NLS-1$
+	public static final String ATTR_NAME_ERROR_PAGE = "errorPage"; //$NON-NLS-1$
+	public static final String ATTR_NAME_IS_ERROR_PAGE = "isErrorPage"; //$NON-NLS-1$
+	public static final String ATTR_NAME_PAGE_ENCODING = "pageEncoding"; //$NON-NLS-1$
+	//   directive.include
+	public static final String ATTR_NAME_FILE = "file"; //$NON-NLS-1$
+	//   directive.taglib
+	public static final String ATTR_NAME_URI = "uri"; //$NON-NLS-1$
+	public static final String ATTR_NAME_PREFIX = "prefix"; //$NON-NLS-1$
+	//   useBean
+	public static final String ATTR_NAME_ID = "id"; //$NON-NLS-1$
+	public static final String ATTR_NAME_SCOPE = "scope"; //$NON-NLS-1$
+	public static final String ATTR_NAME_CLASS = "class"; //$NON-NLS-1$
+	public static final String ATTR_NAME_BEAN_NAME = "beanName"; //$NON-NLS-1$
+	public static final String ATTR_NAME_TYPE = "type"; //$NON-NLS-1$
+	//   setProperty
+	public static final String ATTR_NAME_NAME = "name"; //$NON-NLS-1$
+	public static final String ATTR_NAME_PROPERTY = "property"; //$NON-NLS-1$
+	public static final String ATTR_NAME_VALUE = "value"; //$NON-NLS-1$
+	public static final String ATTR_NAME_PARAM = "param"; //$NON-NLS-1$
+	//   include
+	public static final String ATTR_NAME_PAGE = "page"; //$NON-NLS-1$
+	public static final String ATTR_NAME_FLUSH = "flush"; //$NON-NLS-1$
+	//   plugin
+	public static final String ATTR_NAME_CODE = "code"; //$NON-NLS-1$
+	public static final String ATTR_NAME_CODEBASE = "codebase"; //$NON-NLS-1$
+	public static final String ATTR_NAME_ALIGN = "align"; //$NON-NLS-1$
+	public static final String ATTR_NAME_ARCHIVE = "archive"; //$NON-NLS-1$
+	public static final String ATTR_NAME_HEIGHT = "height"; //$NON-NLS-1$
+	public static final String ATTR_NAME_HSPACE = "hspace"; //$NON-NLS-1$
+	public static final String ATTR_NAME_JREVERSION = "jreversion"; //$NON-NLS-1$
+	public static final String ATTR_NAME_VSPACE = "vspace"; //$NON-NLS-1$
+	public static final String ATTR_NAME_WIDTH = "width"; //$NON-NLS-1$
+	public static final String ATTR_NAME_NSPLUGINURL = "nspluginurl"; //$NON-NLS-1$
+	public static final String ATTR_NAME_IEPLUGINURL = "iepluginurl"; //$NON-NLS-1$
+	//   root
+	public static final String ATTR_NAME_XMLNS_JSP = "xmlns:jsp"; //$NON-NLS-1$
+	public static final String ATTR_NAME_VERSION = "version"; //$NON-NLS-1$
+	// attribute values
+	public static final String ATTR_VALUE_TRUE = "true"; //$NON-NLS-1$
+	public static final String ATTR_VALUE_FALSE = "false"; //$NON-NLS-1$
+	public static final String ATTR_VALUE_JAVA = "java"; //$NON-NLS-1$
+	public static final String ATTR_VALUE_CT_DEFAULT = "text/html; charset=ISO-8859-1";//D195366 //$NON-NLS-1$
+	public static final String ATTR_VALUE_BUFSIZ_DEFAULT = "8kb"; //$NON-NLS-1$
+	public static final String ATTR_VALUE_PAGE = "page"; //$NON-NLS-1$
+	public static final String ATTR_VALUE_SESSION = "session"; //$NON-NLS-1$
+	public static final String ATTR_VALUE_REQUEST = "request"; //$NON-NLS-1$
+	public static final String ATTR_VALUE_APPLICATION = "application"; //$NON-NLS-1$
+	public static final String ATTR_VALUE_BEAN = "bean"; //$NON-NLS-1$
+	public static final String ATTR_VALUE_APPLET = "applet"; //$NON-NLS-1$
+	public static final String ATTR_VALUE_TOP = "top"; //$NON-NLS-1$
+	public static final String ATTR_VALUE_MIDDLE = "middle"; //$NON-NLS-1$
+	public static final String ATTR_VALUE_BOTTOM = "bottom"; //$NON-NLS-1$
+	public static final String ATTR_VALUE_LEFT = "left"; //$NON-NLS-1$
+	public static final String ATTR_VALUE_RIGHT = "right"; //$NON-NLS-1$
+	public static final String ATTR_VALUE_JVER11 = "1.1"; //$NON-NLS-1$
+	public static final String ATTR_VALUE_XMLNS_JSP = "http://java.sun.com/JSP/Page"; //$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/JSP20ElementCollection.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/JSP20ElementCollection.java
new file mode 100644
index 0000000..fd404c5
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/JSP20ElementCollection.java
@@ -0,0 +1,495 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.lang.reflect.Field;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ * Factory for element declarations of JSP 1.1 and JSP 1.2.
+ */
+class JSP20ElementCollection extends JSPElementCollection implements JSP20Namespace.ElementName {
+
+	// element IDs
+	private static class Ids20 extends Ids {
+		public static final int ID_BODY = 17;
+		public static final int ID_ATTRIBUTE = 18;
+		public static final int ID_ELEMENT = 19;
+		public static final int ID_OUTPUT = 20;
+
+		public static int getNumOfIds() {
+			if (numofids != -1)
+				return numofids;
+
+			// NOTE: If the reflection is too slow, this method should
+			// just return the literal value, like 105.
+			// -- 5/25/2001
+			Class clazz = Ids20.class;
+			Field[] fields = clazz.getFields();
+			numofids = 0;
+			for (int i = 0; i < fields.length; i++) {
+				String name = fields[i].getName();
+				if (name.startsWith("ID_"))//$NON-NLS-1$
+					numofids++;
+			}
+			return numofids;
+		}
+
+		// chache the result of the reflection.
+		private static int numofids = -1;
+	}
+
+	// attribute creater
+	class JACreater20 extends JACreater {
+		public JACreater20() {
+			super();
+		}
+
+		public CMNamedNodeMapImpl getDeclarations(int eid) {
+			switch (eid) {
+				case Ids20.ID_ATTRIBUTE :
+					createForAttribute();
+					break;
+				case Ids20.ID_ELEMENT :
+					createForElement();
+					break;
+				case Ids20.ID_BODY :
+					createForBody();
+					break;
+				case Ids20.ID_OUTPUT :
+					createForOutput();
+					break;
+				case Ids.ID_DIRECTIVE_TAGLIB :
+					createForDirTaglib();
+					break;
+				case Ids.ID_DIRECTIVE_PAGE :
+					createForDirPage();
+					break;
+				case Ids.ID_ROOT :
+					createForRoot();
+					break;
+				case Ids.ID_PLUGIN :
+					createForPlugin();
+					break;
+				default :
+					super.getDeclarations(eid);
+			}
+			return declarations;
+		}
+
+		private void createForBody() {
+		}
+
+		private void createForOutput() {
+			AttrDecl adec = new AttrDecl(JSP20Namespace.ATTR_NAME_OMIT_XML_DECL);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_VALUE_TRUE, ATTR_VALUE_FALSE, JSP20Namespace.ATTR_VALUE_YES, JSP20Namespace.ATTR_VALUE_NO};
+			adec.type.setEnumValues(values);
+			adec.type.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, JSP20Namespace.ATTR_VALUE_NO);
+			adec.usage = CMAttributeDeclaration.OPTIONAL;
+			declarations.putNamedItem(JSP20Namespace.ATTR_NAME_OMIT_XML_DECL, adec);
+
+			adec = new AttrDecl(JSP20Namespace.ATTR_NAME_DOCTYPE_ROOT_ELEMENT);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			adec.usage = CMAttributeDeclaration.OPTIONAL;
+			declarations.putNamedItem(JSP20Namespace.ATTR_NAME_DOCTYPE_ROOT_ELEMENT, adec);
+
+			adec = new AttrDecl(JSP20Namespace.ATTR_NAME_DOCTYPE_SYSTEM);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			adec.usage = CMAttributeDeclaration.OPTIONAL;
+			declarations.putNamedItem(JSP20Namespace.ATTR_NAME_DOCTYPE_SYSTEM, adec);
+
+			adec = new AttrDecl(JSP20Namespace.ATTR_NAME_DOCTYPE_PUBLIC);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			adec.usage = CMAttributeDeclaration.OPTIONAL;
+			declarations.putNamedItem(JSP20Namespace.ATTR_NAME_DOCTYPE_PUBLIC, adec);
+		}
+
+		/**
+		 * Changed in 2.0
+		 */
+		void createForDirTaglib() {
+			// ("uri" URI OPTIONAL)
+			AttrDecl adec = new AttrDecl(ATTR_NAME_URI);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.URI);
+			adec.usage = CMAttributeDeclaration.OPTIONAL;
+			declarations.putNamedItem(ATTR_NAME_URI, adec);
+
+			// ("tagdir" URI OPTIONAL)
+			adec = new AttrDecl(JSP20Namespace.ATTR_NAME_TAGDIR);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.URI);
+			adec.usage = CMAttributeDeclaration.OPTIONAL;
+			declarations.putNamedItem(JSP20Namespace.ATTR_NAME_TAGDIR, adec);
+
+			// ("prefix" CDATA REQUIRED)
+			adec = new AttrDecl(ATTR_NAME_PREFIX);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			adec.usage = CMAttributeDeclaration.REQUIRED;
+			declarations.putNamedItem(ATTR_NAME_PREFIX, adec);
+		}
+		
+		void createForDirPage() {
+			AttrDecl adec = null;
+			// ("language" CDATA DECLARED "java")
+			adec = new AttrDecl(ATTR_NAME_LANGUAGE);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			adec.type.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, ATTR_VALUE_JAVA);
+			declarations.putNamedItem(ATTR_NAME_LANGUAGE, adec);
+
+			// ("extends" CDATA IMPLIED)
+			adec = new AttrDecl(ATTR_NAME_EXTENDS);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			declarations.putNamedItem(ATTR_NAME_EXTENDS, adec);
+
+			// ("import" CDATA IMPLIED)
+			adec = new AttrDecl(ATTR_NAME_IMPORT);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			declarations.putNamedItem(ATTR_NAME_IMPORT, adec);
+
+			// ("session" ENUM DECLARED (true|false) "true")
+			adec = createBoolType(ATTR_NAME_SESSION, ATTR_VALUE_TRUE);
+			if (adec != null)
+				declarations.putNamedItem(ATTR_NAME_SESSION, adec);
+
+			// ("buffer" CDATA DECLARED "8kb")
+			adec = new AttrDecl(ATTR_NAME_BUFFER);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			adec.type.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, ATTR_VALUE_BUFSIZ_DEFAULT);
+			declarations.putNamedItem(ATTR_NAME_BUFFER, adec);
+
+			// ("autoFlush" ENUM DECLARED (true|false) "true")
+			adec = createBoolType(ATTR_NAME_AUTOFLUSH, ATTR_VALUE_TRUE);
+			if (adec != null)
+				declarations.putNamedItem(ATTR_NAME_AUTOFLUSH, adec);
+
+			// ("isThreadSafe" ENUM DECLARED (true|false) "true")
+			adec = createBoolType(ATTR_NAME_IS_THREAD_SAFE, ATTR_VALUE_TRUE);
+			if (adec != null)
+				declarations.putNamedItem(ATTR_NAME_IS_THREAD_SAFE, adec);
+
+			// ("info" CDATA IMPLIED)
+			adec = new AttrDecl(ATTR_NAME_INFO);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			declarations.putNamedItem(ATTR_NAME_INFO, adec);
+
+			// ("errorPage" URI IMPLIED)
+			adec = new AttrDecl(ATTR_NAME_ERROR_PAGE);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.URI);
+			declarations.putNamedItem(ATTR_NAME_ERROR_PAGE, adec);
+
+			// ("isErrorPage" ENUM DECLARED (true|false) "false")
+			adec = createBoolType(ATTR_NAME_IS_ERROR_PAGE, ATTR_VALUE_FALSE);
+			if (adec != null)
+				declarations.putNamedItem(ATTR_NAME_IS_ERROR_PAGE, adec);
+
+			// ("contentType" CDATA DECLARED "text/html; ISO-8859-1")
+			adec = new AttrDecl(ATTR_NAME_CONTENT_TYPE);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			adec.type.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, ATTR_VALUE_CT_DEFAULT);
+			declarations.putNamedItem(ATTR_NAME_CONTENT_TYPE, adec);
+
+			// ("pageEncoding" CDATA IMPLIED)
+			adec = new AttrDecl(ATTR_NAME_PAGE_ENCODING);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			adec.type.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, JSP20Namespace.ATTR_VALUE_ENCODING_DEFAULT);
+			declarations.putNamedItem(ATTR_NAME_PAGE_ENCODING, adec);
+
+			// ("isELIgnored" ENUM DECLARED (true|false) "false")
+			adec = new AttrDecl(JSP20Namespace.ATTR_NAME_ISELIGNORED);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = new String[]{ATTR_VALUE_TRUE, ATTR_VALUE_FALSE};
+			adec.type.setEnumValues(values);
+			adec.type.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, ATTR_VALUE_FALSE);
+			adec.usage = CMAttributeDeclaration.OPTIONAL;
+			declarations.putNamedItem(JSP20Namespace.ATTR_NAME_ISELIGNORED, adec);
+		}
+		
+		private void createForElement() {
+			AttrDecl adec = new AttrDecl(ATTR_NAME_NAME);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			adec.usage = CMAttributeDeclaration.REQUIRED;
+			declarations.putNamedItem(ATTR_NAME_NAME, adec);
+		}
+
+		private void createForAttribute() {
+			AttrDecl adec = new AttrDecl(ATTR_NAME_NAME);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			adec.usage = CMAttributeDeclaration.REQUIRED;
+			declarations.putNamedItem(ATTR_NAME_NAME, adec);
+
+			adec = new AttrDecl(JSP20Namespace.ATTR_NAME_TRIM);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_VALUE_TRUE, ATTR_VALUE_FALSE};
+			adec.type.setEnumValues(values);
+			adec.type.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, ATTR_VALUE_TRUE);
+			adec.usage = CMAttributeDeclaration.OPTIONAL;
+			declarations.putNamedItem(JSP20Namespace.ATTR_NAME_TRIM, adec);
+		}
+		
+		private void createForRoot() {
+			// ("xmlns:jsp" CDATA "http://java.sun.com/JSP/Page")
+			AttrDecl adec = new AttrDecl(ATTR_NAME_XMLNS_JSP);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			adec.type.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, ATTR_VALUE_XMLNS_JSP);
+			declarations.putNamedItem(ATTR_NAME_XMLNS_JSP, adec);
+			// ("version" CDATA REQUIRED)
+			adec = new AttrDecl(ATTR_NAME_VERSION);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			adec.type.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, JSP20Namespace.ATTR_VALUE_JSP_VER_20);
+			adec.usage = CMAttributeDeclaration.REQUIRED;
+			declarations.putNamedItem(ATTR_NAME_VERSION, adec);
+		}
+		
+		private void createForPlugin() {
+			// ("type" ENUM REQUIRED (bean|applet))
+			AttrDecl adec = new AttrDecl(ATTR_NAME_TYPE);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			adec.usage = CMAttributeDeclaration.REQUIRED;
+			String[] values = {ATTR_VALUE_BEAN, ATTR_VALUE_APPLET};
+			adec.type.setEnumValues(values);
+			declarations.putNamedItem(ATTR_NAME_TYPE, adec);
+
+			// ("code" CDATA REQUIRED)
+			adec = new AttrDecl(ATTR_NAME_CODE);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.URI);
+			adec.usage = CMAttributeDeclaration.REQUIRED;
+			declarations.putNamedItem(ATTR_NAME_CODE, adec);
+
+			// ("codebase" URI REQUIRED)
+			adec = new AttrDecl(ATTR_NAME_CODEBASE);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.URI);
+			adec.usage = CMAttributeDeclaration.REQUIRED;
+			declarations.putNamedItem(ATTR_NAME_CODEBASE, adec);
+
+			// ("align" ENUM IMPLIED (top|middle|bottom|left|right))
+			adec = new AttrDecl(ATTR_NAME_ALIGN);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] aligns = {ATTR_VALUE_TOP, ATTR_VALUE_MIDDLE, ATTR_VALUE_BOTTOM, ATTR_VALUE_LEFT, ATTR_VALUE_RIGHT};
+			adec.type.setEnumValues(aligns);
+			adec.type.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, ATTR_VALUE_BOTTOM);
+			declarations.putNamedItem(ATTR_NAME_ALIGN, adec);
+
+			// ("archive" CDATA IMPLIED)
+			adec = new AttrDecl(ATTR_NAME_ARCHIVE);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			declarations.putNamedItem(ATTR_NAME_ARCHIVE, adec);
+
+			// ("height" CDATA IMPLIED)
+			adec = new AttrDecl(ATTR_NAME_HEIGHT);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			declarations.putNamedItem(ATTR_NAME_HEIGHT, adec);
+
+			// ("hspace" CDATA IMPLIED)
+			adec = new AttrDecl(ATTR_NAME_HSPACE);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			declarations.putNamedItem(ATTR_NAME_HSPACE, adec);
+
+			// ("jreversion" CDATA DECLARED "1.1")
+			adec = new AttrDecl(ATTR_NAME_JREVERSION);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			adec.type.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, JSP20Namespace.ATTR_VALUE_JVER12);
+			declarations.putNamedItem(ATTR_NAME_JREVERSION, adec);
+
+			// ("name" CDATA IMPLIED)
+			adec = new AttrDecl(ATTR_NAME_NAME);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			declarations.putNamedItem(ATTR_NAME_NAME, adec);
+
+			// ("vspace" CDATA IMPLIED)
+			adec = new AttrDecl(ATTR_NAME_VSPACE);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			declarations.putNamedItem(ATTR_NAME_VSPACE, adec);
+
+			// ("width" CDATA IMPLIED)
+			adec = new AttrDecl(ATTR_NAME_WIDTH);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			declarations.putNamedItem(ATTR_NAME_WIDTH, adec);
+
+			// ("nspluginurl" URI IMPLIED)
+			adec = new AttrDecl(ATTR_NAME_NSPLUGINURL);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.URI);
+			declarations.putNamedItem(ATTR_NAME_NSPLUGINURL, adec);
+
+			// ("iepluginurl" URI IMPLIED)
+			adec = new AttrDecl(ATTR_NAME_IEPLUGINURL);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.URI);
+			declarations.putNamedItem(ATTR_NAME_IEPLUGINURL, adec);
+			
+			// ("mayscript" ENUM IMPLIED (true | false)
+			adec = new AttrDecl(JSP20Namespace.ATTR_NAME_MAYSCRIPT);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			adec.type.setEnumValues(new String[] {ATTR_VALUE_TRUE, ATTR_VALUE_FALSE});
+			declarations.putNamedItem(JSP20Namespace.ATTR_NAME_MAYSCRIPT, adec);
+		}
+	}
+
+	private static String[] names = null;
+
+	static {
+		names = new String[Ids20.getNumOfIds()];
+		names[Ids.ID_SCRIPTLET] = SCRIPTLET;
+		names[Ids.ID_EXPRESSION] = EXPRESSION;
+		names[Ids.ID_DECLARATION] = DECLARATION;
+		names[Ids.ID_DIRECTIVE_PAGE] = DIRECTIVE_PAGE;
+		names[Ids.ID_DIRECTIVE_INCLUDE] = DIRECTIVE_INCLUDE;
+		names[Ids.ID_DIRECTIVE_TAGLIB] = DIRECTIVE_TAGLIB;
+		names[Ids.ID_USEBEAN] = USEBEAN;
+		names[Ids.ID_SETPROPERTY] = SETPROPERTY;
+		names[Ids.ID_GETPROPERTY] = GETPROPERTY;
+		names[Ids.ID_INCLUDE] = INCLUDE;
+		names[Ids.ID_FORWARD] = FORWARD;
+		names[Ids.ID_PLUGIN] = PLUGIN;
+		names[Ids.ID_PARAMS] = PARAMS;
+		names[Ids.ID_FALLBACK] = FALLBACK;
+		names[Ids.ID_PARAM] = PARAM;
+		names[Ids.ID_ROOT] = ROOT;
+		names[Ids.ID_TEXT] = TEXT;
+		names[Ids20.ID_BODY] = JSP20Namespace.ElementName.BODY;
+		names[Ids20.ID_ATTRIBUTE] = JSP20Namespace.ElementName.ATTRIBUTE;
+		names[Ids20.ID_ELEMENT] = JSP20Namespace.ElementName.ELEMENT;
+		names[Ids20.ID_OUTPUT] = JSP20Namespace.ElementName.OUTPUT;
+	}
+
+	/**
+	 */
+	public JSP20ElementCollection() {
+		super(JSP20ElementCollection.names, TOLERANT_CASE);
+	}
+
+	/**
+	 * @param eid
+	 *            int
+	 */
+	CMGroupImpl createContent(int eid) {
+		if (eid == ID_UNKNOWN)
+			return null;
+
+		CMGroupImpl content = null;
+		CMNode child = null;
+
+		switch (eid) {
+			case Ids.ID_ROOT :
+				content = new CMGroupImpl(CMGroup.CHOICE, 0, CMContentImpl.UNBOUNDED);
+				int validChildren[] = {
+				// %Directives;
+							Ids.ID_TEXT, Ids.ID_DIRECTIVE_PAGE, Ids.ID_DIRECTIVE_INCLUDE, Ids20.ID_BODY, Ids20.ID_ATTRIBUTE,
+							// %Scripts;
+							Ids.ID_SCRIPTLET, Ids.ID_DECLARATION, Ids.ID_EXPRESSION,
+							// %Actions;
+							Ids.ID_USEBEAN, Ids.ID_SETPROPERTY, Ids.ID_GETPROPERTY, Ids.ID_INCLUDE, Ids.ID_FORWARD, Ids.ID_PLUGIN};
+				for (int i = 0; i < validChildren.length; i++) {
+					child = item(validChildren[i]);
+					if (child != null)
+						content.appendChild(child);
+				}
+				break;
+			default :
+				content = super.createContent(eid);
+				break;
+		}
+
+		return content;
+	}
+
+	/**
+	 * @param eid
+	 *            int
+	 */
+	HTMLElementDeclaration createElemDecl(int eid) {
+		if (eid == ID_UNKNOWN)
+			return null;
+
+		TypePacket packet = new TypePacket();
+		switch (eid) {
+			case Ids20.ID_BODY :
+				// declaration
+				packet.name = JSP20Namespace.ElementName.BODY;
+				packet.content = CMElementDeclaration.CDATA;
+				packet.layout = HTMLElementDeclaration.LAYOUT_OBJECT;
+				packet.indentChild = true;
+				packet.format = HTMLElementDeclaration.FORMAT_JSP_SCRIPT;
+				break;
+			case Ids20.ID_ELEMENT :
+				// declaration
+				packet.name = JSP20Namespace.ElementName.ELEMENT;
+				packet.content = CMElementDeclaration.CDATA;
+				packet.layout = HTMLElementDeclaration.LAYOUT_OBJECT;
+				packet.indentChild = true;
+				packet.format = HTMLElementDeclaration.FORMAT_JSP_SCRIPT;
+				break;
+			case Ids20.ID_ATTRIBUTE :
+				// declaration
+				packet.name = JSP20Namespace.ElementName.ATTRIBUTE;
+				packet.content = CMElementDeclaration.CDATA;
+				packet.layout = HTMLElementDeclaration.LAYOUT_OBJECT;
+				packet.indentChild = true;
+				packet.format = HTMLElementDeclaration.FORMAT_JSP_SCRIPT;
+				break;
+			case Ids20.ID_OUTPUT :
+				// declaration
+				packet.name = JSP20Namespace.ElementName.OUTPUT;
+				packet.content = CMElementDeclaration.CDATA;
+				packet.layout = HTMLElementDeclaration.LAYOUT_OBJECT;
+				packet.indentChild = true;
+				packet.format = HTMLElementDeclaration.FORMAT_JSP_SCRIPT;
+				break;
+			case Ids.ID_DIRECTIVE_TAGLIB :
+				// directive.taglib
+				packet.name = DIRECTIVE_TAGLIB;
+				packet.omit = HTMLElementDeclaration.OMIT_END;
+				packet.layout = HTMLElementDeclaration.LAYOUT_HIDDEN;
+				packet.format = HTMLElementDeclaration.FORMAT_JSP_DIRECTIVE;
+				break;
+			case Ids.ID_DIRECTIVE_PAGE :
+				// directive.page
+				packet.name = DIRECTIVE_PAGE;
+				packet.omit = HTMLElementDeclaration.OMIT_END;
+				packet.layout = HTMLElementDeclaration.LAYOUT_HIDDEN;
+				packet.format = HTMLElementDeclaration.FORMAT_JSP_DIRECTIVE;
+				break;
+			case Ids.ID_ROOT :
+				packet.name = ROOT;
+				packet.content = CMElementDeclaration.ELEMENT;
+				packet.layout = HTMLElementDeclaration.LAYOUT_HIDDEN; // same as HTML
+				break;
+			case Ids.ID_PLUGIN :
+				// plugin
+				packet.name = PLUGIN;
+				packet.content = CMElementDeclaration.ELEMENT;
+				packet.layout = HTMLElementDeclaration.LAYOUT_OBJECT;
+				packet.indentChild = true;
+				break;
+			default :
+				return super.createElemDecl(eid);
+		}
+		ElemDecl decl = new ElemDecl(packet);
+
+		CMGroupImpl content = createContent(eid);
+		if (content != null)
+			decl.setContent(content);
+
+		JACreater20 creater = getAttributeCreator();
+		decl.setAttributes(creater.getDeclarations(eid));
+
+		return decl;
+	}
+
+	protected JACreater20 getAttributeCreator() {
+		return new JACreater20();
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/JSP20Namespace.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/JSP20Namespace.java
new file mode 100644
index 0000000..ee138a2
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/JSP20Namespace.java
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+/**
+ * New names for JSP 2.0 spec.
+ * 
+ * @deprecated - use
+ *             org.eclipse.jst.jsp.core.internal.provisional.JSP20Namespace
+ */
+
+public interface JSP20Namespace extends JSP11Namespace {
+	public static String JSP20_URI = "";//$NON-NLS-1$
+
+	/**
+	 * New elements for JSP 2.0 spec.
+	 */
+	public static interface ElementName extends JSP11Namespace.ElementName {
+		String DIRECTIVE_TAG = "jsp:directive.tag"; //$NON-NLS-1$
+		String DIRECTIVE_ATTRIBUTE = "jsp:directive.attribute"; //$NON-NLS-1$
+		String DIRECTIVE_VARIABLE = "jsp:directive.variable"; //$NON-NLS-1$
+		String BODY = "jsp:body"; //$NON-NLS-1$
+		String ATTRIBUTE = "jsp:attribute"; //$NON-NLS-1$
+		String ELEMENT = "jsp:element"; //$NON-NLS-1$
+		String DOBODY = "jsp:doBody";
+		String INVOKE = "jsp:invoke";
+		String OUTPUT = "jsp:output";
+	}
+
+	String ATTR_NAME_TAGDIR = "tagdir"; //$NON-NLS-1$
+
+	String ATTR_NAME_DISPLAY_NAME = "display-name"; //$NON-NLS-1$
+	String ATTR_NAME_BODY_CONTENT = "body-content"; //$NON-NLS-1$
+	String ATTR_NAME_SMALL_ICON = "small-icon"; //$NON-NLS-1$
+	String ATTR_NAME_LARGE_ICON = "large-icon"; //$NON-NLS-1$
+	String ATTR_NAME_DESCRIPTION = "description"; //$NON-NLS-1$
+	String ATTR_NAME_EXAMPLE = "example"; //$NON-NLS-1$
+	String ATTR_NAME_LANGUAGE = "language"; //$NON-NLS-1$
+	String ATTR_NAME_ISELIGNORED = "isELIgnored"; //$NON-NLS-1$
+
+	String ATTR_NAME_REQUIRED = "required"; //$NON-NLS-1$
+	String ATTR_NAME_FRAGMENT = "fragment"; //$NON-NLS-1$
+	String ATTR_NAME_RTEXPRVALUE = "rtexprvalue"; //$NON-NLS-1$
+	String ATTR_NAME_TYPE = "type"; //$NON-NLS-1$
+
+	String ATTR_NAME_NAME_GIVEN = "name-given"; //$NON-NLS-1$
+	String ATTR_NAME_NAME_FROM_ATTRIBUTE = "name-from-attribute"; //$NON-NLS-1$
+	String ATTR_NAME_ALIAS = "alias"; //$NON-NLS-1$
+	String ATTR_NAME_VARIABLE_CLASS = "variable-class"; //$NON-NLS-1$
+	String ATTR_NAME_DECLARE = "declare"; //$NON-NLS-1$
+
+	String ATTR_VALUE_SCRIPTLESS = "scriptless"; //$NON-NLS-1$
+	String ATTR_VALUE_TAGDEPENDENT = "tagdependent"; //$NON-NLS-1$
+	String ATTR_VALUE_EMPTY = "empty"; //$NON-NLS-1$
+
+	String ATTR_NAME_TRIM = "trim"; //$NON-NLS-1$
+
+	String ATTR_NAME_VAR = "var"; //$NON-NLS-1$
+	String ATTR_NAME_VARREADER = "varReader"; //$NON-NLS-1$
+
+	String ATTR_NAME_OMIT_XML_DECL = "omit-xml-declaration"; //$NON-NLS-1$
+	String ATTR_NAME_DOCTYPE_ROOT_ELEMENT = "doctype-root-element"; //$NON-NLS-1$
+	String ATTR_NAME_DOCTYPE_SYSTEM = "doctype-system"; //$NON-NLS-1$
+	String ATTR_NAME_DOCTYPE_PUBLIC = "doctype-public"; //$NON-NLS-1$
+
+	String ATTR_VALUE_NO = "no"; //$NON-NLS-1$
+	String ATTR_VALUE_YES = "yes"; //$NON-NLS-1$
+
+	String ATTR_VALUE_SCOPE_AT_END = "AT_END"; //$NON-NLS-1$
+	String ATTR_VALUE_SCOPE_AT_BEGIN = "AT_BEGIN"; //$NON-NLS-1$
+	String ATTR_VALUE_SCOPE_NESTED = "NESTED"; //$NON-NLS-1$
+
+	String ATTR_NAME_DYNAMIC_ATTRIBUTES = "dynamic-attributes"; //$NON-NLS-1$
+	
+	String ATTR_VALUE_ENCODING_DEFAULT = "ISO-8859-1"; //$NON-NLS-1$
+	
+	String ATTR_VALUE_VARIABLE_CLASS_DEFAULT = "java.lang.String"; //$NON-NLS-1$
+	
+	String ATTR_NAME_MAYSCRIPT = "mayscript"; //$NON-NLS-1$
+	
+	String ATTR_VALUE_JVER12 = "1.2"; //$NON-NLS-1$
+	
+	String ATTR_VALUE_JSP_VER_20 = "2.0"; //$NON-NLS-1$
+	
+	// JSP 2.1 attributes
+//	String ATTR_NAME_DEFERRED_SYNTAX_ALLOWED_AS_LITERAL = "deferredSyntaxAllowedAsLiteral"; //$NON-NLS-1$
+//	String ATTR_NAME_TRIM_DIRECTIVE_WHITESPACES = "trimDirectiveWhitespaces"; //$NON-NLS-1$
+	
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/JSP21ElementCollection.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/JSP21ElementCollection.java
new file mode 100644
index 0000000..4b7a1ba
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/JSP21ElementCollection.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+
+class JSP21ElementCollection extends JSP20ElementCollection {
+
+	class JACreator21 extends JACreater20 {
+		void createForDirPage() {
+			super.createForDirPage();
+			AttrDecl adec;
+			// ("trimDirectiveWhitespaces" ENUM DECLARED (true|false) "false")
+			adec = createBoolType(JSP21Namespace.ATTR_NAME_TRIM_DIRECTIVE_WHITESPACES, ATTR_VALUE_FALSE);
+			if (adec != null) {
+				adec.usage = CMAttributeDeclaration.OPTIONAL;
+				declarations.putNamedItem(JSP21Namespace.ATTR_NAME_TRIM_DIRECTIVE_WHITESPACES, adec);
+			}
+			// ("deferredSyntaxAllowedAsLiteral" ENUM DECLARED (true|false) "false")
+			adec = createBoolType(JSP21Namespace.ATTR_NAME_DEFERRED_SYNTAX_ALLOWED_AS_LITERAL, ATTR_VALUE_FALSE);
+			if (adec != null) {
+				adec.usage = CMAttributeDeclaration.OPTIONAL;
+				declarations.putNamedItem(JSP21Namespace.ATTR_NAME_DEFERRED_SYNTAX_ALLOWED_AS_LITERAL, adec);
+			}
+		}
+	}
+
+	protected JACreater20 getAttributeCreator() {
+		return new JACreator21();
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/JSP21Namespace.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/JSP21Namespace.java
new file mode 100644
index 0000000..dde35b7
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/JSP21Namespace.java
@@ -0,0 +1,17 @@
+/*******************************************************************************
+ * Copyright (c) 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+public interface JSP21Namespace extends JSP20Namespace {
+	String JSP21_URI = "";//$NON-NLS-1$
+	String ATTR_NAME_TRIM_DIRECTIVE_WHITESPACES = "trimDirectiveWhitespaces"; //$NON-NLS-1$
+	String ATTR_NAME_DEFERRED_SYNTAX_ALLOWED_AS_LITERAL = "deferredSyntaxAllowedAsLiteral"; //$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/JSPCMDocument.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/JSPCMDocument.java
new file mode 100644
index 0000000..802bfb2
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/JSPCMDocument.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+/**
+ * JSP extension for CMDocument.
+ * This interface provides some short hand methods to get declarations
+ * by a name.
+ */
+public interface JSPCMDocument extends org.eclipse.wst.xml.core.internal.contentmodel.CMDocument {
+
+	/**
+	 * A short hand method to get a element declaration for a JSP element.
+	 * JSP declaration class implements HTMLElementDeclaration interface.
+	 * @param elementName java.lang.String
+	 */
+	HTMLElementDeclaration getElementDeclaration(String elementName);
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/JSPElementCollection.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/JSPElementCollection.java
new file mode 100644
index 0000000..c517f99
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/JSPElementCollection.java
@@ -0,0 +1,900 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.lang.reflect.Field;
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.Vector;
+
+import org.eclipse.wst.html.core.internal.provisional.HTMLCMProperties;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMContent;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ * Factory for element declarations of the JSP 1.1 and 1.2.
+ */
+class JSPElementCollection extends DeclCollection implements JSP11Namespace.ElementName {
+
+
+	class TypePacket {
+		public String name = null;
+		public int content = CMElementDeclaration.EMPTY;
+		public int omit = HTMLElementDeclaration.OMIT_NONE;
+		public int lineBreak = HTMLElementDeclaration.BREAK_NONE;
+		public int layout = HTMLElementDeclaration.LAYOUT_NONE;
+		public int correct = HTMLElementDeclaration.CORRECT_NONE;
+		public int format = HTMLElementDeclaration.FORMAT_XML;
+		public boolean indentChild = false;
+
+		public TypePacket() {
+		}
+	}
+
+	/** JSP element declaration. */
+	class ElemDecl extends CMContentImpl implements HTMLElementDeclaration, HTMLPropertyDeclaration {
+		private TypePacket type = null;
+		private CMGroupImpl content = null;
+		private CMNamedNodeMapImpl attributes = null;
+
+		public ElemDecl(TypePacket t) {
+			super(t.name, 1, 1);
+			type = t;
+		}
+
+		public void setContent(CMGroupImpl group) {
+			content = group;
+		}
+
+		public void setAttributes(CMNamedNodeMapImpl attrs) {
+			attributes = attrs;
+		}
+
+		// implements CMNode
+		public int getNodeType() {
+			return CMNode.ELEMENT_DECLARATION;
+		}
+
+		public boolean supports(String propertyName) {
+			if (propertyName.equals(HTMLCMProperties.SHOULD_IGNORE_CASE)) {
+				return true;
+			}
+			else if (propertyName.equals(HTMLCMProperties.CONTENT_HINT)) {
+				return true;
+			}
+			else {
+				PropertyProvider pp = PropertyProviderFactory.getProvider(propertyName);
+				if (pp == null)
+					return false;
+				return pp.supports(this);
+			}
+		}
+
+		public Object getProperty(String propertyName) {
+			if (propertyName.equals(HTMLCMProperties.SHOULD_IGNORE_CASE)) {
+				return Boolean.FALSE; //D208839
+			}
+			else if (propertyName.equals(HTMLCMProperties.CONTENT_HINT)) {
+				String myName = getElementName();
+				if (myName == JSP11Namespace.ElementName.PLUGIN) {
+					return getNamedItem(JSP11Namespace.ElementName.PARAMS); // outer class method.
+				}
+				else if (myName == JSP11Namespace.ElementName.PARAMS) {
+					return getNamedItem(JSP11Namespace.ElementName.PARAM); // outer class method.
+				}
+				else {
+					return null;
+				}
+			}
+			else {
+				PropertyProvider pp = PropertyProviderFactory.getProvider(propertyName);
+				if (pp == null)
+					return null;
+				return pp.get(this);
+			}
+		}
+
+		// implementes CMElementDeclaration
+		public CMNamedNodeMap getAttributes() {
+			return attributes;
+		}
+
+		public CMContent getContent() {
+			return content;
+		}
+
+		public int getContentType() {
+			return type.content;
+		}
+
+		public CMDataType getDataType() {
+			return null;
+		}
+
+		public String getElementName() {
+			return getNodeName();
+		}
+
+		public CMNamedNodeMap getLocalElements() {
+			return null;
+		}
+
+		// implementes HTMLElementDeclaration
+		public HTMLAttributeDeclaration getAttributeDeclaration(String attrName) {
+			if (attributes == null)
+				return null;
+			return (HTMLAttributeDeclaration) attributes.getNamedItem(attrName);
+		}
+
+		public int getCorrectionType() {
+			return type.correct;
+		}
+
+		public CMContent getExclusion() {
+			return null;
+		}
+
+		public CMContent getInclusion() {
+			return null;
+		}
+
+		public CMNamedNodeMap getProhibitedAncestors() {
+			return EMPTY_MAP;
+		}
+
+		public int getFormatType() {
+			return type.format;
+		}
+
+		public int getLayoutType() {
+			return type.layout;
+		}
+
+		public int getLineBreakHint() {
+			return type.lineBreak;
+		}
+
+		public int getOmitType() {
+			return type.omit;
+		}
+
+		public boolean shouldTerminateAt(HTMLElementDeclaration dec) {
+			return false;
+		}
+
+		public boolean shouldKeepSpaces() {
+			return false;
+		}
+
+		public boolean shouldIndentChildSource() {
+			return type.indentChild;
+		}
+
+		public boolean isJSP() {
+			return true;
+		}
+	}
+
+	// element IDs
+	static class Ids {
+		public static final int ID_SCRIPTLET = 0;
+		public static final int ID_EXPRESSION = 1;
+		public static final int ID_DECLARATION = 2;
+		public static final int ID_DIRECTIVE_PAGE = 3;
+		public static final int ID_DIRECTIVE_INCLUDE = 4;
+		public static final int ID_DIRECTIVE_TAGLIB = 5;
+		public static final int ID_USEBEAN = 6;
+		public static final int ID_SETPROPERTY = 7;
+		public static final int ID_GETPROPERTY = 8;
+		public static final int ID_INCLUDE = 9;
+		public static final int ID_FORWARD = 10;
+		public static final int ID_PLUGIN = 11;
+		public static final int ID_PARAMS = 12;
+		public static final int ID_FALLBACK = 13;
+		public static final int ID_PARAM = 14;
+		public static final int ID_ROOT = 15;
+		public static final int ID_TEXT = 16;
+
+		public static int getNumOfIds() {
+			if (numofids != -1)
+				return numofids;
+
+			// NOTE: If the reflection is too slow, this method should
+			// just return the literal value, like 105.
+			// -- 5/25/2001
+			Class clazz = Ids.class;
+			Field[] fields = clazz.getFields();
+			numofids = 0;
+			for (int i = 0; i < fields.length; i++) {
+				String name = fields[i].getName();
+				if (name.startsWith("ID_"))//$NON-NLS-1$
+					numofids++;
+			}
+			return numofids;
+		}
+
+		// chache the result of the reflection.
+		private static int numofids = -1;
+	}
+
+	// attribute creater
+	class JACreater implements JSP11Namespace {
+		// attribute declaration
+		class AttrDecl extends CMNodeImpl implements HTMLAttributeDeclaration {
+			HTMLCMDataTypeImpl type = null;
+			int usage = CMAttributeDeclaration.OPTIONAL;
+
+			// methods
+			public AttrDecl(String attrName) {
+				super(attrName);
+			}
+
+			public String getAttrName() {
+				return getNodeName();
+			}
+
+			public CMDataType getAttrType() {
+				return type;
+			}
+
+			/** @deprecated by superclass */
+			public String getDefaultValue() {
+				if (type.getImpliedValueKind() != CMDataType.IMPLIED_VALUE_DEFAULT)
+					return null;
+				return type.getImpliedValue();
+			}
+
+			/** @deprecated  by superclass */
+			public Enumeration getEnumAttr() {
+				Vector v = new Vector(Arrays.asList(type.getEnumeratedValues()));
+				return v.elements();
+			}
+
+			public int getNodeType() {
+				return CMNode.ATTRIBUTE_DECLARATION;
+			}
+
+			public int getUsage() {
+				return usage;
+			}
+
+			public boolean shouldIgnoreCase() {
+				return false;
+			}
+		}
+
+		CMNamedNodeMapImpl declarations = null;
+
+		public JACreater() {
+			declarations = new CMNamedNodeMapImpl();
+		}
+
+		public CMNamedNodeMapImpl getDeclarations(int eid) {
+			switch (eid) {
+				case Ids.ID_DIRECTIVE_PAGE :
+					createForDirPage();
+					break;
+				case Ids.ID_DIRECTIVE_INCLUDE :
+					createForDirInclude();
+					break;
+				case Ids.ID_DIRECTIVE_TAGLIB :
+					createForDirTaglib();
+					break;
+				case Ids.ID_USEBEAN :
+					createForUseBean();
+					break;
+				case Ids.ID_SETPROPERTY :
+					createForSetProperty();
+					break;
+				case Ids.ID_GETPROPERTY :
+					createForGetProperty();
+					break;
+				case Ids.ID_INCLUDE :
+					createForInclude();
+					break;
+				case Ids.ID_FORWARD :
+					createForForward();
+					break;
+				case Ids.ID_PLUGIN :
+					createForPlugin();
+					break;
+				case Ids.ID_PARAM :
+					createForParam();
+					break;
+				case Ids.ID_ROOT :
+					createForRoot();
+					break;
+				default :
+					// should warn.
+					break;
+			}
+			return declarations;
+		}
+
+		AttrDecl createBoolType(String name, String defValue) {
+			AttrDecl adec = new AttrDecl(name);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_VALUE_TRUE, ATTR_VALUE_FALSE};
+			adec.type.setEnumValues(values);
+			adec.type.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, defValue);
+			return adec;
+		}
+
+		private void createForDirPage() {
+			AttrDecl adec = null;
+			// ("language" CDATA DECLARED "java")
+			adec = new AttrDecl(ATTR_NAME_LANGUAGE);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			adec.type.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, ATTR_VALUE_JAVA);
+			declarations.putNamedItem(ATTR_NAME_LANGUAGE, adec);
+
+			// ("extends" CDATA IMPLIED)
+			adec = new AttrDecl(ATTR_NAME_EXTENDS);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			declarations.putNamedItem(ATTR_NAME_EXTENDS, adec);
+
+			// ("contentType" CDATA DECLARED "text/html; ISO-8859-1")
+			adec = new AttrDecl(ATTR_NAME_CONTENT_TYPE);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			adec.type.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, ATTR_VALUE_CT_DEFAULT);
+			declarations.putNamedItem(ATTR_NAME_CONTENT_TYPE, adec);
+
+			// ("import" CDATA IMPLIED)
+			adec = new AttrDecl(ATTR_NAME_IMPORT);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			declarations.putNamedItem(ATTR_NAME_IMPORT, adec);
+
+			// ("session" ENUM DECLARED (true|false) "true")
+			adec = createBoolType(ATTR_NAME_SESSION, ATTR_VALUE_TRUE);
+			if (adec != null)
+				declarations.putNamedItem(ATTR_NAME_SESSION, adec);
+
+			// ("buffer" CDATA DECLARED "8kb")
+			adec = new AttrDecl(ATTR_NAME_BUFFER);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			adec.type.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, ATTR_VALUE_BUFSIZ_DEFAULT);
+			declarations.putNamedItem(ATTR_NAME_BUFFER, adec);
+
+			// ("autoFlush" ENUM DECLARED (true|false) "true")
+			adec = createBoolType(ATTR_NAME_AUTOFLUSH, ATTR_VALUE_TRUE);
+			if (adec != null)
+				declarations.putNamedItem(ATTR_NAME_AUTOFLUSH, adec);
+
+			// ("isThreadSafe" ENUM DECLARED (true|false) "true")
+			adec = createBoolType(ATTR_NAME_IS_THREAD_SAFE, ATTR_VALUE_TRUE);
+			if (adec != null)
+				declarations.putNamedItem(ATTR_NAME_IS_THREAD_SAFE, adec);
+
+			// ("info" CDATA IMPLIED)
+			adec = new AttrDecl(ATTR_NAME_INFO);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			declarations.putNamedItem(ATTR_NAME_INFO, adec);
+
+			// ("errorPage" URI IMPLIED)
+			adec = new AttrDecl(ATTR_NAME_ERROR_PAGE);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.URI);
+			declarations.putNamedItem(ATTR_NAME_ERROR_PAGE, adec);
+
+			// ("isErrorPage" ENUM DECLARED (true|false) "false")
+			adec = createBoolType(ATTR_NAME_IS_ERROR_PAGE, ATTR_VALUE_FALSE);
+			if (adec != null)
+				declarations.putNamedItem(ATTR_NAME_IS_ERROR_PAGE, adec);
+
+			// ("pageEncoding" CDATA IMPLIED)
+			adec = new AttrDecl(ATTR_NAME_PAGE_ENCODING);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			declarations.putNamedItem(ATTR_NAME_PAGE_ENCODING, adec);
+
+		}
+
+		private void createForDirInclude() {
+			// ("file" URI REQUIRED); Defect TORO:185241
+			AttrDecl adec = new AttrDecl(ATTR_NAME_FILE);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.URI);
+			adec.usage = CMAttributeDeclaration.REQUIRED;
+			declarations.putNamedItem(ATTR_NAME_FILE, adec);
+		}
+
+		private void createForDirTaglib() {
+			// ("uri" URI REQUIRED)
+			AttrDecl adec = new AttrDecl(ATTR_NAME_URI);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.URI);
+			adec.usage = CMAttributeDeclaration.REQUIRED;
+			declarations.putNamedItem(ATTR_NAME_URI, adec);
+
+			// ("prefix" CDATA REQUIRED)
+			adec = new AttrDecl(ATTR_NAME_PREFIX);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			adec.usage = CMAttributeDeclaration.REQUIRED;
+			declarations.putNamedItem(ATTR_NAME_PREFIX, adec);
+		}
+
+		private void createForUseBean() {
+			// ("id" ID REQUIRED)
+			AttrDecl adec = new AttrDecl(ATTR_NAME_ID);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.ID);
+			adec.usage = CMAttributeDeclaration.REQUIRED;
+			declarations.putNamedItem(ATTR_NAME_ID, adec);
+
+			// ("scope" ENUM DECLARED (page|session|request|application) "page")
+			adec = new AttrDecl(ATTR_NAME_SCOPE);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_VALUE_PAGE, ATTR_VALUE_SESSION, ATTR_VALUE_REQUEST, ATTR_VALUE_APPLICATION};
+			adec.type.setEnumValues(values);
+			adec.type.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, ATTR_VALUE_PAGE);
+			declarations.putNamedItem(ATTR_NAME_SCOPE, adec);
+
+			// ("class" CDATA IMPLIED)
+			adec = new AttrDecl(ATTR_NAME_CLASS);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			declarations.putNamedItem(ATTR_NAME_CLASS, adec);
+
+			// ("beanName" CDATA IMPLIED)
+			adec = new AttrDecl(ATTR_NAME_BEAN_NAME);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			declarations.putNamedItem(ATTR_NAME_BEAN_NAME, adec);
+
+			// ("type" CDATA IMPLIED)
+			adec = new AttrDecl(ATTR_NAME_TYPE);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			declarations.putNamedItem(ATTR_NAME_TYPE, adec);
+		}
+
+		private void createForSetProperty() {
+			// ("name" IDREF REQUIRED)
+			AttrDecl adec = new AttrDecl(ATTR_NAME_NAME);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.IDREF);
+			adec.usage = CMAttributeDeclaration.REQUIRED;
+			declarations.putNamedItem(ATTR_NAME_NAME, adec);
+
+			// ("property" CDATA REQUIRED)
+			adec = new AttrDecl(ATTR_NAME_PROPERTY);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			adec.usage = CMAttributeDeclaration.REQUIRED;
+			declarations.putNamedItem(ATTR_NAME_PROPERTY, adec);
+
+			// ("value" CDATA IMPLIED)
+			adec = new AttrDecl(ATTR_NAME_VALUE);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			declarations.putNamedItem(ATTR_NAME_VALUE, adec);
+
+			// ("param" CDATA IMPLIED)
+			adec = new AttrDecl(ATTR_NAME_PARAM);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			declarations.putNamedItem(ATTR_NAME_PARAM, adec);
+
+		}
+
+		private void createForGetProperty() {
+			// ("name" IDREF REQUIRED)
+			AttrDecl adec = new AttrDecl(ATTR_NAME_NAME);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.IDREF);
+			adec.usage = CMAttributeDeclaration.REQUIRED;
+			declarations.putNamedItem(ATTR_NAME_NAME, adec);
+
+			// ("property" CDATA REQUIRED)
+			adec = new AttrDecl(ATTR_NAME_PROPERTY);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			adec.usage = CMAttributeDeclaration.REQUIRED;
+			declarations.putNamedItem(ATTR_NAME_PROPERTY, adec);
+
+		}
+
+		private void createForInclude() {
+			AttrDecl adec = null;
+			// ("page" URI REQUIRED)
+			adec = new AttrDecl(ATTR_NAME_PAGE);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.URI);
+			adec.usage = CMAttributeDeclaration.REQUIRED;
+			declarations.putNamedItem(ATTR_NAME_PAGE, adec);
+
+			// ("flush" ENUM OPTIONAL (true|false)); Defect TORO:185241
+			adec = new AttrDecl(ATTR_NAME_FLUSH);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			adec.usage = CMAttributeDeclaration.OPTIONAL;
+			String[] values = {ATTR_VALUE_TRUE, ATTR_VALUE_FALSE};
+			adec.type.setEnumValues(values);
+			adec.type.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, ATTR_VALUE_FALSE);
+			declarations.putNamedItem(ATTR_NAME_FLUSH, adec);
+		}
+
+		private void createForForward() {
+			// ("page" URI REQUIRED)
+			AttrDecl adec = new AttrDecl(ATTR_NAME_PAGE);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.URI);
+			adec.usage = CMAttributeDeclaration.REQUIRED;
+			declarations.putNamedItem(ATTR_NAME_PAGE, adec);
+		}
+
+		private void createForPlugin() {
+			// ("type" ENUM REQUIRED (bean|applet))
+			AttrDecl adec = new AttrDecl(ATTR_NAME_TYPE);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			adec.usage = CMAttributeDeclaration.REQUIRED;
+			String[] values = {ATTR_VALUE_BEAN, ATTR_VALUE_APPLET};
+			adec.type.setEnumValues(values);
+			declarations.putNamedItem(ATTR_NAME_TYPE, adec);
+
+			// ("code" CDATA REQUIRED)
+			adec = new AttrDecl(ATTR_NAME_CODE);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.URI);
+			adec.usage = CMAttributeDeclaration.REQUIRED;
+			declarations.putNamedItem(ATTR_NAME_CODE, adec);
+
+			// ("codebase" URI REQUIRED)
+			adec = new AttrDecl(ATTR_NAME_CODEBASE);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.URI);
+			adec.usage = CMAttributeDeclaration.REQUIRED;
+			declarations.putNamedItem(ATTR_NAME_CODEBASE, adec);
+
+			// ("align" ENUM IMPLIED (top|middle|bottom|left|right))
+			adec = new AttrDecl(ATTR_NAME_ALIGN);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] aligns = {ATTR_VALUE_TOP, ATTR_VALUE_MIDDLE, ATTR_VALUE_BOTTOM, ATTR_VALUE_LEFT, ATTR_VALUE_RIGHT};
+			adec.type.setEnumValues(aligns);
+			declarations.putNamedItem(ATTR_NAME_ALIGN, adec);
+
+			// ("archive" CDATA IMPLIED)
+			adec = new AttrDecl(ATTR_NAME_ARCHIVE);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			declarations.putNamedItem(ATTR_NAME_ARCHIVE, adec);
+
+			// ("height" CDATA IMPLIED)
+			adec = new AttrDecl(ATTR_NAME_HEIGHT);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			declarations.putNamedItem(ATTR_NAME_HEIGHT, adec);
+
+			// ("hspace" CDATA IMPLIED)
+			adec = new AttrDecl(ATTR_NAME_HSPACE);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			declarations.putNamedItem(ATTR_NAME_HSPACE, adec);
+
+			// ("jreversion" CDATA DECLARED "1.1")
+			adec = new AttrDecl(ATTR_NAME_JREVERSION);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			adec.type.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, ATTR_VALUE_JVER11);
+			declarations.putNamedItem(ATTR_NAME_JREVERSION, adec);
+
+			// ("name" CDATA IMPLIED)
+			adec = new AttrDecl(ATTR_NAME_NAME);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			declarations.putNamedItem(ATTR_NAME_NAME, adec);
+
+			// ("vspace" CDATA IMPLIED)
+			adec = new AttrDecl(ATTR_NAME_VSPACE);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			declarations.putNamedItem(ATTR_NAME_VSPACE, adec);
+
+			// ("width" CDATA IMPLIED)
+			adec = new AttrDecl(ATTR_NAME_WIDTH);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			declarations.putNamedItem(ATTR_NAME_WIDTH, adec);
+
+			// ("nspluginurl" URI IMPLIED)
+			adec = new AttrDecl(ATTR_NAME_NSPLUGINURL);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.URI);
+			declarations.putNamedItem(ATTR_NAME_NSPLUGINURL, adec);
+
+			// ("iepluginurl" URI IMPLIED)
+			adec = new AttrDecl(ATTR_NAME_IEPLUGINURL);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.URI);
+			declarations.putNamedItem(ATTR_NAME_IEPLUGINURL, adec);
+		}
+
+		private void createForParam() {
+			// ("name" CDATA REQUIRED)
+			AttrDecl adec = new AttrDecl(ATTR_NAME_NAME);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			adec.usage = CMAttributeDeclaration.REQUIRED;
+			declarations.putNamedItem(ATTR_NAME_NAME, adec);
+
+			// ("value" CDATA REQUIRED); Defect TORO:185241
+			adec = new AttrDecl(ATTR_NAME_VALUE);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			adec.usage = CMAttributeDeclaration.REQUIRED;
+			declarations.putNamedItem(ATTR_NAME_VALUE, adec);
+
+		}
+
+		private void createForRoot() {
+			// ("xmlns:jsp" CDATA "http://java.sun.com/JSP/Page")
+			AttrDecl adec = new AttrDecl(ATTR_NAME_XMLNS_JSP);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			adec.type.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, ATTR_VALUE_XMLNS_JSP);
+			declarations.putNamedItem(ATTR_NAME_XMLNS_JSP, adec);
+			// ("version" CDATA REQUIRED)
+			adec = new AttrDecl(ATTR_NAME_VERSION);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			adec.usage = CMAttributeDeclaration.REQUIRED;
+			declarations.putNamedItem(ATTR_NAME_VERSION, adec);
+		}
+	}
+
+	private final static CMNamedNodeMap EMPTY_MAP = new CMNamedNodeMap() {
+		public int getLength() {
+			return 0;
+		}
+
+		public CMNode getNamedItem(String name) {
+			return null;
+		}
+
+		public CMNode item(int index) {
+			return null;
+		}
+
+		public Iterator iterator() {
+			return new Iterator() {
+				public boolean hasNext() {
+					return false;
+				}
+
+				public Object next() {
+					return null;
+				}
+
+				public void remove() {
+				}
+			};
+		}
+	};
+	private static String[] names = null;
+
+	static {
+		names = new String[Ids.getNumOfIds()];
+		names[Ids.ID_SCRIPTLET] = SCRIPTLET;
+		names[Ids.ID_EXPRESSION] = EXPRESSION;
+		names[Ids.ID_DECLARATION] = DECLARATION;
+		names[Ids.ID_DIRECTIVE_PAGE] = DIRECTIVE_PAGE;
+		names[Ids.ID_DIRECTIVE_INCLUDE] = DIRECTIVE_INCLUDE;
+		names[Ids.ID_DIRECTIVE_TAGLIB] = DIRECTIVE_TAGLIB;
+		names[Ids.ID_USEBEAN] = USEBEAN;
+		names[Ids.ID_SETPROPERTY] = SETPROPERTY;
+		names[Ids.ID_GETPROPERTY] = GETPROPERTY;
+		names[Ids.ID_INCLUDE] = INCLUDE;
+		names[Ids.ID_FORWARD] = FORWARD;
+		names[Ids.ID_PLUGIN] = PLUGIN;
+		names[Ids.ID_PARAMS] = PARAMS;
+		names[Ids.ID_FALLBACK] = FALLBACK;
+		names[Ids.ID_PARAM] = PARAM;
+		names[Ids.ID_ROOT] = ROOT;
+		names[Ids.ID_TEXT] = TEXT;
+	}
+
+	JSPElementCollection(String[] names, boolean tolerant) {
+		super(names, tolerant);
+	}
+
+	/**
+	 */
+	public JSPElementCollection() {
+		super(names, TOLERANT_CASE);
+	}
+
+	/**
+	 * @return org.eclipse.wst.xml.core.internal.contentmodel.CMNode
+	 * @param elementName java.lang.String
+	 */
+	protected CMNode create(String elementName) {
+		return createElemDecl(getID(elementName));
+	}
+
+	/**
+	 * @param eid int
+	 */
+	CMGroupImpl createContent(int eid) {
+		if (eid == ID_UNKNOWN)
+			return null;
+
+		CMGroupImpl content = null;
+		CMNode child = null;
+
+		switch (eid) {
+			case Ids.ID_INCLUDE :
+			case Ids.ID_FORWARD :
+				// (jsp:param)*
+				content = new CMGroupImpl(CMGroup.SEQUENCE, 0, CMContentImpl.UNBOUNDED);
+				child = item(Ids.ID_PARAM);
+				if (child != null)
+					content.appendChild(child);
+				break;
+			case Ids.ID_PLUGIN :
+				// (jsp:params | jsp:fallback)?
+				content = new CMGroupImpl(CMGroup.CHOICE, 0, 1);
+				// jsp:params
+				child = item(Ids.ID_PARAMS);
+				if (child != null)
+					content.appendChild(child);
+				// jsp:fallback
+				child = item(Ids.ID_FALLBACK);
+				if (child != null)
+					content.appendChild(child);
+				break;
+			case Ids.ID_PARAMS :
+				// (jsp:param)+
+				content = new CMGroupImpl(CMGroup.SEQUENCE, 1, CMContentImpl.UNBOUNDED);
+				child = item(Ids.ID_PARAM);
+				if (child != null)
+					content.appendChild(child);
+				break;
+			case Ids.ID_ROOT :
+				// %Body;
+				// --> (jsp:text|%Directives;|%Scripts;|%Actions;)*
+				//     %Directives --> jsp:directive.page|jsp:directive.include
+				//     %Scripts; --> jsp:scriptlet|jsp:declaration|jsp:expression
+				//     %Actions --> jsp:useBean|jsp.setProperty|jsp:getProperty
+				//                  |jsp:include|jsp:forward|jsp:plugin
+				content = new CMGroupImpl(CMGroup.CHOICE, 0, CMContentImpl.UNBOUNDED);
+				int validChildren[] = {Ids.ID_TEXT,
+				// %Directves;
+							Ids.ID_DIRECTIVE_PAGE, Ids.ID_DIRECTIVE_INCLUDE,
+							// %Scripts;
+							Ids.ID_SCRIPTLET, Ids.ID_DECLARATION, Ids.ID_EXPRESSION,
+							// %Actions;
+							Ids.ID_USEBEAN, Ids.ID_SETPROPERTY, Ids.ID_GETPROPERTY, Ids.ID_INCLUDE, Ids.ID_FORWARD, Ids.ID_PLUGIN};
+				for (int i = 0; i < validChildren.length; i++) {
+					child = item(validChildren[i]);
+					if (child != null)
+						content.appendChild(child);
+				}
+				break;
+		}
+
+		return content;
+	}
+
+	/**
+	 * @param eid int
+	 */
+	HTMLElementDeclaration createElemDecl(int eid) {
+		if (eid == ID_UNKNOWN)
+			return null;
+
+		TypePacket packet = new TypePacket();
+		switch (eid) {
+			case Ids.ID_SCRIPTLET :
+				// content, omit, lineBreak, layout, correct, format
+				// scriptlet
+				packet.name = SCRIPTLET;
+				packet.content = CMElementDeclaration.CDATA;
+				packet.layout = HTMLElementDeclaration.LAYOUT_OBJECT;
+				packet.format = HTMLElementDeclaration.FORMAT_JSP_SCRIPT;
+				break;
+			case Ids.ID_EXPRESSION :
+				// expression
+				packet.name = EXPRESSION;
+				packet.content = CMElementDeclaration.CDATA;
+				packet.layout = HTMLElementDeclaration.LAYOUT_OBJECT;
+				packet.format = HTMLElementDeclaration.FORMAT_JSP_SCRIPT;
+				break;
+			case Ids.ID_DECLARATION :
+				// declaration
+				packet.name = DECLARATION;
+				packet.content = CMElementDeclaration.CDATA;
+				packet.layout = HTMLElementDeclaration.LAYOUT_HIDDEN;
+				packet.format = HTMLElementDeclaration.FORMAT_JSP_SCRIPT;
+				break;
+			case Ids.ID_DIRECTIVE_PAGE :
+				// directive.page
+				packet.name = DIRECTIVE_PAGE;
+				packet.omit = HTMLElementDeclaration.OMIT_END;
+				packet.layout = HTMLElementDeclaration.LAYOUT_HIDDEN;
+				packet.format = HTMLElementDeclaration.FORMAT_JSP_DIRECTIVE;
+				break;
+			case Ids.ID_DIRECTIVE_INCLUDE :
+				// directive.inlcude
+				packet.name = DIRECTIVE_INCLUDE;
+				packet.omit = HTMLElementDeclaration.OMIT_END;
+				packet.layout = HTMLElementDeclaration.LAYOUT_HIDDEN;
+				packet.format = HTMLElementDeclaration.FORMAT_JSP_DIRECTIVE;
+				break;
+			case Ids.ID_DIRECTIVE_TAGLIB :
+				// directive.taglib
+				packet.name = DIRECTIVE_TAGLIB;
+				packet.omit = HTMLElementDeclaration.OMIT_END;
+				packet.layout = HTMLElementDeclaration.LAYOUT_HIDDEN;
+				packet.format = HTMLElementDeclaration.FORMAT_JSP_DIRECTIVE;
+				break;
+			case Ids.ID_USEBEAN :
+				// useBean
+				packet.name = USEBEAN;
+				packet.content = CMElementDeclaration.ANY;
+				packet.layout = HTMLElementDeclaration.LAYOUT_HIDDEN;
+				packet.indentChild = true;
+				break;
+			case Ids.ID_SETPROPERTY :
+				// setProperty
+				packet.name = SETPROPERTY;
+				packet.omit = HTMLElementDeclaration.OMIT_END;
+				packet.layout = HTMLElementDeclaration.LAYOUT_HIDDEN;
+				break;
+			case Ids.ID_GETPROPERTY :
+				// getProperty
+				packet.name = GETPROPERTY;
+				packet.omit = HTMLElementDeclaration.OMIT_END;
+				packet.layout = HTMLElementDeclaration.LAYOUT_OBJECT;
+				break;
+			case Ids.ID_INCLUDE :
+				// include
+				packet.name = INCLUDE;
+				packet.content = CMElementDeclaration.ELEMENT;
+				packet.omit = HTMLElementDeclaration.OMIT_END;
+				packet.layout = HTMLElementDeclaration.LAYOUT_OBJECT;
+				packet.indentChild = true;
+				break;
+			case Ids.ID_FORWARD :
+				// forward
+				packet.name = FORWARD;
+				packet.content = CMElementDeclaration.ELEMENT;
+				packet.omit = HTMLElementDeclaration.OMIT_END;
+				packet.layout = HTMLElementDeclaration.LAYOUT_OBJECT;
+				packet.indentChild = true;
+				break;
+			case Ids.ID_PLUGIN :
+				// plugin
+				packet.name = PLUGIN;
+				packet.content = CMElementDeclaration.ELEMENT;
+				packet.layout = HTMLElementDeclaration.LAYOUT_OBJECT;
+				packet.indentChild = true;
+				break;
+			case Ids.ID_PARAMS :
+				// params
+				packet.name = PARAMS;
+				packet.content = CMElementDeclaration.ELEMENT;
+				packet.layout = HTMLElementDeclaration.LAYOUT_HIDDEN;
+				packet.indentChild = true;
+				break;
+			case Ids.ID_FALLBACK :
+				// fallback
+				packet.name = FALLBACK;
+				packet.content = CMElementDeclaration.CDATA;
+				packet.layout = HTMLElementDeclaration.LAYOUT_HIDDEN;
+				break;
+			case Ids.ID_PARAM :
+				// param
+				packet.name = PARAM;
+				packet.omit = HTMLElementDeclaration.OMIT_END;
+				packet.layout = HTMLElementDeclaration.LAYOUT_HIDDEN;
+				break;
+			case Ids.ID_ROOT :
+				packet.name = ROOT;
+				packet.content = CMElementDeclaration.ELEMENT;
+				packet.layout = HTMLElementDeclaration.LAYOUT_HIDDEN; // same as HTML
+				break;
+			case Ids.ID_TEXT :
+				packet.name = TEXT;
+				packet.content = CMElementDeclaration.PCDATA;
+				break;
+			default :
+				// unknown ID
+				return null;
+		}
+
+		ElemDecl dec = new ElemDecl(packet);
+
+		CMGroupImpl content = createContent(eid);
+		if (content != null)
+			dec.setContent(content);
+
+		JACreater creater = new JACreater();
+		dec.setAttributes(creater.getDeclarations(eid));
+
+		return dec;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/PropertyProvider.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/PropertyProvider.java
new file mode 100644
index 0000000..f3972ec
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/PropertyProvider.java
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+/**
+ * PropertyProvider class.
+ * This class is intended to be used in HTMLElementDeclaration instances.
+ */
+interface PropertyProvider {
+
+	boolean supports(HTMLElementDeclaration edecl);
+
+	Object get(HTMLElementDeclaration edecl);
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/PropertyProviderFactory.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/PropertyProviderFactory.java
new file mode 100644
index 0000000..5eb1abe
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/PropertyProviderFactory.java
@@ -0,0 +1,360 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+import java.util.Hashtable;
+
+import org.eclipse.wst.html.core.internal.HTMLCorePlugin;
+import org.eclipse.wst.html.core.internal.provisional.HTMLCMProperties;
+import org.eclipse.wst.xml.core.internal.contentmodel.annotation.AnnotationMap;
+
+/**
+ * The factory object of PropertyProvider.
+ */
+final class PropertyProviderFactory {
+
+
+	/**
+	 * DefaultProvider is intended to be used for unknown properties.
+	 * It always returns null value for any properties.
+	 */
+	class DefaultProvider implements PropertyProvider {
+		public DefaultProvider() {
+			super();
+		}
+
+		public boolean supports(HTMLElementDeclaration edecl) {
+			return false;
+		}
+
+		public Object get(HTMLElementDeclaration edecl) {
+			return null;
+		}
+	}
+
+	abstract class AbstractElementPropertyProvider implements PropertyProvider {
+		protected AbstractElementPropertyProvider() {
+			super();
+		}
+
+		public boolean supports(HTMLElementDeclaration edecl) {
+			return (edecl != null);
+		}
+
+		public Object get(HTMLElementDeclaration edecl) {
+			if (!(edecl instanceof HTMLPropertyDeclaration))
+				return null;
+			return getElementProperty((HTMLPropertyDeclaration)edecl);
+		}
+
+		abstract protected Object getElementProperty(HTMLPropertyDeclaration decl);
+	}
+
+	/*
+	 * "tagInfo"
+	 * gets documentation for the element
+	 */
+	class PPTagInfo extends AbstractElementPropertyProvider {
+		private final static String htmlAnnotationLoc = "data/htmref.xml"; //$NON-NLS-1$
+		protected AnnotationMap fAnnotationMap = null;
+
+		public PPTagInfo() {
+			super();
+		}
+
+		/**
+		 * Gets the annotationMap.
+		 * @return Returns a AnnotationMap
+		 */
+		protected AnnotationMap getAnnotationMap() {
+			if (fAnnotationMap == null) {
+				fAnnotationMap = new AnnotationMap();
+				try {
+					fAnnotationMap.load(htmlAnnotationLoc, HTMLCorePlugin.getDefault().getBundle().getSymbolicName());
+				}
+				catch (Exception e) {
+					// no annotation available
+				}
+			}
+			return fAnnotationMap;
+		}
+
+		protected Object getElementProperty(HTMLPropertyDeclaration decl) {
+			if (decl instanceof HTMLElementDeclaration) {
+				return getAnnotationMap().getProperty(((HTMLElementDeclaration)decl).getElementName(), "tagInfo"); //$NON-NLS-1$
+			} else {
+				return null;
+			}
+		}
+	}
+
+	/*
+	 * "shouldKeepSpace"
+	 */
+	class PPShouldKeepSpace extends AbstractElementPropertyProvider {
+		public PPShouldKeepSpace() {
+			super();
+		}
+
+		protected Object getElementProperty(HTMLPropertyDeclaration decl) {
+			return new Boolean(decl.shouldKeepSpaces());
+		}
+	}
+
+	/*
+	 * "shouldIndentChildSource"
+	 */
+	class PPShouldIndentChildSource extends AbstractElementPropertyProvider {
+		public PPShouldIndentChildSource() {
+			super();
+		}
+
+		protected Object getElementProperty(HTMLPropertyDeclaration decl) {
+			return new Boolean(decl.shouldIndentChildSource());
+		}
+	}
+
+	/*
+	 * "terminators"
+	 */
+	class PPTerminators extends AbstractElementPropertyProvider {
+		public PPTerminators() {
+			super();
+		}
+
+		protected Object getElementProperty(HTMLPropertyDeclaration decl) {
+			if (! (decl instanceof HTMLElemDeclImpl)) return null;
+			return ((HTMLElemDeclImpl)decl).getTerminators();
+		}
+	}
+
+	/*
+	 * "prohibitedAncestors"
+	 */
+	class PPProhibitedAncestors extends AbstractElementPropertyProvider {
+		public PPProhibitedAncestors() {
+			super();
+		}
+
+		protected Object getElementProperty(HTMLPropertyDeclaration decl) {
+			return decl.getProhibitedAncestors();
+		}
+	}
+
+	/*
+	 * "isJSP"
+	 */
+	class PPIsJSP extends AbstractElementPropertyProvider {
+		public PPIsJSP() {
+			super();
+		}
+
+		protected Object getElementProperty(HTMLPropertyDeclaration decl) {
+			return new Boolean(decl.isJSP());
+		}
+	}
+
+	/*
+	 * "isXHTML"
+	 * HTMLElementDeclaration itself never represent any XHTML element declaration.
+	 * So, this property must be always false.
+	 */
+	class PPIsXHTML extends AbstractElementPropertyProvider {
+		public PPIsXHTML() {
+			super();
+		}
+
+		protected Object getElementProperty(HTMLPropertyDeclaration decl) {
+			return new Boolean(false);
+		}
+	}
+
+	/*
+	 * "isSSI"
+	 * Each declaration class for SSI elements must provide this property itself,
+	 * and then return true.  Other declaration must always return false.
+	 */
+	class PPIsSSI extends AbstractElementPropertyProvider {
+		public PPIsSSI() {
+			super();
+		}
+
+		protected Object getElementProperty(HTMLPropertyDeclaration decl) {
+			return new Boolean(false);
+		}
+	}
+
+	/*
+	 * "lineBreakHint"
+	 */
+	class PPLineBreakHint extends AbstractElementPropertyProvider {
+		public PPLineBreakHint() {
+			super();
+		}
+
+		protected Object getElementProperty(HTMLPropertyDeclaration decl) {
+			String hint = HTMLCMProperties.Values.BREAK_NONE;
+			switch (decl.getLineBreakHint()) {
+				case HTMLElementDeclaration.BREAK_AFTER_START :
+					hint = HTMLCMProperties.Values.BREAK_AFTER_START;
+					break;
+				case HTMLElementDeclaration.BREAK_BEFORE_START_AND_AFTER_END :
+					hint = HTMLCMProperties.Values.BREAK_BEFORE_START_AND_AFTER_END;
+					break;
+				case HTMLElementDeclaration.BREAK_NONE :
+				// nothing to do
+				default :
+					break;
+			}
+			return hint;
+		}
+	}
+
+	/*
+	 * "layoutType"
+	 */
+	class PPLayoutType extends AbstractElementPropertyProvider {
+		public PPLayoutType() {
+			super();
+		}
+
+		protected Object getElementProperty(HTMLPropertyDeclaration decl) {
+			String type = HTMLCMProperties.Values.LAYOUT_NONE;
+			switch (decl.getLayoutType()) {
+				case HTMLElementDeclaration.LAYOUT_BLOCK :
+					type = HTMLCMProperties.Values.LAYOUT_BLOCK;
+					break;
+				case HTMLElementDeclaration.LAYOUT_BREAK :
+					type = HTMLCMProperties.Values.LAYOUT_BREAK;
+					break;
+				case HTMLElementDeclaration.LAYOUT_HIDDEN :
+					type = HTMLCMProperties.Values.LAYOUT_HIDDEN;
+					break;
+				case HTMLElementDeclaration.LAYOUT_OBJECT :
+					type = HTMLCMProperties.Values.LAYOUT_OBJECT;
+					break;
+				case HTMLElementDeclaration.LAYOUT_WRAP :
+					type = HTMLCMProperties.Values.LAYOUT_WRAP;
+					break;
+				case HTMLElementDeclaration.LAYOUT_NONE :
+				// nothing to do.
+				default :
+					break;
+			}
+			return type;
+		}
+	}
+
+	/*
+	 * "omitType"
+	 */
+	class PPOmitType extends AbstractElementPropertyProvider {
+		public PPOmitType() {
+			super();
+		}
+
+		protected Object getElementProperty(HTMLPropertyDeclaration decl) {
+			String type = HTMLCMProperties.Values.OMIT_NONE;
+			switch (decl.getOmitType()) {
+				case HTMLElementDeclaration.OMIT_BOTH :
+					type = HTMLCMProperties.Values.OMIT_BOTH;
+					break;
+				case HTMLElementDeclaration.OMIT_END :
+					type = HTMLCMProperties.Values.OMIT_END;
+					break;
+				case HTMLElementDeclaration.OMIT_END_DEFAULT :
+					type = HTMLCMProperties.Values.OMIT_END_DEFAULT;
+					break;
+				case HTMLElementDeclaration.OMIT_END_MUST :
+					type = HTMLCMProperties.Values.OMIT_END_MUST;
+					break;
+				case HTMLElementDeclaration.OMIT_NONE :
+				// nothing to do.
+				default :
+					break;
+			}
+			return type;
+		}
+	}
+
+	/*
+	 * "inclusion"
+	 */
+	class PPInclusion extends AbstractElementPropertyProvider {
+		public PPInclusion() {
+			super();
+		}
+
+		protected Object getElementProperty(HTMLPropertyDeclaration decl) {
+			return decl.getInclusion();
+		}
+	}
+
+	public static PropertyProvider getProvider(String propName) {
+		PropertyProviderFactory factory = getInstance();
+		PropertyProvider pp = (PropertyProvider) factory.registry.get(propName);
+		if (pp != null)
+			return pp;
+
+		pp = factory.create(propName);
+		if (pp == null)
+			return factory.defaultProvider;
+
+		factory.registry.put(propName, pp);
+		return pp;
+	}
+
+	private static PropertyProviderFactory instance = null;
+
+	private synchronized static PropertyProviderFactory getInstance() {
+		if (instance != null)
+			return instance;
+		instance = new PropertyProviderFactory();
+		return instance;
+	}
+
+	private Hashtable registry = new Hashtable();
+	private PropertyProvider defaultProvider = new DefaultProvider();
+
+	private PropertyProviderFactory() {
+		super();
+	}
+
+	private PropertyProvider create(String propName) {
+		PropertyProvider pp = null;
+		if (propName.equals(HTMLCMProperties.IS_JSP))
+			pp = new PPIsJSP();
+		else if (propName.equals(HTMLCMProperties.IS_XHTML))
+			pp = new PPIsXHTML();
+		else if (propName.equals(HTMLCMProperties.IS_SSI))
+			pp = new PPIsSSI();
+		else if (propName.equals(HTMLCMProperties.LAYOUT_TYPE))
+			pp = new PPLayoutType();
+		else if (propName.equals(HTMLCMProperties.LINE_BREAK_HINT))
+			pp = new PPLineBreakHint();
+		else if (propName.equals(HTMLCMProperties.PROHIBITED_ANCESTORS))
+			pp = new PPProhibitedAncestors();
+		else if (propName.equals(HTMLCMProperties.SHOULD_KEEP_SPACE))
+			pp = new PPShouldKeepSpace();
+		else if (propName.equals(HTMLCMProperties.SHOULD_INDENT_CHILD_SOURCE))
+			pp = new PPShouldIndentChildSource();
+		else if (propName.equals(HTMLCMProperties.TERMINATORS))
+			pp = new PPTerminators();
+		else if (propName.equals(HTMLCMProperties.TAGINFO))
+			pp = new PPTagInfo();
+		else if (propName.equals(HTMLCMProperties.OMIT_TYPE))
+			pp = new PPOmitType();
+		else if (propName.equals(HTMLCMProperties.INCLUSION))
+			pp = new PPInclusion();
+
+		return pp;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/Tag20ElementCollection.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/Tag20ElementCollection.java
new file mode 100644
index 0000000..8dd86bc
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/Tag20ElementCollection.java
@@ -0,0 +1,693 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+
+
+import java.lang.reflect.Field;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ * Factory for element declarations of JSP 2.0 Tag files.
+ */
+final class Tag20ElementCollection extends JSPElementCollection implements JSP20Namespace.ElementName {
+	// element IDs
+	private static class TagIds20 {
+		public static final int ID_SCRIPTLET = 0;
+		public static final int ID_EXPRESSION = 1;
+		public static final int ID_DECLARATION = 2;
+		public static final int ID_DIRECTIVE_TAG = 3;
+		public static final int ID_DIRECTIVE_INCLUDE = 4;
+		public static final int ID_DIRECTIVE_TAGLIB = 5;
+		public static final int ID_USEBEAN = 6;
+		public static final int ID_SETPROPERTY = 7;
+		public static final int ID_GETPROPERTY = 8;
+		public static final int ID_INCLUDE = 9;
+		public static final int ID_FORWARD = 10;
+		public static final int ID_PLUGIN = 11;
+		public static final int ID_PARAMS = 12;
+		public static final int ID_FALLBACK = 13;
+		public static final int ID_PARAM = 14;
+		public static final int ID_ROOT = 15;
+		public static final int ID_TEXT = 16;
+		public static final int ID_DIRECTIVE_VARIABLE = 17;
+		public static final int ID_DIRECTIVE_ATTRIBUTE = 18;
+		public static final int ID_BODY = 19;
+		public static final int ID_ATTRIBUTE = 20;
+		public static final int ID_ELEMENT = 21;
+		public static final int ID_DOBODY = 22;
+		public static final int ID_INVOKE = 23;
+		public static final int ID_OUTPUT = 24;
+
+		// chache the result of the reflection.
+		private static int numofids = -1;
+
+		public static int getNumOfIds() {
+			if (numofids != -1)
+				return numofids;
+
+			// NOTE: If the reflection is too slow, this method should
+			// just return the literal value, like 105.
+			// -- 5/25/2001
+			Class clazz = TagIds20.class;
+			Field[] fields = clazz.getFields();
+			numofids = 0;
+			for (int i = 0; i < fields.length; i++) {
+				String name = fields[i].getName();
+				if (name.startsWith("ID_"))//$NON-NLS-1$
+					numofids++;
+			}
+			return numofids;
+		}
+	}
+
+	// attribute creater
+	private class TACreater20 extends JACreater {
+
+		public TACreater20() {
+			super();
+		}
+
+		private void createForAttribute() {
+			AttrDecl adec = new AttrDecl(ATTR_NAME_NAME);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			adec.usage = CMAttributeDeclaration.REQUIRED;
+			declarations.putNamedItem(ATTR_NAME_NAME, adec);
+
+			adec = new AttrDecl(JSP20Namespace.ATTR_NAME_TRIM);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_VALUE_TRUE, ATTR_VALUE_FALSE};
+			adec.type.setEnumValues(values);
+			adec.type.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, ATTR_VALUE_TRUE);
+			adec.usage = CMAttributeDeclaration.OPTIONAL;
+			declarations.putNamedItem(JSP20Namespace.ATTR_NAME_TRIM, adec);
+		}
+
+		private void createForBody() {
+		}
+
+		private void createForDirAttribute() {
+			AttrDecl adec = new AttrDecl(ATTR_NAME_NAME);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			adec.usage = CMAttributeDeclaration.REQUIRED;
+			declarations.putNamedItem(ATTR_NAME_NAME, adec);
+
+			adec = new AttrDecl(JSP20Namespace.ATTR_NAME_REQUIRED);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = new String[]{ATTR_VALUE_TRUE, ATTR_VALUE_FALSE};
+			adec.type.setEnumValues(values);
+			adec.type.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, ATTR_VALUE_FALSE);
+			adec.usage = CMAttributeDeclaration.OPTIONAL;
+			declarations.putNamedItem(JSP20Namespace.ATTR_NAME_REQUIRED, adec);
+
+			adec = new AttrDecl(JSP20Namespace.ATTR_NAME_FRAGMENT);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			values = new String[]{ATTR_VALUE_TRUE, ATTR_VALUE_FALSE};
+			adec.type.setEnumValues(values);
+			adec.type.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, ATTR_VALUE_FALSE);
+			adec.usage = CMAttributeDeclaration.OPTIONAL;
+			declarations.putNamedItem(JSP20Namespace.ATTR_NAME_FRAGMENT, adec);
+
+			adec = new AttrDecl(JSP20Namespace.ATTR_NAME_RTEXPRVALUE);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			values = new String[]{ATTR_VALUE_TRUE, ATTR_VALUE_FALSE};
+			adec.type.setEnumValues(values);
+			adec.type.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, ATTR_VALUE_TRUE);
+			adec.usage = CMAttributeDeclaration.OPTIONAL;
+			declarations.putNamedItem(JSP20Namespace.ATTR_NAME_RTEXPRVALUE, adec);
+
+			adec = new AttrDecl(JSP20Namespace.ATTR_NAME_TYPE);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			adec.usage = CMAttributeDeclaration.OPTIONAL;
+			declarations.putNamedItem(JSP20Namespace.ATTR_NAME_TYPE, adec);
+
+			adec = new AttrDecl(JSP20Namespace.ATTR_NAME_DESCRIPTION);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			adec.usage = CMAttributeDeclaration.OPTIONAL;
+			declarations.putNamedItem(JSP20Namespace.ATTR_NAME_DESCRIPTION, adec);
+		}
+
+		private void createForDirTag() {
+			// ("import" URI optional)
+			AttrDecl adec = new AttrDecl(ATTR_NAME_IMPORT);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.URI);
+			adec.usage = CMAttributeDeclaration.OPTIONAL;
+			declarations.putNamedItem(ATTR_NAME_IMPORT, adec);
+
+			adec = new AttrDecl(JSP20Namespace.ATTR_NAME_DISPLAY_NAME);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.ID);
+			adec.usage = CMAttributeDeclaration.OPTIONAL;
+			declarations.putNamedItem(JSP20Namespace.ATTR_NAME_DISPLAY_NAME, adec);
+
+			adec = new AttrDecl(JSP20Namespace.ATTR_NAME_BODY_CONTENT);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {JSP20Namespace.ATTR_VALUE_EMPTY, JSP20Namespace.ATTR_VALUE_TAGDEPENDENT, JSP20Namespace.ATTR_VALUE_SCRIPTLESS};
+			adec.type.setEnumValues(values);
+			adec.usage = CMAttributeDeclaration.OPTIONAL;
+			adec.type.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, JSP20Namespace.ATTR_VALUE_SCRIPTLESS);
+			declarations.putNamedItem(JSP20Namespace.ATTR_NAME_BODY_CONTENT, adec);
+
+			adec = new AttrDecl(JSP20Namespace.ATTR_NAME_DYNAMIC_ATTRIBUTES);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			adec.usage = CMAttributeDeclaration.OPTIONAL;
+			declarations.putNamedItem(JSP20Namespace.ATTR_NAME_DYNAMIC_ATTRIBUTES, adec);
+			
+			adec = new AttrDecl(JSP20Namespace.ATTR_NAME_SMALL_ICON);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.URI);
+			adec.usage = CMAttributeDeclaration.OPTIONAL;
+			declarations.putNamedItem(JSP20Namespace.ATTR_NAME_SMALL_ICON, adec);
+
+			adec = new AttrDecl(JSP20Namespace.ATTR_NAME_LARGE_ICON);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.URI);
+			adec.usage = CMAttributeDeclaration.OPTIONAL;
+			declarations.putNamedItem(JSP20Namespace.ATTR_NAME_LARGE_ICON, adec);
+
+			adec = new AttrDecl(JSP20Namespace.ATTR_NAME_DESCRIPTION);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			adec.usage = CMAttributeDeclaration.OPTIONAL;
+			declarations.putNamedItem(JSP20Namespace.ATTR_NAME_DESCRIPTION, adec);
+
+			adec = new AttrDecl(JSP20Namespace.ATTR_NAME_EXAMPLE);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			adec.usage = CMAttributeDeclaration.OPTIONAL;
+			declarations.putNamedItem(JSP20Namespace.ATTR_NAME_EXAMPLE, adec);
+
+			adec = new AttrDecl(JSP20Namespace.ATTR_NAME_LANGUAGE);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			adec.type.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, ATTR_VALUE_JAVA);
+			adec.usage = CMAttributeDeclaration.OPTIONAL;
+			declarations.putNamedItem(JSP20Namespace.ATTR_NAME_LANGUAGE, adec);
+
+			adec = new AttrDecl(JSP11Namespace.ATTR_NAME_IMPORT);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			adec.usage = CMAttributeDeclaration.OPTIONAL;
+			declarations.putNamedItem(JSP11Namespace.ATTR_NAME_IMPORT, adec);
+
+			adec = new AttrDecl(JSP11Namespace.ATTR_NAME_PAGE_ENCODING);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			adec.type.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, JSP20Namespace.ATTR_VALUE_ENCODING_DEFAULT);
+			adec.usage = CMAttributeDeclaration.OPTIONAL;
+			declarations.putNamedItem(JSP11Namespace.ATTR_NAME_PAGE_ENCODING, adec);
+
+			adec = new AttrDecl(JSP20Namespace.ATTR_NAME_ISELIGNORED);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			values = new String[]{ATTR_VALUE_TRUE, ATTR_VALUE_FALSE};
+			adec.type.setEnumValues(values);
+			adec.type.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, ATTR_VALUE_FALSE);
+			adec.usage = CMAttributeDeclaration.OPTIONAL;
+			declarations.putNamedItem(JSP20Namespace.ATTR_NAME_ISELIGNORED, adec);
+		}
+
+		/**
+		 * Changed in 2.0 (tagdir added)
+		 */
+		void createForDirTaglib() {
+			// ("uri" URI OPTIONAL)
+			AttrDecl adec = new AttrDecl(ATTR_NAME_URI);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.URI);
+			adec.usage = CMAttributeDeclaration.OPTIONAL;
+			declarations.putNamedItem(ATTR_NAME_URI, adec);
+
+			// ("tagdir" URI OPTIONAL)
+			adec = new AttrDecl(JSP20Namespace.ATTR_NAME_TAGDIR);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.URI);
+			adec.usage = CMAttributeDeclaration.OPTIONAL;
+			declarations.putNamedItem(JSP20Namespace.ATTR_NAME_TAGDIR, adec);
+
+			// ("prefix" CDATA REQUIRED)
+			adec = new AttrDecl(ATTR_NAME_PREFIX);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			adec.usage = CMAttributeDeclaration.REQUIRED;
+			declarations.putNamedItem(ATTR_NAME_PREFIX, adec);
+		}
+
+		private void createForDirVariable() {
+			AttrDecl adec = new AttrDecl(JSP20Namespace.ATTR_NAME_NAME_GIVEN);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			adec.usage = CMAttributeDeclaration.OPTIONAL;
+			declarations.putNamedItem(JSP20Namespace.ATTR_NAME_NAME_GIVEN, adec);
+
+			adec = new AttrDecl(JSP20Namespace.ATTR_NAME_NAME_FROM_ATTRIBUTE);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			adec.usage = CMAttributeDeclaration.OPTIONAL;
+			declarations.putNamedItem(JSP20Namespace.ATTR_NAME_NAME_FROM_ATTRIBUTE, adec);
+
+			adec = new AttrDecl(JSP20Namespace.ATTR_NAME_ALIAS);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			adec.usage = CMAttributeDeclaration.OPTIONAL;
+			declarations.putNamedItem(JSP20Namespace.ATTR_NAME_ALIAS, adec);
+
+			adec = new AttrDecl(JSP20Namespace.ATTR_NAME_VARIABLE_CLASS);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			adec.type.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, JSP20Namespace.ATTR_VALUE_VARIABLE_CLASS_DEFAULT);
+			adec.usage = CMAttributeDeclaration.OPTIONAL;
+			declarations.putNamedItem(JSP20Namespace.ATTR_NAME_VARIABLE_CLASS, adec);
+
+			adec = new AttrDecl(JSP20Namespace.ATTR_NAME_DECLARE);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = new String[]{ATTR_VALUE_TRUE, ATTR_VALUE_FALSE};
+			adec.type.setEnumValues(values);
+			adec.type.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, ATTR_VALUE_TRUE);
+			adec.usage = CMAttributeDeclaration.OPTIONAL;
+			declarations.putNamedItem(JSP20Namespace.ATTR_NAME_DECLARE, adec);
+
+			adec = new AttrDecl(JSP20Namespace.ATTR_NAME_DESCRIPTION);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			adec.usage = CMAttributeDeclaration.OPTIONAL;
+			declarations.putNamedItem(JSP20Namespace.ATTR_NAME_DESCRIPTION, adec);
+
+			adec = new AttrDecl(JSP11Namespace.ATTR_NAME_SCOPE);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			adec.usage = CMAttributeDeclaration.OPTIONAL;
+			values = new String[]{JSP20Namespace.ATTR_VALUE_SCOPE_NESTED, JSP20Namespace.ATTR_VALUE_SCOPE_AT_BEGIN, JSP20Namespace.ATTR_VALUE_SCOPE_AT_END};
+			adec.type.setEnumValues(values);
+			adec.type.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, JSP20Namespace.ATTR_VALUE_SCOPE_NESTED);
+			declarations.putNamedItem(JSP11Namespace.ATTR_NAME_SCOPE, adec);
+		}
+
+		private void createForDoBody() {
+			AttrDecl adec = new AttrDecl(JSP20Namespace.ATTR_NAME_VAR);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			adec.usage = CMAttributeDeclaration.OPTIONAL;
+			declarations.putNamedItem(JSP20Namespace.ATTR_NAME_VAR, adec);
+
+			adec = new AttrDecl(JSP20Namespace.ATTR_NAME_VARREADER);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			adec.usage = CMAttributeDeclaration.OPTIONAL;
+			declarations.putNamedItem(JSP20Namespace.ATTR_NAME_VARREADER, adec);
+
+			adec = new AttrDecl(JSP11Namespace.ATTR_NAME_SCOPE);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_VALUE_PAGE, ATTR_VALUE_REQUEST, ATTR_VALUE_SESSION, ATTR_VALUE_APPLICATION};
+			adec.type.setEnumValues(values);
+			adec.type.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, ATTR_VALUE_PAGE);
+			adec.usage = CMAttributeDeclaration.OPTIONAL;
+			declarations.putNamedItem(JSP11Namespace.ATTR_NAME_SCOPE, adec);
+		}
+
+		private void createForElement() {
+			AttrDecl adec = new AttrDecl(ATTR_NAME_NAME);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			adec.usage = CMAttributeDeclaration.REQUIRED;
+			declarations.putNamedItem(ATTR_NAME_NAME, adec);
+		}
+
+		private void createForInvoke() {
+			AttrDecl adec = new AttrDecl(JSP20Namespace.ATTR_NAME_FRAGMENT);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.URI);
+			adec.usage = CMAttributeDeclaration.REQUIRED;
+			declarations.putNamedItem(JSP20Namespace.ATTR_NAME_FRAGMENT, adec);
+
+			adec = new AttrDecl(JSP20Namespace.ATTR_NAME_VAR);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			adec.usage = CMAttributeDeclaration.OPTIONAL;
+			declarations.putNamedItem(JSP20Namespace.ATTR_NAME_VAR, adec);
+
+			adec = new AttrDecl(JSP20Namespace.ATTR_NAME_VARREADER);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			adec.usage = CMAttributeDeclaration.OPTIONAL;
+			declarations.putNamedItem(JSP20Namespace.ATTR_NAME_VARREADER, adec);
+
+			adec = new AttrDecl(JSP11Namespace.ATTR_NAME_SCOPE);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_VALUE_PAGE, ATTR_VALUE_REQUEST, ATTR_VALUE_SESSION, ATTR_VALUE_APPLICATION};
+			adec.type.setEnumValues(values);
+			adec.type.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, ATTR_VALUE_PAGE);
+			adec.usage = CMAttributeDeclaration.OPTIONAL;
+			declarations.putNamedItem(JSP11Namespace.ATTR_NAME_SCOPE, adec);
+		}
+
+		private void createForOutput() {
+			AttrDecl adec = new AttrDecl(JSP20Namespace.ATTR_NAME_OMIT_XML_DECL);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_VALUE_TRUE, ATTR_VALUE_FALSE, JSP20Namespace.ATTR_VALUE_YES, JSP20Namespace.ATTR_VALUE_NO};
+			adec.type.setEnumValues(values);
+			adec.type.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, JSP20Namespace.ATTR_VALUE_NO);
+			adec.usage = CMAttributeDeclaration.OPTIONAL;
+			declarations.putNamedItem(JSP20Namespace.ATTR_NAME_OMIT_XML_DECL, adec);
+
+			adec = new AttrDecl(JSP20Namespace.ATTR_NAME_DOCTYPE_ROOT_ELEMENT);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			adec.usage = CMAttributeDeclaration.OPTIONAL;
+			declarations.putNamedItem(JSP20Namespace.ATTR_NAME_DOCTYPE_ROOT_ELEMENT, adec);
+
+			adec = new AttrDecl(JSP20Namespace.ATTR_NAME_DOCTYPE_SYSTEM);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			adec.usage = CMAttributeDeclaration.OPTIONAL;
+			declarations.putNamedItem(JSP20Namespace.ATTR_NAME_DOCTYPE_SYSTEM, adec);
+
+			adec = new AttrDecl(JSP20Namespace.ATTR_NAME_DOCTYPE_PUBLIC);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			adec.usage = CMAttributeDeclaration.OPTIONAL;
+			declarations.putNamedItem(JSP20Namespace.ATTR_NAME_DOCTYPE_PUBLIC, adec);
+		}
+		
+		private void createForRoot() {
+			// ("xmlns:jsp" CDATA "http://java.sun.com/JSP/Page")
+			AttrDecl adec = new AttrDecl(ATTR_NAME_XMLNS_JSP);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			adec.type.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, ATTR_VALUE_XMLNS_JSP);
+			declarations.putNamedItem(ATTR_NAME_XMLNS_JSP, adec);
+			// ("version" CDATA REQUIRED)
+			adec = new AttrDecl(ATTR_NAME_VERSION);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			adec.type.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, JSP20Namespace.ATTR_VALUE_JSP_VER_20);
+			adec.usage = CMAttributeDeclaration.REQUIRED;
+			declarations.putNamedItem(ATTR_NAME_VERSION, adec);
+		}
+		
+		private void createForPlugin() {
+			// ("type" ENUM REQUIRED (bean|applet))
+			AttrDecl adec = new AttrDecl(ATTR_NAME_TYPE);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			adec.usage = CMAttributeDeclaration.REQUIRED;
+			String[] values = {ATTR_VALUE_BEAN, ATTR_VALUE_APPLET};
+			adec.type.setEnumValues(values);
+			declarations.putNamedItem(ATTR_NAME_TYPE, adec);
+
+			// ("code" CDATA REQUIRED)
+			adec = new AttrDecl(ATTR_NAME_CODE);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.URI);
+			adec.usage = CMAttributeDeclaration.REQUIRED;
+			declarations.putNamedItem(ATTR_NAME_CODE, adec);
+
+			// ("codebase" URI REQUIRED)
+			adec = new AttrDecl(ATTR_NAME_CODEBASE);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.URI);
+			adec.usage = CMAttributeDeclaration.REQUIRED;
+			declarations.putNamedItem(ATTR_NAME_CODEBASE, adec);
+
+			// ("align" ENUM IMPLIED (top|middle|bottom|left|right))
+			adec = new AttrDecl(ATTR_NAME_ALIGN);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] aligns = {ATTR_VALUE_TOP, ATTR_VALUE_MIDDLE, ATTR_VALUE_BOTTOM, ATTR_VALUE_LEFT, ATTR_VALUE_RIGHT};
+			adec.type.setEnumValues(aligns);
+			adec.type.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, ATTR_VALUE_BOTTOM);
+			declarations.putNamedItem(ATTR_NAME_ALIGN, adec);
+
+			// ("archive" CDATA IMPLIED)
+			adec = new AttrDecl(ATTR_NAME_ARCHIVE);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			declarations.putNamedItem(ATTR_NAME_ARCHIVE, adec);
+
+			// ("height" CDATA IMPLIED)
+			adec = new AttrDecl(ATTR_NAME_HEIGHT);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			declarations.putNamedItem(ATTR_NAME_HEIGHT, adec);
+
+			// ("hspace" CDATA IMPLIED)
+			adec = new AttrDecl(ATTR_NAME_HSPACE);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			declarations.putNamedItem(ATTR_NAME_HSPACE, adec);
+
+			// ("jreversion" CDATA DECLARED "1.1")
+			adec = new AttrDecl(ATTR_NAME_JREVERSION);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			adec.type.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, JSP20Namespace.ATTR_VALUE_JVER12);
+			declarations.putNamedItem(ATTR_NAME_JREVERSION, adec);
+
+			// ("name" CDATA IMPLIED)
+			adec = new AttrDecl(ATTR_NAME_NAME);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			declarations.putNamedItem(ATTR_NAME_NAME, adec);
+
+			// ("vspace" CDATA IMPLIED)
+			adec = new AttrDecl(ATTR_NAME_VSPACE);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			declarations.putNamedItem(ATTR_NAME_VSPACE, adec);
+
+			// ("width" CDATA IMPLIED)
+			adec = new AttrDecl(ATTR_NAME_WIDTH);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			declarations.putNamedItem(ATTR_NAME_WIDTH, adec);
+
+			// ("nspluginurl" URI IMPLIED)
+			adec = new AttrDecl(ATTR_NAME_NSPLUGINURL);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.URI);
+			declarations.putNamedItem(ATTR_NAME_NSPLUGINURL, adec);
+
+			// ("iepluginurl" URI IMPLIED)
+			adec = new AttrDecl(ATTR_NAME_IEPLUGINURL);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.URI);
+			declarations.putNamedItem(ATTR_NAME_IEPLUGINURL, adec);
+			
+			// ("mayscript" ENUM IMPLIED (true | false)
+			adec = new AttrDecl(JSP20Namespace.ATTR_NAME_MAYSCRIPT);
+			adec.type = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			adec.type.setEnumValues(new String[] {ATTR_VALUE_TRUE, ATTR_VALUE_FALSE});
+			declarations.putNamedItem(JSP20Namespace.ATTR_NAME_MAYSCRIPT, adec);
+		}
+
+		public CMNamedNodeMapImpl getDeclarations(int eid) {
+			switch (eid) {
+				case TagIds20.ID_DIRECTIVE_TAG :
+					createForDirTag();
+					break;
+				case TagIds20.ID_DIRECTIVE_VARIABLE :
+					createForDirVariable();
+					break;
+				case TagIds20.ID_DIRECTIVE_ATTRIBUTE :
+					createForDirAttribute();
+					break;
+				case TagIds20.ID_DIRECTIVE_TAGLIB :
+					createForDirTaglib();
+					break;
+				case TagIds20.ID_ATTRIBUTE :
+					createForAttribute();
+					break;
+				case TagIds20.ID_ELEMENT :
+					createForElement();
+					break;
+				case TagIds20.ID_BODY :
+					createForBody();
+					break;
+				case TagIds20.ID_DOBODY :
+					createForDoBody();
+					break;
+				case TagIds20.ID_INVOKE :
+					createForInvoke();
+					break;
+				case TagIds20.ID_OUTPUT :
+					createForOutput();
+					break;
+				case TagIds20.ID_ROOT :
+					createForRoot();
+					break;
+				case TagIds20.ID_PLUGIN :
+					createForPlugin();
+					break;
+				default :
+					super.getDeclarations(eid);
+					break;
+			}
+			return declarations;
+		}
+	}
+
+	private static String[] names = null;
+
+	static {
+		names = new String[TagIds20.getNumOfIds()];
+		names[TagIds20.ID_SCRIPTLET] = JSP11Namespace.ElementName.SCRIPTLET;
+		names[TagIds20.ID_EXPRESSION] = JSP11Namespace.ElementName.EXPRESSION;
+		names[TagIds20.ID_DECLARATION] = JSP11Namespace.ElementName.DECLARATION;
+		names[TagIds20.ID_DIRECTIVE_TAG] = JSP20Namespace.ElementName.DIRECTIVE_TAG;
+		names[TagIds20.ID_DIRECTIVE_INCLUDE] = JSP11Namespace.ElementName.DIRECTIVE_INCLUDE;
+		names[TagIds20.ID_DIRECTIVE_TAGLIB] = JSP11Namespace.ElementName.DIRECTIVE_TAGLIB;
+		names[TagIds20.ID_USEBEAN] = JSP11Namespace.ElementName.USEBEAN;
+		names[TagIds20.ID_SETPROPERTY] = JSP11Namespace.ElementName.SETPROPERTY;
+		names[TagIds20.ID_GETPROPERTY] = JSP11Namespace.ElementName.GETPROPERTY;
+		names[TagIds20.ID_INCLUDE] = JSP11Namespace.ElementName.INCLUDE;
+		names[TagIds20.ID_FORWARD] = JSP11Namespace.ElementName.FORWARD;
+		names[TagIds20.ID_PLUGIN] = JSP11Namespace.ElementName.PLUGIN;
+		names[TagIds20.ID_PARAMS] = JSP11Namespace.ElementName.PARAMS;
+		names[TagIds20.ID_FALLBACK] = JSP11Namespace.ElementName.FALLBACK;
+		names[TagIds20.ID_PARAM] = JSP11Namespace.ElementName.PARAM;
+		names[TagIds20.ID_ROOT] = JSP11Namespace.ElementName.ROOT;
+		names[TagIds20.ID_TEXT] = JSP11Namespace.ElementName.TEXT;
+		names[TagIds20.ID_DIRECTIVE_VARIABLE] = JSP20Namespace.ElementName.DIRECTIVE_VARIABLE;
+		names[TagIds20.ID_DIRECTIVE_ATTRIBUTE] = JSP20Namespace.ElementName.DIRECTIVE_ATTRIBUTE;
+		names[TagIds20.ID_BODY] = JSP20Namespace.ElementName.BODY;
+		names[TagIds20.ID_ATTRIBUTE] = JSP20Namespace.ElementName.ATTRIBUTE;
+		names[TagIds20.ID_ELEMENT] = JSP20Namespace.ElementName.ELEMENT;
+		names[TagIds20.ID_DOBODY] = JSP20Namespace.ElementName.DOBODY;
+		names[TagIds20.ID_INVOKE] = JSP20Namespace.ElementName.INVOKE;
+		names[TagIds20.ID_OUTPUT] = JSP20Namespace.ElementName.OUTPUT;
+	}
+
+	/**
+	 */
+	public Tag20ElementCollection() {
+		super(Tag20ElementCollection.names, TOLERANT_CASE);
+	}
+
+	/**
+	 * @return org.eclipse.wst.xml.core.internal.contentmodel.CMNode
+	 * @param elementName
+	 *            java.lang.String
+	 */
+	protected CMNode create(String elementName) {
+		return createElemDecl(getID(elementName));
+	}
+
+	/**
+	 * @param eid
+	 *            int
+	 */
+	CMGroupImpl createContent(int eid) {
+		if (eid == ID_UNKNOWN)
+			return null;
+
+		CMGroupImpl content = null;
+		CMNode child = null;
+
+		switch (eid) {
+			case Ids.ID_ROOT :
+				content = new CMGroupImpl(CMGroup.CHOICE, 0, CMContentImpl.UNBOUNDED);
+				int validChildren[] = {
+				// %Directives;
+							Ids.ID_TEXT, Ids.ID_DIRECTIVE_PAGE, Ids.ID_DIRECTIVE_INCLUDE, TagIds20.ID_DIRECTIVE_TAG, TagIds20.ID_DIRECTIVE_VARIABLE, TagIds20.ID_DIRECTIVE_ATTRIBUTE, TagIds20.ID_BODY, TagIds20.ID_ATTRIBUTE,
+							// %Scripts;
+							Ids.ID_SCRIPTLET, Ids.ID_DECLARATION, Ids.ID_EXPRESSION,
+							// %Actions;
+							Ids.ID_USEBEAN, Ids.ID_SETPROPERTY, Ids.ID_GETPROPERTY, Ids.ID_INCLUDE, Ids.ID_FORWARD, Ids.ID_PLUGIN};
+				for (int i = 0; i < validChildren.length; i++) {
+					child = item(validChildren[i]);
+					if (child != null)
+						content.appendChild(child);
+				}
+				break;
+			default :
+				content = super.createContent(eid);
+				break;
+		}
+
+		return content;
+	}
+
+	/**
+	 * @param eid
+	 *            int
+	 */
+	HTMLElementDeclaration createElemDecl(int eid) {
+		if (eid == ID_UNKNOWN)
+			return null;
+
+		TypePacket packet = new TypePacket();
+		switch (eid) {
+			case TagIds20.ID_DIRECTIVE_TAG :
+				// directive.taglib
+				packet.name = DIRECTIVE_TAG;
+				packet.omit = HTMLElementDeclaration.OMIT_END;
+				packet.layout = HTMLElementDeclaration.LAYOUT_HIDDEN;
+				packet.format = HTMLElementDeclaration.FORMAT_JSP_DIRECTIVE;
+				break;
+			case TagIds20.ID_DIRECTIVE_VARIABLE :
+				// directive.taglib
+				packet.name = DIRECTIVE_VARIABLE;
+				packet.omit = HTMLElementDeclaration.OMIT_END;
+				packet.layout = HTMLElementDeclaration.LAYOUT_HIDDEN;
+				packet.format = HTMLElementDeclaration.FORMAT_JSP_DIRECTIVE;
+				break;
+			case TagIds20.ID_DIRECTIVE_ATTRIBUTE :
+				// directive.taglib
+				packet.name = DIRECTIVE_ATTRIBUTE;
+				packet.omit = HTMLElementDeclaration.OMIT_END;
+				packet.layout = HTMLElementDeclaration.LAYOUT_HIDDEN;
+				packet.format = HTMLElementDeclaration.FORMAT_JSP_DIRECTIVE;
+				break;
+			case TagIds20.ID_DIRECTIVE_TAGLIB :
+				// directive.taglib
+				packet.name = DIRECTIVE_TAGLIB;
+				packet.omit = HTMLElementDeclaration.OMIT_END;
+				packet.layout = HTMLElementDeclaration.LAYOUT_HIDDEN;
+				packet.format = HTMLElementDeclaration.FORMAT_JSP_DIRECTIVE;
+				break;
+			case TagIds20.ID_BODY :
+				// declaration
+				packet.name = BODY;
+				packet.content = CMElementDeclaration.CDATA;
+				packet.layout = HTMLElementDeclaration.LAYOUT_OBJECT;
+				packet.indentChild = true;
+				packet.format = HTMLElementDeclaration.FORMAT_JSP_SCRIPT;
+				break;
+			case TagIds20.ID_ELEMENT :
+				// declaration
+				packet.name = JSP20Namespace.ElementName.ELEMENT;
+				packet.content = CMElementDeclaration.CDATA;
+				packet.layout = HTMLElementDeclaration.LAYOUT_OBJECT;
+				packet.indentChild = true;
+				packet.format = HTMLElementDeclaration.FORMAT_JSP_SCRIPT;
+				break;
+			case TagIds20.ID_ATTRIBUTE :
+				// declaration
+				packet.name = JSP20Namespace.ElementName.ATTRIBUTE;
+				packet.content = CMElementDeclaration.CDATA;
+				packet.layout = HTMLElementDeclaration.LAYOUT_OBJECT;
+				packet.indentChild = true;
+				packet.format = HTMLElementDeclaration.FORMAT_JSP_SCRIPT;
+				break;
+			case TagIds20.ID_DOBODY :
+				// declaration
+				packet.name = JSP20Namespace.ElementName.DOBODY;
+				packet.content = CMElementDeclaration.CDATA;
+				packet.layout = HTMLElementDeclaration.LAYOUT_OBJECT;
+				packet.indentChild = true;
+				packet.format = HTMLElementDeclaration.FORMAT_JSP_SCRIPT;
+				break;
+			case TagIds20.ID_INVOKE :
+				// declaration
+				packet.name = JSP20Namespace.ElementName.INVOKE;
+				packet.content = CMElementDeclaration.CDATA;
+				packet.layout = HTMLElementDeclaration.LAYOUT_OBJECT;
+				packet.indentChild = true;
+				packet.format = HTMLElementDeclaration.FORMAT_JSP_SCRIPT;
+				break;
+			case TagIds20.ID_OUTPUT :
+				// declaration
+				packet.name = JSP20Namespace.ElementName.OUTPUT;
+				packet.content = CMElementDeclaration.CDATA;
+				packet.layout = HTMLElementDeclaration.LAYOUT_OBJECT;
+				packet.indentChild = true;
+				packet.format = HTMLElementDeclaration.FORMAT_JSP_SCRIPT;
+				break;
+			case TagIds20.ID_ROOT :
+				packet.name = ROOT;
+				packet.content = CMElementDeclaration.ELEMENT;
+				packet.layout = HTMLElementDeclaration.LAYOUT_HIDDEN; // same as HTML
+				break;
+			case TagIds20.ID_PLUGIN :
+				// plugin
+				packet.name = PLUGIN;
+				packet.content = CMElementDeclaration.ELEMENT;
+				packet.layout = HTMLElementDeclaration.LAYOUT_OBJECT;
+				packet.indentChild = true;
+				break;
+			default :
+				return super.createElemDecl(eid);
+		}
+		ElemDecl decl = new ElemDecl(packet);
+
+		CMGroupImpl content = createContent(eid);
+		if (content != null)
+			decl.setContent(content);
+
+		TACreater20 creater = new TACreater20();
+		decl.setAttributes(creater.getDeclarations(eid));
+
+		return decl;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/TagCMDocImpl.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/TagCMDocImpl.java
new file mode 100644
index 0000000..b2298f2
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/TagCMDocImpl.java
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel;
+
+/**
+ * Implementation of CMDocument for the JSP 2.0 tag files.
+ */
+class TagCMDocImpl extends JCMDocImpl {
+	/**
+	 * HCMDocImpl constructor comment.
+	 */
+	public TagCMDocImpl(String docTypeName, CMNamespaceImpl targetNamespace) {
+		super(docTypeName, targetNamespace, new Tag20ElementCollection());
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/AttributeCollection.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/AttributeCollection.java
new file mode 100644
index 0000000..e563228
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/AttributeCollection.java
@@ -0,0 +1,314 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import java.util.Iterator;
+
+import org.eclipse.wst.html.core.internal.contentmodel.HTMLAttributeDeclaration;
+import org.eclipse.wst.html.core.internal.contentmodel.HTMLCMDataType;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ * Factory for attribute declarations.
+ */
+final class AttributeCollection extends CMNamedNodeMapImpl implements CHTMLNamespace {
+	/**
+	 * constructor.
+	 */
+	public AttributeCollection() {
+		super();
+	}
+
+	/**
+	 * Create an attribute declaration.
+	 * @param attrName java.lang.String
+	 */
+	private HTMLAttrDeclImpl create(String attrName) {
+		HTMLAttrDeclImpl attr = null;
+		HTMLCMDataTypeImpl atype = null;
+
+		if (attrName.equalsIgnoreCase(ATTR_NAME_ACTION)) {
+			// (action %URI #REQUIRED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.URI);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ACTION, atype, CMAttributeDeclaration.REQUIRED);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ALT)) {
+			// (alt %Text; #REQUIRED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.TEXT);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ALT, atype, CMAttributeDeclaration.REQUIRED);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_BORDER)) {
+			// (border %Pixels; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.PIXELS);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_BORDER, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_CHECKED)) {
+			// (checked (checked) #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_NAME_CHECKED};
+			atype.setEnumValues(values);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_CHECKED, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_CLEAR)) {
+			// (clear (left | all | right | none) none)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_VALUE_LEFT, ATTR_VALUE_ALL, ATTR_VALUE_RIGHT, ATTR_VALUE_NONE};
+			atype.setEnumValues(values);
+			atype.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, ATTR_VALUE_NONE);
+
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_CLEAR, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_COLS)) {
+			// (cols NUMBER #REQUIRED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.NUMBER);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_COLS, atype, CMAttributeDeclaration.REQUIRED);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ENCTYPE)) {
+			// (enctype %ContentType; "application/x-www-form-urlencoded")
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.CONTENT_TYPE);
+			atype.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, ATTR_VALUE_WWW_FORM_URLENCODED);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ENCTYPE, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_HEIGHT)) {
+			// (height %Length; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.LENGTH);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_HEIGHT, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_HREF)) {
+			// (href %URI; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.URI);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_HREF, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_HSPACE)) {
+			// (hspace %Pixels; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.PIXELS);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_HSPACE, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_HTTP_EQUIV)) {
+			// (http-equiv NAME #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.NAME);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_HTTP_EQUIV, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_MAXLENGTH)) {
+			// (maxlength NUMBER #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.NUMBER);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_MAXLENGTH, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_METHOD)) {
+			// (method (GET|POST) GET)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_VALUE_GET, ATTR_VALUE_POST};
+			atype.setEnumValues(values);
+			atype.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, ATTR_VALUE_GET);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_METHOD, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_MULTIPLE)) {
+			// (multiple (multiple) #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_NAME_MULTIPLE};
+			atype.setEnumValues(values);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_MULTIPLE, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_NAME)) {
+			// (name CDATA #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_NAME, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_NOSHADE)) {
+			// (noshade (noshade) #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_NAME_NOSHADE};
+			atype.setEnumValues(values);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_NOSHADE, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_ROWS)) {
+			// (rows NUMBER #REQUIRED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.NUMBER);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_ROWS, atype, CMAttributeDeclaration.REQUIRED);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_SELECTED)) {
+			// (selected (selected) #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+			String[] values = {ATTR_NAME_SELECTED};
+			atype.setEnumValues(values);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_SELECTED, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_SIZE)) {
+			// (size %Pixels; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.PIXELS);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_SIZE, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_SRC)) {
+			// (src %URI; #IMPLIED)
+			// NOTE: "src" attributes are defined in several elements.
+			//		 The definition of IMG is different from others.
+			//		 So, it should be locally defined.
+			atype = new HTMLCMDataTypeImpl(CMDataType.URI);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_SRC, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_TYPE)) {
+			// (type %CotentType; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.CONTENT_TYPE);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_TYPE, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_VALUE)) {
+			// (value CDATA #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_VALUE, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_VERSION)) {
+			// (version CDATA #FIXED '%HTML.Version;)
+			atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+			atype.setImpliedValue(CMDataType.IMPLIED_VALUE_FIXED, ATTR_VALUE_VERSION_TRANSITIONAL);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_VERSION, atype, CMAttributeDeclaration.FIXED);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_WIDTH)) {
+			// (width %Length; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.LENGTH);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_WIDTH, atype, CMAttributeDeclaration.OPTIONAL);
+
+		}
+		else if (attrName.equalsIgnoreCase(ATTR_NAME_VSPACE)) {
+			// (vspace %Pixels; #IMPLIED)
+			atype = new HTMLCMDataTypeImpl(HTMLCMDataType.PIXELS);
+			attr = new HTMLAttrDeclImpl(ATTR_NAME_VSPACE, atype, CMAttributeDeclaration.OPTIONAL);
+
+			// <<D205514
+		}
+		else {
+			// unknown attribute; maybe error.
+			// should warn.
+			attr = null;
+		}
+
+		return attr;
+	}
+
+	/**
+	 * Get %bodycolors; declarations.
+	 */
+	public void getBodycolors(CMNamedNodeMapImpl declarations) {
+	}
+
+	/**
+	 * Get align attribute which has %IAlign; as values..
+	 */
+	public static final HTMLAttrDeclImpl createAlignForImage() {
+		// align (local)
+		HTMLCMDataTypeImpl atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+		// set enum values
+		String[] values = {ATTR_VALUE_TOP, ATTR_VALUE_MIDDLE, ATTR_VALUE_BOTTOM, ATTR_VALUE_LEFT, ATTR_VALUE_RIGHT};
+		atype.setEnumValues(values);
+
+		HTMLAttrDeclImpl attr = new HTMLAttrDeclImpl(ATTR_NAME_ALIGN, atype, CMAttributeDeclaration.OPTIONAL);
+		return attr;
+	}
+
+	/**
+	 * Create an attribute declaration for <code>align</code>
+	 * in several elements, like <code>P</code>, <code>DIV</code>.
+	 * The values are different from attributes those have the same name
+	 * in other elements (<code>IMG</code> and <code>TABLE</code>).
+	 * So, it can't treat as global attributes.
+	 * <strong>NOTE: These attribute declaration has
+	 * no owner CMDocument instance.</strong>
+	 */
+	public static final HTMLAttrDeclImpl createAlignForParagraph() {
+		HTMLCMDataTypeImpl atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+		// set enum values: left|center|right|justify
+		String[] values = {ATTR_VALUE_LEFT, ATTR_VALUE_CENTER, ATTR_VALUE_RIGHT,};
+		atype.setEnumValues(values);
+
+		HTMLAttrDeclImpl attr = new HTMLAttrDeclImpl(ATTR_NAME_ALIGN, atype, CMAttributeDeclaration.OPTIONAL);
+		return attr;
+	}
+
+	/**
+	 * Get %attrs; declarations.
+	 * %attrs; consists of %coreattrs;, %i18n, and %events;.
+	 */
+	public void getAttrs(CMNamedNodeMapImpl declarations) {
+	}
+
+	/**
+	 * Get %coreattrs; declarations.
+	 */
+	public void getCore(CMNamedNodeMapImpl declarations) {
+	}
+
+	/**
+	 * Get a global attribute declaration.
+	 * @param attrName java.lang.String
+	 */
+	public HTMLAttributeDeclaration getDeclaration(String attrName) {
+		CMNode cmnode = getNamedItem(attrName);
+		if (cmnode != null)
+			return (HTMLAttributeDeclaration) cmnode; // already exists.
+
+		HTMLAttrDeclImpl dec = create(attrName);
+		if (dec != null)
+			putNamedItem(attrName, dec);
+
+		return dec;
+	}
+
+	/**
+	 * Get declarations which are specified by names.
+	 * @param names java.util.Iterator
+	 */
+	public void getDeclarations(CMNamedNodeMapImpl declarations, Iterator names) {
+		while (names.hasNext()) {
+			String attrName = (String) names.next();
+			HTMLAttributeDeclaration dec = getDeclaration(attrName);
+			if (dec != null)
+				declarations.putNamedItem(attrName, dec);
+		}
+	}
+
+	/**
+	 * Get %events; declarations.
+	 */
+	public void getEvents(CMNamedNodeMapImpl declarations) {
+	}
+
+	/**
+	 * Get %i18n; declarations.
+	 */
+	public void getI18n(CMNamedNodeMapImpl declarations) {
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/CHCMDocImpl.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/CHCMDocImpl.java
new file mode 100644
index 0000000..00b3528
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/CHCMDocImpl.java
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import org.eclipse.wst.html.core.internal.contentmodel.HTMLCMDocument;
+import org.eclipse.wst.html.core.internal.contentmodel.HTMLElementDeclaration;
+import org.eclipse.wst.html.core.internal.contentmodel.HTMLEntityDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ * CMDocument implementation for the HTML.
+ */
+public class CHCMDocImpl extends CMNodeImpl implements HTMLCMDocument {
+
+	/** Namespace for all names of elements, entities and attributes. */
+	private CMNamespace namespace = null;
+	private ElementCollection elements = null;
+	private EntityCollection entities = null;
+	private AttributeCollection attributes = null;
+
+	/**
+	 */
+	public CHCMDocImpl(String docTypeName, CMNamespace targetNamespace) {
+		super(docTypeName);
+		namespace = targetNamespace;
+		attributes = new AttributeCollection();
+		elements = new ElementCollection(attributes);
+		entities = new EntityCollection();
+	}
+
+	AttributeCollection getAttributes() {
+		return attributes;
+	}
+
+	public HTMLElementDeclaration getElementDeclaration(String elementName) {
+		if (elements == null)
+			return null;
+		return (HTMLElementDeclaration) elements.getNamedItem(elementName);
+	}
+
+	public CMNamedNodeMap getElements() {
+		return elements;
+	}
+
+	public CMNamedNodeMap getEntities() {
+		return entities;
+	}
+
+	public HTMLEntityDeclaration getEntityDeclaration(String entityName) {
+		if (entities == null)
+			return null;
+		return (HTMLEntityDeclaration) entities.getNamedItem(entityName);
+	}
+
+	/**
+	 * @see org.eclipse.wst.xml.core.internal.contentmodel.CMDocument
+	 */
+	public org.eclipse.wst.xml.core.internal.contentmodel.CMNamespace getNamespace() {
+		return namespace;
+	}
+
+	/**
+	 * @see org.eclipse.wst.xml.core.internal.contentmodel.CMNode
+	 */
+	public int getNodeType() {
+		return CMNode.DOCUMENT;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/CHTMLNamespace.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/CHTMLNamespace.java
new file mode 100644
index 0000000..456503c
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/CHTMLNamespace.java
@@ -0,0 +1,152 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+
+
+
+/**
+ * Provide all names defined in the HTML 4.0? specification.
+ */
+public interface CHTMLNamespace {
+
+	// Element names
+	public static interface ElementName {
+		public static final String A = HTML40Namespace.ElementName.A;
+		public static final String ADDRESS = HTML40Namespace.ElementName.ADDRESS;
+		public static final String BASE = HTML40Namespace.ElementName.BASE;
+		public static final String BLOCKQUOTE = HTML40Namespace.ElementName.BLOCKQUOTE;
+		public static final String BODY = HTML40Namespace.ElementName.BODY;
+		public static final String BR = HTML40Namespace.ElementName.BR;
+		public static final String CENTER = HTML40Namespace.ElementName.CENTER;
+		public static final String DD = HTML40Namespace.ElementName.DD;
+		public static final String DIR = HTML40Namespace.ElementName.DIR;
+		public static final String DIV = HTML40Namespace.ElementName.DIV;
+		public static final String DL = HTML40Namespace.ElementName.DL;
+		public static final String DT = HTML40Namespace.ElementName.DT;
+		public static final String FORM = HTML40Namespace.ElementName.FORM;
+		public static final String H1 = HTML40Namespace.ElementName.H1;
+		public static final String H2 = HTML40Namespace.ElementName.H2;
+		public static final String H3 = HTML40Namespace.ElementName.H3;
+		public static final String H4 = HTML40Namespace.ElementName.H4;
+		public static final String H5 = HTML40Namespace.ElementName.H5;
+		public static final String H6 = HTML40Namespace.ElementName.H6;
+		public static final String HEAD = HTML40Namespace.ElementName.HEAD;
+		public static final String HR = HTML40Namespace.ElementName.HR;
+		public static final String HTML = HTML40Namespace.ElementName.HTML;
+		public static final String IMG = HTML40Namespace.ElementName.IMG;
+		public static final String INPUT = HTML40Namespace.ElementName.INPUT;
+		public static final String LI = HTML40Namespace.ElementName.LI;
+		public static final String MENU = HTML40Namespace.ElementName.MENU;
+		public static final String META = HTML40Namespace.ElementName.META;
+		public static final String OL = HTML40Namespace.ElementName.OL;
+		public static final String OPTION = HTML40Namespace.ElementName.OPTION;
+		public static final String P = HTML40Namespace.ElementName.P;
+		public static final String PRE = HTML40Namespace.ElementName.PRE;
+		public static final String SELECT = HTML40Namespace.ElementName.SELECT;
+		public static final String TEXTAREA = HTML40Namespace.ElementName.TEXTAREA;
+		public static final String TITLE = HTML40Namespace.ElementName.TITLE;
+		public static final String UL = HTML40Namespace.ElementName.UL;
+		public static final String SSI_CONFIG = HTML40Namespace.ElementName.SSI_CONFIG;
+		public static final String SSI_ECHO = HTML40Namespace.ElementName.SSI_ECHO;
+		public static final String SSI_EXEC = HTML40Namespace.ElementName.SSI_EXEC;
+		public static final String SSI_FSIZE = HTML40Namespace.ElementName.SSI_FSIZE;
+		public static final String SSI_FLASTMOD = HTML40Namespace.ElementName.SSI_FLASTMOD;
+		public static final String SSI_INCLUDE = HTML40Namespace.ElementName.SSI_INCLUDE;
+		public static final String SSI_PRINTENV = HTML40Namespace.ElementName.SSI_PRINTENV;
+		public static final String SSI_SET = HTML40Namespace.ElementName.SSI_SET;
+	}
+
+	// Character Entities
+	public static interface EntityName {
+	}
+
+	// global attribute names
+	public static final String ATTR_NAME_VERSION = HTML40Namespace.ATTR_NAME_VERSION;
+	public static final String ATTR_NAME_SRC = HTML40Namespace.ATTR_NAME_SRC;
+	public static final String ATTR_NAME_ALT = HTML40Namespace.ATTR_NAME_ALT;
+	public static final String ATTR_NAME_HEIGHT = HTML40Namespace.ATTR_NAME_HEIGHT;
+	public static final String ATTR_NAME_WIDTH = HTML40Namespace.ATTR_NAME_WIDTH;
+	public static final String ATTR_NAME_ALIGN = HTML40Namespace.ATTR_NAME_ALIGN;
+	public static final String ATTR_NAME_BORDER = HTML40Namespace.ATTR_NAME_BORDER;
+	public static final String ATTR_NAME_HSPACE = HTML40Namespace.ATTR_NAME_HSPACE;
+	public static final String ATTR_NAME_VSPACE = HTML40Namespace.ATTR_NAME_VSPACE;
+	public static final String ATTR_NAME_NAME = HTML40Namespace.ATTR_NAME_NAME;
+	public static final String ATTR_NAME_CLEAR = HTML40Namespace.ATTR_NAME_CLEAR;
+	public static final String ATTR_NAME_NOSHADE = HTML40Namespace.ATTR_NAME_NOSHADE;
+	public static final String ATTR_NAME_CHECKED = HTML40Namespace.ATTR_NAME_CHECKED;
+	public static final String ATTR_NAME_MAXLENGTH = HTML40Namespace.ATTR_NAME_MAXLENGTH;
+	public static final String ATTR_NAME_ISTYLE = HTML40Namespace.ATTR_NAME_ISTYLE;
+	public static final String ATTR_NAME_HTTP_EQUIV = HTML40Namespace.ATTR_NAME_HTTP_EQUIV;
+	public static final String ATTR_NAME_CONTENT = HTML40Namespace.ATTR_NAME_CONTENT;
+
+	public static final String ATTR_NAME_HREF = HTML40Namespace.ATTR_NAME_HREF;
+	public static final String ATTR_NAME_MULTIPLE = HTML40Namespace.ATTR_NAME_MULTIPLE;
+	public static final String ATTR_NAME_SELECTED = HTML40Namespace.ATTR_NAME_SELECTED;
+	public static final String ATTR_NAME_ROWS = HTML40Namespace.ATTR_NAME_ROWS;
+	public static final String ATTR_NAME_COLS = HTML40Namespace.ATTR_NAME_COLS;
+	public static final String ATTR_NAME_ACTION = HTML40Namespace.ATTR_NAME_ACTION;
+	public static final String ATTR_NAME_METHOD = HTML40Namespace.ATTR_NAME_METHOD;
+	public static final String ATTR_NAME_ENCTYPE = HTML40Namespace.ATTR_NAME_ENCTYPE;
+	public static final String ATTR_NAME_SIZE = HTML40Namespace.ATTR_NAME_SIZE;
+	public static final String ATTR_NAME_TYPE = HTML40Namespace.ATTR_NAME_TYPE;
+	public static final String ATTR_NAME_VALUE = HTML40Namespace.ATTR_NAME_VALUE;
+
+
+
+	public static final String ATTR_NAME_ERRMSG = HTML40Namespace.ATTR_NAME_ERRMSG;
+	public static final String ATTR_NAME_SIZEFMT = HTML40Namespace.ATTR_NAME_SIZEFMT;
+	public static final String ATTR_NAME_TIMEFMT = HTML40Namespace.ATTR_NAME_TIMEFMT;
+	public static final String ATTR_NAME_VAR = HTML40Namespace.ATTR_NAME_VAR;
+	public static final String ATTR_NAME_CGI = HTML40Namespace.ATTR_NAME_CGI;
+	public static final String ATTR_NAME_CMD = HTML40Namespace.ATTR_NAME_CMD;
+	public static final String ATTR_NAME_FILE = HTML40Namespace.ATTR_NAME_FILE;
+	public static final String ATTR_NAME_VIRTUAL = HTML40Namespace.ATTR_NAME_VIRTUAL;
+
+	// global attribute values; mainly used in enumeration.
+	public static final String ATTR_VALUE_VERSION_TRANSITIONAL = "-//W3C//DTD Compact HTML 1.0 Draft//EN"; //$NON-NLS-1$
+	//   for align (top|middle|bottom|left|right)
+	public static final String ATTR_VALUE_TOP = HTML40Namespace.ATTR_VALUE_TOP;
+	public static final String ATTR_VALUE_MIDDLE = HTML40Namespace.ATTR_VALUE_MIDDLE;
+	public static final String ATTR_VALUE_BOTTOM = HTML40Namespace.ATTR_VALUE_BOTTOM;
+	public static final String ATTR_VALUE_LEFT = HTML40Namespace.ATTR_VALUE_LEFT;
+	public static final String ATTR_VALUE_CENTER = HTML40Namespace.ATTR_VALUE_CENTER;
+	public static final String ATTR_VALUE_RIGHT = HTML40Namespace.ATTR_VALUE_RIGHT;
+	//   for clear (left|all|right|none): left and right are already defined above.
+	public static final String ATTR_VALUE_ALL = HTML40Namespace.ATTR_VALUE_ALL;
+	public static final String ATTR_VALUE_NONE = HTML40Namespace.ATTR_VALUE_NONE;
+	//   for type of INPUT
+	//       (text | password | checkbox | radio | submit | reset |
+	//        file | hidden | image | button)
+	public static final String ATTR_VALUE_TEXT = HTML40Namespace.ATTR_VALUE_TEXT;
+	public static final String ATTR_VALUE_PASSWORD = HTML40Namespace.ATTR_VALUE_PASSWORD;
+	public static final String ATTR_VALUE_CHECKBOX = HTML40Namespace.ATTR_VALUE_CHECKBOX;
+	public static final String ATTR_VALUE_RADIO = HTML40Namespace.ATTR_VALUE_RADIO;
+	public static final String ATTR_VALUE_SUBMIT = HTML40Namespace.ATTR_VALUE_SUBMIT;
+	public static final String ATTR_VALUE_RESET = HTML40Namespace.ATTR_VALUE_RESET;
+	public static final String ATTR_VALUE_HIDDEN = HTML40Namespace.ATTR_VALUE_HIDDEN;
+	//   for span, colspan, rowspan
+	public static final String ATTR_VALUE_1 = HTML40Namespace.ATTR_VALUE_1;
+	//   for frameborder
+	public static final String ATTR_VALUE_0 = HTML40Namespace.ATTR_VALUE_0;
+	//   for method of FORM
+	public static final String ATTR_VALUE_GET = HTML40Namespace.ATTR_VALUE_GET;
+	public static final String ATTR_VALUE_POST = HTML40Namespace.ATTR_VALUE_POST;
+	public static final String ATTR_VALUE_WWW_FORM_URLENCODED = HTML40Namespace.ATTR_VALUE_WWW_FORM_URLENCODED;
+	//   for behaviro of MARQUEE
+	public static final String ATTR_VALUE_SCROLL = HTML40Namespace.ATTR_VALUE_SCROLL;
+	public static final String ATTR_VALUE_SLIDE = HTML40Namespace.ATTR_VALUE_SLIDE;
+	public static final String ATTR_VALUE_ALTERNATE = HTML40Namespace.ATTR_VALUE_ALTERNATE;
+	//   for direction of MARQUEE
+	public static final String ATTR_VALUE_UP = HTML40Namespace.ATTR_VALUE_UP;
+	public static final String ATTR_VALUE_DOWN = HTML40Namespace.ATTR_VALUE_DOWN;
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/CMContentImpl.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/CMContentImpl.java
new file mode 100644
index 0000000..5633cf5
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/CMContentImpl.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+/**
+ * Implementation of CMContent for HTML CM.
+ */
+abstract class CMContentImpl extends CMNodeImpl implements org.eclipse.wst.xml.core.internal.contentmodel.CMContent {
+
+	public static final int UNBOUNDED = -1;
+	/**  -1: it's UNBOUNDED. */
+	private int maxOccur = UNBOUNDED;
+	/**  0: it's OPTIONAL, 1, it's REQUIRED. */
+	private int minOccur = 0;
+
+	/**
+	 * The primary consturctor.
+	 * Use this one for usual cases.<br>
+	 */
+	public CMContentImpl(String name, int min, int max) {
+		super(name);
+		minOccur = min;
+		maxOccur = max;
+	}
+
+	/**
+	 * getMaxOccur method
+	 * @return int
+	 *
+	 * If -1, it's UNBOUNDED.
+	 */
+	public int getMaxOccur() {
+		return maxOccur;
+	}
+
+	/**
+	 * getMinOccur method
+	 * @return int
+	 *
+	 * If 0, it's OPTIONAL.
+	 * If 1, it's REQUIRED.
+	 */
+	public int getMinOccur() {
+		return minOccur;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/CMGroupImpl.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/CMGroupImpl.java
new file mode 100644
index 0000000..2c546f5
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/CMGroupImpl.java
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNodeList;
+
+/**
+ */
+class CMGroupImpl extends CMContentImpl implements CMGroup {
+
+	private int operator = CMGroup.SEQUENCE;
+	private CMNodeListImpl children = null;
+
+	/**
+	 * CMGroupImpl constructor comment.
+	 */
+	public CMGroupImpl(int op, int minOccur, int maxOccur) {
+		super(null, minOccur, maxOccur);
+		switch (op) {
+			case CMGroup.ALL :
+			case CMGroup.CHOICE :
+			case CMGroup.SEQUENCE :
+				operator = op;
+				break;
+			default :
+				// should warn.
+				break;
+		}
+	}
+
+	/**
+	 * @return org.eclipse.wst.xml.core.internal.contentmodel.CMNode
+	 * @param org.eclipse.wst.xml.core.internal.contentmodel.CMNode
+	 */
+	protected CMNode appendChild(CMNode child) {
+		if (child == null)
+			return null;
+		if (children == null)
+			children = new CMNodeListImpl();
+		return children.appendNode(child);
+	}
+
+	/**
+	 * @return org.eclipse.wst.xml.core.internal.contentmodel.CMNodeList
+	 */
+	public CMNodeList getChildNodes() {
+		return children;
+	}
+
+	/**
+	 * getNodeType method
+	 * @return int
+	 *
+	 * Returns one of :
+	 * ELEMENT_DECLARATION, ATTRIBUTE_DECLARATION, GROUP, ENTITY_DECLARATION.
+	 */
+	public int getNodeType() {
+		return CMNode.GROUP;
+	}
+
+	/**
+	 * getOperation method
+	 * @return int
+	 *
+	 * Returns one of :
+	 * ALONE (a), SEQUENCE (a,b), CHOICE (a|b), ALL (a&b).
+	 */
+	public int getOperator() {
+		return operator;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/CMNamedNodeMapImpl.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/CMNamedNodeMapImpl.java
new file mode 100644
index 0000000..d1bae1e
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/CMNamedNodeMapImpl.java
@@ -0,0 +1,112 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import java.util.Iterator;
+import java.util.Locale;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ * An implementation of the CMNamedNodeMap interface. This class is intented
+ * to be used as a container of attribute declarations. If someone wants to
+ * use this class for other purpose, he must pay attention to the fact that
+ * this class is tolerant of the key name case. That is, this class does not
+ * distinguish "name", "NAME", and "Name" as a key name.
+ */
+class CMNamedNodeMapImpl implements org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap {
+
+	private java.util.Hashtable items = null;
+
+	/**
+	 */
+	public CMNamedNodeMapImpl() {
+		super();
+		items = new java.util.Hashtable();
+	}
+
+	/**
+	 * getLength method
+	 * 
+	 * @return int
+	 */
+	public int getLength() {
+		return items.size();
+	}
+
+	/**
+	 * getNamedItem method
+	 * 
+	 * @return CMNode <code>null</code> for unknown keys.
+	 * @param name
+	 *            java.lang.String
+	 */
+	public CMNode getNamedItem(String name) {
+		String cookedName = makeCanonicalForm(name);
+		if (!items.containsKey(cookedName))
+			return null;
+		return (CMNode) items.get(cookedName);
+	}
+
+	/**
+	 * item method
+	 * 
+	 * @return CMNode
+	 * @param index
+	 *            int
+	 */
+	public CMNode item(int index) {
+		Iterator iter = iterator();
+		while (iter.hasNext()) {
+			CMNode node = (CMNode) iter.next();
+			if (--index < 0)
+				return node;
+		}
+		return null;
+	}
+
+	/**
+	 * @return java.util.Iterator
+	 */
+	public Iterator iterator() {
+		return items.values().iterator();
+	}
+
+	/**
+	 * @return java.lang.String
+	 * @param rawForm
+	 *            java.lang.String
+	 */
+	private String makeCanonicalForm(String raw) {
+		// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=100152
+		// we are able to "cheat" here a little and use US Locale
+		// to get a good cononical form, since we are using this only
+		// for HTML and JSP standard tags.
+		// Long term, for similar needs with XML 1.1 (for example)
+		// we should use a class such as com.ibm.icu.text.Normalizer
+		return raw.toUpperCase(Locale.US);
+	}
+
+	/**
+	 * @param key
+	 *            java.lang.String
+	 * @param item
+	 *            java.lang.String
+	 */
+	void putNamedItem(String name, CMNode item) {
+		String cookedName = makeCanonicalForm(name);
+		if (items.containsKey(cookedName))
+			return; // already registered.
+		items.put(cookedName, item);
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/CMNodeImpl.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/CMNodeImpl.java
new file mode 100644
index 0000000..62f7a01
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/CMNodeImpl.java
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+import org.eclipse.wst.html.core.internal.provisional.HTMLCMProperties;
+
+
+
+/**
+ */
+abstract class CMNodeImpl implements org.eclipse.wst.xml.core.internal.contentmodel.CMNode {
+
+	private java.lang.String name = null;
+
+	/**
+	 * CMNodeImpl constructor comment.
+	 */
+	public CMNodeImpl(String nm) {
+		super();
+		name = nm;
+	}
+
+	/**
+	 * getNodeName method
+	 * @return java.lang.String
+	 */
+	public String getNodeName() {
+		return name;
+	}
+
+	/**
+	 * getProperty method
+	 * @return java.lang.Object
+	 *
+	 * Returns the object property desciped by the propertyName
+	 *
+	 */
+	public Object getProperty(String propertyName) {
+		if (propertyName.equals(HTMLCMProperties.IS_XHTML))
+			return new Boolean(false);
+		return null;
+	}
+
+	/**
+	 * supports method
+	 * @return boolean
+	 *
+	 * Returns true if the CMNode supports a specified property
+	 *
+	 */
+	public boolean supports(String propertyName) {
+		if (propertyName.equals(HTMLCMProperties.IS_XHTML))
+			return true;
+		return false;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/CMNodeListImpl.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/CMNodeListImpl.java
new file mode 100644
index 0000000..c1b1cda
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/CMNodeListImpl.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ * Analog of dom.NodeList for CM.
+ */
+class CMNodeListImpl implements org.eclipse.wst.xml.core.internal.contentmodel.CMNodeList {
+
+	private java.util.Vector nodes = null;
+
+	/**
+	 * CMNodeListImpl constructor comment.
+	 */
+	public CMNodeListImpl() {
+		super();
+		nodes = new java.util.Vector();
+	}
+
+	/**
+	 * @return org.eclipse.wst.xml.core.internal.contentmodel.CMNode
+	 * @param node org.eclipse.wst.xml.core.internal.contentmodel.CMNode
+	 */
+	protected CMNode appendNode(CMNode node) {
+		nodes.addElement(node);
+		return node;
+	}
+
+	/**
+	 * getLength method
+	 * @return int
+	 */
+	public int getLength() {
+		return nodes.size();
+	}
+
+	/**
+	 * item method
+	 * @return CMNode
+	 * @param index int
+	 */
+	public CMNode item(int index) {
+		if (index < 0 || index >= nodes.size())
+			return null;
+		return (CMNode) nodes.elementAt(index);
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/ComplexTypeDefinition.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/ComplexTypeDefinition.java
new file mode 100644
index 0000000..fd47c7e
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/ComplexTypeDefinition.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import org.eclipse.wst.html.core.internal.contentmodel.HTMLElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+
+/**
+ * This class is intended to represent a complex type definition
+ * in XML Schema.<br>
+ */
+abstract class ComplexTypeDefinition {
+
+	protected CMGroupImpl content = null;
+	protected ElementCollection collection = null;
+	protected String primaryCandidateName = null;
+
+	/**
+	 * ComplexTypeDefinition constructor comment.
+	 */
+	public ComplexTypeDefinition(ElementCollection elementCollection) {
+		super();
+		collection = elementCollection;
+		createContent();
+	}
+
+	/**
+	 * Create an actual content model.
+	 * This method should be called once and only once in the constructor.<br>
+	 */
+	protected abstract void createContent();
+
+	/**
+	 * @return org.eclipse.wst.xml.core.internal.contentmodel.CMGroup
+	 */
+	public CMGroup getContent() {
+		return content;
+	}
+
+	/**
+	 * @return int; Should be one of ANY, EMPTY, ELEMENT, MIXED, PCDATA, CDATA,
+	 * those are defined in CMElementDeclaration.
+	 */
+	/* NOTE: Do we need LOGICAL type?
+	 * -- 3/7/2001
+	 */
+	public abstract int getContentType();
+
+	/**
+	 * Get content hint.
+	 */
+	public HTMLElementDeclaration getPrimaryCandidate() {
+		if (primaryCandidateName == null)
+			return null;
+		return (HTMLElementDeclaration) collection.getNamedItem(primaryCandidateName);
+	}
+
+	/**
+	 * Name of complex type definition.
+	 * Each singleton must know its own name.
+	 * All names should be defined in
+	 * {@link <code>ComplexTypeDefinitionFactory</code>} as constants.<br>
+	 * @return java.lang.String
+	 */
+	public abstract String getTypeName();
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/ComplexTypeDefinitionFactory.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/ComplexTypeDefinitionFactory.java
new file mode 100644
index 0000000..2a682f9
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/ComplexTypeDefinitionFactory.java
@@ -0,0 +1,144 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+/**
+ * Factory of ComplexTypeDefinition.
+ */
+final class ComplexTypeDefinitionFactory {
+
+	private static ComplexTypeDefinitionFactory instance = null;
+	private java.util.Hashtable definitions = null;
+	// constants for complex type name
+	/** for ADDRESS. */
+	public final static String CTYPE_ADDRESS = "CTYPE_ADDRESS";//$NON-NLS-1$
+	/** CDATA content. No ComplexTypeDefinition instance shuld be created. */
+	public final static String CTYPE_CDATA = "CTYPE_CDATA";//$NON-NLS-1$
+	/** col group content. COL* */
+	public final static String CTYPE_COLUMN_GROUP = "CTYPE_COLUMN_GROUP";//$NON-NLS-1$
+	/** for DL. */
+	public final static String CTYPE_DEFINITION_LIST = "CTYPE_DEFINITION_LIST";//$NON-NLS-1$
+	/** for EMBED. */
+	public final static String CTYPE_EMBED = "CTYPE_EMBED";//$NON-NLS-1$
+	/** empty content. No ComplexTypeDefinition instance should be created. */
+	public final static String CTYPE_EMPTY = "CTYPE_EMPTY";//$NON-NLS-1$
+	/** for FIELDSET. */
+	public final static String CTYPE_FIELDSET = "CTYPE_FIELDSET";//$NON-NLS-1$
+	/** for FRAMESET. */
+	public final static String CTYPE_FRAMESET = "CTYPE_FRAMESET";//$NON-NLS-1$
+	/** flow content. (%flow;)* */
+	public final static String CTYPE_FLOW_CONTAINER = "CTYPE_FLOW_CONTAINER";//$NON-NLS-1$
+	/** html content. HEAD, (FRAMESET|BODY) */
+	public final static String CTYPE_HTML = "CTYPE_HTML";//$NON-NLS-1$
+	/** head content. TITLE & ISINDEX? & BASE? */
+	public final static String CTYPE_HEAD = "CTYPE_HEAD";//$NON-NLS-1$
+	/** inline content. (%inline;)* */
+	public final static String CTYPE_INLINE_CONTAINER = "CTYPE_INLINE_CONTAINER";//$NON-NLS-1$
+	/** list item container. (LI)+ */
+	public final static String CTYPE_LI_CONTAINER = "CTYPE_LI_CONTAINER";//$NON-NLS-1$
+	/** for MAP. */
+	public final static String CTYPE_MAP = "CTYPE_MAP";//$NON-NLS-1$
+	/** noframes content. */
+	public final static String CTYPE_NOFRAMES_CONTENT = "CTYPE_NOFRAMES_CONTENT";//$NON-NLS-1$
+	/** for OPTGROUP. */
+	public final static String CTYPE_OPTION_CONTAINER = "CTYPE_OPTION_CONTAINER";//$NON-NLS-1$
+	/** param container. For OBJECT/APPLET. */
+	public final static String CTYPE_PARAM_CONTAINER = "CTYPE_PARAM_CONTAINER";//$NON-NLS-1$
+	/** PCDATA content. No ComplexTypeDefinition instance shuld be created. */
+	public final static String CTYPE_PCDATA = "CTYPE_PCDATA";//$NON-NLS-1$
+	/** for SELECT. */
+	public final static String CTYPE_SELECT = "CTYPE_SELECT";//$NON-NLS-1$
+	/** table content. CAPTION?, (COL*|COLGROUP*), THEAD?, TFOOT?, TBODY+ */
+	public final static String CTYPE_TABLE = "CTYPE_TABLE";//$NON-NLS-1$
+	/** table cell contaier. (TH|TD)+ */
+	public final static String CTYPE_TCELL_CONTAINER = "CTYPE_TCELL_CONTAINER";//$NON-NLS-1$
+	/** table record container. (TR)+ */
+	public final static String CTYPE_TR_CONTAINER = "CTYPE_TR_CONTAINER";//$NON-NLS-1$
+
+	/**
+	 * ComplexTypeDefinitionFactory constructor comment.
+	 */
+	private ComplexTypeDefinitionFactory() {
+		super();
+		definitions = new java.util.Hashtable();
+	}
+
+	/**
+	 * Factory method for ComplexTypeDefinition.
+	 * Each instance created in this method must be registered into
+	 * the map with its name.
+	 * @param definitionName java.lang.String
+	 * @param elementCollection ElementCollection
+	 */
+	public ComplexTypeDefinition createTypeDefinition(String definitionName, ElementCollection elementCollection) {
+		if (definitions.containsKey(definitionName)) {
+			return (ComplexTypeDefinition) definitions.get(definitionName);
+		}
+
+		ComplexTypeDefinition def = null;
+		if (definitionName == CTYPE_ADDRESS) {
+			def = new CtdAddress(elementCollection);
+
+		}
+		else if (definitionName == CTYPE_DEFINITION_LIST) {
+			def = new CtdDl(elementCollection);
+
+		}
+		else if (definitionName == CTYPE_FLOW_CONTAINER) {
+			def = new CtdFlowContainer(elementCollection);
+
+		}
+		else if (definitionName == CTYPE_HEAD) {
+			def = new CtdHead(elementCollection);
+
+		}
+		else if (definitionName == CTYPE_HTML) {
+			def = new CtdHtml(elementCollection);
+
+		}
+		else if (definitionName == CTYPE_INLINE_CONTAINER) {
+			def = new CtdInlineContainer(elementCollection);
+
+		}
+		else if (definitionName == CTYPE_LI_CONTAINER) {
+			def = new CtdLiContainer(elementCollection);
+
+
+		}
+		else if (definitionName == CTYPE_OPTION_CONTAINER) {
+			def = new CtdOptionContainer(elementCollection);
+
+		}
+		else if (definitionName == CTYPE_SELECT) {
+			def = new CtdSelect(elementCollection);
+
+		}
+		else {
+			def = null;
+		}
+		if (def == null)
+			return null; // fail to create.
+		definitions.put(definitionName, def);
+		return def;
+	}
+
+	/**
+	 * For singleton.<br>
+	 */
+	public synchronized static ComplexTypeDefinitionFactory getInstance() {
+		if (instance != null)
+			return instance;
+		instance = new ComplexTypeDefinitionFactory();
+		return instance;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/CtdAddress.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/CtdAddress.java
new file mode 100644
index 0000000..4ad13c0
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/CtdAddress.java
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ * for ADDRESS.
+ */
+final class CtdAddress extends ComplexTypeDefinition {
+
+	/**
+	 * @param elementCollection ElementCollection
+	 */
+	public CtdAddress(ElementCollection elementCollection) {
+		super(elementCollection);
+	}
+
+	/**
+	 * ((%inline) | P)*.
+	 */
+	protected void createContent() {
+		if (content != null)
+			return; // already created.
+		if (collection == null)
+			return;
+
+		// ( | )*
+		content = new CMGroupImpl(CMGroup.CHOICE, 0, CMContentImpl.UNBOUNDED);
+		// (%inline)
+		CMGroupImpl inlines = new CMGroupImpl(CMGroup.CHOICE, 1, 1);
+		if (inlines == null)
+			return;
+		collection.getInline(inlines);
+		content.appendChild(inlines);
+		// P
+		CMNode p = collection.getNamedItem(CHTMLNamespace.ElementName.P);
+		if (p != null)
+			content.appendChild(p);
+	}
+
+	/**
+	 * ((%inline) | P)*.
+	 * Because %inline; contains #PCDATA, the type is MIXED.
+	 * @return int; Should be one of ANY, EMPTY, ELEMENT, MIXED, PCDATA, CDATA,
+	 * those are defined in CMElementDeclaration.
+	 */
+	public int getContentType() {
+		return CMElementDeclaration.MIXED;
+	}
+
+	/**
+	 * @return java.lang.String
+	 */
+	public String getTypeName() {
+		return ComplexTypeDefinitionFactory.CTYPE_ADDRESS;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/CtdDl.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/CtdDl.java
new file mode 100644
index 0000000..c0abf8a
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/CtdDl.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ * for DL.
+ */
+final class CtdDl extends ComplexTypeDefinition {
+
+	/**
+	 * @param elementCollection ElementCollection
+	 */
+	public CtdDl(ElementCollection elementCollection) {
+		super(elementCollection);
+		primaryCandidateName = CHTMLNamespace.ElementName.DT;
+	}
+
+	/**
+	 * (DT | DD)+
+	 */
+	protected void createContent() {
+		if (content != null)
+			return; // already created.
+		if (collection == null)
+			return;
+
+		// ( | )+
+		content = new CMGroupImpl(CMGroup.CHOICE, 1, CMContentImpl.UNBOUNDED);
+		// DT
+		CMNode dec = collection.getNamedItem(CHTMLNamespace.ElementName.DT);
+		if (dec != null)
+			content.appendChild(dec);
+		// DD
+		dec = collection.getNamedItem(CHTMLNamespace.ElementName.DD);
+		if (dec != null)
+			content.appendChild(dec);
+	}
+
+	/**
+	 * (DT | DD)+.
+	 * @return int; Should be one of ANY, EMPTY, ELEMENT, MIXED, PCDATA, CDATA,
+	 * those are defined in CMElementDeclaration.
+	 */
+	public int getContentType() {
+		return CMElementDeclaration.ELEMENT;
+	}
+
+	/**
+	 * @return java.lang.String
+	 */
+	public String getTypeName() {
+		return ComplexTypeDefinitionFactory.CTYPE_DEFINITION_LIST;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/CtdFlowContainer.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/CtdFlowContainer.java
new file mode 100644
index 0000000..a198d74
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/CtdFlowContainer.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+
+/**
+ * Complex type definition for containers of <code>%flow;</code>.
+ */
+final class CtdFlowContainer extends ComplexTypeDefinition {
+
+	/**
+	 */
+	public CtdFlowContainer(ElementCollection elementCollection) {
+		super(elementCollection);
+	}
+
+	/**
+	 * (%flow;)*
+	 */
+	protected void createContent() {
+		if (content != null)
+			return; // already created.
+		if (collection == null)
+			return;
+
+		content = new CMGroupImpl(CMGroup.CHOICE, 0, CMContentImpl.UNBOUNDED);
+		collection.getFlow(content);
+	}
+
+	public int getContentType() {
+		return CMElementDeclaration.MIXED;
+	}
+
+	public String getTypeName() {
+		return ComplexTypeDefinitionFactory.CTYPE_FLOW_CONTAINER;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/CtdHead.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/CtdHead.java
new file mode 100644
index 0000000..9af78c6
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/CtdHead.java
@@ -0,0 +1,174 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import java.util.Arrays;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ * Complex type definition for the head content.
+ * Content Model: (TITLE & ISINDEX? & BASE?)
+ */
+final class CtdHead extends ComplexTypeDefinition {
+
+	/**
+	 */
+	public CtdHead(ElementCollection elementCollection) {
+		super(elementCollection);
+		primaryCandidateName = CHTMLNamespace.ElementName.TITLE;
+	}
+
+	/**
+	 * for HEAD.
+	 * To avoid using inclusion, the content model comes from the XHTML 1.0.
+	 *
+	 * (%head.misc;, ((title, %head.misc;, (base, %head.misc;)?) | (base, %head.misc;, (title, %head.misc;))))
+	 * And %head.misc; is:
+	 * (script|style|meta|link|object|isindex)*
+	 *
+	 * 0: (%head.misc, A)
+	 * A: (B | C)
+	 * B: (title, %head.misc;, D)
+	 * C: (base, %head.misc;, E)
+	 * D: (base, %head.misc;)?
+	 * E: (title, %head.misc;)
+	 */
+	protected void createContent() {
+		if (content != null)
+			return; // already created.
+		if (collection == null)
+			return;
+
+		// At 1st, create %head.misc; content.
+		// %head.misc;
+		//   ( | )*
+		CMGroupImpl misc = new CMGroupImpl(CMGroup.CHOICE, 0, CMContentImpl.UNBOUNDED);
+		if (misc == null)
+			return;
+		String[] names = {CHTMLNamespace.ElementName.META,};
+		collection.getDeclarations(misc, Arrays.asList(names).iterator());
+		// 2nd, get a title
+		CMNode title = collection.getNamedItem(CHTMLNamespace.ElementName.TITLE);
+		// 3rd, get a base
+		CMNode base = collection.getNamedItem(CHTMLNamespace.ElementName.BASE);
+		if (title == null || base == null)
+			return;
+
+		// Top level content is a sequence of %head.misc; and A.
+		// 0: (%head.misc;, A)
+		//   create a sequence
+		content = new CMGroupImpl(CMGroup.SEQUENCE, 1, 1);
+		if (content == null)
+			return;
+		//   append %head.misc;
+		content.appendChild(misc);
+		//   create A and append it to the top level.
+		{
+			// A is a choice of B and C.
+			// A: (B | C)
+			//   create a choice
+			CMGroupImpl gA = new CMGroupImpl(CMGroup.CHOICE, 1, 1);
+			if (gA == null)
+				return;
+			//   append A to the top level.
+			content.appendChild(gA);
+
+			// create B and append it to A
+			{
+				// B is a sequence of title, %head.misc;, and D.
+				// B: (title, %head.misc;, D)
+				//   create a sequence
+				CMGroupImpl gB = new CMGroupImpl(CMGroup.SEQUENCE, 1, 1);
+				if (gB == null)
+					return;
+				//   append B to A.
+				gA.appendChild(gB);
+
+				//   append title to B
+				gB.appendChild(title);
+				//   append %head.misc; to B
+				gB.appendChild(misc);
+				//   create D and append it to B.
+				{
+					// D is a sequence of base, %head.misc;.
+					// D: (base, %head.misc;)?
+					//   create a sequence
+					CMGroupImpl gD = new CMGroupImpl(CMGroup.SEQUENCE, 0, 1);
+					if (gD == null)
+						return;
+					//   append D to B.
+					gB.appendChild(gD);
+
+					//   append base to D
+					gD.appendChild(base);
+					//   append %head.misc; to D.
+					gD.appendChild(misc);
+				}
+			}
+			// create C and append it to A
+			{
+				// C is a sequence of base, %head.misc;, and E
+				// C: (base, %head.misc;, E)
+				//   create a sequence
+				CMGroupImpl gC = new CMGroupImpl(CMGroup.SEQUENCE, 1, 1);
+				if (gC == null)
+					return;
+				//   append C to A.
+				gA.appendChild(gC);
+
+				//   append base to C
+				gC.appendChild(base);
+				//   append %head.misc; to C
+				gC.appendChild(misc);
+
+				//   create E and append it to C.
+				{
+					// E is a sequence of title and %head.misc;.
+					// E: (title, %head.misc;)
+					//   create a sequence
+					CMGroupImpl gE = new CMGroupImpl(CMGroup.SEQUENCE, 1, 1);
+					if (gE == null)
+						return;
+					//   append E to C.
+					gC.appendChild(gE);
+
+					//   append title to E
+					gE.appendChild(title);
+					//   append %head.misc; to E.
+					gE.appendChild(misc);
+				}
+			}
+		}
+	}
+
+	/**
+	 * Element content.<br>
+	 */
+	public int getContentType() {
+		return CMElementDeclaration.ELEMENT;
+	}
+
+	/**
+	 * Name of complex type definition.
+	 * Each singleton must know its own name.
+	 * All names should be defined in
+	 * {@link <code>ComplexTypeDefinitionFactory</code>} as constants.<br>
+	 * @return java.lang.String
+	 */
+	public String getTypeName() {
+		return ComplexTypeDefinitionFactory.CTYPE_HEAD;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/CtdHtml.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/CtdHtml.java
new file mode 100644
index 0000000..cf4fe4a
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/CtdHtml.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import java.util.Arrays;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ * Complex type definition for <code>HTML</code>.<br>
+ * Content Model:
+ * HEAD, (FRAMESET|BODY)<br>
+ */
+final class CtdHtml extends ComplexTypeDefinition {
+
+	/**
+	 */
+	public CtdHtml(ElementCollection elementCollection) {
+		super(elementCollection);
+		primaryCandidateName = CHTMLNamespace.ElementName.HEAD;
+	}
+
+	/**
+	 * (%html.content;).
+	 * %html.content; is HEAD, (FRAMESET | BODY).
+	 */
+	protected void createContent() {
+		if (content != null)
+			return; // already created.
+		if (collection == null)
+			return;
+
+		// ( )
+		content = new CMGroupImpl(CMGroup.SEQUENCE, 1, 1);
+		if (content == null)
+			return;
+
+		// HEAD
+		CMNode edec = collection.getNamedItem(CHTMLNamespace.ElementName.HEAD);
+		if (edec != null)
+			content.appendChild(edec);
+
+		// ( | )
+		CMGroupImpl group = new CMGroupImpl(CMGroup.CHOICE, 1, 1);
+		content.appendChild(group);
+
+		// FRAMESET, BODY
+		String[] names = {CHTMLNamespace.ElementName.BODY};
+		collection.getDeclarations(group, Arrays.asList(names).iterator());
+	}
+
+	/**
+	 * Element content.
+	 */
+	public int getContentType() {
+		return CMElementDeclaration.ELEMENT;
+	}
+
+	public String getTypeName() {
+		return ComplexTypeDefinitionFactory.CTYPE_HTML;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/CtdInlineContainer.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/CtdInlineContainer.java
new file mode 100644
index 0000000..ed234aa
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/CtdInlineContainer.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+
+/**
+ * Complex type definition for (%inline;)*.
+ */
+final class CtdInlineContainer extends ComplexTypeDefinition {
+
+	/**
+	 * @param elementCollection ElementCollection
+	 */
+	public CtdInlineContainer(ElementCollection elementCollection) {
+		super(elementCollection);
+	}
+
+	/**
+	 * (%inline)*.
+	 */
+	protected void createContent() {
+		if (content != null)
+			return; // already created.
+		if (collection == null)
+			return;
+
+		content = new CMGroupImpl(CMGroup.CHOICE, 0, CMContentImpl.UNBOUNDED);
+		collection.getInline(content);
+	}
+
+	public int getContentType() {
+		return CMElementDeclaration.MIXED;
+	}
+
+	public String getTypeName() {
+		return ComplexTypeDefinitionFactory.CTYPE_INLINE_CONTAINER;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/CtdLiContainer.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/CtdLiContainer.java
new file mode 100644
index 0000000..b28956e
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/CtdLiContainer.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ * List item container.
+ * (LI)+
+ */
+final class CtdLiContainer extends ComplexTypeDefinition {
+
+	/**
+	 * @param elemenCollection ElementCollection
+	 */
+	public CtdLiContainer(ElementCollection elementCollection) {
+		super(elementCollection);
+		primaryCandidateName = CHTMLNamespace.ElementName.LI;
+	}
+
+	/**
+	 * (LI)+.
+	 */
+	protected void createContent() {
+		if (content != null)
+			return; // already created.
+		if (collection == null)
+			return;
+
+		// (LI)+
+		content = new CMGroupImpl(CMGroup.SEQUENCE, 1, CMContentImpl.UNBOUNDED);
+		CMNode li = collection.getNamedItem(CHTMLNamespace.ElementName.LI);
+		if (li != null)
+			content.appendChild(li);
+	}
+
+	/**
+	 * ELEMENT content.<br>
+	 * @return int; Should be one of ANY, EMPTY, ELEMENT, MIXED, PCDATA, CDATA,
+	 * those are defined in CMElementDeclaration.
+	 */
+	public int getContentType() {
+		return CMElementDeclaration.ELEMENT;
+	}
+
+	/**
+	 * Name of complex type definition.
+	 * Each singleton must know its own name.
+	 * All names should be defined in
+	 * {@link <code>ComplexTypeDefinitionFactory</code>} as constants.<br>
+	 * @return java.lang.String
+	 */
+	public String getTypeName() {
+		return ComplexTypeDefinitionFactory.CTYPE_LI_CONTAINER;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/CtdOptionContainer.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/CtdOptionContainer.java
new file mode 100644
index 0000000..c2ec6c5
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/CtdOptionContainer.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ * OPTION container.
+ * (OPTION)+
+ */
+final class CtdOptionContainer extends ComplexTypeDefinition {
+
+	/**
+	 * @param elementCollection ElementCollection
+	 */
+	public CtdOptionContainer(ElementCollection elementCollection) {
+		super(elementCollection);
+		primaryCandidateName = CHTMLNamespace.ElementName.OPTION;
+	}
+
+	/**
+	 * (OPTION)+.
+	 */
+	protected void createContent() {
+		if (content != null)
+			return; // already created.
+		if (collection == null)
+			return;
+
+		// ( )+
+		content = new CMGroupImpl(CMGroup.SEQUENCE, 1, CMContentImpl.UNBOUNDED);
+		// OPTION
+		CMNode dec = collection.getNamedItem(CHTMLNamespace.ElementName.OPTION);
+		if (dec != null)
+			content.appendChild(dec);
+	}
+
+	/**
+	 * (OPTION)+
+	 * @return int; Should be one of ANY, EMPTY, ELEMENT, MIXED, PCDATA, CDATA,
+	 * those are defined in CMElementDeclaration.
+	 */
+	public int getContentType() {
+		return CMElementDeclaration.ELEMENT;
+	}
+
+	/**
+	 * Name of complex type definition.
+	 * Each singleton must know its own name.
+	 * All names should be defined in
+	 * {@link <code>ComplexTypeDefinitionFactory</code>} as constants.<br>
+	 * @return java.lang.String
+	 */
+	public String getTypeName() {
+		return ComplexTypeDefinitionFactory.CTYPE_OPTION_CONTAINER;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/CtdSelect.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/CtdSelect.java
new file mode 100644
index 0000000..7f0c96c
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/CtdSelect.java
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ * for SELECT.
+ */
+final class CtdSelect extends ComplexTypeDefinition {
+
+	/**
+	 * @param elementCollection ElementCollection
+	 */
+	public CtdSelect(ElementCollection elementCollection) {
+		super(elementCollection);
+		primaryCandidateName = CHTMLNamespace.ElementName.OPTION;
+	}
+
+	/**
+	 * (OPTGROUP | OPTION)+.
+	 */
+	protected void createContent() {
+		if (content != null)
+			return; // already created.
+		if (collection == null)
+			return;
+
+		// ( | )+
+		content = new CMGroupImpl(CMGroup.CHOICE, 1, CMContentImpl.UNBOUNDED);
+		// OPTION
+		CMNode dec = collection.getNamedItem(CHTMLNamespace.ElementName.OPTION);
+		if (dec != null)
+			content.appendChild(dec);
+	}
+
+	/**
+	 * (OPTGROUP | OPTION)+.
+	 * @return int; Should be one of ANY, EMPTY, ELEMENT, MIXED, PCDATA, CDATA,
+	 * those are defined in CMElementDeclaration.
+	 */
+	public int getContentType() {
+		return CMElementDeclaration.ELEMENT;
+	}
+
+	/**
+	 * @return java.lang.String
+	 */
+	public String getTypeName() {
+		return ComplexTypeDefinitionFactory.CTYPE_SELECT;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/DeclCollection.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/DeclCollection.java
new file mode 100644
index 0000000..af90b74
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/DeclCollection.java
@@ -0,0 +1,251 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Locale;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ */
+abstract class DeclCollection implements CMNamedNodeMap {
+
+
+	protected class DualMap {
+		public DualMap() {
+			super();
+		}
+
+		public DualMap(Object[] objects) {
+			super();
+			initialize(objects);
+		}
+
+		public int size() {
+			return table.length;
+		}
+
+		public Object getValue(int key) {
+			if (!isValidIndex(key))
+				return null;
+			return table[key];
+		}
+
+		public int getKey(Object value) {
+			Integer keyObj = (Integer) map.get(value);
+			if (keyObj == null)
+				return ID_UNKNOWN;
+			return keyObj.intValue();
+		}
+
+		protected void initialize(Object[] objects) {
+			if (objects == null)
+				return;
+			table = objects;
+			map = new HashMap();
+			for (int key = 0; key < objects.length; key++) {
+				Object value = table[key];
+				map.put(value, new Integer(key));
+			}
+		}
+
+		private Object[] table = null;
+		private HashMap map = null;
+
+		private boolean isValidIndex(int index) {
+			return index >= 0 && index < table.length;
+		}
+	}
+
+	protected class TolerantStringDualMap extends DualMap {
+		public TolerantStringDualMap(String[] names) {
+			super();
+			Object[] objects = new Object[names.length];
+			for (int i = 0; i < names.length; i++) {
+				objects[i] = makeCanonicalForm(names[i]);
+			}
+			initialize(objects);
+		}
+
+		public int getKey(Object value) {
+			try {
+				String name = (String) value;
+				return super.getKey(makeCanonicalForm(name));
+			}
+			catch (ClassCastException e) {
+				return ID_UNKNOWN;
+			}
+		}
+
+		private String makeCanonicalForm(String raw) {
+			// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=100152
+			// we are able to "cheat" here a little and use US Locale
+			// to get a good cononical form, since we are using this only
+			// for HTML and JSP standard tags.
+			// Long term, for similar needs with XML 1.1 (for example)
+			// we should use a class such as com.ibm.icu.text.Normalizer
+			return raw.toUpperCase(Locale.US);
+		}
+	}
+
+	private class DeclIterator implements Iterator {
+		public DeclIterator() {
+			maxid = fDecls.length - 1;
+		}
+
+		public boolean hasNext() {
+			return id < maxid;
+		}
+
+		public Object next() {
+			if (!hasNext())
+				return null;
+			return item(++id);
+		}
+
+		public void remove() { /* nothing should be done. */
+		}
+
+		private int id = -1;
+		private int maxid = -1;
+	}
+
+	CMNode[] fDecls = null;
+	protected final static boolean STRICT_CASE = false;
+	protected final static boolean TOLERANT_CASE = true;
+	protected final static int ID_UNKNOWN = -1;
+	private DualMap fMap = null;
+
+	/**
+	 */
+	public DeclCollection(String[] names, boolean tolerant) {
+		super();
+		fDecls = new CMNode[names.length];
+		if (tolerant) {
+			fMap = new TolerantStringDualMap(names);
+		}
+		else {
+			fMap = new DualMap(names);
+		}
+	}
+
+	/**
+	 * @return org.eclipse.wst.xml.core.internal.contentmodel.CMNode
+	 * @param id
+	 *            int
+	 */
+	protected abstract CMNode create(String name);
+
+	/**
+	 */
+	public CMNamedNodeMap getDeclarations(String[] names) {
+		CMNamedNodeMapImpl map = new CMNamedNodeMapImpl();
+		for (int i = 0; i < names.length; i++) {
+			String name = names[i];
+			CMNode node = getNamedItem(name);
+			if (node == null)
+				continue;
+			map.putNamedItem(name, node);
+		}
+		return map;
+	}
+
+	public void getDeclarations(CMGroupImpl group, Iterator names) {
+		while (names.hasNext()) {
+			String entityName = (String) names.next();
+			CMNode dec = getNamedItem(entityName);
+			if (dec != null)
+				group.appendChild(dec);
+		}
+	}
+
+	/**
+	 * Map name to id.
+	 * 
+	 * @return int
+	 * @param name
+	 *            java.lang.String
+	 */
+	protected int getID(String name) {
+		return fMap.getKey(name);
+	}
+
+	/**
+	 * getLength method
+	 * 
+	 * @return int
+	 */
+	public int getLength() {
+		return fDecls.length;
+	}
+
+	/**
+	 * @return java.lang.String
+	 * @param id
+	 *            int
+	 */
+	protected String getName(int id) {
+		return (String) fMap.getValue(id);
+	}
+
+	/**
+	 * getNamedItem method
+	 * 
+	 * @return CMNode
+	 * @param name
+	 *            java.lang.String
+	 */
+	public CMNode getNamedItem(String name) {
+		int id = getID(name);
+		if (!isValidID(id))
+			return null;
+		return item(id);
+	}
+
+	/**
+	 * @return boolean
+	 * @param id
+	 *            int
+	 */
+	private boolean isValidID(int id) {
+		return id >= 0 && id < fDecls.length;
+	}
+
+	/**
+	 * item method
+	 * 
+	 * @return CMNode
+	 * @param index
+	 *            int
+	 */
+	public CMNode item(int index) {
+		if (!isValidID(index))
+			return null;
+		CMNode decl = fDecls[index];
+		if (decl != null)
+			return decl; // already exist.
+
+		decl = create(getName(index));
+		fDecls[index] = decl;
+		return decl;
+	}
+
+	/**
+	 */
+	public Iterator iterator() {
+		return new DeclIterator();
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/ElementCollection.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/ElementCollection.java
new file mode 100644
index 0000000..8a80135
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/ElementCollection.java
@@ -0,0 +1,492 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import java.lang.reflect.Field;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Vector;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ * Factory for element declarations.
+ */
+final class ElementCollection extends DeclCollection implements org.eclipse.wst.html.core.internal.provisional.HTML40Namespace.ElementName {
+
+
+	// Element IDs
+	private static class Ids {
+		public static final int ID_A = 0;
+		public static final int ID_ADDRESS = 1;
+		public static final int ID_BASE = 2;
+		public static final int ID_BLOCKQUOTE = 3;
+		public static final int ID_BODY = 4;
+		public static final int ID_BR = 5;
+		public static final int ID_CENTER = 6;
+		public static final int ID_DD = 7;
+		public static final int ID_DIR = 8;
+		public static final int ID_DIV = 9;
+		public static final int ID_DL = 10;
+		public static final int ID_DT = 11;
+		public static final int ID_FORM = 12;
+		public static final int ID_H1 = 13;
+		public static final int ID_H2 = 14;
+		public static final int ID_H3 = 15;
+		public static final int ID_H4 = 16;
+		public static final int ID_H5 = 17;
+		public static final int ID_H6 = 18;
+		public static final int ID_HEAD = 19;
+		public static final int ID_HR = 20;
+		public static final int ID_HTML = 21;
+		public static final int ID_IMG = 22;
+		public static final int ID_INPUT = 23;
+		public static final int ID_LI = 24;
+		public static final int ID_MENU = 25;
+		public static final int ID_META = 26;
+		public static final int ID_OL = 27;
+		public static final int ID_OPTION = 28;
+		public static final int ID_P = 29;
+		public static final int ID_PRE = 30;
+		public static final int ID_SELECT = 31;
+		public static final int ID_TEXTAREA = 32;
+		public static final int ID_TITLE = 33;
+		public static final int ID_UL = 34;
+		public static final int ID_SSI_CONFIG = 35;
+		public static final int ID_SSI_ECHO = 36;
+		public static final int ID_SSI_EXEC = 37;
+		public static final int ID_SSI_FSIZE = 38;
+		public static final int ID_SSI_FLASTMOD = 39;
+		public static final int ID_SSI_INCLUDE = 40;
+		public static final int ID_SSI_PRINTENV = 41;
+		public static final int ID_SSI_SET = 42;
+
+		public static int getNumOfIds() {
+			if (numofids != -1)
+				return numofids;
+
+			// NOTE: If the reflection is too slow, this method should
+			// just return the literal value, like 105.
+			// -- 5/25/2001
+			Class clazz = Ids.class;
+			Field[] fields = clazz.getFields();
+			numofids = 0;
+			for (int i = 0; i < fields.length; i++) {
+				String name = fields[i].getName();
+				if (name.startsWith("ID_"))//$NON-NLS-1$
+					numofids++;
+			}
+			return numofids;
+		}
+
+		// chache the result of the reflection.
+		private static int numofids = -1;
+	}
+
+	/** %formctl;. INPUT | SELECT | TEXTAREA */
+	private static final String[] FORMCTL = {INPUT, SELECT, TEXTAREA};
+	/** %phrase;.
+	 * DFN
+	 */
+	private static final String[] PHRASE = {DFN};
+	/** %special;.
+	 * A | IMG | BR
+	 */
+	private static final String[] SPECIAL = {A, IMG, BR};
+	/** %heading;. H[1-6] */
+	private static final String[] HEADING = {H1, H2, H3, H4, H5, H6};
+	/** %list;. UL | OL | DIR | MENU */
+	private static final String[] LIST = {UL, OL, DIR, MENU};
+	/** %preformatted;. PRE */
+	private static final String[] PREFORMATTED = {PRE};
+	private AttributeCollection attributeCollection = null;
+	private static String[] names = null;
+
+	static {
+		names = new String[Ids.getNumOfIds()];
+		names[Ids.ID_A] = A;
+		names[Ids.ID_ADDRESS] = ADDRESS;
+		names[Ids.ID_BASE] = BASE;
+		names[Ids.ID_BLOCKQUOTE] = BLOCKQUOTE;
+		names[Ids.ID_BODY] = BODY;
+		names[Ids.ID_BR] = BR;
+		names[Ids.ID_CENTER] = CENTER;
+		names[Ids.ID_DD] = DD;
+		names[Ids.ID_DIR] = DIR;
+		names[Ids.ID_DIV] = DIV;
+		names[Ids.ID_DL] = DL;
+		names[Ids.ID_DT] = DT;
+		names[Ids.ID_FORM] = FORM;
+		names[Ids.ID_H1] = H1;
+		names[Ids.ID_H2] = H2;
+		names[Ids.ID_H3] = H3;
+		names[Ids.ID_H4] = H4;
+		names[Ids.ID_H5] = H5;
+		names[Ids.ID_H6] = H6;
+		names[Ids.ID_HEAD] = HEAD;
+		names[Ids.ID_HR] = HR;
+		names[Ids.ID_HTML] = HTML;
+		names[Ids.ID_IMG] = IMG;
+		names[Ids.ID_INPUT] = INPUT;
+		names[Ids.ID_LI] = LI;
+		names[Ids.ID_MENU] = MENU;
+		names[Ids.ID_META] = META;
+		names[Ids.ID_OL] = OL;
+		names[Ids.ID_OPTION] = OPTION;
+		names[Ids.ID_P] = P;
+		names[Ids.ID_PRE] = PRE;
+		names[Ids.ID_SELECT] = SELECT;
+		names[Ids.ID_TEXTAREA] = TEXTAREA;
+		names[Ids.ID_TITLE] = TITLE;
+		names[Ids.ID_UL] = UL;
+		names[Ids.ID_SSI_CONFIG] = SSI_CONFIG;
+		names[Ids.ID_SSI_ECHO] = SSI_ECHO;
+		names[Ids.ID_SSI_EXEC] = SSI_EXEC;
+		names[Ids.ID_SSI_FSIZE] = SSI_FSIZE;
+		names[Ids.ID_SSI_FLASTMOD] = SSI_FLASTMOD;
+		names[Ids.ID_SSI_INCLUDE] = SSI_INCLUDE;
+		names[Ids.ID_SSI_PRINTENV] = SSI_PRINTENV;
+		names[Ids.ID_SSI_SET] = SSI_SET;
+	}
+
+	/**
+	 */
+	public ElementCollection(AttributeCollection collection) {
+		super(names, TOLERANT_CASE);
+		attributeCollection = collection;
+	}
+
+	/**
+	 * Actually creates HTMLElementDeclaration instance.
+	 * @return HTMLElementDeclaration
+	 */
+	protected CMNode create(String elementName) {
+		HTMLElemDeclImpl edec = null;
+
+		if (elementName.equalsIgnoreCase(A)) {
+			edec = new HedA(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(ADDRESS)) {
+			edec = new HedADDRESS(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(BASE)) {
+			edec = new HedBASE(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(BLOCKQUOTE)) {
+			edec = new HedBLOCKQUOTE(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(BODY)) {
+			edec = new HedBODY(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(BR)) {
+			edec = new HedBR(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(CENTER)) {
+			edec = new HedCENTER(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(DD)) {
+			edec = new HedDD(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(DIR)) {
+			edec = new HedMENU(DIR, this);
+
+		}
+		else if (elementName.equalsIgnoreCase(DIV)) {
+			edec = new HedDIV(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(DL)) {
+			edec = new HedDL(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(DT)) {
+			edec = new HedDT(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(FORM)) {
+			edec = new HedFORM(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(H1)) {
+			edec = new HedHeading(H1, this);
+
+		}
+		else if (elementName.equalsIgnoreCase(H2)) {
+			edec = new HedHeading(H2, this);
+
+		}
+		else if (elementName.equalsIgnoreCase(H3)) {
+			edec = new HedHeading(H3, this);
+
+		}
+		else if (elementName.equalsIgnoreCase(H4)) {
+			edec = new HedHeading(H4, this);
+
+		}
+		else if (elementName.equalsIgnoreCase(H5)) {
+			edec = new HedHeading(H5, this);
+
+		}
+		else if (elementName.equalsIgnoreCase(H6)) {
+			edec = new HedHeading(H6, this);
+
+		}
+		else if (elementName.equalsIgnoreCase(HEAD)) {
+			edec = new HedHEAD(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(HR)) {
+			edec = new HedHR(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(HTML)) {
+			edec = new HedHTML(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(IMG)) {
+			edec = new HedIMG(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(INPUT)) {
+			edec = new HedINPUT(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(LI)) {
+			edec = new HedLI(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(MENU)) {
+			edec = new HedMENU(MENU, this);
+
+		}
+		else if (elementName.equalsIgnoreCase(META)) {
+			edec = new HedMETA(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(OL)) {
+			edec = new HedOL(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(OPTION)) {
+			edec = new HedOPTION(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(P)) {
+			edec = new HedP(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(PRE)) {
+			edec = new HedPRE(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(SELECT)) {
+			edec = new HedSELECT(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(TEXTAREA)) {
+			edec = new HedTEXTAREA(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(TITLE)) {
+			edec = new HedTITLE(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(UL)) {
+			edec = new HedUL(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(SSI_CONFIG)) {
+			edec = new HedSSIConfig(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(SSI_ECHO)) {
+			edec = new HedSSIEcho(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(SSI_EXEC)) {
+			edec = new HedSSIExec(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(SSI_FSIZE)) {
+			edec = new HedSSIFsize(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(SSI_FLASTMOD)) {
+			edec = new HedSSIFlastmod(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(SSI_INCLUDE)) {
+			edec = new HedSSIInclude(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(SSI_PRINTENV)) {
+			edec = new HedSSIPrintenv(this);
+
+		}
+		else if (elementName.equalsIgnoreCase(SSI_SET)) {
+			edec = new HedSSISet(this);
+
+		} // unknown
+		else {
+			// NOTE: We don't define the UNKNOWN element declaration.
+			// <code>null</code> for a declaration is a sign of
+			// the target element is unknown.
+			// -- 3/9/2001
+			edec = null;
+		}
+		return edec;
+	}
+
+	public AttributeCollection getAttributeCollection() {
+		return attributeCollection;
+	}
+
+	/**
+	 */
+	public final Collection getNamesOfBlock() {
+		// P | %list | %preformatted | DL | DIV | CENTER | BLOCKQUOTE | FORM | HR
+		String[] blockMisc = {P, DL, DIV, CENTER, BLOCKQUOTE, FORM, HR,};
+		Vector blockNames = new Vector(Arrays.asList(blockMisc));
+		// %heading;
+		blockNames.addAll(Arrays.asList(HEADING));
+		// %list;
+		blockNames.addAll(Arrays.asList(LIST));
+		// %preformatted;
+		blockNames.addAll(Arrays.asList(PREFORMATTED));
+
+		return blockNames;
+	}
+
+	/**
+	 * %block;.
+	 * %block; is:
+	 * P | %heading; | %list; | %preformatted; | DL | DIV | CENTER |
+	 * NOSCRIPT | NOFRAMES | BLOCKQUOTE | FORM | ISINDEX | HR |
+	 * TABLE | FIELDSET | ADDRESS.<br>
+	 * @param group CMGroupImpl Return values.
+	 */
+	public final void getBlock(CMGroupImpl group) {
+		if (group == null)
+			return;
+		getDeclarations(group, getNamesOfBlock().iterator());
+	}
+
+	/**
+	 * Create element declarations and store them
+	 * into a <code>CMGroupImpl</code> instance.
+	 * @param group CMGroupImpl Return values.
+	 */
+	public final void getFlow(CMGroupImpl group) {
+		if (group == null)
+			return;
+		getBlock(group);
+		getInline(group);
+	}
+
+	/**
+	 * Create element declarations and store them into a <code>CMGroupImpl</code>
+	 * instance.<br>
+	 * @param group CMGroupImpl Return values.
+	 */
+	public final void getFontstyle(CMGroupImpl group) {
+		return;
+	}
+
+	/**
+	 * Create element declarations and store them into a <code>CMGroupImpl</code>
+	 * instance.<br>
+	 * @param group CMGroupImpl Return values.
+	 */
+	public final void getFormctrl(CMGroupImpl group) {
+		if (group == null)
+			return;
+		getDeclarations(group, Arrays.asList(FORMCTL).iterator());
+	}
+
+	/**
+	 * %heading;.
+	 * @param group CMGroupImpl Return values.
+	 */
+	public final void getHeading(CMGroupImpl group) {
+		if (group == null)
+			return;
+
+		getDeclarations(group, Arrays.asList(HEADING).iterator());
+	}
+
+	/**
+	 * Create element declarations and store them
+	 * into a <code>CMGroupImpl</code> instance.
+	 * @param group CMGroupImpl Return values.
+	 */
+	public final void getInline(CMGroupImpl group) {
+		if (group == null)
+			return;
+		getFontstyle(group);
+		getPhrase(group);
+		getSpecial(group);
+		getFormctrl(group);
+	}
+
+	/**
+	 * %list;.
+	 * @param group CMGroupImpl Return values.
+	 */
+	public final void getList(CMGroupImpl group) {
+		if (group == null)
+			return;
+
+		getDeclarations(group, Arrays.asList(LIST).iterator());
+	}
+
+	/**
+	 * Create element declarations and store them into a <code>CMGroupImpl</code>
+	 * instance.<br>
+	 * @param group CMGroupImpl Return values.
+	 */
+	public final void getPhrase(CMGroupImpl group) {
+		if (group == null)
+			return;
+		getDeclarations(group, Arrays.asList(PHRASE).iterator());
+	}
+
+	/**
+	 * %preformatted;
+	 * @param group CMGroupImpl Return values.
+	 */
+	public final void getPreformatted(CMGroupImpl group) {
+		if (group == null)
+			return;
+
+		getDeclarations(group, Arrays.asList(PREFORMATTED).iterator());
+	}
+
+	/**
+	 * Create element declarations and store them into a <code>CMGroupImpl</code>
+	 * instance.<br>
+	 * @param group CMGroupImpl Return values.
+	 */
+	public final void getSpecial(CMGroupImpl group) {
+		if (group == null)
+			return;
+		getDeclarations(group, Arrays.asList(SPECIAL).iterator());
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/EntityCollection.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/EntityCollection.java
new file mode 100644
index 0000000..4f371fc
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/EntityCollection.java
@@ -0,0 +1,837 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import java.lang.reflect.Field;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ * Factory for entity declarations.
+ */
+final class EntityCollection extends DeclCollection implements org.eclipse.wst.html.core.internal.provisional.HTML40Namespace.EntityName {
+
+
+	private static class Ids {
+		public static final int ID_AACUTE_L = 0;
+		public static final int ID_AACUTE_U = 1;
+		public static final int ID_ACIRC_L = 2;
+		public static final int ID_ACIRC_U = 3;
+		public static final int ID_ACUTE = 4;
+		public static final int ID_AELIG_L = 5;
+		public static final int ID_AELIG_U = 6;
+		public static final int ID_AGRAVE_L = 7;
+		public static final int ID_AGRAVE_U = 8;
+		public static final int ID_ALEFSYM = 9;
+		public static final int ID_ALPHA_L = 10;
+		public static final int ID_ALPHA_U = 11;
+		public static final int ID_AMP = 12;
+		public static final int ID_AND = 13;
+		public static final int ID_ANG = 14;
+		public static final int ID_ARING_L = 15;
+		public static final int ID_ARING_U = 16;
+		public static final int ID_ASYMP = 17;
+		public static final int ID_ATILDE_L = 18;
+		public static final int ID_ATILDE_U = 19;
+		public static final int ID_AUML_L = 20;
+		public static final int ID_AUML_U = 21;
+		public static final int ID_BDQUO = 22;
+		public static final int ID_BETA_L = 23;
+		public static final int ID_BETA_U = 24;
+		public static final int ID_BRVBAR = 25;
+		public static final int ID_BULL = 26;
+		public static final int ID_CAP = 27;
+		public static final int ID_CCEDIL_L = 28;
+		public static final int ID_CCEDIL_U = 29;
+		public static final int ID_CEDIL = 30;
+		public static final int ID_CENT = 31;
+		public static final int ID_CHI_L = 32;
+		public static final int ID_CHI_U = 33;
+		public static final int ID_CIRC = 34;
+		public static final int ID_CLUBS = 35;
+		public static final int ID_CONG = 36;
+		public static final int ID_COPY = 37;
+		public static final int ID_CRARR = 38;
+		public static final int ID_CUP = 39;
+		public static final int ID_CURREN = 40;
+		public static final int ID_DAGGER_L = 41;
+		public static final int ID_DAGGER_U = 42;
+		public static final int ID_DARR_L = 43;
+		public static final int ID_DARR_U = 44;
+		public static final int ID_DEG = 45;
+		public static final int ID_DELTA_L = 46;
+		public static final int ID_DELTA_U = 47;
+		public static final int ID_DIAMS = 48;
+		public static final int ID_DIVIDE = 49;
+		public static final int ID_EACUTE_L = 50;
+		public static final int ID_EACUTE_U = 51;
+		public static final int ID_ECIRC_L = 52;
+		public static final int ID_ECIRC_U = 53;
+		public static final int ID_EGRAVE_L = 54;
+		public static final int ID_EGRAVE_U = 55;
+		public static final int ID_EMPTY = 56;
+		public static final int ID_EMSP = 57;
+		public static final int ID_ENSP = 58;
+		public static final int ID_EPSILON_L = 59;
+		public static final int ID_EPSILON_U = 60;
+		public static final int ID_EQUIV = 61;
+		public static final int ID_ETA_L = 62;
+		public static final int ID_ETA_U = 63;
+		public static final int ID_ETH_L = 64;
+		public static final int ID_ETH_U = 65;
+		public static final int ID_EUML_L = 66;
+		public static final int ID_EUML_U = 67;
+		public static final int ID_EURO = 68;
+		public static final int ID_EXIST = 69;
+		public static final int ID_FNOF = 70;
+		public static final int ID_FORALL = 71;
+		public static final int ID_FRAC12 = 72;
+		public static final int ID_FRAC14 = 73;
+		public static final int ID_FRAC34 = 74;
+		public static final int ID_FRASL = 75;
+		public static final int ID_GAMMA_L = 76;
+		public static final int ID_GAMMA_U = 77;
+		public static final int ID_GE = 78;
+		public static final int ID_GT = 79;
+		public static final int ID_HARR_L = 80;
+		public static final int ID_HARR_U = 81;
+		public static final int ID_HEARTS = 82;
+		public static final int ID_HELLIP = 83;
+		public static final int ID_IACUTE_L = 84;
+		public static final int ID_IACUTE_U = 85;
+		public static final int ID_ICIRC_L = 86;
+		public static final int ID_ICIRC_U = 87;
+		public static final int ID_IEXCL = 88;
+		public static final int ID_IGRAVE_L = 89;
+		public static final int ID_IGRAVE_U = 90;
+		public static final int ID_IMAGE = 91;
+		public static final int ID_INFIN = 92;
+		public static final int ID_INT = 93;
+		public static final int ID_IOTA_L = 94;
+		public static final int ID_IOTA_U = 95;
+		public static final int ID_IQUEST = 96;
+		public static final int ID_ISIN = 97;
+		public static final int ID_IUML_L = 98;
+		public static final int ID_IUML_U = 99;
+		public static final int ID_KAPPA_L = 100;
+		public static final int ID_KAPPA_U = 101;
+		public static final int ID_LAMBDA_L = 102;
+		public static final int ID_LAMBDA_U = 103;
+		public static final int ID_LANG = 104;
+		public static final int ID_LAQUO = 105;
+		public static final int ID_LARR_L = 106;
+		public static final int ID_LARR_U = 107;
+		public static final int ID_LCEIL = 108;
+		public static final int ID_LDQUO = 109;
+		public static final int ID_LE = 110;
+		public static final int ID_LFLOOR = 111;
+		public static final int ID_LOWAST = 112;
+		public static final int ID_LOZ = 113;
+		public static final int ID_LRM = 114;
+		public static final int ID_LSAQUO = 115;
+		public static final int ID_LSQUO = 116;
+		public static final int ID_LT = 117;
+		public static final int ID_MACR = 118;
+		public static final int ID_MDASH = 119;
+		public static final int ID_MICRO = 120;
+		public static final int ID_MIDDOT = 121;
+		public static final int ID_MINUS = 122;
+		public static final int ID_MU_L = 123;
+		public static final int ID_MU_U = 124;
+		public static final int ID_NABLA = 125;
+		public static final int ID_NBSP = 126;
+		public static final int ID_NDASH = 127;
+		public static final int ID_NE = 128;
+		public static final int ID_NI = 129;
+		public static final int ID_NOT = 130;
+		public static final int ID_NOTIN = 131;
+		public static final int ID_NSUB = 132;
+		public static final int ID_NTILDE_L = 133;
+		public static final int ID_NTILDE_U = 134;
+		public static final int ID_NU_L = 135;
+		public static final int ID_NU_U = 136;
+		public static final int ID_OACUTE_L = 137;
+		public static final int ID_OACUTE_U = 138;
+		public static final int ID_OCIRC_L = 139;
+		public static final int ID_OCIRC_U = 140;
+		public static final int ID_OELIG_L = 141;
+		public static final int ID_OELIG_U = 142;
+		public static final int ID_OGRAVE_L = 143;
+		public static final int ID_OGRAVE_U = 144;
+		public static final int ID_OLINE = 145;
+		public static final int ID_OMEGA_L = 146;
+		public static final int ID_OMEGA_U = 147;
+		public static final int ID_OMICRON_L = 148;
+		public static final int ID_OMICRON_U = 149;
+		public static final int ID_OPLUS = 150;
+		public static final int ID_OR = 151;
+		public static final int ID_ORDF = 152;
+		public static final int ID_ORDM = 153;
+		public static final int ID_OSLASH_L = 154;
+		public static final int ID_OSLASH_U = 155;
+		public static final int ID_OTILDE_L = 156;
+		public static final int ID_OTILDE_U = 157;
+		public static final int ID_OTIMES = 158;
+		public static final int ID_OUML_L = 159;
+		public static final int ID_OUML_U = 160;
+		public static final int ID_PARA = 161;
+		public static final int ID_PART = 162;
+		public static final int ID_PERMIL = 163;
+		public static final int ID_PERP = 164;
+		public static final int ID_PHI_L = 165;
+		public static final int ID_PHI_U = 166;
+		public static final int ID_PIV = 167;
+		public static final int ID_PI_L = 168;
+		public static final int ID_PI_U = 169;
+		public static final int ID_PLUSMN = 170;
+		public static final int ID_POUND = 171;
+		public static final int ID_PRIME_L = 172;
+		public static final int ID_PRIME_U = 173;
+		public static final int ID_PROD = 174;
+		public static final int ID_PROP = 175;
+		public static final int ID_PSI_L = 176;
+		public static final int ID_PSI_U = 177;
+		public static final int ID_QUOT = 178;
+		public static final int ID_RADIC = 179;
+		public static final int ID_RANG = 180;
+		public static final int ID_RAQUO = 181;
+		public static final int ID_RARR_L = 182;
+		public static final int ID_RARR_U = 183;
+		public static final int ID_RCEIL = 184;
+		public static final int ID_RDQUO = 185;
+		public static final int ID_REAL = 186;
+		public static final int ID_REG = 187;
+		public static final int ID_RFLOOR = 188;
+		public static final int ID_RHO_L = 189;
+		public static final int ID_RHO_U = 190;
+		public static final int ID_RLM = 191;
+		public static final int ID_RSAQUO = 192;
+		public static final int ID_RSQUO = 193;
+		public static final int ID_SBQUO = 194;
+		public static final int ID_SCARON_L = 195;
+		public static final int ID_SCARON_U = 196;
+		public static final int ID_SDOT = 197;
+		public static final int ID_SECT = 198;
+		public static final int ID_SHY = 199;
+		public static final int ID_SIGMAF = 200;
+		public static final int ID_SIGMA_L = 201;
+		public static final int ID_SIGMA_U = 202;
+		public static final int ID_SIM = 203;
+		public static final int ID_SPADES = 204;
+		public static final int ID_SUB = 205;
+		public static final int ID_SUBE = 206;
+		public static final int ID_SUM = 207;
+		public static final int ID_SUP = 208;
+		public static final int ID_SUP1 = 209;
+		public static final int ID_SUP2 = 210;
+		public static final int ID_SUP3 = 211;
+		public static final int ID_SUPE = 212;
+		public static final int ID_SZLIG = 213;
+		public static final int ID_TAU_L = 214;
+		public static final int ID_TAU_U = 215;
+		public static final int ID_THERE4 = 216;
+		public static final int ID_THETASYM = 217;
+		public static final int ID_THETA_L = 218;
+		public static final int ID_THETA_U = 219;
+		public static final int ID_THINSP = 220;
+		public static final int ID_THORN_L = 221;
+		public static final int ID_THORN_U = 222;
+		public static final int ID_TILDE = 223;
+		public static final int ID_TIMES = 224;
+		public static final int ID_TRADE = 225;
+		public static final int ID_UACUTE_L = 226;
+		public static final int ID_UACUTE_U = 227;
+		public static final int ID_UARR_L = 228;
+		public static final int ID_UARR_U = 229;
+		public static final int ID_UCIRC_L = 230;
+		public static final int ID_UCIRC_U = 231;
+		public static final int ID_UGRAVE_L = 232;
+		public static final int ID_UGRAVE_U = 233;
+		public static final int ID_UML = 234;
+		public static final int ID_UPSIH = 235;
+		public static final int ID_UPSILON_L = 236;
+		public static final int ID_UPSILON_U = 237;
+		public static final int ID_UUML_L = 238;
+		public static final int ID_UUML_U = 239;
+		public static final int ID_WEIERP = 240;
+		public static final int ID_XI_L = 241;
+		public static final int ID_XI_U = 242;
+		public static final int ID_YACUTE_L = 243;
+		public static final int ID_YACUTE_U = 244;
+		public static final int ID_YEN = 245;
+		public static final int ID_YUML_L = 246;
+		public static final int ID_YUML_U = 247;
+		public static final int ID_ZETA_L = 248;
+		public static final int ID_ZETA_U = 249;
+		public static final int ID_ZWJ = 250;
+		public static final int ID_ZWNJ = 251;
+
+		public static int getNumOfIds() {
+			if (numofids != -1)
+				return numofids;
+
+			// NOTE: If the reflection is too slow, this method should
+			// just return the literal value, like 252.
+			// -- 5/24/2001
+			Class clazz = Ids.class;
+			Field[] fields = clazz.getFields();
+			numofids = 0;
+			for (int i = 0; i < fields.length; i++) {
+				String name = fields[i].getName();
+				if (name.startsWith("ID_"))//$NON-NLS-1$
+					numofids++;
+			}
+			return numofids;
+		}
+
+		// chache the result of the reflection.
+		private static int numofids = -1;
+	}
+
+	private static String[] names = null;
+
+	static {
+		names = new String[Ids.getNumOfIds()];
+		names[Ids.ID_AACUTE_L] = AACUTE_L;
+		names[Ids.ID_AACUTE_U] = AACUTE_U;
+		names[Ids.ID_ACIRC_L] = ACIRC_L;
+		names[Ids.ID_ACIRC_U] = ACIRC_U;
+		names[Ids.ID_ACUTE] = ACUTE;
+		names[Ids.ID_AELIG_L] = AELIG_L;
+		names[Ids.ID_AELIG_U] = AELIG_U;
+		names[Ids.ID_AGRAVE_L] = AGRAVE_L;
+		names[Ids.ID_AGRAVE_U] = AGRAVE_U;
+		names[Ids.ID_ALEFSYM] = ALEFSYM;
+		names[Ids.ID_ALPHA_L] = ALPHA_L;
+		names[Ids.ID_ALPHA_U] = ALPHA_U;
+		names[Ids.ID_AMP] = AMP;
+		names[Ids.ID_AND] = AND;
+		names[Ids.ID_ANG] = ANG;
+		names[Ids.ID_ARING_L] = ARING_L;
+		names[Ids.ID_ARING_U] = ARING_U;
+		names[Ids.ID_ASYMP] = ASYMP;
+		names[Ids.ID_ATILDE_L] = ATILDE_L;
+		names[Ids.ID_ATILDE_U] = ATILDE_U;
+		names[Ids.ID_AUML_L] = AUML_L;
+		names[Ids.ID_AUML_U] = AUML_U;
+		names[Ids.ID_BDQUO] = BDQUO;
+		names[Ids.ID_BETA_L] = BETA_L;
+		names[Ids.ID_BETA_U] = BETA_U;
+		names[Ids.ID_BRVBAR] = BRVBAR;
+		names[Ids.ID_BULL] = BULL;
+		names[Ids.ID_CAP] = CAP;
+		names[Ids.ID_CCEDIL_L] = CCEDIL_L;
+		names[Ids.ID_CCEDIL_U] = CCEDIL_U;
+		names[Ids.ID_CEDIL] = CEDIL;
+		names[Ids.ID_CENT] = CENT;
+		names[Ids.ID_CHI_L] = CHI_L;
+		names[Ids.ID_CHI_U] = CHI_U;
+		names[Ids.ID_CIRC] = CIRC;
+		names[Ids.ID_CLUBS] = CLUBS;
+		names[Ids.ID_CONG] = CONG;
+		names[Ids.ID_COPY] = COPY;
+		names[Ids.ID_CRARR] = CRARR;
+		names[Ids.ID_CUP] = CUP;
+		names[Ids.ID_CURREN] = CURREN;
+		names[Ids.ID_DAGGER_L] = DAGGER_L;
+		names[Ids.ID_DAGGER_U] = DAGGER_U;
+		names[Ids.ID_DARR_L] = DARR_L;
+		names[Ids.ID_DARR_U] = DARR_U;
+		names[Ids.ID_DEG] = DEG;
+		names[Ids.ID_DELTA_L] = DELTA_L;
+		names[Ids.ID_DELTA_U] = DELTA_U;
+		names[Ids.ID_DIAMS] = DIAMS;
+		names[Ids.ID_DIVIDE] = DIVIDE;
+		names[Ids.ID_EACUTE_L] = EACUTE_L;
+		names[Ids.ID_EACUTE_U] = EACUTE_U;
+		names[Ids.ID_ECIRC_L] = ECIRC_L;
+		names[Ids.ID_ECIRC_U] = ECIRC_U;
+		names[Ids.ID_EGRAVE_L] = EGRAVE_L;
+		names[Ids.ID_EGRAVE_U] = EGRAVE_U;
+		names[Ids.ID_EMPTY] = EMPTY;
+		names[Ids.ID_EMSP] = EMSP;
+		names[Ids.ID_ENSP] = ENSP;
+		names[Ids.ID_EPSILON_L] = EPSILON_L;
+		names[Ids.ID_EPSILON_U] = EPSILON_U;
+		names[Ids.ID_EQUIV] = EQUIV;
+		names[Ids.ID_ETA_L] = ETA_L;
+		names[Ids.ID_ETA_U] = ETA_U;
+		names[Ids.ID_ETH_L] = ETH_L;
+		names[Ids.ID_ETH_U] = ETH_U;
+		names[Ids.ID_EUML_L] = EUML_L;
+		names[Ids.ID_EUML_U] = EUML_U;
+		names[Ids.ID_EURO] = EURO;
+		names[Ids.ID_EXIST] = EXIST;
+		names[Ids.ID_FNOF] = FNOF;
+		names[Ids.ID_FORALL] = FORALL;
+		names[Ids.ID_FRAC12] = FRAC12;
+		names[Ids.ID_FRAC14] = FRAC14;
+		names[Ids.ID_FRAC34] = FRAC34;
+		names[Ids.ID_FRASL] = FRASL;
+		names[Ids.ID_GAMMA_L] = GAMMA_L;
+		names[Ids.ID_GAMMA_U] = GAMMA_U;
+		names[Ids.ID_GE] = GE;
+		names[Ids.ID_GT] = GT;
+		names[Ids.ID_HARR_L] = HARR_L;
+		names[Ids.ID_HARR_U] = HARR_U;
+		names[Ids.ID_HEARTS] = HEARTS;
+		names[Ids.ID_HELLIP] = HELLIP;
+		names[Ids.ID_IACUTE_L] = IACUTE_L;
+		names[Ids.ID_IACUTE_U] = IACUTE_U;
+		names[Ids.ID_ICIRC_L] = ICIRC_L;
+		names[Ids.ID_ICIRC_U] = ICIRC_U;
+		names[Ids.ID_IEXCL] = IEXCL;
+		names[Ids.ID_IGRAVE_L] = IGRAVE_L;
+		names[Ids.ID_IGRAVE_U] = IGRAVE_U;
+		names[Ids.ID_IMAGE] = IMAGE;
+		names[Ids.ID_INFIN] = INFIN;
+		names[Ids.ID_INT] = INT;
+		names[Ids.ID_IOTA_L] = IOTA_L;
+		names[Ids.ID_IOTA_U] = IOTA_U;
+		names[Ids.ID_IQUEST] = IQUEST;
+		names[Ids.ID_ISIN] = ISIN;
+		names[Ids.ID_IUML_L] = IUML_L;
+		names[Ids.ID_IUML_U] = IUML_U;
+		names[Ids.ID_KAPPA_L] = KAPPA_L;
+		names[Ids.ID_KAPPA_U] = KAPPA_U;
+		names[Ids.ID_LAMBDA_L] = LAMBDA_L;
+		names[Ids.ID_LAMBDA_U] = LAMBDA_U;
+		names[Ids.ID_LANG] = LANG;
+		names[Ids.ID_LAQUO] = LAQUO;
+		names[Ids.ID_LARR_L] = LARR_L;
+		names[Ids.ID_LARR_U] = LARR_U;
+		names[Ids.ID_LCEIL] = LCEIL;
+		names[Ids.ID_LDQUO] = LDQUO;
+		names[Ids.ID_LE] = LE;
+		names[Ids.ID_LFLOOR] = LFLOOR;
+		names[Ids.ID_LOWAST] = LOWAST;
+		names[Ids.ID_LOZ] = LOZ;
+		names[Ids.ID_LRM] = LRM;
+		names[Ids.ID_LSAQUO] = LSAQUO;
+		names[Ids.ID_LSQUO] = LSQUO;
+		names[Ids.ID_LT] = LT;
+		names[Ids.ID_MACR] = MACR;
+		names[Ids.ID_MDASH] = MDASH;
+		names[Ids.ID_MICRO] = MICRO;
+		names[Ids.ID_MIDDOT] = MIDDOT;
+		names[Ids.ID_MINUS] = MINUS;
+		names[Ids.ID_MU_L] = MU_L;
+		names[Ids.ID_MU_U] = MU_U;
+		names[Ids.ID_NABLA] = NABLA;
+		names[Ids.ID_NBSP] = NBSP;
+		names[Ids.ID_NDASH] = NDASH;
+		names[Ids.ID_NE] = NE;
+		names[Ids.ID_NI] = NI;
+		names[Ids.ID_NOT] = NOT;
+		names[Ids.ID_NOTIN] = NOTIN;
+		names[Ids.ID_NSUB] = NSUB;
+		names[Ids.ID_NTILDE_L] = NTILDE_L;
+		names[Ids.ID_NTILDE_U] = NTILDE_U;
+		names[Ids.ID_NU_L] = NU_L;
+		names[Ids.ID_NU_U] = NU_U;
+		names[Ids.ID_OACUTE_L] = OACUTE_L;
+		names[Ids.ID_OACUTE_U] = OACUTE_U;
+		names[Ids.ID_OCIRC_L] = OCIRC_L;
+		names[Ids.ID_OCIRC_U] = OCIRC_U;
+		names[Ids.ID_OELIG_L] = OELIG_L;
+		names[Ids.ID_OELIG_U] = OELIG_U;
+		names[Ids.ID_OGRAVE_L] = OGRAVE_L;
+		names[Ids.ID_OGRAVE_U] = OGRAVE_U;
+		names[Ids.ID_OLINE] = OLINE;
+		names[Ids.ID_OMEGA_L] = OMEGA_L;
+		names[Ids.ID_OMEGA_U] = OMEGA_U;
+		names[Ids.ID_OMICRON_L] = OMICRON_L;
+		names[Ids.ID_OMICRON_U] = OMICRON_U;
+		names[Ids.ID_OPLUS] = OPLUS;
+		names[Ids.ID_OR] = OR;
+		names[Ids.ID_ORDF] = ORDF;
+		names[Ids.ID_ORDM] = ORDM;
+		names[Ids.ID_OSLASH_L] = OSLASH_L;
+		names[Ids.ID_OSLASH_U] = OSLASH_U;
+		names[Ids.ID_OTILDE_L] = OTILDE_L;
+		names[Ids.ID_OTILDE_U] = OTILDE_U;
+		names[Ids.ID_OTIMES] = OTIMES;
+		names[Ids.ID_OUML_L] = OUML_L;
+		names[Ids.ID_OUML_U] = OUML_U;
+		names[Ids.ID_PARA] = PARA;
+		names[Ids.ID_PART] = PART;
+		names[Ids.ID_PERMIL] = PERMIL;
+		names[Ids.ID_PERP] = PERP;
+		names[Ids.ID_PHI_L] = PHI_L;
+		names[Ids.ID_PHI_U] = PHI_U;
+		names[Ids.ID_PIV] = PIV;
+		names[Ids.ID_PI_L] = PI_L;
+		names[Ids.ID_PI_U] = PI_U;
+		names[Ids.ID_PLUSMN] = PLUSMN;
+		names[Ids.ID_POUND] = POUND;
+		names[Ids.ID_PRIME_L] = PRIME_L;
+		names[Ids.ID_PRIME_U] = PRIME_U;
+		names[Ids.ID_PROD] = PROD;
+		names[Ids.ID_PROP] = PROP;
+		names[Ids.ID_PSI_L] = PSI_L;
+		names[Ids.ID_PSI_U] = PSI_U;
+		names[Ids.ID_QUOT] = QUOT;
+		names[Ids.ID_RADIC] = RADIC;
+		names[Ids.ID_RANG] = RANG;
+		names[Ids.ID_RAQUO] = RAQUO;
+		names[Ids.ID_RARR_L] = RARR_L;
+		names[Ids.ID_RARR_U] = RARR_U;
+		names[Ids.ID_RCEIL] = RCEIL;
+		names[Ids.ID_RDQUO] = RDQUO;
+		names[Ids.ID_REAL] = REAL;
+		names[Ids.ID_REG] = REG;
+		names[Ids.ID_RFLOOR] = RFLOOR;
+		names[Ids.ID_RHO_L] = RHO_L;
+		names[Ids.ID_RHO_U] = RHO_U;
+		names[Ids.ID_RLM] = RLM;
+		names[Ids.ID_RSAQUO] = RSAQUO;
+		names[Ids.ID_RSQUO] = RSQUO;
+		names[Ids.ID_SBQUO] = SBQUO;
+		names[Ids.ID_SCARON_L] = SCARON_L;
+		names[Ids.ID_SCARON_U] = SCARON_U;
+		names[Ids.ID_SDOT] = SDOT;
+		names[Ids.ID_SECT] = SECT;
+		names[Ids.ID_SHY] = SHY;
+		names[Ids.ID_SIGMAF] = SIGMAF;
+		names[Ids.ID_SIGMA_L] = SIGMA_L;
+		names[Ids.ID_SIGMA_U] = SIGMA_U;
+		names[Ids.ID_SIM] = SIM;
+		names[Ids.ID_SPADES] = SPADES;
+		names[Ids.ID_SUB] = SUB;
+		names[Ids.ID_SUBE] = SUBE;
+		names[Ids.ID_SUM] = SUM;
+		names[Ids.ID_SUP] = SUP;
+		names[Ids.ID_SUP1] = SUP1;
+		names[Ids.ID_SUP2] = SUP2;
+		names[Ids.ID_SUP3] = SUP3;
+		names[Ids.ID_SUPE] = SUPE;
+		names[Ids.ID_SZLIG] = SZLIG;
+		names[Ids.ID_TAU_L] = TAU_L;
+		names[Ids.ID_TAU_U] = TAU_U;
+		names[Ids.ID_THERE4] = THERE4;
+		names[Ids.ID_THETASYM] = THETASYM;
+		names[Ids.ID_THETA_L] = THETA_L;
+		names[Ids.ID_THETA_U] = THETA_U;
+		names[Ids.ID_THINSP] = THINSP;
+		names[Ids.ID_THORN_L] = THORN_L;
+		names[Ids.ID_THORN_U] = THORN_U;
+		names[Ids.ID_TILDE] = TILDE;
+		names[Ids.ID_TIMES] = TIMES;
+		names[Ids.ID_TRADE] = TRADE;
+		names[Ids.ID_UACUTE_L] = UACUTE_L;
+		names[Ids.ID_UACUTE_U] = UACUTE_U;
+		names[Ids.ID_UARR_L] = UARR_L;
+		names[Ids.ID_UARR_U] = UARR_U;
+		names[Ids.ID_UCIRC_L] = UCIRC_L;
+		names[Ids.ID_UCIRC_U] = UCIRC_U;
+		names[Ids.ID_UGRAVE_L] = UGRAVE_L;
+		names[Ids.ID_UGRAVE_U] = UGRAVE_U;
+		names[Ids.ID_UML] = UML;
+		names[Ids.ID_UPSIH] = UPSIH;
+		names[Ids.ID_UPSILON_L] = UPSILON_L;
+		names[Ids.ID_UPSILON_U] = UPSILON_U;
+		names[Ids.ID_UUML_L] = UUML_L;
+		names[Ids.ID_UUML_U] = UUML_U;
+		names[Ids.ID_WEIERP] = WEIERP;
+		names[Ids.ID_XI_L] = XI_L;
+		names[Ids.ID_XI_U] = XI_U;
+		names[Ids.ID_YACUTE_L] = YACUTE_L;
+		names[Ids.ID_YACUTE_U] = YACUTE_U;
+		names[Ids.ID_YEN] = YEN;
+		names[Ids.ID_YUML_L] = YUML_L;
+		names[Ids.ID_YUML_U] = YUML_U;
+		names[Ids.ID_ZETA_L] = ZETA_L;
+		names[Ids.ID_ZETA_U] = ZETA_U;
+		names[Ids.ID_ZWJ] = ZWJ;
+		names[Ids.ID_ZWNJ] = ZWNJ;
+	}
+	private static char[] values = null;
+
+	static {
+		values = new char[Ids.getNumOfIds()];
+		values[Ids.ID_AACUTE_L] = 225;
+		values[Ids.ID_AACUTE_U] = 193;
+		values[Ids.ID_ACIRC_L] = 226;
+		values[Ids.ID_ACIRC_U] = 194;
+		values[Ids.ID_ACUTE] = 180;
+		values[Ids.ID_AELIG_L] = 230;
+		values[Ids.ID_AELIG_U] = 198;
+		values[Ids.ID_AGRAVE_L] = 224;
+		values[Ids.ID_AGRAVE_U] = 192;
+		values[Ids.ID_ALEFSYM] = 8501;
+		values[Ids.ID_ALPHA_L] = 945;
+		values[Ids.ID_ALPHA_U] = 913;
+		values[Ids.ID_AMP] = 38;
+		values[Ids.ID_AND] = 8743;
+		values[Ids.ID_ANG] = 8736;
+		values[Ids.ID_ARING_L] = 229;
+		values[Ids.ID_ARING_U] = 197;
+		values[Ids.ID_ASYMP] = 8776;
+		values[Ids.ID_ATILDE_L] = 227;
+		values[Ids.ID_ATILDE_U] = 195;
+		values[Ids.ID_AUML_L] = 228;
+		values[Ids.ID_AUML_U] = 196;
+		values[Ids.ID_BDQUO] = 8222;
+		values[Ids.ID_BETA_L] = 946;
+		values[Ids.ID_BETA_U] = 914;
+		values[Ids.ID_BRVBAR] = 166;
+		values[Ids.ID_BULL] = 8226;
+		values[Ids.ID_CAP] = 8745;
+		values[Ids.ID_CCEDIL_L] = 231;
+		values[Ids.ID_CCEDIL_U] = 199;
+		values[Ids.ID_CEDIL] = 184;
+		values[Ids.ID_CENT] = 162;
+		values[Ids.ID_CHI_L] = 967;
+		values[Ids.ID_CHI_U] = 935;
+		values[Ids.ID_CIRC] = 710;
+		values[Ids.ID_CLUBS] = 9827;
+		values[Ids.ID_CONG] = 8773;
+		values[Ids.ID_COPY] = 169;
+		values[Ids.ID_CRARR] = 8629;
+		values[Ids.ID_CUP] = 8746;
+		values[Ids.ID_CURREN] = 164;
+		values[Ids.ID_DAGGER_L] = 8224;
+		values[Ids.ID_DAGGER_U] = 8225;
+		values[Ids.ID_DARR_L] = 8595;
+		values[Ids.ID_DARR_U] = 8659;
+		values[Ids.ID_DEG] = 176;
+		values[Ids.ID_DELTA_L] = 948;
+		values[Ids.ID_DELTA_U] = 916;
+		values[Ids.ID_DIAMS] = 9830;
+		values[Ids.ID_DIVIDE] = 247;
+		values[Ids.ID_EACUTE_L] = 233;
+		values[Ids.ID_EACUTE_U] = 201;
+		values[Ids.ID_ECIRC_L] = 234;
+		values[Ids.ID_ECIRC_U] = 202;
+		values[Ids.ID_EGRAVE_L] = 232;
+		values[Ids.ID_EGRAVE_U] = 200;
+		values[Ids.ID_EMPTY] = 8709;
+		values[Ids.ID_EMSP] = 8195;
+		values[Ids.ID_ENSP] = 8194;
+		values[Ids.ID_EPSILON_L] = 949;
+		values[Ids.ID_EPSILON_U] = 917;
+		values[Ids.ID_EQUIV] = 8801;
+		values[Ids.ID_ETA_L] = 951;
+		values[Ids.ID_ETA_U] = 919;
+		values[Ids.ID_ETH_L] = 240;
+		values[Ids.ID_ETH_U] = 208;
+		values[Ids.ID_EUML_L] = 235;
+		values[Ids.ID_EUML_U] = 203;
+		values[Ids.ID_EURO] = 8364;
+		values[Ids.ID_EXIST] = 8707;
+		values[Ids.ID_FNOF] = 402;
+		values[Ids.ID_FORALL] = 8704;
+		values[Ids.ID_FRAC12] = 189;
+		values[Ids.ID_FRAC14] = 188;
+		values[Ids.ID_FRAC34] = 190;
+		values[Ids.ID_FRASL] = 8260;
+		values[Ids.ID_GAMMA_L] = 947;
+		values[Ids.ID_GAMMA_U] = 915;
+		values[Ids.ID_GE] = 8805;
+		values[Ids.ID_GT] = 62;
+		values[Ids.ID_HARR_L] = 8596;
+		values[Ids.ID_HARR_U] = 8660;
+		values[Ids.ID_HEARTS] = 9829;
+		values[Ids.ID_HELLIP] = 8230;
+		values[Ids.ID_IACUTE_L] = 237;
+		values[Ids.ID_IACUTE_U] = 205;
+		values[Ids.ID_ICIRC_L] = 238;
+		values[Ids.ID_ICIRC_U] = 206;
+		values[Ids.ID_IEXCL] = 161;
+		values[Ids.ID_IGRAVE_L] = 236;
+		values[Ids.ID_IGRAVE_U] = 204;
+		values[Ids.ID_IMAGE] = 8465;
+		values[Ids.ID_INFIN] = 8734;
+		values[Ids.ID_INT] = 8747;
+		values[Ids.ID_IOTA_L] = 953;
+		values[Ids.ID_IOTA_U] = 921;
+		values[Ids.ID_IQUEST] = 191;
+		values[Ids.ID_ISIN] = 8712;
+		values[Ids.ID_IUML_L] = 239;
+		values[Ids.ID_IUML_U] = 207;
+		values[Ids.ID_KAPPA_L] = 954;
+		values[Ids.ID_KAPPA_U] = 922;
+		values[Ids.ID_LAMBDA_L] = 955;
+		values[Ids.ID_LAMBDA_U] = 923;
+		values[Ids.ID_LANG] = 9001;
+		values[Ids.ID_LAQUO] = 171;
+		values[Ids.ID_LARR_L] = 8592;
+		values[Ids.ID_LARR_U] = 8656;
+		values[Ids.ID_LCEIL] = 8968;
+		values[Ids.ID_LDQUO] = 8220;
+		values[Ids.ID_LE] = 8804;
+		values[Ids.ID_LFLOOR] = 8970;
+		values[Ids.ID_LOWAST] = 8727;
+		values[Ids.ID_LOZ] = 9674;
+		values[Ids.ID_LRM] = 8206;
+		values[Ids.ID_LSAQUO] = 8249;
+		values[Ids.ID_LSQUO] = 8216;
+		values[Ids.ID_LT] = 60;
+		values[Ids.ID_MACR] = 175;
+		values[Ids.ID_MDASH] = 8212;
+		values[Ids.ID_MICRO] = 181;
+		values[Ids.ID_MIDDOT] = 183;
+		values[Ids.ID_MINUS] = 8722;
+		values[Ids.ID_MU_L] = 956;
+		values[Ids.ID_MU_U] = 924;
+		values[Ids.ID_NABLA] = 8711;
+		values[Ids.ID_NBSP] = 160;
+		values[Ids.ID_NDASH] = 8211;
+		values[Ids.ID_NE] = 8800;
+		values[Ids.ID_NI] = 8715;
+		values[Ids.ID_NOT] = 172;
+		values[Ids.ID_NOTIN] = 8713;
+		values[Ids.ID_NSUB] = 8836;
+		values[Ids.ID_NTILDE_L] = 241;
+		values[Ids.ID_NTILDE_U] = 209;
+		values[Ids.ID_NU_L] = 957;
+		values[Ids.ID_NU_U] = 925;
+		values[Ids.ID_OACUTE_L] = 243;
+		values[Ids.ID_OACUTE_U] = 211;
+		values[Ids.ID_OCIRC_L] = 244;
+		values[Ids.ID_OCIRC_U] = 212;
+		values[Ids.ID_OELIG_L] = 339;
+		values[Ids.ID_OELIG_U] = 338;
+		values[Ids.ID_OGRAVE_L] = 242;
+		values[Ids.ID_OGRAVE_U] = 210;
+		values[Ids.ID_OLINE] = 8254;
+		values[Ids.ID_OMEGA_L] = 969;
+		values[Ids.ID_OMEGA_U] = 937;
+		values[Ids.ID_OMICRON_L] = 959;
+		values[Ids.ID_OMICRON_U] = 927;
+		values[Ids.ID_OPLUS] = 8853;
+		values[Ids.ID_OR] = 8744;
+		values[Ids.ID_ORDF] = 170;
+		values[Ids.ID_ORDM] = 186;
+		values[Ids.ID_OSLASH_L] = 248;
+		values[Ids.ID_OSLASH_U] = 216;
+		values[Ids.ID_OTILDE_L] = 245;
+		values[Ids.ID_OTILDE_U] = 213;
+		values[Ids.ID_OTIMES] = 8855;
+		values[Ids.ID_OUML_L] = 246;
+		values[Ids.ID_OUML_U] = 214;
+		values[Ids.ID_PARA] = 182;
+		values[Ids.ID_PART] = 8706;
+		values[Ids.ID_PERMIL] = 8240;
+		values[Ids.ID_PERP] = 8869;
+		values[Ids.ID_PHI_L] = 966;
+		values[Ids.ID_PHI_U] = 934;
+		values[Ids.ID_PIV] = 982;
+		values[Ids.ID_PI_L] = 960;
+		values[Ids.ID_PI_U] = 928;
+		values[Ids.ID_PLUSMN] = 177;
+		values[Ids.ID_POUND] = 163;
+		values[Ids.ID_PRIME_L] = 8242;
+		values[Ids.ID_PRIME_U] = 8243;
+		values[Ids.ID_PROD] = 8719;
+		values[Ids.ID_PROP] = 8733;
+		values[Ids.ID_PSI_L] = 968;
+		values[Ids.ID_PSI_U] = 936;
+		values[Ids.ID_QUOT] = 34;
+		values[Ids.ID_RADIC] = 8730;
+		values[Ids.ID_RANG] = 9002;
+		values[Ids.ID_RAQUO] = 187;
+		values[Ids.ID_RARR_L] = 8594;
+		values[Ids.ID_RARR_U] = 8658;
+		values[Ids.ID_RCEIL] = 8969;
+		values[Ids.ID_RDQUO] = 8221;
+		values[Ids.ID_REAL] = 8476;
+		values[Ids.ID_REG] = 174;
+		values[Ids.ID_RFLOOR] = 8971;
+		values[Ids.ID_RHO_L] = 961;
+		values[Ids.ID_RHO_U] = 929;
+		values[Ids.ID_RLM] = 8207;
+		values[Ids.ID_RSAQUO] = 8250;
+		values[Ids.ID_RSQUO] = 8217;
+		values[Ids.ID_SBQUO] = 8218;
+		values[Ids.ID_SCARON_L] = 353;
+		values[Ids.ID_SCARON_U] = 352;
+		values[Ids.ID_SDOT] = 8901;
+		values[Ids.ID_SECT] = 167;
+		values[Ids.ID_SHY] = 173;
+		values[Ids.ID_SIGMAF] = 962;
+		values[Ids.ID_SIGMA_L] = 963;
+		values[Ids.ID_SIGMA_U] = 931;
+		values[Ids.ID_SIM] = 8764;
+		values[Ids.ID_SPADES] = 9824;
+		values[Ids.ID_SUB] = 8834;
+		values[Ids.ID_SUBE] = 8838;
+		values[Ids.ID_SUM] = 8721;
+		values[Ids.ID_SUP] = 8835;
+		values[Ids.ID_SUP1] = 185;
+		values[Ids.ID_SUP2] = 178;
+		values[Ids.ID_SUP3] = 179;
+		values[Ids.ID_SUPE] = 8839;
+		values[Ids.ID_SZLIG] = 223;
+		values[Ids.ID_TAU_L] = 964;
+		values[Ids.ID_TAU_U] = 932;
+		values[Ids.ID_THERE4] = 8756;
+		values[Ids.ID_THETASYM] = 977;
+		values[Ids.ID_THETA_L] = 952;
+		values[Ids.ID_THETA_U] = 920;
+		values[Ids.ID_THINSP] = 8201;
+		values[Ids.ID_THORN_L] = 254;
+		values[Ids.ID_THORN_U] = 222;
+		values[Ids.ID_TILDE] = 732;
+		values[Ids.ID_TIMES] = 215;
+		values[Ids.ID_TRADE] = 8482;
+		values[Ids.ID_UACUTE_L] = 250;
+		values[Ids.ID_UACUTE_U] = 218;
+		values[Ids.ID_UARR_L] = 8593;
+		values[Ids.ID_UARR_U] = 8657;
+		values[Ids.ID_UCIRC_L] = 251;
+		values[Ids.ID_UCIRC_U] = 219;
+		values[Ids.ID_UGRAVE_L] = 249;
+		values[Ids.ID_UGRAVE_U] = 217;
+		values[Ids.ID_UML] = 168;
+		values[Ids.ID_UPSIH] = 978;
+		values[Ids.ID_UPSILON_L] = 965;
+		values[Ids.ID_UPSILON_U] = 933;
+		values[Ids.ID_UUML_L] = 252;
+		values[Ids.ID_UUML_U] = 220;
+		values[Ids.ID_WEIERP] = 8472;
+		values[Ids.ID_XI_L] = 958;
+		values[Ids.ID_XI_U] = 926;
+		values[Ids.ID_YACUTE_L] = 253;
+		values[Ids.ID_YACUTE_U] = 221;
+		values[Ids.ID_YEN] = 165;
+		values[Ids.ID_YUML_L] = 255;
+		values[Ids.ID_YUML_U] = 376;
+		values[Ids.ID_ZETA_L] = 950;
+		values[Ids.ID_ZETA_U] = 918;
+		values[Ids.ID_ZWJ] = 8205;
+		values[Ids.ID_ZWNJ] = 8204;
+	}
+
+	/**
+	 */
+	public EntityCollection() {
+		super(names, STRICT_CASE);
+	}
+
+	/**
+	 * Create an entity declaration.
+	 * @return org.eclipse.wst.xml.core.internal.contentmodel.CMNode
+	 * @param attrName java.lang.String
+	 */
+	protected CMNode create(String entityName) {
+		int id = getID(entityName);
+		if (id == ID_UNKNOWN)
+			return null;
+
+		String value = String.valueOf(values[id]);
+		HTMLEntityDeclImpl dec = new HTMLEntityDeclImpl(entityName, value);
+
+		return dec;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HTMLAttrDeclImpl.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HTMLAttrDeclImpl.java
new file mode 100644
index 0000000..98ab2d9
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HTMLAttrDeclImpl.java
@@ -0,0 +1,118 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import org.eclipse.wst.html.core.internal.contentmodel.HTMLAttributeDeclaration;
+import org.eclipse.wst.html.core.internal.provisional.HTMLCMProperties;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ * Implementation class of {@link <code>HTMLAttributeDeclaration</code>} interface.<br>
+ */
+class HTMLAttrDeclImpl extends CMNodeImpl implements HTMLAttributeDeclaration {
+
+	private HTMLCMDataTypeImpl type = null;
+	private int usage = 0;
+
+	/**
+	 */
+	public HTMLAttrDeclImpl(String attrName, HTMLCMDataTypeImpl valueType, int valueUsage) {
+		super(attrName);
+		this.type = valueType;
+
+		switch (valueUsage) {
+			case OPTIONAL :
+			case REQUIRED :
+			case FIXED :
+			case PROHIBITED :
+				this.usage = valueUsage;
+				break;
+			default :
+				// should warn...
+				this.usage = OPTIONAL; // fall back
+				break;
+		}
+	}
+
+	/**
+	 * getAttrName method
+	 * @return java.lang.String
+	 */
+	public String getAttrName() {
+		return getNodeName();
+	}
+
+	/**
+	 * getAttrType method
+	 * @return CMDataType
+	 */
+	public CMDataType getAttrType() {
+		return type;
+	}
+
+	/**
+	 * @deprecated in superclass
+	 */
+	public String getDefaultValue() {
+		if (type.getImpliedValueKind() != CMDataType.IMPLIED_VALUE_DEFAULT)
+			return null;
+		return type.getImpliedValue();
+	}
+
+	/**
+	 * @deprecated in superclass
+	 */
+	public Enumeration getEnumAttr() {
+		Vector v = new Vector(Arrays.asList(type.getEnumeratedValues()));
+		return v.elements();
+	}
+
+	/**
+	 * getNodeType method
+	 * @return int
+	 *
+	 * Returns one of :
+	 * ELEMENT_DECLARATION, ATTRIBUTE_DECLARATION, GROUP, ENTITY_DECLARATION.
+	 */
+	public int getNodeType() {
+		return CMNode.ATTRIBUTE_DECLARATION;
+	}
+
+	/**
+	 * @return int
+	 */
+	public int getUsage() {
+		return usage;
+	}
+
+	/**
+	 */
+	public boolean supports(String propertyName) {
+		if (propertyName.equals(HTMLCMProperties.SHOULD_IGNORE_CASE))
+			return true;
+		return super.supports(propertyName);
+	}
+
+	/**
+	 */
+	public Object getProperty(String propertyName) {
+		if (propertyName.equals(HTMLCMProperties.SHOULD_IGNORE_CASE))
+			return new Boolean(true);
+		return super.getProperty(propertyName);
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HTMLCMDataTypeImpl.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HTMLCMDataTypeImpl.java
new file mode 100644
index 0000000..63366fd
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HTMLCMDataTypeImpl.java
@@ -0,0 +1,126 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+import org.eclipse.wst.html.core.internal.contentmodel.HTMLCMDataType;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+
+
+/**
+ */
+class HTMLCMDataTypeImpl extends CMNodeImpl implements HTMLCMDataType {
+
+	private int impliedValueKind = IMPLIED_VALUE_NONE;
+	private String impliedValue = null;
+	private final static String[] emptyArray = new String[0];
+	private String[] enumValues = emptyArray;
+	private String instanceValue = null;
+
+	/**
+	 * HTMLCMDataTypeImpl constructor comment.
+	 * @param nm java.lang.String
+	 */
+	public HTMLCMDataTypeImpl(String typeName) {
+		super(typeName);
+	}
+
+	/**
+	 * HTMLCMDataTypeImpl constructor comment.
+	 * @param nm java.lang.String
+	 */
+	public HTMLCMDataTypeImpl(String typeName, String instanceValue) {
+		super(typeName);
+		this.instanceValue = instanceValue;
+	}
+
+	/**
+	 * getTypeName method
+	 * @return java.lang.String
+	 *
+	 * This method returns a suitable default value that can be used when an instance of the data type is created.
+	 * This returns null of a suitable default is not available.
+	 */
+	public String generateInstanceValue() {
+		return instanceValue;
+	}
+
+	/**
+	 * @see org.eclipse.wst.xml.core.internal.contentmodel.CMDataType
+	 */
+	public String getDataTypeName() {
+		return getNodeName();
+	}
+
+	/**
+	 * getTypeName method
+	 * @return java.lang.String[]
+	 *
+	 */
+	public String[] getEnumeratedValues() {
+		return enumValues;
+	}
+
+	/**
+	 * getTypeName method
+	 * @return java.lang.String  
+	 *
+	 * Returns the implied value or null if none exists.
+	 */
+	public String getImpliedValue() {
+		return impliedValue;
+	}
+
+	/**
+	 * getImpliedValueKind method
+	 * @return int
+	 *
+	 * Returns one of :
+	 * IMPLIED_VALUE_NONE, IMPLIED_VALUE_FIXED, IMPLIED_VALUE_DEFAULT.
+	 */
+	public int getImpliedValueKind() {
+		return impliedValueKind;
+	}
+
+	/**
+	 * @see org.eclipse.wst.xml.core.internal.contentmodel.CMNode
+	 */
+	public int getNodeType() {
+		return CMNode.DATA_TYPE;
+	}
+
+	/**
+	 */
+	void setEnumValues(String[] values) {
+		enumValues = new String[values.length];
+		for (int i = 0; i < values.length; i++) {
+			enumValues[i] = values[i];
+		}
+	}
+
+	/**
+	 * package scope.
+	 */
+	void setImpliedValue(int kind, String value) {
+		switch (kind) {
+			case IMPLIED_VALUE_FIXED :
+			case IMPLIED_VALUE_DEFAULT :
+				impliedValueKind = kind;
+				impliedValue = value;
+				break;
+			case IMPLIED_VALUE_NONE :
+			default :
+				impliedValueKind = IMPLIED_VALUE_NONE;
+				impliedValue = null; // maybe a null string?
+				break;
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HTMLCMNode.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HTMLCMNode.java
new file mode 100644
index 0000000..b294b27
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HTMLCMNode.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+/**
+ * In HTML Documents, name and value of an attribute/element/entity
+ * should be treated ignoring theirs case.  However, in XML documents,
+ * they should be distinguished with sensitiveness of their case.
+ * CMNode is basically designed to represent DTDs or Schemas for XML
+ * documents.  So, it doesn't have interfaces to retrieve such information.
+ * However, declarations in the HTML CM should provide such information.
+ * This intermediate interface is intended to provide whether ignore cases
+ * or not.<br>
+ */
+interface HTMLCMNode extends org.eclipse.wst.xml.core.internal.contentmodel.CMNode {
+
+	/**
+	 * Returns <code>true</code>, if declaration is for HTML attribute/element/entity.
+	 * Otherwise, returns <code>false</code>.
+	 * @return boolean
+	 */
+	boolean shouldIgnoreCase();
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HTMLElemDeclImpl.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HTMLElemDeclImpl.java
new file mode 100644
index 0000000..c003526
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HTMLElemDeclImpl.java
@@ -0,0 +1,369 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import java.util.Iterator;
+
+import org.eclipse.wst.html.core.internal.contentmodel.HTMLAttributeDeclaration;
+import org.eclipse.wst.html.core.internal.contentmodel.HTMLElementDeclaration;
+import org.eclipse.wst.html.core.internal.contentmodel.HTMLPropertyDeclaration;
+import org.eclipse.wst.html.core.internal.provisional.HTMLCMProperties;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMContent;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ * Base class for all Hed???? classes.
+ */
+abstract class HTMLElemDeclImpl extends CMContentImpl implements HTMLElementDeclaration, HTMLPropertyDeclaration {
+
+	// DTD
+	protected CMNamedNodeMapImpl attributes = null;
+	protected String typeDefinitionName = ComplexTypeDefinitionFactory.CTYPE_EMPTY;
+	/** Never access this field directly.  Instead, use getComplexTypeDefinition method. */
+	private ComplexTypeDefinition typeDefinition = null;
+	protected CMGroupImpl inclusion = null;
+	protected CMGroupImpl exclusion = null;
+	// advanced information
+	protected CMNamedNodeMap prohibitedAncestors = null;
+	protected int correctionType = CORRECT_NONE;
+	protected int formatType = FORMAT_HTML;
+	protected int layoutType = LAYOUT_NONE;
+	protected int omitType = OMIT_NONE;
+	protected boolean keepSpaces = false;
+	protected boolean indentChild = false;
+	protected ElementCollection elementCollection = null;
+	protected AttributeCollection attributeCollection = null;
+	protected final static CMNamedNodeMap EMPTY_MAP = new CMNamedNodeMap() {
+		public int getLength() {
+			return 0;
+		}
+
+		public CMNode getNamedItem(String name) {
+			return null;
+		}
+
+		public CMNode item(int index) {
+			return null;
+		}
+
+		public Iterator iterator() {
+			return new Iterator() {
+				public boolean hasNext() {
+					return false;
+				}
+
+				public Object next() {
+					return null;
+				}
+
+				public void remove() {
+				}
+			};
+		}
+	};
+
+	/**
+	 * HTMLElemDeclImpl constructor.
+	 * In the HTML DTD, an element declaration has no specification
+	 * for its occurrence.  Occurrence is specifed in content model, like
+	 * <code>(LI)+</code>.  To avoid confusion (and complexity),
+	 * occurrence of an element declaration is always 1 (it means, min = 1 and
+	 * max = 1).  Instead, occurrence of CMGroup represents actual occurrence
+	 * of the content.
+	 * <br>
+	 * @param name java.lang.String
+	 */
+	public HTMLElemDeclImpl(String elementName, ElementCollection collection) {
+		super(elementName, 1, 1);
+		elementCollection = collection;
+		attributeCollection = collection.getAttributeCollection();
+	}
+
+	/**
+	 */
+	protected abstract void createAttributeDeclarations();
+
+	private ComplexTypeDefinition createComplexTypeDefinition() {
+		if (typeDefinitionName.equals(ComplexTypeDefinitionFactory.CTYPE_CDATA) || typeDefinitionName.equals(ComplexTypeDefinitionFactory.CTYPE_EMPTY) || typeDefinitionName.equals(ComplexTypeDefinitionFactory.CTYPE_PCDATA))
+			return null;
+
+		ComplexTypeDefinitionFactory factory = ComplexTypeDefinitionFactory.getInstance();
+		if (factory == null)
+			return null; // fatal error.
+
+		ComplexTypeDefinition def = factory.createTypeDefinition(typeDefinitionName, elementCollection);
+		return def;
+	}
+
+	/**
+	 * Get an attribute declaration.
+	 */
+	public HTMLAttributeDeclaration getAttributeDeclaration(String attrName) {
+		if (attributes == null) {
+			createAttributeDeclarations();
+			if (attributes == null)
+				return null; // fail to create
+		}
+
+		CMNode cmnode = attributes.getNamedItem(attrName);
+		if (cmnode == null) {
+			return null;
+		}
+		else {
+			return (HTMLAttributeDeclaration) cmnode; // already exists.
+		}
+	}
+
+	/**
+	 * @see org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration
+	 */
+	public CMNamedNodeMap getAttributes() {
+		if (attributes == null)
+			createAttributeDeclarations(); // lazy eval.
+		return attributes;
+	}
+
+	/**
+	 * Get an instance of complex type definition.
+	 */
+	private ComplexTypeDefinition getComplexTypeDefinition() {
+		if (typeDefinition == null)
+			typeDefinition = createComplexTypeDefinition();
+		return typeDefinition;
+	}
+
+	/**
+	 * Content.<br>
+	 * Element declarations which type is EMPTY or CDATA (maybe PCDATA)
+	 * <strong>MUST</strong> override this method and always return null.
+	 * This default implementation always tries to create a complex type definition
+	 * instance and access to it.
+	 * <br>
+	 * @see org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration
+	 */
+	public CMContent getContent() {
+		ComplexTypeDefinition def = getComplexTypeDefinition(); // lazy eval.
+		return (def != null) ? def.getContent() : null;
+	}
+
+	/**
+	 * Content type.<br>
+	 * Element declarations which type is EMPTY or CDATA (maybe PCDATA)
+	 * <strong>MUST</strong> override this method and return an appropriate type.
+	 * This default implementation always tries to create a complex type definition
+	 * instance and access to it.
+	 * <br>
+	 * @see org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration
+	 */
+	public int getContentType() {
+		ComplexTypeDefinition def = getComplexTypeDefinition(); // lazy eval.
+		return (def != null) ? def.getContentType() : CMElementDeclaration.CDATA;
+	}
+
+	/**
+	 * @see HTMLElementDeclaration#getCorrectionType
+	 */
+	public int getCorrectionType() {
+		return correctionType;
+	}
+
+	/**
+	 * HTML element doesn't have any data type.  So, this method always
+	 * returns <code>null</code>.<br>
+	 * @see org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration
+	 */
+	public CMDataType getDataType() {
+		return null;
+	}
+
+	/**
+	 * @see org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration
+	 */
+	public String getElementName() {
+		return getNodeName();
+	}
+
+	/**
+	 * Exclusion.
+	 * Almost elements don't have a exclusion.
+	 * Only classes those have exclusion should override this method.
+	 */
+	public CMContent getExclusion() {
+		return null;
+	}
+
+	/**
+	 * Default format type is <code>FORMAT_HTML</code>.<br>
+	 */
+	public int getFormatType() {
+		return formatType;
+	}
+
+	/**
+	 * Inclusion.
+	 * Almost elements don't have a inclusion.
+	 * Only classes those have inclusion should override this method.
+	 */
+	public CMContent getInclusion() {
+		return null;
+	}
+
+	/**
+	 */
+	public int getLayoutType() {
+		return layoutType;
+	}
+
+	/**
+	 * Line break hint is strongly related to layout type.
+	 * Indeed, in the C++DOM, it is determined from layout type only.
+	 * So, this implementation, as the default implementation for all declarations,
+	 * also determines from layout type only.<br>
+	 * @return int
+	 */
+	public int getLineBreakHint() {
+		switch (getLayoutType()) {
+			case HTMLElementDeclaration.LAYOUT_BLOCK :
+				return HTMLElementDeclaration.BREAK_BEFORE_START_AND_AFTER_END;
+			case HTMLElementDeclaration.LAYOUT_BREAK :
+				return HTMLElementDeclaration.BREAK_AFTER_START;
+			case HTMLElementDeclaration.LAYOUT_HIDDEN :
+				return HTMLElementDeclaration.BREAK_BEFORE_START_AND_AFTER_END;
+			default :
+				return HTMLElementDeclaration.BREAK_NONE;
+		}
+	}
+
+	/**
+	 * No HTML element has local elements.  So, this method always
+	 * returns an empty map.
+	 * @see org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration
+	 */
+	public CMNamedNodeMap getLocalElements() {
+		return EMPTY_MAP;
+	}
+
+	/**
+	 * @see org.eclipse.wst.xml.core.internal.contentmodel.CMNode
+	 */
+	public int getNodeType() {
+		return CMNode.ELEMENT_DECLARATION;
+	}
+
+	/**
+	 */
+	public int getOmitType() {
+		return omitType;
+	}
+
+	/**
+	 */
+	public CMNamedNodeMap getProhibitedAncestors() {
+		return EMPTY_MAP;
+	}
+
+	/**
+	 */
+	public boolean supports(String propertyName) {
+		if (propertyName.equals(HTMLCMProperties.SHOULD_IGNORE_CASE)) {
+			return true;
+		}
+		else if (propertyName.equals(HTMLCMProperties.CONTENT_HINT)) {
+			ComplexTypeDefinition def = getComplexTypeDefinition();
+			return (def != null);
+		}
+		else {
+			PropertyProvider pp = PropertyProviderFactory.getProvider(propertyName);
+			if (pp == null)
+				return false;
+			return pp.supports(this);
+		}
+
+	}
+
+	/**
+	 */
+	public Object getProperty(String propertyName) {
+		if (propertyName.equals(HTMLCMProperties.SHOULD_IGNORE_CASE)) {
+			return new Boolean(true);
+		}
+		else if (propertyName.equals(HTMLCMProperties.CONTENT_HINT)) {
+			ComplexTypeDefinition def = getComplexTypeDefinition();
+			return (def != null) ? def.getPrimaryCandidate() : null;
+		}
+		else {
+			PropertyProvider pp = PropertyProviderFactory.getProvider(propertyName);
+			if (pp == null)
+				return null;
+			return pp.get(this);
+		}
+	}
+
+	/**
+	 * Return element names which terminates this element.<br>
+	 * @return java.util.Iterator
+	 */
+	protected Iterator getTerminators() {
+		return null;
+	}
+
+	/**
+	 * return true when the element is a JSP element.
+	 */
+	public boolean isJSP() {
+		return false;
+	}
+
+	/**
+	 * In some elements, such as APPLET, a source generator should indent child
+	 * elements that their parents.  That is, a source generator should generate
+	 * source  of APPLET and PARAMS like this:
+	 * <PRE>
+	 *   &lt;APPLET ...&gt;
+	 *     &lt;PARAM ... &gt;
+	 *     &lt;PARAM ... &gt;
+	 *   &lt;/APPLET&gt;
+	 * <PRE>
+	 * @return boolean
+	 */
+	public boolean shouldIndentChildSource() {
+		return indentChild;
+	}
+
+	/**
+	 * Most of elements can compact spaces in their child text nodes.
+	 * Some special elements should keep them in their source.
+	 * @return boolean
+	 */
+	public boolean shouldKeepSpaces() {
+		return keepSpaces;
+	}
+
+	/**
+	 * @return boolean
+	 */
+	public boolean shouldTerminateAt(HTMLElementDeclaration nextElement) {
+		Iterator i = getTerminators();
+		if (i == null)
+			return false;
+		String nextName = nextElement.getElementName();
+		while (i.hasNext()) {
+			if (nextName.equals(i.next()))
+				return true;
+		}
+		return false;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HTMLEntityDeclImpl.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HTMLEntityDeclImpl.java
new file mode 100644
index 0000000..1a47b01
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HTMLEntityDeclImpl.java
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+import org.eclipse.wst.html.core.internal.contentmodel.HTMLEntityDeclaration;
+import org.eclipse.wst.html.core.internal.provisional.HTMLCMProperties;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+
+
+/**
+ */
+class HTMLEntityDeclImpl extends CMNodeImpl implements HTMLEntityDeclaration {
+
+	private java.lang.String value = null;
+
+	/**
+	 * CMEntityDeclImpl constructor comment.
+	 * @param entityName java.lang.String; Entity name.
+	 * @param entityValue java.lang.String; Value string.
+	 */
+	public HTMLEntityDeclImpl(String entityName, String entityValue) {
+		super(entityName);
+		value = entityValue;
+	}
+
+	/**
+	 * getName method
+	 * @return java.lang.String
+	 */
+	public String getName() {
+		return getNodeName();
+	}
+
+	/**
+	 * Get CMNode type.<br>
+	 * @return int; Always return ENTITY_DECLARATION.
+	 */
+	public int getNodeType() {
+		return CMNode.ENTITY_DECLARATION;
+	}
+
+	/**
+	 * getValue method
+	 * @return java.lang.String
+	 */
+	public String getValue() {
+		return value;
+	}
+
+	/**
+	 */
+	public boolean supports(String propertyName) {
+		if (propertyName.equals(HTMLCMProperties.SHOULD_IGNORE_CASE))
+			return true;
+		return super.supports(propertyName);
+	}
+
+	/**
+	 * Entities in HTML documents are always treated with ignoring cases.
+	 * Because no special entities are defined in JSP 1.0, this method
+	 * can always return <code>true</code>.<br>
+	 */
+	public Object getProperty(String propertyName) {
+		if (propertyName.equals(HTMLCMProperties.SHOULD_IGNORE_CASE))
+			return new Boolean(true);
+		return super.getProperty(propertyName);
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedA.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedA.java
new file mode 100644
index 0000000..f603c37
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedA.java
@@ -0,0 +1,98 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import java.util.Arrays;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMContent;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ * A.
+ */
+final class HedA extends HedInlineContainer {
+
+	/**
+	 */
+	public HedA(ElementCollection collection) {
+		super(CHTMLNamespace.ElementName.A, collection);
+		// CORRECT_EMPTY - GROUP_COMPACT
+		correctionType = CORRECT_EMPTY;
+	}
+
+	/**
+	 * %attrs;
+	 * (charset %Charset; #IMPLIED)
+	 * (type %ContentType; #IMPLIED)
+	 * (name CDATA #IMPLIED)
+	 * (href %URI; #IMPLIED)
+	 * (hreflang %LanguageCode; #IMPLIED)
+	 * (target %FrameTarget; #IMPLIED)
+	 * (rel %LinkTypes; #IMPLIED)
+	 * (rev %LinkTypes; #IMPLIED)
+	 * (accesskey %Character; #IMPLIED)
+	 * (directkey %Character; #IMPLIED)
+	 * (shape %Shape; rect)
+	 * (coords %Coords; #IMPLIED)
+	 * (tabindex NUMBER #IMPLIED)
+	 * (onfocus %Script; #IMPLIED)
+	 * (onblur %Script; #IMPLIED) 
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+
+		String[] names = {CHTMLNamespace.ATTR_NAME_NAME, CHTMLNamespace.ATTR_NAME_HREF,};
+		attributeCollection.getDeclarations(attributes, Arrays.asList(names).iterator());
+	}
+
+	/**
+	 * Exclusion.
+	 * <code>A</code> has the exclusion.
+	 * It is <code>A</code> itself.
+	 */
+	public CMContent getExclusion() {
+		if (exclusion != null)
+			return exclusion; // already created.
+		if (elementCollection == null)
+			return null;
+
+		exclusion = new CMGroupImpl(CMGroup.CHOICE, 1, 1);
+		CMNode a = elementCollection.getNamedItem(CHTMLNamespace.ElementName.A);
+		if (a != null)
+			exclusion.appendChild(a);
+
+		return exclusion;
+	}
+
+	/**
+	 */
+	public CMNamedNodeMap getProhibitedAncestors() {
+		if (prohibitedAncestors != null)
+			return prohibitedAncestors;
+
+		String[] names = {CHTMLNamespace.ElementName.A,};
+		prohibitedAncestors = elementCollection.getDeclarations(names);
+
+		return prohibitedAncestors;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedADDRESS.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedADDRESS.java
new file mode 100644
index 0000000..36a72f2
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedADDRESS.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+
+/**
+ * ADDRESS.
+ */
+final class HedADDRESS extends HTMLElemDeclImpl {
+
+	/**
+	 */
+	public HedADDRESS(ElementCollection collection) {
+		super(CHTMLNamespace.ElementName.ADDRESS, collection);
+		typeDefinitionName = ComplexTypeDefinitionFactory.CTYPE_ADDRESS;
+		correctionType = CORRECT_EMPTY;
+		layoutType = LAYOUT_BLOCK;
+	}
+
+	/**
+	 * %attrs;
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+	}
+
+	/**
+	 */
+	public CMNamedNodeMap getProhibitedAncestors() {
+		if (prohibitedAncestors != null)
+			return prohibitedAncestors;
+
+		String[] names = {CHTMLNamespace.ElementName.DIR, CHTMLNamespace.ElementName.MENU};
+		prohibitedAncestors = elementCollection.getDeclarations(names);
+
+		return prohibitedAncestors;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedBASE.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedBASE.java
new file mode 100644
index 0000000..f33abe0
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedBASE.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import java.util.Arrays;
+
+/**
+ * BASE.
+ */
+final class HedBASE extends HedEmpty {
+
+	/**
+	 */
+	public HedBASE(ElementCollection collection) {
+		super(CHTMLNamespace.ElementName.BASE, collection);
+		// LAYOUT_HIDDEN.
+		// Because, BASE is GROUP_HIDDEN in the C++DOM/DTDParser.cpp.
+		layoutType = LAYOUT_HIDDEN;
+	}
+
+	/**
+	 * BASE.
+	 * (href %URI; #IMPLIED)
+	 * (target %FrameTarget; #IMPLIED)
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		String[] names = {CHTMLNamespace.ATTR_NAME_HREF,};
+		attributeCollection.getDeclarations(attributes, Arrays.asList(names).iterator());
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedBLOCKQUOTE.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedBLOCKQUOTE.java
new file mode 100644
index 0000000..5aef97b
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedBLOCKQUOTE.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+
+/**
+ * BLOCKQUOTE.
+ */
+final class HedBLOCKQUOTE extends HedFlowContainer {
+
+	/**
+	 */
+	public HedBLOCKQUOTE(ElementCollection collection) {
+		super(CHTMLNamespace.ElementName.BLOCKQUOTE, collection);
+		correctionType = CORRECT_EMPTY;
+		layoutType = LAYOUT_BLOCK;
+	}
+
+	/**
+	 * %attrs;
+	 * (cite %URI; #IMPLIED) 
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+	}
+
+	/**
+	 */
+	public CMNamedNodeMap getProhibitedAncestors() {
+		if (prohibitedAncestors != null)
+			return prohibitedAncestors;
+
+		String[] names = {CHTMLNamespace.ElementName.DIR, CHTMLNamespace.ElementName.MENU};
+		prohibitedAncestors = elementCollection.getDeclarations(names);
+
+		return prohibitedAncestors;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedBODY.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedBODY.java
new file mode 100644
index 0000000..7483c58
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedBODY.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import java.util.Arrays;
+import java.util.Iterator;
+
+/**
+ * BODY.
+ */
+final class HedBODY extends HedFlowContainer {
+
+	private static String[] terminators = {CHTMLNamespace.ElementName.HEAD, CHTMLNamespace.ElementName.BODY, CHTMLNamespace.ElementName.HTML};
+
+	/**
+	 */
+	public HedBODY(ElementCollection collection) {
+		super(CHTMLNamespace.ElementName.BODY, collection);
+		layoutType = LAYOUT_BLOCK;
+		omitType = OMIT_BOTH;
+	}
+
+	/**
+	 * %attrs;
+	 * %bodycolors;
+	 * (onload %Script; #IMPLIED)
+	 * (onunload %Script; #IMPLIED)
+	 * (background %URI; #IMPLIED)
+	 * (marginwidth %Pixels; #IMPLIED) ... D205514
+	 * (marginheight %Pixels; #IMPLIED) .. D205514
+	 * (topmargin, CDATA, #IMPLIED) ...... D205514
+	 * (bottommargin, CDATA, #IMPLIED) ... D205514
+	 * (leftmargin, CDATA, #IMPLIED) ..... D205514
+	 * (rightmargin, CDATA, #IMPLIED) .... D205514
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+		// %bodycolors;
+		attributeCollection.getBodycolors(attributes);
+
+	}
+
+	/**
+	 * BODY has terminators.
+	 * @return java.util.Iterator
+	 */
+	protected Iterator getTerminators() {
+		return Arrays.asList(terminators).iterator();
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedBR.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedBR.java
new file mode 100644
index 0000000..3ec16f5
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedBR.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+import org.eclipse.wst.html.core.internal.contentmodel.HTMLAttributeDeclaration;
+
+
+
+/**
+ * BR.
+ */
+final class HedBR extends HedEmpty {
+
+	/**
+	 */
+	public HedBR(ElementCollection collection) {
+		super(CHTMLNamespace.ElementName.BR, collection);
+		// LAYOUT_BREAK.
+		// Because, BR is GROUP_BREAK in the C++DOM/DTDParser.cpp.
+		layoutType = LAYOUT_BREAK;
+	}
+
+	/**
+	 * BR.
+	 * %coreattrs;
+	 * (clear (left | all | right | none) none)
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %coreattrs;
+		attributeCollection.getCore(attributes);
+		// clear
+		HTMLAttributeDeclaration attr = attributeCollection.getDeclaration(CHTMLNamespace.ATTR_NAME_CLEAR);
+		if (attr != null)
+			attributes.putNamedItem(CHTMLNamespace.ATTR_NAME_CLEAR, attr);
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedCENTER.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedCENTER.java
new file mode 100644
index 0000000..7693933
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedCENTER.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+
+/**
+ * CENTER.
+ */
+final class HedCENTER extends HedFlowContainer {
+
+	/**
+	 */
+	public HedCENTER(ElementCollection collection) {
+		super(CHTMLNamespace.ElementName.CENTER, collection);
+		layoutType = LAYOUT_BLOCK;
+	}
+
+	/**
+	 * %attrs;
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+	}
+
+	/**
+	 */
+	public CMNamedNodeMap getProhibitedAncestors() {
+		if (prohibitedAncestors != null)
+			return prohibitedAncestors;
+
+		String[] names = {CHTMLNamespace.ElementName.DIR, CHTMLNamespace.ElementName.MENU};
+		prohibitedAncestors = elementCollection.getDeclarations(names);
+
+		return prohibitedAncestors;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedDD.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedDD.java
new file mode 100644
index 0000000..dd70e26
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedDD.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import java.util.Arrays;
+import java.util.Iterator;
+
+/**
+ * DD.
+ */
+final class HedDD extends HedFlowContainer {
+
+	private static String[] terminators = {CHTMLNamespace.ElementName.DT, CHTMLNamespace.ElementName.DD};
+
+	/**
+	 */
+	public HedDD(ElementCollection collection) {
+		super(CHTMLNamespace.ElementName.DD, collection);
+		correctionType = CORRECT_EMPTY;
+		layoutType = LAYOUT_BLOCK;
+		omitType = OMIT_END_DEFAULT;
+	}
+
+	/**
+	 * %attrs;
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+	}
+
+	/**
+	 * DD has terminators.
+	 * @return java.util.Iterator
+	 */
+	protected Iterator getTerminators() {
+		return Arrays.asList(terminators).iterator();
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedDIV.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedDIV.java
new file mode 100644
index 0000000..8e2d794
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedDIV.java
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+
+/**
+ * DIV.
+ */
+final class HedDIV extends HedFlowContainer {
+
+	/**
+	 */
+	public HedDIV(ElementCollection collection) {
+		super(CHTMLNamespace.ElementName.DIV, collection);
+		layoutType = LAYOUT_BLOCK;
+	}
+
+	/**
+	 * %attrs;
+	 * %align;
+	 * %reserved;
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+		// %align;
+		HTMLAttrDeclImpl attr = AttributeCollection.createAlignForParagraph();
+		if (attr != null)
+			attributes.putNamedItem(CHTMLNamespace.ATTR_NAME_ALIGN, attr);
+		// %reserved; ... empty
+	}
+
+	/**
+	 */
+	public CMNamedNodeMap getProhibitedAncestors() {
+		if (prohibitedAncestors != null)
+			return prohibitedAncestors;
+
+		String[] names = {CHTMLNamespace.ElementName.DIR, CHTMLNamespace.ElementName.MENU};
+		prohibitedAncestors = elementCollection.getDeclarations(names);
+
+		return prohibitedAncestors;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedDL.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedDL.java
new file mode 100644
index 0000000..1746bb2
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedDL.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+
+/**
+ * DL.
+ */
+final class HedDL extends HTMLElemDeclImpl {
+
+	/**
+	 */
+	public HedDL(ElementCollection collection) {
+		super(CHTMLNamespace.ElementName.DL, collection);
+		typeDefinitionName = ComplexTypeDefinitionFactory.CTYPE_DEFINITION_LIST;
+		correctionType = CORRECT_EMPTY;
+		layoutType = LAYOUT_BLOCK;
+		indentChild = true;
+	}
+
+	/**
+	 * %arrays;
+	 * (compact (compact) #IMPLIED)
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+
+	}
+
+	/**
+	 */
+	public CMNamedNodeMap getProhibitedAncestors() {
+		if (prohibitedAncestors != null)
+			return prohibitedAncestors;
+
+		String[] names = {CHTMLNamespace.ElementName.DIR, CHTMLNamespace.ElementName.MENU};
+		prohibitedAncestors = elementCollection.getDeclarations(names);
+
+		return prohibitedAncestors;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedDT.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedDT.java
new file mode 100644
index 0000000..933d877
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedDT.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import java.util.Arrays;
+import java.util.Iterator;
+
+/**
+ * DT.
+ */
+final class HedDT extends HedInlineContainer {
+
+	private static String[] terminators = {CHTMLNamespace.ElementName.DT, CHTMLNamespace.ElementName.DD};
+
+	/**
+	 */
+	public HedDT(ElementCollection collection) {
+		super(CHTMLNamespace.ElementName.DT, collection);
+		correctionType = CORRECT_EMPTY;
+		layoutType = LAYOUT_BLOCK;
+		omitType = OMIT_END_DEFAULT;
+	}
+
+	/**
+	 * %attrs;
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+	}
+
+	/**
+	 * DT has terminators.
+	 * @return java.util.Iterator
+	 */
+	protected Iterator getTerminators() {
+		return Arrays.asList(terminators).iterator();
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedEmpty.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedEmpty.java
new file mode 100644
index 0000000..c6de6e0
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedEmpty.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMContent;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+
+/**
+ * Base class for EMPTY type element declarations.
+ */
+abstract class HedEmpty extends HTMLElemDeclImpl {
+
+	/**
+	 */
+	public HedEmpty(String elementName, ElementCollection collection) {
+		super(elementName, collection);
+		typeDefinitionName = ComplexTypeDefinitionFactory.CTYPE_EMPTY;
+		// EMPTY type has no end tag.
+		omitType = OMIT_END_MUST;
+	}
+
+	/**
+	 * Content.<br>
+	 * EMPTY type always returns <code>null</code>.
+	 * <br>
+	 * @return org.eclipse.wst.xml.core.internal.contentmodel.CMContent
+	 */
+	public CMContent getContent() {
+		return null;
+	}
+
+	/**
+	 * Content type.<br>
+	 * @see org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration
+	 */
+	public int getContentType() {
+		return CMElementDeclaration.EMPTY;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedFORM.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedFORM.java
new file mode 100644
index 0000000..090d61a
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedFORM.java
@@ -0,0 +1,91 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import java.util.Arrays;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMContent;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ * FORM.
+ */
+final class HedFORM extends HedFlowContainer {
+
+	/**
+	 */
+	public HedFORM(ElementCollection collection) {
+		super(CHTMLNamespace.ElementName.FORM, collection);
+		layoutType = LAYOUT_BLOCK;
+	}
+
+	/**
+	 * %attrs;
+	 * (action %URI; #REQUIRED)
+	 * (method (GET|POST) GET)
+	 * (enctype %ContentType; "application/x-www-form-urlencoded")
+	 * (accept %ContentTypes; #IMPLIED)
+	 * (name CDATA #IMPLIED)
+	 * (onsubmit %Script; #IMPLIED)
+	 * (onreset %Script; #IMPLIED)
+	 * (target %FrameTarget; #IMPLIED)
+	 * (accept-charset %Charsets; #IMPLIED)
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+
+		String[] names = {CHTMLNamespace.ATTR_NAME_ACTION, CHTMLNamespace.ATTR_NAME_METHOD, CHTMLNamespace.ATTR_NAME_ENCTYPE, CHTMLNamespace.ATTR_NAME_NAME,};
+		attributeCollection.getDeclarations(attributes, Arrays.asList(names).iterator());
+	}
+
+	/**
+	 * Exclusion.
+	 * <code>FORM</code> has the exclusion.
+	 * It is <code>FORM</code> itself.
+	 */
+	public CMContent getExclusion() {
+		if (exclusion != null)
+			return exclusion; // already created.
+		if (elementCollection == null)
+			return null; // fatal
+
+		exclusion = new CMGroupImpl(CMGroup.CHOICE, 1, 1);
+		CMNode form = elementCollection.getNamedItem(CHTMLNamespace.ElementName.FORM);
+		if (form != null)
+			exclusion.appendChild(form);
+
+		return exclusion;
+	}
+
+	/**
+	 */
+	public CMNamedNodeMap getProhibitedAncestors() {
+		if (prohibitedAncestors != null)
+			return prohibitedAncestors;
+
+		String[] names = {CHTMLNamespace.ElementName.DIR, CHTMLNamespace.ElementName.FORM, CHTMLNamespace.ElementName.MENU};
+		prohibitedAncestors = elementCollection.getDeclarations(names);
+
+		return prohibitedAncestors;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedFlowContainer.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedFlowContainer.java
new file mode 100644
index 0000000..8c48416
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedFlowContainer.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+/**
+ * Base class for (%flow;)* containers.
+ */
+abstract class HedFlowContainer extends HTMLElemDeclImpl {
+
+	/**
+	 */
+	public HedFlowContainer(String elementName, ElementCollection collection) {
+		super(elementName, collection);
+		typeDefinitionName = ComplexTypeDefinitionFactory.CTYPE_FLOW_CONTAINER;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedHEAD.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedHEAD.java
new file mode 100644
index 0000000..e8ef6f9
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedHEAD.java
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import java.util.Arrays;
+import java.util.Iterator;
+
+/**
+ * HTML.
+ */
+final class HedHEAD extends HTMLElemDeclImpl {
+
+	private static String[] terminators = {CHTMLNamespace.ElementName.HEAD, CHTMLNamespace.ElementName.BODY, CHTMLNamespace.ElementName.HTML};
+
+	/**
+	 */
+	public HedHEAD(ElementCollection collection) {
+		super(CHTMLNamespace.ElementName.HEAD, collection);
+		typeDefinitionName = ComplexTypeDefinitionFactory.CTYPE_HEAD;
+		layoutType = LAYOUT_HIDDEN;
+		omitType = OMIT_BOTH;
+	}
+
+	/**
+	 * Create all attribute declarations.
+	 * This method is called once in the constructor of the super class.
+	 * The <code>HEAD</code> element may have the following attributes:
+	 * <table>
+	 * <tbody>
+	 *   <tr>
+	 *     <th>NAME</th><th>TYPE</th><th>USAGE</th><th>DEFAULT (INITIAL) VALUE</th><th>MEMO</th>
+	 *   </tr>
+	 *   <tr>
+	 *     <td>%i18n;</td><td>-</td><td>-</td><td>-</td><td>-</td>
+	 *   </tr>
+	 *   <tr>
+	 *     <td>profile</td><td>URI</td><td>#IMPLIED</td><td>N/A</td><td>-</td>
+	 *   </tr>
+	 * </tbody>
+	 * </table>
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %i18n;
+		attributeCollection.getI18n(attributes);
+	}
+
+	/**
+	 * HEAD has terminators.
+	 * @return java.util.Iterator
+	 */
+	protected Iterator getTerminators() {
+		return Arrays.asList(terminators).iterator();
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedHR.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedHR.java
new file mode 100644
index 0000000..732d095
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedHR.java
@@ -0,0 +1,75 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import java.util.Arrays;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+
+/**
+ * HR.
+ */
+final class HedHR extends HedEmpty {
+
+	/**
+	 */
+	public HedHR(ElementCollection collection) {
+		super(CHTMLNamespace.ElementName.HR, collection);
+		layoutType = LAYOUT_BLOCK;
+	}
+
+	/**
+	 * %attrs
+	 * (align (left|center|right) #IMPLIED) ... should be defined locally.
+	 * (noshade (noshade) #IMPLIED)
+	 * (size %Pixels; #IMPLIED)
+	 * (width %Length; #IMPLIED)
+	 * (color %Color; #IMPLIED) ... D205514
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+
+		// (align (left|center|right) #IMPLIED) ... should be defined locally.
+		HTMLCMDataTypeImpl atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+		String[] values = {CHTMLNamespace.ATTR_VALUE_LEFT, CHTMLNamespace.ATTR_VALUE_CENTER, CHTMLNamespace.ATTR_VALUE_RIGHT};
+		atype.setEnumValues(values);
+		HTMLAttrDeclImpl attr = new HTMLAttrDeclImpl(CHTMLNamespace.ATTR_NAME_ALIGN, atype, CMAttributeDeclaration.OPTIONAL);
+		attributes.putNamedItem(CHTMLNamespace.ATTR_NAME_ALIGN, attr);
+
+		// the rest.
+		String[] names = {CHTMLNamespace.ATTR_NAME_NOSHADE, CHTMLNamespace.ATTR_NAME_SIZE, CHTMLNamespace.ATTR_NAME_WIDTH,};
+		attributeCollection.getDeclarations(attributes, Arrays.asList(names).iterator());
+	}
+
+	/**
+	 */
+	public CMNamedNodeMap getProhibitedAncestors() {
+		if (prohibitedAncestors != null)
+			return prohibitedAncestors;
+
+		String[] names = {CHTMLNamespace.ElementName.DIR, CHTMLNamespace.ElementName.MENU};
+		prohibitedAncestors = elementCollection.getDeclarations(names);
+
+		return prohibitedAncestors;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedHTML.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedHTML.java
new file mode 100644
index 0000000..36c2e4a
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedHTML.java
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import java.util.Arrays;
+import java.util.Iterator;
+
+import org.eclipse.wst.html.core.internal.contentmodel.HTMLAttributeDeclaration;
+
+
+/**
+ * HTML.
+ */
+final class HedHTML extends HTMLElemDeclImpl {
+
+	private static String[] terminators = {CHTMLNamespace.ElementName.HTML};
+
+	/**
+	 */
+	public HedHTML(ElementCollection collection) {
+		super(CHTMLNamespace.ElementName.HTML, collection);
+		typeDefinitionName = ComplexTypeDefinitionFactory.CTYPE_HTML;
+		layoutType = LAYOUT_HIDDEN;
+		omitType = OMIT_BOTH;
+	}
+
+	/**
+	 * Create all attribute declarations.
+	 * This method is called once in the constructor of the super class.
+	 * The <code>HTML</code> element may have the following attributes:
+	 * <table>
+	 * <tbody>
+	 *   <tr>
+	 *     <th>NAME</th><th>TYPE</th><th>USAGE</th><th>DEFAULT (INITIAL) VALUE</th><th>MEMO</th>
+	 *   </tr>
+	 *   <tr>
+	 *     <td><code>%i18n;</code></td><td>-</td><td>-</td><td>-</td>
+	 *     <td>{@link PDCMDocImpl#getAttrDeclarationsI18n}</td>
+	 *   </tr>
+	 *   <tr>
+	 *     <td>version</td><td>CDATA</td><td>#FIXED</td>
+	 *     <td>{@link HTML_VERSION_TRANSITIONAL}</td><td>deplecated in HTML4.01</td>
+	 *   </tr>
+	 * </tbody>
+	 * </table><br>
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %i18n;
+		attributeCollection.getI18n(attributes);
+		// version
+		HTMLAttributeDeclaration adec = attributeCollection.getDeclaration(CHTMLNamespace.ATTR_NAME_VERSION);
+		if (adec != null)
+			attributes.putNamedItem(CHTMLNamespace.ATTR_NAME_VERSION, adec);
+	}
+
+	/**
+	 * HTML has terminators.
+	 * @return java.util.Iterator
+	 */
+	protected Iterator getTerminators() {
+		return Arrays.asList(terminators).iterator();
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedHeading.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedHeading.java
new file mode 100644
index 0000000..af3be37
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedHeading.java
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+
+/**
+ * H[1-6].
+ */
+final class HedHeading extends HedInlineContainer {
+
+	/**
+	 */
+	public HedHeading(String elementName, ElementCollection collection) {
+		super(elementName, collection);
+		correctionType = CORRECT_EMPTY;
+		layoutType = LAYOUT_BLOCK;
+	}
+
+	/**
+	 * Create all attribute declarations.
+	 * This method is called once in the constructor of the super class.
+	 * The <code>H1</code> element may have the following attributes:
+	 * <table>
+	 * <tbody>
+	 *   <tr>
+	 *     <th>NAME</th><th>TYPE</th><th>USAGE</th><th>DEFAULT (INITIAL) VALUE</th><th>MEMO</th>
+	 *   </tr>
+	 *   <tr>
+	 *     <td>%attrs;</td><td>-</td><td>-</td><td>-</td><td>-</td>
+	 *   </tr>
+	 *   <tr>
+	 *     <td>%align;</td><td>-</td><td>-</td><td>-</td><td>-</td>
+	 *   </tr>
+	 * </tbody>
+	 * </table>
+	 * <p><b>%align;</b> means <code>align (left|center|right|justify) #IMPLIED</code>.
+	 * Unfortunately, this <code>align</code> is different from one in
+	 * <code>IMG</code> or <code>TABLE</code>.  So, the attribute declaration
+	 * of <code>align</code> should be localy created and it shouldn't be registered
+	 * in a <code>HCMDocImpl</code> instance.</p>
+	 * <p>However, %align is used in sevaral times.  I wouldn't write same code
+	 * in many times.  So, I add a new utility method into <code>CMUtil</code>
+	 * to create the attribute declaration.</p>
+	 * <br>
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+		// align
+		HTMLAttrDeclImpl attr = AttributeCollection.createAlignForParagraph();
+		if (attr != null)
+			attributes.putNamedItem(CHTMLNamespace.ATTR_NAME_ALIGN, attr);
+	}
+
+	/**
+	 */
+	public CMNamedNodeMap getProhibitedAncestors() {
+		if (prohibitedAncestors != null)
+			return prohibitedAncestors;
+
+		String[] names = {CHTMLNamespace.ElementName.DIR, CHTMLNamespace.ElementName.MENU};
+		prohibitedAncestors = elementCollection.getDeclarations(names);
+
+		return prohibitedAncestors;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedIMG.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedIMG.java
new file mode 100644
index 0000000..e8454e2
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedIMG.java
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import java.util.Arrays;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+
+/**
+ * IMG.
+ */
+final class HedIMG extends HedEmpty {
+
+	/**
+	 */
+	public HedIMG(ElementCollection collection) {
+		super(CHTMLNamespace.ElementName.IMG, collection);
+		layoutType = LAYOUT_OBJECT;
+	}
+
+	/**
+	 * IMG.
+	 * %attrs;
+	 * (src %URI; #REQUIRED): should be defined locally.
+	 * (alt %Text; #REQUIRED)
+	 * (longdesc %URI; #IMPLIED)
+	 * (name CDATA #IMPLIED)
+	 * (height %Length; #IMPLIED)
+	 * (width %Length; #IMPLIED)
+	 * (usemap %URI; #IMPLIED)
+	 * (ismap (ismap) #IMPLIED)
+	 * (align %IAlign; #IMPLIED): should be defined locally.
+	 * (border %Pixels; #IMPLIED)
+	 * (hspace %Pixels; #IMPLIED)
+	 * (vspace %Pixels; #IMPLIED)
+	 * (mapfile %URI; #IMPLIED)
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+
+		// (src %URI; #REQUIRED): should be defined locally.
+		HTMLCMDataTypeImpl atype = null;
+		HTMLAttrDeclImpl attr = null;
+		atype = new HTMLCMDataTypeImpl(CMDataType.URI);
+		attr = new HTMLAttrDeclImpl(CHTMLNamespace.ATTR_NAME_SRC, atype, CMAttributeDeclaration.REQUIRED);
+		attributes.putNamedItem(CHTMLNamespace.ATTR_NAME_SRC, attr);
+
+		String[] names = {CHTMLNamespace.ATTR_NAME_ALT, CHTMLNamespace.ATTR_NAME_NAME, CHTMLNamespace.ATTR_NAME_HEIGHT, CHTMLNamespace.ATTR_NAME_WIDTH, CHTMLNamespace.ATTR_NAME_BORDER, CHTMLNamespace.ATTR_NAME_HSPACE, CHTMLNamespace.ATTR_NAME_VSPACE,};
+		attributeCollection.getDeclarations(attributes, Arrays.asList(names).iterator());
+
+		// align (local); should be defined locally.
+		attr = AttributeCollection.createAlignForImage();
+		attributes.putNamedItem(CHTMLNamespace.ATTR_NAME_ALIGN, attr);
+	}
+
+	/**
+	 */
+	public CMNamedNodeMap getProhibitedAncestors() {
+		if (prohibitedAncestors != null)
+			return prohibitedAncestors;
+
+		String[] names = {CHTMLNamespace.ElementName.PRE};
+		prohibitedAncestors = elementCollection.getDeclarations(names);
+
+		return prohibitedAncestors;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedINPUT.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedINPUT.java
new file mode 100644
index 0000000..29acb3a
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedINPUT.java
@@ -0,0 +1,108 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import java.util.Arrays;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+
+/**
+ * INPUT.
+ */
+final class HedINPUT extends HedEmpty {
+
+	/**
+	 */
+	public HedINPUT(ElementCollection collection) {
+		super(CHTMLNamespace.ElementName.INPUT, collection);
+		layoutType = LAYOUT_OBJECT;
+	}
+
+	/**
+	 * INPUT.
+	 * %attrs;
+	 * (type %InputType; TEXT) ... should be defined locally.
+	 * (name CDATA #IMPLIED)
+	 * (value CDATA #IMPLIED)
+	 * (checked (checked) #IMPLIED)
+	 * (disabled (disabled) #IMPLIED)
+	 * (readonly (readonly) #IMPLIED)
+	 * (size CDATA #IMPLIED) ... should be defined locally.
+	 * (maxlength NUMBER #IMPLIED)
+	 * (src %URI; #IMPLIED)
+	 * (alt CDATA #IMPLIED) ... should be defined locally.
+	 * (usemap %URI; #IMPLIED)
+	 * (ismap (ismap) #IMPLIED)
+	 * (tabindex NUMBER #IMPLIED)
+	 * (accesskey %Character; #IMPLIED)
+	 * (onfocus %Script; #IMPLIED)
+	 * (onblur %Script; #IMPLIED)
+	 * (onselect %Script; #IMPLIED)
+	 * (onchange %Script; #IMPLIED)
+	 * (accept %ContentTypes; #IMPLIED)
+	 * (align %IAlign; #IMPLIED) ... should be defined locally.
+	 * (istyle CDATA #IMPLIED)
+	 * <<D215684
+	 * (width CDATA; #IMPLIED)
+	 * (height CDATA; #IMPLIED)
+	 * (border CDATA; #IMPLIED)
+	 * D215684
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+
+		HTMLCMDataTypeImpl atype = null;
+		HTMLAttrDeclImpl attr = null;
+		// (type %InputType; TEXT) ... should be defined locally.
+		// NOTE: %InputType is ENUM;
+		// (text | password | checkbox | radio | submit | reset |
+		//  file | hidden | image | button)
+		atype = new HTMLCMDataTypeImpl(CMDataType.ENUM);
+		String[] values = {CHTMLNamespace.ATTR_VALUE_TEXT, CHTMLNamespace.ATTR_VALUE_PASSWORD, CHTMLNamespace.ATTR_VALUE_CHECKBOX, CHTMLNamespace.ATTR_VALUE_RADIO, CHTMLNamespace.ATTR_VALUE_SUBMIT, CHTMLNamespace.ATTR_VALUE_RESET, CHTMLNamespace.ATTR_VALUE_HIDDEN,};
+		atype.setEnumValues(values);
+		atype.setImpliedValue(CMDataType.IMPLIED_VALUE_DEFAULT, CHTMLNamespace.ATTR_VALUE_TEXT);
+		attr = new HTMLAttrDeclImpl(CHTMLNamespace.ATTR_NAME_TYPE, atype, CMAttributeDeclaration.OPTIONAL);
+		attributes.putNamedItem(CHTMLNamespace.ATTR_NAME_TYPE, attr);
+
+		// (size CDATA #IMPLIED) ... should be defined locally.
+		atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+		attr = new HTMLAttrDeclImpl(CHTMLNamespace.ATTR_NAME_SIZE, atype, CMAttributeDeclaration.OPTIONAL);
+		attributes.putNamedItem(CHTMLNamespace.ATTR_NAME_SIZE, attr);
+
+		// (alt CDATA #IMPLIED) ... should be defined locally.
+		atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+		attr = new HTMLAttrDeclImpl(CHTMLNamespace.ATTR_NAME_ALT, atype, CMAttributeDeclaration.OPTIONAL);
+		attributes.putNamedItem(CHTMLNamespace.ATTR_NAME_ALT, attr);
+
+		// (align %IAlign; #IMPLIED) ... should be defined locally.
+		attr = AttributeCollection.createAlignForImage();
+		attributes.putNamedItem(CHTMLNamespace.ATTR_NAME_ALIGN, attr);
+
+		// the rest.
+		String[] names = {CHTMLNamespace.ATTR_NAME_NAME, CHTMLNamespace.ATTR_NAME_VALUE, CHTMLNamespace.ATTR_NAME_CHECKED, CHTMLNamespace.ATTR_NAME_SIZE, CHTMLNamespace.ATTR_NAME_MAXLENGTH, CHTMLNamespace.ATTR_NAME_SRC, CHTMLNamespace.ATTR_NAME_ALT, CHTMLNamespace.ATTR_NAME_ALIGN, CHTMLNamespace.ATTR_NAME_ISTYLE,
+		//<<D215684
+					CHTMLNamespace.ATTR_NAME_WIDTH, CHTMLNamespace.ATTR_NAME_HEIGHT, CHTMLNamespace.ATTR_NAME_BORDER
+		//<D215684
+		};
+		attributeCollection.getDeclarations(attributes, Arrays.asList(names).iterator());
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedInlineContainer.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedInlineContainer.java
new file mode 100644
index 0000000..dbd4bc9
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedInlineContainer.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+/**
+ * Base class for (%inline;)* containers.
+ */
+abstract class HedInlineContainer extends HTMLElemDeclImpl {
+
+	/**
+	 * HedInlineContainer.
+	 * @param elementName java.lang.String
+	 * @param collection ElementCollection
+	 */
+	public HedInlineContainer(String elementName, ElementCollection collection) {
+		super(elementName, collection);
+		typeDefinitionName = ComplexTypeDefinitionFactory.CTYPE_INLINE_CONTAINER;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedLI.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedLI.java
new file mode 100644
index 0000000..ea1f4a6
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedLI.java
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import java.util.Arrays;
+import java.util.Iterator;
+
+/**
+ * LI.
+ */
+final class HedLI extends HedFlowContainer {
+
+	private static String[] terminators = {CHTMLNamespace.ElementName.LI};
+
+	/**
+	 */
+	public HedLI(ElementCollection collection) {
+		super(CHTMLNamespace.ElementName.LI, collection);
+		layoutType = LAYOUT_BLOCK;
+		omitType = OMIT_END_DEFAULT;
+	}
+
+	/**
+	 * %attrs;
+	 * (type %LIStyle; #IMPLIED) ... should be defined locally.
+	 * (value NUMBER #IMPLIED) ... should be defined locally.
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+
+	}
+
+	/**
+	 * LI has terminators.
+	 * @return java.util.Iterator
+	 */
+	protected Iterator getTerminators() {
+		return Arrays.asList(terminators).iterator();
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedListItemContainer.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedListItemContainer.java
new file mode 100644
index 0000000..1f35e93
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedListItemContainer.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+/**
+ * Base class for list item container declarations.
+ * - OL, UL, MENU, DIR.
+ */
+abstract class HedListItemContainer extends HTMLElemDeclImpl {
+
+	/**
+	 */
+	public HedListItemContainer(String elementName, ElementCollection collection) {
+		super(elementName, collection);
+		typeDefinitionName = ComplexTypeDefinitionFactory.CTYPE_LI_CONTAINER;
+		correctionType = CORRECT_EMPTY;
+		layoutType = LAYOUT_BLOCK;
+		indentChild = true;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedMENU.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedMENU.java
new file mode 100644
index 0000000..c0f0e83
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedMENU.java
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import java.util.Arrays;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMContent;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+
+/**
+ * MENU/DIR.
+ */
+final class HedMENU extends HedListItemContainer {
+
+	/**
+	 */
+	public HedMENU(String elementName, ElementCollection collection) {
+		super(elementName, collection);
+	}
+
+	/**
+	 * MENU/DIR.
+	 * (compact (compact) #IMPLIED)
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+
+	}
+
+	/**
+	 * Exclusion.
+	 * <code>MENU/DIR</code> has the exclusion.
+	 * It is <code>%block;</code>.
+	 * %block; is:
+	 * P | %heading; | %list; | %preformatted; | DL | DIV | CENTER |
+	 * NOSCRIPT | NOFRAMES | BLOCKQUOTE | FORM | ISINDEX | HR |
+	 * TABLE | FIELDSET | ADDRESS.
+	 * %heading; is: H1 | H2 | H3 | H4 | H5 | H6.
+	 * %list; is : UL | OL | DIR | MENU.
+	 * %preformatted; is PRE.
+	 * <br>
+	 */
+	public CMContent getExclusion() {
+		if (exclusion != null)
+			return exclusion; // already created.
+		if (elementCollection == null)
+			return null;
+
+		// %block;
+		exclusion = new CMGroupImpl(CMGroup.CHOICE, 1, 1);
+		String[] names = {CHTMLNamespace.ElementName.P, CHTMLNamespace.ElementName.H1, CHTMLNamespace.ElementName.H2, CHTMLNamespace.ElementName.H3, CHTMLNamespace.ElementName.H4, CHTMLNamespace.ElementName.H5, CHTMLNamespace.ElementName.H6, CHTMLNamespace.ElementName.UL, CHTMLNamespace.ElementName.OL, CHTMLNamespace.ElementName.DIR, CHTMLNamespace.ElementName.MENU, CHTMLNamespace.ElementName.PRE, CHTMLNamespace.ElementName.DL, CHTMLNamespace.ElementName.DIV, CHTMLNamespace.ElementName.CENTER, CHTMLNamespace.ElementName.BLOCKQUOTE, CHTMLNamespace.ElementName.FORM, CHTMLNamespace.ElementName.HR, CHTMLNamespace.ElementName.ADDRESS};
+		elementCollection.getDeclarations(exclusion, Arrays.asList(names).iterator());
+		return exclusion;
+	}
+
+	/**
+	 */
+	public CMNamedNodeMap getProhibitedAncestors() {
+		if (prohibitedAncestors != null)
+			return prohibitedAncestors;
+
+		String[] names = {CHTMLNamespace.ElementName.DIR, CHTMLNamespace.ElementName.MENU};
+		prohibitedAncestors = elementCollection.getDeclarations(names);
+
+		return prohibitedAncestors;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedMETA.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedMETA.java
new file mode 100644
index 0000000..172a6fb
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedMETA.java
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import java.util.Arrays;
+
+import org.eclipse.wst.html.core.internal.contentmodel.HTMLCMDataType;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+
+/**
+ * META.
+ */
+final class HedMETA extends HedEmpty {
+
+	/**
+	 */
+	public HedMETA(ElementCollection collection) {
+		super(CHTMLNamespace.ElementName.META, collection);
+		layoutType = LAYOUT_HIDDEN;
+	}
+
+	/**
+	 * META.
+	 * %i18n;
+	 * (http-equiv NAME #IMPLIED)
+	 * (name NAME #IMPLIED) ... should be defined locally.
+	 * (content CDATA #REQUIRED)
+	 * (scheme CDATA #IMPLIED)
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %i18n;
+		attributeCollection.getI18n(attributes);
+
+		// (name NAME #IMPLIED) ... should be defined locally.
+		HTMLCMDataTypeImpl atype = new HTMLCMDataTypeImpl(HTMLCMDataType.NAME);
+		HTMLAttrDeclImpl attr = new HTMLAttrDeclImpl(CHTMLNamespace.ATTR_NAME_NAME, atype, CMAttributeDeclaration.OPTIONAL);
+		attributes.putNamedItem(CHTMLNamespace.ATTR_NAME_NAME, attr);
+
+		// 249493
+		atype = new HTMLCMDataTypeImpl(CMDataType.CDATA);
+		attr = new HTMLAttrDeclImpl(CHTMLNamespace.ATTR_NAME_CONTENT, atype, CMAttributeDeclaration.OPTIONAL);
+		attributes.putNamedItem(CHTMLNamespace.ATTR_NAME_CONTENT, attr);
+
+		String[] names = {CHTMLNamespace.ATTR_NAME_HTTP_EQUIV,
+		//		CHTMLNamespace.ATTR_NAME_CONTENT
+		};
+		attributeCollection.getDeclarations(attributes, Arrays.asList(names).iterator());
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedOL.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedOL.java
new file mode 100644
index 0000000..7e801d2
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedOL.java
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+
+/**
+ * OL.
+ */
+final class HedOL extends HedListItemContainer {
+
+	/**
+	 */
+	public HedOL(ElementCollection collection) {
+		super(CHTMLNamespace.ElementName.OL, collection);
+	}
+
+	/**
+	 * OL.
+	 * (type %OLStyle; #IMPLIED) ... should be defined locally.
+	 * (compact (compact) #IMPLIED)
+	 * (start NUMBER #IMPLIED)
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+
+	}
+
+	/**
+	 */
+	public CMNamedNodeMap getProhibitedAncestors() {
+		if (prohibitedAncestors != null)
+			return prohibitedAncestors;
+
+		String[] names = {CHTMLNamespace.ElementName.DIR, CHTMLNamespace.ElementName.MENU};
+		prohibitedAncestors = elementCollection.getDeclarations(names);
+
+		return prohibitedAncestors;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedOPTION.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedOPTION.java
new file mode 100644
index 0000000..6df202d
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedOPTION.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import java.util.Arrays;
+import java.util.Iterator;
+
+/**
+ * OPTION.
+ */
+final class HedOPTION extends HedPcdata {
+
+	private static String[] terminators = {CHTMLNamespace.ElementName.OPTION};
+
+	/**
+	 */
+	public HedOPTION(ElementCollection collection) {
+		super(CHTMLNamespace.ElementName.OPTION, collection);
+		layoutType = LAYOUT_HIDDEN;
+		omitType = OMIT_END;
+	}
+
+	/**
+	 * OPTION.
+	 * %attrs;
+	 * (selected (selected) #IMPLIED)
+	 * (disabled (disabled) #IMPLIED)
+	 * (label %Text; #IMPLIED)
+	 * (value CDATA #IMPLIED)
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+
+		String[] names = {CHTMLNamespace.ATTR_NAME_SELECTED, CHTMLNamespace.ATTR_NAME_VALUE};
+		attributeCollection.getDeclarations(attributes, Arrays.asList(names).iterator());
+	}
+
+	/**
+	 * OPTION has terminators.
+	 * @return java.util.Iterator
+	 */
+	protected Iterator getTerminators() {
+		return Arrays.asList(terminators).iterator();
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedP.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedP.java
new file mode 100644
index 0000000..a92e091
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedP.java
@@ -0,0 +1,104 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Vector;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+
+/**
+ * P.
+ */
+final class HedP extends HedInlineContainer {
+
+	private static Collection terminators = null;
+
+	/**
+	 */
+	public HedP(ElementCollection collection) {
+		super(CHTMLNamespace.ElementName.P, collection);
+		correctionType = CORRECT_EMPTY;
+		layoutType = LAYOUT_BLOCK;
+		omitType = OMIT_END;
+	}
+
+	/**
+	 * Create all attribute declarations.
+	 * This method is called once in the constructor of the super class.
+	 * The <code>P</code> element may have the following attributes:
+	 * <table>
+	 * <tbody>
+	 *   <tr>
+	 *     <th>NAME</th><th>TYPE</th><th>USAGE</th><th>DEFAULT (INITIAL) VALUE</th><th>MEMO</th>
+	 *   </tr>
+	 *   <tr>
+	 *     <td>%attrs;</td><td>-</td><td>-</td><td>-</td><td>-</td>
+	 *   </tr>
+	 *   <tr>
+	 *     <td>%align;</td><td>-</td><td>-</td><td>-</td><td>-</td>
+	 *   </tr>
+	 * </tbody>
+	 * </table>
+	 * <p><b>%align;</b> means <code>align (left|center|right|justify) #IMPLIED</code>.
+	 * Unfortunately, this <code>align</code> is different from one in
+	 * <code>IMG</code> or <code>TABLE</code>.  So, the attribute declaration
+	 * of <code>align</code> should be localy created and it shouldn't be registered
+	 * in a <code>HCMDocImpl</code> instance.</p>
+	 * <p>However, %align is used in sevaral times.  I wouldn't write same code
+	 * in many times.  So, I add a new utility method into <code>CMUtil</code>
+	 * to create the attribute declaration.</p>
+	 * <br>
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+		attributes = new CMNamedNodeMapImpl();
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+		// align
+		HTMLAttrDeclImpl adec = AttributeCollection.createAlignForParagraph();
+		attributes.putNamedItem(CHTMLNamespace.ATTR_NAME_ALIGN, adec);
+	}
+
+	/**
+	 */
+	public CMNamedNodeMap getProhibitedAncestors() {
+		if (prohibitedAncestors != null)
+			return prohibitedAncestors;
+		String[] names = {CHTMLNamespace.ElementName.DIR, CHTMLNamespace.ElementName.MENU};
+		prohibitedAncestors = elementCollection.getDeclarations(names);
+		return prohibitedAncestors;
+	}
+
+	/**
+	 * Return names of terminators.
+	 * <code>P</code> has terminators.
+	 * @return java.util.Iterator
+	 */
+	protected Iterator getTerminators() {
+		if (terminators != null)
+			return terminators.iterator();
+		//<<D217982
+		terminators = new Vector();
+		terminators.addAll(elementCollection.getNamesOfBlock());
+		terminators.add(CHTMLNamespace.ElementName.LI);
+		terminators.add(CHTMLNamespace.ElementName.DT);
+		terminators.add(CHTMLNamespace.ElementName.DD);
+		//D217982
+		return terminators.iterator();
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedPRE.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedPRE.java
new file mode 100644
index 0000000..02f5353
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedPRE.java
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import java.util.Arrays;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMContent;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+
+/**
+ * PRE.
+ */
+final class HedPRE extends HedInlineContainer {
+
+	/**
+	 * PRE element should keep spaces in its source.
+	 */
+	public HedPRE(ElementCollection collection) {
+		super(CHTMLNamespace.ElementName.PRE, collection);
+		// CORRECT_EMPTY - GROUP_COMPACT
+		correctionType = CORRECT_EMPTY;
+
+		keepSpaces = true;
+	}
+
+	/**
+	 * %attrs;
+	 * (width NUMBER #IMPLIED) ... should be defined locally.
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+		// (width NUMBER #IMPLIED) ... should be defined locally.
+		HTMLCMDataTypeImpl atype = new HTMLCMDataTypeImpl(CMDataType.NUMBER);
+		HTMLAttrDeclImpl attr = new HTMLAttrDeclImpl(CHTMLNamespace.ATTR_NAME_WIDTH, atype, CMAttributeDeclaration.OPTIONAL);
+		attributes.putNamedItem(CHTMLNamespace.ATTR_NAME_WIDTH, attr);
+	}
+
+	/**
+	 * Exclusion.
+	 * <code>PRE</code> has the exclusion.
+	 * It is <code>%pre.exclusion;</code>.
+	 * %pre.exclusion is:
+	 * IMG | OBJECT | APPLET | BIG | SMALL | SUB | SUP | FONT | BASEFONT
+	 */
+	public CMContent getExclusion() {
+		if (exclusion != null)
+			return exclusion; // already created.
+		if (elementCollection == null)
+			return null;
+
+		exclusion = new CMGroupImpl(CMGroup.CHOICE, 1, 1);
+		String[] names = {CHTMLNamespace.ElementName.IMG,};
+		elementCollection.getDeclarations(exclusion, Arrays.asList(names).iterator());
+
+		return exclusion;
+	}
+
+	/**
+	 */
+	public CMNamedNodeMap getProhibitedAncestors() {
+		if (prohibitedAncestors != null)
+			return prohibitedAncestors;
+
+		String[] names = {CHTMLNamespace.ElementName.DIR, CHTMLNamespace.ElementName.MENU};
+		prohibitedAncestors = elementCollection.getDeclarations(names);
+
+		return prohibitedAncestors;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedPcdata.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedPcdata.java
new file mode 100644
index 0000000..6490df0
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedPcdata.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMContent;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+
+/**
+ * Base class for PCDATA type element declarations.<br>
+ */
+abstract class HedPcdata extends HTMLElemDeclImpl {
+
+	/**
+	 */
+	public HedPcdata(String elementName, ElementCollection collection) {
+		super(elementName, collection);
+		typeDefinitionName = ComplexTypeDefinitionFactory.CTYPE_PCDATA;
+	}
+
+	/**
+	 * Content.<br>
+	 * PCDATA type always returns <code>null</code>.
+	 * <br>
+	 * @return org.eclipse.wst.xml.core.internal.contentmodel.CMContent
+	 */
+	public CMContent getContent() {
+		return null;
+	}
+
+	/**
+	 * Content type.<br>
+	 * @see org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration
+	 */
+	public int getContentType() {
+		return CMElementDeclaration.PCDATA;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedSELECT.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedSELECT.java
new file mode 100644
index 0000000..db036f7
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedSELECT.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import java.util.Arrays;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+
+/**
+ * SELECT.
+ */
+final class HedSELECT extends HTMLElemDeclImpl {
+
+	/**
+	 */
+	public HedSELECT(ElementCollection collection) {
+		super(CHTMLNamespace.ElementName.SELECT, collection);
+		typeDefinitionName = ComplexTypeDefinitionFactory.CTYPE_SELECT;
+		layoutType = LAYOUT_OBJECT;
+		indentChild = true;
+	}
+
+	/**
+	 * %attrs;
+	 * %reserved;
+	 * (name CDATA #IMPLIED)
+	 * (size NUMBER #IMPLIED) ... should be defined locally.
+	 * (multiple (multiple) #IMPLIED)
+	 * (disabled (disabled) #IMPLIED)
+	 * (tabindex NUMBER #IMPLIED)
+	 * (onfocus %Script; #IMPLIED)
+	 * (onblur %Script; #IMPLIED)
+	 * (onchange %Script; #IMPLIED)
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+
+		// (size NUMBER #IMPLIED) ... should be defined locally.
+		HTMLCMDataTypeImpl atype = new HTMLCMDataTypeImpl(CMDataType.NUMBER);
+		HTMLAttrDeclImpl attr = new HTMLAttrDeclImpl(CHTMLNamespace.ATTR_NAME_SIZE, atype, CMAttributeDeclaration.OPTIONAL);
+		attributes.putNamedItem(CHTMLNamespace.ATTR_NAME_SIZE, attr);
+
+		String[] names = {CHTMLNamespace.ATTR_NAME_NAME, CHTMLNamespace.ATTR_NAME_MULTIPLE,};
+		attributeCollection.getDeclarations(attributes, Arrays.asList(names).iterator());
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedSSIBase.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedSSIBase.java
new file mode 100644
index 0000000..fddb04d
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedSSIBase.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+import org.eclipse.wst.html.core.internal.contentmodel.HTMLElementDeclaration;
+import org.eclipse.wst.html.core.internal.provisional.HTMLCMProperties;
+
+
+
+
+/**
+ * Base class for SSI declarations.
+ */
+abstract class HedSSIBase extends HedEmpty {
+
+	/**
+	 */
+	public HedSSIBase(String elementName, ElementCollection collection) {
+		super(elementName, collection);
+		layoutType = LAYOUT_OBJECT;
+	}
+
+	/**
+	 */
+	public int getFormatType() {
+		return HTMLElementDeclaration.FORMAT_SSI;
+	}
+
+	/**
+	 */
+	public boolean supports(String propName) {
+		if (propName.equals(HTMLCMProperties.IS_SSI))
+			return true;
+		return super.supports(propName);
+	}
+
+	/*
+	 */
+	public Object getProperty(String propName) {
+		if (propName.equals(HTMLCMProperties.IS_SSI))
+			return new Boolean(true);
+		return super.getProperty(propName);
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedSSIConfig.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedSSIConfig.java
new file mode 100644
index 0000000..3b52b06
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedSSIConfig.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import java.util.Arrays;
+
+/**
+ * SSI:CONFIG.
+ */
+final class HedSSIConfig extends HedSSIBase {
+
+	/**
+	 */
+	public HedSSIConfig(ElementCollection collection) {
+		super(CHTMLNamespace.ElementName.SSI_CONFIG, collection);
+	}
+
+	/**
+	 * SSI:CONFIG.
+	 * (errmsg CDATA #IMPLIED)
+	 * (sizefmt CDATA #IMPLIED)
+	 * (timefmt CDATA #IMPLIED)
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		String[] names = {CHTMLNamespace.ATTR_NAME_ERRMSG, CHTMLNamespace.ATTR_NAME_SIZEFMT, CHTMLNamespace.ATTR_NAME_TIMEFMT};
+		attributeCollection.getDeclarations(attributes, Arrays.asList(names).iterator());
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedSSIEcho.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedSSIEcho.java
new file mode 100644
index 0000000..9d1b226
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedSSIEcho.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import java.util.Arrays;
+
+/**
+ * SSI:ECHO.
+ */
+final class HedSSIEcho extends HedSSIBase {
+
+	/**
+	 */
+	public HedSSIEcho(ElementCollection collection) {
+		super(CHTMLNamespace.ElementName.SSI_ECHO, collection);
+	}
+
+	/**
+	 * SSI:ECHO
+	 * (var CDATA #IMPLIED)
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		String[] names = {CHTMLNamespace.ATTR_NAME_VAR};
+		attributeCollection.getDeclarations(attributes, Arrays.asList(names).iterator());
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedSSIExec.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedSSIExec.java
new file mode 100644
index 0000000..26ad58e
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedSSIExec.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import java.util.Arrays;
+
+/**
+ * SSI:EXEC.
+ */
+final class HedSSIExec extends HedSSIBase {
+
+	/**
+	 */
+	public HedSSIExec(ElementCollection collection) {
+		super(CHTMLNamespace.ElementName.SSI_EXEC, collection);
+	}
+
+	/**
+	 * SSI:EXEC
+	 * (cgi %URI; #IMPLIED)
+	 * (cmd CDATA #IMPLIED)
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		String[] names = {CHTMLNamespace.ATTR_NAME_CGI, CHTMLNamespace.ATTR_NAME_CMD};
+		attributeCollection.getDeclarations(attributes, Arrays.asList(names).iterator());
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedSSIFlastmod.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedSSIFlastmod.java
new file mode 100644
index 0000000..5a0cb73
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedSSIFlastmod.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import java.util.Arrays;
+
+/**
+ * SSI:FLASTMOD.
+ */
+final class HedSSIFlastmod extends HedSSIBase {
+
+	/**
+	 */
+	public HedSSIFlastmod(ElementCollection collection) {
+		super(CHTMLNamespace.ElementName.SSI_FLASTMOD, collection);
+	}
+
+	/**
+	 * SSI:FLASTMOD
+	 * (file %URI; #IMPLIED)
+	 * (virtual %URI #IMPLIED)
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		String[] names = {CHTMLNamespace.ATTR_NAME_FILE, CHTMLNamespace.ATTR_NAME_VIRTUAL};
+		attributeCollection.getDeclarations(attributes, Arrays.asList(names).iterator());
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedSSIFsize.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedSSIFsize.java
new file mode 100644
index 0000000..c56f282
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedSSIFsize.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import java.util.Arrays;
+
+/**
+ * SSI:FSIZE.
+ */
+final class HedSSIFsize extends HedSSIBase {
+
+	/**
+	 */
+	public HedSSIFsize(ElementCollection collection) {
+		super(CHTMLNamespace.ElementName.SSI_FSIZE, collection);
+	}
+
+	/**
+	 * SSI:FSIZE
+	 * (file %URI; #IMPLIED)
+	 * (virtual %URI #IMPLIED)
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		String[] names = {CHTMLNamespace.ATTR_NAME_FILE, CHTMLNamespace.ATTR_NAME_VIRTUAL};
+		attributeCollection.getDeclarations(attributes, Arrays.asList(names).iterator());
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedSSIInclude.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedSSIInclude.java
new file mode 100644
index 0000000..220f726
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedSSIInclude.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import java.util.Arrays;
+
+/**
+ * SSI:INCLUDE.
+ */
+final class HedSSIInclude extends HedSSIBase {
+
+	/**
+	 */
+	public HedSSIInclude(ElementCollection collection) {
+		super(CHTMLNamespace.ElementName.SSI_INCLUDE, collection);
+	}
+
+	/**
+	 * SSI:INCLUDE
+	 * (file %URI; #IMPLIED)
+	 * (virtual %URI #IMPLIED)
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		String[] names = {CHTMLNamespace.ATTR_NAME_FILE, CHTMLNamespace.ATTR_NAME_VIRTUAL};
+		attributeCollection.getDeclarations(attributes, Arrays.asList(names).iterator());
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedSSIPrintenv.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedSSIPrintenv.java
new file mode 100644
index 0000000..6860996
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedSSIPrintenv.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+
+/**
+ * SSI:PRINTENV.
+ */
+final class HedSSIPrintenv extends HedSSIBase {
+
+	/**
+	 */
+	public HedSSIPrintenv(ElementCollection collection) {
+		super(CHTMLNamespace.ElementName.SSI_PRINTENV, collection);
+	}
+
+	/**
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+	}
+
+	/**
+	 * SSI:PRINTENV has no attributes.  So, this method should
+	 * always return <code>null</code>.
+	 * Note: Since somebody doesn't expect null is returned, return the empty attribute
+	 * like a custom tag which doesn't have attributes
+	 */
+	public CMNamedNodeMap getAttributes() {
+		return super.getAttributes();
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedSSISet.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedSSISet.java
new file mode 100644
index 0000000..d447488
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedSSISet.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import java.util.Arrays;
+
+/**
+ * SSI:SET.
+ */
+final class HedSSISet extends HedSSIBase {
+
+	/**
+	 */
+	public HedSSISet(ElementCollection collection) {
+		super(CHTMLNamespace.ElementName.SSI_SET, collection);
+	}
+
+	/**
+	 * SSI:SET
+	 * (var CDATA #IMPLIED)
+	 * (value CDATA #IMPLIED)
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		String[] names = {CHTMLNamespace.ATTR_NAME_VAR, CHTMLNamespace.ATTR_NAME_VALUE};
+		attributeCollection.getDeclarations(attributes, Arrays.asList(names).iterator());
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedTEXTAREA.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedTEXTAREA.java
new file mode 100644
index 0000000..18198ea
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedTEXTAREA.java
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import java.util.Arrays;
+
+/**
+ * TEXTAREA.
+ */
+final class HedTEXTAREA extends HedPcdata {
+
+	/**
+	 * TEXTAREA should keep spaces in its source.
+	 */
+	public HedTEXTAREA(ElementCollection collection) {
+		super(CHTMLNamespace.ElementName.TEXTAREA, collection);
+		layoutType = LAYOUT_OBJECT;
+
+		keepSpaces = true;
+	}
+
+	/**
+	 * TEXTAREA.
+	 * %attrs;
+	 * %reserved; ... empty
+	 * (name CDATA #IMPLIED)
+	 * (rows NUMBER #REQUIRED)
+	 * (cols NUMBER #REQUIRED)
+	 * (disabled (disabled) #IMPLIED)
+	 * (readonly (readonly) #IMPLIED)
+	 * (tabindex NUMBER #IMPLIED)
+	 * (accesskey %Character; #IMPLIED)
+	 * (onfocus %Script; #IMPLIED)
+	 * (onblur %Script; #IMPLIED)
+	 * (onselect %Script; #IMPLIED)
+	 * (onchange %Script; #IMPLIED)
+	 * (istyle CDATA #IMPLIED)
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+
+		String[] names = {CHTMLNamespace.ATTR_NAME_NAME, CHTMLNamespace.ATTR_NAME_ROWS, CHTMLNamespace.ATTR_NAME_COLS, CHTMLNamespace.ATTR_NAME_ISTYLE};
+		attributeCollection.getDeclarations(attributes, Arrays.asList(names).iterator());
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedTITLE.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedTITLE.java
new file mode 100644
index 0000000..e92e0ad
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedTITLE.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import java.util.Arrays;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMContent;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+
+/**
+ * TITLE.
+ */
+final class HedTITLE extends HedPcdata {
+
+	/**
+	 */
+	public HedTITLE(ElementCollection collection) {
+		super(CHTMLNamespace.ElementName.TITLE, collection);
+		layoutType = LAYOUT_HIDDEN;
+	}
+
+	/**
+	 * TITLE.
+	 * %i18n;
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %i18n;
+		attributeCollection.getI18n(attributes);
+	}
+
+	/**
+	 * Exclusion.
+	 * <code>TITLE</code> has the exclusion.
+	 * It is <code>%head.misc;</code>.
+	 * %head.misc; is <code>SCRIPT|STYLE|META|LINK|OBJECT</code>.
+	 * <br>
+	 */
+	public CMContent getExclusion() {
+		if (exclusion != null)
+			return exclusion; // already created.
+		if (elementCollection == null)
+			return null;
+
+		// (SCRIPT|STYLE|META|LINK|OBJECT)
+		exclusion = new CMGroupImpl(CMGroup.CHOICE, 1, 1);
+
+		String[] names = {CHTMLNamespace.ElementName.META,};
+		elementCollection.getDeclarations(exclusion, Arrays.asList(names).iterator());
+		return exclusion;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedUL.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedUL.java
new file mode 100644
index 0000000..a2249a8
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/HedUL.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+
+/**
+ * UL.
+ */
+final class HedUL extends HedListItemContainer {
+
+	/**
+	 */
+	public HedUL(ElementCollection collection) {
+		super(CHTMLNamespace.ElementName.UL, collection);
+	}
+
+	/**
+	 * UL.
+	 * (type %ULStyle; #IMPLIED) ... should be defined locally.
+	 * (compact (compact) #IMPLIED)
+	 */
+	protected void createAttributeDeclarations() {
+		if (attributes != null)
+			return; // already created.
+		if (attributeCollection == null)
+			return; // fatal
+
+		attributes = new CMNamedNodeMapImpl();
+
+		// %attrs;
+		attributeCollection.getAttrs(attributes);
+
+	}
+
+	/**
+	 */
+	public CMNamedNodeMap getProhibitedAncestors() {
+		if (prohibitedAncestors != null)
+			return prohibitedAncestors;
+
+		String[] names = {CHTMLNamespace.ElementName.DIR, CHTMLNamespace.ElementName.MENU};
+		prohibitedAncestors = elementCollection.getDeclarations(names);
+
+		return prohibitedAncestors;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/PropertyProvider.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/PropertyProvider.java
new file mode 100644
index 0000000..6040a3e
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/PropertyProvider.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+import org.eclipse.wst.html.core.internal.contentmodel.HTMLElementDeclaration;
+
+
+
+/**
+ * PropertyProvider class.
+ * This class is intended to be used in HTMLElementDeclaration instances.
+ */
+interface PropertyProvider {
+
+	boolean supports(HTMLElementDeclaration edecl);
+
+	Object get(HTMLElementDeclaration edecl);
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/PropertyProviderFactory.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/PropertyProviderFactory.java
new file mode 100644
index 0000000..214a2ca
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/chtml/PropertyProviderFactory.java
@@ -0,0 +1,364 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.chtml;
+
+import java.util.Hashtable;
+
+import org.eclipse.wst.html.core.internal.HTMLCorePlugin;
+import org.eclipse.wst.html.core.internal.contentmodel.HTMLElementDeclaration;
+import org.eclipse.wst.html.core.internal.contentmodel.HTMLPropertyDeclaration;
+import org.eclipse.wst.html.core.internal.provisional.HTMLCMProperties;
+import org.eclipse.wst.xml.core.internal.contentmodel.annotation.AnnotationMap;
+
+/**
+ * The factory object of PropertyProvider.
+ */
+final class PropertyProviderFactory {
+
+
+	/**
+	 * DefaultProvider is intended to be used for unknown properties.
+	 * It always returns null value for any properties.
+	 */
+	class DefaultProvider implements PropertyProvider {
+		public DefaultProvider() {
+			super();
+		}
+
+		public boolean supports(HTMLElementDeclaration edecl) {
+			return false;
+		}
+
+		public Object get(HTMLElementDeclaration edecl) {
+			return null;
+		}
+	}
+
+	abstract class AbstractElementPropertyProvider implements PropertyProvider {
+		protected AbstractElementPropertyProvider() {
+			super();
+		}
+
+		public boolean supports(HTMLElementDeclaration edecl) {
+			return (edecl != null);
+		}
+
+		public Object get(HTMLElementDeclaration edecl) {
+			if (!(edecl instanceof HTMLPropertyDeclaration))
+				return null;
+			return getElementProperty((HTMLPropertyDeclaration)edecl);
+		}
+
+		abstract protected Object getElementProperty(HTMLPropertyDeclaration decl);
+	}
+
+	/*
+	 * "tagInfo"
+	 * gets documentation for the element
+	 */
+	class PPTagInfo extends AbstractElementPropertyProvider {
+		private final static String htmlAnnotationLoc = "data/htmref.xml"; //$NON-NLS-1$
+		protected AnnotationMap fAnnotationMap = null;
+
+		public PPTagInfo() {
+			super();
+		}
+
+		/**
+		 * Gets the annotationMap.
+		 * @return Returns a AnnotationMap
+		 */
+		protected AnnotationMap getAnnotationMap() {
+			if (fAnnotationMap == null) {
+				fAnnotationMap = new AnnotationMap();
+				try {
+					fAnnotationMap.load(htmlAnnotationLoc, HTMLCorePlugin.getDefault().getBundle().getSymbolicName());
+				}
+				catch (Exception e) {
+					// no annotation available
+				}
+			}
+			return fAnnotationMap;
+		}
+
+		protected Object getElementProperty(HTMLPropertyDeclaration decl) {
+			if (decl instanceof HTMLElementDeclaration) {
+				return getAnnotationMap().getProperty(((HTMLElementDeclaration)decl).getElementName(), "tagInfo"); //$NON-NLS-1$
+			} else {
+				return null;
+			}
+		}
+	}
+
+	/*
+	 * "shouldKeepSpace"
+	 */
+	class PPShouldKeepSpace extends AbstractElementPropertyProvider {
+		public PPShouldKeepSpace() {
+			super();
+		}
+
+		protected Object getElementProperty(HTMLPropertyDeclaration decl) {
+			return new Boolean(decl.shouldKeepSpaces());
+		}
+	}
+
+	/*
+	 * "shouldIndentChildSource"
+	 */
+	class PPShouldIndentChildSource extends AbstractElementPropertyProvider {
+		public PPShouldIndentChildSource() {
+			super();
+		}
+
+		protected Object getElementProperty(HTMLPropertyDeclaration decl) {
+			return new Boolean(decl.shouldIndentChildSource());
+		}
+	}
+
+	/*
+	 * "terminators"
+	 */
+	class PPTerminators extends AbstractElementPropertyProvider {
+		public PPTerminators() {
+			super();
+		}
+
+		protected Object getElementProperty(HTMLPropertyDeclaration decl) {
+			if (decl == null)
+				return null;
+			if (! (decl instanceof HTMLElemDeclImpl)) return null;
+			return ((HTMLElemDeclImpl)decl).getTerminators();
+		}
+	}
+
+	/*
+	 * "prohibitedAncestors"
+	 */
+	class PPProhibitedAncestors extends AbstractElementPropertyProvider {
+		public PPProhibitedAncestors() {
+			super();
+		}
+
+		protected Object getElementProperty(HTMLPropertyDeclaration decl) {
+			return decl.getProhibitedAncestors();
+		}
+	}
+
+	/*
+	 * "isJSP"
+	 */
+	class PPIsJSP extends AbstractElementPropertyProvider {
+		public PPIsJSP() {
+			super();
+		}
+
+		protected Object getElementProperty(HTMLPropertyDeclaration decl) {
+			return new Boolean(decl.isJSP());
+		}
+	}
+
+	/*
+	 * "isXHTML"
+	 * HTMLElementDeclaration itself never represent any XHTML element declaration.
+	 * So, this property must be always false.
+	 */
+	class PPIsXHTML extends AbstractElementPropertyProvider {
+		public PPIsXHTML() {
+			super();
+		}
+
+		protected Object getElementProperty(HTMLPropertyDeclaration decl) {
+			return new Boolean(false);
+		}
+	}
+
+	/*
+	 * "isSSI"
+	 * Each declaration class for SSI elements must provide this property itself,
+	 * and then return true.  Other declaration must always return false.
+	 */
+	class PPIsSSI extends AbstractElementPropertyProvider {
+		public PPIsSSI() {
+			super();
+		}
+
+		protected Object getElementProperty(HTMLPropertyDeclaration decl) {
+			return new Boolean(false);
+		}
+	}
+
+	/*
+	 * "lineBreakHint"
+	 */
+	class PPLineBreakHint extends AbstractElementPropertyProvider {
+		public PPLineBreakHint() {
+			super();
+		}
+
+		protected Object getElementProperty(HTMLPropertyDeclaration decl) {
+			String hint = HTMLCMProperties.Values.BREAK_NONE;
+			switch (decl.getLineBreakHint()) {
+				case HTMLElementDeclaration.BREAK_AFTER_START :
+					hint = HTMLCMProperties.Values.BREAK_AFTER_START;
+					break;
+				case HTMLElementDeclaration.BREAK_BEFORE_START_AND_AFTER_END :
+					hint = HTMLCMProperties.Values.BREAK_BEFORE_START_AND_AFTER_END;
+					break;
+				case HTMLElementDeclaration.BREAK_NONE :
+				// nothing to do
+				default :
+					break;
+			}
+			return hint;
+		}
+	}
+
+	/*
+	 * "layoutType"
+	 */
+	class PPLayoutType extends AbstractElementPropertyProvider {
+		public PPLayoutType() {
+			super();
+		}
+
+		protected Object getElementProperty(HTMLPropertyDeclaration decl) {
+			String type = HTMLCMProperties.Values.LAYOUT_NONE;
+			switch (decl.getLayoutType()) {
+				case HTMLElementDeclaration.LAYOUT_BLOCK :
+					type = HTMLCMProperties.Values.LAYOUT_BLOCK;
+					break;
+				case HTMLElementDeclaration.LAYOUT_BREAK :
+					type = HTMLCMProperties.Values.LAYOUT_BREAK;
+					break;
+				case HTMLElementDeclaration.LAYOUT_HIDDEN :
+					type = HTMLCMProperties.Values.LAYOUT_HIDDEN;
+					break;
+				case HTMLElementDeclaration.LAYOUT_OBJECT :
+					type = HTMLCMProperties.Values.LAYOUT_OBJECT;
+					break;
+				case HTMLElementDeclaration.LAYOUT_WRAP :
+					type = HTMLCMProperties.Values.LAYOUT_WRAP;
+					break;
+				case HTMLElementDeclaration.LAYOUT_NONE :
+				// nothing to do.
+				default :
+					break;
+			}
+			return type;
+		}
+	}
+
+	/*
+	 * "omitType"
+	 */
+	class PPOmitType extends AbstractElementPropertyProvider {
+		public PPOmitType() {
+			super();
+		}
+
+		protected Object getElementProperty(HTMLPropertyDeclaration decl) {
+			String type = HTMLCMProperties.Values.OMIT_NONE;
+			switch (decl.getOmitType()) {
+				case HTMLElementDeclaration.OMIT_BOTH :
+					type = HTMLCMProperties.Values.OMIT_BOTH;
+					break;
+				case HTMLElementDeclaration.OMIT_END :
+					type = HTMLCMProperties.Values.OMIT_END;
+					break;
+				case HTMLElementDeclaration.OMIT_END_DEFAULT :
+					type = HTMLCMProperties.Values.OMIT_END_DEFAULT;
+					break;
+				case HTMLElementDeclaration.OMIT_END_MUST :
+					type = HTMLCMProperties.Values.OMIT_END_MUST;
+					break;
+				case HTMLElementDeclaration.OMIT_NONE :
+				// nothing to do.
+				default :
+					break;
+			}
+			return type;
+		}
+	}
+
+	/*
+	 * "inclusion"
+	 */
+	class PPInclusion extends AbstractElementPropertyProvider {
+		public PPInclusion() {
+			super();
+		}
+
+		protected Object getElementProperty(HTMLPropertyDeclaration decl) {
+			return decl.getInclusion();
+		}
+	}
+
+	public static PropertyProvider getProvider(String propName) {
+		PropertyProviderFactory factory = getInstance();
+		PropertyProvider pp = (PropertyProvider) factory.registry.get(propName);
+		if (pp != null)
+			return pp;
+
+		pp = factory.create(propName);
+		if (pp == null)
+			return factory.defaultProvider;
+
+		factory.registry.put(propName, pp);
+		return pp;
+	}
+
+	private static PropertyProviderFactory instance = null;
+
+	private synchronized static PropertyProviderFactory getInstance() {
+		if (instance != null)
+			return instance;
+		instance = new PropertyProviderFactory();
+		return instance;
+	}
+
+	private Hashtable registry = new Hashtable();
+	private PropertyProvider defaultProvider = new DefaultProvider();
+
+	private PropertyProviderFactory() {
+		super();
+	}
+
+	private PropertyProvider create(String propName) {
+		PropertyProvider pp = null;
+		if (propName.equals(HTMLCMProperties.IS_JSP))
+			pp = new PPIsJSP();
+		else if (propName.equals(HTMLCMProperties.IS_XHTML))
+			pp = new PPIsXHTML();
+		else if (propName.equals(HTMLCMProperties.IS_SSI))
+			pp = new PPIsSSI();
+		else if (propName.equals(HTMLCMProperties.LAYOUT_TYPE))
+			pp = new PPLayoutType();
+		else if (propName.equals(HTMLCMProperties.LINE_BREAK_HINT))
+			pp = new PPLineBreakHint();
+		else if (propName.equals(HTMLCMProperties.PROHIBITED_ANCESTORS))
+			pp = new PPProhibitedAncestors();
+		else if (propName.equals(HTMLCMProperties.SHOULD_KEEP_SPACE))
+			pp = new PPShouldKeepSpace();
+		else if (propName.equals(HTMLCMProperties.SHOULD_INDENT_CHILD_SOURCE))
+			pp = new PPShouldIndentChildSource();
+		else if (propName.equals(HTMLCMProperties.TERMINATORS))
+			pp = new PPTerminators();
+		else if (propName.equals(HTMLCMProperties.TAGINFO))
+			pp = new PPTagInfo();
+		else if (propName.equals(HTMLCMProperties.OMIT_TYPE))
+			pp = new PPOmitType();
+		else if (propName.equals(HTMLCMProperties.INCLUSION))
+			pp = new PPInclusion();
+
+		return pp;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/ssi/SSICMDocumentFactory.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/ssi/SSICMDocumentFactory.java
new file mode 100644
index 0000000..3a4dfd7
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentmodel/ssi/SSICMDocumentFactory.java
@@ -0,0 +1,158 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentmodel.ssi;
+
+import java.util.Hashtable;
+import java.util.Iterator;
+
+import org.eclipse.wst.html.core.internal.contentmodel.HTMLCMDocumentFactory;
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.provisional.contentmodel.CMDocType;
+
+/**
+ * CMDocument factory for SSI documents.
+ */
+public final class SSICMDocumentFactory {
+
+	private final static String PREFIX = "SSI";//$NON-NLS-1$
+	private final static String DOC_TYPE_NAME = "SSI";//$NON-NLS-1$
+
+	static class CMNamespaceImpl implements CMNamespace {
+		public CMNamespaceImpl() {
+			super();
+		}
+
+		public String getPrefix() {
+			return PREFIX;
+		}
+
+		public String getURI() {
+			return ""; //$NON-NLS-1$
+		}
+
+		public String getNodeName() {
+			return DOC_TYPE_NAME;
+		}
+
+		public int getNodeType() {
+			return CMNode.NAME_SPACE;
+		}
+
+		public boolean supports(String propertyName) {
+			return false;
+		}
+
+		public Object getProperty(String propertyName) {
+			return null;
+		}
+
+	}
+
+	static class CMDocImpl implements CMDocument {
+		private static CMDocument hcm = HTMLCMDocumentFactory.getCMDocument(CMDocType.HTML_DOC_TYPE);
+
+		static class Elements implements CMNamedNodeMap {
+			private static String[] names = {HTML40Namespace.ElementName.SSI_CONFIG, HTML40Namespace.ElementName.SSI_ECHO, HTML40Namespace.ElementName.SSI_EXEC, HTML40Namespace.ElementName.SSI_FSIZE, HTML40Namespace.ElementName.SSI_FLASTMOD, HTML40Namespace.ElementName.SSI_INCLUDE, HTML40Namespace.ElementName.SSI_PRINTENV, HTML40Namespace.ElementName.SSI_SET};
+			private Hashtable map = new Hashtable();
+
+			public Elements() {
+				CMNamedNodeMap elems = hcm.getElements();
+				for (int i = 0; i < names.length; i++) {
+					String name = names[i];
+					CMElementDeclaration dec = (CMElementDeclaration) elems.getNamedItem(name);
+					if (dec != null)
+						map.put(name, dec);
+				}
+			}
+
+			public int getLength() {
+				return map.size();
+			}
+
+			public CMNode getNamedItem(String name) {
+				String cooked = getCanonicalName(name);
+				if (!map.containsKey(cooked))
+					return null;
+				return (CMNode) map.get(cooked);
+			}
+
+			public CMNode item(int index) {
+				Iterator iter = iterator();
+				while (iter.hasNext()) {
+					Object node = iter.next();
+					if (--index < 0)
+						return (CMNode) node;
+				}
+				return null;
+			}
+
+			public Iterator iterator() {
+				return map.values().iterator();
+			}
+
+			private String getCanonicalName(String rawName) {
+				return rawName.toUpperCase();
+			}
+		}
+
+		static private Elements elements = new Elements();
+
+
+		public CMDocImpl() {
+			super();
+		}
+
+		public String getNodeName() {
+			return ""; //$NON-NLS-1$
+		}
+
+		public int getNodeType() {
+			return CMNode.DOCUMENT;
+		}
+
+		public CMNamedNodeMap getElements() {
+			return elements;
+		}
+
+		public CMNamedNodeMap getEntities() {
+			return null;
+		}
+
+		public CMNamespace getNamespace() {
+			return ssins;
+		}
+
+		public Object getProperty(String propertyName) {
+			return null;
+		}
+
+		public boolean supports(String propertyName) {
+			return false;
+		}
+	}
+
+	private static CMNamespace ssins = new CMNamespaceImpl();
+	private static CMDocument mycm = new CMDocImpl();
+
+	private SSICMDocumentFactory() {
+		super();
+	}
+
+	public static CMDocument getCMDocument() {
+		return mycm;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentproperties/HTMLContentProperties.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentproperties/HTMLContentProperties.java
new file mode 100644
index 0000000..f76fd8e
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentproperties/HTMLContentProperties.java
@@ -0,0 +1,194 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentproperties;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ProjectScope;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.wst.html.core.internal.HTMLCorePlugin;
+import org.eclipse.wst.html.core.internal.Logger;
+import org.osgi.service.prefs.BackingStoreException;
+import org.osgi.service.prefs.Preferences;
+
+/**
+ * Properties constants used by HTML. Clients should only read and modify the
+ * HTML properties programmatically using this class.
+ * 
+ * @since 1.1
+ */
+public class HTMLContentProperties {
+	static final String HTMLCORE_ID = HTMLCorePlugin.getDefault().getBundle().getSymbolicName();
+	private static final String PROJECT_KEY = "<project>"; //$NON-NLS-1$
+
+	/**
+	 * The default document type to use when none is specified.
+	 * <p>
+	 * Value is of type <code>String</code>.
+	 * </p>
+	 */
+	public static final String DOCUMENT_TYPE = "document-type"; //$NON-NLS-1$
+
+	/**
+	 * Generates a preference key based on resourcePath
+	 * 
+	 * @param resourcePath
+	 *            the path the key will be based off of
+	 * @return preference key based on resourcePath (basically the
+	 *         resourcePath without the filename); PROJECT_KEY if resourcePath
+	 *         is null
+	 */
+	static String getKeyFor(IPath resourcePath) {
+		String key = PROJECT_KEY;
+		if (resourcePath != null && resourcePath.segmentCount() > 1) {
+			key = resourcePath.removeFirstSegments(1).toString();
+		}
+		return key;
+	}
+
+	/**
+	 * Get the preferences node associated with the given project scope and
+	 * preference key (subNode) If create is true, the preference node will be
+	 * created if one does not already exist
+	 * 
+	 * @param project
+	 *            the project the preference node is under
+	 * @param preferenceKey
+	 *            the subnode/category the preference node is located in
+	 * @param create
+	 *            if true, a preference node will be created if one does not
+	 *            already exist
+	 * @return Preferences associated with the given project scope and
+	 *         preference key. null if one could not be found and create is
+	 *         false
+	 */
+	static Preferences getPreferences(IProject project, String preferenceKey, boolean create) {
+		if (create)
+			// create all nodes down to the one we are interested in
+			return new ProjectScope(project).getNode(HTMLCORE_ID).node(preferenceKey);
+		// be careful looking up for our node so not to create any nodes as
+		// side effect
+		Preferences node = Platform.getPreferencesService().getRootNode().node(ProjectScope.SCOPE);
+		try {
+			// TODO once bug 90500 is fixed, should be as simple as this:
+			// String path = project.getName() + IPath.SEPARATOR +
+			// ResourcesPlugin.PI_RESOURCES + IPath.SEPARATOR +
+			// ENCODING_PREF_NODE;
+			// return node.nodeExists(path) ? node.node(path) : null;
+			// for now, take the long way
+			if (!node.nodeExists(project.getName()))
+				return null;
+			node = node.node(project.getName());
+			if (!node.nodeExists(HTMLCORE_ID))
+				return null;
+			node = node.node(HTMLCORE_ID);
+			if (!node.nodeExists(preferenceKey))
+				return null;
+			return node.node(preferenceKey);
+		}
+		catch (BackingStoreException e) {
+			// nodeExists failed
+			Logger.log(Logger.WARNING_DEBUG, "Could not retrieve preference node", e); //$NON-NLS-1$
+		}
+		return null;
+	}
+
+	/**
+	 * Returns the value for the given key in the given context.
+	 * 
+	 * @param key
+	 *            The property key
+	 * @param resource
+	 *            The current context or <code>null</code> if no context is
+	 *            available and the workspace setting should be taken. Note
+	 *            that passing <code>null</code> should be avoided.
+	 * @param recurse
+	 *            whether the parent should be queried till property is found
+	 * @return Returns the current value for the key.
+	 * @since 1.1
+	 */
+	public static String getProperty(String key, IResource resource, boolean recurse) {
+		String val = null;
+		// boolean preferenceFound = false;
+		if (resource != null) {
+			IProject project = resource.getProject();
+			if (project != null) {
+				Preferences preferences = getPreferences(project, key, false);
+				if (preferences != null) {
+					val = internalGetProperty(resource, recurse, preferences);
+					// preferenceFound = true;
+				}
+			}
+		}
+		// Workbench preference may not be needed so leave out for now
+		// // no preferences found - for performance reasons,
+		// // short-circuit
+		// // lookup by falling back to workspace's default
+		// // setting
+		// if (!preferenceFound)
+		// val = getWorkbenchPreference(key);
+		return val;
+	}
+
+	private static String internalGetProperty(IResource resource, boolean recurse, Preferences preferences) {
+		String value = preferences.get(getKeyFor(resource.getFullPath()), null);
+		if (value == null && resource != resource.getProject() && recurse) {
+			value = preferences.get(getKeyFor(null), null);
+		}
+
+		// Workbench preference may not be needed so leave out for now
+		// // ensure we default to the workspace preference if none is found
+		// return value == null ? getWorkbenchPreference(key) : value;
+		return value;
+	}
+
+	/**
+	 * Sets the value for the given key in the given context.
+	 * 
+	 * @param key
+	 *            The property key
+	 * @param resource
+	 *            The current context. Note context cannot be
+	 *            <code>null</code>.
+	 * @param value
+	 *            The value to set for the key. If value is <code>null</code>
+	 *            the key is removed from properties.
+	 * @since 1.1
+	 */
+	public static void setProperty(String key, IResource resource, String value) throws CoreException {
+		if (resource != null) {
+			IProject project = resource.getProject();
+			if (project != null) {
+				Preferences preferences = getPreferences(project, key, true);
+				if (value == null)
+					preferences.remove(getKeyFor(resource.getFullPath()));
+				else
+					preferences.put(getKeyFor(resource.getFullPath()), value);
+				try {
+					// save changes
+					preferences.flush();
+				}
+				catch (BackingStoreException e) {
+					throw new CoreException(new Status(IStatus.ERROR, HTMLCORE_ID, IStatus.ERROR, "Unable to set property", e)); //$NON-NLS-1$
+				}
+			}
+		}
+		// Workbench preference may not be needed so leave out for now
+		// just set a preference in the instance scope
+		// if (!preferenceFound) {
+		// setWorkbenchPreference(key);
+		// }
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentproperties/HTMLContentPropertiesManager.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentproperties/HTMLContentPropertiesManager.java
new file mode 100644
index 0000000..41f03c8
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contentproperties/HTMLContentPropertiesManager.java
@@ -0,0 +1,238 @@
+/*******************************************************************************
+ * Copyright (c) 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contentproperties;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResourceChangeEvent;
+import org.eclipse.core.resources.IResourceChangeListener;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.resources.IResourceStatus;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.MultiStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.wst.html.core.internal.HTMLCoreMessages;
+import org.eclipse.wst.html.core.internal.Logger;
+import org.osgi.framework.Bundle;
+import org.osgi.service.prefs.BackingStoreException;
+import org.osgi.service.prefs.Preferences;
+
+public class HTMLContentPropertiesManager {
+	public HTMLContentPropertiesManager() {
+		super();
+		fResourceChangeListener = new ResourceChangeListener();
+		fJob = new ContentPropertiesManagerJob();
+	}
+
+	private static HTMLContentPropertiesManager _instance = null;
+	private IResourceChangeListener fResourceChangeListener;
+	ContentPropertiesManagerJob fJob;
+
+	/**
+	 * This job implementation is used to allow the resource change listener
+	 * to schedule operations that need to modify the workspace.
+	 */
+	private class ContentPropertiesManagerJob extends Job {
+		private static final int PROPERTIES_UPDATE_DELAY = 500;
+		private List asyncChanges = new ArrayList();
+
+		public ContentPropertiesManagerJob() {
+			super(HTMLCoreMessages.HTMLContentPropertiesManager_Updating);
+			setSystem(true);
+			setPriority(Job.INTERACTIVE);
+		}
+
+		public void addChanges(Set newChanges) {
+			if (newChanges.isEmpty())
+				return;
+			synchronized (asyncChanges) {
+				asyncChanges.addAll(newChanges);
+				asyncChanges.notify();
+			}
+			schedule(PROPERTIES_UPDATE_DELAY);
+		}
+
+		public IProject getNextChange() {
+			synchronized (asyncChanges) {
+				return asyncChanges.isEmpty() ? null : (IProject) asyncChanges.remove(asyncChanges.size() - 1);
+			}
+		}
+
+		protected IStatus run(IProgressMonitor monitor) {
+			MultiStatus result = new MultiStatus(HTMLContentProperties.HTMLCORE_ID, IResourceStatus.FAILED_SETTING_CHARSET, HTMLCoreMessages.HTMLContentPropertiesManager_Updating, null);
+			monitor = monitor == null ? new NullProgressMonitor() : monitor;
+			try {
+				monitor.beginTask(HTMLCoreMessages.HTMLContentPropertiesManager_Updating, asyncChanges.size());
+				try {
+					IProject next;
+					while ((next = getNextChange()) != null) {
+						// just exit if the system is shutting down or has
+						// been shut down
+						// it is too late to change the workspace at this
+						// point anyway
+						if (Platform.getBundle("org.eclipse.osgi").getState() != Bundle.ACTIVE) //$NON-NLS-1$
+							return Status.OK_STATUS;
+						try {
+							// save the preferences nodes
+							if (next.isAccessible()) {
+								// save document type preferences
+								Preferences projectPrefs = HTMLContentProperties.getPreferences(next, HTMLContentProperties.DOCUMENT_TYPE, false);
+								if (projectPrefs != null)
+									projectPrefs.flush();
+							}
+						}
+						catch (BackingStoreException e) {
+							// we got an error saving
+							String detailMessage = NLS.bind(HTMLCoreMessages.HTMLContentPropertiesManager_Problems_Updating, next.getFullPath());
+							result.add(new Status(1 << (IResourceStatus.FAILED_SETTING_CHARSET % 100 / 33), ResourcesPlugin.PI_RESOURCES, IResourceStatus.FAILED_SETTING_CHARSET, detailMessage, e));
+						}
+					}
+					monitor.worked(1);
+				}
+				catch (OperationCanceledException e) {
+					throw e;
+				}
+			}
+			finally {
+				monitor.done();
+			}
+			return result;
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see org.eclipse.core.runtime.jobs.Job#shouldRun()
+		 */
+		public boolean shouldRun() {
+			synchronized (asyncChanges) {
+				return !asyncChanges.isEmpty();
+			}
+		}
+	}
+
+	class ResourceChangeListener implements IResourceChangeListener {
+		private void processEntryChanges(IResourceDelta projectDelta, Set projectsToSave) {
+			// check each resource with web content setting to see if it has
+			// been moved/deleted
+			boolean resourceChanges = false;
+
+			// project affected
+			IProject currentProject = (IProject) projectDelta.getResource();
+
+			resourceChanges = processPreferences(currentProject, HTMLContentProperties.DOCUMENT_TYPE, projectDelta, projectsToSave);
+
+			// if there was a preference key change, need to save preferences
+			if (resourceChanges)
+				projectsToSave.add(currentProject);
+		}
+
+		/**
+		 * Goes through all the resource-dependent preferences associated with
+		 * currentProject & key and updates the preference keys if needed
+		 * based on projectDelta
+		 * 
+		 * @param currentProject
+		 *            current project of the preferences to be looked at
+		 * @param key
+		 *            current key/subcategory of the preferences to be looked
+		 *            at
+		 * @param projectDelta
+		 *            the changes to process the preference keys against
+		 * @param projectsToSave
+		 *            the projects that need to be updated/saved
+		 * @return true if currentProject's preferences were modified
+		 */
+		private boolean processPreferences(IProject currentProject, String key, IResourceDelta projectDelta, Set projectsToSave) {
+			boolean resourceChanges = false;
+
+			// get the project-key preference node
+			Preferences projectPrefs = HTMLContentProperties.getPreferences(currentProject, key, false);
+			if (projectPrefs == null)
+				// no preferences for this project-key, just bail
+				return false;
+			String[] affectedResources;
+			try {
+				affectedResources = projectPrefs.keys();
+			}
+			catch (BackingStoreException e) {
+				// problems with the project scope... we gonna miss the
+				// changes (but will log)
+				Logger.log(Logger.WARNING_DEBUG, "Problem retreiving JSP Fragment preferences", e); //$NON-NLS-1$
+				return false;
+			}
+
+			// go through each preference key (which is really a file name)
+			for (int i = 0; i < affectedResources.length; i++) {
+				// see if preference key/file name was file that was changed
+				IResourceDelta memberDelta = projectDelta.findMember(new Path(affectedResources[i]));
+				// no changes for the given resource
+				if (memberDelta == null)
+					continue;
+				if (memberDelta.getKind() == IResourceDelta.REMOVED) {
+					resourceChanges = true;
+					// remove the setting for the original location
+					String currentValue = projectPrefs.get(affectedResources[i], null);
+					projectPrefs.remove(affectedResources[i]);
+					if ((memberDelta.getFlags() & IResourceDelta.MOVED_TO) != 0) {
+						// if moving, copy the setting for the new location
+						IProject targetProject = ResourcesPlugin.getWorkspace().getRoot().getProject(memberDelta.getMovedToPath().segment(0));
+						Preferences targetPrefs = HTMLContentProperties.getPreferences(targetProject, key, true);
+						targetPrefs.put(HTMLContentProperties.getKeyFor(memberDelta.getMovedToPath()), currentValue);
+						if (targetProject != currentProject)
+							projectsToSave.add(targetProject);
+					}
+				}
+			}
+			return resourceChanges;
+		}
+
+		/**
+		 * For any change to the encoding file or any resource with encoding
+		 * set, just discard the cache for the corresponding project.
+		 */
+		public void resourceChanged(IResourceChangeEvent event) {
+			IResourceDelta delta = event.getDelta();
+			if (delta == null)
+				return;
+			IResourceDelta[] projectDeltas = delta.getAffectedChildren();
+			// process each project in the delta
+			Set projectsToSave = new HashSet();
+			for (int i = 0; i < projectDeltas.length; i++)
+				// nothing to do if a project has been added/removed/moved
+				if (projectDeltas[i].getKind() == IResourceDelta.CHANGED && (projectDeltas[i].getFlags() & IResourceDelta.OPEN) == 0)
+					processEntryChanges(projectDeltas[i], projectsToSave);
+			fJob.addChanges(projectsToSave);
+		}
+	}
+
+	public synchronized static void startup() {
+		_instance = new HTMLContentPropertiesManager();
+		ResourcesPlugin.getWorkspace().addResourceChangeListener(_instance.fResourceChangeListener, IResourceChangeEvent.POST_CHANGE);
+	}
+
+	public synchronized static void shutdown() {
+		ResourcesPlugin.getWorkspace().removeResourceChangeListener(_instance.fResourceChangeListener);
+		_instance = null;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contenttype/AbstractResourceEncodingDetector.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contenttype/AbstractResourceEncodingDetector.java
new file mode 100644
index 0000000..8b359e6
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contenttype/AbstractResourceEncodingDetector.java
@@ -0,0 +1,261 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contenttype;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.nio.charset.Charset;
+import java.nio.charset.IllegalCharsetNameException;
+import java.nio.charset.UnsupportedCharsetException;
+
+import org.eclipse.core.resources.IStorage;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.wst.sse.core.internal.encoding.CodedIO;
+import org.eclipse.wst.sse.core.internal.encoding.EncodingMemento;
+import org.eclipse.wst.sse.core.internal.encoding.IResourceCharsetDetector;
+
+
+public abstract class AbstractResourceEncodingDetector implements IResourceCharsetDetector {
+
+	protected EncodingMemento fEncodingMemento;
+
+	protected boolean fHeaderParsed;
+
+	protected Reader fReader;
+
+	/**
+	 * 
+	 */
+	public AbstractResourceEncodingDetector() {
+		super();
+	}
+
+	/**
+	 * Note: once this instance is created, trace info still needs to be
+	 * appended by caller, depending on the context its created.
+	 */
+	private void createEncodingMemento(String detectedCharsetName) {
+		fEncodingMemento = new EncodingMemento();
+		fEncodingMemento.setJavaCharsetName(getAppropriateJavaCharset(detectedCharsetName));
+		fEncodingMemento.setDetectedCharsetName(detectedCharsetName);
+		// TODO: if detectedCharset and spec default is
+		// null, need to use "work
+		// bench based" defaults.
+		fEncodingMemento.setAppropriateDefault(getSpecDefaultEncoding());
+	}
+
+	/**
+	 * convience method all subclasses can use (but not override)
+	 * 
+	 * @param detectedCharsetName
+	 * @param reason
+	 */
+	final protected void createEncodingMemento(String detectedCharsetName, String reason) {
+		createEncodingMemento(detectedCharsetName);
+	}
+
+	/**
+	 * convience method all subclasses can use (but not override)
+	 */
+	final protected void ensureInputSet() {
+		if (fReader == null) {
+			throw new IllegalStateException("input must be set before use"); //$NON-NLS-1$
+		}
+	}
+
+	/**
+	 * This method can return null, if invalid charset name (in which case
+	 * "appropriateDefault" should be used, if a name is really need for some
+	 * "save anyway" cases).
+	 * 
+	 * @param detectedCharsetName
+	 * @return
+	 */
+	private String getAppropriateJavaCharset(String detectedCharsetName) {
+		String result = null;
+		// 1. Check explicit mapping overrides from
+		// property file -- its here we pick up "rules" for cases
+		// that are not even in Java
+		result = CodedIO.checkMappingOverrides(detectedCharsetName);
+		// 2. Use the "canonical" name from JRE mappings
+		// Note: see Charset JavaDoc, the name you get one
+		// with can be alias,
+		// the name you get back is "standard" name.
+		Charset javaCharset = null;
+		try {
+			javaCharset = Charset.forName(detectedCharsetName);
+		}
+		catch (UnsupportedCharsetException e) {
+			// only set invalid, if result is same as detected -- they won't
+			// be equal if
+			// overridden
+			if (result != null && result.equals(detectedCharsetName)) {
+				fEncodingMemento.setInvalidEncoding(detectedCharsetName);
+			}
+		}
+		catch (IllegalCharsetNameException e) {
+			// only set invalid, if result is same as detected -- they won't
+			// be equal if
+			// overridden
+			if (result != null && result.equals(detectedCharsetName)) {
+				fEncodingMemento.setInvalidEncoding(detectedCharsetName);
+			}
+		}
+		// give priority to java cononical name, if present
+		if (javaCharset != null) {
+			result = javaCharset.name();
+			// but still allow overrides
+			result = CodedIO.checkMappingOverrides(result);
+		}
+		return result;
+	}
+
+	public String getEncoding() throws IOException {
+		return getEncodingMemento().getDetectedCharsetName();
+	}
+
+	// to ensure consist overall rules used, we'll mark as
+	// final,
+	// and require subclasses to provide certain pieces of
+	// the
+	// implementation
+	public EncodingMemento getEncodingMemento() throws IOException {
+		ensureInputSet();
+		if (!fHeaderParsed) {
+			parseInput();
+			// we keep track of if header's already been
+			// parse, so can make
+			// multiple 'get' calls, without causing
+			// reparsing.
+			fHeaderParsed = true;
+			// Note: there is a "hidden assumption" here
+			// that an empty
+			// string in content should be treated same as
+			// not present.
+		}
+		if (fEncodingMemento == null) {
+			handleSpecDefault();
+		}
+		if (fEncodingMemento == null) {
+			// safty net
+			fEncodingMemento = new NullMemento();
+		}
+		return fEncodingMemento;
+	}
+
+	/**
+	 * This is to return a default encoding -- as specified by an industry
+	 * content type spec -- when not present in the stream, for example, XML
+	 * specifies UTF-8, JSP specifies ISO-8859-1. This method should return
+	 * null if there is no such "spec default".
+	 */
+	abstract public String getSpecDefaultEncoding();
+
+	public EncodingMemento getSpecDefaultEncodingMemento() {
+		resetAll();
+		EncodingMemento result = null;
+		String enc = getSpecDefaultEncoding();
+		if (enc != null) {
+			createEncodingMemento(enc, EncodingMemento.DEFAULTS_ASSUMED_FOR_EMPTY_INPUT);
+			fEncodingMemento.setAppropriateDefault(enc);
+			result = fEncodingMemento;
+		}
+		return result;
+	}
+
+	private void handleSpecDefault() {
+		String encodingName;
+		encodingName = getSpecDefaultEncoding();
+		if (encodingName != null) {
+			// createEncodingMemento(encodingName,
+			// EncodingMemento.USED_CONTENT_TYPE_DEFAULT);
+			fEncodingMemento = new EncodingMemento();
+			fEncodingMemento.setJavaCharsetName(encodingName);
+			fEncodingMemento.setAppropriateDefault(encodingName);
+		}
+	}
+
+	/**
+	 * Every subclass must provide a way to parse the input. This method has
+	 * several critical responsibilities:
+	 * <li>set the fEncodingMemento field appropriately, according to the
+	 * results of the parse of fReader.</li>
+	 * <li>set fHarderParsed to true, to avoid wasted re-parsing.</li>
+	 */
+	abstract protected void parseInput() throws IOException;
+
+	/**
+	 * 
+	 */
+	private void resetAll() {
+		fReader = null;
+		fHeaderParsed = false;
+		fEncodingMemento = null;
+	}
+
+	/**
+	 * 
+	 */
+	public void set(InputStream inputStream) {
+		resetAll();
+		fReader = new ByteReader(inputStream);
+		try {
+			fReader.mark(CodedIO.MAX_MARK_SIZE);
+		}
+		catch (IOException e) {
+			// impossible, since we know ByteReader
+			// supports marking
+			throw new Error(e);
+		}
+	}
+
+	/**
+	 * 
+	 */
+	public void set(IStorage iStorage) throws CoreException {
+		resetAll();
+		InputStream inputStream = iStorage.getContents();
+		InputStream resettableStream = new BufferedInputStream(inputStream, CodedIO.MAX_BUF_SIZE);
+		resettableStream.mark(CodedIO.MAX_MARK_SIZE);
+		set(resettableStream);
+		// TODO we'll need to "remember" IFile, or
+		// get its (or its project's) settings, in case
+		// those are needed to handle cases when the
+		// encoding is not in the file stream.
+	}
+
+	/**
+	 * Note: this is not part of interface to help avoid confusion ... it
+	 * expected this Reader is a well formed character reader ... that is, its
+	 * all ready been determined to not be a unicode marked input stream. And,
+	 * its assumed to be in the correct position, at position zero, ready to
+	 * read first character.
+	 */
+	public void set(Reader reader) {
+		resetAll();
+		fReader = reader;
+		if (!fReader.markSupported()) {
+			fReader = new BufferedReader(fReader);
+		}
+		try {
+			fReader.mark(CodedIO.MAX_MARK_SIZE);
+		}
+		catch (IOException e) {
+			// impossble, since we just checked if markable
+			throw new Error(e);
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contenttype/ByteReader.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contenttype/ByteReader.java
new file mode 100644
index 0000000..98199b0
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contenttype/ByteReader.java
@@ -0,0 +1,109 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contenttype;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+
+import org.eclipse.wst.sse.core.internal.encoding.CodedIO;
+
+/**
+ * This is an "adapter" class, simply to get in input stream to act like a
+ * reader. We could not use InputStreamReader directly because its internal
+ * buffers are not controllable, and it sometimes pulls too much out of input
+ * stream (even when it wasn't needed for our purposes).
+ * 
+ * The use of this class is highly specialized and by not means meant to be
+ * general purpose. Its use is restricted to those cases where the input
+ * stream can be regarded as ascii just long enough to determine what the real
+ * encoding should be.
+ */
+
+public class ByteReader extends Reader {
+
+	
+	public static final int DEFAULT_BUFFER_SIZE = CodedIO.MAX_BUF_SIZE;
+
+	protected byte[] fBuffer;
+
+	protected InputStream fInputStream;
+
+	protected ByteReader() {
+		super();
+	}
+
+	public ByteReader(InputStream inputStream) {
+		this(inputStream, DEFAULT_BUFFER_SIZE);
+		if (!inputStream.markSupported()) {
+			throw new IllegalArgumentException("ByteReader is required to have a resettable stream"); //$NON-NLS-1$
+		}
+	}
+
+	public ByteReader(InputStream inputStream, int size) {
+		this.fInputStream = inputStream;
+		if (!inputStream.markSupported()) {
+			throw new IllegalArgumentException("ByteReader is required to have a resettable stream"); //$NON-NLS-1$
+		}
+		this.fBuffer = new byte[size];
+
+	}
+
+	public void close() throws IOException {
+		this.fInputStream.close();
+	}
+
+	public void mark(int readAheadLimit) {
+		this.fInputStream.mark(readAheadLimit);
+	}
+
+	public boolean markSupported() {
+		return true;
+	}
+
+	public int read() throws IOException {
+		int b0 = this.fInputStream.read();
+		return (b0 & 0x00FF);
+	}
+
+	public int read(char ch[], int offset, int length) throws IOException {
+		if (length > this.fBuffer.length) {
+			length = this.fBuffer.length;
+		}
+
+		int count = this.fInputStream.read(this.fBuffer, 0, length);
+
+		for (int i = 0; i < count; i++) {
+			int b0 = this.fBuffer[i];
+			// the 0x00FF is to "lose" the negative bits filled in the byte to
+			// int conversion
+			// (and which would be there if cast directly from byte to char).
+			char c0 = (char) (b0 & 0x00FF);
+			ch[offset + i] = c0;
+		}
+		return count;
+	}
+
+	public boolean ready() throws IOException {
+		return this.fInputStream.available() > 0;
+	}
+
+	public void reset() throws IOException {
+		this.fInputStream.reset();
+	}
+
+	public long skip(long n) throws IOException {
+		return this.fInputStream.skip(n);
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contenttype/ContentDescriberForHTML.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contenttype/ContentDescriberForHTML.java
new file mode 100644
index 0000000..8a70983
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contenttype/ContentDescriberForHTML.java
@@ -0,0 +1,231 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contenttype;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+
+import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.core.runtime.content.IContentDescriber;
+import org.eclipse.core.runtime.content.IContentDescription;
+import org.eclipse.core.runtime.content.ITextContentDescriber;
+import org.eclipse.wst.sse.core.internal.encoding.EncodingMemento;
+import org.eclipse.wst.sse.core.internal.encoding.IContentDescriptionExtended;
+import org.eclipse.wst.sse.core.internal.encoding.IResourceCharsetDetector;
+
+/**
+ * 
+ * ContentDescriberForHTML
+ * 
+ * A few design principles to remember with content describers:
+ * <ul> 
+ * <li>Remember not to store values/data in the descriptions array of properties, 
+ * especially not large objects! and even no value that is already the default value, 
+ * since those description properties are cached per session, so can add up in memory. 
+ * <li>Remember that a ContentDescriber instance becomes a "root object" in the 
+ * ContentDescriberManager (that is, always in memory, never GC'd), so it should 
+ * not have any instance or state data since it would always become stale and 
+ * "hold on" to objects unneccessarily. 
+ * </ul>
+ */
+
+public final class ContentDescriberForHTML implements ITextContentDescriber {
+
+	final private static QualifiedName[] SUPPORTED_OPTIONS = {IContentDescription.CHARSET, IContentDescription.BYTE_ORDER_MARK, IContentDescriptionExtended.DETECTED_CHARSET, IContentDescriptionExtended.UNSUPPORTED_CHARSET, IContentDescriptionExtended.APPROPRIATE_DEFAULT};
+
+	public int describe(InputStream contents, IContentDescription description) throws IOException {
+		int result = IContentDescriber.INDETERMINATE;
+
+		if (description == null) {
+			result = computeValidity(contents);
+		}
+		else {
+			calculateSupportedOptions(contents, description);
+			// assummming we should return same 'validity' value we did
+			// when called before. (technically, could be a performance issue
+			// in future, so might want to check if any 'ol value would
+			// be ok here.
+			result = computeValidity(contents);
+		}
+
+		return result;
+	}
+
+	public int describe(Reader contents, IContentDescription description) throws IOException {
+		int result = IContentDescriber.INDETERMINATE;
+
+		if (description == null) {
+			result = computeValidity(contents);
+		}
+		else {
+			calculateSupportedOptions(contents, description);
+			// assummming we should return same 'validity' value we did
+			// when called before. (technically, could be a performance issue
+			// in future, so might want to check if hard coded 'valid' would
+			// be ok here.
+			result = computeValidity(contents);
+		}
+
+		return result;
+	}
+
+	public QualifiedName[] getSupportedOptions() {
+
+		return SUPPORTED_OPTIONS;
+	}
+
+	private void calculateSupportedOptions(InputStream contents, IContentDescription description) throws IOException {
+		if (isRelevent(description)) {
+			IResourceCharsetDetector detector = getDetector();
+			detector.set(contents);
+			handleCalculations(description, detector);
+		}
+	}
+
+	/**
+	 * @param contents
+	 * @param description
+	 * @throws IOException
+	 */
+	private void calculateSupportedOptions(Reader contents, IContentDescription description) throws IOException {
+		if (isRelevent(description)) {
+			IResourceCharsetDetector detector = getDetector();
+			detector.set(contents);
+			handleCalculations(description, detector);
+		}
+	}
+
+	private int computeValidity(InputStream inputStream) {
+		// currently no contents specific check for valid HTML contents
+		// (this may change once we add XHTML content type)
+		return IContentDescriber.INDETERMINATE;
+	}
+
+	private int computeValidity(Reader reader) {
+		// currently no contents specific check for valid HTML contents
+		// (this may change once we add XHTML content type)
+		return IContentDescriber.INDETERMINATE;
+	}
+
+	private IResourceCharsetDetector getDetector() {
+
+		return new HTMLResourceEncodingDetector();
+
+	}
+
+	/**
+	 * @param description
+	 * @param detector
+	 * @throws IOException
+	 */
+	private void handleCalculations(IContentDescription description, IResourceCharsetDetector detector) throws IOException {
+
+		EncodingMemento encodingMemento = ((HTMLResourceEncodingDetector) detector).getEncodingMemento();
+		// TODO: I need to verify to see if this BOM work is always done
+		// by text type.
+		Object detectedByteOrderMark = encodingMemento.getUnicodeBOM();
+		if (detectedByteOrderMark != null) {
+			Object existingByteOrderMark = description.getProperty(IContentDescription.BYTE_ORDER_MARK);
+			// not sure why would ever be different, so if is different, may
+			// need to "push" up into base.
+			if (!detectedByteOrderMark.equals(existingByteOrderMark))
+				description.setProperty(IContentDescription.BYTE_ORDER_MARK, detectedByteOrderMark);
+		}
+
+
+		if (!encodingMemento.isValid()) {
+			/*
+			 * note: after setting here, its the mere presence of
+			 * IContentDescriptionExtended.UNSUPPORTED_CHARSET in the
+			 * resource's description that can be used to determine if invalid
+			 * in those cases, the "detected" property contains an
+			 * "appropriate default" to use.
+			 */
+			description.setProperty(IContentDescriptionExtended.UNSUPPORTED_CHARSET, encodingMemento.getInvalidEncoding());
+			description.setProperty(IContentDescriptionExtended.APPROPRIATE_DEFAULT, encodingMemento.getAppropriateDefault());
+		}
+
+		Object detectedCharset = encodingMemento.getDetectedCharsetName();
+		Object javaCharset = encodingMemento.getJavaCharsetName();
+
+		// we always include detected, if its different than java
+		handleDetectedSpecialCase(description, detectedCharset, javaCharset);
+
+		if (javaCharset != null) {
+			Object existingCharset = description.getProperty(IContentDescription.CHARSET);
+			if (javaCharset.equals(existingCharset)) {
+				handleDetectedSpecialCase(description, detectedCharset, javaCharset);
+			}
+			else {
+				// we may need to add what we found, but only need to add
+				// if different from default.the
+				Object defaultCharset = detector.getSpecDefaultEncoding();
+				if (defaultCharset != null) {
+					if (!defaultCharset.equals(javaCharset)) {
+						description.setProperty(IContentDescription.CHARSET, javaCharset);
+					}
+				}
+				else {
+					// assuming if there is no spec default, we always need to
+					// add, I'm assuming
+					description.setProperty(IContentDescription.CHARSET, javaCharset);
+				}
+			}
+		}
+
+	}
+
+	private void handleDetectedSpecialCase(IContentDescription description, Object detectedCharset, Object javaCharset) {
+		// since equal, we don't need to add, but if our detected version is
+		// different than
+		// javaCharset, then we should add it. This will happen, for example,
+		// if there's
+		// differences in case, or differences due to override properties
+		if (detectedCharset != null) {
+			// if (!detectedCharset.equals(javaCharset)) {
+			// description.setProperty(IContentDescriptionExtended.DETECTED_CHARSET,
+			// detectedCharset);
+			// }
+
+			// Once we detected a charset, we should set the property even
+			// though it's the same as javaCharset
+			// because there are clients that rely on this property to
+			// determine if the charset is actually detected in file or not.
+			description.setProperty(IContentDescriptionExtended.DETECTED_CHARSET, detectedCharset);
+		}
+	}
+
+	/**
+	 * @param description
+	 * @return
+	 */
+	private boolean isRelevent(IContentDescription description) {
+		boolean result = false;
+		if (description == null)
+			result = false;
+		else if (description.isRequested(IContentDescription.BYTE_ORDER_MARK))
+			result = true;
+		else if (description.isRequested(IContentDescription.CHARSET))
+			result = true;
+		else if (description.isRequested(IContentDescriptionExtended.APPROPRIATE_DEFAULT))
+			result = true;
+		else if (description.isRequested(IContentDescriptionExtended.DETECTED_CHARSET))
+			result = true;
+		else if (description.isRequested(IContentDescriptionExtended.UNSUPPORTED_CHARSET))
+			result = true;
+		// else if
+		// (description.isRequested(IContentDescriptionExtended.ENCODING_MEMENTO))
+		// result = true;
+		return result;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contenttype/EncodingGuesser.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contenttype/EncodingGuesser.java
new file mode 100644
index 0000000..7656fba
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contenttype/EncodingGuesser.java
@@ -0,0 +1,178 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2011 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contenttype;
+
+/**
+ * 
+ * This is ported from PageDesigner's hpbcom/Kanji.cpp's
+ * Kanji::guess_kanji_code(),
+ *  
+ */
+public class EncodingGuesser {
+	private static final int ASCII = 0; // ASCII
+	// ISO-2022-JP
+	private static final int ASCII_IN = 8; // This is after ISO2022's change
+	// Shift-JIS
+	private static final int EUC_HALFKANA = 6; // This is Half Kana in EUC-JP
+	private static final int EUC_JP = 3; // This is EUC-JP
+	private static final int ISO2022_JP = 4; // This is ISO-2022-JP
+	private static final int JIS_HALFKANA = 7; // THis is Half Kana in
+	private static final byte KT_EUC1 = 0x40;
+	private static final byte KT_EUC2 = (byte) 0x80;
+	// ASCII
+	private static final byte KT_JIN = 0x01;
+	private static final byte KT_JOUT = 0x02;
+	//	private static final byte KT_ESC = 0x04;
+	//	private static final byte KT_JIS = 0x08;
+	private static final byte KT_SFT1 = 0x10;
+	private static final byte KT_SFT2 = 0x20;
+	private static final byte ktype[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 00 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 10 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x09, 0x08, 0x08, 0x08, /* !"#$%&' *//* " */
+	0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* ()*+,-./ */
+	0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 01234567 */
+	0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 89:; <=>? */
+	0x29, 0x28, 0x2b, 0x28, 0x28, 0x28, 0x28, 0x28, /* @ABCDEFG */
+	0x2a, 0x28, 0x2a, 0x28, 0x28, 0x28, 0x28, 0x28, /* HIJKLMNO */
+	0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, /* PQRSTUVW */
+	0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, /* XYZ[\]^_ */
+	0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, /* abcdefg */
+	0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, /* hijklmno */
+	0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, /* pqrstuvw */
+	0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x00, /* xyz{|}~ */
+	0x20, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, /* 80 */
+	0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, /* 90 */
+	0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x20, (byte) 0xe0, (byte) 0xe0, (byte) 0xe0, (byte) 0xe0, (byte) 0xe0, (byte) 0xe0, (byte) 0xe0, /* A0 */
+	(byte) 0xe0, (byte) 0xe0, (byte) 0xe0, (byte) 0xe0, (byte) 0xe0, (byte) 0xe0, (byte) 0xe0, (byte) 0xe0, (byte) 0xe0, (byte) 0xe0, (byte) 0xe0, (byte) 0xe0, (byte) 0xe0, (byte) 0xe0, (byte) 0xe0, (byte) 0xe0, /* B0 */
+	(byte) 0xe0, (byte) 0xe0, (byte) 0xe0, (byte) 0xe0, (byte) 0xe0, (byte) 0xe0, (byte) 0xe0, (byte) 0xe0, (byte) 0xe0, (byte) 0xe0, (byte) 0xe0, (byte) 0xe0, (byte) 0xe0, (byte) 0xe0, (byte) 0xe0, (byte) 0xe0, /* C0 */
+	(byte) 0xe0, (byte) 0xe0, (byte) 0xe0, (byte) 0xe0, (byte) 0xe0, (byte) 0xe0, (byte) 0xe0, (byte) 0xe0, (byte) 0xe0, (byte) 0xe0, (byte) 0xe0, (byte) 0xe0, (byte) 0xe0, (byte) 0xe0, (byte) 0xe0, (byte) 0xe0, /* D0 */
+	(byte) 0xe0, (byte) 0xe0, (byte) 0xe0, (byte) 0xe0, (byte) 0xe0, (byte) 0xe0, (byte) 0xe0, (byte) 0xe0, (byte) 0xf0, (byte) 0xf0, (byte) 0xf0, (byte) 0xf0, (byte) 0xf0, (byte) 0xf0, (byte) 0xf0, (byte) 0xf0, /* E0 */
+	(byte) 0xf0, (byte) 0xf0, (byte) 0xf0, (byte) 0xf0, (byte) 0xf0, (byte) 0xf0, (byte) 0xf0, (byte) 0xf0, (byte) 0xf0, (byte) 0xf0, (byte) 0xf0, (byte) 0xf0, (byte) 0xf0, (byte) 0xf0, (byte) 0xf0, (byte) 0xf0, /* F0 */
+	(byte) 0xf0, (byte) 0xf0, (byte) 0xf0, (byte) 0xf0, (byte) 0xf0, (byte) 0xc0, (byte) 0xc0, 0x00,};
+	//	private static final int ISO8859_1 = 1; // ISO-1
+	private static final int SHIFT_JIS = 2; // This is Shift-JIS
+	private static final int SJIS_HALFKANA = 5; // This is Half Kana in
+
+	/**
+	 * Currently, only Japanese encodings are supported.
+	 */
+	private static final int UNKNOWN = -1; // Unknown
+
+	/**
+	 * @return java.lang.String
+	 * @param code
+	 *            int
+	 * 
+	 * Convert private int to IANA Encoding name.
+	 */
+	private static String convertToIANAEncodingName(int code) {
+		String encoding = null;
+
+		switch (code) {
+			case SHIFT_JIS :
+			case SJIS_HALFKANA :
+				encoding = "Shift_JIS";//$NON-NLS-1$
+				break;
+			case EUC_JP :
+			case EUC_HALFKANA :
+				encoding = "EUC-JP";//$NON-NLS-1$
+				break;
+			case ISO2022_JP :
+			case JIS_HALFKANA :
+				encoding = "ISO-2022-JP";//$NON-NLS-1$
+			default :
+				break;
+		}
+
+		return encoding;
+	}
+
+	public static boolean canGuess() {
+		// Currently, only Japanese is supported.
+		String system_ctype = java.util.Locale.getDefault().getLanguage();
+		String jp_ctype = java.util.Locale.JAPANESE.getLanguage();
+		return system_ctype.compareTo(jp_ctype) == 0;
+	}
+
+	/**
+	 * Return guessed Java Encoding name target: bytes to be inspected length:
+	 * length of target
+	 */
+	public static String guessEncoding(byte[] target, int length) {
+		int code = UNKNOWN;
+
+		
+		if (canGuess()) {
+			// Ok, I'm under ja_JP.
+			code = ASCII;
+			int pos = 0;
+			while ((code == ASCII) && (length > 0)) {
+				int ch1 = target[pos];
+				ch1 = ch1 & 0x000000FF;
+				int ch2 = (length >= 2) ? target[pos + 1] : 0;
+				ch2 = ch2 & 0x000000FF;
+				int ch3 = (length >= 3) ? target[pos + 2] : 0;
+				ch3 = ch3 & 0x000000FF;
+				code = guessJapaneseKanjiCode(ch1, ch2, ch3, 0);
+				pos++;
+				length--;
+			}
+			switch (code) {
+				case ISO2022_JP :
+				case JIS_HALFKANA :
+					code = ISO2022_JP;
+					break;
+				case EUC_JP :
+					code = EUC_JP;
+					break;
+				default :
+					code = SHIFT_JIS;
+			}
+		}
+		return (convertToIANAEncodingName(code));
+	}
+
+	/**
+	 * Guess the encoding. halfkana_flag = 0x01 ( detect SJIS half kana )
+	 * halfkana_flag = 0x02 ( detect EUC half kana )
+	 */
+	private static int guessJapaneseKanjiCode(int ch1, int ch2, int ch3, int halfkana_flag) {
+		boolean sjis_hankaku_flag = ((halfkana_flag & 0x01) != 0) ? true : false;
+		boolean euc_hankaku_flag = ((halfkana_flag & 0x02) != 0) ? true : false;
+
+		if (ch1 == 0)
+			return UNKNOWN;
+		if (sjis_hankaku_flag && ch1 >= 0xa1 && ch1 <= 0xdf)
+			return SJIS_HALFKANA;
+		else if (euc_hankaku_flag && ch1 == 0x8e && ch2 >= 0xa1 && ch2 <= 0xdf)
+			return EUC_HALFKANA;
+		else if (((ktype[ch1] & KT_SFT1) != 0) && ((ktype[ch2] & KT_SFT2) != 0))
+			return SHIFT_JIS;
+		else if (((ktype[ch1] & KT_EUC1) != 0) && ((ktype[ch2] & KT_EUC2) != 0))
+			return EUC_JP;
+		else if (ch1 == 0x1b && ((ktype[ch2] & KT_JIN) != 0))
+			return ISO2022_JP;
+		else if (ch1 >= 0xa1 && ch1 <= 0xdf)
+			return SJIS_HALFKANA;
+		else if (ch1 == 0x1b && ch2 == 0x28/* '(' */&& ch3 == 0x49/* 'I' */)
+			return JIS_HALFKANA;
+		else if (ch1 == 0x1b && ch2 == 0x28/* '(' */&& ((ktype[ch3] & KT_JOUT) != 0))
+			return ASCII_IN;
+
+		return ASCII;
+	}
+
+	public EncodingGuesser() {
+		super();
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contenttype/HTMLHeadTokenizer.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contenttype/HTMLHeadTokenizer.java
new file mode 100644
index 0000000..06d1052
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contenttype/HTMLHeadTokenizer.java
@@ -0,0 +1,3193 @@
+/* The following code was generated by JFlex 1.2.2 on 11/2/10 2:04 PM */
+
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+/*nlsXXX*/
+package org.eclipse.wst.html.core.internal.contenttype;
+import java.io.IOException;
+import java.io.Reader;
+
+import org.eclipse.wst.xml.core.internal.contenttype.EncodingParserConstants;
+import org.eclipse.wst.xml.core.internal.contenttype.XMLHeadTokenizerConstants;
+
+
+
+
+/**
+ * This class is a scanner generated by 
+ * <a href="http://www.informatik.tu-muenchen.de/~kleing/jflex/">JFlex</a> 1.2.2
+ * on 11/2/10 2:04 PM from the specification file
+ * <tt>file:/C:/dev/workspaces/helios/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/HTMLHeadTokenizer/HTMLHeadTokenizer.jFlex</tt>
+ */
+public class HTMLHeadTokenizer {
+
+  /** this character denotes the end of file */
+  final public static int YYEOF = -1;
+
+  /** lexical states */
+  final public static int ST_META_TAG = 4;
+  final public static int YYINITIAL = 0;
+  final public static int UnDelimitedString = 12;
+  final public static int DQ_STRING = 8;
+  final public static int UnDelimitedCharset = 14;
+  final public static int SQ_STRING = 10;
+  final public static int ST_XMLDecl = 2;
+  final public static int QuotedAttributeValue = 6;
+
+  /**
+   * YY_LEXSTATE[l] is the state in the DFA for the lexical state l
+   * YY_LEXSTATE[l+1] is the state in the DFA for the lexical state l
+   *                  at the beginning of a line
+   * l is of the form l = 2*k, k a non negative integer
+   */
+  private final static int YY_LEXSTATE[] = { 
+     0,  1,  2,  2,  3,  3,  4,  4,  5,  5,  6,  6,  7,  7,  8, 8
+  };
+
+  /** 
+   * Translates characters to character classes
+   */
+  final private static String yycmap_packed = 
+    "\1\11\10\0\1\6\1\7\2\0\1\10\22\0\1\6\1\23\1\40"+
+    "\2\0\1\56\1\0\1\41\5\0\1\53\1\44\1\35\1\0\1\50"+
+    "\1\0\1\45\5\0\1\51\1\42\1\57\1\13\1\12\1\52\1\14"+
+    "\1\0\1\22\1\33\1\26\1\24\1\20\1\0\1\47\1\31\1\34"+
+    "\2\0\1\17\1\16\1\36\1\25\1\30\1\54\1\46\1\37\1\21"+
+    "\1\32\1\55\1\43\1\15\1\27\7\0\1\22\1\33\1\26\1\24"+
+    "\1\20\1\0\1\47\1\31\1\34\2\0\1\17\1\16\1\36\1\25"+
+    "\1\30\1\54\1\46\1\37\1\21\1\32\1\55\1\43\1\15\1\27"+
+    "\101\0\1\4\3\0\1\5\17\0\1\3\16\0\1\1\20\0\1\3"+
+    "\16\0\1\1\1\2\170\0\1\2\ufe87\0";
+
+  /** 
+   * Translates characters to character classes
+   */
+  final private static char [] yycmap = yy_unpack_cmap(yycmap_packed);
+
+
+  /* error codes */
+  final private static int YY_UNKNOWN_ERROR = 0;
+  final private static int YY_ILLEGAL_STATE = 1;
+  final private static int YY_NO_MATCH = 2;
+  final private static int YY_PUSHBACK_2BIG = 3;
+
+  /* error messages for the codes above */
+  final private static String YY_ERROR_MSG[] = {
+    "Unkown internal scanner error",
+    "Internal error: unknown state",
+    "Error: could not match input",
+    "Error: pushback value was too large"
+  };
+
+  /** the input device */
+  private java.io.Reader yy_reader;
+
+  /** the current state of the DFA */
+  private int yy_state;
+
+  /** the current lexical state */
+  private int yy_lexical_state = YYINITIAL;
+
+  /** this buffer contains the current text to be matched and is
+      the source of the yytext() string */
+  private char yy_buffer[] = new char[16384];
+
+  /** the textposition at the last accepting state */
+  private int yy_markedPos;
+
+  /** the textposition at the last state to be included in yytext */
+  private int yy_pushbackPos;
+
+  /** the current text position in the buffer */
+  private int yy_currentPos;
+
+  /** startRead marks the beginning of the yytext() string in the buffer */
+  private int yy_startRead;
+
+  /** endRead marks the last character in the buffer, that has been read
+      from input */
+  private int yy_endRead;
+
+  /** number of newlines encountered up to the start of the matched text */
+  //private int yyline;
+
+  /** the number of characters up to the start of the matched text */
+  private int yychar;
+
+  /**
+   * the number of characters from the last newline up to the start of the 
+   * matched text
+   */
+  //private int yycolumn; 
+
+  /** 
+   * yy_atBOL == true <=> the scanner is currently at the beginning of a line
+   */
+  private boolean yy_atBOL;
+
+  /** yy_atEOF == true <=> the scanner has returned a value for EOF */
+  private boolean yy_atEOF;
+
+  /** denotes if the user-EOF-code has already been executed */
+  private boolean yy_eof_done;
+
+  /* user code: */
+
+
+	private boolean hasMore = true;
+	private boolean hasCharsetAttr = false;
+	private final static int MAX_TO_SCAN = 8000;
+	StringBuffer string = new StringBuffer();
+	// state stack for easier state handling
+	private IntStack fStateStack = new IntStack();
+	private String valueText = null;
+	boolean foundContentTypeValue = false;
+	private boolean isXHTML;
+
+
+
+	public HTMLHeadTokenizer() {
+		super();
+	}
+
+	  public void reset (Reader in) {
+	  	/* the input device */
+	  	yy_reader = in;
+
+  		/* the current state of the DFA */
+  		yy_state = 0;
+
+  		/* the current lexical state */
+  		yy_lexical_state = YYINITIAL;
+
+  		/* this buffer contains the current text to be matched and is
+  		 the source of the yytext() string */
+  		java.util.Arrays.fill(yy_buffer, (char)0);
+
+  		/* the textposition at the last accepting state */
+  		yy_markedPos = 0;
+
+  		/* the textposition at the last state to be included in yytext */
+  		yy_pushbackPos = 0;
+
+  		/* the current text position in the buffer */
+  		yy_currentPos = 0;
+
+  		/* startRead marks the beginning of the yytext() string in the buffer */
+  		yy_startRead = 0;
+
+  		/** 
+  		 * endRead marks the last character in the buffer, that has been read
+  		 * from input 
+  		 */
+  		yy_endRead = 0;
+
+  		/* number of newlines encountered up to the start of the matched text */
+  		// yyline = 0;
+
+  		/* the number of characters up to the start of the matched text */
+  		yychar = 0;
+
+  		/**
+  		 * the number of characters from the last newline up to the start
+  		 * of the matched text
+  		 */
+  		// yycolumn = 0; 
+
+  		/** 
+  		 * yy_atBOL == true <=> the scanner is currently at the beginning 
+  		 * of a line
+  		 */
+  		yy_atBOL = false;
+
+  		/* yy_atEOF == true <=> the scanner has returned a value for EOF */
+  		yy_atEOF = false;
+
+  		/* denotes if the user-EOF-code has already been executed */
+  		yy_eof_done = false;
+
+
+  		fStateStack.clear();
+  		
+  		hasMore = true;
+  		hasCharsetAttr = false;
+  		isXHTML = false;
+
+		// its a little wasteful to "throw away" first char array generated
+		// by class init (via auto generated code), but we really do want
+		// a small buffer for our head parsers.
+		if (yy_buffer.length != MAX_TO_SCAN) {
+			yy_buffer = new char[MAX_TO_SCAN];
+		}
+  		
+
+  	}
+
+
+	public final HeadParserToken getNextToken() throws IOException {
+		String context = null;
+		HeadParserToken result = null;
+		try {
+			context = primGetNextToken();
+		}
+		catch (IllegalStateException e) {
+			hasMore = false;
+			result = createToken(HTMLHeadTokenizerConstants.UNDEFINED, yychar, yytext());
+			while(yy_advance() != YYEOF) {}
+			return result;
+		}
+		if (valueText != null) {
+			result = createToken(context, yychar, valueText);
+			valueText = null;
+		} else {
+			result = createToken(context, yychar, yytext());
+		}
+		return result;
+	}
+
+	public final boolean hasMoreTokens() {
+		return hasMore && yychar < MAX_TO_SCAN;
+	}
+	private void pushCurrentState() {
+		fStateStack.push(yystate());
+
+	}
+	public final boolean hasCharsetAttr() {
+		return hasCharsetAttr;
+	}
+
+	private void popState() {
+		yybegin(fStateStack.pop());
+	}
+	private HeadParserToken createToken(String context, int start, String text) {
+		return new HeadParserToken(context, start, text);
+	}
+	
+    public boolean isXHTML() {
+       return isXHTML;
+    }
+
+
+  /**
+   * Creates a new scanner
+   * There is also a java.io.InputStream version of this constructor.
+   *
+   * @param   in  the java.io.Reader to read input from.
+   */
+  public HTMLHeadTokenizer(java.io.Reader in) {
+    this.yy_reader = in;
+  }
+
+  /**
+   * Creates a new scanner.
+   * There is also java.io.Reader version of this constructor.
+   *
+   * @param   in  the java.io.Inputstream to read input from.
+   */
+  public HTMLHeadTokenizer(java.io.InputStream in) {
+    this(new java.io.InputStreamReader(in));
+  }
+
+  /** 
+   * Unpacks the compressed character translation table.
+   *
+   * @param packed   the packed character translation table
+   * @return         the unpacked character translation table
+   */
+  private static char [] yy_unpack_cmap(String packed) {
+    char [] map = new char[0x10000];
+    int i = 0;  /* index in packed string  */
+    int j = 0;  /* index in unpacked array */
+    while (i < 192) {
+      int  count = packed.charAt(i++);
+      char value = packed.charAt(i++);
+      do map[j++] = value; while (--count > 0);
+    }
+    return map;
+  }
+
+
+  /**
+   * Gets the next input character.
+   *
+   * @return      the next character of the input stream, EOF if the
+   *              end of the stream is reached.
+   * @exception   IOException  if any I/O-Error occurs
+   */
+  private int yy_advance() throws java.io.IOException {
+
+    /* standard case */
+    if (yy_currentPos < yy_endRead) return yy_buffer[yy_currentPos++];
+
+    /* if the eof is reached, we don't need to work hard */ 
+    if (yy_atEOF) return YYEOF;
+
+    /* otherwise: need to refill the buffer */
+
+    /* first: make room (if you can) */
+    if (yy_startRead > 0) {
+      System.arraycopy(yy_buffer, yy_startRead, 
+                       yy_buffer, 0, 
+                       yy_endRead-yy_startRead);
+
+      /* translate stored positions */
+      yy_endRead-= yy_startRead;
+      yy_currentPos-= yy_startRead;
+      yy_markedPos-= yy_startRead;
+      yy_pushbackPos-= yy_startRead;
+      yy_startRead = 0;
+    }
+
+    /* is the buffer big enough? */
+    if (yy_currentPos >= yy_buffer.length) {
+      /* if not: blow it up */
+      char newBuffer[] = new char[yy_currentPos*2];
+      System.arraycopy(yy_buffer, 0, newBuffer, 0, yy_buffer.length);
+      yy_buffer = newBuffer;
+    }
+
+    /* finally: fill the buffer with new input */
+    int numRead = yy_reader.read(yy_buffer, yy_endRead, 
+                                            yy_buffer.length-yy_endRead);
+
+    if ( numRead == -1 ) return YYEOF;
+
+    yy_endRead+= numRead;
+
+    return yy_buffer[yy_currentPos++];
+  }
+
+    
+  /**
+   * Closes the input stream.
+   */
+  final public void yyclose() throws java.io.IOException {
+    yy_atEOF = true;            /* indicate end of file */
+    yy_endRead = yy_startRead;  /* invalidate buffer    */
+    yy_reader.close();
+  }
+
+
+  /**
+   * Returns the current lexical state.
+   */
+  final public int yystate() {
+    return yy_lexical_state;
+  }
+
+  /**
+   * Enters a new lexical state
+   *
+   * @param newState the new lexical state
+   */
+  final public void yybegin(int newState) {
+    yy_lexical_state = newState;
+  }
+
+
+  /**
+   * Returns the text matched by the current regular expression.
+   */
+  final public String yytext() {
+    return new String( yy_buffer, yy_startRead, yy_markedPos-yy_startRead );
+  }
+
+  /**
+   * Returns the length of the matched text region.
+   */
+  final public int yylength() {
+    return yy_markedPos-yy_startRead;
+  }
+
+
+  /**
+   * Reports an error that occured while scanning.
+   *
+   * @param   errorCode  the code of the errormessage to display
+   */
+  private void yy_ScanError(int errorCode) {
+    try {
+      IllegalStateException ise = new IllegalStateException("Instance: " + System.identityHashCode(this) + " offset:" + yychar + " state:" + yystate());
+      System.out.println(YY_ERROR_MSG[errorCode] + "\n" + ise);
+      throw ise;
+    }
+    catch (ArrayIndexOutOfBoundsException e) {
+      System.out.println(YY_ERROR_MSG[YY_UNKNOWN_ERROR]);
+    }
+
+  } 
+
+
+  /**
+   * Pushes the specified amount of characters back into the input stream.
+   *
+   * They will be read again by then next call of the scanning method
+   *
+   * @param number  the number of characters to be read again.
+   *                This number must not be greater than yylength()!
+   */
+  private void yypushback(int number) {
+    if ( number > yylength() )
+      yy_ScanError(YY_PUSHBACK_2BIG);
+
+    yy_markedPos -= number;
+  }
+
+
+  /**
+   * Contains user EOF-code, which will be executed exactly once,
+   * when the end of file is reached
+   */
+  private void yy_do_eof() {
+    if (!yy_eof_done) {
+      yy_eof_done = true;
+    	hasMore=false;
+
+    }
+  }
+
+
+  /**
+   * Resumes scanning until the next regular expression is matched,
+   * the end of input is encountered or an I/O-Error occurs.
+   *
+   * @return      the next token
+   * @exception   IOException  if any I/O-Error occurs
+   */
+  public String primGetNextToken() throws java.io.IOException {
+    int yy_input;
+    int yy_action;
+
+    yy_pushbackPos = -1;
+    boolean yy_was_pushback;
+
+    while (true) {
+
+      yychar+= yylength();
+
+      yy_atBOL = yy_markedPos <= 0 || yy_buffer[yy_markedPos-1] == '\n';
+      if (!yy_atBOL && yy_buffer[yy_markedPos-1] == '\r') {
+        yy_atBOL = yy_advance() != '\n';
+        if (!yy_atEOF) yy_currentPos--;
+      }
+
+      yy_action = -1;
+
+      yy_currentPos = yy_startRead = yy_markedPos;
+
+      if (yy_atBOL)
+        yy_state = YY_LEXSTATE[yy_lexical_state+1];
+      else
+        yy_state = YY_LEXSTATE[yy_lexical_state];
+
+      yy_was_pushback = false;
+
+      yy_forAction: {
+        while (true) {
+    
+          yy_input = yy_advance();
+
+          if ( yy_input == YYEOF ) break yy_forAction;
+
+          yy_input = yycmap[yy_input];
+
+          boolean yy_pushback = false;
+          boolean yy_isFinal = false;
+          boolean yy_noLookAhead = false;
+
+          yy_forNext: { switch (yy_state) {
+            case 0:
+              switch (yy_input) {
+                case 1: yy_isFinal = true; yy_state = 10; break yy_forNext;
+                case 2: yy_isFinal = true; yy_state = 11; break yy_forNext;
+                case 3: yy_isFinal = true; yy_state = 12; break yy_forNext;
+                case 9: yy_isFinal = true; yy_state = 13; break yy_forNext;
+                case 11: yy_isFinal = true; yy_state = 14; break yy_forNext;
+                default: yy_isFinal = true; yy_noLookAhead = true; yy_state = 9; break yy_forNext;
+              }
+
+            case 1:
+              switch (yy_input) {
+                case 1: yy_isFinal = true; yy_state = 10; break yy_forNext;
+                case 2: yy_isFinal = true; yy_state = 11; break yy_forNext;
+                case 3: yy_isFinal = true; yy_state = 12; break yy_forNext;
+                case 6: 
+                case 7: 
+                case 8: yy_isFinal = true; yy_state = 15; break yy_forNext;
+                case 9: yy_isFinal = true; yy_state = 16; break yy_forNext;
+                case 11: yy_isFinal = true; yy_state = 17; break yy_forNext;
+                default: yy_isFinal = true; yy_noLookAhead = true; yy_state = 9; break yy_forNext;
+              }
+
+            case 2:
+              switch (yy_input) {
+                case 9: yy_isFinal = true; yy_state = 18; break yy_forNext;
+                case 12: yy_isFinal = true; yy_state = 19; break yy_forNext;
+                case 16: yy_isFinal = true; yy_state = 20; break yy_forNext;
+                default: yy_isFinal = true; yy_noLookAhead = true; yy_state = 9; break yy_forNext;
+              }
+
+            case 3:
+              switch (yy_input) {
+                case 9: yy_isFinal = true; yy_state = 21; break yy_forNext;
+                case 22: yy_isFinal = true; yy_state = 22; break yy_forNext;
+                case 25: yy_isFinal = true; yy_state = 23; break yy_forNext;
+                case 29: yy_isFinal = true; yy_state = 24; break yy_forNext;
+                case 42: yy_isFinal = true; yy_state = 25; break yy_forNext;
+                default: yy_isFinal = true; yy_noLookAhead = true; yy_state = 9; break yy_forNext;
+              }
+
+            case 4:
+              switch (yy_input) {
+                case 6: 
+                case 8: yy_isFinal = true; yy_state = 27; break yy_forNext;
+                case 7: yy_isFinal = true; yy_state = 28; break yy_forNext;
+                case 9: yy_isFinal = true; yy_state = 29; break yy_forNext;
+                case 32: yy_isFinal = true; yy_state = 30; break yy_forNext;
+                case 33: yy_isFinal = true; yy_state = 31; break yy_forNext;
+                default: yy_isFinal = true; yy_noLookAhead = true; yy_state = 26; break yy_forNext;
+              }
+
+            case 5:
+              switch (yy_input) {
+                case 7: 
+                case 8: 
+                case 11: 
+                case 42: yy_isFinal = true; yy_state = 33; break yy_forNext;
+                case 9: yy_isFinal = true; yy_state = 34; break yy_forNext;
+                case 12: 
+                case 29: yy_isFinal = true; yy_state = 35; break yy_forNext;
+                case 32: yy_isFinal = true; yy_state = 36; break yy_forNext;
+                default: yy_isFinal = true; yy_noLookAhead = true; yy_state = 32; break yy_forNext;
+              }
+
+            case 6:
+              switch (yy_input) {
+                case 7: 
+                case 8: 
+                case 11: 
+                case 42: yy_isFinal = true; yy_state = 33; break yy_forNext;
+                case 29: yy_isFinal = true; yy_state = 35; break yy_forNext;
+                case 33: yy_isFinal = true; yy_state = 36; break yy_forNext;
+                case 9: yy_isFinal = true; yy_state = 37; break yy_forNext;
+                case 46: yy_isFinal = true; yy_state = 38; break yy_forNext;
+                default: yy_isFinal = true; yy_noLookAhead = true; yy_state = 32; break yy_forNext;
+              }
+
+            case 7:
+              switch (yy_input) {
+                case 11: 
+                case 42: yy_isFinal = true; yy_state = 33; break yy_forNext;
+                case 29: yy_isFinal = true; yy_state = 35; break yy_forNext;
+                case 12: yy_isFinal = true; yy_state = 38; break yy_forNext;
+                case 6: 
+                case 7: 
+                case 8: yy_isFinal = true; yy_state = 39; break yy_forNext;
+                case 9: yy_isFinal = true; yy_state = 40; break yy_forNext;
+                case 32: 
+                case 33: yy_isFinal = true; yy_state = 41; break yy_forNext;
+                case 47: yy_isFinal = true; yy_pushbackPos = yy_currentPos; yy_pushback = true; yy_state = 42; break yy_forNext;
+                default: yy_isFinal = true; yy_noLookAhead = true; yy_state = 32; break yy_forNext;
+              }
+
+            case 8:
+              switch (yy_input) {
+                case 9: yy_isFinal = true; yy_noLookAhead = true; yy_state = 9; break yy_forNext;
+                case 6: 
+                case 7: 
+                case 8: yy_isFinal = true; yy_noLookAhead = true; yy_state = 32; break yy_forNext;
+                default: yy_isFinal = true; yy_noLookAhead = true; yy_state = 43; break yy_forNext;
+              }
+
+            case 10:
+              switch (yy_input) {
+                case 2: yy_isFinal = true; yy_noLookAhead = true; yy_state = 44; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 11:
+              switch (yy_input) {
+                case 1: yy_isFinal = true; yy_noLookAhead = true; yy_state = 45; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 12:
+              switch (yy_input) {
+                case 4: yy_state = 46; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 13:
+              switch (yy_input) {
+                case 11: yy_state = 47; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 14:
+              switch (yy_input) {
+                case 9: yy_state = 48; break yy_forNext;
+                case 14: yy_state = 49; break yy_forNext;
+                case 19: yy_state = 50; break yy_forNext;
+                case 25: yy_state = 51; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 15:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_state = 52; break yy_forNext;
+                case 9: yy_state = 53; break yy_forNext;
+                case 11: yy_state = 54; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 16:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_state = 52; break yy_forNext;
+                case 11: yy_state = 55; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 17:
+              switch (yy_input) {
+                case 14: yy_state = 49; break yy_forNext;
+                case 19: yy_state = 50; break yy_forNext;
+                case 25: yy_state = 51; break yy_forNext;
+                case 9: yy_state = 56; break yy_forNext;
+                case 12: yy_state = 57; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 18:
+              switch (yy_input) {
+                case 12: yy_state = 58; break yy_forNext;
+                case 16: yy_state = 59; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 19:
+              switch (yy_input) {
+                case 9: yy_state = 60; break yy_forNext;
+                case 42: yy_isFinal = true; yy_state = 61; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 20:
+              switch (yy_input) {
+                case 9: yy_state = 62; break yy_forNext;
+                case 30: yy_state = 63; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 21:
+              switch (yy_input) {
+                case 42: yy_isFinal = true; yy_state = 25; break yy_forNext;
+                case 22: yy_state = 64; break yy_forNext;
+                case 25: yy_state = 65; break yy_forNext;
+                case 29: yy_state = 66; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 22:
+              switch (yy_input) {
+                case 9: yy_state = 67; break yy_forNext;
+                case 25: yy_state = 68; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 23:
+              switch (yy_input) {
+                case 9: yy_state = 69; break yy_forNext;
+                case 17: yy_state = 70; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 24:
+              switch (yy_input) {
+                case 9: yy_state = 71; break yy_forNext;
+                case 42: yy_isFinal = true; yy_state = 72; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 25:
+              switch (yy_input) {
+                case 9: yy_isFinal = true; yy_noLookAhead = true; yy_state = 73; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 27:
+              switch (yy_input) {
+                case 6: 
+                case 8: yy_isFinal = true; yy_state = 27; break yy_forNext;
+                case 7: yy_state = 74; break yy_forNext;
+                case 9: yy_isFinal = true; yy_state = 75; break yy_forNext;
+                default: yy_isFinal = true; yy_noLookAhead = true; yy_state = 26; break yy_forNext;
+              }
+
+            case 28:
+              switch (yy_input) {
+                case 6: 
+                case 8: yy_isFinal = true; yy_state = 27; break yy_forNext;
+                case 7: yy_state = 74; break yy_forNext;
+                case 9: yy_isFinal = true; yy_state = 75; break yy_forNext;
+                default: yy_isFinal = true; yy_noLookAhead = true; yy_state = 26; break yy_forNext;
+              }
+
+            case 29:
+              switch (yy_input) {
+                case 32: yy_isFinal = true; yy_state = 30; break yy_forNext;
+                case 33: yy_isFinal = true; yy_state = 31; break yy_forNext;
+                case 6: 
+                case 7: 
+                case 8: yy_state = 74; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 30:
+              switch (yy_input) {
+                case 9: yy_isFinal = true; yy_noLookAhead = true; yy_state = 76; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 31:
+              switch (yy_input) {
+                case 9: yy_isFinal = true; yy_noLookAhead = true; yy_state = 77; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 33:
+              switch (yy_input) {
+                case 9: yy_isFinal = true; yy_noLookAhead = true; yy_state = 78; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 34:
+              switch (yy_input) {
+                case 7: 
+                case 8: 
+                case 11: 
+                case 42: yy_isFinal = true; yy_state = 33; break yy_forNext;
+                case 32: yy_isFinal = true; yy_state = 36; break yy_forNext;
+                case 12: 
+                case 29: yy_state = 79; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 35:
+              switch (yy_input) {
+                case 9: yy_state = 80; break yy_forNext;
+                case 42: yy_isFinal = true; yy_state = 81; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 36:
+              switch (yy_input) {
+                case 9: yy_isFinal = true; yy_noLookAhead = true; yy_state = 82; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 37:
+              switch (yy_input) {
+                case 7: 
+                case 8: 
+                case 11: 
+                case 42: yy_isFinal = true; yy_state = 33; break yy_forNext;
+                case 33: yy_isFinal = true; yy_state = 36; break yy_forNext;
+                case 29: yy_state = 79; break yy_forNext;
+                case 46: yy_state = 83; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 38:
+              switch (yy_input) {
+                case 42: yy_isFinal = true; yy_state = 33; break yy_forNext;
+                case 9: yy_state = 84; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 39:
+              switch (yy_input) {
+                case 9: yy_isFinal = true; yy_noLookAhead = true; yy_state = 85; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 40:
+              switch (yy_input) {
+                case 11: 
+                case 42: yy_isFinal = true; yy_state = 33; break yy_forNext;
+                case 6: 
+                case 7: 
+                case 8: yy_isFinal = true; yy_state = 39; break yy_forNext;
+                case 32: 
+                case 33: yy_isFinal = true; yy_state = 41; break yy_forNext;
+                case 29: yy_state = 79; break yy_forNext;
+                case 12: yy_state = 83; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 41:
+              switch (yy_input) {
+                case 9: yy_isFinal = true; yy_noLookAhead = true; yy_state = 86; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 42:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_isFinal = true; yy_pushback = true; yy_state = 87; break yy_forNext;
+                case 9: yy_state = 88; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 46:
+              switch (yy_input) {
+                case 5: yy_isFinal = true; yy_noLookAhead = true; yy_state = 89; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 47:
+              switch (yy_input) {
+                case 9: yy_state = 48; break yy_forNext;
+                case 14: yy_state = 49; break yy_forNext;
+                case 19: yy_state = 50; break yy_forNext;
+                case 25: yy_state = 51; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 48:
+              switch (yy_input) {
+                case 14: yy_state = 49; break yy_forNext;
+                case 19: yy_state = 50; break yy_forNext;
+                case 25: yy_state = 51; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 49:
+              switch (yy_input) {
+                case 9: yy_state = 90; break yy_forNext;
+                case 16: yy_state = 91; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 50:
+              switch (yy_input) {
+                case 9: yy_state = 92; break yy_forNext;
+                case 20: yy_state = 93; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 51:
+              switch (yy_input) {
+                case 9: yy_state = 94; break yy_forNext;
+                case 17: yy_state = 95; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 52:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_state = 52; break yy_forNext;
+                case 9: yy_state = 53; break yy_forNext;
+                case 11: yy_state = 54; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 53:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_state = 52; break yy_forNext;
+                case 11: yy_state = 54; break yy_forNext;
+                case 9: yy_state = 96; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 54:
+              switch (yy_input) {
+                case 12: yy_state = 57; break yy_forNext;
+                case 9: yy_state = 97; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 55:
+              switch (yy_input) {
+                case 14: yy_state = 49; break yy_forNext;
+                case 19: yy_state = 50; break yy_forNext;
+                case 25: yy_state = 51; break yy_forNext;
+                case 9: yy_state = 56; break yy_forNext;
+                case 12: yy_state = 57; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 56:
+              switch (yy_input) {
+                case 14: yy_state = 49; break yy_forNext;
+                case 19: yy_state = 50; break yy_forNext;
+                case 25: yy_state = 51; break yy_forNext;
+                case 12: yy_state = 57; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 57:
+              switch (yy_input) {
+                case 9: yy_state = 98; break yy_forNext;
+                case 13: yy_state = 99; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 58:
+              switch (yy_input) {
+                case 9: yy_state = 60; break yy_forNext;
+                case 42: yy_isFinal = true; yy_state = 61; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 59:
+              switch (yy_input) {
+                case 9: yy_state = 62; break yy_forNext;
+                case 30: yy_state = 63; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 60:
+              switch (yy_input) {
+                case 42: yy_isFinal = true; yy_state = 61; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 61:
+              switch (yy_input) {
+                case 9: yy_isFinal = true; yy_noLookAhead = true; yy_state = 100; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 62:
+              switch (yy_input) {
+                case 30: yy_state = 63; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 63:
+              switch (yy_input) {
+                case 9: yy_state = 101; break yy_forNext;
+                case 22: yy_state = 102; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 64:
+              switch (yy_input) {
+                case 9: yy_state = 67; break yy_forNext;
+                case 25: yy_state = 68; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 65:
+              switch (yy_input) {
+                case 9: yy_state = 69; break yy_forNext;
+                case 17: yy_state = 70; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 66:
+              switch (yy_input) {
+                case 9: yy_state = 71; break yy_forNext;
+                case 42: yy_isFinal = true; yy_state = 72; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 67:
+              switch (yy_input) {
+                case 25: yy_state = 68; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 68:
+              switch (yy_input) {
+                case 9: yy_state = 103; break yy_forNext;
+                case 18: yy_state = 104; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 69:
+              switch (yy_input) {
+                case 17: yy_state = 70; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 70:
+              switch (yy_input) {
+                case 9: yy_state = 105; break yy_forNext;
+                case 17: yy_state = 106; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 71:
+              switch (yy_input) {
+                case 42: yy_isFinal = true; yy_state = 72; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 72:
+              switch (yy_input) {
+                case 9: yy_isFinal = true; yy_noLookAhead = true; yy_state = 107; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 74:
+              switch (yy_input) {
+                case 6: 
+                case 8: yy_isFinal = true; yy_state = 27; break yy_forNext;
+                case 7: yy_state = 74; break yy_forNext;
+                case 9: yy_isFinal = true; yy_state = 75; break yy_forNext;
+                default: yy_isFinal = true; yy_noLookAhead = true; yy_state = 26; break yy_forNext;
+              }
+
+            case 75:
+              switch (yy_input) {
+                case 6: 
+                case 8: yy_isFinal = true; yy_state = 27; break yy_forNext;
+                case 7: yy_state = 74; break yy_forNext;
+                case 9: yy_isFinal = true; yy_state = 108; break yy_forNext;
+                default: yy_isFinal = true; yy_noLookAhead = true; yy_state = 26; break yy_forNext;
+              }
+
+            case 79:
+              switch (yy_input) {
+                case 9: yy_state = 80; break yy_forNext;
+                case 42: yy_isFinal = true; yy_state = 81; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 80:
+              switch (yy_input) {
+                case 42: yy_isFinal = true; yy_state = 81; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 81:
+              switch (yy_input) {
+                case 9: yy_isFinal = true; yy_noLookAhead = true; yy_state = 109; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 83:
+              switch (yy_input) {
+                case 42: yy_isFinal = true; yy_state = 33; break yy_forNext;
+                case 9: yy_state = 84; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 84:
+              switch (yy_input) {
+                case 42: yy_isFinal = true; yy_state = 33; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 87:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_isFinal = true; yy_pushback = true; yy_state = 87; break yy_forNext;
+                case 9: yy_isFinal = true; yy_pushback = true; yy_state = 110; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 88:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_isFinal = true; yy_pushback = true; yy_state = 87; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 90:
+              switch (yy_input) {
+                case 16: yy_state = 91; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 91:
+              switch (yy_input) {
+                case 9: yy_state = 111; break yy_forNext;
+                case 17: yy_state = 112; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 92:
+              switch (yy_input) {
+                case 20: yy_state = 93; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 93:
+              switch (yy_input) {
+                case 9: yy_state = 113; break yy_forNext;
+                case 21: yy_state = 114; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 94:
+              switch (yy_input) {
+                case 17: yy_state = 95; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 95:
+              switch (yy_input) {
+                case 9: yy_state = 115; break yy_forNext;
+                case 14: yy_state = 116; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 96:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_state = 52; break yy_forNext;
+                case 11: yy_state = 54; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 97:
+              switch (yy_input) {
+                case 12: yy_state = 57; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 98:
+              switch (yy_input) {
+                case 13: yy_state = 99; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 99:
+              switch (yy_input) {
+                case 9: yy_state = 117; break yy_forNext;
+                case 14: yy_state = 118; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 101:
+              switch (yy_input) {
+                case 22: yy_state = 102; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 102:
+              switch (yy_input) {
+                case 9: yy_state = 119; break yy_forNext;
+                case 21: yy_state = 120; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 103:
+              switch (yy_input) {
+                case 18: yy_state = 104; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 104:
+              switch (yy_input) {
+                case 9: yy_state = 121; break yy_forNext;
+                case 38: yy_state = 122; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 105:
+              switch (yy_input) {
+                case 17: yy_state = 106; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 106:
+              switch (yy_input) {
+                case 9: yy_state = 123; break yy_forNext;
+                case 24: yy_state = 124; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 108:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_state = 74; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 110:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_isFinal = true; yy_pushback = true; yy_state = 87; break yy_forNext;
+                case 9: yy_state = 88; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 111:
+              switch (yy_input) {
+                case 17: yy_state = 112; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 112:
+              switch (yy_input) {
+                case 9: yy_state = 125; break yy_forNext;
+                case 18: yy_isFinal = true; yy_state = 126; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 113:
+              switch (yy_input) {
+                case 21: yy_state = 114; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 114:
+              switch (yy_input) {
+                case 9: yy_state = 127; break yy_forNext;
+                case 22: yy_state = 128; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 115:
+              switch (yy_input) {
+                case 14: yy_state = 116; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 116:
+              switch (yy_input) {
+                case 9: yy_state = 129; break yy_forNext;
+                case 15: yy_state = 130; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 117:
+              switch (yy_input) {
+                case 14: yy_state = 118; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 118:
+              switch (yy_input) {
+                case 9: yy_state = 131; break yy_forNext;
+                case 15: yy_state = 132; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 119:
+              switch (yy_input) {
+                case 21: yy_state = 120; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 120:
+              switch (yy_input) {
+                case 9: yy_state = 133; break yy_forNext;
+                case 20: yy_state = 134; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 121:
+              switch (yy_input) {
+                case 38: yy_state = 122; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 122:
+              switch (yy_input) {
+                case 9: yy_state = 135; break yy_forNext;
+                case 31: yy_state = 136; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 123:
+              switch (yy_input) {
+                case 24: yy_state = 124; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 124:
+              switch (yy_input) {
+                case 9: yy_state = 137; break yy_forNext;
+                case 43: yy_state = 138; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 125:
+              switch (yy_input) {
+                case 18: yy_isFinal = true; yy_state = 126; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 126:
+              switch (yy_input) {
+                case 9: yy_isFinal = true; yy_noLookAhead = true; yy_state = 139; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 127:
+              switch (yy_input) {
+                case 22: yy_state = 128; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 128:
+              switch (yy_input) {
+                case 9: yy_state = 140; break yy_forNext;
+                case 17: yy_state = 141; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 129:
+              switch (yy_input) {
+                case 15: yy_state = 130; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 130:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_state = 130; break yy_forNext;
+                case 9: yy_state = 142; break yy_forNext;
+                case 13: yy_state = 143; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 131:
+              switch (yy_input) {
+                case 15: yy_state = 132; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 132:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_isFinal = true; yy_state = 144; break yy_forNext;
+                case 9: yy_state = 145; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 133:
+              switch (yy_input) {
+                case 20: yy_state = 134; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 134:
+              switch (yy_input) {
+                case 9: yy_state = 146; break yy_forNext;
+                case 28: yy_state = 147; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 135:
+              switch (yy_input) {
+                case 31: yy_state = 136; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 136:
+              switch (yy_input) {
+                case 9: yy_state = 148; break yy_forNext;
+                case 16: yy_state = 149; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 137:
+              switch (yy_input) {
+                case 43: yy_state = 138; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 138:
+              switch (yy_input) {
+                case 9: yy_state = 150; break yy_forNext;
+                case 16: yy_state = 151; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 140:
+              switch (yy_input) {
+                case 17: yy_state = 141; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 141:
+              switch (yy_input) {
+                case 9: yy_state = 152; break yy_forNext;
+                case 23: yy_state = 153; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 142:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_state = 130; break yy_forNext;
+                case 13: yy_state = 143; break yy_forNext;
+                case 9: yy_state = 154; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 143:
+              switch (yy_input) {
+                case 9: yy_state = 155; break yy_forNext;
+                case 14: yy_state = 156; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 144:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_isFinal = true; yy_state = 144; break yy_forNext;
+                case 9: yy_isFinal = true; yy_state = 157; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 145:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_isFinal = true; yy_state = 144; break yy_forNext;
+                case 9: yy_state = 158; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 146:
+              switch (yy_input) {
+                case 28: yy_state = 147; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 147:
+              switch (yy_input) {
+                case 9: yy_state = 159; break yy_forNext;
+                case 30: yy_state = 160; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 148:
+              switch (yy_input) {
+                case 16: yy_state = 149; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 149:
+              switch (yy_input) {
+                case 9: yy_state = 161; break yy_forNext;
+                case 17: yy_state = 162; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 150:
+              switch (yy_input) {
+                case 16: yy_state = 151; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 151:
+              switch (yy_input) {
+                case 9: yy_state = 163; break yy_forNext;
+                case 44: yy_state = 164; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 152:
+              switch (yy_input) {
+                case 23: yy_state = 153; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 153:
+              switch (yy_input) {
+                case 9: yy_state = 165; break yy_forNext;
+                case 24: yy_state = 166; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 154:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_state = 130; break yy_forNext;
+                case 13: yy_state = 143; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 155:
+              switch (yy_input) {
+                case 14: yy_state = 156; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 156:
+              switch (yy_input) {
+                case 9: yy_state = 167; break yy_forNext;
+                case 15: yy_state = 168; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 157:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_isFinal = true; yy_state = 144; break yy_forNext;
+                case 9: yy_state = 158; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 158:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_isFinal = true; yy_state = 144; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 159:
+              switch (yy_input) {
+                case 30: yy_state = 160; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 160:
+              switch (yy_input) {
+                case 9: yy_state = 169; break yy_forNext;
+                case 39: yy_state = 170; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 161:
+              switch (yy_input) {
+                case 17: yy_state = 162; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 162:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_state = 162; break yy_forNext;
+                case 9: yy_state = 171; break yy_forNext;
+                case 10: yy_isFinal = true; yy_state = 172; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 163:
+              switch (yy_input) {
+                case 44: yy_state = 164; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 164:
+              switch (yy_input) {
+                case 9: yy_state = 173; break yy_forNext;
+                case 26: yy_state = 174; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 165:
+              switch (yy_input) {
+                case 24: yy_state = 166; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 166:
+              switch (yy_input) {
+                case 9: yy_state = 175; break yy_forNext;
+                case 16: yy_state = 176; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 167:
+              switch (yy_input) {
+                case 15: yy_state = 168; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 168:
+              switch (yy_input) {
+                case 9: yy_state = 177; break yy_forNext;
+                case 30: yy_state = 178; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 169:
+              switch (yy_input) {
+                case 39: yy_state = 170; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 170:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_state = 170; break yy_forNext;
+                case 9: yy_state = 179; break yy_forNext;
+                case 10: yy_isFinal = true; yy_state = 180; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 171:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_state = 162; break yy_forNext;
+                case 10: yy_isFinal = true; yy_state = 172; break yy_forNext;
+                case 9: yy_state = 181; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 172:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_isFinal = true; yy_state = 182; break yy_forNext;
+                case 9: yy_state = 183; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 173:
+              switch (yy_input) {
+                case 26: yy_state = 174; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 174:
+              switch (yy_input) {
+                case 9: yy_state = 184; break yy_forNext;
+                case 28: yy_state = 185; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 175:
+              switch (yy_input) {
+                case 16: yy_state = 176; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 176:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_state = 176; break yy_forNext;
+                case 9: yy_state = 186; break yy_forNext;
+                case 25: yy_state = 187; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 177:
+              switch (yy_input) {
+                case 30: yy_state = 178; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 178:
+              switch (yy_input) {
+                case 9: yy_state = 188; break yy_forNext;
+                case 31: yy_state = 189; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 179:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_state = 170; break yy_forNext;
+                case 10: yy_isFinal = true; yy_state = 180; break yy_forNext;
+                case 9: yy_state = 190; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 180:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_isFinal = true; yy_state = 191; break yy_forNext;
+                case 9: yy_state = 192; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 181:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_state = 162; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 182:
+              switch (yy_input) {
+                case 9: yy_isFinal = true; yy_state = 172; break yy_forNext;
+                case 6: 
+                case 7: 
+                case 8: yy_isFinal = true; yy_state = 182; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 183:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_isFinal = true; yy_state = 182; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 184:
+              switch (yy_input) {
+                case 28: yy_state = 185; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 185:
+              switch (yy_input) {
+                case 9: yy_state = 193; break yy_forNext;
+                case 45: yy_state = 194; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 186:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_state = 176; break yy_forNext;
+                case 25: yy_state = 187; break yy_forNext;
+                case 9: yy_state = 195; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 187:
+              switch (yy_input) {
+                case 9: yy_state = 196; break yy_forNext;
+                case 17: yy_state = 197; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 188:
+              switch (yy_input) {
+                case 31: yy_state = 189; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 189:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_state = 189; break yy_forNext;
+                case 9: yy_state = 198; break yy_forNext;
+                case 10: yy_state = 199; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 190:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_state = 170; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 191:
+              switch (yy_input) {
+                case 9: yy_isFinal = true; yy_state = 180; break yy_forNext;
+                case 6: 
+                case 7: 
+                case 8: yy_isFinal = true; yy_state = 191; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 192:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_isFinal = true; yy_state = 191; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 193:
+              switch (yy_input) {
+                case 45: yy_state = 194; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 194:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_state = 194; break yy_forNext;
+                case 9: yy_state = 200; break yy_forNext;
+                case 10: yy_state = 201; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 195:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_state = 176; break yy_forNext;
+                case 25: yy_state = 187; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 196:
+              switch (yy_input) {
+                case 17: yy_state = 197; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 197:
+              switch (yy_input) {
+                case 9: yy_state = 202; break yy_forNext;
+                case 14: yy_state = 203; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 198:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_state = 189; break yy_forNext;
+                case 10: yy_state = 199; break yy_forNext;
+                case 9: yy_state = 204; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 199:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_state = 199; break yy_forNext;
+                case 9: yy_state = 205; break yy_forNext;
+                case 32: 
+                case 33: yy_state = 206; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 200:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_state = 194; break yy_forNext;
+                case 10: yy_state = 201; break yy_forNext;
+                case 9: yy_state = 207; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 201:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_state = 208; break yy_forNext;
+                case 9: yy_state = 209; break yy_forNext;
+                case 22: yy_state = 210; break yy_forNext;
+                case 32: yy_state = 211; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 202:
+              switch (yy_input) {
+                case 14: yy_state = 203; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 203:
+              switch (yy_input) {
+                case 9: yy_state = 212; break yy_forNext;
+                case 15: yy_state = 213; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 204:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_state = 189; break yy_forNext;
+                case 10: yy_state = 199; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 205:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_state = 199; break yy_forNext;
+                case 32: 
+                case 33: yy_state = 206; break yy_forNext;
+                case 9: yy_state = 214; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 206:
+              switch (yy_input) {
+                case 9: yy_state = 215; break yy_forNext;
+                case 25: yy_state = 216; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 207:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_state = 194; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 208:
+              switch (yy_input) {
+                case 9: yy_state = 201; break yy_forNext;
+                case 6: 
+                case 7: 
+                case 8: yy_state = 208; break yy_forNext;
+                case 22: yy_state = 210; break yy_forNext;
+                case 32: yy_state = 211; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 209:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_state = 208; break yy_forNext;
+                case 22: yy_state = 210; break yy_forNext;
+                case 32: yy_state = 211; break yy_forNext;
+                case 9: yy_state = 217; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 210:
+              switch (yy_input) {
+                case 9: yy_state = 218; break yy_forNext;
+                case 21: yy_state = 219; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 211:
+              switch (yy_input) {
+                case 22: yy_state = 210; break yy_forNext;
+                case 9: yy_state = 217; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 212:
+              switch (yy_input) {
+                case 15: yy_state = 213; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 213:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_state = 213; break yy_forNext;
+                case 9: yy_state = 220; break yy_forNext;
+                case 24: yy_state = 221; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 214:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_state = 199; break yy_forNext;
+                case 32: 
+                case 33: yy_state = 206; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 215:
+              switch (yy_input) {
+                case 25: yy_state = 216; break yy_forNext;
+                case 9: yy_state = 222; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 216:
+              switch (yy_input) {
+                case 9: yy_state = 223; break yy_forNext;
+                case 17: yy_state = 224; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 217:
+              switch (yy_input) {
+                case 22: yy_state = 210; break yy_forNext;
+                case 9: yy_state = 225; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 218:
+              switch (yy_input) {
+                case 21: yy_state = 219; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 219:
+              switch (yy_input) {
+                case 9: yy_state = 226; break yy_forNext;
+                case 30: yy_state = 227; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 220:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_state = 213; break yy_forNext;
+                case 24: yy_state = 221; break yy_forNext;
+                case 9: yy_state = 228; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 221:
+              switch (yy_input) {
+                case 9: yy_state = 229; break yy_forNext;
+                case 26: yy_state = 230; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 222:
+              switch (yy_input) {
+                case 25: yy_state = 216; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 223:
+              switch (yy_input) {
+                case 17: yy_state = 224; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 224:
+              switch (yy_input) {
+                case 9: yy_state = 231; break yy_forNext;
+                case 17: yy_state = 232; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 225:
+              switch (yy_input) {
+                case 22: yy_state = 210; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 226:
+              switch (yy_input) {
+                case 30: yy_state = 227; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 227:
+              switch (yy_input) {
+                case 9: yy_state = 233; break yy_forNext;
+                case 17: yy_state = 234; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 228:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_state = 213; break yy_forNext;
+                case 24: yy_state = 221; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 229:
+              switch (yy_input) {
+                case 26: yy_state = 230; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 230:
+              switch (yy_input) {
+                case 9: yy_state = 235; break yy_forNext;
+                case 27: yy_state = 236; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 231:
+              switch (yy_input) {
+                case 17: yy_state = 232; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 232:
+              switch (yy_input) {
+                case 9: yy_state = 237; break yy_forNext;
+                case 24: yy_state = 238; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 233:
+              switch (yy_input) {
+                case 17: yy_state = 234; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 234:
+              switch (yy_input) {
+                case 9: yy_state = 239; break yy_forNext;
+                case 16: yy_state = 240; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 235:
+              switch (yy_input) {
+                case 27: yy_state = 236; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 236:
+              switch (yy_input) {
+                case 9: yy_state = 241; break yy_forNext;
+                case 15: yy_state = 242; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 237:
+              switch (yy_input) {
+                case 24: yy_state = 238; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 238:
+              switch (yy_input) {
+                case 9: yy_state = 243; break yy_forNext;
+                case 34: yy_state = 244; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 239:
+              switch (yy_input) {
+                case 16: yy_state = 240; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 240:
+              switch (yy_input) {
+                case 9: yy_state = 245; break yy_forNext;
+                case 30: yy_state = 246; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 241:
+              switch (yy_input) {
+                case 15: yy_state = 242; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 242:
+              switch (yy_input) {
+                case 9: yy_state = 247; break yy_forNext;
+                case 28: yy_state = 248; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 243:
+              switch (yy_input) {
+                case 34: yy_state = 244; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 244:
+              switch (yy_input) {
+                case 9: yy_state = 249; break yy_forNext;
+                case 29: yy_state = 250; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 245:
+              switch (yy_input) {
+                case 30: yy_state = 246; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 246:
+              switch (yy_input) {
+                case 9: yy_state = 251; break yy_forNext;
+                case 17: yy_state = 252; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 247:
+              switch (yy_input) {
+                case 28: yy_state = 248; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 248:
+              switch (yy_input) {
+                case 9: yy_state = 253; break yy_forNext;
+                case 22: yy_state = 254; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 249:
+              switch (yy_input) {
+                case 29: yy_state = 250; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 250:
+              switch (yy_input) {
+                case 9: yy_state = 255; break yy_forNext;
+                case 29: yy_state = 256; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 251:
+              switch (yy_input) {
+                case 17: yy_state = 252; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 252:
+              switch (yy_input) {
+                case 9: yy_state = 257; break yy_forNext;
+                case 43: yy_state = 258; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 253:
+              switch (yy_input) {
+                case 22: yy_state = 254; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 254:
+              switch (yy_input) {
+                case 29: yy_state = 259; break yy_forNext;
+                case 7: break yy_forAction;
+                default: yy_state = 254; break yy_forNext;
+              }
+
+            case 255:
+              switch (yy_input) {
+                case 29: yy_state = 256; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 256:
+              switch (yy_input) {
+                case 9: yy_state = 260; break yy_forNext;
+                case 35: yy_state = 261; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 257:
+              switch (yy_input) {
+                case 43: yy_state = 258; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 258:
+              switch (yy_input) {
+                case 9: yy_state = 262; break yy_forNext;
+                case 17: yy_state = 263; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 259:
+              switch (yy_input) {
+                case 9: yy_state = 264; break yy_forNext;
+                case 29: yy_state = 265; break yy_forNext;
+                case 7: break yy_forAction;
+                default: yy_state = 254; break yy_forNext;
+              }
+
+            case 260:
+              switch (yy_input) {
+                case 35: yy_state = 261; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 261:
+              switch (yy_input) {
+                case 9: yy_state = 266; break yy_forNext;
+                case 35: yy_state = 267; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 262:
+              switch (yy_input) {
+                case 17: yy_state = 263; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 263:
+              switch (yy_input) {
+                case 9: yy_state = 268; break yy_forNext;
+                case 23: yy_state = 269; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 264:
+              switch (yy_input) {
+                case 29: yy_state = 265; break yy_forNext;
+                case 7: break yy_forAction;
+                default: yy_state = 254; break yy_forNext;
+              }
+
+            case 265:
+              switch (yy_input) {
+                case 29: yy_state = 265; break yy_forNext;
+                case 9: yy_state = 270; break yy_forNext;
+                case 20: yy_state = 271; break yy_forNext;
+                case 7: break yy_forAction;
+                default: yy_state = 254; break yy_forNext;
+              }
+
+            case 266:
+              switch (yy_input) {
+                case 35: yy_state = 267; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 267:
+              switch (yy_input) {
+                case 9: yy_state = 272; break yy_forNext;
+                case 35: yy_state = 273; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 268:
+              switch (yy_input) {
+                case 23: yy_state = 269; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 269:
+              switch (yy_input) {
+                case 9: yy_state = 274; break yy_forNext;
+                case 24: yy_state = 275; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 270:
+              switch (yy_input) {
+                case 29: yy_state = 265; break yy_forNext;
+                case 20: yy_state = 271; break yy_forNext;
+                case 7: break yy_forAction;
+                default: yy_state = 254; break yy_forNext;
+              }
+
+            case 271:
+              switch (yy_input) {
+                case 29: yy_state = 259; break yy_forNext;
+                case 9: yy_state = 276; break yy_forNext;
+                case 17: yy_state = 277; break yy_forNext;
+                case 7: break yy_forAction;
+                default: yy_state = 254; break yy_forNext;
+              }
+
+            case 272:
+              switch (yy_input) {
+                case 35: yy_state = 273; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 273:
+              switch (yy_input) {
+                case 9: yy_state = 278; break yy_forNext;
+                case 36: yy_state = 279; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 274:
+              switch (yy_input) {
+                case 24: yy_state = 275; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 275:
+              switch (yy_input) {
+                case 9: yy_state = 280; break yy_forNext;
+                case 16: yy_state = 281; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 276:
+              switch (yy_input) {
+                case 29: yy_state = 259; break yy_forNext;
+                case 17: yy_state = 277; break yy_forNext;
+                case 7: break yy_forAction;
+                default: yy_state = 254; break yy_forNext;
+              }
+
+            case 277:
+              switch (yy_input) {
+                case 29: yy_state = 259; break yy_forNext;
+                case 9: yy_state = 282; break yy_forNext;
+                case 20: yy_state = 283; break yy_forNext;
+                case 7: break yy_forAction;
+                default: yy_state = 254; break yy_forNext;
+              }
+
+            case 278:
+              switch (yy_input) {
+                case 36: yy_state = 279; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 279:
+              switch (yy_input) {
+                case 9: yy_state = 284; break yy_forNext;
+                case 35: yy_state = 285; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 280:
+              switch (yy_input) {
+                case 16: yy_state = 281; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 281:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_state = 286; break yy_forNext;
+                case 9: yy_state = 287; break yy_forNext;
+                case 32: yy_state = 288; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 282:
+              switch (yy_input) {
+                case 29: yy_state = 259; break yy_forNext;
+                case 20: yy_state = 283; break yy_forNext;
+                case 7: break yy_forAction;
+                default: yy_state = 254; break yy_forNext;
+              }
+
+            case 283:
+              switch (yy_input) {
+                case 29: yy_state = 259; break yy_forNext;
+                case 6: 
+                case 8: yy_state = 289; break yy_forNext;
+                case 7: yy_state = 290; break yy_forNext;
+                case 9: yy_state = 291; break yy_forNext;
+                default: yy_state = 254; break yy_forNext;
+              }
+
+            case 284:
+              switch (yy_input) {
+                case 35: yy_state = 285; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 285:
+              switch (yy_input) {
+                case 9: yy_state = 292; break yy_forNext;
+                case 37: yy_state = 293; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 286:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_state = 286; break yy_forNext;
+                case 9: yy_state = 294; break yy_forNext;
+                case 22: yy_state = 295; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 287:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_state = 286; break yy_forNext;
+                case 32: yy_state = 288; break yy_forNext;
+                case 9: yy_state = 296; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 288:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_state = 286; break yy_forNext;
+                case 9: yy_state = 296; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 289:
+              switch (yy_input) {
+                case 29: yy_state = 259; break yy_forNext;
+                case 9: yy_state = 297; break yy_forNext;
+                case 13: yy_state = 298; break yy_forNext;
+                case 7: break yy_forAction;
+                default: yy_state = 254; break yy_forNext;
+              }
+
+            case 290:
+              switch (yy_input) {
+                case 9: yy_state = 299; break yy_forNext;
+                case 13: yy_state = 300; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 291:
+              switch (yy_input) {
+                case 29: yy_state = 259; break yy_forNext;
+                case 6: 
+                case 8: yy_state = 289; break yy_forNext;
+                case 7: yy_state = 290; break yy_forNext;
+                case 9: yy_state = 301; break yy_forNext;
+                default: yy_state = 254; break yy_forNext;
+              }
+
+            case 292:
+              switch (yy_input) {
+                case 37: yy_state = 293; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 293:
+              switch (yy_input) {
+                case 9: yy_state = 302; break yy_forNext;
+                case 36: yy_state = 303; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 294:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_state = 286; break yy_forNext;
+                case 22: yy_state = 295; break yy_forNext;
+                case 9: yy_state = 304; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 295:
+              switch (yy_input) {
+                case 9: yy_state = 305; break yy_forNext;
+                case 21: yy_state = 306; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 296:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_state = 286; break yy_forNext;
+                case 9: yy_state = 307; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 297:
+              switch (yy_input) {
+                case 29: yy_state = 259; break yy_forNext;
+                case 13: yy_state = 298; break yy_forNext;
+                case 9: yy_state = 308; break yy_forNext;
+                case 7: break yy_forAction;
+                default: yy_state = 254; break yy_forNext;
+              }
+
+            case 298:
+              switch (yy_input) {
+                case 29: yy_state = 259; break yy_forNext;
+                case 9: yy_state = 309; break yy_forNext;
+                case 25: yy_state = 310; break yy_forNext;
+                case 7: break yy_forAction;
+                default: yy_state = 254; break yy_forNext;
+              }
+
+            case 299:
+              switch (yy_input) {
+                case 13: yy_state = 300; break yy_forNext;
+                case 9: yy_state = 311; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 300:
+              switch (yy_input) {
+                case 9: yy_state = 312; break yy_forNext;
+                case 25: yy_state = 313; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 301:
+              switch (yy_input) {
+                case 29: yy_state = 259; break yy_forNext;
+                case 6: 
+                case 8: yy_state = 289; break yy_forNext;
+                case 7: yy_state = 290; break yy_forNext;
+                default: yy_state = 254; break yy_forNext;
+              }
+
+            case 302:
+              switch (yy_input) {
+                case 36: yy_state = 303; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 303:
+              switch (yy_input) {
+                case 9: yy_state = 314; break yy_forNext;
+                case 21: yy_state = 315; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 304:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_state = 286; break yy_forNext;
+                case 22: yy_state = 295; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 305:
+              switch (yy_input) {
+                case 21: yy_state = 306; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 306:
+              switch (yy_input) {
+                case 9: yy_state = 316; break yy_forNext;
+                case 30: yy_state = 317; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 307:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_state = 286; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 308:
+              switch (yy_input) {
+                case 29: yy_state = 259; break yy_forNext;
+                case 13: yy_state = 298; break yy_forNext;
+                case 7: break yy_forAction;
+                default: yy_state = 254; break yy_forNext;
+              }
+
+            case 309:
+              switch (yy_input) {
+                case 29: yy_state = 259; break yy_forNext;
+                case 25: yy_state = 310; break yy_forNext;
+                case 7: break yy_forAction;
+                default: yy_state = 254; break yy_forNext;
+              }
+
+            case 310:
+              switch (yy_input) {
+                case 29: yy_state = 259; break yy_forNext;
+                case 9: yy_state = 318; break yy_forNext;
+                case 17: yy_state = 319; break yy_forNext;
+                case 7: break yy_forAction;
+                default: yy_state = 254; break yy_forNext;
+              }
+
+            case 311:
+              switch (yy_input) {
+                case 13: yy_state = 300; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 312:
+              switch (yy_input) {
+                case 25: yy_state = 313; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 313:
+              switch (yy_input) {
+                case 9: yy_state = 320; break yy_forNext;
+                case 17: yy_state = 321; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 314:
+              switch (yy_input) {
+                case 21: yy_state = 315; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 315:
+              switch (yy_input) {
+                case 9: yy_state = 322; break yy_forNext;
+                case 38: yy_state = 323; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 316:
+              switch (yy_input) {
+                case 30: yy_state = 317; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 317:
+              switch (yy_input) {
+                case 9: yy_state = 324; break yy_forNext;
+                case 17: yy_state = 325; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 318:
+              switch (yy_input) {
+                case 29: yy_state = 259; break yy_forNext;
+                case 17: yy_state = 319; break yy_forNext;
+                case 7: break yy_forAction;
+                default: yy_state = 254; break yy_forNext;
+              }
+
+            case 319:
+              switch (yy_input) {
+                case 29: yy_state = 259; break yy_forNext;
+                case 9: yy_state = 326; break yy_forNext;
+                case 14: yy_state = 327; break yy_forNext;
+                case 7: break yy_forAction;
+                default: yy_state = 254; break yy_forNext;
+              }
+
+            case 320:
+              switch (yy_input) {
+                case 17: yy_state = 321; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 321:
+              switch (yy_input) {
+                case 9: yy_state = 328; break yy_forNext;
+                case 14: yy_state = 329; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 322:
+              switch (yy_input) {
+                case 38: yy_state = 323; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 323:
+              switch (yy_input) {
+                case 9: yy_state = 330; break yy_forNext;
+                case 39: yy_state = 331; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 324:
+              switch (yy_input) {
+                case 17: yy_state = 325; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 325:
+              switch (yy_input) {
+                case 9: yy_state = 332; break yy_forNext;
+                case 16: yy_state = 333; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 326:
+              switch (yy_input) {
+                case 29: yy_state = 259; break yy_forNext;
+                case 14: yy_state = 327; break yy_forNext;
+                case 7: break yy_forAction;
+                default: yy_state = 254; break yy_forNext;
+              }
+
+            case 327:
+              switch (yy_input) {
+                case 29: yy_state = 259; break yy_forNext;
+                case 9: yy_state = 334; break yy_forNext;
+                case 15: yy_isFinal = true; yy_state = 335; break yy_forNext;
+                case 7: break yy_forAction;
+                default: yy_state = 254; break yy_forNext;
+              }
+
+            case 328:
+              switch (yy_input) {
+                case 14: yy_state = 329; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 329:
+              switch (yy_input) {
+                case 9: yy_state = 336; break yy_forNext;
+                case 15: yy_isFinal = true; yy_state = 337; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 330:
+              switch (yy_input) {
+                case 39: yy_state = 331; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 331:
+              switch (yy_input) {
+                case 9: yy_state = 338; break yy_forNext;
+                case 29: yy_state = 339; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 332:
+              switch (yy_input) {
+                case 16: yy_state = 333; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 333:
+              switch (yy_input) {
+                case 9: yy_state = 340; break yy_forNext;
+                case 30: yy_state = 341; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 334:
+              switch (yy_input) {
+                case 29: yy_state = 259; break yy_forNext;
+                case 15: yy_isFinal = true; yy_state = 335; break yy_forNext;
+                case 7: break yy_forAction;
+                default: yy_state = 254; break yy_forNext;
+              }
+
+            case 335:
+              switch (yy_input) {
+                case 29: yy_state = 259; break yy_forNext;
+                case 9: yy_isFinal = true; yy_state = 342; break yy_forNext;
+                case 7: break yy_forAction;
+                default: yy_state = 254; break yy_forNext;
+              }
+
+            case 336:
+              switch (yy_input) {
+                case 15: yy_isFinal = true; yy_state = 337; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 337:
+              switch (yy_input) {
+                case 9: yy_isFinal = true; yy_noLookAhead = true; yy_state = 343; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 338:
+              switch (yy_input) {
+                case 29: yy_state = 339; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 339:
+              switch (yy_input) {
+                case 9: yy_state = 344; break yy_forNext;
+                case 40: yy_state = 345; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 340:
+              switch (yy_input) {
+                case 30: yy_state = 341; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 341:
+              switch (yy_input) {
+                case 9: yy_state = 346; break yy_forNext;
+                case 17: yy_state = 347; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 342:
+              switch (yy_input) {
+                case 29: yy_state = 259; break yy_forNext;
+                case 7: break yy_forAction;
+                default: yy_state = 254; break yy_forNext;
+              }
+
+            case 344:
+              switch (yy_input) {
+                case 40: yy_state = 345; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 345:
+              switch (yy_input) {
+                case 9: yy_state = 348; break yy_forNext;
+                case 41: yy_state = 349; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 346:
+              switch (yy_input) {
+                case 17: yy_state = 347; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 347:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_state = 347; break yy_forNext;
+                case 9: yy_state = 350; break yy_forNext;
+                case 10: yy_isFinal = true; yy_state = 351; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 348:
+              switch (yy_input) {
+                case 41: yy_state = 349; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 349:
+              switch (yy_input) {
+                case 9: yy_state = 352; break yy_forNext;
+                case 41: yy_state = 353; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 350:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_state = 347; break yy_forNext;
+                case 10: yy_isFinal = true; yy_state = 351; break yy_forNext;
+                case 9: yy_state = 354; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 351:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_isFinal = true; yy_state = 355; break yy_forNext;
+                case 9: yy_state = 356; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 352:
+              switch (yy_input) {
+                case 41: yy_state = 353; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 353:
+              switch (yy_input) {
+                case 9: yy_state = 357; break yy_forNext;
+                case 41: yy_state = 358; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 354:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_state = 347; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 355:
+              switch (yy_input) {
+                case 9: yy_isFinal = true; yy_state = 351; break yy_forNext;
+                case 6: 
+                case 7: 
+                case 8: yy_isFinal = true; yy_state = 355; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 356:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_isFinal = true; yy_state = 355; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 357:
+              switch (yy_input) {
+                case 41: yy_state = 358; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 358:
+              switch (yy_input) {
+                case 29: yy_state = 299; break yy_forNext;
+                case 9: yy_state = 359; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 359:
+              switch (yy_input) {
+                case 29: yy_state = 299; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            default:
+              yy_ScanError(YY_ILLEGAL_STATE);
+              break;
+          } }
+
+          if ( yy_isFinal ) {
+            yy_was_pushback = yy_pushback;
+            yy_action = yy_state; 
+            yy_markedPos = yy_currentPos; 
+            if ( yy_noLookAhead ) break yy_forAction;
+          }
+
+        }
+      }
+
+      if (yy_was_pushback)
+        yy_markedPos = yy_pushbackPos;
+
+      switch (yy_action) {    
+
+        case 33: 
+        case 78: 
+          {  yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue; }
+        case 361: break;
+        case 26: 
+        case 27: 
+        case 29: 
+        case 75: 
+        case 108: 
+          {  yypushback(1); yybegin(UnDelimitedString); string.setLength(0); }
+        case 362: break;
+        case 25: 
+        case 73: 
+          {  yybegin(YYINITIAL);  if (foundContentTypeValue) hasMore = false; return HTMLHeadTokenizerConstants.MetaTagEnd; }
+        case 363: break;
+        case 41: 
+        case 86: 
+          {  yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTermintatedUnDelimitedStringValue; }
+        case 364: break;
+        case 72: 
+        case 107: 
+          {  yybegin(YYINITIAL); if (foundContentTypeValue) hasMore = false; return HTMLHeadTokenizerConstants.MetaTagEnd; }
+        case 365: break;
+        case 81: 
+        case 109: 
+          {  yypushback(yylength()); popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue; }
+        case 366: break;
+        case 144: 
+        case 157: 
+          { if (yychar == 0 ) {yybegin(ST_XMLDecl); return XMLHeadTokenizerConstants.XMLDeclStart;} }
+        case 367: break;
+        case 9: 
+        case 10: 
+        case 11: 
+        case 12: 
+        case 13: 
+        case 14: 
+        case 15: 
+        case 16: 
+        case 17: 
+        case 18: 
+        case 19: 
+        case 20: 
+        case 21: 
+        case 22: 
+        case 23: 
+        case 24: 
+        case 28: 
+        case 34: 
+        case 37: 
+        case 40: 
+          { if(yychar > MAX_TO_SCAN) {hasMore=false; return EncodingParserConstants.MAX_CHARS_REACHED;} }
+        case 368: break;
+        case 126: 
+        case 139: 
+          { yybegin(ST_META_TAG); return HTMLHeadTokenizerConstants.MetaTagStart; }
+        case 369: break;
+        case 61: 
+        case 100: 
+          { yybegin(YYINITIAL);  return XMLHeadTokenizerConstants.XMLDeclEnd; }
+        case 370: break;
+        case 351: 
+        case 355: 
+          { pushCurrentState(); yybegin(QuotedAttributeValue); foundContentTypeValue=true; return HTMLHeadTokenizerConstants.MetaTagContentType; }
+        case 371: break;
+        case 180: 
+        case 191: 
+          { pushCurrentState(); yybegin(QuotedAttributeValue); return XMLHeadTokenizerConstants.XMLDelEncoding; }
+        case 372: break;
+        case 172: 
+        case 182: 
+          { pushCurrentState(); yybegin(QuotedAttributeValue); foundContentTypeValue=true; hasCharsetAttr=true; return HTMLHeadTokenizerConstants.MetaTagContentType; }
+        case 373: break;
+        case 335: 
+        case 337: 
+        case 342: 
+        case 343: 
+          { isXHTML = true; }
+        case 374: break;
+        case 89: 
+          { hasMore = false; return EncodingParserConstants.UTF83ByteBOM; }
+        case 375: break;
+        case 44: 
+          { hasMore = false; return EncodingParserConstants.UTF16BE; }
+        case 376: break;
+        case 45: 
+          { hasMore = false; return EncodingParserConstants.UTF16LE; }
+        case 377: break;
+        case 36: 
+        case 82: 
+          {  popState(); valueText = string.toString(); return EncodingParserConstants.StringValue;  }
+        case 378: break;
+        case 32: 
+        case 35: 
+        case 38: 
+          {  string.append( yytext() );  }
+        case 379: break;
+        case 31: 
+        case 77: 
+          {  yybegin(SQ_STRING); string.setLength(0);  }
+        case 380: break;
+        case 30: 
+        case 76: 
+          {  yybegin(DQ_STRING); string.setLength(0);  }
+        case 381: break;
+        case 39: 
+        case 85: 
+          {  yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.UnDelimitedStringValue;  }
+        case 382: break;
+        case 42: 
+        case 87: 
+        case 110: 
+          {  pushCurrentState(); yybegin(UnDelimitedCharset); string.append( yytext() );  }
+        case 383: break;
+        case 43: 
+          { yypushback(1); popState();  }
+        case 384: break;
+        default: 
+          if (yy_input == YYEOF && yy_startRead == yy_currentPos) {
+            yy_atEOF = true;
+            yy_do_eof();
+              { hasMore = false; return EncodingParserConstants.EOF; }
+          } 
+          else {
+            yy_ScanError(YY_NO_MATCH);
+          }
+      }
+    }
+  }    
+
+
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contenttype/HTMLHeadTokenizerConstants.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contenttype/HTMLHeadTokenizerConstants.java
new file mode 100644
index 0000000..2600b07
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contenttype/HTMLHeadTokenizerConstants.java
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contenttype;
+
+
+public interface HTMLHeadTokenizerConstants {
+
+	String MetaTagEnd = "MetaTagEnd"; //$NON-NLS-1$
+	String MetaTagStart = "MetaTagStart"; //$NON-NLS-1$
+	String MetaTagContentType = "MetaTagContentType"; //$NON-NLS-1$
+	String UNDEFINED = "UNDEFINED"; //$NON-NLS-1$
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contenttype/HTMLResourceEncodingDetector.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contenttype/HTMLResourceEncodingDetector.java
new file mode 100644
index 0000000..22a6136
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contenttype/HTMLResourceEncodingDetector.java
@@ -0,0 +1,219 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contenttype;
+
+import java.io.IOException;
+import java.util.regex.Pattern;
+
+import org.eclipse.core.runtime.content.IContentDescription;
+import org.eclipse.wst.sse.core.internal.encoding.CodedIO;
+import org.eclipse.wst.sse.core.internal.encoding.EncodingMemento;
+import org.eclipse.wst.sse.core.internal.encoding.IResourceCharsetDetector;
+import org.eclipse.wst.xml.core.internal.contenttype.EncodingParserConstants;
+import org.eclipse.wst.xml.core.internal.contenttype.XMLHeadTokenizerConstants;
+
+public class HTMLResourceEncodingDetector extends AbstractResourceEncodingDetector implements IResourceCharsetDetector {
+
+	private HTMLHeadTokenizer fTokenizer;
+
+	/**
+	 * There is no spec defined encoding for HTML (historically), so null is
+	 * returned.
+	 */
+	public String getSpecDefaultEncoding() {
+		return null;
+	}
+
+	private boolean canHandleAsUnicodeStream(String tokenType) {
+		boolean canHandleAsUnicodeStream = false;
+		if (tokenType == EncodingParserConstants.UTF83ByteBOM) {
+			canHandleAsUnicodeStream = true;
+			String enc = "UTF-8"; //$NON-NLS-1$
+			createEncodingMemento(enc, EncodingMemento.DETECTED_STANDARD_UNICODE_BYTES);
+			fEncodingMemento.setUTF83ByteBOMUsed(true);
+		}
+		else if (tokenType == EncodingParserConstants.UTF16BE || tokenType == EncodingParserConstants.UTF16LE) {
+			canHandleAsUnicodeStream = true;
+			String enc = "UTF-16"; //$NON-NLS-1$
+			byte[] bom = (tokenType == EncodingParserConstants.UTF16BE) ? IContentDescription.BOM_UTF_16BE : IContentDescription.BOM_UTF_16LE;
+			createEncodingMemento(enc, EncodingMemento.DETECTED_STANDARD_UNICODE_BYTES);
+			fEncodingMemento.setUnicodeStream(true);
+			fEncodingMemento.setUnicodeBOM(bom);
+		}
+		return canHandleAsUnicodeStream;
+	}
+
+	/**
+	 * @return Returns the tokenizer.
+	 */
+	private HTMLHeadTokenizer getTokenizer() {
+		// TODO: need to work on 'reset' in tokenizer, so new instance isn't
+		// always needed
+		//if (fTokenizer == null) {
+		fTokenizer = new HTMLHeadTokenizer();
+		//		}
+		return fTokenizer;
+	}
+
+	private boolean isLegalString(String valueTokenType) {
+		if (valueTokenType == null)
+			return false;
+		else
+			return valueTokenType.equals(EncodingParserConstants.StringValue) || valueTokenType.equals(EncodingParserConstants.UnDelimitedStringValue) || valueTokenType.equals(EncodingParserConstants.InvalidTerminatedStringValue) || valueTokenType.equals(EncodingParserConstants.InvalidTermintatedUnDelimitedStringValue);
+	}
+
+	protected void parseInput() throws IOException {
+		checkInContent();
+		if (fEncodingMemento == null) {
+			checkHeuristics();
+		}
+	}
+
+	/**
+	 *  
+	 */
+	private void checkHeuristics() throws IOException {
+		boolean noHeuristic = false;
+		String heuristicEncoding = null;
+		try {
+			if (EncodingGuesser.canGuess()) {
+				fReader.reset();
+				fReader.mark(CodedIO.MAX_MARK_SIZE);
+				byte[] bytes = new byte[CodedIO.MAX_MARK_SIZE];
+				int nRead = 0;
+				for (int i = 0; i < bytes.length; i++) {
+					int oneByte = fReader.read();
+					nRead++;
+					if (oneByte == -1) {
+						break;
+					}
+					if (oneByte <= 0xFF) {
+						bytes[i] = (byte) oneByte;
+					}
+					else {
+						noHeuristic = true;
+						break;
+					}
+				}
+				if (!noHeuristic) {
+					heuristicEncoding = EncodingGuesser.guessEncoding(bytes, nRead);
+				}
+			}
+		}
+		catch (IOException e) {
+			// if any IO exception, then not a heuristic case
+		}
+		finally {
+			fReader.reset();
+		}
+		if (heuristicEncoding != null) {
+			createEncodingMemento(heuristicEncoding, EncodingMemento.GUESSED_ENCODING_FROM_STREAM);
+		}
+
+	}
+
+	private void checkInContent() throws IOException {
+		HTMLHeadTokenizer tokenizer = getTokenizer();
+		tokenizer.reset(fReader);
+		HeadParserToken token = null;
+		String tokenType = null;
+		String contentTypeValue = null;
+		String xhtmlEncoding = HTMLHeadTokenizerConstants.UNDEFINED;
+		boolean isXHTML = false;
+		do {
+			token = tokenizer.getNextToken();
+			tokenType = token.getType();
+			if (tokenizer.isXHTML()) {
+				isXHTML = true;
+				if (!xhtmlEncoding.equals(HTMLHeadTokenizerConstants.UNDEFINED)) {
+					if (xhtmlEncoding.length() > 0) {
+						createEncodingMemento(xhtmlEncoding, EncodingMemento.FOUND_ENCODING_IN_CONTENT);
+						return ;
+					}
+				}
+			}
+			if (canHandleAsUnicodeStream(tokenType)) {
+				// side effect of canHandle is to create appropriate
+				// memento
+			}
+			else if (tokenType == HTMLHeadTokenizerConstants.MetaTagContentType) {
+				if (tokenizer.hasMoreTokens()) {
+					HeadParserToken valueToken = tokenizer.getNextToken();
+					String valueTokenType = valueToken.getType();
+					if (isLegalString(valueTokenType)) {
+						contentTypeValue = valueToken.getText();
+
+					}
+				}
+			}
+			else if (tokenType == XMLHeadTokenizerConstants.XMLDelEncoding ) {
+				if (tokenizer.hasMoreTokens()) {
+					token = tokenizer.getNextToken();
+					tokenType = token.getType();
+					if (isLegalString(tokenType)) 
+						xhtmlEncoding = token.getText();
+				}
+			}
+
+		}
+		while (tokenizer.hasMoreTokens());
+		if (contentTypeValue != null) {
+			if (tokenizer.hasCharsetAttr()) {
+				contentTypeValue = contentTypeValue.trim();
+				if (contentTypeValue.length() > 0) {
+					createEncodingMemento(contentTypeValue, EncodingMemento.FOUND_ENCODING_IN_CONTENT);
+				}
+			}
+			else {
+				parseContentTypeValue(contentTypeValue);
+			}
+		}
+		//Content type is XHTML and no encoding found(since we did't hit return statement), use UTF-8
+		//https://bugs.eclipse.org/bugs/show_bug.cgi?id=318768
+		if (isXHTML) {
+			createEncodingMemento("UTF-8", EncodingMemento.DEFAULTS_ASSUMED_FOR_EMPTY_INPUT); //$NON-NLS-1$		
+		}
+	}
+
+	private void parseContentTypeValue(String contentType) {
+		String charset = null;
+		Pattern pattern = Pattern.compile(";\\s*charset\\s*=\\s*"); //$NON-NLS-1$
+		String[] parts = pattern.split(contentType);
+		if (parts.length > 0) {
+			// if only one item, it can still be charset instead of
+			// contentType
+			if (parts.length == 1) {
+				if (parts[0].length() > 6) {
+					String checkForCharset = parts[0].substring(0, 7);
+					if (checkForCharset.equalsIgnoreCase("charset")) { //$NON-NLS-1$
+						int eqpos = parts[0].indexOf('=');
+						eqpos = eqpos + 1;
+						if (eqpos < parts[0].length()) {
+							charset = parts[0].substring(eqpos);
+							charset = charset.trim();
+						}
+					}
+				}
+			}
+			else {
+				//fContentType = parts[0];
+			}
+		}
+		if (parts.length > 1) {
+			charset = parts[1].trim();
+		}
+		
+		if (charset != null && charset.length() > 0) {
+			createEncodingMemento(charset, EncodingMemento.FOUND_ENCODING_IN_CONTENT);
+		}
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contenttype/HeadParserToken.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contenttype/HeadParserToken.java
new file mode 100644
index 0000000..a6190bf
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contenttype/HeadParserToken.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contenttype;
+
+public class HeadParserToken {
+	private int fStart;
+
+	private String fText;
+	private String fType;
+
+	protected HeadParserToken() {
+		super();
+	}
+
+	public HeadParserToken(String type, int start, String text) {
+		this();
+		fType = type;
+		fStart = start;
+		fText = text;
+
+	}
+
+	public String getText() {
+		return fText;
+	}
+
+	public String getType() {
+		return fType;
+	}
+
+	public String toString() {
+		return ("text: " + fText + " offset: " + fStart + " type: " + fType); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contenttype/IntStack.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contenttype/IntStack.java
new file mode 100644
index 0000000..f48f2f0
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contenttype/IntStack.java
@@ -0,0 +1,114 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contenttype;
+
+/*
+ * 
+ * A non-resizable class implementing the behavior of java.util.Stack, but
+ * directly for the <code> integer </code> primitive.
+ */
+import java.util.EmptyStackException;
+
+public class IntStack {
+	private int[] list = null;
+
+	private int size = 0;
+
+	public IntStack() {
+		this(100);
+	}
+
+	public IntStack(int maxdepth) {
+		super();
+		list = new int[maxdepth];
+		initialize();
+	}
+
+	public void clear() {
+		initialize();
+	}
+
+	public boolean empty() {
+		return size == 0;
+	}
+
+	public int get(int slot) {
+		return list[slot];
+	}
+
+	private void initialize() {
+		for (int i = 0; i < list.length; i++)
+			list[i] = -1;
+	}
+
+	/**
+	 * Returns the int at the top of the stack without removing it
+	 * 
+	 * @return int at the top of this stack.
+	 * @exception EmptyStackException
+	 *                when empty.
+	 */
+	public int peek() {
+		if (size == 0)
+			throw new EmptyStackException();
+		return list[size - 1];
+	}
+
+	/**
+	 * Removes and returns the int at the top of the stack
+	 * 
+	 * @return int at the top of this stack.
+	 * @exception EmptyStackException
+	 *                when empty.
+	 */
+	public int pop() {
+		int value = peek();
+		list[size - 1] = -1;
+		size--;
+		return value;
+	}
+
+	/**
+	 * Pushes an item onto the top of this stack.
+	 * 
+	 * @param newValue -
+	 *            the int to be pushed onto this stack.
+	 * @return the <code>newValue</code> argument.
+	 */
+	public int push(int newValue) {
+		if (size == list.length) {
+			throw new StackOverflowError();
+		}
+		list[size++] = newValue;
+		return newValue;
+	}
+
+	public int size() {
+		return size;
+	}
+	
+	/* (non-Javadoc)
+	 * @see java.lang.Object#toString()
+	 */
+	public String toString() {
+		StringBuffer s = new StringBuffer(getClass().getName() + ":" +size + " [");
+		for (int i = 0; i < size; i++) {
+			s.append(list[i]);
+			if(i < size - 1) {
+				s.append(", ");
+			}
+		}
+		s.append("]");
+		return s.toString();
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contenttype/NullMemento.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contenttype/NullMemento.java
new file mode 100644
index 0000000..1a24c31
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/contenttype/NullMemento.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.contenttype;
+
+import org.eclipse.wst.sse.core.internal.encoding.EncodingMemento;
+import org.eclipse.wst.sse.core.internal.encoding.NonContentBasedEncodingRules;
+
+
+
+/**
+ * This class can be used in place of an EncodingMemento (its super class),
+ * when there is not in fact ANY encoding information. For example, when a
+ * structuredDocument is created directly from a String
+ */
+public class NullMemento extends EncodingMemento {
+	/**
+	 *  
+	 */
+	public NullMemento() {
+		super();
+		String defaultCharset = NonContentBasedEncodingRules.useDefaultNameRules(null);
+		setJavaCharsetName(defaultCharset);
+		setAppropriateDefault(defaultCharset);
+		setDetectedCharsetName(null);
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/document/DOMStyleModelImpl.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/document/DOMStyleModelImpl.java
new file mode 100644
index 0000000..dc2de33
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/document/DOMStyleModelImpl.java
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *******************************************************************************/
+/*
+ * Created on Sep 2, 2003
+ *
+ * To change the template for this generated file go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+ */
+package org.eclipse.wst.html.core.internal.document;
+
+import org.eclipse.wst.xml.core.internal.document.DOMModelImpl;
+import org.w3c.dom.Document;
+
+/**
+ * @author davidw
+ *
+ * To change the template for this generated type comment go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+ */
+public class DOMStyleModelImpl extends DOMModelImpl {
+	public DOMStyleModelImpl() {
+		// remember, the document is created in super constructor, 
+		// via internalCreateDocument
+		super();
+	}
+
+	public void releaseFromEdit() {
+		releaseStyleSheets();
+		super.releaseFromEdit();
+	}
+
+	/**
+	 */
+	public void releaseFromRead() {
+		releaseStyleSheets();
+		super.releaseFromRead();
+	}
+
+	private void releaseStyleSheets() {
+		if (!isShared()) {
+			Document doc = getDocument();
+			if (doc instanceof DocumentStyleImpl) {
+				((DocumentStyleImpl) doc).releaseStyleSheets();
+			}
+		}
+	}
+
+	/**
+	 * createDocument method
+	 * @return org.w3c.dom.Document
+	 */
+	protected Document internalCreateDocument() {
+		DocumentStyleImpl document = new DocumentStyleImpl();
+		document.setModel(this);
+		return document;
+	}
+
+
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/document/DocumentStyleImpl.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/document/DocumentStyleImpl.java
new file mode 100644
index 0000000..8efb14b
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/document/DocumentStyleImpl.java
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 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
+ *******************************************************************************/
+/*
+ * http://www.w3.org/TR/DOM-Level-2-Style/stylesheets.html#StyleSheets-StyleSheet-DocumentStyle
+ */
+package org.eclipse.wst.html.core.internal.document;
+
+import org.eclipse.wst.css.core.internal.provisional.adapters.IStyleSheetListAdapter;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapter;
+import org.eclipse.wst.xml.core.internal.document.DocumentImpl;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.css.CSSStyleDeclaration;
+import org.w3c.dom.css.DocumentCSS;
+import org.w3c.dom.stylesheets.StyleSheetList;
+
+/**
+ * @author davidw
+ *
+ * To change the template for this generated type comment go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+ */
+public class DocumentStyleImpl extends DocumentImpl implements IDOMDocument, DocumentCSS {
+	public DocumentStyleImpl() {
+		super();
+	}
+
+	protected DocumentStyleImpl(DocumentImpl that) {
+		super(that);
+	}
+
+	public CSSStyleDeclaration getOverrideStyle(Element element, String pseudoName) {
+		INodeAdapter adapter = getAdapterFor(IStyleSheetListAdapter.class);
+		if (adapter == null)
+			return null;
+		return ((IStyleSheetListAdapter) adapter).getOverrideStyle(element, pseudoName);
+	}
+
+	public StyleSheetList getStyleSheets() {
+		INodeAdapter adapter = getAdapterFor(IStyleSheetListAdapter.class);
+		if (adapter == null)
+			return null;
+		return ((IStyleSheetListAdapter) adapter).getStyleSheets();
+	}
+
+	protected void releaseStyleSheets() {
+		INodeAdapter adapter = getExistingAdapter(IStyleSheetListAdapter.class);
+		if (adapter == null)
+			return;
+		((IStyleSheetListAdapter) adapter).releaseStyleSheets();
+	}
+
+	/**
+	 * createElement method
+	 * @return org.w3c.dom.Element
+	 * @param tagName java.lang.String
+	 */
+	public Element createElement(String tagName) throws DOMException {
+		checkTagNameValidity(tagName);
+
+		ElementStyleImpl element = new ElementStyleImpl();
+		element.setOwnerDocument(this);
+		element.setTagName(tagName);
+		return element;
+	}
+
+	/**
+	 * cloneNode method
+	 * @return org.w3c.dom.Node
+	 * @param deep boolean
+	 */
+	public Node cloneNode(boolean deep) {
+		DocumentStyleImpl cloned = new DocumentStyleImpl(this);
+		if (deep)
+			cloned.importChildNodes(this, true);
+		return cloned;
+	}
+
+	protected void setModel(IDOMModel model) {
+		super.setModel(model);
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/document/ElementStyleImpl.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/document/ElementStyleImpl.java
new file mode 100644
index 0000000..7acc0fb
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/document/ElementStyleImpl.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2011 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
+ *******************************************************************************/
+/*
+ * Created on Sep 2, 2003
+ *
+ * To change the template for this generated file go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+ */
+package org.eclipse.wst.html.core.internal.document;
+
+import org.eclipse.wst.css.core.internal.provisional.adapters.IStyleDeclarationAdapter;
+import org.eclipse.wst.css.core.internal.provisional.adapters.IStyleSheetAdapter;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapter;
+import org.eclipse.wst.xml.core.internal.document.ElementImpl;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
+import org.w3c.dom.Document;
+import org.w3c.dom.css.CSSStyleDeclaration;
+import org.w3c.dom.css.ElementCSSInlineStyle;
+import org.w3c.dom.stylesheets.LinkStyle;
+import org.w3c.dom.stylesheets.StyleSheet;
+
+public class ElementStyleImpl extends ElementImpl implements IDOMElement, ElementCSSInlineStyle, LinkStyle {
+	public ElementStyleImpl() {
+		super();
+	}
+
+	public ElementStyleImpl(ElementImpl that) {
+		super(that);
+	}
+
+	public StyleSheet getSheet() {
+		INodeAdapter adapter = getAdapterFor(IStyleSheetAdapter.class);
+		if (adapter == null)
+			return null;
+		if (!(adapter instanceof IStyleSheetAdapter))
+			return null;
+		return ((IStyleSheetAdapter) adapter).getSheet();
+	}
+
+	public CSSStyleDeclaration getStyle() {
+		INodeAdapter adapter = getAdapterFor(IStyleDeclarationAdapter.class);
+		if (adapter == null)
+			return null;
+		if (!(adapter instanceof IStyleDeclarationAdapter))
+			return null;
+		return ((IStyleDeclarationAdapter) adapter).getStyle();
+	}
+
+	protected void setOwnerDocument(Document ownerDocument) {
+		super.setOwnerDocument(ownerDocument);
+	}
+
+	protected void setTagName(String tagName) {
+		super.setTagName(tagName);
+	}
+
+	protected ElementImpl newInstance() {
+		return new ElementStyleImpl(this);
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/document/HTMLConverter.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/document/HTMLConverter.java
new file mode 100644
index 0000000..c1cfcc1
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/document/HTMLConverter.java
@@ -0,0 +1,302 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.document;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.wst.html.core.internal.cleanup.HTMLCleanupProcessorImpl;
+import org.eclipse.wst.html.core.internal.preferences.HTMLCorePreferenceNames;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.cleanup.IStructuredCleanupPreferences;
+import org.eclipse.wst.sse.core.internal.provisional.IModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocumentType;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.ProcessingInstruction;
+import org.w3c.dom.Text;
+
+/**
+ */
+public class HTMLConverter {
+
+	/**
+	 */
+	public HTMLConverter() {
+		super();
+
+	}
+
+	public void cleanupModel(IDOMModel model) {
+		if (model == null)
+			return;
+
+		HTMLCleanupProcessorImpl processor = new HTMLCleanupProcessorImpl();
+		IStructuredCleanupPreferences pref = processor.getCleanupPreferences();
+
+		// backup options
+		boolean compressEmptyElementTags = pref.getCompressEmptyElementTags();
+		boolean insertRequiredAttrs = pref.getInsertRequiredAttrs();
+		boolean insertMissingTags = pref.getInsertMissingTags();
+		boolean quoteAttrValues = pref.getQuoteAttrValues();
+		boolean formatSource = pref.getFormatSource();
+		int tagNameCase = pref.getTagNameCase();
+		int attrNameCase = pref.getAttrNameCase();
+
+		// setup options
+		pref.setCompressEmptyElementTags(true);
+		pref.setInsertRequiredAttrs(true);
+		pref.setInsertMissingTags(true);
+		pref.setQuoteAttrValues(true);
+		pref.setFormatSource(false);
+		if (model.getDocument().isXMLType()) { // XHTML
+			pref.setTagNameCase(HTMLCorePreferenceNames.LOWER);
+			pref.setAttrNameCase(HTMLCorePreferenceNames.LOWER);
+		}
+		else {
+			pref.setTagNameCase(HTMLCorePreferenceNames.ASIS);
+			pref.setAttrNameCase(HTMLCorePreferenceNames.ASIS);
+		}
+
+		processor.cleanupModel(model);
+
+		// set back options
+		pref.setCompressEmptyElementTags(compressEmptyElementTags);
+		pref.setInsertRequiredAttrs(insertRequiredAttrs);
+		pref.setInsertMissingTags(insertMissingTags);
+		pref.setQuoteAttrValues(quoteAttrValues);
+		pref.setFormatSource(formatSource);
+		pref.setTagNameCase(tagNameCase);
+		pref.setAttrNameCase(attrNameCase);
+	}
+
+	/**
+	 * declaratoin: "data" for XML declaration, such as "version=\"1.0\""
+	 * publicId: publicId for DOCTYPE declaration
+	 */
+	public void convert(IDOMModel model, String declaration, String publicId) {
+		if (model == null)
+			return;
+		setDeclaration(model, declaration, publicId);
+		cleanupModel(model);
+	}
+
+	/**
+	 * declaratoin: "data" for XML declaration, such as "version=\"1.0\""
+	 * publicId: publicId for DOCTYPE declaration
+	 */
+	public void convert(InputStream input, OutputStream output, String declaration, String publicId) throws UnsupportedEncodingException, IOException, CoreException {
+		IDOMModel model = readModel(input);
+		if (model == null)
+			return;
+		try {
+			convert(model, declaration, publicId);
+			writeModel(model, output);
+		}
+		finally {
+			if (model != null)
+				model.releaseFromEdit();
+		}
+	}
+
+	/**
+	 * declaratoin: "data" for XML declaration, such as "version=\"1.0\""
+	 * publicId: publicId for DOCTYPE declaration
+	 */
+	public void convert(IFile file, String declaration, String publicId) throws IOException, CoreException {
+		IDOMModel model = readModel(file);
+		if (model == null)
+			return;
+		try {
+			convert(model, declaration, publicId);
+			writeModel(model, file);
+		}
+		finally {
+			if (model != null)
+				model.releaseFromEdit();
+		}
+	}
+
+	/**
+	 */
+	private static void insertBreak(IDOMModel model, Node node) {
+		if (model == null || node == null)
+			return;
+		if (node.getNodeType() == Node.TEXT_NODE)
+			return;
+
+		// get delimiter string
+		IStructuredDocument structuredDocument = model.getStructuredDocument();
+		if (structuredDocument == null)
+			return;
+		String delim = structuredDocument.getLineDelimiter();
+		if (delim == null || delim.length() == 0)
+			return;
+
+		Node parent = node.getParentNode();
+		if (parent == null)
+			return;
+		Document document = node.getOwnerDocument();
+		if (document == null)
+			return;
+		Text text = document.createTextNode(delim);
+		parent.insertBefore(text, node);
+	}
+
+	/**
+	 */
+	private IDOMModel readModel(InputStream input) throws IOException, UnsupportedEncodingException {
+		if (input == null)
+			return null;
+		// create temporary model
+		String id = input.toString() + ".html"; //$NON-NLS-1$
+		IModelManager manager = StructuredModelManager.getModelManager();
+		IStructuredModel model = manager.getModelForEdit(id, input, null);
+		if (!(model instanceof IDOMModel)) {
+			if (model != null)
+				model.releaseFromEdit();
+			return null;
+		}
+		return (IDOMModel) model;
+	}
+
+	/**
+	 */
+	private IDOMModel readModel(IFile file) throws IOException, CoreException {
+		if (file == null)
+			return null;
+		IModelManager manager = StructuredModelManager.getModelManager();
+		IStructuredModel model = manager.getModelForEdit(file);
+		if (!(model instanceof IDOMModel)) {
+			if (model != null)
+				model.releaseFromEdit();
+			return null;
+		}
+		return (IDOMModel) model;
+	}
+
+	/**
+	 */
+	public void setDeclaration(IDOMModel model, String declaration, String publicId) {
+		if (model == null)
+			return;
+		IDOMDocument document = model.getDocument();
+		if (document == null)
+			return;
+
+		try {
+			model.aboutToChangeModel();
+
+			ProcessingInstruction pi = null;
+			Node child = document.getFirstChild();
+			if (child != null && child.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE) {
+				String target = child.getNodeName();
+				if (target != null && target.equals("xml")) { //$NON-NLS-1$
+					pi = (ProcessingInstruction) child;
+					child = child.getNextSibling();
+				}
+			}
+			IDOMDocumentType docType = (IDOMDocumentType) document.getDoctype();
+
+			if (declaration != null) {
+				if (pi != null) {
+					pi.setData(declaration);
+				}
+				else {
+					pi = document.createProcessingInstruction("xml", declaration); //$NON-NLS-1$
+					document.insertBefore(pi, child);
+					insertBreak(model, child);
+				}
+			}
+
+			if (publicId != null) {
+				HTMLDocumentTypeEntry entry = HTMLDocumentTypeRegistry.getInstance().getEntry(publicId);
+				String name = (entry != null ? entry.getName() : null);
+				if (name == null || name.length() == 0)
+					name = "HTML"; // default //$NON-NLS-1$
+				if (docType != null) {
+					if (!name.equals(docType.getName())) { // replace
+						Node parent = docType.getParentNode();
+						child = docType;
+						docType = (IDOMDocumentType) document.createDoctype(name);
+						parent.insertBefore(docType, child);
+						parent.removeChild(child);
+					}
+				}
+				else {
+					docType = (IDOMDocumentType) document.createDoctype(name);
+					document.insertBefore(docType, child);
+					insertBreak(model, child);
+				}
+				docType.setPublicId(publicId);
+				if (entry != null) {
+					String systemId = entry.getSystemId();
+					if (systemId != null)
+						docType.setSystemId(systemId);
+					String namespaceURI = entry.getNamespaceURI();
+					if (namespaceURI != null) {
+						Element element = document.getDocumentElement();
+						if (element != null) {
+							element.setAttribute("xmlns", namespaceURI); //$NON-NLS-1$
+						}
+					}
+				}
+			}
+		}
+		finally {
+			model.changedModel();
+		}
+	}
+
+	/**
+	 */
+	private void writeModel(IDOMModel model, OutputStream output) throws UnsupportedEncodingException, IOException, CoreException {
+		if (model == null || output == null)
+			return;
+		model.save();
+	}
+
+	/**
+	 */
+	private void writeModel(IDOMModel model, IFile file) throws IOException, CoreException {
+		if (model == null || file == null)
+			return;
+		IStructuredDocument structuredDocument = model.getStructuredDocument();
+		if (structuredDocument == null)
+			return;
+		//ByteArrayOutputStream output = null;
+		ByteArrayInputStream input = null;
+		try {
+			//output = new
+			// ByteArrayOutputStream(structuredDocument.getLength());
+			model.save();
+			//input = new ByteArrayInputStream(output.toByteArray());
+			//file.setContents(input, true, true, null);
+		}
+		finally {
+			//			if (output != null)
+			//				output.close();
+			if (input != null)
+				input.close();
+		}
+
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/document/HTMLDocumentTypeAdapter.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/document/HTMLDocumentTypeAdapter.java
new file mode 100644
index 0000000..aecadc1
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/document/HTMLDocumentTypeAdapter.java
@@ -0,0 +1,268 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.document;
+
+
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.wst.html.core.internal.contentproperties.HTMLContentProperties;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.xml.core.internal.document.DocumentTypeAdapter;
+import org.eclipse.wst.xml.core.internal.document.DocumentTypeAdapterImpl;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocumentType;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Node;
+
+/**
+ */
+public class HTMLDocumentTypeAdapter extends DocumentTypeAdapterImpl implements HTMLDocumentTypeConstants {
+
+	private HTMLDocumentTypeAdapterFactory fFactory = null;
+	private HTMLDocumentTypeEntry entry = null;
+	private boolean isXMLType = false;
+	private final static String XML = "xml"; //$NON-NLS-1$
+	private final static String XHTML = "xhtml"; //$NON-NLS-1$
+	private final static String WML = "wml"; //$NON-NLS-1$
+
+	/**
+	 */
+	protected HTMLDocumentTypeAdapter() {
+		super();
+	}
+
+	/**
+	 */
+	protected HTMLDocumentTypeAdapter(IDOMDocument document, HTMLDocumentTypeAdapterFactory factory) {
+		super(document);
+
+		this.fFactory = factory;
+
+		// initialize
+		documentTypeChanged();
+	}
+
+	/**
+	 */
+	private void documentTypeChanged() {
+		IDOMDocument document = getDocument();
+		if (document == null)
+			return; // error
+		IDOMModel model = document.getModel();
+		if (model == null)
+			return; // error
+
+		IFile file = getFile(model);
+
+		// find DOCTYPE delcaration and Public ID
+		String publicId = null;
+		String systemId = null;
+		DocumentType newDocumentType = findDocumentType(document);
+		if (newDocumentType != null) {
+			publicId = newDocumentType.getPublicId();
+			systemId = newDocumentType.getSystemId();
+		}
+		else {
+			// lookup default set by contentsettings
+			publicId = HTMLContentProperties.getProperty(HTMLContentProperties.DOCUMENT_TYPE, file, true);
+		}
+
+		// lookup DOCTYPE registry
+		HTMLDocumentTypeEntry newEntry = null;
+		if (publicId != null) {
+			newEntry = HTMLDocumentTypeRegistry.getInstance().getEntry(publicId);
+		}
+		else if (systemId == null){
+			if (newDocumentType != null){ // <!DOCTYPE html>
+				newEntry = HTMLDocumentTypeRegistry.getInstance().getDefaultEntry(HTMLDocumentTypeRegistry.DEFAULT_HTML5);
+			}
+		}
+
+		boolean newXMLType = (newEntry != null ? newEntry.isXMLType() : false);
+		boolean newWMLType = (newEntry != null ? newEntry.isWMLType() : false);
+
+		if (!newXMLType) {
+			// find XML declaration
+			if (findXMLNode(document) != null) {
+				newXMLType = true;
+			}
+
+			// check file extension
+			if (file != null) {
+				String ext = file.getFileExtension();
+				if (ext != null && ext.equalsIgnoreCase(XHTML)) {
+					newXMLType = true;
+				}
+
+				if (ext != null && ext.equalsIgnoreCase(WML)) {
+					newXMLType = true;
+					newWMLType = true;
+				}
+			}
+
+		}
+
+		if (newEntry == null) {
+			// lookup system default
+			if (newXMLType && newDocumentType == null) {
+				// use default XHTML, if it's XML and no document type
+				// declared
+				if (newWMLType)
+					newEntry = HTMLDocumentTypeRegistry.getInstance().getDefaultEntry(HTMLDocumentTypeRegistry.DEFAULT_WML);
+				else
+					newEntry = HTMLDocumentTypeRegistry.getInstance().getDefaultEntry(HTMLDocumentTypeRegistry.DEFAULT_XHTML);
+
+			}
+			else {
+				newEntry = HTMLDocumentTypeRegistry.getInstance().getDefaultEntry(HTMLDocumentTypeRegistry.DEFAULT_HTML);
+			}
+			if (newEntry == null)
+				return; // error
+		}
+
+		if (newDocumentType == null) {
+			DocumentType oldDocumentType = getDocumentType();
+			if (oldDocumentType == null || oldDocumentType.getName() != newEntry.getName()) {
+				// create implicit DocumentType
+				DOMImplementation impl = document.getImplementation();
+				if (impl != null) {
+					String name = newEntry.getName();
+					publicId = newEntry.getPublicId();
+					systemId = newEntry.getSystemId();
+					newDocumentType = impl.createDocumentType(name, publicId, systemId);
+				}
+			}
+		}
+
+		boolean notify = false;
+		if (this.entry != null) { // do not notify on initialization
+			notify = (newEntry != this.entry || newXMLType != this.isXMLType);
+		}
+
+		if (newDocumentType != null)
+			setDocumentType(newDocumentType);
+		this.entry = newEntry;
+		this.isXMLType = newXMLType;
+
+		if (notify)
+			notifyDocumentTypeChanged();
+	}
+
+	/**
+	 */
+	private IDOMDocumentType findDocumentType(IDOMDocument document) {
+		IDOMDocumentType documentType = (IDOMDocumentType) document.getDoctype();
+		if (documentType != null && documentType.getExistingAdapter(DocumentTypeAdapter.class) == null) {
+			// watch future changes
+			documentType.addAdapter(this);
+		}
+		return documentType;
+	}
+
+	/**
+	 */
+	private Node findXMLNode(Document document) {
+		for (Node child = document.getFirstChild(); child != null; child = child.getNextSibling()) {
+			if (child.getNodeType() != Node.PROCESSING_INSTRUCTION_NODE)
+				continue;
+			String target = child.getNodeName();
+			if (target != null && target.equals(XML)) {
+				return child;
+			}
+		}
+		return null;
+	}
+
+	/**
+	 */
+	public int getAttrNameCase() {
+		if (isXMLType())
+			return super.getAttrNameCase(); // XHTML
+		return this.fFactory.getAttrNameCase();
+	}
+
+	private IFile getFile(IStructuredModel model) {
+		IFile result = null;
+		String location = model.getBaseLocation();
+		if (location != null) {
+			IPath path = new Path(location);
+			if (path.segmentCount() > 1) {
+				result = ResourcesPlugin.getWorkspace().getRoot().getFile(path);
+			}
+		}
+		return result;
+	}
+
+	/**
+	 */
+	public int getTagNameCase() {
+		if (isXMLType())
+			return LOWER_CASE; // XHTML
+		return this.fFactory.getTagNameCase();
+	}
+
+	/**
+	 */
+	public boolean hasFeature(String feature) {
+		if (feature == null)
+			return false;
+		if (feature.equals(HTML))
+			return true;
+		if (feature.equals(SSI))
+			return true;
+		if (feature.equals(FRAMESET)) {
+			if (this.entry == null)
+				return false;
+			return this.entry.hasFrameset();
+		}
+		if (feature.equals(HTML5)) {
+			if (this.entry == null)
+				return false;
+			return this.entry == HTMLDocumentTypeRegistry.getInstance().getDefaultEntry(HTMLDocumentTypeRegistry.DEFAULT_HTML5);
+		}
+		return false;
+	}
+
+	/**
+	 */
+	public boolean isXMLType() {
+		return this.isXMLType;
+	}
+
+	/**
+	 */
+	public void notifyChanged(INodeNotifier notifier, int eventType, Object changedFeature, Object oldValue, Object newValue, int pos) {
+		if (notifier == null)
+			return;
+		if (notifier instanceof IDOMDocument) {
+			if (eventType != INodeNotifier.STRUCTURE_CHANGED)
+				return;
+		}
+		else {
+			if (eventType != INodeNotifier.CHANGE)
+				return;
+		}
+		documentTypeChanged();
+	}
+
+	/**
+	 */
+	public void release() {
+		super.release();
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/document/HTMLDocumentTypeAdapterFactory.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/document/HTMLDocumentTypeAdapterFactory.java
new file mode 100644
index 0000000..3e15e13
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/document/HTMLDocumentTypeAdapterFactory.java
@@ -0,0 +1,170 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.document;
+
+
+
+import java.util.HashMap;
+
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.wst.html.core.internal.HTMLCorePlugin;
+import org.eclipse.wst.html.core.internal.preferences.HTMLCorePreferenceNames;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapter;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapterFactory;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.xml.core.internal.document.DocumentTypeAdapter;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
+
+/**
+ */
+public class HTMLDocumentTypeAdapterFactory implements INodeAdapterFactory, Preferences.IPropertyChangeListener {
+
+	private int tagNameCase = DocumentTypeAdapter.LOWER_CASE;
+	private int attrNameCase = DocumentTypeAdapter.LOWER_CASE;
+	private Preferences preferences = null;
+
+	// for removal later on release()
+	private HashMap fDoc2AdapterMap = new HashMap();
+	
+	/**
+	 */
+	public HTMLDocumentTypeAdapterFactory() {
+		super();
+		this.preferences = HTMLCorePlugin.getDefault().getPluginPreferences();
+
+		if (this.preferences != null) {
+			updateCases(); // initialize
+			this.preferences.addPropertyChangeListener(this);
+		}
+	}
+
+	/**
+	 * Method that returns the adapter associated with the given object. It
+	 * may be a singleton or not ... depending on the needs of the
+	 * INodeAdapter ... but in general it is recommended for an adapter to be
+	 * stateless, so the efficiencies of a singleton can be gained.
+	 * 
+	 * The implementation of this method should call addAdapter on the adapted
+	 * object with the correct instance of the adapter.
+	 */
+	public INodeAdapter adapt(INodeNotifier notifier) {
+		INodeAdapter result = null;
+		// only adapt IDOMDocument
+		if (notifier instanceof IDOMDocument) {
+
+			// if already has an adapter, no need to recreate/initialize.
+			// Note: this means if "doctype" for DOM changes,
+			// theDocumentTypeAdatper for that DOM
+			// should be removed (and released) and it will be re-created next
+			// time required.
+			DocumentTypeAdapter oldAdapter = (DocumentTypeAdapter) notifier.getExistingAdapter(DocumentTypeAdapter.class);
+			if (oldAdapter != null) {
+				result = oldAdapter;
+			}
+			else {
+				
+				// if there already was an adapter
+				//if(fAdapter != null) 
+				//	fAdapter.release();
+				
+				// note, the factory is included in this case to have a central place
+				// to come back to for case preferences.
+				result = new HTMLDocumentTypeAdapter((IDOMDocument) notifier, this);
+				notifier.addAdapter(result);
+				
+				fDoc2AdapterMap.put(notifier, result);
+			}
+		}
+		return result;
+	}
+
+	/**
+	 */
+	public int getAttrNameCase() {
+		return this.attrNameCase;
+	}
+
+	/**
+	 */
+	public int getTagNameCase() {
+		return this.tagNameCase;
+	}
+
+	/**
+	 */
+	public boolean isFactoryForType(Object type) {
+		return (type == DocumentTypeAdapter.class);
+	}
+
+	/**
+	 */
+	public void propertyChange(Preferences.PropertyChangeEvent event) {
+		if (event == null)
+			return;
+		String property = event.getProperty();
+		if (property == null)
+			return;
+
+		if (property.equals(HTMLCorePreferenceNames.TAG_NAME_CASE) || property.equals(HTMLCorePreferenceNames.ATTR_NAME_CASE)) {
+			updateCases();
+		}
+	}
+
+	/**
+	 */
+	private void updateCases() {
+		this.tagNameCase = DocumentTypeAdapter.LOWER_CASE;
+		this.attrNameCase = DocumentTypeAdapter.LOWER_CASE;
+
+		if (this.preferences == null)
+			return;
+
+		int tagCase = this.preferences.getInt(HTMLCorePreferenceNames.TAG_NAME_CASE);
+		if (tagCase == HTMLCorePreferenceNames.LOWER)
+			this.tagNameCase = DocumentTypeAdapter.LOWER_CASE;
+		else if (tagCase == HTMLCorePreferenceNames.UPPER)
+			this.tagNameCase = DocumentTypeAdapter.UPPER_CASE;
+		
+		int attCase = this.preferences.getInt(HTMLCorePreferenceNames.ATTR_NAME_CASE);
+		if (attCase == HTMLCorePreferenceNames.LOWER)
+			this.attrNameCase = DocumentTypeAdapter.LOWER_CASE;
+		else if (attCase == HTMLCorePreferenceNames.UPPER)
+			this.tagNameCase = DocumentTypeAdapter.UPPER_CASE;
+	}
+
+	/**
+	 */
+	public void release() {
+		
+		if(!fDoc2AdapterMap.isEmpty()) {
+			Object[] docs = fDoc2AdapterMap.keySet().toArray();
+			DocumentTypeAdapter adapter = null;
+			for (int i = 0; i < docs.length; i++) {
+				adapter = (DocumentTypeAdapter)fDoc2AdapterMap.get(docs[i]);
+				adapter.release();
+				((IDOMDocument)docs[i]).removeAdapter(adapter);
+			}
+			fDoc2AdapterMap.clear();
+		}
+		
+		// https://bugs.eclipse.org/bugs/show_bug.cgi?id=95960
+		if (this.preferences != null) {
+			this.preferences.removePropertyChangeListener(this);
+		}
+	}
+
+	/**
+	 * Overriding copy method
+	 */
+	public INodeAdapterFactory copy() {
+		return new HTMLDocumentTypeAdapterFactory();
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/document/HTMLDocumentTypeConstants.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/document/HTMLDocumentTypeConstants.java
new file mode 100644
index 0000000..7aae3cf
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/document/HTMLDocumentTypeConstants.java
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.document;
+
+public interface HTMLDocumentTypeConstants {
+
+	public final static String HTML = "HTML"; //$NON-NLS-1$
+	public final static String FRAMESET = "FRAMESET"; //$NON-NLS-1$
+	public final static String SSI = "SSI"; //$NON-NLS-1$
+	String HTML5 = "HTML5"; //$NON-NLS-1$
+
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/document/HTMLDocumentTypeEntry.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/document/HTMLDocumentTypeEntry.java
new file mode 100644
index 0000000..83158e7
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/document/HTMLDocumentTypeEntry.java
@@ -0,0 +1,136 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.document;
+
+
+
+/**
+ */
+public class HTMLDocumentTypeEntry {
+
+	private String name;
+	private String publicId;
+	private String systemId;
+	private String namespaceURI;
+	private boolean isXMLType;
+	private boolean isXHTMLType;
+	private boolean isWMLType;
+	private boolean hasFrameset;
+	private String displayName;
+	private boolean isDefaultXHTML;
+	private boolean isDefaultWML;
+	private static String XHTML_NAME = "html"; //$NON-NLS-1$
+	private static String HTML_NAME = "HTML"; //$NON-NLS-1$
+	private boolean useInternalModel = false;
+
+	/**
+	 */
+	private HTMLDocumentTypeEntry() {
+		super();
+	}
+
+	/**
+	 */
+	public HTMLDocumentTypeEntry(String name, String publicId, String systemId, String namespaceURI, boolean isXHTMLType, boolean hasFrameset, String displayName, boolean isDefaultXHTML, boolean isDefaultWML, boolean isWMLType) {
+		this();
+
+		if (name != null && name.length() > 0) {
+			this.name = name;
+		}
+		else {
+			if (isXMLType)
+				this.name = XHTML_NAME;// need code for wml?
+			else
+				this.name = HTML_NAME;
+		}
+		this.publicId = publicId;
+		this.systemId = systemId;
+		this.namespaceURI = namespaceURI;
+		this.isXMLType = isXHTMLType | isWMLType;
+		this.hasFrameset = hasFrameset;
+		this.displayName = displayName;
+		this.isDefaultXHTML = isDefaultXHTML;
+		this.isDefaultWML = isDefaultWML;
+		this.isXHTMLType = isXHTMLType;
+		this.isWMLType = isWMLType;
+	}
+	
+	HTMLDocumentTypeEntry(String name, String publicId, String systemId, String namespaceURI, boolean isXHTMLType, boolean hasFrameset, String displayName, boolean isDefaultXHTML, boolean isDefaultWML, boolean isWMLType, boolean useInternalModel) {
+		this(name, publicId, systemId, namespaceURI, isXHTMLType, hasFrameset, displayName, isDefaultXHTML, isDefaultWML, isWMLType);
+		this.useInternalModel = useInternalModel;
+	}
+
+	/**
+	 */
+	public final String getName() {
+		return this.name;
+	}
+
+	/**
+	 */
+	public final String getNamespaceURI() {
+		return this.namespaceURI;
+	}
+
+	/**
+	 */
+	public final String getPublicId() {
+		return this.publicId;
+	}
+
+	/**
+	 */
+	public final String getSystemId() {
+		return this.systemId;
+	}
+
+	/**
+	 */
+	public final boolean isXMLType() {
+		return this.isXMLType;
+	}
+
+	/**
+	 */
+	public final boolean hasFrameset() {
+		return this.hasFrameset;
+	}
+
+	/**
+	 */
+	public final String getDisplayName() {
+		return this.displayName;
+	}
+
+	/**
+	 */
+	public final boolean isDefaultXHTML() {
+		return this.isDefaultXHTML;
+	}
+
+	public final boolean isDefaultWML() {
+		return this.isDefaultWML;
+	}
+
+
+	public final boolean isXHTMLType() {
+		return isXHTMLType;
+	}
+
+	public final boolean isWMLType() {
+		return isWMLType;
+	}
+	
+	public final boolean useInternalModel() {
+		return useInternalModel;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/document/HTMLDocumentTypeRegistry.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/document/HTMLDocumentTypeRegistry.java
new file mode 100644
index 0000000..457558f
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/document/HTMLDocumentTypeRegistry.java
@@ -0,0 +1,172 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.document;
+
+import java.text.Collator;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Vector;
+
+public class HTMLDocumentTypeRegistry {
+	static class HTMLDocumentTypeEntryComparator implements Comparator {
+		static Collator delegate = Collator.getInstance();
+
+		public int compare(Object o1, Object o2) {
+			if (o1 instanceof HTMLDocumentTypeEntry && o2 instanceof HTMLDocumentTypeEntry) {
+				if (((HTMLDocumentTypeEntry) o1).getDisplayName() != null && ((HTMLDocumentTypeEntry) o2).getDisplayName() != null) {
+					return delegate.compare(((HTMLDocumentTypeEntry) o1).getDisplayName(), ((HTMLDocumentTypeEntry) o2).getDisplayName());
+				}
+			}
+			return 0;
+		}
+	}
+
+	private static HTMLDocumentTypeRegistry instance = null;
+	private Hashtable entries = null;
+	private HTMLDocumentTypeEntry defaultEntry = null;
+	private HTMLDocumentTypeEntry defaultXHTMLEntry = null;
+	private HTMLDocumentTypeEntry defaultWMLEntry = null;
+	private HTMLDocumentTypeEntry defaultCHTMLEntry = null;
+	private HTMLDocumentTypeEntry defaultHTML5Entry = null;
+	
+	final static int DEFAULT_HTML = 0;
+	final static int DEFAULT_XHTML = 1;
+	final static int DEFAULT_WML = 2;
+	final static int DEFAULT_CHTML = 3;
+	final static int DEFAULT_HTML5 = 4;
+	
+	public static final String CHTML_PUBLIC_ID = "-//W3C//DTD Compact HTML 1.0 Draft//EN";//$NON-NLS-1$
+
+	/**
+	 */
+	private HTMLDocumentTypeRegistry() {
+		super();
+
+		this.entries = new Hashtable();
+		// HTML 4.01
+		String name = "HTML";//$NON-NLS-1$
+		String publicId = "-//W3C//DTD HTML 4.01 Transitional//EN";//$NON-NLS-1$
+		String systemId = "http://www.w3.org/TR/html4/loose.dtd";//$NON-NLS-1$
+		String displayName = "HTML 4.01 Transitional"; //$NON-NLS-1$
+		this.defaultEntry = new HTMLDocumentTypeEntry(name, publicId, systemId, null, false, false, displayName, false, false, false, true);
+		this.entries.put(publicId, this.defaultEntry);
+		publicId = "-//W3C//DTD HTML 4.01//EN";//$NON-NLS-1$
+		systemId = "http://www.w3.org/TR/html4/strict.dtd";//$NON-NLS-1$
+		displayName = "HTML 4.01 Strict"; //$NON-NLS-1$
+		this.entries.put(publicId, new HTMLDocumentTypeEntry(name, publicId, systemId, null, false, false, displayName, false, false, false, true));
+		publicId = "-//W3C//DTD HTML 4.01 Frameset//EN";//$NON-NLS-1$
+		systemId = "http://www.w3.org/TR/html4/frameset.dtd";//$NON-NLS-1$
+		displayName = "HTML 4.01 Frameset"; //$NON-NLS-1$
+		this.entries.put(publicId, new HTMLDocumentTypeEntry(name, publicId, systemId, null, false, true, displayName, false, false, false, true));
+		// CHTML
+		name = "HTML";//$NON-NLS-1$
+		publicId = CHTML_PUBLIC_ID;
+		displayName = "Compact HTML 1.0 Draft"; //$NON-NLS-1$
+		this.defaultCHTMLEntry = new HTMLDocumentTypeEntry(name, publicId, null, null, false, false, displayName, false, false, false, true);
+		this.entries.put(publicId, this.defaultCHTMLEntry);
+
+		//HTML5
+		name = "HTML5";//$NON-NLS-1$
+		publicId = "";
+		displayName = "HTML5"; //$NON-NLS-1$
+		this.defaultHTML5Entry = new HTMLDocumentTypeEntry(name, publicId, null, null, false, false, displayName, false, false, false, true);
+		this.entries.put(publicId, this.defaultHTML5Entry);
+		
+		
+
+		HTMLDocumentTypeRegistryReader reader = new HTMLDocumentTypeRegistryReader();
+		if (reader != null)
+			reader.readRegistry(this);
+	}
+
+	/**
+	 */
+	void regist(String pid, HTMLDocumentTypeEntry doctype) {
+		if (pid == null || doctype == null)
+			return;
+		this.entries.put(pid, doctype);
+		if (this.defaultXHTMLEntry == null) {
+			if (doctype.isDefaultXHTML())
+				this.defaultXHTMLEntry = doctype;
+		}
+		if (this.defaultWMLEntry == null) {
+			if (doctype.isDefaultWML())
+				this.defaultWMLEntry = doctype;
+		}
+	}
+
+	/**
+	 * 
+	 */
+	public HTMLDocumentTypeEntry getDefaultEntry(int type) {
+		HTMLDocumentTypeEntry entry = null;
+		switch (type) {
+			case DEFAULT_HTML5 :
+				entry = this.defaultHTML5Entry;
+				break;
+			case DEFAULT_XHTML :
+				entry = this.defaultXHTMLEntry;
+				break;
+			case DEFAULT_WML :
+				entry = this.defaultWMLEntry;
+				break;
+			case DEFAULT_CHTML :
+				entry = this.defaultCHTMLEntry;
+				break;
+			case DEFAULT_HTML :
+			default :
+				entry = this.defaultEntry;
+				break;
+		}
+		return entry;
+	}
+
+	/**
+	 * 
+	 */
+	public HTMLDocumentTypeEntry getDefaultEntry() {
+		return this.defaultEntry;
+	}
+
+	/**
+	 */
+	public HTMLDocumentTypeEntry getXHTMLDefaultEntry() {
+		return this.defaultXHTMLEntry;
+	}
+
+	/**
+	 */
+	public Enumeration getEntries() {
+		List values = new ArrayList(this.entries.values());
+		Collections.sort(values, new HTMLDocumentTypeEntryComparator());
+		return new Vector(values).elements();
+	}
+
+	/**
+	 */
+	public HTMLDocumentTypeEntry getEntry(String publicId) {
+		if (publicId == null)
+			return null;
+		return (HTMLDocumentTypeEntry) this.entries.get(publicId);
+	}
+
+	/**
+	 */
+	public synchronized static HTMLDocumentTypeRegistry getInstance() {
+		if (instance == null)
+			instance = new HTMLDocumentTypeRegistry();
+		return instance;
+	}
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/document/HTMLDocumentTypeRegistryReader.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/document/HTMLDocumentTypeRegistryReader.java
new file mode 100644
index 0000000..f419978
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/document/HTMLDocumentTypeRegistryReader.java
@@ -0,0 +1,107 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.document;
+
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtensionPoint;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.Platform;
+
+/**
+ */
+class HTMLDocumentTypeRegistryReader {
+
+	//
+	private final static String PLUGIN_ID = "org.eclipse.wst.sse.core"; //$NON-NLS-1$
+	private final static String EXTENSION_POINT_ID = "documentTypes"; //$NON-NLS-1$
+	private final static String TAG_NAME = "documentType"; //$NON-NLS-1$
+	private final static String ATT_PID = "publicID"; //$NON-NLS-1$
+	private final static String ATT_SID = "systemID"; //$NON-NLS-1$
+	private final static String ATT_IS_XHTML = "isXHTML"; //$NON-NLS-1$
+	private final static String ATT_IS_WML = "isWML"; //$NON-NLS-1$
+	private final static String ATT_HAS_FRAMESET = "hasFrameset"; //$NON-NLS-1$
+	private final static String ATT_NSURI = "namespaceURI"; //$NON-NLS-1$
+	private final static String ATT_ENAME = "elementName"; //$NON-NLS-1$
+	private final static String ATT_DNAME = "displayName"; //$NON-NLS-1$
+	private final static String ATT_IS_DEFAULT_XHTML = "defaultXHTML"; //$NON-NLS-1$
+	private final static String ATT_IS_DEFAULT_WML = "defaultWML"; //$NON-NLS-1$
+	private final static String ATV_TRUE = "true"; //$NON-NLS-1$
+	private final static String ATV_NULL_STRING = ""; //$NON-NLS-1$
+
+	/**
+	 */
+	HTMLDocumentTypeRegistryReader() {
+		super();
+	}
+
+	/**
+	 */
+	void readRegistry(HTMLDocumentTypeRegistry reg) {
+		if (reg == null)
+			return;
+		IExtensionRegistry registry = Platform.getExtensionRegistry();
+		IExtensionPoint point = registry.getExtensionPoint(PLUGIN_ID, EXTENSION_POINT_ID);
+		if (point != null) {
+			IConfigurationElement[] elements = point.getConfigurationElements();
+			for (int i = 0; i < elements.length; i++) {
+				HTMLDocumentTypeEntry doctype = readElement(elements[i]);
+				// null can be returned if there's an error reading the element
+				if (doctype != null) {
+					reg.regist(doctype.getPublicId(), doctype);
+				}
+			}
+		}
+	}
+
+	/**
+	 */
+	private HTMLDocumentTypeEntry readElement(IConfigurationElement element) {
+		HTMLDocumentTypeEntry doctype = null;
+		String pid = null;
+		String sid = null;
+		String nsuri = null;
+		String root = null;
+		boolean xhtml = true;
+		boolean frameset = false;
+		String dname = null;
+		boolean defaultXhtml = false;
+		boolean defaultWML = false;
+		boolean isWML = false;
+
+		if (element.getName().equals(TAG_NAME)) {
+			pid = element.getAttribute(ATT_PID);
+			// publicID attribute is mandatory.
+			if (pid == null || pid.equals(ATV_NULL_STRING))
+				return null;
+
+			sid = element.getAttribute(ATT_SID);
+			nsuri = element.getAttribute(ATT_NSURI);
+			root = element.getAttribute(ATT_ENAME);
+			xhtml = getBoolean(element, ATT_IS_XHTML);
+			frameset = getBoolean(element, ATT_HAS_FRAMESET);
+			dname = element.getAttribute(ATT_DNAME);
+			defaultXhtml = getBoolean(element, ATT_IS_DEFAULT_XHTML);
+			defaultWML = getBoolean(element, ATT_IS_DEFAULT_WML);
+			isWML = getBoolean(element, ATT_IS_WML);
+			doctype = new HTMLDocumentTypeEntry(root, pid, sid, nsuri, xhtml, frameset, dname, defaultXhtml, defaultWML, isWML);
+		}
+		return doctype;
+	}
+
+	/**
+	 */
+	private boolean getBoolean(IConfigurationElement element, String att) {
+		String value = element.getAttribute(att);
+		if (value != null && value.equals(ATV_TRUE))
+			return true;
+		return false;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/document/HTMLModelParserAdapter.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/document/HTMLModelParserAdapter.java
new file mode 100644
index 0000000..4e7ddcb
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/document/HTMLModelParserAdapter.java
@@ -0,0 +1,365 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.document;
+
+
+
+import org.eclipse.wst.html.core.internal.contentmodel.HTMLElementDeclaration;
+import org.eclipse.wst.html.core.internal.contentmodel.HTMLPropertyDeclaration;
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.html.core.internal.provisional.HTMLCMProperties;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMContent;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNodeList;
+import org.eclipse.wst.xml.core.internal.document.CMNodeUtil;
+import org.eclipse.wst.xml.core.internal.document.ModelParserAdapter;
+import org.eclipse.wst.xml.core.internal.document.TagAdapter;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMText;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+/**
+ * HTMLDocumentImpl class
+ */
+public class HTMLModelParserAdapter implements ModelParserAdapter {
+	/**
+	 * note: I made public, temparily, so could be used by JSPLoader
+	 */
+	protected HTMLModelParserAdapter() {
+		super();
+	}
+
+	private boolean shouldTerminateAt(CMElementDeclaration parent, CMElementDeclaration child) {
+		if (!parent.supports(HTMLCMProperties.TERMINATORS))
+			return false;
+		java.util.Iterator i = (java.util.Iterator) parent.getProperty(HTMLCMProperties.TERMINATORS);
+		if (i == null)
+			return false;
+		String nextName = child.getElementName();
+		while (i.hasNext()) {
+			// NOTE: CMElementDeclaration of child is not always HTMLCMElementDeclaration.
+			// It might be one of based on DTD (for XHTML element).  So, comparison must
+			// be performed ignoring case.
+			// -- 3/20/2002
+			String terminator = (String) i.next();
+			if (terminator == null)
+				continue;
+			if (nextName.equalsIgnoreCase(terminator))
+				return true;
+		}
+		return false;
+	}
+
+	public boolean isEndTagOmissible(Element element) {
+		CMElementDeclaration dec = CMNodeUtil.getElementDeclaration(element);
+		if (dec == null || !(dec instanceof HTMLPropertyDeclaration))
+			return false;
+		int type = ((HTMLPropertyDeclaration)dec ).getOmitType();
+		return type == HTMLElementDeclaration.OMIT_BOTH || type == HTMLElementDeclaration.OMIT_END || type == HTMLElementDeclaration.OMIT_END_DEFAULT || type == HTMLElementDeclaration.OMIT_END_MUST;
+	}
+
+	/**
+	 */
+	public boolean canContain(Element element, Node child) {
+		if (element == null || child == null)
+			return false;
+		IDOMElement impl = (IDOMElement) element;
+
+		if (child.getNodeType() == Node.ELEMENT_NODE) {
+			if (!impl.isGlobalTag())
+				return true; // non HTML tag
+			IDOMElement childElement = (IDOMElement) child;
+
+			CMElementDeclaration myDec = CMNodeUtil.getElementDeclaration(element);
+			if (myDec == null)
+				return true;
+			//if (!(myDec instanceof HTMLElementDeclaration)) return true;
+			if (myDec.getContentType() == CMElementDeclaration.EMPTY)
+				return false;
+
+			if (!childElement.isGlobalTag())
+				return true; // non HTML tag
+			CMElementDeclaration childDec = CMNodeUtil.getElementDeclaration(childElement);
+			if (childDec == null)
+				return true;
+			//if (!(childDec instanceof HTMLElementDeclaration)) return true;
+
+			if (myDec instanceof HTMLElementDeclaration) {
+				if (((Boolean) ((HTMLElementDeclaration) myDec).getProperty(HTMLCMProperties.IS_JSP)).booleanValue())
+					return true;
+			}
+			if (shouldTerminateAt(myDec, childDec) && !isValidChild(myDec, childDec)) {
+				return false;
+			}
+
+			String tagName = impl.getTagName();
+			if (tagName == null)
+				return true;
+			String childName = childElement.getTagName();
+			if (childName == null)
+				return true;
+			if (!impl.hasStartTag() && !impl.hasEndTag()) {
+				// implicit element
+				if (tagName.equalsIgnoreCase(childElement.getTagName()))
+					return false;
+				if (tagName.equalsIgnoreCase(HTML40Namespace.ElementName.HEAD)) {
+					if (!childName.equalsIgnoreCase(HTML40Namespace.ElementName.META) && !childName.equalsIgnoreCase(HTML40Namespace.ElementName.TITLE) && !childName.equalsIgnoreCase(HTML40Namespace.ElementName.LINK) && !childName.equalsIgnoreCase(HTML40Namespace.ElementName.STYLE) && !childName.equalsIgnoreCase(HTML40Namespace.ElementName.BASE) && !childName.equalsIgnoreCase(HTML40Namespace.ElementName.ISINDEX)) {
+						return false;
+					}
+				}
+
+				Node parent = element.getParentNode();
+				if (parent != null && parent.getNodeType() == Node.ELEMENT_NODE) {
+					IDOMElement parentElement = (IDOMElement) parent;
+					if (!parentElement.hasStartTag() && !parentElement.hasEndTag()) {
+						if (!canContain(parentElement, child))
+							return false;
+					}
+				}
+				return true;
+			}
+
+			// contexual termination for TABLE content tags
+			boolean isTableContent = false;
+			if (childName.equalsIgnoreCase(HTML40Namespace.ElementName.TBODY) || childName.equalsIgnoreCase(HTML40Namespace.ElementName.THEAD) || childName.equalsIgnoreCase(HTML40Namespace.ElementName.TFOOT)) {
+				if (tagName.equalsIgnoreCase(HTML40Namespace.ElementName.TABLE))
+					return true;
+				isTableContent = true;
+			}
+			else if (childName.equalsIgnoreCase(HTML40Namespace.ElementName.TR)) {
+				if (tagName.equalsIgnoreCase(HTML40Namespace.ElementName.TBODY) || tagName.equalsIgnoreCase(HTML40Namespace.ElementName.THEAD) || tagName.equalsIgnoreCase(HTML40Namespace.ElementName.TFOOT) || tagName.equalsIgnoreCase(HTML40Namespace.ElementName.TABLE))
+					return true;
+				isTableContent = true;
+			}
+			else if (childName.equalsIgnoreCase(HTML40Namespace.ElementName.TD) || childName.equalsIgnoreCase(HTML40Namespace.ElementName.TH)) {
+				if (tagName.equalsIgnoreCase(HTML40Namespace.ElementName.TR) || tagName.equalsIgnoreCase(HTML40Namespace.ElementName.TBODY) || tagName.equalsIgnoreCase(HTML40Namespace.ElementName.THEAD) || tagName.equalsIgnoreCase(HTML40Namespace.ElementName.TFOOT) || tagName.equalsIgnoreCase(HTML40Namespace.ElementName.TABLE))
+					return true;
+				isTableContent = true;
+			}
+			if (isTableContent) {
+				// TABLE content tags should terminate non TABLE content tags,
+				// if in TABLE
+				for (Node parent = element.getParentNode(); parent != null; parent = parent.getParentNode()) {
+					if (parent.getNodeType() != Node.ELEMENT_NODE)
+						break;
+					IDOMElement parentElement = (IDOMElement) parent;
+					String parentName = parentElement.getTagName();
+					if (parentName == null)
+						continue;
+					if (parentName.equalsIgnoreCase(HTML40Namespace.ElementName.TABLE))
+						return false;
+				}
+			}
+			if (tagName.equalsIgnoreCase(HTML40Namespace.ElementName.EMBED)) {
+				if (!childName.equalsIgnoreCase(HTML40Namespace.ElementName.NOEMBED))
+					return false;
+			}
+		}
+		else if (child.getNodeType() == Node.TEXT_NODE) {
+			String tagName = impl.getTagName();
+			if (tagName != null && tagName.equalsIgnoreCase(HTML40Namespace.ElementName.EMBED)) {
+				IDOMText text = (IDOMText) child;
+				if (!text.isElementContentWhitespace())
+					return false;
+			}
+		}
+		else if (child.getNodeType() == Node.DOCUMENT_TYPE_NODE) {
+			if (impl.isImplicitTag())
+				return false;
+		}
+
+		return true;
+	}
+
+	/**
+	 */
+	public boolean canBeImplicitTag(Element element) {
+		return false;
+	}
+
+	/**
+	 */
+	public boolean canBeImplicitTag(Element element, Node child) {
+		return false;
+	}
+
+	/**
+	 */
+	public Element createCommentElement(Document document, String data, boolean isJSPTag) {
+		if (document == null || data == null || data.length() == 0)
+			return null;
+
+		return createMetaElement(document, data, isJSPTag);
+	}
+
+	/**
+	 * This routine create an implicit Element for given parent and child,
+	 * such as HTML, BODY, HEAD, and TBODY for HTML document.
+	 */
+	public Element createImplicitElement(Document document, Node parent, Node child) {
+		return null;
+	}
+
+	/**
+	 */
+	private Element createMetaElement(Document document, String data, boolean isJSPTag) {
+		if (data == null || data.length() == 0)
+			return null;
+
+		TagScanner scanner = new TagScanner(data, 0, true); // one line
+		String name = scanner.nextName();
+		if (name == null || !name.equalsIgnoreCase(MetaData.METADATA))
+			return null;
+
+		String type = null;
+		boolean isStartSpan = false;
+		boolean isEndSpan = false;
+		name = scanner.nextName();
+		while (name != null) {
+			String value = scanner.nextValue();
+			if (name.equalsIgnoreCase(MetaData.TYPE)) {
+				if (value == null)
+					return null;
+				if (value.equalsIgnoreCase(MetaData.DESIGNER_CONTROL)) {
+					type = MetaData.DESIGNER_CONTROL;
+				}
+				else if (value.equalsIgnoreCase(MetaData.DYNAMIC_DATA)) {
+					type = MetaData.DYNAMIC_DATA;
+				}
+				else if (value.equalsIgnoreCase(MetaData.AUTHOR_TIME_VISUAL)) {
+					type = MetaData.AUTHOR_TIME_VISUAL;
+				}
+				else if (value.equalsIgnoreCase(MetaData.ANNOTATION)) {
+					type = MetaData.ANNOTATION;
+				}
+				else {
+					return null;
+				}
+			}
+			else if (name.equalsIgnoreCase(MetaData.STARTSPAN)) {
+				isStartSpan = true;
+			}
+			else if (name.equalsIgnoreCase(MetaData.ENDSPAN)) {
+				if (!isStartSpan)
+					isEndSpan = true;
+			}
+			name = scanner.nextName();
+		}
+		if (type == null)
+			return null;
+		if (!isStartSpan && !isEndSpan)
+			return null;
+		String metaData = null;
+		int offset = scanner.getNextOffset(); // skip new line
+		if (offset < data.length())
+			metaData = data.substring(offset);
+		if (metaData == null)
+			metaData = new String();
+
+		IDOMElement element = (IDOMElement) document.createElement(MetaData.PREFIX + type);
+
+		MetaDataAdapter adapter = new MetaDataAdapter(type);
+		if (isStartSpan) {
+			if (metaData != null)
+				adapter.setData(metaData);
+		}
+		else {
+			if (metaData != null)
+				adapter.setEndData(metaData);
+		}
+		element.addAdapter(adapter);
+		adapter.setElement(element);
+		element.setJSPTag(isJSPTag);
+
+		return element;
+	}
+
+	/**
+	 */
+	public String getFindRootName(String tagName) {
+		if (tagName == null)
+			return null;
+		// tag matching should not beyond TABLE tag except BODY tag
+		if (tagName.equalsIgnoreCase(HTML40Namespace.ElementName.BODY))
+			return null;
+		return HTML40Namespace.ElementName.TABLE;
+	}
+
+	/**
+	 */
+	public boolean isAdapterForType(Object type) {
+		return (type == ModelParserAdapter.class);
+	}
+
+	/**
+	 */
+	public boolean isEndTag(IDOMElement element) {
+		TagAdapter adapter = (TagAdapter) element.getExistingAdapter(TagAdapter.class);
+		if (adapter != null)
+			return adapter.isEndTag();
+		return element.isEndTag();
+	}
+
+	/**
+	 */
+	public void notifyChanged(INodeNotifier notifier, int eventType, Object changedFeature, Object oldValue, Object newValue, int pos) {
+		// do nothing on notifiy change
+		// TODO: this means good candidate for regular platform adapter
+	}
+
+	private static boolean isValidChild(CMElementDeclaration parent, CMElementDeclaration child) {
+		if (parent == null || child == null)
+			return false;
+		CMContent content = parent.getContent();
+		if (content == null)
+			return false;
+		return isChild(content, child);
+	}
+
+	/**
+	 */
+	private static boolean isChild(CMContent content, CMElementDeclaration target) {
+		switch (content.getNodeType()) {
+			case CMNode.ELEMENT_DECLARATION :
+				return isSameDeclaration((CMElementDeclaration) content, target);
+			case CMNode.GROUP :
+				CMNodeList children = ((CMGroup) content).getChildNodes();
+				for (int i = 0; i < children.getLength(); i++) {
+					CMNode child = children.item(i);
+					switch (child.getNodeType()) {
+						case CMNode.ELEMENT_DECLARATION :
+							if (isSameDeclaration((CMElementDeclaration) child, target))
+								return true;
+							continue; // Go next child.
+						case CMNode.GROUP :
+							if (isChild((CMContent) child, target))
+								return true;
+							continue; // Go next child.
+						default :
+							continue; // Go next child.
+					}
+				}
+		}
+		return false;
+	}
+
+	/**
+	 */
+	private static boolean isSameDeclaration(CMElementDeclaration aDec, CMElementDeclaration otherDec) {
+		return aDec.getElementName() == otherDec.getElementName();
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/document/HTMLModelParserAdapterFactory.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/document/HTMLModelParserAdapterFactory.java
new file mode 100644
index 0000000..98765e8
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/document/HTMLModelParserAdapterFactory.java
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.document;
+
+
+
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapter;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapterFactory;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.xml.core.internal.document.ModelParserAdapter;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
+
+/**
+ */
+public class HTMLModelParserAdapterFactory implements INodeAdapterFactory {
+
+	private static HTMLModelParserAdapterFactory instance = null;
+
+	/**
+	 */
+	private HTMLModelParserAdapterFactory() {
+		super();
+	}
+
+	/**
+	 * Method that returns the adapter associated with the given object. It
+	 * may be a singleton or not ... depending on the needs of the
+	 * INodeAdapter ... but in general it is recommended for an adapter to be
+	 * stateless, so the efficiencies of a singleton can be gained.
+	 * 
+	 * The implementation of this method should call addAdapter on the adapted
+	 * object with the correct instance of the adapter.
+	 */
+	public INodeAdapter adapt(INodeNotifier notifier) {
+		INodeAdapter adapter = null;
+		if (notifier != null) {
+			if (notifier instanceof IDOMDocument) {
+				adapter = notifier.getExistingAdapter(ModelParserAdapter.class);
+				if (adapter == null) {
+					adapter = new HTMLModelParserAdapter();
+					notifier.addAdapter(adapter);
+				}
+			}
+		}
+		return adapter;
+
+	}
+
+	/**
+	 */
+	public synchronized static HTMLModelParserAdapterFactory getInstance() {
+		if (instance == null)
+			instance = new HTMLModelParserAdapterFactory();
+		return instance;
+	}
+
+	/**
+	 */
+	public boolean isFactoryForType(Object type) {
+		return (type == ModelParserAdapter.class);
+	}
+
+	/**
+	 */
+	public void release() {
+		// no state to cleanup
+	}
+
+	/**
+	 * Overriding copy method
+	 */
+	public INodeAdapterFactory copy() {
+		return getInstance();
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/document/MetaData.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/document/MetaData.java
new file mode 100644
index 0000000..a05758c
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/document/MetaData.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.document;
+
+
+
+/**
+ */
+public interface MetaData {
+
+	static final String METADATA = "METADATA";//$NON-NLS-1$
+	static final String TYPE = "type";//$NON-NLS-1$
+	static final String STARTSPAN = "startspan";//$NON-NLS-1$
+	static final String ENDSPAN = "endspan";//$NON-NLS-1$
+	static final String DESIGNER_CONTROL = "DesignerControl";//$NON-NLS-1$
+	static final String DYNAMIC_DATA = "DynamicData";//$NON-NLS-1$
+	static final String AUTHOR_TIME_VISUAL = "AuthorTimeVisual";//$NON-NLS-1$
+	static final String ANNOTATION = "Annotation";//$NON-NLS-1$
+	static final String PREFIX = "METADATA:";//$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/document/MetaDataAdapter.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/document/MetaDataAdapter.java
new file mode 100644
index 0000000..9b8596e
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/document/MetaDataAdapter.java
@@ -0,0 +1,301 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.document;
+
+
+
+import java.util.Iterator;
+
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+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.ITextRegionList;
+import org.eclipse.wst.xml.core.internal.document.TagAdapter;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+
+/**
+ */
+public class MetaDataAdapter implements TagAdapter, MetaData {
+
+	private IDOMElement element = null;
+	private String type = null;
+	private String data = null;
+	private String endData = null;
+
+	/**
+	 */
+	public MetaDataAdapter(String type) {
+		super();
+
+		if (type != null) {
+			if (type.equals(ANNOTATION)) {
+				this.type = ANNOTATION;
+			}
+			else if (type.equals(AUTHOR_TIME_VISUAL)) {
+				this.type = AUTHOR_TIME_VISUAL;
+			}
+			else {
+				this.type = type;
+			}
+		}
+	}
+
+	/**
+	 */
+	private String getData(IStructuredDocumentRegion flatNode) {
+		if (flatNode == null)
+			return null;
+		ITextRegionList regions = flatNode.getRegions();
+		if (regions == null)
+			return null;
+
+		String data = null;
+		Iterator e = regions.iterator();
+		while (e.hasNext()) {
+			ITextRegion region = (ITextRegion) e.next();
+			String regionType = region.getType();
+			if (isCommentText(regionType)) {
+				data = flatNode.getText(region);
+				break;
+			}
+		}
+		if (data == null)
+			return null;
+		int length = data.length();
+		int offset = 0;
+		for (; offset < length; offset++) {
+			char c = data.charAt(offset);
+			if (c == '\r' || c == '\n') {
+				offset++;
+				break;
+			}
+		}
+		for (; offset < length; offset++) {
+			char c = data.charAt(offset);
+			if (c != '\r' && c != '\n') {
+				break;
+			}
+		}
+		return data.substring(offset);
+	}
+
+	private boolean isCommentText(String regionType) {
+		boolean result = false;
+		result = isDOMComment(regionType) || isNestedContentComment(regionType);
+		return result;
+	}
+
+	/**
+	 * ISSUE: this is a bit of hidden JSP knowledge that was implemented this
+	 * way for expedency. Should be evolved in future to depend on
+	 * "nestedContext".
+	 */
+
+	private boolean isNestedContentComment(String regionType) {
+		final String JSP_COMMENT_TEXT = "JSP_COMMENT_TEXT"; //$NON-NLS-1$
+		return regionType.equals(JSP_COMMENT_TEXT);
+	}
+
+	private boolean isDOMComment(String regionType) {
+		return regionType == DOMRegionContext.XML_COMMENT_TEXT;
+	}
+
+	public String getData() {
+		if (this.element == null)
+			return null;
+		IStructuredDocumentRegion flatNode = this.element.getStartStructuredDocumentRegion();
+		if (flatNode == null)
+			return null;
+		if (this.data != null)
+			return this.data;
+		return getData(flatNode);
+	}
+
+	/**
+	 */
+	private String getDelimiter(IDOMModel model) {
+		String delim = null;
+		if (model != null) {
+			IStructuredDocument structuredDocument = model.getStructuredDocument();
+			if (structuredDocument != null)
+				delim = structuredDocument.getLineDelimiter();
+		}
+		if (delim == null)
+			delim = "\r\n";//$NON-NLS-1$
+		return delim;
+	}
+
+	/**
+	 */
+	public String getEndData() {
+		if (this.element == null)
+			return null;
+		IStructuredDocumentRegion flatNode = this.element.getEndStructuredDocumentRegion();
+		if (flatNode == null)
+			return null;
+		if (this.endData != null)
+			return this.endData;
+		return getData(flatNode);
+	}
+
+	/**
+	 */
+	public String getEndTag(IDOMElement element) {
+		StringBuffer buffer = new StringBuffer();
+		if (element.isJSPTag())
+			buffer.append("<%--");//$NON-NLS-1$
+		else
+			buffer.append("<!--");//$NON-NLS-1$
+		buffer.append(METADATA);
+		buffer.append(' ');
+		buffer.append(TYPE);
+		buffer.append("=\"");//$NON-NLS-1$
+		buffer.append(this.type);
+		buffer.append("\" ");//$NON-NLS-1$
+		buffer.append(MetaData.ENDSPAN);
+		String data = getEndData();
+		if (data != null && data.length() > 0) {
+			String delim = getDelimiter(element.getModel());
+			buffer.append(delim);
+			buffer.append(data);
+			buffer.append(delim);
+		}
+		if (element.isJSPTag())
+			buffer.append("--%>");//$NON-NLS-1$
+		else
+			buffer.append("-->");//$NON-NLS-1$
+
+		return buffer.toString();
+	}
+
+	/**
+	 */
+	public String getStartTag(IDOMElement element) {
+		StringBuffer buffer = new StringBuffer();
+		if (element.isJSPTag())
+			buffer.append("<%--");//$NON-NLS-1$
+		else
+			buffer.append("<!--");//$NON-NLS-1$
+		buffer.append(METADATA);
+		buffer.append(' ');
+		buffer.append(TYPE);
+		buffer.append("=\"");//$NON-NLS-1$
+		buffer.append(this.type);
+		buffer.append("\" ");//$NON-NLS-1$
+		buffer.append(MetaData.STARTSPAN);
+		String data = getData();
+		if (data != null && data.length() > 0) {
+			String delim = getDelimiter(element.getModel());
+			buffer.append(delim);
+			buffer.append(data);
+			buffer.append(delim);
+		}
+		if (element.isJSPTag())
+			buffer.append("--%>");//$NON-NLS-1$
+		else
+			buffer.append("-->");//$NON-NLS-1$
+
+		return buffer.toString();
+	}
+
+	/**
+	 */
+	public String getType() {
+		return this.type;
+	}
+
+	/**
+	 */
+	public boolean isAdapterForType(Object type) {
+		return (type == TagAdapter.class || type == MetaDataAdapter.class);
+	}
+
+	/**
+	 */
+	public boolean isEndTag() {
+		if (this.element == null)
+			return false;
+		if (this.element.hasStartTag())
+			return false;
+		if (this.element.hasEndTag())
+			return true;
+		if (this.data != null)
+			return false;
+		return (this.endData != null);
+	}
+
+	/**
+	 */
+	public boolean isRuntimeContainer() {
+		return (this.type == ANNOTATION || this.type == AUTHOR_TIME_VISUAL);
+	}
+
+	/**
+	 */
+	public void notifyChanged(INodeNotifier notifier, int eventType, Object changedFeature, Object oldValue, Object newValue, int pos) {
+	}
+
+	/**
+	 */
+	public void setData(String data) {
+		this.data = data;
+
+		if (this.element != null)
+			this.element.notifyStartTagChanged();
+	}
+
+	/**
+	 */
+	public void setEndData(String data) {
+		this.endData = data;
+
+		if (this.element != null)
+			this.element.notifyEndTagChanged();
+	}
+
+	/**
+	 */
+	public void setElement(IDOMElement element) {
+		this.element = element;
+
+		if (this.element != null) {
+			this.element.setCommentTag(true);
+			if (this.type != MetaData.ANNOTATION) {
+				this.element.setJSPTag(true);
+			}
+		}
+	}
+
+	/**
+	 */
+	public void setRuntimeSource(String source) {
+		if (source == null)
+			return;
+		if (this.element == null)
+			return;
+		if (isRuntimeContainer())
+			return;
+
+		IDOMModel model = this.element.getModel();
+		if (model == null)
+			return;
+		IStructuredDocument structuredDocument = model.getStructuredDocument();
+		if (structuredDocument == null)
+			return;
+		int offset = this.element.getStartEndOffset();
+		int end = this.element.getEndStartOffset();
+		int length = end - offset;
+		structuredDocument.replaceText(model, offset, length, source);
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/document/TagScanner.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/document/TagScanner.java
new file mode 100644
index 0000000..4cbd509
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/document/TagScanner.java
@@ -0,0 +1,166 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.document;
+
+
+
+/**
+ */
+class TagScanner {
+
+	private String tag = null;
+	private int offset = 0;
+	private int length = 0;
+	private boolean oneLine = false;
+
+	/**
+	 */
+	TagScanner(String tag, int offset) {
+		super();
+
+		this.tag = tag;
+		this.offset = offset;
+		if (tag != null)
+			this.length = tag.length();
+	}
+
+	/**
+	 */
+	TagScanner(String tag, int offset, boolean oneLine) {
+		this(tag, offset);
+
+		this.oneLine = oneLine;
+	}
+
+	/**
+	 */
+	int getNextOffset() {
+		for (; this.offset < this.length; this.offset++) {
+			char c = this.tag.charAt(this.offset);
+			if (!isEnd(c))
+				break;
+		}
+		return this.offset;
+	}
+
+	/**
+	 */
+	int getOffset() {
+		return this.offset;
+	}
+
+	/**
+	 */
+	private final boolean isEnd(char c) {
+		return (this.oneLine && (c == '\r' || c == '\n'));
+	}
+
+	/**
+	 */
+	private static boolean isEqual(char c) {
+		return (c == '=');
+	}
+
+	/**
+	 */
+	private static boolean isQuote(char c) {
+		return (c == '"' || c == '\'');
+	}
+
+	/**
+	 */
+	private static boolean isSpace(char c) {
+		return Character.isWhitespace(c);
+	}
+
+	/**
+	 */
+	private char nextChar() {
+		for (; this.offset < this.length; this.offset++) {
+			char c = this.tag.charAt(this.offset);
+			if (isEnd(c))
+				break;
+			if (!isSpace(c))
+				return c;
+		}
+		return 0;
+	}
+
+	/**
+	 */
+	String nextName() {
+		if (this.tag == null)
+			return null;
+		if (this.offset >= this.length)
+			return null;
+
+		if (nextChar() == 0)
+			return null;
+
+		int nameOffset = this.offset;
+		for (; this.offset < this.length; this.offset++) {
+			char c = this.tag.charAt(this.offset);
+			if (isEnd(c) || isSpace(c))
+				break;
+			if (isEqual(c) && this.offset > nameOffset)
+				break;
+		}
+		if (this.offset == nameOffset)
+			return null;
+
+		return this.tag.substring(nameOffset, this.offset);
+	}
+
+	/**
+	 */
+	String nextValue() {
+		if (this.tag == null)
+			return null;
+		if (this.offset >= this.length)
+			return null;
+
+		char seperator = nextChar();
+		if (!isEqual(seperator))
+			return null;
+		this.offset++; // skip '='
+		char quote = nextChar();
+		if (quote == 0)
+			return null;
+		if (isQuote(quote))
+			this.offset++;
+		else
+			quote = 0;
+
+		int valueOffset = this.offset;
+		for (; this.offset < this.length; this.offset++) {
+			char c = this.tag.charAt(this.offset);
+			if (isEnd(c)) {
+				quote = 0;
+				break;
+			}
+			if (quote == 0) {
+				if (isSpace(c))
+					break;
+			}
+			else {
+				if (c == quote)
+					break;
+			}
+		}
+		int valueEnd = this.offset;
+		if (quote != 0 && this.offset < this.length)
+			this.offset++;
+		if (valueEnd == valueOffset)
+			return null;
+
+		return this.tag.substring(valueOffset, valueEnd);
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/document/UnknownTagAdapter.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/document/UnknownTagAdapter.java
new file mode 100644
index 0000000..ec6053f
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/document/UnknownTagAdapter.java
@@ -0,0 +1,82 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.document;
+
+
+
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.xml.core.internal.document.TagAdapter;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
+
+/**
+ */
+public class UnknownTagAdapter implements TagAdapter {
+
+	private String startTag = null;
+	private String endTag = null;
+
+	/**
+	 */
+	public UnknownTagAdapter() {
+		super();
+	}
+
+	/**
+	 */
+	public String getEndTag(IDOMElement element) {
+		String tag = null;
+		if (this.endTag != null) {
+			tag = this.endTag;
+			this.endTag = null;
+		}
+		return tag;
+	}
+
+	/**
+	 */
+	public String getStartTag(IDOMElement element) {
+		String tag = null;
+		if (this.startTag != null) {
+			tag = this.startTag;
+			this.startTag = null;
+		}
+		return tag;
+	}
+
+	/**
+	 */
+	public boolean isAdapterForType(Object type) {
+		return (type == TagAdapter.class);
+	}
+
+	/**
+	 */
+	public boolean isEndTag() {
+		return false;
+	}
+
+	/**
+	 */
+	public void notifyChanged(INodeNotifier notifier, int eventType, Object changedFeature, Object oldValue, Object newValue, int pos) {
+	}
+
+	/**
+	 */
+	public void setEndTag(String endTag) {
+		this.endTag = endTag;
+	}
+
+	/**
+	 */
+	public void setStartTag(String startTag) {
+		this.startTag = startTag;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/encoding/HTMLDocumentCharsetDetector.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/encoding/HTMLDocumentCharsetDetector.java
new file mode 100644
index 0000000..40d3692
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/encoding/HTMLDocumentCharsetDetector.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.encoding;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.wst.html.core.internal.contenttype.HTMLResourceEncodingDetector;
+import org.eclipse.wst.sse.core.internal.document.DocumentReader;
+import org.eclipse.wst.sse.core.internal.document.IDocumentCharsetDetector;
+
+/**
+ * This class parses beginning portion of HTML file to get the encoding value
+ * in a META tag. Example:
+ * <META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+ * 
+ * Note: even though, technically, a META tag must come in a <HEAD>tag, we
+ * don't check for that, under the assumption that whatever, or whereever, the
+ * the first <META>tag is, it is the one intended to be used by the user, and
+ * they may just be trying to repair the error. The HTML validator will tell
+ * them if its in the wrong location.
+ *  
+ */
+public class HTMLDocumentCharsetDetector extends HTMLResourceEncodingDetector implements IDocumentCharsetDetector {
+
+
+	public HTMLDocumentCharsetDetector() {
+		super();
+	}
+
+	public void set(IDocument document) {
+		set(new DocumentReader(document, 0));
+
+
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/encoding/HTMLDocumentLoader.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/encoding/HTMLDocumentLoader.java
new file mode 100644
index 0000000..8027e3c
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/encoding/HTMLDocumentLoader.java
@@ -0,0 +1,165 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.encoding;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.jface.text.IDocumentPartitioner;
+import org.eclipse.wst.html.core.internal.contenttype.EncodingGuesser;
+import org.eclipse.wst.html.core.internal.document.HTMLDocumentTypeAdapterFactory;
+import org.eclipse.wst.html.core.internal.document.HTMLModelParserAdapterFactory;
+import org.eclipse.wst.html.core.internal.htmlcss.HTMLStyleSelectorAdapterFactory;
+import org.eclipse.wst.html.core.internal.htmlcss.StyleAdapterFactory;
+import org.eclipse.wst.html.core.internal.modelquery.ModelQueryAdapterFactoryForHTML;
+import org.eclipse.wst.html.core.internal.provisional.contenttype.ContentTypeIdForHTML;
+import org.eclipse.wst.html.core.internal.text.StructuredTextPartitionerForHTML;
+import org.eclipse.wst.sse.core.internal.PropagatingAdapter;
+import org.eclipse.wst.sse.core.internal.document.AbstractDocumentLoader;
+import org.eclipse.wst.sse.core.internal.document.IDocumentCharsetDetector;
+import org.eclipse.wst.sse.core.internal.document.IDocumentLoader;
+import org.eclipse.wst.sse.core.internal.document.StructuredDocumentFactory;
+import org.eclipse.wst.sse.core.internal.encoding.ContentTypeEncodingPreferences;
+import org.eclipse.wst.sse.core.internal.ltk.parser.BlockMarker;
+import org.eclipse.wst.sse.core.internal.ltk.parser.RegionParser;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapterFactory;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.provisional.document.IEncodedDocument;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+import org.eclipse.wst.sse.core.internal.text.BasicStructuredDocument;
+import org.eclipse.wst.xml.core.internal.parser.XMLSourceParser;
+import org.eclipse.wst.xml.core.internal.parser.XMLStructuredDocumentReParser;
+import org.eclipse.wst.xml.core.internal.propagate.PropagatingAdapterFactoryImpl;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+
+public class HTMLDocumentLoader extends AbstractDocumentLoader {
+
+	public HTMLDocumentLoader() {
+		super();
+	}
+
+	/**
+	 * Convenience method to add tag names using BlockMarker object
+	 */
+	protected void addHTMLishTag(XMLSourceParser parser, String tagname) {
+		BlockMarker bm = new BlockMarker(tagname, null, DOMRegionContext.BLOCK_TEXT, false);
+		parser.addBlockMarker(bm);
+	}
+
+	/**
+	 * Default encoding. For HTML, there is no spec.
+	 */
+	protected String getSpecDefaultEncoding() {
+		return null;
+	}
+
+	/**
+	 * @return java.lang.String
+	 * @param string
+	 *            byte[]
+	 * @param length
+	 *            int
+	 * 
+	 * Do automatic encoding detection by guess
+	 */
+	protected String getEncodingNameByGuess(byte[] string, int length) {
+		final String ianaEnc = EncodingGuesser.guessEncoding(string, length);
+		return ianaEnc;
+	}
+
+	/*
+	 * @see AbstractLoader#createNewStructuredDocument()
+	 */
+	protected IEncodedDocument newEncodedDocument() {
+		IStructuredDocument structuredDocument = StructuredDocumentFactory.getNewStructuredDocumentInstance(getParser());
+		((BasicStructuredDocument) structuredDocument).setReParser(new XMLStructuredDocumentReParser());
+
+		return structuredDocument;
+	}
+
+	/*
+	 * @see IModelLoader#getParser()
+	 */
+	public RegionParser getParser() {
+		XMLSourceParser parser = new XMLSourceParser();
+		// for the "static HTML" case, we need to initialize
+		// Blocktags here.
+		addHTMLishTag(parser, "script"); //$NON-NLS-1$
+		addHTMLishTag(parser, "style"); //$NON-NLS-1$
+		return parser;
+	}
+
+	/**
+	 * This method must return those factories which must be attached to the
+	 * structuredModel before content is applied.
+	 */
+	public List getAdapterFactories() {
+		List result = new ArrayList();
+		INodeAdapterFactory factory = null;
+		factory = StyleAdapterFactory.getInstance();
+		result.add(factory);
+		factory = HTMLStyleSelectorAdapterFactory.getInstance();
+		result.add(factory);
+		factory = new HTMLDocumentTypeAdapterFactory();
+		result.add(factory);
+		factory = HTMLModelParserAdapterFactory.getInstance();
+		result.add(factory);
+		//
+		factory = new ModelQueryAdapterFactoryForHTML();
+		result.add(factory);
+
+		factory = new PropagatingAdapterFactoryImpl();
+		result.add(factory);
+
+
+		return result;
+	}
+
+	protected String getPreferredNewLineDelimiter(IFile file) {
+		String delimiter = ContentTypeEncodingPreferences.getPreferredNewLineDelimiter(ContentTypeIdForHTML.ContentTypeID_HTML);
+		if (delimiter == null)
+			delimiter = super.getPreferredNewLineDelimiter(file);
+		return delimiter;
+	}
+
+	public IDocumentCharsetDetector getDocumentEncodingDetector() {
+		if (fDocumentEncodingDetector == null) {
+			fDocumentEncodingDetector = new HTMLDocumentCharsetDetector();
+		}
+		return fDocumentEncodingDetector;
+	}
+
+	protected void preLoadAdapt(IStructuredModel structuredModel) {
+		// DMW: just added this preload on 8/16/2002
+		// I noticed the ProagatingAdapterFactory was being added,
+		// that that the ProagatingAdapterAdapter was not being
+		// preload adapted -- I'm assuing it ALWAYS has to be.
+		IDOMModel domModel = (IDOMModel) structuredModel;
+		// if there is a model in the adapter, this will adapt it to
+		// first node. After that the PropagatingAdater spreads over the
+		// children being
+		// created. Each time that happends, a side effect is to
+		// also "spread" sprecific registered adapters,
+		// they two can propigate is needed.
+		((INodeNotifier) domModel.getDocument()).getAdapterFor(PropagatingAdapter.class);
+	}
+
+	public IDocumentPartitioner getDefaultDocumentPartitioner() {
+		return new StructuredTextPartitionerForHTML();
+	}
+
+	public IDocumentLoader newInstance() {
+		return new HTMLDocumentLoader();
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/encoding/HTMLModelLoader.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/encoding/HTMLModelLoader.java
new file mode 100644
index 0000000..398b154
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/encoding/HTMLModelLoader.java
@@ -0,0 +1,112 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.encoding;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.wst.html.core.internal.document.DOMStyleModelImpl;
+import org.eclipse.wst.html.core.internal.document.HTMLDocumentTypeAdapterFactory;
+import org.eclipse.wst.html.core.internal.document.HTMLModelParserAdapterFactory;
+import org.eclipse.wst.html.core.internal.htmlcss.HTMLStyleSelectorAdapterFactory;
+import org.eclipse.wst.html.core.internal.htmlcss.StyleAdapterFactory;
+import org.eclipse.wst.html.core.internal.modelquery.ModelQueryAdapterFactoryForHTML;
+import org.eclipse.wst.sse.core.internal.PropagatingAdapter;
+import org.eclipse.wst.sse.core.internal.document.IDocumentLoader;
+import org.eclipse.wst.sse.core.internal.ltk.parser.BlockMarker;
+import org.eclipse.wst.sse.core.internal.model.AbstractModelLoader;
+import org.eclipse.wst.sse.core.internal.provisional.IModelLoader;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapterFactory;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.util.Debug;
+import org.eclipse.wst.xml.core.internal.DebugAdapterFactory;
+import org.eclipse.wst.xml.core.internal.parser.XMLSourceParser;
+import org.eclipse.wst.xml.core.internal.propagate.PropagatingAdapterFactoryImpl;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+
+public class HTMLModelLoader extends AbstractModelLoader {
+
+
+	public HTMLModelLoader() {
+		super();
+	}
+
+	/**
+	 * Convenience method to add tag names using BlockMarker object
+	 */
+	protected void addHTMLishTag(XMLSourceParser parser, String tagname) {
+		BlockMarker bm = new BlockMarker(tagname, null, DOMRegionContext.BLOCK_TEXT, false);
+		parser.addBlockMarker(bm);
+	}
+
+	public IStructuredModel newModel() {
+		DOMStyleModelImpl model = new DOMStyleModelImpl();
+		return model;
+	}
+
+	/**
+	 * This method must return those factories which must be attached to the
+	 * structuredModel before content is applied.
+	 */
+	public List getAdapterFactories() {
+		List result = new ArrayList();
+		INodeAdapterFactory factory = null;
+		factory = StyleAdapterFactory.getInstance();
+		result.add(factory);
+		factory = HTMLStyleSelectorAdapterFactory.getInstance();
+		result.add(factory);
+		factory = new HTMLDocumentTypeAdapterFactory();
+		result.add(factory);
+		factory = HTMLModelParserAdapterFactory.getInstance();
+		result.add(factory);
+		//
+		factory = new ModelQueryAdapterFactoryForHTML();
+		result.add(factory);
+
+		factory = new PropagatingAdapterFactoryImpl();
+		result.add(factory);
+		
+
+		return result;
+	}
+
+	protected void preLoadAdapt(IStructuredModel structuredModel) {
+		super.preLoadAdapt(structuredModel);
+		// DMW: just added this preload on 8/16/2002
+		// I noticed the ProagatingAdapterFactory was being added,
+		// that that the ProagatingAdapterAdapter was not being
+		// preload adapted -- I'm assuing it ALWAYS has to be.
+		IDOMModel domModel = (IDOMModel) structuredModel;
+		// if there is a model in the adapter, this will adapt it to
+		// first node. After that the PropagatingAdater spreads over the
+		// children being
+		// created. Each time that happends, a side effect is to
+		// also "spread" sprecific registered adapters,
+		// they two can propigate is needed.
+		((INodeNotifier) domModel.getDocument()).getAdapterFor(PropagatingAdapter.class);
+		if (Debug.debugNotificationAndEvents) {
+			PropagatingAdapter propagatingAdapter = (PropagatingAdapter) ((INodeNotifier) domModel.getDocument()).getAdapterFor(PropagatingAdapter.class);
+			propagatingAdapter.addAdaptOnCreateFactory(new DebugAdapterFactory());
+		}	}
+
+	public IModelLoader newInstance() {
+		return new HTMLModelLoader();
+	}
+
+	public IDocumentLoader getDocumentLoader() {
+		if (documentLoaderInstance == null) {
+			documentLoaderInstance = new HTMLDocumentLoader();
+		}
+		return documentLoaderInstance;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/format/EmbeddedCSSFormatter.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/format/EmbeddedCSSFormatter.java
new file mode 100644
index 0000000..74ec679
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/format/EmbeddedCSSFormatter.java
@@ -0,0 +1,94 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.format;
+
+
+
+import org.eclipse.wst.css.core.internal.formatter.CSSSourceFormatter;
+import org.eclipse.wst.css.core.internal.formatter.CSSSourceFormatterFactory;
+import org.eclipse.wst.css.core.internal.provisional.adapters.IStyleSheetAdapter;
+import org.eclipse.wst.css.core.internal.provisional.document.ICSSModel;
+import org.eclipse.wst.css.core.internal.provisional.document.ICSSNode;
+import org.eclipse.wst.html.core.internal.provisional.HTMLFormatContraints;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapter;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMText;
+
+// nakamori_TODO: check and remove
+
+public class EmbeddedCSSFormatter extends HTMLFormatter {
+
+	// private IAdapterFactory factory = new
+	// CSSSourceFormatterFactory(CSSSourceFormatter.class, true);
+	/**
+	 */
+	protected EmbeddedCSSFormatter() {
+		super();
+	}
+
+	/**
+	 */
+	protected void formatNode(IDOMNode node, HTMLFormatContraints contraints) {
+		if (node == null)
+			return;
+		IDOMText text = (IDOMText) node;
+
+		String source = getCSSContent(node);
+		if (source == null) { // fallback
+			source = text.getSource();
+		}
+
+		int offset = text.getStartOffset();
+		int length = text.getEndOffset() - offset;
+		replaceSource(text.getModel(), offset, length, source);
+		setWidth(contraints, source);
+	}
+
+	/**
+	 */
+	private String getCSSContent(IDOMNode text) {
+		ICSSModel model = getCSSModel(text);
+		if (model == null)
+			return null;
+		ICSSNode document = model.getDocument();
+		if (document == null)
+			return null;
+		INodeNotifier notifier = (INodeNotifier) document;
+		CSSSourceFormatter formatter = (CSSSourceFormatter) notifier.getAdapterFor(CSSSourceFormatter.class);
+		// try another way to get formatter
+		if (formatter == null)
+			formatter = CSSSourceFormatterFactory.getInstance().getSourceFormatter(notifier);
+		if (formatter == null)
+			return null;
+		StringBuffer buffer = formatter.format(document);
+		if (buffer == null)
+			return null;
+		return buffer.toString();
+	}
+
+	/**
+	 */
+	private ICSSModel getCSSModel(IDOMNode text) {
+		if (text == null)
+			return null;
+		INodeNotifier notifier = (INodeNotifier) text.getParentNode();
+		if (notifier == null)
+			return null;
+		INodeAdapter adapter = notifier.getAdapterFor(IStyleSheetAdapter.class);
+		if (adapter == null)
+			return null;
+		if (!(adapter instanceof IStyleSheetAdapter))
+			return null;
+		IStyleSheetAdapter styleAdapter = (IStyleSheetAdapter) adapter;
+		return styleAdapter.getModel();
+	}
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/format/HTMLElementFormatter.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/format/HTMLElementFormatter.java
new file mode 100644
index 0000000..ce14df4
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/format/HTMLElementFormatter.java
@@ -0,0 +1,394 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.format;
+
+import java.util.Iterator;
+
+import org.eclipse.wst.css.core.internal.formatter.CSSSourceFormatter;
+import org.eclipse.wst.css.core.internal.formatter.CSSSourceFormatterFactory;
+import org.eclipse.wst.css.core.internal.provisional.adapters.IStyleDeclarationAdapter;
+import org.eclipse.wst.css.core.internal.provisional.document.ICSSModel;
+import org.eclipse.wst.css.core.internal.provisional.document.ICSSNode;
+import org.eclipse.wst.html.core.internal.provisional.HTMLFormatContraints;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapter;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+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.ITextRegionContainer;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.eclipse.wst.xml.core.internal.provisional.format.StructuredFormatPreferencesXML;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+import org.w3c.dom.Attr;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+// nakamori_TODO: check and remove CSS formatting
+
+public class HTMLElementFormatter extends HTMLFormatter {
+
+	/**
+	 */
+	protected HTMLElementFormatter() {
+		super();
+	}
+
+	/**
+	 */
+	private void compressTailingSpaces(IStructuredDocumentRegion flatNode, ITextRegion region) {
+		int offset = region.getTextEnd();
+		int count = region.getEnd() - offset;
+		if (count == 1) {
+			String source = flatNode.getFullText(region);
+			int start = region.getStart();
+			if (source != null && source.charAt(offset - start) == ' ') {
+				// nothing to do
+				return;
+			}
+		}
+		replaceSource(flatNode, offset, count, " ");//$NON-NLS-1$
+	}
+
+	/**
+	 */
+	private void formatEndTag(IDOMElement element, HTMLFormatContraints contraints) {
+		Node lastChild = element.getLastChild();
+
+		if (lastChild != null && lastChild instanceof IDOMElement && lastChild.getNodeName().equals("jsp:scriptlet")) { //$NON-NLS-1$
+			insertBreakAfter((IDOMElement) lastChild, contraints);
+			return;
+		}
+
+
+		IStructuredDocumentRegion endStructuredDocumentRegion = element.getEndStructuredDocumentRegion();
+		if (endStructuredDocumentRegion == null)
+			return;
+
+		if (element.isJSPTag() || element.isCommentTag()) {
+			String endTag = endStructuredDocumentRegion.getText();
+			if (endTag != null && endTag.length() > 0) {
+				setWidth(contraints, endTag);
+			}
+			return;
+		}
+
+		ITextRegion prevRegion = null;
+		ITextRegionList regions = endStructuredDocumentRegion.getRegions();
+		Iterator e = regions.iterator();
+		while (e.hasNext()) {
+			ITextRegion region = (ITextRegion) e.next();
+			if (region == null)
+				continue;
+			String regionType = region.getType();
+			if (regionType == DOMRegionContext.XML_TAG_NAME || isNestedTag(regionType)) {
+				if (prevRegion != null && prevRegion.getType() == DOMRegionContext.XML_END_TAG_OPEN) {
+					removeTailingSpaces(endStructuredDocumentRegion, prevRegion);
+				}
+			}
+			else if (regionType == DOMRegionContext.XML_TAG_CLOSE) {
+				if (prevRegion != null && (prevRegion.getType() == DOMRegionContext.XML_TAG_NAME || isNestedRootTag(prevRegion.getType()))) {
+					removeTailingSpaces(endStructuredDocumentRegion, prevRegion);
+				}
+			}
+			prevRegion = region;
+		}
+		if (prevRegion != null && (prevRegion.getType() == DOMRegionContext.XML_TAG_NAME || isNestedRootTag(prevRegion.getType()))) {
+			removeTailingSpaces(endStructuredDocumentRegion, prevRegion);
+		}
+
+		// BUG123890 (end tag length was already prefactored into
+		// formatStartTag so no need to do it here)
+		// String newEndTag = endStructuredDocumentRegion.getText();
+		// if (newEndTag != null && newEndTag.length() > 0) {
+		// setWidth(contraints, newEndTag);
+		// }
+	}
+
+	/**
+	 */
+	protected void formatNode(IDOMNode node, HTMLFormatContraints contraints) {
+		if (node == null)
+			return;
+		IDOMElement element = (IDOMElement) node;
+
+		formatStartTag(element, contraints);
+
+		formatChildNodes(element, contraints);
+
+		formatEndTag(element, contraints);
+	}
+
+	/**
+	 */
+	private void formatStartTag(IDOMElement element, HTMLFormatContraints contraints) {
+
+		if (element.getNodeName().equals("jsp:scriptlet")) { //$NON-NLS-1$
+			insertBreakBefore(element, contraints);
+			return;
+		}
+
+		IStructuredDocumentRegion startStructuredDocumentRegion = element.getStartStructuredDocumentRegion();
+		if (startStructuredDocumentRegion == null)
+			return;
+
+		// We should format attributes in JSPTag?
+		// if (element.isJSPTag() || element.isCommentTag()) {
+		if (element.isCommentTag()) {
+			String startTag = startStructuredDocumentRegion.getText();
+			if (startTag != null && startTag.length() > 0) {
+				setWidth(contraints, startTag);
+			}
+			return;
+		}
+
+		// first process style attribute
+		if (element.isGlobalTag()) {
+			Attr attr = element.getAttributeNode("style");//$NON-NLS-1$
+			if (attr != null)
+				formatStyleAttr(attr);
+		}
+		boolean insertBreak = false;
+		insertBreak = ((StructuredFormatPreferencesXML) getFormatPreferences()).getSplitMultiAttrs();
+		boolean alignEndBracket = ((StructuredFormatPreferencesXML) getFormatPreferences()).isAlignEndBracket();
+		boolean attributesSplitted = false;
+
+		if (insertBreak) {
+			NamedNodeMap attributes = element.getAttributes();
+			if (attributes == null || attributes.getLength() < 2)
+				insertBreak = false;
+		}
+		String breakSpaces = getBreakSpaces(element);
+		String originalBreakSpaces = breakSpaces;
+		String indent = getIndent();
+		if (indent != null && indent.length() > 0) {
+			breakSpaces += indent;
+		}
+		ITextRegion lastBreakRegion = null;
+
+		ITextRegion prevRegion = null;
+		ITextRegionList regions = startStructuredDocumentRegion.getRegions();
+		Iterator e = regions.iterator();
+		while (e.hasNext()) {
+			ITextRegion region = (ITextRegion) e.next();
+			if (region == null)
+				continue;
+
+			ITextRegion breakRegion = null;
+
+			String regionType = region.getType();
+			if (regionType == DOMRegionContext.XML_TAG_NAME || isNestedTag(regionType)) {
+				if (prevRegion != null && prevRegion.getType() == DOMRegionContext.XML_TAG_OPEN) {
+					removeTailingSpaces(startStructuredDocumentRegion, prevRegion);
+				}
+				breakRegion = region;
+			}
+			else if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) {
+				if (prevRegion != null && (prevRegion.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME || prevRegion.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_EQUALS)) {
+					// attribute name without value
+					breakRegion = prevRegion;
+				}
+			}
+			else if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_EQUALS) {
+				if (prevRegion != null && prevRegion.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) {
+					removeTailingSpaces(startStructuredDocumentRegion, prevRegion);
+				}
+			}
+			else if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
+				if (prevRegion != null && prevRegion.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_EQUALS) {
+					removeTailingSpaces(startStructuredDocumentRegion, prevRegion);
+				}
+				breakRegion = region;
+			}
+			else if (regionType == DOMRegionContext.XML_TAG_CLOSE || regionType == DOMRegionContext.XML_EMPTY_TAG_CLOSE) {
+				if (prevRegion != null && (prevRegion.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME || prevRegion.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_EQUALS)) {
+					// attribute name without value
+					breakRegion = prevRegion;
+				}
+			}
+
+			if (breakRegion != null) {
+				int end = breakRegion.getTextEnd();
+				if (lastBreakRegion != null) {
+					int offset = lastBreakRegion.getEnd();
+					int count = end - offset;
+					if (insertBreak || !isWidthAvailable(contraints, count + 1)) {
+						replaceTailingSpaces(startStructuredDocumentRegion, lastBreakRegion, breakSpaces);
+						setWidth(contraints, breakSpaces);
+						attributesSplitted = true;
+					}
+					else {
+						compressTailingSpaces(startStructuredDocumentRegion, lastBreakRegion);
+						addWidth(contraints, 1);
+					}
+					addWidth(contraints, count);
+				}
+				else {
+					addWidth(contraints, end);
+				}
+				lastBreakRegion = breakRegion;
+			}
+
+			prevRegion = region;
+		}
+		if (prevRegion != null && (prevRegion.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME || prevRegion.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_EQUALS)) {
+			// attribute name without value
+			int end = prevRegion.getTextEnd();
+			if (lastBreakRegion != null) {
+				int offset = lastBreakRegion.getEnd();
+				int count = end - offset;
+				if (insertBreak || !isWidthAvailable(contraints, count + 1)) {
+					replaceTailingSpaces(startStructuredDocumentRegion, lastBreakRegion, breakSpaces);
+					setWidth(contraints, breakSpaces);
+					attributesSplitted = true;
+				}
+				else {
+					compressTailingSpaces(startStructuredDocumentRegion, lastBreakRegion);
+					addWidth(contraints, 1);
+				}
+				addWidth(contraints, count);
+			}
+			else {
+				addWidth(contraints, end);
+			}
+			lastBreakRegion = prevRegion;
+		}
+
+		if (lastBreakRegion != null) {
+			int offset = lastBreakRegion.getTextEnd();
+			int count = startStructuredDocumentRegion.getLength() - offset;
+			if (prevRegion != null && prevRegion.getType() == DOMRegionContext.XML_EMPTY_TAG_CLOSE) {
+				compressTailingSpaces(startStructuredDocumentRegion, lastBreakRegion);
+				count++;
+			}
+			else {
+				removeTailingSpaces(startStructuredDocumentRegion, lastBreakRegion);
+				// BUG123890 (pre-factor in end tag)
+				count += element.getTagName().length() + 3;
+			}
+			addWidth(contraints, count);
+		}
+		else {
+			addWidth(contraints, startStructuredDocumentRegion.getLength());
+		}
+		// BUG113584 - align last bracket
+		if (alignEndBracket && attributesSplitted) {
+			removeTailingSpaces(startStructuredDocumentRegion, lastBreakRegion);
+			replaceTailingSpaces(startStructuredDocumentRegion, lastBreakRegion, originalBreakSpaces);
+			contraints.setAvailableLineWidth(getLineWidth() - originalBreakSpaces.length() - 1);
+		}
+	}
+
+	/**
+	 * ISSUE: this is a bit of hidden JSP knowledge that was implemented this
+	 * way for expedency. Should be evolved in future to depend on
+	 * "nestedContext".
+	 */
+	private boolean isNestedTag(String regionType) {
+		final String JSP_ROOT_TAG_NAME = "JSP_ROOT_TAG_NAME"; //$NON-NLS-1$
+		final String JSP_DIRECTIVE_NAME = "JSP_DIRECTIVE_NAME"; //$NON-NLS-1$
+		boolean result = regionType.equals(JSP_ROOT_TAG_NAME) || regionType.equals(JSP_DIRECTIVE_NAME);
+		return result;
+	}
+
+	/**
+	 * ISSUE: this is a bit of hidden JSP knowledge that was implemented this
+	 * way for expedency. Should be evolved in future to depend on
+	 * "nestedContext".
+	 */
+	private boolean isNestedRootTag(String regionType) {
+		final String JSP_ROOT_TAG_NAME = "JSP_ROOT_TAG_NAME"; //$NON-NLS-1$
+		boolean result = regionType.equals(JSP_ROOT_TAG_NAME);
+		return result;
+	}
+
+
+	/**
+	 */
+	private void formatStyleAttr(Attr attr) {
+		if (attr == null)
+			return;
+		// if someone's made it a container somehow, CSS can't format it
+		if (((IDOMNode) attr).getValueRegion() instanceof ITextRegionContainer)
+			return;
+		String value = getCSSValue(attr);
+		if (value == null)
+			return;
+		String oldValue = ((IDOMNode) attr).getValueSource();
+		if (oldValue != null && value.equals(oldValue))
+			return;
+		attr.setValue(value);
+	}
+
+	/**
+	 */
+	private ICSSModel getCSSModel(Attr attr) {
+		if (attr == null)
+			return null;
+		INodeNotifier notifier = (INodeNotifier) attr.getOwnerElement();
+		if (notifier == null)
+			return null;
+		INodeAdapter adapter = notifier.getAdapterFor(IStyleDeclarationAdapter.class);
+		if (adapter == null)
+			return null;
+		if (!(adapter instanceof IStyleDeclarationAdapter))
+			return null;
+		IStyleDeclarationAdapter styleAdapter = (IStyleDeclarationAdapter) adapter;
+		return styleAdapter.getModel();
+	}
+
+	/**
+	 */
+	private String getCSSValue(Attr attr) {
+		ICSSModel model = getCSSModel(attr);
+		if (model == null)
+			return null;
+		ICSSNode document = model.getDocument();
+		if (document == null)
+			return null;
+		INodeNotifier notifier = (INodeNotifier) document;
+		CSSSourceFormatter formatter = (CSSSourceFormatter) notifier.getAdapterFor(CSSSourceFormatter.class);
+		// try another way to get formatter
+		if (formatter == null)
+			formatter = CSSSourceFormatterFactory.getInstance().getSourceFormatter(notifier);
+		if (formatter == null)
+			return null;
+		StringBuffer buffer = formatter.format(document);
+		if (buffer == null)
+			return null;
+		return buffer.toString();
+	}
+
+	/**
+	 */
+	private void removeTailingSpaces(IStructuredDocumentRegion flatNode, ITextRegion region) {
+		int offset = region.getTextEnd();
+		int count = region.getEnd() - offset;
+		if (count <= 0)
+			return;
+		replaceSource(flatNode, offset, count, null);
+	}
+
+	/**
+	 */
+	private void replaceTailingSpaces(IStructuredDocumentRegion flatNode, ITextRegion region, String spaces) {
+		int offset = region.getTextEnd();
+		int count = region.getEnd() - offset;
+		if (count == spaces.length()) {
+			String source = flatNode.getFullText(region);
+			if (source != null && source.endsWith(spaces)) {
+				// nothing to do
+				return;
+			}
+		}
+		replaceSource(flatNode, offset, count, spaces);
+	}
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/format/HTMLFormatContraintsImpl.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/format/HTMLFormatContraintsImpl.java
new file mode 100644
index 0000000..bf81533
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/format/HTMLFormatContraintsImpl.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.format;
+
+import org.eclipse.wst.html.core.internal.provisional.HTMLFormatContraints;
+import org.eclipse.wst.sse.core.internal.format.StructuredFormatContraints;
+
+/**
+ * @deprecated
+ * Please un-deprecate this if Page Designer thinks they are needed.
+ */
+public class HTMLFormatContraintsImpl extends StructuredFormatContraints implements HTMLFormatContraints {
+	protected int fAvailableLineWidth;
+
+	/**
+	 * @deprecated
+	 * 	It's very hard to keep the available line width accurate.
+	 * 	Sometimes a node wants to start on a new line, sometimes it doesn't.
+	 * 	It's best for the node to figure out the available line width on the fly.
+	 */
+	public int getAvailableLineWidth() {
+		return fAvailableLineWidth;
+	}
+
+	/**
+	 * @deprecated
+	 * 	It's very hard to keep the available line width accurate.
+	 * 	Sometimes a node wants to start on a new line, sometimes it doesn't.
+	 * 	It's best for the node to figure out the available line width on the fly.
+	 */
+	public void setAvailableLineWidth(int availableLineWidth) {
+		fAvailableLineWidth = availableLineWidth;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/format/HTMLFormatProcessorImpl.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/format/HTMLFormatProcessorImpl.java
new file mode 100644
index 0000000..0552bc2
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/format/HTMLFormatProcessorImpl.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.format;
+
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.wst.html.core.internal.HTMLCorePlugin;
+import org.eclipse.wst.html.core.internal.preferences.HTMLCorePreferenceNames;
+import org.eclipse.wst.sse.core.internal.format.IStructuredFormatPreferences;
+import org.eclipse.wst.sse.core.internal.format.IStructuredFormatter;
+import org.eclipse.wst.xml.core.internal.provisional.format.FormatProcessorXML;
+import org.eclipse.wst.xml.core.internal.provisional.format.StructuredFormatPreferencesXML;
+import org.w3c.dom.Node;
+
+public class HTMLFormatProcessorImpl extends FormatProcessorXML {
+	protected String getFileExtension() {
+		return "html"; //$NON-NLS-1$
+	}
+
+	protected IStructuredFormatter getFormatter(Node node) {
+		IStructuredFormatter formatter = HTMLFormatterFactory.getInstance().createFormatter(node, getFormatPreferences());
+
+		return formatter;
+	}
+
+	public IStructuredFormatPreferences getFormatPreferences() {
+		if (fFormatPreferences == null) {
+			fFormatPreferences = new StructuredFormatPreferencesXML();
+
+			Preferences preferences = HTMLCorePlugin.getDefault().getPluginPreferences();
+			if (preferences != null) {
+				fFormatPreferences.setLineWidth(preferences.getInt(HTMLCorePreferenceNames.LINE_WIDTH));
+				((StructuredFormatPreferencesXML) fFormatPreferences).setSplitMultiAttrs(preferences.getBoolean(HTMLCorePreferenceNames.SPLIT_MULTI_ATTRS));
+				((StructuredFormatPreferencesXML) fFormatPreferences).setAlignEndBracket(preferences.getBoolean(HTMLCorePreferenceNames.ALIGN_END_BRACKET));
+				fFormatPreferences.setClearAllBlankLines(preferences.getBoolean(HTMLCorePreferenceNames.CLEAR_ALL_BLANK_LINES));
+
+				char indentChar = ' ';
+				String indentCharPref = preferences.getString(HTMLCorePreferenceNames.INDENTATION_CHAR);
+				if (HTMLCorePreferenceNames.TAB.equals(indentCharPref)) {
+					indentChar = '\t';
+				}
+				int indentationWidth = preferences.getInt(HTMLCorePreferenceNames.INDENTATION_SIZE);
+
+				StringBuffer indent = new StringBuffer();
+				for (int i = 0; i < indentationWidth; i++) {
+					indent.append(indentChar);
+				}
+				fFormatPreferences.setIndent(indent.toString());
+			}
+		}
+
+		return fFormatPreferences;
+	}
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/format/HTMLFormatter.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/format/HTMLFormatter.java
new file mode 100644
index 0000000..07fb206
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/format/HTMLFormatter.java
@@ -0,0 +1,826 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2011 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
+ *     Genuitec - fix for bug #203252
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.format;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.wst.html.core.internal.HTMLCorePlugin;
+import org.eclipse.wst.html.core.internal.preferences.HTMLCorePreferenceNames;
+import org.eclipse.wst.html.core.internal.provisional.HTMLCMProperties;
+import org.eclipse.wst.html.core.internal.provisional.HTMLFormatContraints;
+import org.eclipse.wst.sse.core.internal.format.IStructuredFormatContraints;
+import org.eclipse.wst.sse.core.internal.format.IStructuredFormatPreferences;
+import org.eclipse.wst.sse.core.internal.format.IStructuredFormatter;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.modelquery.ModelQueryUtil;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
+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.provisional.format.StructuredFormatPreferencesXML;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.Text;
+
+public class HTMLFormatter implements IStructuredFormatter {
+
+	private static final String HTML_NAME = "html";//$NON-NLS-1$
+	private static final String HEAD_NAME = "head"; //$NON-NLS-1$
+	private static final String BODY_NAME = "BODY";//$NON-NLS-1$
+	// hidden jsp logic that should be removed when jsp formatter is created
+	private static final String JSP = "jsp";//$NON-NLS-1$
+
+	private HTMLFormattingUtil formattingUtil;
+
+	public HTMLFormatter() {
+		formattingUtil = new HTMLFormattingUtil();
+	}
+
+	/**
+	 */
+	protected void addWidth(HTMLFormatContraints contraints, int width) {
+		if (contraints == null)
+			return;
+		if (!splitLines() || getLineWidth() < 0)
+			return;
+
+		int availableWidth = contraints.getAvailableLineWidth() - width;
+		if (availableWidth < 0)
+			availableWidth = 0;
+		contraints.setAvailableLineWidth(availableWidth);
+	}
+
+	/**
+	 */
+	protected boolean canFormatChild(Node node) {
+		while (node != null) {
+			if (node.getNodeType() != Node.ELEMENT_NODE)
+				return true;
+			CMElementDeclaration decl = getElementDeclaration((Element) node);
+			if (decl != null) {
+				if (decl.getContentType() == CMElementDeclaration.CDATA)
+					return false;
+				if (decl.supports(HTMLCMProperties.SHOULD_KEEP_SPACE)) {
+					boolean shouldKeepSpace = ((Boolean) decl.getProperty(HTMLCMProperties.SHOULD_KEEP_SPACE)).booleanValue();
+					if (shouldKeepSpace)
+						return false;
+				}
+			}
+			node = node.getParentNode();
+		}
+		return false;
+	}
+
+	/**
+	 */
+	protected boolean canInsertBreakAfter(CMElementDeclaration decl) {
+		if (decl == null)
+			return false;
+		if (!decl.supports(HTMLCMProperties.LINE_BREAK_HINT))
+			return false;
+		String hint = (String) decl.getProperty(HTMLCMProperties.LINE_BREAK_HINT);
+		if (hint == null)
+			return false;
+		return (hint.equals(HTMLCMProperties.Values.BREAK_BEFORE_START_AND_AFTER_END) || hint.equals(HTMLCMProperties.Values.BREAK_AFTER_START));
+	}
+
+	/**
+	 */
+	protected boolean canInsertBreakAfter(Node node) {
+		if (node == null)
+			return false;
+		Node parent = node.getParentNode();
+		if (parent == null)
+			return false;
+		Node next = node.getNextSibling();
+
+		// special exception if this node is a non-HTML tag (like JSP
+		// elements)
+		// BUG188093 - only preserve whitespace for jsp (not custom) tags
+		String prefix = node.getPrefix();
+		if (prefix != null && JSP.equals(prefix)) {
+			boolean canInsertBreakAfter = false;
+			// if a whitespace does not exist after it, do not add one
+			if (next != null && next.getNodeType() == Node.TEXT_NODE) {
+				String theText = ((Text) next).getData();
+				if (theText != null && theText.length() > 0) {
+					char theChar = theText.charAt(0);
+					canInsertBreakAfter = Character.isWhitespace(theChar);
+				}
+			}
+			// if cannot insert break, go ahead and return false (otherwise,
+			// continue processing)
+			if (!canInsertBreakAfter)
+				return false;
+		}
+
+		// special exception if next node is a non-HTML tag (like JSP
+		// elements)
+		// BUG188093 - only preserve whitespace for jsp (not custom) tags
+		if (next != null) {
+			prefix = next.getPrefix();
+			if (prefix != null && JSP.equals(prefix)) {
+				boolean canInsertBreakAfterPrevious = false;
+				// if a whitespace does not exist before it, do not add one
+				if (node.getNodeType() == Node.TEXT_NODE) {
+					String theText = ((Text) node).getData();
+					if (theText != null && theText.length() > 0) {
+						char theChar = theText.charAt(theText.length() - 1);
+						canInsertBreakAfterPrevious = Character.isWhitespace(theChar);
+					}
+				}
+				// if cannot insert break, go ahead and return false
+				// (otherwise,
+				// continue processing)
+				if (!canInsertBreakAfterPrevious)
+					return false;
+			}
+		}
+		if (parent.getNodeType() == Node.DOCUMENT_NODE) {
+			if (node.getNodeType() == Node.ELEMENT_NODE) {
+				// do not insert break after unclosed tag
+				if (!((IDOMElement) node).isClosed())
+					return false;
+			}
+			return true;
+		}
+		else if (parent.getNodeType() == Node.ELEMENT_NODE) {
+			IDOMElement element = (IDOMElement) parent;
+			// do not insert break before missing end tag
+			if (next == null && element.getEndStructuredDocumentRegion() == null)
+				return false;
+
+			// insert line break under non-HTML elements including JSP
+			// elements
+			if (element.getPrefix() != null)
+				return true;
+
+			CMElementDeclaration decl = getElementDeclaration(element);
+			if (decl != null) {
+				if (decl.getContentType() == CMElementDeclaration.ELEMENT)
+					return true;
+                // causes all closing tags to wrap to a new line
+                boolean allowsText = decl.getContentType() == CMElementDeclaration.MIXED
+                        || decl.getContentType() == CMElementDeclaration.PCDATA;
+                if (allowsNewlineAfter(allowsText, node, element))
+                    return true;
+				String tagName = element.getTagName();
+				// special for direct children under BODY
+				if (tagName != null && tagName.equalsIgnoreCase(BODY_NAME))
+					return true;
+			}
+		}
+
+		if (node.getNodeType() == Node.ELEMENT_NODE) {
+			IDOMElement element = (IDOMElement) node;
+			CMElementDeclaration decl = getElementDeclaration(element);
+			if (canInsertBreakAfter(decl)) {
+				// spcial for BR
+				return canFormatChild(parent);
+			}
+		}
+		if (next != null && next.getNodeType() == Node.ELEMENT_NODE) {
+			CMElementDeclaration decl = getElementDeclaration((Element) next);
+			if (canInsertBreakBefore(decl))
+				return true;
+		}
+		return false;
+	}
+
+	/**
+	 */
+	protected boolean canInsertBreakBefore(CMElementDeclaration decl) {
+		if (decl == null)
+			return false;
+		if (!decl.supports(HTMLCMProperties.LINE_BREAK_HINT))
+			return false;
+		String hint = (String) decl.getProperty(HTMLCMProperties.LINE_BREAK_HINT);
+		if (hint == null)
+			return false;
+		return hint.equals(HTMLCMProperties.Values.BREAK_BEFORE_START_AND_AFTER_END);
+	}
+
+	/**
+	 */
+	protected boolean canInsertBreakBefore(Node node) {
+		if (node == null)
+			return false;
+		Node parent = node.getParentNode();
+		if (parent == null)
+			return false;
+		Node prev = node.getPreviousSibling();
+
+		// special exception if this node is a non-HTML tag (like JSP
+		// elements)
+		// BUG188093 - only preserve whitespace for jsp (not custom) tags
+		String prefix = node.getPrefix();
+		if (prefix != null && JSP.equals(prefix)) {
+			boolean canInsertBreakBefore = false;
+			// if a whitespace does not exist before it, do not add one
+			if (prev != null && prev.getNodeType() == Node.TEXT_NODE) {
+				String theText = ((Text) prev).getData();
+				if (theText != null && theText.length() > 0) {
+					char theChar = theText.charAt(theText.length() - 1);
+					canInsertBreakBefore = Character.isWhitespace(theChar);
+				}
+			}
+			// if cannot insert break, go ahead and return false (otherwise,
+			// continue processing)
+			if (!canInsertBreakBefore)
+				return false;
+		}
+
+		// special exception if previous node is a non-HTML tag (like JSP
+		// elements)
+		// BUG188093 - only preserve whitespace for jsp (not custom) tags
+		if (prev != null) {
+			prefix = prev.getPrefix();
+			if (prefix != null && JSP.equals(prefix)) {
+				boolean canInsertBreakBeforeNext = false;
+				// if a whitespace does not exist after it, do not add one
+				if (node.getNodeType() == Node.TEXT_NODE) {
+					String theText = ((Text) node).getData();
+					if (theText != null && theText.length() > 0) {
+						char theChar = theText.charAt(0);
+						canInsertBreakBeforeNext = Character.isWhitespace(theChar);
+					}
+				}
+				// if cannot insert break, go ahead and return false
+				// (otherwise,
+				// continue processing)
+				if (!canInsertBreakBeforeNext)
+					return false;
+			}
+		}
+
+		if (parent.getNodeType() == Node.DOCUMENT_NODE) {
+			if (prev == null)
+				return false;
+			return true;
+		}
+		else if (parent.getNodeType() == Node.ELEMENT_NODE) {
+			IDOMElement element = (IDOMElement) parent;
+			// do not insert break after missing start tag
+			if (prev == null && element.getStartStructuredDocumentRegion() == null)
+				return false;
+
+			// insert line break under non-HTML elements including JSP
+			// elements
+			if (element.getPrefix() != null)
+				return true;
+
+			CMElementDeclaration decl = getElementDeclaration(element);
+			if (decl != null) {
+			    return allowNewlineBefore(node, element);
+			}
+		}
+
+		if (node.getNodeType() == Node.ELEMENT_NODE) {
+			return true;
+		}
+		if (prev != null && prev.getNodeType() == Node.ELEMENT_NODE) {
+			CMElementDeclaration decl = getElementDeclaration((Element) prev);
+			if (canInsertBreakAfter(decl)) {
+				// spcial for BR
+				return canFormatChild(parent);
+			}
+		}
+		return false;
+	}
+
+	/**
+	 */
+	public void format(Node node) {
+		format(node, getFormatContraints());
+	}
+
+	/**
+	 */
+	public void format(Node node, IStructuredFormatContraints contraints) {
+		if (node instanceof IDOMNode && contraints instanceof HTMLFormatContraints)
+			format((IDOMNode) node, (HTMLFormatContraints) contraints);
+	}
+
+	public void format(IDOMNode node, HTMLFormatContraints contraints) {
+		if (node == null)
+			return;
+		if (node.getParentNode() == null)
+			return; // do not format removed node
+
+		setWidth(contraints, node);
+
+		if (canInsertBreakBefore(node))
+			insertBreakBefore(node, contraints);
+
+		formatNode(node, contraints);
+
+		if (canInsertBreakAfter(node))
+			insertBreakAfter(node, contraints);
+	}
+
+	/**
+	 */
+	protected void formatChildNodes(IDOMNode node, HTMLFormatContraints contraints) {
+		if (node == null)
+			return;
+		if (!node.hasChildNodes())
+			return;
+
+		// concat adjacent texts
+		node.normalize();
+
+		// disable sibling indent during formatting all the children
+		boolean indent = false;
+		if (contraints != null) {
+			indent = contraints.getFormatWithSiblingIndent();
+			contraints.setFormatWithSiblingIndent(false);
+		}
+
+		boolean insertBreak = true;
+		IDOMNode child = (IDOMNode) node.getFirstChild();
+		while (child != null) {
+			if (child.getParentNode() != node)
+				break;
+			IDOMNode next = (IDOMNode) child.getNextSibling();
+
+			if (insertBreak && canInsertBreakBefore(child)) {
+				insertBreakBefore(child, contraints);
+			}
+
+			IStructuredFormatter formatter = HTMLFormatterFactory.getInstance().createFormatter(child, getFormatPreferences());
+			if (formatter != null) {
+				if (formatter instanceof HTMLFormatter) {
+					HTMLFormatter htmlFormatter = (HTMLFormatter) formatter;
+					htmlFormatter.formatNode(child, contraints);
+				}
+				else {
+					formatter.format(child);
+				}
+			}
+
+			if (canInsertBreakAfter(child)) {
+				insertBreakAfter(child, contraints);
+				insertBreak = false; // not to insert twice
+			}
+			else {
+				insertBreak = true;
+			}
+
+			child = next;
+		}
+
+		if (contraints != null)
+			contraints.setFormatWithSiblingIndent(indent);
+	}
+
+	/**
+	 */
+	protected void formatNode(IDOMNode node, HTMLFormatContraints contraints) {
+		if (node == null)
+			return;
+
+		if (node.hasChildNodes()) { // container
+			formatChildNodes(node, contraints);
+		}
+		else { // leaf
+			IStructuredDocumentRegion flatNode = node.getStartStructuredDocumentRegion();
+			if (flatNode != null) {
+				String source = flatNode.getText();
+				if (source != null && source.length() > 0) {
+					setWidth(contraints, source);
+				}
+			}
+		}
+	}
+
+	/**
+	 */
+	protected String getBreakSpaces(Node node) {
+		if (node == null)
+			return null;
+		StringBuffer buffer = new StringBuffer();
+
+		String delim = ((IDOMNode) node).getModel().getStructuredDocument().getLineDelimiter();
+		if (delim != null && delim.length() > 0)
+			buffer.append(delim);
+
+		String indent = getIndent();
+		if (indent != null && indent.length() > 0) {
+			for (Node parent = node.getParentNode(); parent != null; parent = parent.getParentNode()) {
+				if (parent.getNodeType() != Node.ELEMENT_NODE)
+					break;
+				// ignore omitted tag
+				if (((IDOMNode) parent).getStartStructuredDocumentRegion() == null)
+					continue;
+
+				IDOMElement element = (IDOMElement) parent;
+				if (element.getPrefix() != null) {
+					String localName = element.getLocalName();
+					// special for html:html
+					if (localName != null && !localName.equals(HTML_NAME)) {
+						buffer.append(indent);
+					}
+					continue;
+				}
+				else {
+					String localName = element.getLocalName();
+					if (HTML_NAME.equalsIgnoreCase(localName) || HEAD_NAME.equalsIgnoreCase(localName))
+						break;
+				}
+
+				CMElementDeclaration decl = getElementDeclaration(element);
+				if (decl != null && decl.supports(HTMLCMProperties.SHOULD_INDENT_CHILD_SOURCE)) {
+					boolean shouldIndent = isIdentable(node, parent); 
+					if (shouldIndent)
+						buffer.append(indent);
+				}
+
+			}
+		}
+
+		return buffer.toString();
+	}
+
+	/**
+	 */
+	protected String getIndent() {
+		return getFormatPreferences().getIndent();
+	}
+
+	/**
+	 */
+	protected int getLineWidth() {
+		return getFormatPreferences().getLineWidth();
+	}
+
+	/**
+	 */
+	protected CMElementDeclaration getElementDeclaration(Element element) {
+		if (element == null)
+			return null;
+		Document document = element.getOwnerDocument();
+		if (document == null)
+			return null;
+		ModelQuery modelQuery = ModelQueryUtil.getModelQuery(document);
+		if (modelQuery == null)
+			return null;
+		return modelQuery.getCMElementDeclaration(element);
+	}
+
+	/**
+	 */
+	protected void insertBreakAfter(IDOMNode node, HTMLFormatContraints contraints) {
+		if (node == null)
+			return;
+		if (node.getNodeType() == Node.TEXT_NODE)
+			return;
+		// don't insert break if node is on the last line
+		int documentLength = node.getStructuredDocument().getLength();
+		if (documentLength < 1 || (node.getEndOffset() >= (documentLength - 1)))
+			return;
+		Node parent = node.getParentNode();
+		if (parent == null)
+			return;
+		Node next = node.getNextSibling();
+
+		String spaces = null;
+		if (next == null) { // last spaces
+			// use parent indent for the end tag
+			spaces = getBreakSpaces(parent);
+		}
+		else if (next.getNodeType() == Node.TEXT_NODE) {
+			if (contraints != null && contraints.getFormatWithSiblingIndent()) {
+				IDOMNode text = (IDOMNode) next;
+				IStructuredFormatter formatter = HTMLFormatterFactory.getInstance().createFormatter(text, getFormatPreferences());
+				if (formatter instanceof HTMLTextFormatter) {
+					HTMLTextFormatter textFormatter = (HTMLTextFormatter) formatter;
+					textFormatter.formatText(text, contraints, HTMLTextFormatter.FORMAT_HEAD);
+				}
+			}
+			return;
+		}
+		else {
+			spaces = getBreakSpaces(node);
+		}
+		if (spaces == null || spaces.length() == 0)
+			return;
+
+		replaceSource(node.getModel(), node.getEndOffset(), 0, spaces);
+		setWidth(contraints, spaces);
+	}
+
+	/**
+	 */
+	protected void insertBreakBefore(IDOMNode node, HTMLFormatContraints contraints) {
+		if (node == null)
+			return;
+		if (node.getNodeType() == Node.TEXT_NODE)
+			return;
+		Node parent = node.getParentNode();
+		if (parent == null)
+			return;
+		Node prev = node.getPreviousSibling();
+
+		String spaces = null;
+		if (prev != null && prev.getNodeType() == Node.TEXT_NODE) {
+			if (contraints != null && contraints.getFormatWithSiblingIndent()) {
+				IDOMNode text = (IDOMNode) prev;
+				IStructuredFormatter formatter = HTMLFormatterFactory.getInstance().createFormatter(text, getFormatPreferences());
+				if (formatter instanceof HTMLTextFormatter) {
+					HTMLTextFormatter textFormatter = (HTMLTextFormatter) formatter;
+					textFormatter.formatText(text, contraints, HTMLTextFormatter.FORMAT_TAIL);
+				}
+			}
+			return;
+		}
+		else {
+			spaces = getBreakSpaces(node);
+		}
+		if (spaces == null || spaces.length() == 0)
+			return;
+
+		replaceSource(node.getModel(), node.getStartOffset(), 0, spaces);
+		setWidth(contraints, spaces);
+	}
+
+	/**
+	 */
+	protected boolean isWidthAvailable(HTMLFormatContraints contraints, int width) {
+		if (contraints == null)
+			return true;
+		if (!splitLines() || getLineWidth() < 0)
+			return true;
+		return (contraints.getAvailableLineWidth() >= width);
+	}
+
+	/**
+	 */
+	protected boolean keepBlankLines(HTMLFormatContraints contraints) {
+		if (contraints == null)
+			return true;
+		return (!contraints.getClearAllBlankLines());
+	}
+
+	/**
+	 */
+	protected void replaceSource(IStructuredDocumentRegion flatNode, int offset, int length, String source) {
+		if (flatNode == null)
+			return;
+		IStructuredDocument structuredDocument = flatNode.getParentDocument();
+		if (structuredDocument == null)
+			return;
+		if (source == null)
+			source = new String();
+		int startOffset = flatNode.getStartOffset();
+		if (structuredDocument.containsReadOnly(startOffset + offset, length))
+			return;
+		// We use 'structuredDocument' as the requester object just so this
+		// and the other
+		// format-related 'repalceText' (in replaceSource) can use the same
+		// requester.
+		// Otherwise, if requester is not identical,
+		// the undo group gets "broken" into multiple pieces based
+		// on the requesters being different. Technically, any unique, common
+		// requester object would work.
+		structuredDocument.replaceText(structuredDocument, startOffset + offset, length, source);
+	}
+
+	/**
+	 */
+	protected void replaceSource(IDOMModel model, int offset, int length, String source) {
+		if (model == null)
+			return;
+		IStructuredDocument structuredDocument = model.getStructuredDocument();
+		if (structuredDocument == null)
+			return;
+		if (source == null)
+			source = new String();
+		if (structuredDocument.containsReadOnly(offset, length))
+			return;
+		// We use 'structuredDocument' as the requester object just so this
+		// and the other
+		// format-related 'repalceText' (in replaceSource) can use the same
+		// requester.
+		// Otherwise, if requester is not identical,
+		// the undo group gets "broken" into multiple pieces based
+		// on the requesters being different. Technically, any unique, common
+		// requester object would work.
+		structuredDocument.replaceText(structuredDocument, offset, length, source);
+	}
+
+	/**
+	 */
+	protected void setWidth(HTMLFormatContraints contraints, String source) {
+		if (contraints == null)
+			return;
+		if (source == null)
+			return;
+		int length = source.length();
+		if (length == 0)
+			return;
+
+		if (!splitLines())
+			return;
+		int lineWidth = getLineWidth();
+		if (lineWidth < 0)
+			return;
+
+		int offset = source.lastIndexOf('\n');
+		int offset2 = source.lastIndexOf('\r');
+		if (offset2 > offset)
+			offset = offset2;
+		if (offset >= 0)
+			offset++;
+
+		int availableWidth = 0;
+		if (offset >= 0) {
+			availableWidth = lineWidth - (length - offset);
+		}
+		else {
+			availableWidth = contraints.getAvailableLineWidth() - length;
+		}
+		if (availableWidth < 0)
+			availableWidth = 0;
+		contraints.setAvailableLineWidth(availableWidth);
+	}
+
+	/**
+	 */
+	protected void setWidth(HTMLFormatContraints contraints, Node node) {
+		if (contraints == null)
+			return;
+		if (node == null)
+			return;
+		IStructuredDocument structuredDocument = ((IDOMNode) node).getStructuredDocument();
+		if (structuredDocument == null)
+			return; // error
+
+		if (!splitLines())
+			return;
+		int lineWidth = getLineWidth();
+		if (lineWidth < 0)
+			return;
+
+		int offset = ((IDOMNode) node).getStartOffset();
+		int line = structuredDocument.getLineOfOffset(offset);
+		int lineOffset = 0;
+		try {
+			lineOffset = structuredDocument.getLineOffset(line);
+		}
+		catch (BadLocationException ex) {
+			return; // error
+		}
+		if (lineOffset > offset)
+			return; // error
+
+		int availableWidth = lineWidth - (offset - lineOffset);
+		if (availableWidth < 0)
+			availableWidth = 0;
+
+		contraints.setAvailableLineWidth(availableWidth);
+	}
+
+	/**
+	 */
+	protected boolean splitLines() {
+		return true;// getFormatPreferences().getSplitLines();
+	}
+
+	protected IStructuredFormatPreferences fFormatPreferences = null;
+	protected HTMLFormatContraints fFormatContraints = null;
+	protected IProgressMonitor fProgressMonitor = null;
+
+	// public void format(XMLNode node, FormatContraints formatContraints) {
+	// if (formatContraints.getFormatWithSiblingIndent())
+	// formatContraints.setCurrentIndent(getSiblingIndent(node));
+	//
+	// formatNode(node, formatContraints);
+	// }
+
+	public void setFormatPreferences(IStructuredFormatPreferences formatPreferences) {
+		fFormatPreferences = formatPreferences;
+	}
+
+	public IStructuredFormatPreferences getFormatPreferences() {
+		if (fFormatPreferences == null) {
+			fFormatPreferences = new StructuredFormatPreferencesXML();
+
+			Preferences preferences = HTMLCorePlugin.getDefault().getPluginPreferences();
+			if (preferences != null) {
+				fFormatPreferences.setLineWidth(preferences.getInt(HTMLCorePreferenceNames.LINE_WIDTH));
+				((StructuredFormatPreferencesXML) fFormatPreferences).setSplitMultiAttrs(preferences.getBoolean(HTMLCorePreferenceNames.SPLIT_MULTI_ATTRS));
+				((StructuredFormatPreferencesXML) fFormatPreferences).setAlignEndBracket(preferences.getBoolean(HTMLCorePreferenceNames.ALIGN_END_BRACKET));
+				fFormatPreferences.setClearAllBlankLines(preferences.getBoolean(HTMLCorePreferenceNames.CLEAR_ALL_BLANK_LINES));
+
+				char indentChar = ' ';
+				String indentCharPref = preferences.getString(HTMLCorePreferenceNames.INDENTATION_CHAR);
+				if (HTMLCorePreferenceNames.TAB.equals(indentCharPref)) {
+					indentChar = '\t';
+				}
+				int indentationWidth = preferences.getInt(HTMLCorePreferenceNames.INDENTATION_SIZE);
+
+				StringBuffer indent = new StringBuffer();
+				for (int i = 0; i < indentationWidth; i++) {
+					indent.append(indentChar);
+				}
+				fFormatPreferences.setIndent(indent.toString());
+			}
+		}
+
+		return fFormatPreferences;
+	}
+
+	public IStructuredFormatContraints getFormatContraints() {
+		if (fFormatContraints == null) {
+			fFormatContraints = new HTMLFormatContraintsImpl();
+
+			fFormatContraints.setAvailableLineWidth(getFormatPreferences().getLineWidth());
+			fFormatContraints.setClearAllBlankLines(getFormatPreferences().getClearAllBlankLines());
+		}
+
+		return fFormatContraints;
+	}
+
+	public void setProgressMonitor(IProgressMonitor progressMonitor) {
+		fProgressMonitor = progressMonitor;
+	}
+
+    /* Check to see if current text Node is a child of an inline element. */
+    public boolean isInlinableTextNode(Node theNode, Element theParentElement) {
+        return formattingUtil.isInline(theParentElement) && 
+               theNode.getNodeType() == Node.TEXT_NODE;
+    }
+    
+    public boolean allowsNewlineAfter(boolean theBool, Node theNode, Element theParentElement) {
+        boolean result = theBool;
+        if ((theNode.getNodeType() == Node.TEXT_NODE) && formattingUtil.isInline(theParentElement)) {
+            result = false;
+        } else if (theNode.getNodeType() == Node.ELEMENT_NODE
+                && formattingUtil.isInline(theNode.getNextSibling())) {
+            result = false;
+        }
+        else if (theNode.getNodeType() == Node.TEXT_NODE) {
+        	Node next = theNode.getNextSibling();
+        	if (next != null && formattingUtil.isInline(next) || theParentElement.getChildNodes().getLength() <= 1) {
+        		result = false;
+        	}
+        }
+        return result;
+    }
+
+    public boolean allowNewlineBefore(Node theNode) {
+        if (theNode.getNodeType() != Node.TEXT_NODE &&
+            theNode.getNodeType() != Node.ELEMENT_NODE) return false;
+        return (formattingUtil.isInline(theNode.getParentNode()) ||
+                        formattingUtil.isInline(theNode.getPreviousSibling()));        
+    }
+    
+    public boolean allowNewlineBefore(Node theNode, Element theParentElement) {
+        boolean result = true;
+        /* The calling method canInsertBreakBefore is checking if you can 
+         * insert a line break after the text node in the parentElement.  We 
+         * need to check for the case with inline element because we don't want to 
+         * break before the closing </tag> */
+        if (isInlinableTextNode(theNode, theParentElement)) {
+            result = false;
+        /* Check to see if we need to not break the line because we are
+         * a child of a inline element or a next sibling to an inline element*/
+        } else if (allowNewlineBefore(theNode)) {
+            result = false;
+        } else if (theNode.getNodeType() == Node.TEXT_NODE && theParentElement.getChildNodes().getLength() <= 1) {
+        	result = false;
+        }
+        return result;
+    }
+
+    public boolean isIdentable(Node theNode, Node theParent) {
+        boolean result = true;
+        /* The first 2 cases where we don't want to break/indent or if the
+         * node is a inlineText ELement or if we should skip it before its parent
+         * is an inlineText element.  
+         * The last check is to make sure that the parent is actually the parent
+         * of the node.  This method is called when the formatter is formatting
+         * the startTag and the wrap margin causes attributes to be indents on
+         * mulitple lines.  In this case where the parentNode doesn't match
+         * theParent argument, we can allow the indent. */
+        if (formattingUtil.isInline(theNode) && 
+        		formattingUtil.shouldSkipIndentForNode(theNode) &&
+                theParent == theNode.getParentNode()) {
+            result = false;
+        }
+        return result;
+    }
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/format/HTMLFormatterFactory.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/format/HTMLFormatterFactory.java
new file mode 100644
index 0000000..d34701a
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/format/HTMLFormatterFactory.java
@@ -0,0 +1,109 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.format;
+
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.wst.html.core.internal.HTMLCorePlugin;
+import org.eclipse.wst.html.core.internal.preferences.HTMLCorePreferenceNames;
+import org.eclipse.wst.sse.core.internal.format.IStructuredFormatPreferences;
+import org.eclipse.wst.sse.core.internal.format.IStructuredFormatter;
+import org.eclipse.wst.xml.core.internal.provisional.format.StructuredFormatPreferencesXML;
+import org.w3c.dom.Node;
+
+// nakamori_TODO: check and remove CSS formatting
+
+class HTMLFormatterFactory {
+	private static HTMLFormatterFactory fInstance = null;
+	protected StructuredFormatPreferencesXML fFormatPreferences = null;
+
+	static synchronized HTMLFormatterFactory getInstance() {
+		if (fInstance == null) {
+			fInstance = new HTMLFormatterFactory();
+		}
+		return fInstance;
+	}
+
+	protected IStructuredFormatter createFormatter(Node node, IStructuredFormatPreferences formatPreferences) {
+		IStructuredFormatter formatter = null;
+
+		switch (node.getNodeType()) {
+			case Node.ELEMENT_NODE :
+				formatter = new HTMLElementFormatter();
+				break;
+			case Node.TEXT_NODE :
+				if (isEmbeddedCSS(node)) {
+					formatter = new EmbeddedCSSFormatter();
+				}
+				else {
+					formatter = new HTMLTextFormatter();
+				}
+				break;
+			default :
+				formatter = new HTMLFormatter();
+				break;
+		}
+
+		// init FormatPreferences
+		formatter.setFormatPreferences(formatPreferences);
+
+		return formatter;
+	}
+
+	/**
+	 */
+	private boolean isEmbeddedCSS(Node node) {
+		if (node == null)
+			return false;
+		Node parent = node.getParentNode();
+		if (parent == null)
+			return false;
+		if (parent.getNodeType() != Node.ELEMENT_NODE)
+			return false;
+		String name = parent.getNodeName();
+		if (name == null)
+			return false;
+		return name.equalsIgnoreCase("STYLE");//$NON-NLS-1$
+	}
+
+
+	private HTMLFormatterFactory() {
+		super();
+	}
+
+	protected StructuredFormatPreferencesXML getFormatPreferences() {
+		if (fFormatPreferences == null) {
+			fFormatPreferences = new StructuredFormatPreferencesXML();
+
+			Preferences preferences = HTMLCorePlugin.getDefault().getPluginPreferences();
+			if (preferences != null) {
+				fFormatPreferences.setLineWidth(preferences.getInt(HTMLCorePreferenceNames.LINE_WIDTH));
+				fFormatPreferences.setSplitMultiAttrs(preferences.getBoolean(HTMLCorePreferenceNames.SPLIT_MULTI_ATTRS));
+				fFormatPreferences.setAlignEndBracket(preferences.getBoolean(HTMLCorePreferenceNames.ALIGN_END_BRACKET));
+				fFormatPreferences.setClearAllBlankLines(preferences.getBoolean(HTMLCorePreferenceNames.CLEAR_ALL_BLANK_LINES));
+
+				char indentChar = ' ';
+				String indentCharPref = preferences.getString(HTMLCorePreferenceNames.INDENTATION_CHAR);
+				if (HTMLCorePreferenceNames.TAB.equals(indentCharPref)) {
+					indentChar = '\t';
+				}
+				int indentationWidth = preferences.getInt(HTMLCorePreferenceNames.INDENTATION_SIZE);
+
+				StringBuffer indent = new StringBuffer();
+				for (int i = 0; i < indentationWidth; i++) {
+					indent.append(indentChar);
+				}
+				fFormatPreferences.setIndent(indent.toString());
+			}
+		}
+
+		return fFormatPreferences;
+	}
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/format/HTMLFormattingUtil.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/format/HTMLFormattingUtil.java
new file mode 100644
index 0000000..9a2b000
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/format/HTMLFormattingUtil.java
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.format;
+
+import java.util.HashSet;
+import java.util.Locale;
+import java.util.Set;
+
+import org.eclipse.wst.html.core.internal.HTMLCorePlugin;
+import org.eclipse.wst.html.core.internal.preferences.HTMLCorePreferenceNames;
+import org.w3c.dom.Node;
+
+import com.ibm.icu.util.StringTokenizer;
+
+public class HTMLFormattingUtil {
+
+	private Set fInlineElements;
+
+	public HTMLFormattingUtil() {
+		fInlineElements = getInlineSet();
+	}
+
+	public boolean isInline(Node node) {
+		return node != null && fInlineElements.contains(node.getNodeName().toLowerCase(Locale.US));
+	}
+
+	public boolean shouldSkipIndentForNode(Node node) {
+		return isInline(node.getParentNode());
+	}
+
+	/**
+	 * Returns an array of the element names considered as "inline" for the purposes of formatting.
+	 * This list represents those stored in the preference store when invoked.
+	 * 
+	 * @return An array of element names considered to be "inline"
+	 */
+	public static Object[] getInlineElements() {
+		return getInlineSet().toArray();
+	}
+
+	/**
+	 * Stores the element names to the preference store to be considered as "inline"
+	 * 
+	 * @param elements The element names considered to be "inline"
+	 */
+	public static void exportToPreferences(Object[] elements) {
+		if (elements != null) {
+			StringBuffer buffer = new StringBuffer();
+			for (int i = 0; i < elements.length; i++) {
+				if (i > 0)
+					buffer.append(',');
+				buffer.append(elements[i]);
+			}
+			HTMLCorePlugin.getDefault().getPluginPreferences().setValue(HTMLCorePreferenceNames.INLINE_ELEMENTS, buffer.toString());
+		}
+	}
+
+	/**
+	 * Returns an array of the default element names considered as "inline" for the purposes of formatting.
+	 * 
+	 * @return An array of the default element names considered to be "inline"
+	 */
+	public static Object[] getDefaultInlineElements() {
+		String inline = HTMLCorePlugin.getDefault().getPluginPreferences().getDefaultString(HTMLCorePreferenceNames.INLINE_ELEMENTS);
+		Set defaults = new HashSet();
+		StringTokenizer tokenizer = new StringTokenizer(inline, ",");
+		while (tokenizer.hasMoreTokens()) {
+			defaults.add(tokenizer.nextToken());
+		}
+		return defaults.toArray();
+	}
+
+	private static Set getInlineSet() {
+		String inline = HTMLCorePlugin.getDefault().getPluginPreferences().getString(HTMLCorePreferenceNames.INLINE_ELEMENTS);
+		Set elements = new HashSet();
+		StringTokenizer tokenizer = new StringTokenizer(inline, ",");
+		while (tokenizer.hasMoreTokens()) {
+			elements.add(tokenizer.nextToken());
+		}
+		return elements;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/format/HTMLTextFormatter.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/format/HTMLTextFormatter.java
new file mode 100644
index 0000000..91aefd3
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/format/HTMLTextFormatter.java
@@ -0,0 +1,299 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.format;
+
+
+
+import org.eclipse.wst.html.core.internal.provisional.HTMLCMProperties;
+import org.eclipse.wst.html.core.internal.provisional.HTMLFormatContraints;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMText;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+public class HTMLTextFormatter extends HTMLFormatter {
+
+	public static int FORMAT_ALL = 0;
+	public static int FORMAT_HEAD = 1;
+	public static int FORMAT_TAIL = 2;
+
+	/**
+	 */
+	protected HTMLTextFormatter() {
+		super();
+	}
+
+	/**
+	 */
+	private boolean canFormatText(IDOMText text) {
+		if (text == null)
+			return false;
+
+		IStructuredDocumentRegion flatNode = text.getFirstStructuredDocumentRegion();
+		if (flatNode != null) {
+			String type = flatNode.getType();
+			if (isUnparsedRegion(type))
+				return false;
+		}
+
+		Node parent = text.getParentNode();
+		if (parent != null && parent.getNodeType() == Node.ELEMENT_NODE) {
+			IDOMElement element = (IDOMElement) parent;
+			if (!element.isGlobalTag() && !text.isElementContentWhitespace())
+				return false;
+		}
+
+		return canFormatChild(parent);
+	}
+
+	private boolean isUnparsedRegion(String type) {
+		boolean result = isNestedScannedRegion(type) || isBlockScannedRegion(type);
+		return result;
+	}
+
+	private boolean isBlockScannedRegion(String type) {
+		return type == DOMRegionContext.BLOCK_TEXT;
+	}
+
+	/**
+	 * ISSUE: this is a bit of hidden JSP knowledge that was implemented this
+	 * way for expedency. Should be evolved in future to depend on
+	 * "nestedContext".
+	 */
+	private boolean isNestedScannedRegion(String type) {
+		final String JSP_CONTENT = "JSP_CONTENT"; //$NON-NLS-1$
+		return type.equals(JSP_CONTENT);
+	}
+
+	/**
+	 */
+	private boolean canRemoveHeadingSpaces(IDOMNode node) {
+		if (node == null)
+			return false;
+		if (node.getPreviousSibling() != null)
+			return false;
+		Node parent = node.getParentNode();
+		if (parent == null || parent.getNodeType() != Node.ELEMENT_NODE)
+			return false;
+
+		CMElementDeclaration decl = getElementDeclaration((Element) parent);
+		if (decl == null || (!decl.supports(HTMLCMProperties.LINE_BREAK_HINT)))
+			return false;
+		String hint = (String) decl.getProperty(HTMLCMProperties.LINE_BREAK_HINT);
+		return hint.equals(HTMLCMProperties.Values.BREAK_BEFORE_START_AND_AFTER_END);
+	}
+
+	/**
+	 */
+	private boolean canRemoveTailingSpaces(IDOMNode node) {
+		if (node == null)
+			return false;
+		if (node.getNextSibling() != null)
+			return false;
+		Node parent = node.getParentNode();
+		if (parent == null || parent.getNodeType() != Node.ELEMENT_NODE)
+			return false;
+
+		CMElementDeclaration decl = getElementDeclaration((Element) parent);
+		if (decl == null || (!decl.supports(HTMLCMProperties.LINE_BREAK_HINT)))
+			return false;
+		String hint = (String) decl.getProperty(HTMLCMProperties.LINE_BREAK_HINT);
+		return hint.equals(HTMLCMProperties.Values.BREAK_BEFORE_START_AND_AFTER_END);
+	}
+
+	/**
+	 */
+	protected void formatNode(IDOMNode node, HTMLFormatContraints contraints) {
+		formatText(node, contraints, FORMAT_ALL); // full format
+	}
+
+	/**
+	 */
+	protected void formatText(IDOMNode node, HTMLFormatContraints contraints, int mode) {
+		if (node == null)
+			return;
+		Node parent = node.getParentNode();
+		if (parent == null)
+			return;
+
+		IDOMText text = (IDOMText) node;
+		String source = text.getSource();
+
+		if (!canFormatText(text)) {
+			setWidth(contraints, source);
+			return;
+		}
+
+		int offset = text.getStartOffset();
+		int length = text.getEndOffset() - offset;
+
+		// format adjacent text at once
+		if (mode == FORMAT_HEAD) {
+			Node next = node.getNextSibling();
+			while (next != null && next.getNodeType() == Node.TEXT_NODE) {
+				IDOMText nextText = (IDOMText) next;
+				length += (nextText.getEndOffset() - nextText.getStartOffset());
+				String nextSource = nextText.getSource();
+				if (nextSource != null && nextSource.length() > 0) {
+					if (source == null)
+						source = nextSource;
+					else
+						source += nextSource;
+				}
+				next = next.getNextSibling();
+			}
+		}
+		else if (mode == FORMAT_TAIL) {
+			Node prev = node.getPreviousSibling();
+			while (prev != null && prev.getNodeType() == Node.TEXT_NODE) {
+				IDOMText prevText = (IDOMText) prev;
+				offset = prevText.getStartOffset();
+				length += (prevText.getEndOffset() - offset);
+				String prevSource = prevText.getSource();
+				if (prevSource != null && prevSource.length() > 0) {
+					if (source == null)
+						source = prevSource;
+					else
+						source = prevSource + source;
+				}
+				prev = prev.getPreviousSibling();
+			}
+		}
+
+		SpaceConverter converter = new SpaceConverter(source, keepBlankLines(contraints));
+
+		int wordLength = converter.nextWord();
+		if (wordLength == 0) { // only spaces
+			if (!converter.hasSpaces())
+				return; // empty
+			boolean removeSpaces = false;
+			if (parent.getNodeType() == Node.ELEMENT_NODE) {
+				// check if tags are omitted
+				IDOMNode element = (IDOMNode) parent;
+				if (node.getPreviousSibling() == null && element.getStartStructuredDocumentRegion() == null) {
+					removeSpaces = true;
+				}
+				else if (node.getNextSibling() == null && element.getEndStructuredDocumentRegion() == null) {
+					removeSpaces = true;
+				}
+			}
+			if (removeSpaces) {
+				converter.replaceSpaces(null);
+			}
+			else if (!isWidthAvailable(contraints, 2) || canInsertBreakAfter(node) || canInsertBreakBefore(node)) {
+				String spaces = null;
+				if (node.getNextSibling() == null) { // last spaces
+					// use parent indent for the end tag
+					spaces = getBreakSpaces(parent);
+				}
+				else {
+					spaces = getBreakSpaces(node);
+				}
+				converter.replaceSpaces(spaces);
+				setWidth(contraints, spaces);
+			}
+			else if (canRemoveHeadingSpaces(node) || canRemoveTailingSpaces(node)) {
+				converter.replaceSpaces(null);
+			}
+			else {
+				converter.compressSpaces();
+				addWidth(contraints, 1);
+			}
+		}
+		else {
+			String breakSpaces = null;
+
+			// format heading spaces
+			boolean hasSpaces = converter.hasSpaces();
+			if (mode == FORMAT_TAIL) {
+				// keep spaces as is
+				addWidth(contraints, converter.getSpaceCount());
+			}
+			else if ((hasSpaces && !isWidthAvailable(contraints, wordLength + 1)) || canInsertBreakBefore(node)) {
+				breakSpaces = getBreakSpaces(node);
+				converter.replaceSpaces(breakSpaces);
+				setWidth(contraints, breakSpaces);
+			}
+			else {
+				if (hasSpaces) {
+					if (canRemoveHeadingSpaces(node)) {
+						converter.replaceSpaces(null);
+					}
+					else {
+						converter.compressSpaces();
+						addWidth(contraints, 1);
+					}
+				}
+			}
+			addWidth(contraints, wordLength);
+
+			// format middle
+			wordLength = converter.nextWord();
+			while (wordLength > 0) {
+				if (mode != FORMAT_ALL) {
+					// keep spaces as is
+					addWidth(contraints, converter.getSpaceCount());
+				}
+				else if (!isWidthAvailable(contraints, wordLength + 1)) {
+					if (breakSpaces == null)
+						breakSpaces = getBreakSpaces(node);
+					converter.replaceSpaces(breakSpaces);
+					setWidth(contraints, breakSpaces);
+				}
+				else {
+					converter.compressSpaces();
+					addWidth(contraints, 1);
+				}
+				addWidth(contraints, wordLength);
+				wordLength = converter.nextWord();
+			}
+
+			// format tailing spaces
+			hasSpaces = converter.hasSpaces();
+			if (mode == FORMAT_HEAD) {
+				// keep spaces as is
+				addWidth(contraints, converter.getSpaceCount());
+			}
+			else if ((hasSpaces && !isWidthAvailable(contraints, 2)) || canInsertBreakAfter(node)) {
+				if (node.getNextSibling() == null) { // last test
+					// use parent indent for the end tag
+					breakSpaces = getBreakSpaces(parent);
+				}
+				else {
+					if (breakSpaces == null)
+						breakSpaces = getBreakSpaces(node);
+				}
+				converter.replaceSpaces(breakSpaces);
+				setWidth(contraints, breakSpaces);
+			}
+			else {
+				if (hasSpaces) {
+					if (canRemoveTailingSpaces(node)) {
+						converter.replaceSpaces(null);
+					}
+					else {
+						converter.compressSpaces();
+						addWidth(contraints, 1);
+					}
+				}
+			}
+		}
+
+		if (converter.isModified()) {
+			source = converter.getSource();
+			replaceSource(text.getModel(), offset, length, source);
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/format/SpaceConverter.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/format/SpaceConverter.java
new file mode 100644
index 0000000..38f9203
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/format/SpaceConverter.java
@@ -0,0 +1,235 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.format;
+
+
+
+final class SpaceConverter {
+
+	private String source = null;
+	private int length = 0;
+	private int startOffset = 0;
+	private int endOffset = 0;
+	private int spaceCount = 0;
+	private int wordCount = 0;
+	private StringBuffer buffer = null;
+	private int lastOffset = 0;
+	private boolean keepBlankLines = false;
+
+	/**
+	 */
+	public SpaceConverter(String source) {
+		super();
+
+		if (source == null) {
+			this.source = new String();
+		}
+		else {
+			this.source = source;
+			this.length = source.length();
+		}
+	}
+
+	/**
+	 */
+	public SpaceConverter(String source, boolean keepBlankLines) {
+		super();
+
+		if (source == null) {
+			this.source = new String();
+		}
+		else {
+			this.source = source;
+			this.length = source.length();
+		}
+		this.keepBlankLines = keepBlankLines;
+	}
+
+	/**
+	 */
+	public void compressSpaces() {
+		if (this.spaceCount == 0)
+			return;
+		if (this.spaceCount == 1 && this.source.charAt(this.startOffset) == ' ')
+			return;
+
+		if (this.buffer == null)
+			this.buffer = new StringBuffer();
+		if (this.startOffset > this.lastOffset) {
+			this.buffer.append(this.source.substring(this.lastOffset, this.startOffset));
+		}
+
+		this.buffer.append(' ');
+
+		this.lastOffset = this.startOffset + this.spaceCount;
+	}
+
+	/**
+	 */
+	public String getSource() {
+		if (this.buffer == null)
+			this.buffer = new StringBuffer();
+		if (this.length > this.lastOffset) {
+			this.buffer.append(this.source.substring(this.lastOffset, this.length));
+		}
+		return this.buffer.toString();
+	}
+
+	/**
+	 */
+	public int getSpaceCount() {
+		return this.spaceCount;
+	}
+
+	/**
+	 */
+	public boolean hasSpaces() {
+		return (this.spaceCount > 0);
+	}
+
+	/**
+	 */
+	public boolean isModified() {
+		return (this.buffer != null);
+	}
+
+	/**
+	 * Add number of the old blank lines to new space string
+	 */
+	private static String mergeBlankLines(String newSpaces, String oldSpaces) {
+		if (newSpaces == null || newSpaces.length() == 0)
+			return newSpaces;
+		if (oldSpaces == null)
+			return newSpaces;
+
+		// count old new lines
+		int newLineCount = 0;
+		int oldLength = oldSpaces.length();
+		for (int i = 0; i < oldLength; i++) {
+			char c = oldSpaces.charAt(i);
+			if (c == '\r') {
+				newLineCount++;
+				if (i + 1 < oldLength) {
+					c = oldSpaces.charAt(i + 1);
+					if (c == '\n')
+						i++;
+				}
+			}
+			else {
+				if (c == '\n')
+					newLineCount++;
+			}
+		}
+		if (newLineCount < 2)
+			return newSpaces; // no blank line
+
+		// here assuming newSpaces starts with a new line if any
+		String delim = null;
+		char d = newSpaces.charAt(0);
+		if (d == '\r') {
+			if (newSpaces.length() > 1 && newSpaces.charAt(1) == '\n')
+				delim = "\r\n";//$NON-NLS-1$
+			else
+				delim = "\r";//$NON-NLS-1$
+		}
+		else {
+			if (d == '\n')
+				delim = "\n";//$NON-NLS-1$
+			else
+				return newSpaces; // no new line
+		}
+
+		newLineCount--;
+		StringBuffer buffer = new StringBuffer(newSpaces.length() + newLineCount * 2);
+		while (newLineCount > 0) {
+			buffer.append(delim);
+			newLineCount--;
+		}
+		buffer.append(newSpaces);
+		return buffer.toString();
+	}
+
+	/**
+	 */
+	public int nextWord() {
+		if (this.endOffset == this.length) {
+			this.startOffset = this.endOffset;
+			this.spaceCount = 0;
+			this.wordCount = 0;
+			return 0;
+		}
+
+		this.startOffset = this.endOffset;
+		int i = this.startOffset;
+		for (; i < this.length; i++) {
+			if (!Character.isWhitespace(this.source.charAt(i)))
+				break;
+		}
+		this.spaceCount = i - this.startOffset;
+
+		int wordOffset = i;
+		for (; i < this.length; i++) {
+			if (Character.isWhitespace(this.source.charAt(i)))
+				break;
+		}
+		this.wordCount = i - wordOffset;
+		this.endOffset = i;
+
+		return this.wordCount;
+	}
+
+	/**
+	 */
+	public void replaceSpaces(String spaces) {
+		int spaceLength = (spaces != null ? spaces.length() : 0);
+		String oldSpaces = null;
+		if (spaceLength == this.spaceCount) {
+			if (spaceLength == 0)
+				return;
+			if (this.startOffset == 0) {
+				if (this.source.startsWith(spaces))
+					return;
+			}
+			else if (this.endOffset == this.length) {
+				if (this.source.endsWith(spaces))
+					return;
+			}
+			else {
+				int textOffset = this.startOffset + this.spaceCount;
+				oldSpaces = this.source.substring(this.startOffset, textOffset);
+				if (oldSpaces.equals(spaces))
+					return;
+			}
+		}
+		if (this.keepBlankLines && this.spaceCount > 0) {
+			if (oldSpaces == null) {
+				int textOffset = this.startOffset + this.spaceCount;
+				oldSpaces = this.source.substring(this.startOffset, textOffset);
+			}
+			if (oldSpaces != null) {
+				spaces = mergeBlankLines(spaces, oldSpaces);
+				if (oldSpaces.equals(spaces))
+					return;
+			}
+		}
+
+		if (this.buffer == null)
+			this.buffer = new StringBuffer();
+		if (this.startOffset > this.lastOffset) {
+			this.buffer.append(this.source.substring(this.lastOffset, this.startOffset));
+		}
+
+		if (spaceLength > 0)
+			this.buffer.append(spaces);
+
+		this.lastOffset = this.startOffset + this.spaceCount;
+	}
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/htmlcss/AbstractCSSModelAdapter.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/htmlcss/AbstractCSSModelAdapter.java
new file mode 100644
index 0000000..891868c
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/htmlcss/AbstractCSSModelAdapter.java
@@ -0,0 +1,105 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.htmlcss;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+import org.eclipse.wst.css.core.internal.document.CSSModelImpl;
+import org.eclipse.wst.css.core.internal.provisional.adapters.ICSSModelAdapter;
+import org.eclipse.wst.css.core.internal.provisional.contenttype.ContentTypeIdForCSS;
+import org.eclipse.wst.css.core.internal.provisional.document.ICSSModel;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapter;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.w3c.dom.Element;
+
+/**
+ */
+public abstract class AbstractCSSModelAdapter implements ICSSModelAdapter {
+	private final static String CSS_ID = ContentTypeIdForCSS.ContentTypeID_CSS;
+
+	private Element element = null;
+	private ICSSModel model = null;
+
+	/**
+	 */
+	AbstractCSSModelAdapter() {
+		super();
+	}
+
+	/**
+	 */
+	protected ICSSModel createModel() {
+		// create embedded CSS model (not for external CSS)
+		if (getElement() == null)
+			return null;
+		IStructuredModel baseModel = ((IDOMNode) getElement()).getModel();
+		ICSSModel newModel = (ICSSModel) baseModel.getModelManager().createUnManagedStructuredModelFor(CSS_ID);
+		((CSSModelImpl) newModel).setOwnerDOMNode(getElement());
+		return newModel;
+	}
+
+	/**
+	 */
+	public Element getElement() {
+		return this.element;
+	}
+
+	/**
+	 */
+	protected ICSSModel getExistingModel() {
+		return this.model;
+	}
+
+	/**
+	 */
+	protected void notifyStyleChanged(Element target) {
+		INodeNotifier notifier = (INodeNotifier) target;
+		if (notifier == null)
+			return;
+		Collection adapters = notifier.getAdapters();
+		if (adapters == null)
+			return;
+		Iterator it = adapters.iterator();
+		if (it == null)
+			return;
+		while (it.hasNext()) {
+			INodeAdapter adapter = (INodeAdapter) it.next();
+			if (adapter instanceof StyleListener) {
+				StyleListener listener = (StyleListener) adapter;
+				listener.styleChanged();
+			}
+		}
+	}
+
+	/**
+	 */
+	void setElement(Element element) {
+		this.element = element;
+	}
+
+	/**
+	 * check 
+	 * 1. If attributes of element is valid (type,rel ...)
+	 * 2. If content model supports this element / attribute (future ?)
+	 */
+	protected boolean isValidAttribute() {
+		return (getElement() != null);
+	}
+
+	/**
+	 */
+	protected void setModel(ICSSModel model) {
+		this.model = model;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/htmlcss/AbstractStyleSheetAdapter.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/htmlcss/AbstractStyleSheetAdapter.java
new file mode 100644
index 0000000..9051483
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/htmlcss/AbstractStyleSheetAdapter.java
@@ -0,0 +1,249 @@
+/*******************************************************************************
+ * Copyright (c) 2004-2006 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
+ *     
+ * 		Masaki Saitoh (MSAITOH@jp.ibm.com)
+ *		See Bug 153000  Style Adapters should be lazier
+ *		https://bugs.eclipse.org/bugs/show_bug.cgi?id=153000
+ *
+ ********************************************************************************/
+package org.eclipse.wst.html.core.internal.htmlcss;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+
+import org.eclipse.wst.css.core.internal.event.ICSSStyleListener;
+import org.eclipse.wst.css.core.internal.provisional.adapters.IModelProvideAdapter;
+import org.eclipse.wst.css.core.internal.provisional.adapters.IStyleSheetAdapter;
+import org.eclipse.wst.css.core.internal.provisional.document.ICSSModel;
+import org.eclipse.wst.css.core.internal.provisional.document.ICSSNode;
+import org.eclipse.wst.css.core.internal.provisional.document.ICSSSelector;
+import org.eclipse.wst.css.core.internal.util.ImportedCollector;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapter;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.xml.core.internal.document.XMLModelNotifier;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.stylesheets.DocumentStyle;
+import org.w3c.dom.stylesheets.StyleSheet;
+import org.w3c.dom.stylesheets.StyleSheetList;
+import org.w3c.dom.traversal.DocumentTraversal;
+import org.w3c.dom.traversal.NodeFilter;
+import org.w3c.dom.traversal.NodeIterator;
+
+/**
+ */
+public abstract class AbstractStyleSheetAdapter extends AbstractCSSModelAdapter implements ICSSStyleListener, IStyleSheetAdapter {
+
+	// this variable to hold the class is just a VAJava trick.
+	// it improves performance in VAJava by minimizing class loading.
+	private final Class StyleSheetAdapterClass = IStyleSheetAdapter.class;
+	private Collection styleChangedNodes;
+
+	/**
+	 */
+	protected AbstractStyleSheetAdapter() {
+		super();
+	}
+
+	/**
+	 */
+	protected ICSSModel createModel() {
+		return createModel(true);
+	}
+
+	/**
+	 */
+	protected ICSSModel createModel(boolean notify) {
+		ICSSModel newModel = super.createModel();
+		if (notify && newModel != null) {
+			// get ModelProvideAdapter
+			IModelProvideAdapter adapter = (IModelProvideAdapter) ((INodeNotifier) getElement()).getAdapterFor(IModelProvideAdapter.class);
+			// notify adapter
+			if (adapter != null)
+				adapter.modelProvided(newModel);
+		}
+		return newModel;
+	}
+
+	/**
+	 */
+	public StyleSheet getSheet() {
+		ICSSModel model = getModel();
+		if (model == null)
+			return null;
+		return (StyleSheet) model.getDocument();
+	}
+
+	/**
+	 * Allowing the INodeAdapter to compare itself against the type
+	 * allows it to return true in more than one case.
+	 */
+	public boolean isAdapterForType(Object type) {
+		return (type == StyleSheetAdapterClass);
+	}
+
+	/**
+	 */
+	public void released() {
+		ICSSModel currentModel = getModel();
+
+		// get ModelProvideAdapter
+		IModelProvideAdapter adapter = (IModelProvideAdapter) ((INodeNotifier) getElement()).getAdapterFor(IModelProvideAdapter.class);
+
+		setElement(null);
+		setModel(null);
+
+		if (adapter != null)
+			adapter.modelReleased(currentModel);
+
+		if (currentModel != null)
+			currentModel.releaseFromRead();
+	}
+
+	/**
+	 */
+	public void removed() {
+		ICSSModel currentModel = getModel();
+
+		setModel(null);
+
+		// get ModelProvideAdapter
+		IModelProvideAdapter adapter = (IModelProvideAdapter) ((INodeNotifier) getElement()).getAdapterFor(IModelProvideAdapter.class);
+		if (adapter != null)
+			adapter.modelRemoved(currentModel);
+
+		if (currentModel != null)
+			currentModel.releaseFromRead();
+	}
+
+	/**
+	 * @param srcModel com.ibm.sed.css.model.interfaces.ICSSModel
+	 * @param removed com.ibm.sed.css.model.interfaces.ICSSSelector[]
+	 * @param added com.ibm.sed.css.model.interfaces.ICSSSelector[]
+	 * @param media java.lang.String
+	 */
+	public void styleChanged(ICSSModel srcModel, ICSSSelector[] removed, ICSSSelector[] added, String media) {
+		Element element = getElement();
+		if (element == null)
+			return; // might released
+		Document doc = element.getOwnerDocument();
+		if (doc == null)
+			return; // error
+
+		// to notify GEF tree 
+		if (doc instanceof INodeNotifier) {
+			Collection adapters = ((INodeNotifier) doc).getAdapters();
+			if (adapters == null)
+				return;
+			Iterator it = adapters.iterator();
+			if (it == null)
+				return;
+			while (it.hasNext()) {
+				INodeAdapter adapter = (INodeAdapter) it.next();
+				if (adapter instanceof ICSSStyleListener) {
+					((ICSSStyleListener) adapter).styleChanged(srcModel, removed, added, media);
+				}
+			}
+		}
+		//
+
+		if (styleChangedNodes == null) {
+			styleChangedNodes = new HashSet();
+		}
+
+		try {
+			int removedSelNum = removed != null ? removed.length : 0;
+			int addedSelNum = added != null ? added.length : 0;
+
+			NodeIterator iter = ((DocumentTraversal) doc).createNodeIterator(doc, NodeFilter.SHOW_ELEMENT, null, true);
+			Node node;
+			while ((node = iter.nextNode()) != null) {
+				if (node.getNodeType() == Node.ELEMENT_NODE) {
+					Element elm = (Element) node;
+					boolean match = false;
+					int i;
+					for (i = 0; i < removedSelNum && !match; i++) {
+						match = removed[i].match(elm, null);
+					}
+					for (i = 0; i < addedSelNum && !match; i++) {
+						match = added[i].match(elm, null);
+					}
+					if (match) {
+						if (!styleChangedNodes.contains(elm))
+							styleChangedNodes.add(elm);
+						// notifyStyleChanged(elm);
+					}
+				}
+			}
+		}
+		catch (ClassCastException ex) {
+			// Document doesn't implement DocumentTraversal...
+		}
+
+	}
+
+	/**
+	 * @param srcModel com.ibm.sed.css.model.interfaces.ICSSModel
+	 */
+	public void styleUpdate(ICSSModel srcModel) {
+		IDOMNode node = (IDOMNode) getElement();
+		if (node == null)
+			return;
+		IDOMModel model = node.getModel();
+		if (model == null)
+			return;
+		XMLModelNotifier notifier = model.getModelNotifier();
+		if (notifier == null)
+			return;
+
+		// before updating, all sub-models should be loaded!
+		DocumentStyle document = (DocumentStyle) model.getDocument();
+		StyleSheetList styles = document.getStyleSheets();
+		if (styles != null) {
+			int n = styles.getLength();
+			ImportedCollector trav = new ImportedCollector();
+			for (int i = 0; i < n; i++) {
+				org.w3c.dom.stylesheets.StyleSheet sheet = styles.item(i);
+				if (sheet instanceof ICSSNode)
+					trav.apply((ICSSNode) sheet);
+			}
+		}
+
+		// flash style changed events
+		if (styleChangedNodes != null) {
+			Object[] elements = styleChangedNodes.toArray();
+			for (int i = 0; elements != null && i < elements.length; i++)
+				notifyStyleChanged((Element) elements[i]);
+			styleChangedNodes.clear();
+		}
+
+		// to notify GEF tree 
+		if (document instanceof INodeNotifier) {
+			Collection adapters = ((INodeNotifier) document).getAdapters();
+			if (adapters == null)
+				return;
+			Iterator it = adapters.iterator();
+			if (it == null)
+				return;
+			while (it.hasNext()) {
+				INodeAdapter adapter = (INodeAdapter) it.next();
+				if (adapter instanceof ICSSStyleListener) {
+					((ICSSStyleListener) adapter).styleUpdate(srcModel);
+				}
+			}
+		}
+
+		notifier.propertyChanged(node);
+	}
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/htmlcss/CSSQueryContext.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/htmlcss/CSSQueryContext.java
new file mode 100644
index 0000000..1e98f23
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/htmlcss/CSSQueryContext.java
@@ -0,0 +1,137 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.htmlcss;
+
+
+
+import java.util.Enumeration;
+
+import org.eclipse.wst.css.core.internal.contentmodel.PropCMProperty;
+import org.eclipse.wst.css.core.internal.provisional.document.ICSSStyleDeclItem;
+import org.eclipse.wst.css.core.internal.provisional.document.ICSSStyleDeclaration;
+import org.eclipse.wst.css.core.internal.provisional.document.ICSSValue;
+import org.eclipse.wst.css.core.internal.util.CSSLinkConverter;
+import org.eclipse.wst.css.core.internal.util.declaration.CSSPropertyContext;
+
+/**
+ */
+class CSSQueryContext extends CSSPropertyContext {
+
+	/**
+	 */
+	public CSSQueryContext() {
+		super();
+	}
+
+	/**
+	 */
+	public CSSQueryContext(ICSSStyleDeclaration decl) {
+		super(decl);
+	}
+
+	/**
+	 *
+	 */
+	public void applyFull(ICSSStyleDeclaration decl) {
+		if (decl == null)
+			return;
+		Enumeration keys = fProperties.keys();
+		while (keys.hasMoreElements()) {
+			Object key = keys.nextElement();
+			Object val = fProperties.get(key);
+
+			if (val instanceof CSSQueryDeclarationData) {
+				ICSSStyleDeclItem declItem = ((CSSQueryDeclarationData) val).getDeclItem();
+				if (declItem.getLength() <= 0) {
+					ICSSStyleDeclItem itemToRemove = decl.getDeclItemNode(key.toString());
+					if (itemToRemove != null) {
+						decl.removeDeclItemNode(itemToRemove);
+					}
+				}
+				else {
+					decl.setDeclItemNode(declItem);
+				}
+			}
+			else {
+				String value = (val instanceof ICSSValue) ? ((ICSSValue) val).getCSSValueText() : val.toString();
+
+				if (value == null || value.length() <= 0) {
+					ICSSStyleDeclItem itemToRemove = decl.getDeclItemNode(key.toString());
+					if (itemToRemove != null) {
+						decl.removeDeclItemNode(itemToRemove);
+					}
+				}
+				else {
+					decl.setProperty(key.toString(), value, null);
+				}
+			}
+		}
+	}
+
+	/**
+	 */
+	private boolean check(String propName, boolean important, int specificity) {
+		Object current = fProperties.get(propName);
+		if (current != null && current instanceof CSSQueryValueData) {
+			CSSQueryValueData currentValue = (CSSQueryValueData) current;
+			if ((!important && currentValue.important) || (currentValue.getSpecificity() > specificity)) {
+				return false;
+			}
+		}
+		return true;
+	}
+
+	/**
+	 */
+	public void overrideWithExpand(ICSSStyleDeclaration decl, int specificity) {
+		if (decl == null)
+			return;
+
+		CSSLinkConverter conv = new CSSLinkConverter(decl.getOwnerDocument().getModel());
+
+		int nProperties = decl.getLength();
+		for (int i = 0; i < nProperties; i++) {
+			String propName = decl.item(i);
+			if (propName != null) {
+				String propN = propName.trim().toLowerCase();
+				if (propN.length() != 0) {
+					PropCMProperty prop = PropCMProperty.getInstanceOf(propN);
+					String priority = decl.getPropertyPriority(propName);
+					boolean important = priority != null && priority.length() > 0;
+					if (prop != null && prop.isShorthand()) {
+						// expand shorthand property
+						CSSQueryContext context = new CSSQueryContext();
+						expandToLeaf(prop, decl.getPropertyValue(propName), context);
+
+						Enumeration properties = context.properties();
+						while (properties.hasMoreElements()) {
+							propN = properties.nextElement().toString();
+							if (check(propN, important, specificity)) {
+								fProperties.put(propN, new CSSQueryValueData(conv.toAbsolute(context.get(propN)), important, specificity));
+							}
+						}
+					}
+					else {
+						if (check(propN, important, specificity)) {
+							ICSSStyleDeclItem declItem = (ICSSStyleDeclItem) decl.getDeclItemNode(propName).cloneNode(true);
+							int nValues = declItem.getLength();
+							for (int j = 0; j < nValues; j++) {
+								conv.toAbsolute(declItem.item(j));
+							}
+							declItem.setPriority(null);
+							fProperties.put(propN, new CSSQueryDeclarationData(declItem, important, specificity));
+						}
+					}
+				}
+			}
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/htmlcss/CSSQueryDeclarationData.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/htmlcss/CSSQueryDeclarationData.java
new file mode 100644
index 0000000..4f6125d
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/htmlcss/CSSQueryDeclarationData.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.htmlcss;
+
+import org.eclipse.wst.css.core.internal.provisional.document.ICSSStyleDeclItem;
+
+
+
+/**
+ */
+public class CSSQueryDeclarationData extends CSSQueryValueData {
+
+
+	ICSSStyleDeclItem declItem;
+
+	public CSSQueryDeclarationData(ICSSStyleDeclItem declItem, boolean imp, int specificity) {
+		super(null, imp, specificity);
+		this.declItem = declItem;
+	}
+
+	/**
+	 */
+	ICSSStyleDeclItem getDeclItem() {
+		return declItem;
+	}
+
+	/**
+	 */
+	public String toString() {
+		if (value == null && declItem != null) {
+			value = declItem.getCSSValueText();
+		}
+		return value;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/htmlcss/CSSQueryTraverser.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/htmlcss/CSSQueryTraverser.java
new file mode 100644
index 0000000..860610a
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/htmlcss/CSSQueryTraverser.java
@@ -0,0 +1,115 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.htmlcss;
+
+
+
+import org.eclipse.wst.css.core.internal.provisional.document.ICSSNode;
+import org.eclipse.wst.css.core.internal.provisional.document.ICSSSelector;
+import org.eclipse.wst.css.core.internal.provisional.document.ICSSSelectorList;
+import org.eclipse.wst.css.core.internal.provisional.document.ICSSStyleDeclaration;
+import org.eclipse.wst.css.core.internal.provisional.document.ICSSStyleRule;
+import org.eclipse.wst.css.core.internal.util.AbstractCssTraverser;
+import org.eclipse.wst.css.core.internal.util.CSSStyleDeclarationFactory;
+import org.w3c.dom.Element;
+import org.w3c.dom.css.ElementCSSInlineStyle;
+
+/**
+ */
+public class CSSQueryTraverser extends AbstractCssTraverser {
+
+	private Element element;
+	private String pseudoName;
+	private CSSQueryContext context = null;
+	ICSSStyleDeclaration decl = null;
+
+	/**
+	 */
+	public ICSSStyleDeclaration getDeclaration() {
+		try {
+			ICSSStyleDeclaration inlineStyle = (ICSSStyleDeclaration) ((ElementCSSInlineStyle) element).getStyle();
+			if (inlineStyle != null) {
+				if (context == null) {
+					context = new CSSQueryContext();
+				}
+				context.overrideWithExpand(inlineStyle, 10000);
+				// style attribute's specificity is 100 (in CSS2 spec.) and
+				// our implement use 100 as base number (see CSSSelector.java)
+			}
+		}
+		catch (ClassCastException ex) {
+			// element is not ElementCSSInlineStyle ???
+		}
+		if (context == null)
+			return null;
+
+		if (decl == null)
+			decl = CSSStyleDeclarationFactory.getInstance().createStyleDeclaration();
+		context.applyFull(decl);
+		return decl;
+	}
+
+	/**
+	 */
+	private void overwriteDeclaration(ICSSStyleDeclaration d, int specificity) {
+		if (d == null)
+			return;
+		if (context == null)
+			context = new CSSQueryContext();
+		context.overrideWithExpand(d, specificity);
+	}
+
+	/**
+	 */
+	protected short postNode(ICSSNode node) {
+		return TRAV_CONT;
+	}
+
+	/**
+	 */
+	protected short preNode(ICSSNode node) {
+		if (node instanceof ICSSStyleRule) {
+			// style rule
+			ICSSStyleRule style = (ICSSStyleRule) node;
+			ICSSSelectorList list = style.getSelectors();
+			int nSelectors = list.getLength();
+			int maxSpecificity = -1;
+			for (int iSelector = 0; iSelector < nSelectors; iSelector++) {
+				// Check each Selector Lists
+				ICSSSelector selector = list.getSelector(iSelector);
+				int specificity = selector.getSpecificity();
+				if (maxSpecificity < specificity && selector.match(element, pseudoName)) {
+					maxSpecificity = specificity;
+				}
+			}
+			if (maxSpecificity >= 0) {
+				// apply this style to the element
+				overwriteDeclaration((ICSSStyleDeclaration) style.getStyle(), maxSpecificity);
+			}
+			return TRAV_PRUNE;
+		}
+		return TRAV_CONT;
+	}
+
+	/**
+	 */
+	private void resetContext() {
+		context = null;
+	}
+
+	/**
+	 */
+	public void setElement(Element element, String pseudoName) {
+		this.element = element;
+		this.pseudoName = pseudoName;
+		resetContext();
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/htmlcss/CSSQueryValueData.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/htmlcss/CSSQueryValueData.java
new file mode 100644
index 0000000..6198156
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/htmlcss/CSSQueryValueData.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.htmlcss;
+
+import org.eclipse.wst.css.core.internal.util.declaration.ValueData;
+
+
+
+/**
+ */
+class CSSQueryValueData extends ValueData {
+
+	private int specificity;
+
+	/**
+	 */
+	public CSSQueryValueData() {
+		super();
+	}
+
+	/**
+	 */
+	public CSSQueryValueData(String val, boolean imp) {
+		super(val, imp);
+	}
+
+	/**
+	 */
+	public CSSQueryValueData(String val, boolean imp, int specificity) {
+		super(val, imp);
+		this.specificity = specificity;
+	}
+
+	/**
+	 */
+	int getSpecificity() {
+		return specificity;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/htmlcss/HTMLDocumentAdapter.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/htmlcss/HTMLDocumentAdapter.java
new file mode 100644
index 0000000..49eb7ff
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/htmlcss/HTMLDocumentAdapter.java
@@ -0,0 +1,418 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.htmlcss;
+
+
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+import org.eclipse.wst.css.core.internal.provisional.adapters.IStyleSheetAdapter;
+import org.eclipse.wst.css.core.internal.provisional.adapters.IStyleSheetListAdapter;
+import org.eclipse.wst.css.core.internal.provisional.document.ICSSImportRule;
+import org.eclipse.wst.css.core.internal.provisional.document.ICSSModel;
+import org.eclipse.wst.css.core.internal.provisional.document.ICSSNode;
+import org.eclipse.wst.css.core.internal.util.CSSClassTraverser;
+import org.eclipse.wst.css.core.internal.util.ImportRuleCollector;
+import org.eclipse.wst.html.core.internal.contentmodel.JSP11Namespace;
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapter;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.css.CSSStyleDeclaration;
+import org.w3c.dom.stylesheets.StyleSheet;
+import org.w3c.dom.stylesheets.StyleSheetList;
+
+
+
+/**
+ */
+public class HTMLDocumentAdapter implements IStyleSheetListAdapter, StyleSheetList {
+
+	private Document document = null;
+	private Vector styleAdapters = null;
+	private Vector oldStyleAdapters = null;
+
+	/**
+	 */
+	HTMLDocumentAdapter() {
+		super();
+	}
+
+	/**
+	 */
+	private void addStyleSheet(Element node) {
+		IDOMElement element = (IDOMElement) node;
+		String tagName = element.getTagName();
+		if (tagName == null)
+			return;
+		boolean isContainer = false;
+		if (tagName.equalsIgnoreCase(HTML40Namespace.ElementName.HTML) || tagName.equalsIgnoreCase(HTML40Namespace.ElementName.HEAD) || tagName.equalsIgnoreCase(HTML40Namespace.ElementName.NOSCRIPT) || tagName.equalsIgnoreCase(HTML40Namespace.ElementName.BASE) || tagName.equalsIgnoreCase(JSP11Namespace.ElementName.ROOT) || (!element.isGlobalTag() && element.isContainer())) {
+			isContainer = true;
+		}
+		else if (element.isCommentTag()) {
+			Node parent = element.getParentNode();
+			if (parent == element.getOwnerDocument()) {
+				// This condition is too severe, actually do not work for JSF template.
+				// But above (! globalTag() && isContainer()) cover JSF template + tpl template
+				isContainer = true;
+			}
+			else if (parent.getNodeType() == Node.ELEMENT_NODE) {
+				tagName = ((Element) parent).getTagName();
+				if (tagName != null && tagName.equalsIgnoreCase(HTML40Namespace.ElementName.HEAD)) {
+					isContainer = true;
+				}
+			}
+		}
+
+		else {
+			String localName = element.getLocalName();
+			if (localName != null && localName.equalsIgnoreCase(HTML40Namespace.ElementName.HTML)) {
+				// taglib html tag
+				isContainer = true;
+			}
+			else {
+				INodeNotifier notifier = element;
+				INodeAdapter adapter = notifier.getAdapterFor(IStyleSheetAdapter.class);
+				if (adapter != null && adapter instanceof IStyleSheetAdapter) {
+					this.styleAdapters.addElement(adapter);
+				}
+			}
+		}
+		if (isContainer) {
+			INodeNotifier notifier = element;
+			if (notifier.getExistingAdapter(IStyleSheetListAdapter.class) == null) {
+				notifier.addAdapter(this);
+			}
+			for (Node child = element.getFirstChild(); child != null; child = child.getNextSibling()) {
+				if (child.getNodeType() != Node.ELEMENT_NODE)
+					continue;
+				addStyleSheet((Element) child);
+			}
+		}
+	}
+
+	/**
+	 */
+	void childReplaced() {
+		if (this.styleAdapters == null)
+			return;
+
+		// backup old adapters to be released on updating in getStyleSheets()
+		this.oldStyleAdapters = this.styleAdapters;
+		// invalidate the list
+		this.styleAdapters = null;
+
+		notifyStyleSheetsChanged(this.document);
+	}
+
+	/**
+	 */
+	public Enumeration getClasses() {
+		StyleSheetList sheetList = getStyleSheets();
+		int nSheets = sheetList.getLength();
+
+		final ArrayList classes = new ArrayList();
+
+		CSSClassTraverser traverser = new CSSClassTraverser();
+		traverser.setTraverseImported(true);
+
+		for (int i = 0; i < nSheets; i++) {
+			org.w3c.dom.stylesheets.StyleSheet sheet = sheetList.item(i);
+			if (sheet instanceof ICSSNode) {
+				traverser.apply((ICSSNode) sheet);
+			}
+		}
+		classes.addAll(traverser.getClassNames());
+
+		return new Enumeration() {
+			int i = 0;
+
+			public boolean hasMoreElements() {
+				return i < classes.size();
+			}
+
+			public Object nextElement() {
+				return classes.get(i++);
+			}
+		};
+	}
+
+	/**
+	 */
+	private List getValidAdapters() {
+		Vector validAdapters = new Vector();
+		if (this.styleAdapters != null) {
+			Iterator i = this.styleAdapters.iterator();
+			while (i.hasNext()) {
+				Object obj = i.next();
+				if (obj instanceof AbstractStyleSheetAdapter && ((AbstractStyleSheetAdapter) obj).isValidAttribute()) {
+					validAdapters.add(obj);
+				}
+			}
+		}
+		return validAdapters;
+	}
+
+	/**
+	 */
+	public int getLength() {
+		return getValidAdapters().size();
+	}
+
+	/**
+	 */
+	public CSSStyleDeclaration getOverrideStyle(Element element, String pseudoName) {
+		StyleSheetList ssl = getStyleSheets();
+		int numStyles = ssl.getLength();
+
+		CSSQueryTraverser query = new CSSQueryTraverser();
+		query.setTraverseImported(true);
+		query.setTraverseImportFirst(true);
+		query.setElement(element, pseudoName);
+
+		for (int i = 0; i < numStyles; i++) {
+			// loop for styles (<style> and <link>)
+			org.w3c.dom.stylesheets.StyleSheet ss = ssl.item(i);
+
+			try {
+				query.apply((ICSSNode) ss);
+			}
+			catch (ClassCastException ex) {
+				// I can handle only CSS style
+			}
+		}
+
+		return query.getDeclaration();
+	}
+
+	/**
+	 */
+	public StyleSheetList getStyleSheets() {
+		if (this.styleAdapters == null) {
+			if (this.document == null)
+				return null;
+
+			this.styleAdapters = new Vector();
+			for (Node child = this.document.getFirstChild(); child != null; child = child.getNextSibling()) {
+				if (child.getNodeType() != Node.ELEMENT_NODE)
+					continue;
+				addStyleSheet((Element) child);
+			}
+
+			removeOldStyleSheets();
+		}
+		return this;
+	}
+
+	/**
+	 * Allowing the INodeAdapter to compare itself against the type
+	 * allows it to return true in more than one case.
+	 */
+	public boolean isAdapterForType(Object type) {
+		return (type == IStyleSheetListAdapter.class);
+	}
+
+	/**
+	 */
+	public StyleSheet item(int index) {
+		if (this.styleAdapters == null)
+			return null;
+
+		List validAdapters = getValidAdapters();
+
+		if (index < 0 || index >= validAdapters.size())
+			return null;
+		StyleSheet sheet = ((IStyleSheetAdapter) validAdapters.get(index)).getSheet();
+		if (sheet == null) {// for LINK element whose link is broken
+			ICSSModel model = ((AbstractStyleSheetAdapter) validAdapters.get(index)).createModel();
+			sheet = ((model != null) ? (StyleSheet) model.getDocument() : null);
+		}
+		return sheet;
+	}
+
+	/**
+	 */
+	public void notifyChanged(INodeNotifier notifier, int eventType, Object changedFeature, Object oldValue, Object newValue, int pos) {
+		Node node = null;
+		switch (eventType) {
+			case INodeNotifier.ADD :
+				if (newValue instanceof Node)
+					node = (Node) newValue;
+				else if (changedFeature instanceof Attr)
+					node = ((Attr) changedFeature);
+				break;
+			case INodeNotifier.REMOVE :
+				if (oldValue instanceof Node)
+					node = (Node) oldValue;
+				else if (changedFeature instanceof Attr)
+					node = ((Attr) changedFeature);
+				break;
+			case INodeNotifier.CHANGE :
+				node = (Node) notifier;
+				break;
+			default :
+				break;
+		}
+		
+		if (node == null)
+			return;
+		
+		switch(node.getNodeType()) {
+			case Node.ELEMENT_NODE: {
+				IDOMElement element = (IDOMElement) node;
+				String tagName = element.getTagName();
+				if (tagName == null)
+					return;
+
+				if (eventType == INodeNotifier.CHANGE) {
+					if (tagName.equalsIgnoreCase(HTML40Namespace.ElementName.BASE)) {
+						refreshAdapters();
+					}
+				}
+				else {
+					if (tagName.equalsIgnoreCase(HTML40Namespace.ElementName.HTML) || tagName.equalsIgnoreCase(HTML40Namespace.ElementName.HEAD) || tagName.equalsIgnoreCase(HTML40Namespace.ElementName.STYLE) || tagName.equalsIgnoreCase(HTML40Namespace.ElementName.LINK) || tagName.equalsIgnoreCase(HTML40Namespace.ElementName.NOSCRIPT) || tagName.equalsIgnoreCase(JSP11Namespace.ElementName.ROOT) || element.isCommentTag() || (!element.isGlobalTag() && element.isContainer())) {
+						childReplaced();
+					}
+					else if (tagName.equalsIgnoreCase(HTML40Namespace.ElementName.BASE)) {
+						refreshAdapters();
+					}
+					else {
+						String localName = element.getLocalName();
+						if (localName != null && localName.equalsIgnoreCase(HTML40Namespace.ElementName.HTML)) {
+							// taglib html tag
+							childReplaced();
+						}
+					}
+				}
+				break;
+			}
+			case Node.ATTRIBUTE_NODE : {
+				if (HTML40Namespace.ElementName.BASE.equals(((Attr) node).getOwnerElement().getLocalName())) {
+					refreshAdapters();
+				}
+			}
+		}
+		
+	}
+
+	/**
+	 * reload LINK / @import if BASE changed
+	 */
+	private void refreshAdapters() {
+		Iterator iAdapter = this.styleAdapters.iterator();
+		while (iAdapter.hasNext()) {
+			Object adapter = iAdapter.next();
+			if (adapter instanceof LinkElementAdapter) {
+				((LinkElementAdapter) adapter).refreshSheet();
+			}
+			else if (adapter instanceof StyleElementAdapter) {
+				ICSSModel model = ((StyleElementAdapter) adapter).getModel();
+				ImportRuleCollector trav = new ImportRuleCollector();
+				trav.apply(model);
+				Iterator iRule = trav.getRules().iterator();
+				while (iRule.hasNext()) {
+					ICSSImportRule rule = (ICSSImportRule) iRule.next();
+					rule.refreshStyleSheet();
+				}
+			}
+		}
+	}
+
+	/**
+	 */
+	private void notifyStyleSheetsChanged(Document target) {
+		INodeNotifier notifier = (INodeNotifier) target;
+		if (notifier == null)
+			return;
+		Collection adapters = notifier.getAdapters();
+		if (adapters == null)
+			return;
+		Iterator it = adapters.iterator();
+		if (it == null)
+			return;
+		while (it.hasNext()) {
+			INodeAdapter adapter = (INodeAdapter) it.next();
+			if (adapter instanceof StyleListener) {
+				StyleListener listener = (StyleListener) adapter;
+				listener.styleChanged();
+			}
+		}
+	}
+
+	/**
+	 */
+	private void releaseOldStyleSheets() {
+		if (this.oldStyleAdapters == null)
+			return;
+		Iterator it = this.oldStyleAdapters.iterator();
+		while (it.hasNext()) {
+			IStyleSheetAdapter adapter = (IStyleSheetAdapter) it.next();
+			if (adapter == null)
+				continue;
+			// if the same adapter is in the current list,
+			// do not release
+			if (this.styleAdapters != null && this.styleAdapters.contains(adapter))
+				continue;
+			adapter.released();
+		}
+		this.oldStyleAdapters = null;
+	}
+
+	/**
+	 */
+	public void releaseStyleSheets() {
+		releaseOldStyleSheets();
+
+		if (this.styleAdapters == null)
+			return;
+		Iterator it = this.styleAdapters.iterator();
+		while (it.hasNext()) {
+			IStyleSheetAdapter adapter = (IStyleSheetAdapter) it.next();
+			if (adapter != null)
+				adapter.released();
+		}
+		this.styleAdapters = null;
+	}
+
+	/**
+	 */
+	private void removeOldStyleSheets() {
+		if (this.oldStyleAdapters == null)
+			return;
+		Iterator it = this.oldStyleAdapters.iterator();
+		while (it.hasNext()) {
+			IStyleSheetAdapter adapter = (IStyleSheetAdapter) it.next();
+			if (adapter == null)
+				continue;
+			// if the same adapter is in the current list,
+			// do not release
+			if (this.styleAdapters != null && this.styleAdapters.contains(adapter))
+				continue;
+			adapter.removed();
+		}
+		this.oldStyleAdapters = null;
+	}
+
+	/**
+	 */
+	void setDocument(Document document) {
+		this.document = document;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/htmlcss/HTMLStyleSelectorAdapter.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/htmlcss/HTMLStyleSelectorAdapter.java
new file mode 100644
index 0000000..cee65d1
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/htmlcss/HTMLStyleSelectorAdapter.java
@@ -0,0 +1,140 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.htmlcss;
+
+
+
+import org.eclipse.wst.css.core.internal.provisional.adapters.IStyleSelectorAdapter;
+import org.eclipse.wst.css.core.internal.provisional.document.ICSSSimpleSelector;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.w3c.dom.Element;
+
+import com.ibm.icu.util.StringTokenizer;
+
+/**
+ * Insert the type's description here.
+ */
+public class HTMLStyleSelectorAdapter implements IStyleSelectorAdapter {
+
+	static private HTMLStyleSelectorAdapter instance;
+	private Object toMatch = IStyleSelectorAdapter.class;
+
+	public synchronized static HTMLStyleSelectorAdapter getInstance() {
+		if (instance == null) {
+			instance = new HTMLStyleSelectorAdapter();
+		}
+		return instance;
+	}
+
+	public boolean isAdapterForType(Object type) {
+		return type == toMatch;
+	}
+
+	public boolean match(ICSSSimpleSelector selector, Element element, String pseudoName) {
+		if (element == null)
+			return false;
+		int i;
+		String key;
+
+		// PseudoName
+		i = selector.getNumOfPseudoNames();
+		if (i > 0) {
+			if (pseudoName == null || pseudoName.length() == 0)
+				return false;
+			for (i = i - 1; i >= 0; i--) {
+				if (pseudoName.equalsIgnoreCase(selector.getPseudoName(i))) {
+					break;
+				}
+			}
+			if (i < 0)
+				return false;
+		}
+
+		// check tag name
+		if (!selector.isUniversal() && !element.getNodeName().equalsIgnoreCase(selector.getName()))
+			return false;
+
+		// check id
+		i = selector.getNumOfIDs();
+		if (i > 0) {
+			if (i > 1)
+				return false;
+			if (!element.hasAttribute("id") || (key = element.getAttribute("id")).length() == 0)//$NON-NLS-1$ //$NON-NLS-2$
+				return false;
+			if (!selector.getID(0).equals(key))
+				return false;
+		}
+
+		// check class
+		i = selector.getNumOfClasses();
+		if (i > 0) {
+			if (!element.hasAttribute("class") || (key = element.getAttribute("class")).length() == 0) //$NON-NLS-1$  //$NON-NLS-2$
+				return false;
+			StringTokenizer tokenizer = new StringTokenizer(key);
+			for (i = i - 1; i >= 0; i--) {
+				boolean ok = false;
+				while (tokenizer.hasMoreTokens()) {
+					if (selector.getClass(i).equals(tokenizer.nextToken())) {
+						ok = true;
+						break;
+					}
+				}
+				if (!ok)
+					return false;
+			}
+		}
+
+		// check attributes
+		for (i = selector.getNumOfAttributes() - 1; i >= 0; i--) {
+			StringTokenizer tokenizer = new StringTokenizer(selector.getAttribute(i), "=~| \t\r\n\f");//$NON-NLS-1$
+			int countTokens = tokenizer.countTokens();
+			if (countTokens > 0) {
+				String attrName = tokenizer.nextToken();
+				String attrValue = null;
+				if (!element.hasAttribute(attrName) || (attrValue = element.getAttribute(attrName)).length() == 0)
+					return false;
+				if (countTokens > 1) {
+					String token = tokenizer.nextToken("= \t\r\n\f");//$NON-NLS-1$
+					StringTokenizer attrValueTokenizer = null;
+					if (token.equals("~")) {//$NON-NLS-1$
+						attrValueTokenizer = new StringTokenizer(attrValue);
+					}
+					else if (token.equals("|")) {//$NON-NLS-1$
+						attrValueTokenizer = new StringTokenizer(attrValue, "-");//$NON-NLS-1$
+					}
+					if (attrValueTokenizer != null) {
+						if (tokenizer.hasMoreTokens()) {
+							token = tokenizer.nextToken();
+							boolean ok = false;
+							while (attrValueTokenizer.hasMoreTokens()) {
+								if (token.equals(attrValueTokenizer.nextToken())) {
+									ok = true;
+									break;
+								}
+							}
+							if (!ok)
+								return false;
+						}
+					}
+					else {
+						if (!attrValue.equals(token))
+							return false;
+					}
+				}
+			}
+		}
+
+		return true;
+	}
+
+	public void notifyChanged(INodeNotifier notifier, int eventType, Object changedFeature, Object oldValue, Object newValue, int pos) {
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/htmlcss/HTMLStyleSelectorAdapterFactory.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/htmlcss/HTMLStyleSelectorAdapterFactory.java
new file mode 100644
index 0000000..57cd685
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/htmlcss/HTMLStyleSelectorAdapterFactory.java
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.htmlcss;
+
+
+
+import org.eclipse.wst.css.core.internal.provisional.adapters.IStyleSelectorAdapter;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapter;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapterFactory;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+
+/**
+ * Insert the type's description here.
+ */
+public class HTMLStyleSelectorAdapterFactory implements INodeAdapterFactory {
+
+	private static HTMLStyleSelectorAdapterFactory instance;
+	private Object toMatch = IStyleSelectorAdapter.class;
+
+	/**
+	 * CSSModelProvideAdapterFactory constructor comment.
+	 */
+	public HTMLStyleSelectorAdapterFactory() {
+		super();
+	}
+
+	/**
+	 * Method that returns the adapter associated with the given object.
+	 * It may be a singleton or not ... depending on the needs of the INodeAdapter  ...
+	 * but in general it is recommended for an adapter to be stateless, 
+	 * so the efficiencies of a singleton can be gained.
+	 *
+	 * The implementation of this method should call addAdapter on the adapted
+	 * object with the correct instance of the adapter.
+	 */
+	public INodeAdapter adapt(INodeNotifier notifier) {
+		INodeAdapter adapter = notifier.getExistingAdapter(IStyleSelectorAdapter.class);
+		if (adapter != null)
+			return adapter;
+		adapter = HTMLStyleSelectorAdapter.getInstance();
+		notifier.addAdapter(adapter);
+		return adapter;
+	}
+
+	public synchronized static HTMLStyleSelectorAdapterFactory getInstance() {
+		if (instance == null)
+			instance = new HTMLStyleSelectorAdapterFactory();
+		return instance;
+	}
+
+	/**
+	 * isFactoryForType method comment.
+	 */
+	public boolean isFactoryForType(Object type) {
+		return type == toMatch;
+	}
+
+	public void release() {
+		// default is to do nothing
+	}
+
+	/**
+	 * Overriding copy method
+	 */
+	public INodeAdapterFactory copy() {
+		return getInstance();
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/htmlcss/LinkElementAdapter.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/htmlcss/LinkElementAdapter.java
new file mode 100644
index 0000000..6113d4b
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/htmlcss/LinkElementAdapter.java
@@ -0,0 +1,273 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.htmlcss;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.wst.css.core.internal.provisional.adapters.IModelProvideAdapter;
+import org.eclipse.wst.css.core.internal.provisional.adapters.IStyleSheetListAdapter;
+import org.eclipse.wst.css.core.internal.provisional.contenttype.ContentTypeIdForCSS;
+import org.eclipse.wst.css.core.internal.provisional.document.ICSSModel;
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.util.URIResolver;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/**
+ */
+public class LinkElementAdapter extends AbstractStyleSheetAdapter {
+
+	private final static String CSS_ID = ContentTypeIdForCSS.ContentTypeID_CSS;
+	private boolean replaceModel = true;
+	// this variable to hold the class is just a VAJava trick.
+	// it improves performance in VAJava by minimizing class loading.
+	private final Class ModelProvideAdapterClass = IModelProvideAdapter.class;
+
+	/**
+	 */
+	protected LinkElementAdapter() {
+		super();
+	}
+
+	/**
+	 */
+	private void attrReplaced() {
+		this.replaceModel = true;
+
+		Element element = getElement();
+		if (element == null)
+			return; // error
+		Document document = element.getOwnerDocument();
+		if (document == null)
+			return; // error
+		INodeNotifier notifier = (INodeNotifier) document;
+		HTMLDocumentAdapter adapter = (HTMLDocumentAdapter) notifier.getAdapterFor(IStyleSheetListAdapter.class);
+		if (adapter == null)
+			return;
+		adapter.childReplaced();
+	}
+
+	protected ICSSModel createModel() {
+		// create phantom(broken link) external CSS model
+		if (getElement() == null)
+			return null;
+		IStructuredModel baseModel = ((IDOMNode) getElement()).getModel();
+		ICSSModel newModel = (ICSSModel) baseModel.getModelManager().createUnManagedStructuredModelFor(CSS_ID);
+
+		// calculate base location and set
+		// get resolver in Model
+		URIResolver resolver = baseModel.getResolver();
+
+		// resolve to absolute url : this need not exact location of css file. It is important that absurl is not null. 
+		String ref = getElement().getAttribute(HTML40Namespace.ATTR_NAME_HREF);
+		String absurl = (resolver != null && ref != null && ref.length() > 0) ? resolver.getLocationByURI(ref, true) : null;
+		if ((absurl == null) || (absurl.length() == 0)) {
+			IPath basePath = new Path(baseModel.getBaseLocation());
+			URLHelper helper = new URLHelper(basePath.removeLastSegments(1).toString());
+			absurl = helper.toAbsolute(ref == null ? "" : ref);//$NON-NLS-1$
+		}
+		if ((absurl == null) || (absurl.length() == 0)) {
+			absurl = ref;
+		}
+		if (absurl == null) {
+			absurl = "";//$NON-NLS-1$
+		}
+		newModel.setBaseLocation(absurl);
+
+		// set style listener
+		newModel.addStyleListener(this);
+
+		return newModel;
+	}
+
+	/**
+	 */
+	public ICSSModel getModel() {
+		ICSSModel model = getExistingModel();
+		if (this.replaceModel) {
+			ICSSModel oldModel = model;
+			try {
+				model = retrieveModel();
+				setModel(model);
+
+				// release old model
+				if (oldModel != null) {
+					// get ModelProvideAdapter
+					IModelProvideAdapter adapter = (IModelProvideAdapter) ((INodeNotifier) getElement()).getAdapterFor(IModelProvideAdapter.class);
+					if (adapter != null)
+						adapter.modelRemoved(oldModel);
+				}
+			}
+			finally {
+				if (oldModel != null)
+					oldModel.releaseFromRead();
+			}
+			this.replaceModel = false;
+		}
+		return model;
+	}
+
+	/**
+	 */
+	public void notifyChanged(INodeNotifier notifier, int eventType, Object changedFeature, Object oldValue, Object newValue, int pos) {
+		if (eventType != INodeNotifier.CHANGE)
+			return;
+		Attr attr = (Attr) changedFeature;
+		if (attr == null)
+			return;
+		String name = attr.getName();
+		if (name.equalsIgnoreCase("rel") || //$NON-NLS-1$
+					name.equalsIgnoreCase("type") || //$NON-NLS-1$	
+					name.equalsIgnoreCase("href")) {//$NON-NLS-1$
+			attrReplaced();
+		}
+	}
+
+	/**
+	 */
+	public void refreshSheet() {
+		if (!replaceModel) {
+			removed();
+			replaceModel = true;
+
+			IDOMNode node = (IDOMNode) getElement();
+			if (node != null) {
+				node.notify(INodeNotifier.CHANGE, getElement().getAttributeNode(org.eclipse.wst.html.core.internal.provisional.HTML40Namespace.ATTR_NAME_HREF), null, null, node.getStartOffset());
+			}
+		}
+	}
+
+	/**
+	 */
+	public void released() {
+		ICSSModel model = getExistingModel();
+		if (model != null) {
+			try {
+				// get ModelProvideAdapter
+				IModelProvideAdapter adapter = (IModelProvideAdapter) ((INodeNotifier) getElement()).getAdapterFor(IModelProvideAdapter.class);
+
+				// set element to null first, so that no document wide updates
+				setElement(null);
+				setModel(null);
+
+				if (adapter != null)
+					adapter.modelReleased(model);
+			}
+			finally {
+				model.releaseFromRead();
+			}
+		}
+		this.replaceModel = false;
+	}
+
+	/**
+	 */
+	public void removed() {
+		ICSSModel model = getExistingModel();
+		if (model != null) {
+			try {
+				setModel(null);
+
+				// get ModelProvideAdapter
+				IModelProvideAdapter adapter = (IModelProvideAdapter) ((INodeNotifier) getElement()).getAdapterFor(IModelProvideAdapter.class);
+				if (adapter != null)
+					adapter.modelRemoved(model);
+			}
+			finally {
+				model.releaseFromRead();
+			}
+		}
+		this.replaceModel = false;
+	}
+
+	/**
+	 */
+	protected boolean isValidAttribute() {
+		Element element = getElement();
+		if (element == null)
+			return false;
+		if (!element.hasAttribute("rel") || !"stylesheet".equalsIgnoreCase(element.getAttribute("rel")))//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+			return false;
+		if (element.hasAttribute("type") && !"text/css".equalsIgnoreCase(element.getAttribute("type")))//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+			return false;
+		if (!element.hasAttribute("href") || element.getAttribute("href").length() == 0) //$NON-NLS-1$ //$NON-NLS-2$
+			return false;
+		return true;
+	}
+
+	/**
+	 */
+	private ICSSModel retrieveModel() {
+		if (!isValidAttribute()) {
+			return null;
+		}
+
+		// null,attr check is done in isValidAttribute()
+		Element element = getElement();
+		String href = element.getAttribute("href");//$NON-NLS-1$
+
+		IDOMModel baseModel = ((IDOMNode) element).getModel();
+		if (baseModel == null)
+			return null;
+		Object id = baseModel.getId();
+		if (!(id instanceof String))
+			return null;
+		//String base = (String)id;
+
+		// get ModelProvideAdapter
+		IModelProvideAdapter adapter = (IModelProvideAdapter) ((INodeNotifier) getElement()).getAdapterFor(ModelProvideAdapterClass);
+
+		URLModelProvider provider = new URLModelProvider();
+		try {
+			IStructuredModel newModel = provider.getModelForRead(baseModel, href);
+			if (newModel == null)
+				return null;
+			if (!(newModel instanceof ICSSModel)) {
+				newModel.releaseFromRead();
+				return null;
+			}
+
+			// notify adapter
+			if (adapter != null)
+				adapter.modelProvided(newModel);
+
+			return (ICSSModel) newModel;
+		}
+		catch (UnsupportedEncodingException e) {
+		}
+		catch (IOException e) {
+		}
+
+		return null;
+	}
+
+	/**
+	 */
+	protected void setModel(ICSSModel model) {
+		ICSSModel oldModel = getExistingModel();
+		if (model == oldModel)
+			return;
+		super.setModel(model);
+		if (this.replaceModel)
+			this.replaceModel = false;
+		if (oldModel != null)
+			oldModel.removeStyleListener(this);
+		if (model != null)
+			model.addStyleListener(this);
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/htmlcss/StyleAdapterFactory.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/htmlcss/StyleAdapterFactory.java
new file mode 100644
index 0000000..922ee62
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/htmlcss/StyleAdapterFactory.java
@@ -0,0 +1,162 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.htmlcss;
+
+
+
+import org.eclipse.wst.css.core.internal.provisional.adapters.IStyleDeclarationAdapter;
+import org.eclipse.wst.css.core.internal.provisional.adapters.IStyleSheetAdapter;
+import org.eclipse.wst.css.core.internal.provisional.adapters.IStyleSheetListAdapter;
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapter;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapterFactory;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.modelquery.ModelQueryUtil;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+/**
+ */
+public class StyleAdapterFactory implements INodeAdapterFactory {
+
+	private static StyleAdapterFactory instance = null;
+
+	//	private static String CSS_CONTENT_TYPE = "text/css";//$NON-NLS-1$
+	/**
+	 */
+	private StyleAdapterFactory() {
+		super();
+	}
+
+	/**
+	 */
+	public INodeAdapter adapt(INodeNotifier notifier) {
+		if (notifier == null)
+			return null;
+
+		Node node = (Node) notifier;
+		short nodeType = node.getNodeType();
+		if (nodeType == Node.DOCUMENT_NODE) {
+			INodeAdapter adapter = notifier.getExistingAdapter(IStyleSheetListAdapter.class);
+			if (adapter != null)
+				return adapter;
+			HTMLDocumentAdapter newAdapter = new HTMLDocumentAdapter();
+			newAdapter.setDocument((Document) node);
+			notifier.addAdapter(newAdapter);
+			return newAdapter;
+		}
+		if (nodeType != Node.ELEMENT_NODE)
+			return null;
+
+		Element element = (Element) node;
+		String tagName = element.getTagName();
+		if (tagName.equalsIgnoreCase(HTML40Namespace.ElementName.STYLE)) {
+			if (!isTagAvailable(element.getOwnerDocument(), HTML40Namespace.ElementName.STYLE)) {
+				return null;
+			}
+			//		String type = element.getAttribute(HTML40Namespace.ATTR_NAME_TYPE);
+			//		if (type != null && ! type.equalsIgnoreCase(CSS_CONTENT_TYPE)) {
+			//			return null;
+			//		}
+			INodeAdapter adapter = notifier.getExistingAdapter(IStyleSheetAdapter.class);
+			if (adapter != null)
+				return adapter;
+			StyleElementAdapter newAdapter = new StyleElementAdapter();
+			newAdapter.setElement(element);
+			notifier.addAdapter(newAdapter);
+			return newAdapter;
+		}
+		else if (tagName.equalsIgnoreCase(HTML40Namespace.ElementName.LINK)) {
+			if (!isTagAvailable(element.getOwnerDocument(), HTML40Namespace.ElementName.LINK)) {
+				return null;
+			}
+			INodeAdapter adapter = notifier.getExistingAdapter(IStyleSheetAdapter.class);
+			if (adapter != null)
+				return adapter;
+			LinkElementAdapter newAdapter = new LinkElementAdapter();
+			newAdapter.setElement(element);
+			notifier.addAdapter(newAdapter);
+			return newAdapter;
+		}
+
+		INodeAdapter adapter = notifier.getExistingAdapter(IStyleDeclarationAdapter.class);
+		if (adapter != null)
+			return adapter;
+
+		if (!isAttributeAvailable(element, HTML40Namespace.ATTR_NAME_STYLE)) {
+			return null;
+		}
+		StyleAttrAdapter newAdapter = new StyleAttrAdapter();
+		newAdapter.setElement(element);
+		notifier.addAdapter(newAdapter);
+		return newAdapter;
+	}
+
+	/**
+	 */
+	public synchronized static StyleAdapterFactory getInstance() {
+		if (instance == null)
+			instance = new StyleAdapterFactory();
+		return instance;
+	}
+
+	/**
+	 */
+	public boolean isFactoryForType(Object type) {
+		return (type == IStyleSheetAdapter.class || type == IStyleDeclarationAdapter.class || type == IStyleSheetListAdapter.class);
+	}
+
+	public void release() {
+		// default is to do nothing
+	}
+
+	private static boolean isTagAvailable(Document document, String elementName) {
+		ModelQuery modelQuery = ModelQueryUtil.getModelQuery(document);
+		if (modelQuery != null) {
+			CMDocument cmdoc = modelQuery.getCorrespondingCMDocument(document);
+			CMNamedNodeMap map = cmdoc.getElements();
+			if ((CMElementDeclaration) map.getNamedItem(elementName) != null) {
+				return true;
+			}
+		}
+
+		return false;
+	}
+
+	private static boolean isAttributeAvailable(Element element, String attrName) {
+		ModelQuery modelQuery = ModelQueryUtil.getModelQuery(element.getOwnerDocument());
+		if (modelQuery != null) {
+			CMElementDeclaration decl = modelQuery.getCMElementDeclaration(element);
+			if (decl != null) {
+				CMNamedNodeMap map = decl.getAttributes();
+				if ((CMAttributeDeclaration) map.getNamedItem(attrName) != null) {
+					return true;
+				}
+			}
+		}
+
+		return false;
+	}
+
+	/**
+	 * Overriding Object's clone() method
+	 */
+	public INodeAdapterFactory copy() {
+		return getInstance();
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/htmlcss/StyleAttrAdapter.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/htmlcss/StyleAttrAdapter.java
new file mode 100644
index 0000000..a4d8c73
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/htmlcss/StyleAttrAdapter.java
@@ -0,0 +1,248 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.htmlcss;
+
+
+
+import org.eclipse.wst.css.core.internal.parser.CSSSourceParser;
+import org.eclipse.wst.css.core.internal.provisional.adapters.IStyleDeclarationAdapter;
+import org.eclipse.wst.css.core.internal.provisional.document.ICSSModel;
+import org.eclipse.wst.sse.core.internal.ltk.parser.RegionParser;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.sse.core.internal.provisional.events.IStructuredDocumentListener;
+import org.eclipse.wst.sse.core.internal.provisional.events.NewDocumentEvent;
+import org.eclipse.wst.sse.core.internal.provisional.events.NoChangeEvent;
+import org.eclipse.wst.sse.core.internal.provisional.events.RegionChangedEvent;
+import org.eclipse.wst.sse.core.internal.provisional.events.RegionsReplacedEvent;
+import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentRegionsReplacedEvent;
+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.IStructuredDocumentRegionList;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.css.CSSStyleDeclaration;
+
+/**
+ */
+public class StyleAttrAdapter extends AbstractCSSModelAdapter implements IStructuredDocumentListener, IStyleDeclarationAdapter {
+
+	private boolean ignoreNotification = false;
+	private final static String STYLE = "style";//$NON-NLS-1$
+
+	/**
+	 */
+	StyleAttrAdapter() {
+		super();
+	}
+
+	/**
+	 */
+	public ICSSModel getModel() {
+		ICSSModel model = getExistingModel();
+		if (model == null && isModelNecessary()) {
+			model = createModel();
+			if (model == null)
+				return null;
+			
+			IStructuredDocument structuredDocument = model.getStructuredDocument();
+			if (structuredDocument == null)
+				return null;
+
+			RegionParser parser = structuredDocument.getParser();
+			if (parser instanceof CSSSourceParser) {
+				((CSSSourceParser)parser).setParserMode(CSSSourceParser.MODE_DECLARATION);
+			} else {
+				return null;
+			}
+			
+			structuredDocument.addDocumentChangedListener(this);
+
+			setModel(model); // need to set before valueChanged()
+			valueChanged();
+		}
+		if (model != null && !isModelNecessary()) {
+			model = null;
+			valueChanged();
+		}
+		return model;
+	}
+
+	/**
+	 */
+	public CSSStyleDeclaration getStyle() {
+		ICSSModel model = getModel();
+		if (model == null)
+			return null;
+		return (CSSStyleDeclaration) model.getDocument();
+	}
+
+	/**
+	 * Allowing the INodeAdapter to compare itself against the type
+	 * allows it to return true in more than one case.
+	 */
+	public boolean isAdapterForType(Object type) {
+		return (type == IStyleDeclarationAdapter.class);
+	}
+
+	/**
+	 */
+	public void newModel(NewDocumentEvent event) {
+		if (event == null)
+			return;
+		if (event.getOriginalRequester() == this)
+			return;
+
+		setValue();
+	}
+
+	/**
+	 */
+	public void noChange(NoChangeEvent structuredDocumentEvent) {
+	}
+
+	/**
+	 */
+	public void nodesReplaced(StructuredDocumentRegionsReplacedEvent event) {
+		if (event == null)
+			return;
+		if (event.getOriginalRequester() == this)
+			return;
+
+		setValue();
+	}
+
+	/**
+	 */
+	public void notifyChanged(INodeNotifier notifier, int eventType, Object changedFeature, Object oldValue, Object newValue, int pos) {
+		if (this.ignoreNotification)
+			return;
+
+		if (eventType != INodeNotifier.CHANGE)
+			return;
+		Attr attr = (Attr) changedFeature;
+		if (attr == null)
+			return;
+		String name = attr.getName();
+		if (name.equalsIgnoreCase(STYLE)) {
+			valueChanged();
+		}
+	}
+
+	/**
+	 */
+	public void regionChanged(RegionChangedEvent event) {
+		if (event == null)
+			return;
+		if (event.getOriginalRequester() == this)
+			return;
+
+		setValue();
+	}
+
+	/**
+	 */
+	public void regionsReplaced(RegionsReplacedEvent event) {
+		if (event == null)
+			return;
+		if (event.getOriginalRequester() == this)
+			return;
+
+		setValue();
+	}
+
+	/**
+	 */
+	private void setValue() {
+		Element element = getElement();
+		if (element == null)
+			return;
+		ICSSModel model = getExistingModel();
+		if (model == null)
+			return;
+		IStructuredDocument structuredDocument = model.getStructuredDocument();
+		if (structuredDocument == null)
+			return;
+
+		String value = null;
+		IStructuredDocumentRegionList flatNodes = structuredDocument.getRegionList();
+		if (flatNodes != null) {
+			int count = flatNodes.getLength();
+			if (count > 0) {
+				StringBuffer buffer = new StringBuffer();
+				for (int i = 0; i < count; i++) {
+					IStructuredDocumentRegion flatNode = flatNodes.item(i);
+					if (flatNode == null)
+						continue;
+					buffer.append(flatNode.getText());
+				}
+				value = buffer.toString();
+			}
+		}
+
+		this.ignoreNotification = true;
+		if (value == null || value.length() == 0) {
+			element.removeAttribute(STYLE);
+		}
+		else {
+			Attr attr = element.getAttributeNode(STYLE);
+			if (attr != null) {
+				((IDOMNode) attr).setValueSource(value);
+			}
+			else {
+				Document document = element.getOwnerDocument();
+				attr = document.createAttribute(STYLE);
+				((IDOMNode) attr).setValueSource(value);
+				element.setAttributeNode(attr);
+			}
+		}
+		this.ignoreNotification = false;
+
+		notifyStyleChanged(element);
+	}
+
+	/**
+	 */
+	private void valueChanged() {
+		Element element = getElement();
+		if (element == null)
+			return;
+		if (!isModelNecessary()) { // removed
+			setModel(null);
+
+			notifyStyleChanged(element);
+			return;
+		}
+
+		ICSSModel model = getExistingModel();
+		if (model == null)
+			return; // defer
+		IStructuredDocument structuredDocument = model.getStructuredDocument();
+		if (structuredDocument == null)
+			return; // error
+
+		String value = null;
+		Attr attr = element.getAttributeNode(org.eclipse.wst.html.core.internal.provisional.HTML40Namespace.ATTR_NAME_STYLE);
+		if (attr != null)
+			value = ((IDOMNode) attr).getValueSource();
+		structuredDocument.setText(this, value);
+
+		notifyStyleChanged(element);
+	}
+
+	/**
+	 * @return boolean
+	 */
+	private boolean isModelNecessary() {
+		return getElement() != null && getElement().getAttributeNode(org.eclipse.wst.html.core.internal.provisional.HTML40Namespace.ATTR_NAME_STYLE) != null;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/htmlcss/StyleElementAdapter.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/htmlcss/StyleElementAdapter.java
new file mode 100644
index 0000000..f26c904
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/htmlcss/StyleElementAdapter.java
@@ -0,0 +1,455 @@
+/*******************************************************************************
+ * 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
+ *     
+ * 	    Masaki Saitoh (MSAITOH@jp.ibm.com)
+ *		See Bug 153000  Style Adapters should be lazier
+ *		https://bugs.eclipse.org/bugs/show_bug.cgi?id=153000
+ *
+ ********************************************************************************/
+package org.eclipse.wst.html.core.internal.htmlcss;
+
+
+
+import org.eclipse.wst.css.core.internal.provisional.adapters.IModelProvideAdapter;
+import org.eclipse.wst.css.core.internal.provisional.adapters.IStyleSheetListAdapter;
+import org.eclipse.wst.css.core.internal.provisional.document.ICSSModel;
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.sse.core.internal.provisional.events.IStructuredDocumentListener;
+import org.eclipse.wst.sse.core.internal.provisional.events.NewDocumentEvent;
+import org.eclipse.wst.sse.core.internal.provisional.events.NoChangeEvent;
+import org.eclipse.wst.sse.core.internal.provisional.events.RegionChangedEvent;
+import org.eclipse.wst.sse.core.internal.provisional.events.RegionsReplacedEvent;
+import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentRegionsReplacedEvent;
+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.IStructuredDocumentRegionList;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+/**
+ */
+public class StyleElementAdapter extends AbstractStyleSheetAdapter implements IStructuredDocumentListener {
+
+	private boolean replaceModel = true;
+	private boolean ignoreNotification = false;
+
+	/**
+	 */
+	protected StyleElementAdapter() {
+		super();
+	}
+
+	/**
+	 * Preparation of applying changes from CSS sub-model to HTML model
+	 */
+	private void changeStructuredDocumentRegion(IStructuredDocumentRegion flatNode) {
+		if (flatNode == null)
+			return;
+		Element element = getElement();
+		if (element == null)
+			return;
+		ICSSModel model = getExistingModel();
+		if (model == null)
+			return;
+		IStructuredDocument structuredDocument = model.getStructuredDocument();
+		if (structuredDocument == null)
+			return;
+
+		// get old content length
+		Node child = element.getFirstChild();
+		if (child == null || child.getNodeType() != Node.TEXT_NODE)
+			return;
+		IDOMNode content = (IDOMNode) child;
+		int oldLength = content.getEndOffset() - content.getStartOffset();
+
+		// get new content length
+		int newLength = 0;
+		IStructuredDocumentRegionList flatNodes = structuredDocument.getRegionList();
+		if (flatNodes != null) {
+			int count = flatNodes.getLength();
+			if (count > 0) {
+				IStructuredDocumentRegion last = flatNodes.item(count - 1);
+				if (last != null)
+					newLength = last.getEnd();
+			}
+		}
+
+		int offset = flatNode.getStart();
+		int end = flatNode.getEnd();
+		int diff = oldLength - newLength;
+		int length = end - offset + diff;
+		String data = flatNode.getText();
+
+		replaceData(offset, length, data);
+	}
+
+	/**
+	 * Apply changes from HTML model to CSS sub-model
+	 */
+	private void contentChanged() {
+		Element element = getElement();
+		if (element == null)
+			return;
+		ICSSModel model = getExistingModel();
+		if (model == null)
+			return;
+		IStructuredDocument structuredDocument = model.getStructuredDocument();
+		if (structuredDocument == null)
+			return;
+
+		String data = null;
+		Node child = element.getFirstChild();
+		if (child != null && child.getNodeType() == Node.TEXT_NODE && child.getNextSibling() == null) {
+			data = child.getNodeValue();
+		}
+		if (data == null)
+			data = "";//$NON-NLS-1$
+
+		// minimize replace range
+		int start = 0, end = 0;
+		String oldData = structuredDocument.get();
+		if (oldData == null)
+			oldData = "";//$NON-NLS-1$
+
+		// search differenct character position from first
+		for (; start < oldData.length() && start < data.length(); start++)
+			if (oldData.charAt(start) != data.charAt(start))
+				break;
+
+		if (start == oldData.length() && start == data.length())
+			return; // no change
+		else if (start == oldData.length()) {
+			structuredDocument.replaceText(getRequesterH2C(), start, 0, data.substring(start)); // append text to last
+		}
+		else if (start == data.length()) {
+			structuredDocument.replaceText(getRequesterH2C(), start, oldData.length() - start, ""); // remove text of last //$NON-NLS-1$
+		}
+		else {
+			// search differenct character position from last
+			for (; start < oldData.length() - end && start < data.length() - end; end++) {
+				if (oldData.charAt(oldData.length() - end - 1) != data.charAt(data.length() - end - 1))
+					break;
+			}
+			structuredDocument.replaceText(getRequesterH2C(), start, oldData.length() - end - start, data.substring(start, data.length() - end));
+		}
+
+	}
+
+	/**
+	 */
+	public ICSSModel getModel() {
+		ICSSModel model = getExistingModel();
+		if (this.replaceModel) {
+			ICSSModel oldModel = model;
+			model = createModel(false);
+
+			setModel(model, false); // need to set before contentChanged()
+			contentChanged();
+
+			// from super.createModel()
+			// get ModelProvideAdapter
+			IModelProvideAdapter modelProvideAdapter = (IModelProvideAdapter) ((INodeNotifier) getElement()).getAdapterFor(IModelProvideAdapter.class);
+			// notify adapter
+			if (modelProvideAdapter != null)
+				modelProvideAdapter.modelProvided(model);
+
+			// from createModel()
+			IStructuredDocument structuredDocument = null;
+			if (model != null)
+				structuredDocument = model.getStructuredDocument();
+			if (structuredDocument == null)
+				return null;
+			structuredDocument.addDocumentChangedListener(this);
+
+			// from setModel()
+			if (oldModel != null)
+				oldModel.removeStyleListener(this);
+			if (model != null)
+				model.addStyleListener(this);
+
+			if (oldModel != null) {
+				// get ModelProvideAdapter
+				IModelProvideAdapter adapter = (IModelProvideAdapter) ((INodeNotifier) getElement()).getAdapterFor(IModelProvideAdapter.class);
+				if (adapter != null) {
+					adapter.modelRemoved(oldModel);
+				}
+			}
+
+			this.replaceModel = false;
+		}
+		return model;
+	}
+
+	/**
+	 */
+	protected boolean isValidAttribute() {
+		Element element = getElement();
+		if (element == null) {
+			return false;
+		}
+		String type = element.getAttribute(HTML40Namespace.ATTR_NAME_TYPE);
+		if (element.hasAttribute(HTML40Namespace.ATTR_NAME_TYPE) && type.length() > 0 && !type.equalsIgnoreCase("text/css")) { //$NON-NLS-1$
+			return false;
+		}
+		return true;
+	}
+
+	/**
+	 */
+	protected ICSSModel createModel() {
+		return createModel(true);
+	}
+
+	/**
+	 */
+	protected ICSSModel createModel(boolean addListener) {
+		if (!isValidAttribute()) {
+			return null;
+		}
+
+		ICSSModel model = super.createModel(addListener);
+
+		if (!addListener)
+			return model;
+
+		IStructuredDocument structuredDocument = model.getStructuredDocument();
+		if (structuredDocument == null)
+			return null;
+		structuredDocument.addDocumentChangedListener(this);
+
+		return model;
+	}
+
+	/**
+	 */
+	//  public ICSSModel getModel() {
+	//  	ICSSModel model = getExistingModel();
+	//  	if (model == null) {
+	//  		model = createModel();
+	//  		if (model == null) return null;
+	//  		IStructuredDocument structuredDocument = model.getStructuredDocument();
+	//  		if (structuredDocument == null) return null;
+	//  		structuredDocument.addModelChangedListener(this);
+	//  		setModel(model); // need to set before contentChanged()
+	//  		contentChanged();
+	//  	}
+	//  	return model;
+	//  }
+	/**
+	 */
+	private Object getRequesterH2C() {
+		return (getElement() != null && ((IDOMNode) getElement()).getModel() != null) ? (Object) ((IDOMNode) getElement()).getModel() : this;
+	}
+
+	/**
+	 */
+	private Object getRequesterC2H() {
+		return (getModel() != null) ? (Object) getModel() : this;
+	}
+
+	/**
+	 * Implementing IStructuredDocumentListener's method
+	 * Event from CSS Flat Model
+	 */
+	public void newModel(NewDocumentEvent event) {
+		if (event == null)
+			return;
+		if (event.getOriginalRequester() == getRequesterH2C())
+			return;
+		IStructuredDocument structuredDocument = event.getStructuredDocument();
+		if (structuredDocument == null)
+			return;
+		IStructuredDocumentRegionList flatNodes = structuredDocument.getRegionList();
+		if (flatNodes == null)
+			return;
+
+		replaceStructuredDocumentRegions(flatNodes, null);
+	}
+
+	/**
+	 * Implementing IStructuredDocumentListener's method
+	 * Event from CSS Flat Model
+	 */
+	public void noChange(NoChangeEvent structuredDocumentEvent) {
+	}
+
+	/**
+	 * Implementing IStructuredDocumentListener's method
+	 * Event from CSS Flat Model
+	 */
+	public void nodesReplaced(StructuredDocumentRegionsReplacedEvent event) {
+		if (event == null)
+			return;
+		if (event.getOriginalRequester() == getRequesterH2C())
+			return;
+		IStructuredDocumentRegionList oldStructuredDocumentRegions = event.getOldStructuredDocumentRegions();
+		IStructuredDocumentRegionList newStructuredDocumentRegions = event.getNewStructuredDocumentRegions();
+		if (oldStructuredDocumentRegions == null && newStructuredDocumentRegions == null)
+			return;
+
+		replaceStructuredDocumentRegions(newStructuredDocumentRegions, oldStructuredDocumentRegions);
+	}
+
+	/**
+	 * Overriding INodeAdapter's method
+	 * Event from <STYLE> element
+	 */
+	public void notifyChanged(INodeNotifier notifier, int eventType, Object changedFeature, Object oldValue, Object newValue, int pos) {
+		if (this.ignoreNotification)
+			return;
+
+		if (eventType == INodeNotifier.ADD || eventType == INodeNotifier.REMOVE || eventType == INodeNotifier.CONTENT_CHANGED) {
+			contentChanged();
+		}
+		else if (eventType == INodeNotifier.CHANGE) {
+			Attr attr = (Attr) changedFeature;
+			if (attr == null)
+				return;
+			String name = attr.getName();
+			if (name.equalsIgnoreCase("type")) { //$NON-NLS-1$
+				this.replaceModel = true;
+
+				Element element = getElement();
+				if (element == null) {
+					return;
+				}
+				Document document = element.getOwnerDocument();
+				if (document == null) {
+					return;
+				}
+				HTMLDocumentAdapter adapter = (HTMLDocumentAdapter) ((INodeNotifier) document).getAdapterFor(IStyleSheetListAdapter.class);
+				if (adapter != null) {
+					adapter.childReplaced();
+				}
+			}
+		}
+	}
+
+	/**
+	 * Implementing IStructuredDocumentListener's method
+	 * Event from CSS Flat Model
+	 */
+	public void regionChanged(RegionChangedEvent event) {
+		if (event == null)
+			return;
+		if (event.getOriginalRequester() == getRequesterH2C())
+			return;
+		IStructuredDocumentRegion flatNode = event.getStructuredDocumentRegion();
+		if (flatNode == null)
+			return;
+
+		changeStructuredDocumentRegion(flatNode);
+	}
+
+	/**
+	 * Implementing IStructuredDocumentListener's method
+	 * Event from CSS Flat Model
+	 */
+	public void regionsReplaced(RegionsReplacedEvent event) {
+		if (event == null)
+			return;
+		if (event.getOriginalRequester() == getRequesterH2C())
+			return;
+		IStructuredDocumentRegion flatNode = event.getStructuredDocumentRegion();
+		if (flatNode == null)
+			return;
+
+		changeStructuredDocumentRegion(flatNode);
+	}
+
+	/**
+	 * Apply changes from CSS sub-model to HTML model
+	 */
+	private void replaceData(int offset, int length, String data) {
+		IDOMNode element = (IDOMNode) getElement();
+		if (element == null)
+			return;
+		IDOMModel ownerModel = element.getModel();
+		if (ownerModel == null)
+			return;
+		IStructuredDocument structuredDocument = ownerModel.getStructuredDocument();
+		if (structuredDocument == null)
+			return;
+		IStructuredDocumentRegion flatNode = element.getStartStructuredDocumentRegion();
+		if (flatNode == null)
+			return;
+
+		int contentOffset = flatNode.getEndOffset();
+		if (data == null)
+			data = "";//$NON-NLS-1$
+
+		this.ignoreNotification = true;
+		structuredDocument.replaceText(getRequesterC2H(), contentOffset + offset, length, data);
+		this.ignoreNotification = false;
+	}
+
+	/**
+	 * Preparation of applying changes from CSS sub-model to HTML model
+	 */
+	private void replaceStructuredDocumentRegions(IStructuredDocumentRegionList newStructuredDocumentRegions, IStructuredDocumentRegionList oldStructuredDocumentRegions) {
+		int offset = 0;
+		int length = 0;
+		if (oldStructuredDocumentRegions != null) {
+			int count = oldStructuredDocumentRegions.getLength();
+			if (count > 0) {
+				IStructuredDocumentRegion first = oldStructuredDocumentRegions.item(0);
+				if (first != null)
+					offset = first.getStart();
+				IStructuredDocumentRegion last = oldStructuredDocumentRegions.item(count - 1);
+				if (last != null)
+					length = last.getEnd() - offset;
+			}
+		}
+		String data = null;
+		if (newStructuredDocumentRegions != null) {
+			int count = newStructuredDocumentRegions.getLength();
+			if (count > 0) {
+				StringBuffer buffer = new StringBuffer();
+				for (int i = 0; i < count; i++) {
+					IStructuredDocumentRegion flatNode = newStructuredDocumentRegions.item(i);
+					if (flatNode == null)
+						continue;
+					buffer.append(flatNode.getText());
+					if (i == 0)
+						offset = flatNode.getStart();
+				}
+				data = buffer.toString();
+			}
+		}
+
+		replaceData(offset, length, data);
+	}
+
+	/**
+	 */
+	protected void setModel(ICSSModel model) {
+		setModel(model, true);
+	}
+
+	/**
+	 */
+	protected void setModel(ICSSModel model, boolean setupListener) {
+		ICSSModel oldModel = getExistingModel();
+		if (model == oldModel)
+			return;
+		super.setModel(model);
+		if (!setupListener)
+			return;
+		if (oldModel != null)
+			oldModel.removeStyleListener(this);
+		if (model != null)
+			model.addStyleListener(this);
+	}
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/htmlcss/StyleListener.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/htmlcss/StyleListener.java
new file mode 100644
index 0000000..5dc6d51
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/htmlcss/StyleListener.java
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.htmlcss;
+
+
+
+/**
+ */
+public interface StyleListener {
+
+	/**
+	 */
+	void styleChanged();
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/htmlcss/URLHelper.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/htmlcss/URLHelper.java
new file mode 100644
index 0000000..68559e3
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/htmlcss/URLHelper.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.htmlcss;
+
+/**
+ * @deprecated 
+ */
+public class URLHelper extends org.eclipse.wst.css.core.internal.util.URLHelper {
+
+	/**
+	 * @param baseUrl
+	 */
+	public URLHelper(String baseUrl) {
+		super(baseUrl);
+	}
+
+	/**
+	 * @param baseUrl
+	 * @param docRoot
+	 */
+	public URLHelper(String baseUrl, String docRoot) {
+		super(baseUrl, docRoot);
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/htmlcss/URLModelProvider.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/htmlcss/URLModelProvider.java
new file mode 100644
index 0000000..821b118
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/htmlcss/URLModelProvider.java
@@ -0,0 +1,451 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.htmlcss;
+
+
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.UnsupportedCharsetException;
+
+import org.eclipse.core.resources.IContainer;
+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.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.wst.html.core.internal.document.HTMLDocumentTypeConstants;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.encoding.EncodingRule;
+import org.eclipse.wst.sse.core.internal.provisional.IModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.provisional.exceptions.ResourceAlreadyExists;
+import org.eclipse.wst.sse.core.internal.provisional.exceptions.ResourceInUse;
+import org.eclipse.wst.sse.core.internal.util.PathHelper;
+import org.eclipse.wst.sse.core.internal.util.ProjectResolver;
+import org.eclipse.wst.sse.core.internal.util.URIResolver;
+import org.eclipse.wst.xml.core.internal.document.DocumentTypeAdapter;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+// TODO when this class is removed from .core, PathHelper and URLHelper class
+// also can be removed.
+
+/**
+ */
+public class URLModelProvider {
+
+	private static final int GET_MODEL_FOR_READ = 1;
+	//	private static final int GET_NEW_MODEL_FOR_READ = 2;
+	private static final int GET_MODEL_FOR_EDIT = 3;
+	//	private static final int GET_NEW_MODEL_FOR_EDIT = 4;
+	//	private static final int READ_BUFFER_SIZE = 4096;
+	// IModelManager
+	private IModelManager modelManager = null;
+
+	/**
+	 */
+	public URLModelProvider() {
+		super();
+
+		// obtain model manager
+		modelManager = StructuredModelManager.getModelManager();
+	}
+
+	/**
+	 * Calculate ID from a filename. This must be same as
+	 * FileModelProvider.calculateId(IFile)
+	 */
+	private static String calculateId(IPath fullIPath) {
+		return fullIPath.toString();
+	}
+
+	/**
+	 * <code>baseModel</code>: the model containing the link
+	 * <code>ref</code>: the link URL string
+	 */
+	private IStructuredModel getCommonModelFor(final IStructuredModel baseModel, final String ref, final int which) throws IOException {
+		// first, create absolute url
+		String absURL = resolveURI(baseModel, ref, true);
+		if ((absURL == null) || (absURL.length() == 0)) {
+			return null;
+		}
+
+		// need to remove file:// scheme if necessary
+		try {
+			final java.net.URL aURL = new java.net.URL(absURL);
+			// An actual URL was given, only file:/// is supported
+			// resolve it by finding the file it points to
+			if (!aURL.getProtocol().equals("platform")) { //$NON-NLS-1$
+				if (aURL.getProtocol().equals("file") && (aURL.getHost().equals("localhost") || aURL.getHost().length() == 0)) {//$NON-NLS-2$//$NON-NLS-1$
+					absURL = aURL.getFile();
+					final IPath ipath = new Path(absURL);
+					//  if path has a device, and if it begins with
+					// IPath.SEPARATOR, remove it
+					final String device = ipath.getDevice();
+					if ((device != null) && (device.length() > 0)) {
+						if (device.charAt(0) == IPath.SEPARATOR) {
+							final String newDevice = device.substring(1);
+							absURL = ipath.setDevice(newDevice).toString();
+						}
+					}
+
+				}
+			}
+		}
+		catch (java.net.MalformedURLException mfuExc) {
+		}
+
+
+		// next, decide project
+		IProject project = null;
+		final IPath fullIPath = new Path(absURL);
+		IWorkspaceRoot workspace = ResourcesPlugin.getWorkspace().getRoot();
+		IContainer container = workspace.getContainerForLocation(fullIPath);
+		if (container != null) {
+			// fullIPath doesn't exist in workspace
+			project = container.getProject();
+		}
+
+		// If HTML document has a link to an extern CSS which is not in
+		// IProject
+		// workspace.getContainerForLoation() may return null. We need to take
+		// care
+		// of this case
+
+		// now, get absURL's IFile
+		if ((project != null) && (project.getLocation().isPrefixOf(fullIPath) == false)) {
+			// it's at outside of Project
+			return null;
+		}
+
+		IStructuredModel model = null;
+		if (project != null) {
+			IPath filePath = fullIPath.removeFirstSegments(project.getLocation().segmentCount());
+			IFile file = (filePath != null && !filePath.isEmpty()) ? project.getFile(filePath) : null;
+			if (file == null) {
+				return null;
+			}
+
+			// obtain model
+			if (which == GET_MODEL_FOR_EDIT) {
+				model = getModelForEdit(file);
+			}
+			else if (which == GET_MODEL_FOR_READ) {
+				model = getModelForRead(file);
+			}
+
+			// setting synchronization stamp is IModelManager's client's
+			// responsibility
+			if (model != null && model.getSynchronizationStamp() == IResource.NULL_STAMP)
+				model.resetSynchronizationStamp(file);
+		}
+		else {
+			String id = null;
+			InputStream inStream = null;
+			// obtain resolver
+			URIResolver resolver = (project != null) ? (URIResolver) project.getAdapter(URIResolver.class) : null;
+			if (resolver == null) {
+				// ProjectResolver can take care of the case if project is
+				// null.
+				resolver = new ProjectResolver(project);
+			}
+			if (resolver == null) {
+				return null;
+			}
+
+			// there is no project. we can't expect IProject help to create
+			// id/inputStream
+			java.io.File file = fullIPath.toFile();
+
+			// obatin id
+			id = calculateId(fullIPath);
+
+			// obtain InputStream
+			try {
+				inStream = new FileInputStream(file);
+			}
+			catch (FileNotFoundException fnfe) {
+				// the file does not exist, or we don't have read permission
+				return null;
+			}
+
+			// obtain model
+			try {
+				if (which == GET_MODEL_FOR_EDIT) {
+					model = getModelManager().getModelForEdit(id, inStream, resolver);
+				}
+				else if (which == GET_MODEL_FOR_READ) {
+					model = getModelManager().getModelForRead(id, inStream, resolver);
+				}
+			}
+			catch (UnsupportedEncodingException ue) {
+			}
+			catch (IOException ioe) {
+			}
+			finally {
+				// close now !
+				if (inStream != null) {
+					inStream.close();
+				}
+			}
+		}
+
+
+		// set locationid
+		if (model != null && model.getBaseLocation() == null) {
+			model.setBaseLocation(fullIPath.toString());
+		}
+
+		return model;
+	}
+
+	/**
+	 * <code>baseModel</code>: the model containing the link
+	 * <code>ref</code>: the link URL string
+	 */
+	public IStructuredModel getModelForEdit(IStructuredModel baseModel, String ref) throws IOException {
+		return getCommonModelFor(baseModel, ref, GET_MODEL_FOR_EDIT);
+	}
+
+	/**
+	 */
+	private IStructuredModel getModelForEdit(IFile file) throws IOException {
+		if (file == null)
+			return null;
+		IModelManager manager = getModelManager();
+
+		// create a fake InputStream
+		IStructuredModel model = null;
+		try {
+			model = manager.getModelForEdit(file);
+		}
+		catch (UnsupportedCharsetException ex) {
+			try {
+				model = manager.getModelForEdit(file, EncodingRule.FORCE_DEFAULT);
+			}
+			catch (IOException ioe) {
+			}
+			catch (CoreException ce) {
+			}
+		}
+		catch (CoreException ce) {
+		}
+		return model;
+	}
+
+	/**
+	 * <code>baseModel</code>: the model containing the link
+	 * <code>ref</code>: the link URL string
+	 */
+	public IStructuredModel getModelForRead(IStructuredModel baseModel, String ref) throws UnsupportedEncodingException, IOException {
+		return getCommonModelFor(baseModel, ref, GET_MODEL_FOR_READ);
+	}
+
+	/**
+	 */
+	private IStructuredModel getModelForRead(IFile file) throws IOException {
+		if (file == null)
+			return null;
+		IModelManager manager = getModelManager();
+
+		// create a fake InputStream
+		IStructuredModel model = null;
+		try {
+			model = manager.getModelForRead(file);
+		}
+		catch (UnsupportedCharsetException ex) {
+			try {
+				model = manager.getModelForRead(file, EncodingRule.FORCE_DEFAULT);
+			}
+			catch (IOException ioe) {
+			}
+			catch (CoreException ce) {
+			}
+		}
+		catch (CoreException ce) {
+		}
+		return model;
+	}
+
+	/**
+	 */
+	private IModelManager getModelManager() {
+		return modelManager;
+	}
+
+	public IStructuredModel getNewModelForEdit(IFile iFile) {
+		if (iFile == null)
+			return null;
+		IModelManager manager = getModelManager();
+		if (manager == null)
+			return null;
+
+		IStructuredModel model = null;
+		try {
+			model = manager.getNewModelForEdit(iFile, false);
+		}
+		catch (IOException ex) {
+		}
+		catch (ResourceInUse riu) {
+		}
+		catch (ResourceAlreadyExists rae) {
+		}
+		catch (CoreException ce) {
+		}
+		return model;
+	}
+
+	public IStructuredModel getNewModelForRead(IFile iFile) {
+		if (iFile == null)
+			return null;
+		IModelManager manager = getModelManager();
+		if (manager == null)
+			return null;
+
+		IStructuredModel model = null;
+		try {
+			model = manager.getNewModelForEdit(iFile, false);
+		}
+		catch (IOException ex) {
+		}
+		catch (ResourceInUse riu) {
+		}
+		catch (ResourceAlreadyExists rae) {
+		}
+		catch (CoreException ce) {
+		}
+		return model;
+	}
+
+	/**
+	 * Utility to check the model is HTML family or not
+	 */
+	static private boolean isHTMLFamily(IStructuredModel model) {
+		if (model instanceof IDOMModel) {
+			IDOMDocument document = ((IDOMModel) model).getDocument();
+			DocumentTypeAdapter adapter = (DocumentTypeAdapter) document.getAdapterFor(DocumentTypeAdapter.class);
+			if (adapter != null)
+				return adapter.hasFeature(HTMLDocumentTypeConstants.HTML);
+		}
+		return false;
+	}
+
+	/**
+	 * <code>baseModel</code>: the model containing the link
+	 * <code>ref</code>: the link URL string
+	 * <code>resolveCrossProjectLinks</code>: If resolveCrossProjectLinks
+	 * is set to true, then this method will properly resolve the URI if it is
+	 * a valid URI pointing to another (appropriate) project.
+	 */
+	public static String resolveURI(IStructuredModel baseModel, String ref, boolean resolveCrossProjectLinks) {
+		if (baseModel == null)
+			return null;
+		// for HTML, 'href' attribute value of BASE element
+		// should be used, if exists any
+		String baseHref = null;
+		// dmw_TODO needs to be changed to handle a content model
+		// of HTML or XHTML
+		if (isHTMLFamily(baseModel)) {
+			final IDOMModel xmlmodel = (IDOMModel) baseModel;
+			final IDOMDocument doc = xmlmodel.getDocument();
+			// look for <BASE> w/ href
+			final NodeList nl = doc.getElementsByTagName("BASE");//$NON-NLS-1$
+			if ((nl != null) && (nl.getLength() > 0)) {
+				// per each <BASE>
+				for (int i = 0; i < nl.getLength(); i++) {
+					final Node baseNode = nl.item(i);
+					if (baseNode != null) {
+						// get all attrs
+						final NamedNodeMap attrNodes = baseNode.getAttributes();
+						if (attrNodes != null) {
+							final Node attrNode = attrNodes.getNamedItem("HREF");//$NON-NLS-1$
+							if (attrNode != null) {
+								// found href=""
+								final String attrValue = attrNode.getNodeValue();
+								if (attrValue != null) {
+									baseHref = attrValue.trim();
+								}
+							}
+						}
+					}
+					// what if there are multiple <BASE> tags ??
+					if (baseHref != null) {
+						break;
+					}
+				}
+			}
+		}
+
+		// get resolver in Model
+		final URIResolver resolver = baseModel.getResolver();
+
+		// resolve to absolute url
+		final String absurl = (resolver != null) ? ((baseHref != null) ? resolver.getLocationByURI(ref, baseHref, resolveCrossProjectLinks) : resolver.getLocationByURI(ref, resolveCrossProjectLinks)) : null;
+		if ((resolver != null) && (absurl == null) && (ref != null) && (ref.trim().length() > 0) && (ref.trim().charAt(0) == '/')) {
+			// to reach here means :
+			//    ref is a Docroot relative
+			//    resolver can't resolve ref
+			// so that href is a broken and should not create model
+			return null;
+		}
+		if ((absurl != null) && (absurl.length() > 0)) {
+			return absurl;
+		}
+
+		// maybe ref is at outside of the Project
+		// obtain docroot;
+		final IContainer container = (resolver != null) ? resolver.getRootLocation() : null;
+		String docroot = null;
+		if (container != null) {
+			IPath containerLocation = container.getLocation();
+			if (containerLocation != null) {
+				docroot = containerLocation.toString();
+			}
+			else if (container.getLocationURI() != null) {
+				docroot = container.getLocationURI().toString();
+			}
+		}
+		if (docroot == null) {
+			docroot = baseModel.getBaseLocation();
+		}
+		if (docroot == null) {
+			// should not be
+			return null;
+		}
+
+		// obtain document url
+		String modelBaseLocation = baseModel.getBaseLocation();
+		if ((modelBaseLocation == null) || (modelBaseLocation.length() == 0)) {
+			// fallback...
+			modelBaseLocation = baseModel.getId();
+		}
+		if ((modelBaseLocation == null) || (modelBaseLocation.length() == 0)) {
+			// i can't resolve uri !
+			return null;
+		}
+
+		// resolve url
+		URLHelper helper = new URLHelper(PathHelper.getContainingFolderPath(modelBaseLocation), PathHelper.getContainingFolderPath(PathHelper.appendTrailingURLSlash(docroot)));
+		return helper.toAbsolute(ref);
+	}
+
+}
+
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/modelhandler/EmbeddedHTML.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/modelhandler/EmbeddedHTML.java
new file mode 100644
index 0000000..cf9ffb7
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/modelhandler/EmbeddedHTML.java
@@ -0,0 +1,170 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.modelhandler;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.wst.css.core.internal.provisional.adapters.IStyleSelectorAdapter;
+import org.eclipse.wst.css.core.internal.provisional.adapters.IStyleSheetAdapter;
+import org.eclipse.wst.html.core.internal.document.HTMLDocumentTypeAdapterFactory;
+import org.eclipse.wst.html.core.internal.document.HTMLModelParserAdapterFactory;
+import org.eclipse.wst.html.core.internal.htmlcss.HTMLStyleSelectorAdapterFactory;
+import org.eclipse.wst.html.core.internal.htmlcss.StyleAdapterFactory;
+import org.eclipse.wst.html.core.internal.modelquery.ModelQueryAdapterFactoryForEmbeddedHTML;
+import org.eclipse.wst.sse.core.internal.ltk.modelhandler.EmbeddedTypeHandler;
+import org.eclipse.wst.sse.core.internal.ltk.parser.BlockMarker;
+import org.eclipse.wst.sse.core.internal.ltk.parser.BlockTagParser;
+import org.eclipse.wst.sse.core.internal.ltk.parser.RegionParser;
+import org.eclipse.wst.sse.core.internal.model.FactoryRegistry;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapterFactory;
+import org.eclipse.wst.sse.core.internal.util.Assert;
+import org.eclipse.wst.xml.core.internal.document.DocumentTypeAdapter;
+import org.eclipse.wst.xml.core.internal.document.ModelParserAdapter;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+
+public class EmbeddedHTML implements EmbeddedTypeHandler {
+
+	public String ContentTypeID_EmbeddedHTML = "org.eclipse.wst.html.core.internal.contenttype.EmbeddedHTML"; //$NON-NLS-1$
+	private List supportedMimeTypes;
+
+	/**
+	 * Constructor for EmbeddedHTML.
+	 */
+	public EmbeddedHTML() {
+		super();
+	}
+
+	/**
+	 * Convenience method to add tag names using BlockMarker object
+	 */
+	private void addHTMLishTag(BlockTagParser parser, String tagname) {
+		BlockMarker bm = new BlockMarker(tagname, null, DOMRegionContext.BLOCK_TEXT, false);
+		parser.addBlockMarker(bm);
+	}
+
+	/**
+	 * @see EmbeddedContentType#getFamilyId()
+	 */
+	public String getFamilyId() {
+		return ModelHandlerForHTML.AssociatedContentTypeID;
+	}
+
+	/*
+	 * Only "model side" embedded factories can be added here.
+	 */
+	public List getAdapterFactories() {
+		List factories = new ArrayList();
+		factories.add(new ModelQueryAdapterFactoryForEmbeddedHTML());
+		// factories.addAll(PluginContributedFactoryReader.getInstance().getFactories(this));
+		return factories;
+	}
+
+	/*
+	 * @see EmbeddedContentType#initializeParser(RegionParser)
+	 */
+	public void initializeParser(RegionParser parser) {
+		if (parser instanceof BlockTagParser) {
+			addHTMLishTag((BlockTagParser) parser, "script"); //$NON-NLS-1$
+			addHTMLishTag((BlockTagParser) parser, "style"); //$NON-NLS-1$
+		}
+	}
+
+	public List getSupportedMimeTypes() {
+		if (supportedMimeTypes == null) {
+			supportedMimeTypes = new ArrayList();
+			supportedMimeTypes.add("text/html"); //$NON-NLS-1$
+			supportedMimeTypes.add("text/xhtml"); //$NON-NLS-1$
+			supportedMimeTypes.add("application/xhtml+xml"); //$NON-NLS-1$
+			supportedMimeTypes.add("text/vnd.wap.wml"); //$NON-NLS-1$
+		}
+		return supportedMimeTypes;
+	}
+
+	public void initializeFactoryRegistry(FactoryRegistry registry) {
+		Assert.isNotNull(registry);
+
+		INodeAdapterFactory factory = null;
+		if (!registry.contains(DocumentTypeAdapter.class)) {
+			factory = new HTMLDocumentTypeAdapterFactory();
+			registry.addFactory(factory);
+		}
+		if (!registry.contains(ModelParserAdapter.class)) {
+			factory = HTMLModelParserAdapterFactory.getInstance();
+			registry.addFactory(factory);
+		}
+		if (!registry.contains(IStyleSelectorAdapter.class)) {
+
+			factory = HTMLStyleSelectorAdapterFactory.getInstance();
+			registry.addFactory(factory);
+		}
+		if (!registry.contains(IStyleSheetAdapter.class)) {
+
+			factory = StyleAdapterFactory.getInstance();
+			registry.addFactory(factory);
+		}
+
+	}
+
+	public void uninitializeFactoryRegistry(FactoryRegistry registry) {
+		Assert.isNotNull(registry);
+
+		// ISSUE: should these factories be released? Or just 
+		// removed from this registry, because we are getting ready to
+		// re-add them?
+		INodeAdapterFactory factory = null;
+		if (!registry.contains(DocumentTypeAdapter.class)) {
+			factory = registry.getFactoryFor(DocumentTypeAdapter.class);
+			factory.release();
+			registry.removeFactory(factory);
+		}
+		if (!registry.contains(ModelParserAdapter.class)) {
+			factory = registry.getFactoryFor(ModelParserAdapter.class);
+			factory.release();
+			registry.removeFactory(factory);
+		}
+		if (!registry.contains(IStyleSelectorAdapter.class)) {
+			factory = registry.getFactoryFor(IStyleSelectorAdapter.class);
+			factory.release();
+			registry.removeFactory(factory);
+		}
+		if (!registry.contains(IStyleSheetAdapter.class)) {
+			factory = registry.getFactoryFor(IStyleSheetAdapter.class);
+			factory.release();
+			registry.removeFactory(factory);
+		}
+
+	}
+
+	public void uninitializeParser(RegionParser parser) {
+		// I'm assuming block markers are unique based on name only
+		// we add these as full BlockMarkers, but remove based on name alone.
+		if (parser instanceof BlockTagParser) {
+			((BlockTagParser) parser).removeBlockMarker("style"); //$NON-NLS-1$
+			((BlockTagParser) parser).removeBlockMarker("script"); //$NON-NLS-1$
+		}
+	}
+
+	public EmbeddedTypeHandler newInstance() {
+		return new EmbeddedHTML();
+	}
+
+	/**
+	 * will someday be controlled via extension point
+	 */
+	public boolean isDefault() {
+		return true;
+	}
+
+	public boolean canHandleMimeType(String mimeType) {
+		return getSupportedMimeTypes().contains(mimeType);
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/modelhandler/ModelHandlerForHTML.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/modelhandler/ModelHandlerForHTML.java
new file mode 100644
index 0000000..9f9badb
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/modelhandler/ModelHandlerForHTML.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.modelhandler;
+
+import org.eclipse.wst.html.core.internal.encoding.HTMLDocumentCharsetDetector;
+import org.eclipse.wst.html.core.internal.encoding.HTMLDocumentLoader;
+import org.eclipse.wst.html.core.internal.encoding.HTMLModelLoader;
+import org.eclipse.wst.sse.core.internal.document.IDocumentCharsetDetector;
+import org.eclipse.wst.sse.core.internal.document.IDocumentLoader;
+import org.eclipse.wst.sse.core.internal.ltk.modelhandler.AbstractModelHandler;
+import org.eclipse.wst.sse.core.internal.ltk.modelhandler.IModelHandler;
+import org.eclipse.wst.sse.core.internal.provisional.IModelLoader;
+
+public class ModelHandlerForHTML extends AbstractModelHandler implements IModelHandler {
+	/** 
+	 * Needs to match what's in plugin registry. 
+	 * In fact, can be overwritten at run time with 
+	 * what's in registry! (so should never be 'final')
+	 */
+	static String AssociatedContentTypeID = "org.eclipse.wst.html.core.htmlsource"; //$NON-NLS-1$
+	/**
+	 * Needs to match what's in plugin registry. 
+	 * In fact, can be overwritten at run time with 
+	 * what's in registry! (so should never be 'final')
+	 */
+	private static String ModelHandlerID_HTML = "org.eclipse.wst.html.core.modelhandler"; //$NON-NLS-1$
+
+
+	public ModelHandlerForHTML() {
+		super();
+		setId(ModelHandlerID_HTML);
+		setAssociatedContentTypeId(AssociatedContentTypeID);
+	}
+
+	public IModelLoader getModelLoader() {
+		return new HTMLModelLoader();
+	}
+
+	public IDocumentCharsetDetector getEncodingDetector() {
+		return new HTMLDocumentCharsetDetector();
+	}
+
+	public IDocumentLoader getDocumentLoader() {
+		return new HTMLDocumentLoader();
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/modelquery/CMAttributeDeclarationBuddySystem.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/modelquery/CMAttributeDeclarationBuddySystem.java
new file mode 100644
index 0000000..34b600c
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/modelquery/CMAttributeDeclarationBuddySystem.java
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.modelquery;
+
+import java.util.Enumeration;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+
+/**
+ */
+class CMAttributeDeclarationBuddySystem extends CMNodeBuddySystem implements CMAttributeDeclaration {
+
+
+	public CMAttributeDeclarationBuddySystem(CMAttributeDeclaration self, CMAttributeDeclaration buddy, boolean isXHTML) {
+		super(self, buddy, isXHTML);
+	}
+
+	/*
+	 * @see CMAttributeDeclaration#getAttrName()
+	 */
+	public String getAttrName() {
+		return getSelf().getAttrName();
+	}
+
+	/*
+	 * @see CMAttributeDeclaration#getAttrType()
+	 */
+	public CMDataType getAttrType() {
+		return getSelf().getAttrType();
+	}
+
+	/*
+	 * @see CMAttributeDeclaration#getDefaultValue()
+	 * @deprecated in superclass
+	 */
+	public String getDefaultValue() {
+		return getSelf().getDefaultValue();
+	}
+
+	/*
+	 * @see CMAttributeDeclaration#getEnumAttr()
+	 * @deprecated in superclass
+	 */
+	public Enumeration getEnumAttr() {
+		return getSelf().getEnumAttr();
+	}
+
+	/*
+	 * @see CMAttributeDeclaration#getUsage()
+	 */
+	public int getUsage() {
+		return getSelf().getUsage();
+	}
+
+	private CMAttributeDeclaration getSelf() {
+		return (CMAttributeDeclaration) self;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/modelquery/CMDocumentForBuddySystem.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/modelquery/CMDocumentForBuddySystem.java
new file mode 100644
index 0000000..a710eab
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/modelquery/CMDocumentForBuddySystem.java
@@ -0,0 +1,119 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.modelquery;
+
+import java.util.Iterator;
+
+import org.eclipse.wst.html.core.internal.contentmodel.HTMLCMDocumentFactory;
+import org.eclipse.wst.html.core.internal.contentmodel.ssi.SSICMDocumentFactory;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.provisional.contentmodel.CMDocType;
+
+/**
+ */
+class CMDocumentForBuddySystem extends CMNodeBuddySystem implements CMDocument {
+
+
+	private static CMDocument getHTMLCMDocument() {
+		return HTMLCMDocumentFactory.getCMDocument(CMDocType.HTML_DOC_TYPE);
+	}
+
+	class Elements extends CMNamedNodeMapForBuddySystem {
+		public Elements(CMNamedNodeMap elements, boolean isXHTML) {
+			super(isXHTML);
+			makeBuddySystem(elements);
+			addSSIDecls();
+		}
+
+		protected String getKeyName(CMNode original) {
+			CMElementDeclaration edecl = getDecl(original);
+			if (edecl == null)
+				return null;
+			return edecl.getElementName();
+		}
+
+		protected CMNode createBuddySystem(CMNode original) {
+			CMElementDeclaration edecl = getDecl(original);
+			return new CMElementDeclarationBuddySystem(edecl, isXHTML());
+		}
+
+		private CMElementDeclaration getDecl(CMNode cmnode) {
+			if (cmnode == null)
+				return null;
+			if (cmnode.getNodeType() != CMNode.ELEMENT_DECLARATION)
+				return null;
+			return (CMElementDeclaration) cmnode;
+		}
+
+		private void addSSIDecls() {
+			CMDocument ssi = SSICMDocumentFactory.getCMDocument();
+			if (ssi == null)
+				return;
+			CMNamedNodeMap elements = ssi.getElements();
+			Iterator i = elements.iterator();
+			while (i.hasNext()) {
+				CMElementDeclaration decl = (CMElementDeclaration) i.next();
+				if (decl == null)
+					continue;
+				put(decl.getElementName(), decl);
+			}
+		}
+	}
+
+	private Elements elements = null;
+
+	public CMDocumentForBuddySystem(CMDocument self, boolean isXHTML) {
+		super(self, getHTMLCMDocument(), isXHTML);
+	}
+
+	/*
+	 * @see CMDocument#getElements()
+	 */
+	public CMNamedNodeMap getElements() {
+		if (elements != null)
+			return elements;
+		CMDocument cmdoc = getSelf();
+		if (cmdoc == null)
+			return null;
+		elements = new Elements(cmdoc.getElements(), isXHTML);
+		return elements;
+	}
+
+	/*
+	 * @see CMDocument#getEntities()
+	 */
+	public CMNamedNodeMap getEntities() {
+		CMDocument cmdoc = getSelf();
+		if (cmdoc == null)
+			return null;
+		return cmdoc.getEntities();
+	}
+
+	/*
+	 * @see CMDocument#getNamespace()
+	 */
+	public CMNamespace getNamespace() {
+		CMDocument cmdoc = getSelf();
+		if (cmdoc == null)
+			return null;
+		return cmdoc.getNamespace();
+	}
+
+	private CMDocument getSelf() {
+		if (self.getNodeType() != CMNode.DOCUMENT)
+			return null;
+		return (CMDocument) self;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/modelquery/CMElementDeclarationBuddySystem.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/modelquery/CMElementDeclarationBuddySystem.java
new file mode 100644
index 0000000..c934dbb
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/modelquery/CMElementDeclarationBuddySystem.java
@@ -0,0 +1,201 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.modelquery;
+
+
+import org.eclipse.wst.html.core.internal.contentmodel.HTMLCMDocumentFactory;
+import org.eclipse.wst.html.core.internal.provisional.HTMLCMProperties;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMContent;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.provisional.contentmodel.CMDocType;
+
+/**
+ */
+class CMElementDeclarationBuddySystem extends CMNodeBuddySystem implements CMElementDeclaration {
+
+
+	private static CMDocument htmlcm = HTMLCMDocumentFactory.getCMDocument(CMDocType.HTML_DOC_TYPE);
+
+	private static CMElementDeclaration getHTMLCMElemDecl(CMElementDeclaration original) {
+		CMElementDeclaration buddy = null;
+		if (htmlcm != null) {
+			CMNamedNodeMap elems = htmlcm.getElements();
+			if (elems != null) {
+				buddy = (CMElementDeclaration) elems.getNamedItem(original.getElementName());
+			}
+		}
+		return buddy;
+	}
+
+	private class Attrs extends CMNamedNodeMapForBuddySystem {
+		private CMNamedNodeMap buddyAttrs = null;
+
+		public Attrs(CMNamedNodeMap attrs, CMNamedNodeMap buddyAttrs, boolean isXHTML) {
+			super(isXHTML);
+			this.buddyAttrs = buddyAttrs;
+			makeBuddySystem(attrs);
+		}
+
+		protected String getKeyName(CMNode original) {
+			CMAttributeDeclaration adecl = getDecl(original);
+			if (adecl == null)
+				return null;
+			return adecl.getAttrName();
+		}
+
+		protected CMNode createBuddySystem(CMNode original) {
+			CMAttributeDeclaration adecl = getDecl(original);
+			if (adecl == null)
+				return null;
+			CMAttributeDeclaration buddy = null;
+			if (buddyAttrs != null) {
+				buddy = (CMAttributeDeclaration) buddyAttrs.getNamedItem(adecl.getAttrName());
+			}
+			return new CMAttributeDeclarationBuddySystem(adecl, buddy, isXHTML());
+		}
+
+		private CMAttributeDeclaration getDecl(CMNode cmnode) {
+			if (cmnode == null)
+				return null;
+			if (cmnode.getNodeType() != CMNode.ATTRIBUTE_DECLARATION)
+				return null;
+			return (CMAttributeDeclaration) cmnode;
+		}
+	}
+
+	private Attrs attributes = null;
+
+	public CMElementDeclarationBuddySystem(CMElementDeclaration self, boolean isXHTML) {
+		super(self, getHTMLCMElemDecl(self), isXHTML);
+	}
+
+	/*
+	 * @see CMElementDeclaration#getAttributes()
+	 */
+	public CMNamedNodeMap getAttributes() {
+		if (attributes != null)
+			return attributes;
+		CMElementDeclaration edecl = getSelf();
+		if (edecl == null)
+			return null;
+		CMElementDeclaration htmlDecl = getBuddy();
+		CMNamedNodeMap htmlAttrs = (htmlDecl == null) ? null : htmlDecl.getAttributes();
+		attributes = new Attrs(edecl.getAttributes(), htmlAttrs, isXHTML);
+		return attributes;
+	}
+
+	/*
+	 * @see CMElementDeclaration#getContent()
+	 */
+	public CMContent getContent() {
+		CMElementDeclaration edecl = getSelf();
+		if (edecl == null)
+			return null;
+		return edecl.getContent();
+	}
+
+	/*
+	 * @see CMElementDeclaration#getContentType()
+	 */
+	public int getContentType() {
+		CMElementDeclaration edecl = getSelf();
+		if (edecl == null)
+			return CMElementDeclaration.ANY;
+		return edecl.getContentType();
+	}
+
+	/*
+	 * @see CMElementDeclaration#getElementName()
+	 */
+	public String getElementName() {
+		CMElementDeclaration edecl = getSelf();
+		if (edecl == null)
+			return null;
+		return edecl.getElementName();
+	}
+
+	/*
+	 * @see CMElementDeclaration#getDataType()
+	 */
+	public CMDataType getDataType() {
+		CMElementDeclaration edecl = getSelf();
+		if (edecl == null)
+			return null;
+		return edecl.getDataType();
+	}
+
+	/*
+	 * @see CMElementDeclaration#getLocalElements()
+	 */
+	public CMNamedNodeMap getLocalElements() {
+		CMElementDeclaration edecl = getSelf();
+		if (edecl == null)
+			return null;
+		return edecl.getLocalElements();
+	}
+
+	/*
+	 * @see CMContent#getMaxOccur()
+	 */
+	public int getMaxOccur() {
+		CMElementDeclaration edecl = getSelf();
+		if (edecl == null)
+			return -1;
+		return edecl.getMaxOccur();
+	}
+
+	/*
+	 * @see CMContent#getMinOccur()
+	 */
+	public int getMinOccur() {
+		CMElementDeclaration edecl = getSelf();
+		if (edecl == null)
+			return -1;
+		return edecl.getMinOccur();
+	}
+
+	/*
+	 * @see CMNode#supports(String)
+	 */
+	public boolean supports(String propertyName) {
+		if (isXHTML && propertyName.equals(HTMLCMProperties.OMIT_TYPE))
+			return true;
+		return super.supports(propertyName);
+	}
+
+	/*
+	 * @see CMNode#getProperty(String)
+	 */
+	public Object getProperty(String propertyName) {
+		if (isXHTML && propertyName.equals(HTMLCMProperties.OMIT_TYPE))
+			return HTMLCMProperties.Values.OMIT_NONE;
+		return super.getProperty(propertyName);
+	}
+
+	private CMElementDeclaration getSelf() {
+		if (self.getNodeType() != CMNode.ELEMENT_DECLARATION)
+			return null;
+		return (CMElementDeclaration) self;
+	}
+
+	private CMElementDeclaration getBuddy() {
+		if (buddy == null)
+			return null;
+		if (buddy.getNodeType() != CMNode.ELEMENT_DECLARATION)
+			return null;
+		return (CMElementDeclaration) buddy;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/modelquery/CMNamedNodeMapForBuddySystem.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/modelquery/CMNamedNodeMapForBuddySystem.java
new file mode 100644
index 0000000..9b584bf
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/modelquery/CMNamedNodeMapForBuddySystem.java
@@ -0,0 +1,116 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.modelquery;
+
+
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Locale;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ */
+abstract class CMNamedNodeMapForBuddySystem implements CMNamedNodeMap {
+
+
+	private boolean isXHTML = false;
+	private Hashtable map = new Hashtable();
+
+	/**
+	 * Constructor of CMNamedNodeMapForBuddySystem.
+	 * CAUTION: Each derived class must call 'makeBuddySystem' method in its
+	 * constructor to build up its contents.
+	 */
+	public CMNamedNodeMapForBuddySystem(boolean isXHTML) {
+		super();
+		this.isXHTML = isXHTML;
+	}
+
+	/*
+	 * @see CMNamedNodeMap#getLength()
+	 */
+	public int getLength() {
+		return map.size();
+	}
+
+	/*
+	 * @see CMNamedNodeMap#getNamedItem(String)
+	 */
+	public CMNode getNamedItem(String name) {
+		String key = canonicalName(name);
+		if (!map.containsKey(key))
+			return null;
+		return (CMNode) map.get(key);
+	}
+
+	/*
+	 * @see CMNamedNodeMap#item(int)
+	 */
+	public CMNode item(int index) {
+		Iterator iter = iterator();
+		while (iter.hasNext()) {
+			Object node = iter.next();
+			if (--index < 0)
+				return (CMNode) node;
+		}
+		return null;
+	}
+
+	/*
+	 * @see CMNamedNodeMap#iterator()
+	 */
+	public Iterator iterator() {
+		return map.values().iterator();
+	}
+
+	/* package scope. */
+	void put(String name, CMNode cmnode) {
+		if (name == null || cmnode == null)
+			return;
+		map.put(canonicalName(name), cmnode);
+	}
+
+	abstract protected String getKeyName(CMNode original);
+
+	abstract protected CMNode createBuddySystem(CMNode original);
+
+	protected boolean isXHTML() {
+		return isXHTML;
+	}
+
+	/**
+	 * Each derived class must call this method in its constructor
+	 * to build up its contents.
+	 */
+	protected void makeBuddySystem(CMNamedNodeMap original) {
+		Iterator i = original.iterator();
+		if (i == null)
+			return;
+		while (i.hasNext()) {
+			CMNode org = (CMNode) i.next();
+			String key = getKeyName(org);
+			CMNode newNode = createBuddySystem(org);
+			put(key, newNode);
+		}
+	}
+
+	private String canonicalName(String name) {
+		// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=171918
+		// we are able to "cheat" here a little and use US Locale
+		// to get a good canonical form, since we are using this only
+		// for HTML and JSP standard tags.
+		// Long term, for similar needs with XML 1.1 (for example)
+		// we should use a class such as com.ibm.icu.text.Normalizer
+		return name.toUpperCase(Locale.US);
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/modelquery/CMNodeBuddySystem.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/modelquery/CMNodeBuddySystem.java
new file mode 100644
index 0000000..e282f9a
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/modelquery/CMNodeBuddySystem.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.modelquery;
+
+import org.eclipse.wst.html.core.internal.provisional.HTMLCMProperties;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ */
+class CMNodeBuddySystem implements CMNode {
+
+
+	protected boolean isXHTML = false;
+	protected CMNode self = null;
+	protected CMNode buddy = null;
+
+	public CMNodeBuddySystem(CMNode self, CMNode buddy, boolean isXHTML) {
+		super();
+		this.self = self;
+		this.buddy = buddy;
+		this.isXHTML = isXHTML;
+	}
+
+	/*
+	 * @see CMNode#getNodeName()
+	 */
+	public String getNodeName() {
+		return self.getNodeName();
+	}
+
+	/*
+	 * @see CMNode#getNodeType()
+	 */
+	public int getNodeType() {
+		return self.getNodeType();
+	}
+
+	/*
+	 * @see CMNode#supports(String)
+	 */
+	public boolean supports(String propertyName) {
+		if (propertyName.equals(HTMLCMProperties.SHOULD_IGNORE_CASE))
+			return true;
+		if (propertyName.equals(HTMLCMProperties.IS_XHTML))
+			return true;
+		if (buddy == null)
+			return false;
+		return buddy.supports(propertyName);
+	}
+
+	/*
+	 * @see CMNode#getProperty(String)
+	 */
+	public Object getProperty(String propertyName) {
+		if (propertyName.equals(HTMLCMProperties.SHOULD_IGNORE_CASE)) {
+			return new Boolean(!isXHTML);
+		}
+		if (propertyName.equals(HTMLCMProperties.IS_XHTML)) {
+			return new Boolean(isXHTML);
+		}
+
+		if (buddy == null || (!buddy.supports(propertyName)))
+			return null;
+		return buddy.getProperty(propertyName);
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/modelquery/DocumentQuery.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/modelquery/DocumentQuery.java
new file mode 100644
index 0000000..2d802d8
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/modelquery/DocumentQuery.java
@@ -0,0 +1,200 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.modelquery;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.ranges.Range;
+
+/**
+ */
+public interface DocumentQuery {
+
+	/**
+	 * isRenderRoot() returns true if - node is BODY element (both explicit
+	 * and implicit) - node is portalhtml:body element - node is Document node
+	 * and the document is treated as fragment (with BODY context) Note that
+	 * in editing a fragment file, Document node should be treated as a
+	 * substitute of BODY element.
+	 */
+	boolean isRenderRoot(Node node);
+
+	/**
+	 * isHeadCorrespondent() returns true if - node is HEAD element (both
+	 * explicit and implicit) - node is portalhtml:head element - node is
+	 * Document node and the document is treated as fragment (with HEAD
+	 * context) Note that in editing a fragment file (with HEAD context),
+	 * Document node should be treated as a substitute of HEAD element.
+	 */
+	boolean isHeadCorrespondent(Node node);
+
+	/**
+	 * Implicit BODY element will be gone in V6 SED model. So page designer
+	 * provides an API to get a range whose content nodes are rendered in
+	 * design view. getRenderRootRange() returns - a range from BODY's first
+	 * to its last (if the document has BODY element) - a range form
+	 * Document's first to its last (if the document is fragment with BODY
+	 * context) - null (if the document is fragment with HEAD context) [The
+	 * following cases will be supported since V6] - a range from a custom
+	 * tag's first to its last (if the document has a custom tag which
+	 * generates BODY element at runtime) - a range from Document's
+	 * appropirate offset to its last (if the document does not have explicit
+	 * BODY/HTML) - a range from HTML element's appropriate offset to its last
+	 * (if the document does not have explicit BODY but have explicit HTML)
+	 * 
+	 * @param doc
+	 * @return
+	 */
+	Range getRenderRootRange(Document doc);
+
+	/**
+	 * Implicit HEAD element will be gone in V6 SED model. So page designer
+	 * provides an API to get a range whose content nodes are treated as HEAD
+	 * element's child. getHeadCorrespondentRange() returns - a range from
+	 * HEAD's first to its last (if the document has HEAD element) - a range
+	 * form Document's first to its last (if the document is fragment with
+	 * HEAD context) - null (if the document is fragment with BODY context)
+	 * [The following cases will be supported since V6] - a range from a
+	 * custom tag's first to its last (if the document has a custom tag which
+	 * generates HEAD element at runtime) - a range from Document's first to
+	 * appropirate offset (if the document does not have explicit HEAD/HTML) -
+	 * a range from HTML element's first to appropriate offset (if the
+	 * document does not have explicit HEAD but have explicit HTML)
+	 * 
+	 * @param doc
+	 * @return
+	 */
+	Range getHeadCorrespondentRange(Document doc);
+
+	/**
+	 * getRenderRootNode() with [create=false] returns - BODY element if this
+	 * document is not fragment and has BODY element - null if this document
+	 * is not fragment and does not have BODY element - Document node if this
+	 * document is fragment with BODY context - null if this document is
+	 * fragment with HEAD context [The following cases will be supported since
+	 * V6] - a custom tag which generates BODY tag at runtime - Document node
+	 * or HTML element if this document is not fragment but does not have
+	 * explicit BODY element getRenderRootNode() with [create=true] returns -
+	 * BODY element if this document is not fragment and has BODY element (no
+	 * modifictation) - newly created BODY element if this document is not
+	 * fragment but does not have BODY element - Document node if this
+	 * document is fragment with BODY context (no modifictation) [The
+	 * following cases will be supported since V6] - a custom tag which
+	 * generates BODY tag at runtime (no modifictation) - newly created BODY
+	 * element if this document is not fragment but does not have explicit
+	 * BODY element getRenderRootNode() throws HTMLCommandException (since V6)
+	 * if - this document is fragment with HEAD context and - "create"
+	 * parameter is true Note that in editing a fragment file, Document node
+	 * should be treated as a substitute of BODY element.
+	 * 
+	 * @param childOrDocument
+	 * @param create
+	 * @return
+	 */
+	Node getRenderRootNode(Node childOrDocument, boolean create);
+
+	/**
+	 * getHeadCorrespondentNode() with [create=false] returns - HEAD element
+	 * if this document is not fragment and has HEAD element - null if this
+	 * document is not fragment and does not have HEAD element - Document node
+	 * if this document is fragment with HEAD context - null if this document
+	 * is fragment with BODY context [The following cases will be supported
+	 * since V6] - a custom tag which generates HEAD tag at runtime - Document
+	 * node or HTML element if this document is not fragment but does not have
+	 * explicit HEAD element getHeadCorrespondentNode() with [create=true]
+	 * returns - HEAD element if this document is not fragment and has HEAD
+	 * element (no modifictation) - newly created HEAD element if this
+	 * document is not fragment but does not have HEAD element - Document node
+	 * if this document is fragment with HEAD context (no modifictation) [The
+	 * following cases will be supported since V6] - a custom tag which
+	 * generates HEAD tag at runtime (no modifictation) - newly created HEAD
+	 * element if this document is not fragment but does not have explicit
+	 * HEAD element getHeadCorrespondentNode() throws HTMLCommandException
+	 * (since V6) if - this document is fragment with BODY context and -
+	 * "create" parameter is true Note that in editing a fragment file,
+	 * Document node should be treated as a substitute of HEAD element.
+	 * 
+	 * @param childOrDocument
+	 * @param create
+	 * @return
+	 */
+	Node getHeadCorrespondentNode(Node childOrDocument, boolean create);
+
+	/**
+	 * getHtmlCorrespondentNode() throws HTMLCommandException (since V6) if -
+	 * this document is fragment and "create" parameter is true
+	 * 
+	 * @param childOrDocument
+	 * @param create
+	 * @return
+	 */
+	Node getHtmlCorrespondentNode(Node childOrDocument, boolean create);
+
+	/**
+	 * This inner class is intended for insertion target. please use this like
+	 * the following : DocumentQuery.InsertionTarget ins;
+	 * ins.getParent().insertBefore(youInsertionNode, ins.getRef());
+	 */
+	public class InsertionTarget {
+		private final Node parent;
+		private final Node ref;
+
+		public InsertionTarget(Node parent, Node ref) {
+			this.parent = parent;
+			this.ref = ref;
+		}
+
+		public Node getParent() {
+			return parent;
+		}
+
+		public Node getRef() {
+			return ref;
+		}
+	}
+
+	/**
+	 * getHeadInsertionTarget() returns appropriate insetion target location
+	 * for HEAD child tags such as <script>, <style>, <meta>etc. Basically
+	 * this function returns <HEAD>tag's the last position. Note that this
+	 * would not create actual <HEAD>tag when the document does not have it.
+	 * <HEAD>is omittable tag so this function returns appropriate position
+	 * to which implicit <HEAD>can be inserted, if the document has no
+	 * <HEAD>.
+	 * 
+	 * @param doc
+	 * @return
+	 */
+	InsertionTarget getHeadInsertionTarget(Document doc);
+
+	/**
+	 * getPageInsertionTarget() returns appropriate insetion target location
+	 * for page-level markups, such as JSP directives, usebean tags or <html>
+	 * tag. Basically this function returns just before <HTML>tag. Note that
+	 * this would not create actual <HTML>tag when the document does not have
+	 * it. In such case, this function returns a position just before the
+	 * meaningful tags such as HTML/JSP elements.
+	 * 
+	 * @param doc
+	 * @return
+	 */
+	InsertionTarget getPageInsertionTarget(Document doc);
+
+	/**
+	 * isFragment() returns whether the document is fragment or complete
+	 * document
+	 * 
+	 * @param doc
+	 * @return
+	 */
+	boolean isFragment(Document doc);
+
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/modelquery/ElementDeclarationAdapter.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/modelquery/ElementDeclarationAdapter.java
new file mode 100644
index 0000000..e5ee296
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/modelquery/ElementDeclarationAdapter.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.modelquery;
+
+
+
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapter;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+
+/**
+ */
+public interface ElementDeclarationAdapter extends INodeAdapter {
+
+	/**
+	 */
+	CMElementDeclaration getDeclaration();
+
+	/**
+	 */
+	void setDeclaration(CMElementDeclaration declaration);
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/modelquery/ElementDeclarationAdapterFactory.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/modelquery/ElementDeclarationAdapterFactory.java
new file mode 100644
index 0000000..b558fb5
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/modelquery/ElementDeclarationAdapterFactory.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.modelquery;
+
+
+
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapter;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapterFactory;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+
+/**
+ */
+public class ElementDeclarationAdapterFactory implements INodeAdapterFactory {
+
+	private static ElementDeclarationAdapterFactory instance = null;
+
+	/**
+	 */
+	private ElementDeclarationAdapterFactory() {
+		super();
+	}
+
+	/**
+	 */
+	public INodeAdapter adapt(INodeNotifier notifier) {
+		if (notifier == null)
+			return null;
+		INodeAdapter adapter = notifier.getExistingAdapter(ElementDeclarationAdapter.class);
+		if (adapter != null)
+			return adapter;
+		adapter = new HTMLElementDeclarationAdapter();
+		notifier.addAdapter(adapter);
+		return adapter;
+	}
+
+	/**
+	 */
+	public synchronized static ElementDeclarationAdapterFactory getInstance() {
+		if (instance == null)
+			instance = new ElementDeclarationAdapterFactory();
+		return instance;
+	}
+
+	/**
+	 */
+	public boolean isFactoryForType(Object type) {
+		return (type == ElementDeclarationAdapter.class);
+	}
+
+	public void release() {
+		// default is to do nothing
+	}
+
+	/**
+	 * Overriding copy method
+	 */
+	public INodeAdapterFactory copy() {
+		return getInstance();
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/modelquery/HMQUtil.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/modelquery/HMQUtil.java
new file mode 100644
index 0000000..377ad09
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/modelquery/HMQUtil.java
@@ -0,0 +1,121 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.modelquery;
+
+import java.util.Collection;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Vector;
+
+import org.eclipse.wst.html.core.internal.provisional.HTMLCMProperties;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMContent;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNodeList;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.modelquery.ModelQueryUtil;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+public final class HMQUtil {
+
+	private final static Vector nullVector = new Vector();
+
+	/* HMQUtil class must not instantiate. */
+	private HMQUtil() {
+		super();
+	}
+
+	/* gather all element declarations in inclusion of each parent of the target. 
+	 * the inclusion of the target is also gathered. */
+	public static Collection getInclusions(Element target) {
+		if (target == null)
+			return nullVector;
+		Collection inclusions = gatherInclusions(getAncestorDeclarations(target));
+
+		Hashtable availables = new Hashtable();
+		Iterator iter = inclusions.iterator();
+		while (iter.hasNext()) {
+			CMContent inclusion = (CMContent) iter.next();
+			switch (inclusion.getNodeType()) {
+				case CMNode.GROUP :
+					extractDeclarations(availables, (CMGroup) inclusion);
+					break;
+				case CMNode.ELEMENT_DECLARATION :
+					addInclusion(availables, (CMElementDeclaration) inclusion);
+					break;
+			}
+		}
+
+		return availables.values();
+	}
+
+	private static Collection getAncestorDeclarations(Element target) {
+		Vector ancestors = new Vector();
+
+		Document doc = target.getOwnerDocument();
+		ModelQuery query = ModelQueryUtil.getModelQuery(doc);
+		CMElementDeclaration decl = query.getCMElementDeclaration(target);
+		ancestors.add(decl);
+
+		Element parent = getParent(target);
+		while (parent != null) {
+			decl = query.getCMElementDeclaration(parent);
+			if (decl != null)
+				ancestors.add(decl);
+			parent = getParent(parent);
+		}
+		return ancestors;
+	}
+
+	private static void addInclusion(Hashtable availables, CMElementDeclaration decl) {
+		String name = decl.getElementName();
+		if (availables.containsKey(name))
+			return;
+		availables.put(name, decl);
+	}
+
+	private static Collection gatherInclusions(Collection ancestors) {
+		Vector inclusions = new Vector();
+		Iterator iter = ancestors.iterator();
+		while (iter.hasNext()) {
+			CMElementDeclaration decl = (CMElementDeclaration) iter.next();
+			if (decl.supports(HTMLCMProperties.INCLUSION)) {
+				CMContent inclusion = (CMContent) decl.getProperty(HTMLCMProperties.INCLUSION);
+				if (inclusion != null)
+					inclusions.add(inclusion);
+			}
+		}
+		return inclusions;
+	}
+
+	private static Element getParent(Node target) {
+		Node parent = target.getParentNode();
+		while (parent != null) {
+			if (parent.getNodeType() == Node.ELEMENT_NODE)
+				return (Element) parent;
+			parent = parent.getParentNode();
+		}
+		return null;
+	}
+
+	private static void extractDeclarations(Hashtable availables, CMGroup group) {
+		CMNodeList content = group.getChildNodes();
+		for (int i = 0; i < content.getLength(); i++) {
+			CMNode cmn = content.item(i);
+			if (cmn == null || cmn.getNodeType() != CMNode.ELEMENT_DECLARATION)
+				continue;
+			addInclusion(availables, (CMElementDeclaration) cmn);
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/modelquery/HTMLElementDeclarationAdapter.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/modelquery/HTMLElementDeclarationAdapter.java
new file mode 100644
index 0000000..76f0281
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/modelquery/HTMLElementDeclarationAdapter.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.modelquery;
+
+
+
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+
+/**
+ */
+public class HTMLElementDeclarationAdapter implements ElementDeclarationAdapter {
+
+	private CMElementDeclaration declaration = null;
+
+	/**
+	 */
+	public HTMLElementDeclarationAdapter() {
+		super();
+	}
+
+	/**
+	 */
+	public CMElementDeclaration getDeclaration() {
+		return this.declaration;
+	}
+
+	/**
+	 * Allowing the INodeAdapter to compare itself against the type
+	 * allows it to return true in more than one case.
+	 */
+	public boolean isAdapterForType(Object type) {
+		return (type == ElementDeclarationAdapter.class);
+	}
+
+	/**
+	 */
+	public void notifyChanged(INodeNotifier notifier, int eventType, Object changedFeature, Object oldValue, Object newValue, int pos) {
+	}
+
+	/**
+	 */
+	public void setDeclaration(CMElementDeclaration declaration) {
+		this.declaration = declaration;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/modelquery/HTMLModelQueryAssociationProvider.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/modelquery/HTMLModelQueryAssociationProvider.java
new file mode 100644
index 0000000..6d7fbbe
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/modelquery/HTMLModelQueryAssociationProvider.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.modelquery;
+
+
+
+import org.eclipse.wst.common.uriresolver.internal.provisional.URIResolver;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelqueryimpl.SimpleAssociationProvider;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.CMDocumentCache;
+
+/**
+ */
+public class HTMLModelQueryAssociationProvider extends SimpleAssociationProvider {
+
+	/**
+	 * @param modelQueryCMProvider org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQueryCMProvider
+	 */
+	public HTMLModelQueryAssociationProvider(CMDocumentCache cache, URIResolver idResolver) {
+		super(new HTMLModelQueryCMProvider(cache, idResolver));
+	}
+
+	// MIWA: We cannot cache a CMElementDeclaration any more.  Because, when the DOCTYPE
+	// was changed, CMDocument would be changed.  Then, a cached CMElementDeclaration
+	// would be invalid.  If some performance problems occurs, we consider a smarter
+	// cache mechanism.
+	//
+	//	public CMElementDeclaration getCMElementDeclaration(Element element) {
+	//		// check if element declaration is cached
+	//		INodeNotifier notifier = (INodeNotifier) element;
+	//		ElementDeclarationAdapter adapter = (ElementDeclarationAdapter) notifier.getExistingAdapter(ElementDeclarationAdapter.class);
+	//		if (adapter != null)
+	//			return adapter.getDeclaration();
+	//
+	//		CMElementDeclaration decl = super.getCMElementDeclaration(element);
+	//
+	//		// cache HTML element declaration only
+	//		if (decl != null && decl instanceof HTMLElementDeclaration) {
+	//			IAdapterFactory factory = ElementDeclarationAdapterFactory.getInstance();
+	//			adapter = (ElementDeclarationAdapter) factory.adapt(notifier);
+	//			if (adapter != null)
+	//				adapter.setDeclaration(decl);
+	//		}
+	//
+	//		return decl;
+	//	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/modelquery/HTMLModelQueryCMProvider.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/modelquery/HTMLModelQueryCMProvider.java
new file mode 100644
index 0000000..80c1ce5
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/modelquery/HTMLModelQueryCMProvider.java
@@ -0,0 +1,124 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.modelquery;
+
+
+import java.util.Hashtable;
+
+import org.eclipse.wst.common.uriresolver.internal.provisional.URIResolver;
+import org.eclipse.wst.html.core.internal.contentmodel.HTMLCMDocumentFactory;
+import org.eclipse.wst.html.core.internal.document.HTMLDocumentTypeEntry;
+import org.eclipse.wst.html.core.internal.document.HTMLDocumentTypeRegistry;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQueryCMProvider;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.CMDocumentCache;
+import org.eclipse.wst.xml.core.internal.provisional.contentmodel.CMDocType;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Node;
+
+/**
+ * CMDocument provider for HTML and XHTML documents.
+ * 
+ * This added and/or made public specifically for experimentation. It will
+ * change as this functionality becomes API. See
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=119084
+ */
+
+
+public class HTMLModelQueryCMProvider implements ModelQueryCMProvider {
+
+
+	private static CMDocument staticHTML5 = HTMLCMDocumentFactory.getCMDocument(CMDocType.HTML5_DOC_TYPE);
+	private static CMDocument staticHTML = HTMLCMDocumentFactory.getCMDocument(CMDocType.HTML_DOC_TYPE);
+	private static CMDocument staticCHTML = HTMLCMDocumentFactory.getCMDocument(CMDocType.CHTML_DOC_TYPE);
+	private static HTMLDocumentTypeRegistry doctypeRegistry = HTMLDocumentTypeRegistry.getInstance();
+	private static Hashtable buddyCache = new Hashtable();
+
+	private XHTMLAssociationProvider xhtmlassoc = null;
+
+	public HTMLModelQueryCMProvider(CMDocumentCache cache, URIResolver idResolver) {
+		super();
+		xhtmlassoc = new XHTMLAssociationProvider(cache, idResolver);
+	}
+
+	/**
+	 * Returns the CMDocument that corresponds to the DOM Node. or null if no
+	 * CMDocument is appropriate for the DOM Node.
+	 */
+	public CMDocument getCorrespondingCMDocument(Node node) {
+		IDOMDocument owner = getOwnerXMLDocument(node);
+		if (owner == null)
+			return null;
+
+		String pid = getPublicId(owner);
+		// no PID, always return the currently-supported HTML version
+		if (pid == null || "".equals(pid)){
+			return staticHTML5;
+		}
+
+		HTMLDocumentTypeEntry entry = doctypeRegistry.getEntry(pid);
+		if (entry == null)
+			return staticHTML;
+		
+		// https://bugs.eclipse.org/bugs/show_bug.cgi?id=151000 - use internal content model
+		if (entry.useInternalModel()) {
+			if (pid != null && pid.equals(HTMLDocumentTypeRegistry.CHTML_PUBLIC_ID)) {
+				return staticCHTML;
+			}
+			return staticHTML;
+		}
+
+		pid = entry.getPublicId();
+		String sid = entry.getSystemId();
+
+		CMDocument dtdcm = xhtmlassoc.getXHTMLCMDocument(pid, sid);
+		if (dtdcm == null) {
+			if (pid != null && pid.equals(HTMLDocumentTypeRegistry.CHTML_PUBLIC_ID)) {
+				return staticCHTML;
+			}
+			return staticHTML;
+		}
+
+		String grammarURI = xhtmlassoc.getCachedGrammerURI();
+		CMDocument buddycm = (CMDocument) buddyCache.get(grammarURI);
+		if (buddycm != null)
+			return buddycm;
+
+		buddycm = new CMDocumentForBuddySystem(dtdcm, entry.isXMLType());
+		buddyCache.put(grammarURI, buddycm);
+		return buddycm;
+	}
+
+	// private methods
+	private IDOMDocument getOwnerXMLDocument(Node node) {
+		if (node == null)
+			return null;
+		Document owner = (node.getNodeType() == Node.DOCUMENT_NODE) ? (Document) node : node.getOwnerDocument();
+		if (owner == null)
+			return null;
+		if (!(owner instanceof IDOMDocument))
+			return null;
+		return (IDOMDocument) owner;
+	}
+
+	private String getPublicId(IDOMDocument doc) {
+		if (doc == null)
+			return null;
+		DocumentType doctype = doc.getDoctype();
+		//doctype.
+		return (doctype != null) ? doctype.getPublicId() : doc.getDocumentTypeId();
+	}
+	
+	
+	
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/modelquery/HTMLModelQueryImpl.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/modelquery/HTMLModelQueryImpl.java
new file mode 100644
index 0000000..b3b02bd
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/modelquery/HTMLModelQueryImpl.java
@@ -0,0 +1,159 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.modelquery;
+
+
+import java.util.List;
+import java.util.Vector;
+
+import org.eclipse.wst.common.uriresolver.internal.provisional.URIResolver;
+import org.eclipse.wst.html.core.internal.provisional.HTMLCMProperties;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelqueryimpl.ModelQueryImpl;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.CMDocumentCache;
+import org.eclipse.wst.xml.core.internal.modelquery.XMLModelQueryAssociationProvider;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
+import org.eclipse.wst.xml.core.internal.ssemodelquery.MovableModelQuery;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+/**
+ * This added and/or made public specifically for experimentation. It
+ * will change as this functionality becomes API. See
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=119084
+ */
+ 
+public class HTMLModelQueryImpl extends ModelQueryImpl implements MovableModelQuery {
+
+	protected CMDocumentCache fCache = null;
+	protected XMLModelQueryAssociationProvider xmlAssocProv = null;
+
+	public HTMLModelQueryImpl(CMDocumentCache cache, URIResolver idResolver) {
+		super(new HTMLModelQueryAssociationProvider(cache, idResolver));
+		fCache = cache;
+		xmlAssocProv = new XMLModelQueryAssociationProvider(cache, idResolver);
+	}
+
+	public List getAvailableContent(Element element, CMElementDeclaration ed, int includeOptions) {
+		List originalCandidates = super.getAvailableContent(element, ed, includeOptions);
+		if ((includeOptions & INCLUDE_CHILD_NODES) == 0)
+			return originalCandidates;
+		// When the target document is XHTML, it is waste to find inclusions,
+		// since inclusion is available in HTML only.
+		if (!ed.supports(HTMLCMProperties.IS_XHTML))
+			return originalCandidates;
+		
+		Boolean isXhtml = Boolean.FALSE;
+		isXhtml = (Boolean) ed.getProperty(HTMLCMProperties.IS_XHTML);
+		if (isXhtml != null && isXhtml.booleanValue())
+			return originalCandidates;
+
+		// OK, the target is surely a HTML element, so it may have inclusion.
+		// Try to find it.
+		Vector candidates = new Vector(originalCandidates);
+
+		switch (ed.getContentType()) {
+			case CMElementDeclaration.ANY :
+			case CMElementDeclaration.ELEMENT :
+			case CMElementDeclaration.MIXED :
+				// do enumerate inclusions.
+				candidates.addAll(HMQUtil.getInclusions(element));
+				break;
+			case CMElementDeclaration.EMPTY :
+			case CMElementDeclaration.PCDATA :
+			case CMElementDeclaration.CDATA :
+			default :
+				// should not add any inclusions.
+				// so, nothing to do here.
+				break;
+		}
+		// If the current element does not available, it is impossible
+		// to filter out exclusion.
+		if (element == null)
+			return candidates;
+
+		// Now, the time to check exclusion.
+		Vector content = new Vector(candidates.size());
+		for (int i = 0; i < candidates.size(); i++) {
+			Object eCandidate = candidates.elementAt(i);
+			if(eCandidate instanceof CMElementDeclaration) {
+				CMElementDeclaration candidate = (CMElementDeclaration) eCandidate;
+				if (candidate == null)
+					continue;
+				if (isExcluded(candidate, element))
+					continue;
+				content.add(candidate);
+			}
+		}
+
+		return content;
+	}
+
+	/**
+	 * @see MovableModelQuery#setIdResolver(IdResolver)
+	 */
+	public void setIdResolver(URIResolver newIdResolver) {
+		modelQueryAssociationProvider = new HTMLModelQueryAssociationProvider(fCache, newIdResolver);
+	}
+
+	// utilities
+	private static boolean isExcluded(CMElementDeclaration candidate, Element target) {
+		CMNamedNodeMap prohibited = getProhibitedAncestors(candidate);
+		if (prohibited == null)
+			return false;
+		Element parent = target;
+		while (parent != null) {
+			CMNode pdec = prohibited.getNamedItem(parent.getNodeName());
+			if (pdec != null)
+				return true;
+			parent = getExplicitParentElement(parent);
+		}
+		return false;
+	}
+
+	private static CMNamedNodeMap getProhibitedAncestors(CMElementDeclaration dec) {
+		if (!dec.supports(HTMLCMProperties.PROHIBITED_ANCESTORS))
+			return null;
+		return (CMNamedNodeMap) dec.getProperty(HTMLCMProperties.PROHIBITED_ANCESTORS);
+	}
+
+	/* get an ancestor element ignoring implicit ones. */
+	private static Element getExplicitParentElement(Node child) {
+		if (child == null)
+			return null;
+
+		Node p = child.getParentNode();
+		while (p != null) {
+			if (p.getNodeType() == Node.ELEMENT_NODE) {
+				if (p instanceof IDOMElement) {
+					if (((IDOMElement) p).isImplicitTag()) {
+						p = p.getParentNode();
+						continue;
+					}
+				}
+				return (Element) p;
+			}
+			p = p.getParentNode();
+		}
+		return null;
+	}
+
+	public CMElementDeclaration getCMElementDeclaration(Element element) {
+		CMElementDeclaration result = super.getCMElementDeclaration(element);
+		if (null != result)
+			return result;
+		
+		return xmlAssocProv.getCMElementDeclaration(element);
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/modelquery/ModelQueryAdapterFactoryForEmbeddedHTML.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/modelquery/ModelQueryAdapterFactoryForEmbeddedHTML.java
new file mode 100644
index 0000000..ef7c263
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/modelquery/ModelQueryAdapterFactoryForEmbeddedHTML.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.modelquery;
+
+
+
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapter;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapterFactory;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.xml.core.internal.ssemodelquery.ModelQueryAdapter;
+
+public class ModelQueryAdapterFactoryForEmbeddedHTML extends ModelQueryAdapterFactoryForHTML {
+
+
+	/**
+	 * Constructor for ModelQueryAdapterFactoryForEmbeddedHTML.
+	 */
+	public ModelQueryAdapterFactoryForEmbeddedHTML() {
+		super(ModelQueryAdapter.class, false);
+	}
+
+
+	public INodeAdapterFactory copy() {
+
+		return new ModelQueryAdapterFactoryForEmbeddedHTML();
+	}
+
+	/**
+	 * ISSUE: this "forces" a new one to always be created/returned, not
+	 * "cached" on the node. That seems incorrect. Simply using
+	 * shouldRegisterFalse should work, except, there might have been one
+	 * there that someone else already explicitly put there, so this is only
+	 * way I know to override that. Especially complicated here since a number
+	 * of adapters are for ModelQueryAdapter.class.
+	 */
+	public INodeAdapter adapt(INodeNotifier object) {
+		return adaptNew(object);
+	}
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/modelquery/ModelQueryAdapterFactoryForHTML.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/modelquery/ModelQueryAdapterFactoryForHTML.java
new file mode 100644
index 0000000..9cc2f2e
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/modelquery/ModelQueryAdapterFactoryForHTML.java
@@ -0,0 +1,247 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.modelquery;
+
+
+
+import java.io.File;
+import java.net.URI;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.wst.common.uriresolver.internal.provisional.URIResolver;
+import org.eclipse.wst.html.core.internal.Logger;
+import org.eclipse.wst.sse.core.internal.provisional.AbstractAdapterFactory;
+import org.eclipse.wst.sse.core.internal.provisional.IModelStateListener;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapter;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapterFactory;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.util.Debug;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.CMDocumentCache;
+import org.eclipse.wst.xml.core.internal.modelquery.XMLCatalogIdResolver;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.eclipse.wst.xml.core.internal.ssemodelquery.ModelQueryAdapter;
+import org.eclipse.wst.xml.core.internal.ssemodelquery.ModelQueryAdapterImpl;
+
+/**
+ * Creates a ModelQueryAdapter for HTML models
+ */
+public class ModelQueryAdapterFactoryForHTML extends AbstractAdapterFactory {
+
+	ModelQueryAdapterImpl modelQueryAdapter;
+	IStructuredModel modelStateNotifier;
+	private InternalModelStateListener internalModelStateListener;
+
+	class InternalModelStateListener implements IModelStateListener {
+
+		/**
+		 * @see IModelStateListener#modelAboutToBeChanged(IStructuredModel)
+		 */
+		public void modelAboutToBeChanged(IStructuredModel model) {
+			// ISSUE: should we "freeze" state, or anything?
+		}
+
+		public void modelAboutToBeReinitialized(IStructuredModel structuredModel) {
+			// ISSUE: should we "freeze" state, or anything?
+
+		}
+
+		/**
+		 * @see IModelStateListener#modelChanged(IStructuredModel)
+		 */
+		public void modelChanged(IStructuredModel model) {
+			// nothing to do?
+		}
+
+		/**
+		 * @see IModelStateListener#modelDirtyStateChanged(IStructuredModel,
+		 *      boolean)
+		 */
+		public void modelDirtyStateChanged(IStructuredModel model, boolean isDirty) {
+			// nothing to do
+		}
+
+		public void modelReinitialized(IStructuredModel structuredModel) {
+			updateResolver(structuredModel);
+		}
+
+		/**
+		 * @see IModelStateListener#modelResourceDeleted(IStructuredModel)
+		 */
+		public void modelResourceDeleted(IStructuredModel model) {
+			// nothing to do?
+		}
+
+		/**
+		 * @see IModelStateListener#modelResourceMoved(IStructuredModel,
+		 *      IStructuredModel)
+		 */
+		public void modelResourceMoved(IStructuredModel oldModel, IStructuredModel newModel) {
+			modelStateNotifier.removeModelStateListener(this);
+			modelStateNotifier = newModel;
+			updateResolver(modelStateNotifier);
+			modelStateNotifier.addModelStateListener(this);
+		}
+
+		private void updateResolver(IStructuredModel model) {
+			String baseLocation = model.getBaseLocation();
+			IFile baseFile = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(model.getBaseLocation()));
+			if (baseFile != null) {
+				if (baseFile.getLocation() != null) {
+					baseLocation = baseFile.getLocation().toString();
+				}
+				if (baseLocation == null && baseFile.getLocationURI() != null) {
+					baseLocation = baseFile.getLocationURI().toString();
+				}
+				if (baseLocation == null) {
+					baseLocation = baseFile.getFullPath().toString();
+				}
+			}
+			else {
+				baseLocation = model.getBaseLocation();
+			}
+			modelQueryAdapter.setIdResolver(new XMLCatalogIdResolver(baseLocation, model.getResolver()));
+		}
+
+	}
+
+
+	/**
+	 * ModelQueryAdapterFactoryForHTML constructor comment. Note: this is a
+	 * case there the key is not exactly same as the class we are after.
+	 */
+	public ModelQueryAdapterFactoryForHTML() {
+		super(ModelQueryAdapter.class, true);
+	}
+
+	/**
+	 * We need this protected version to allow subclasses to pass up standard
+	 * behaviour.
+	 * 
+	 * @param adapterKey
+	 * @param registerAdapters
+	 */
+
+	protected ModelQueryAdapterFactoryForHTML(Object adapterKey, boolean registerAdapters) {
+		super(adapterKey, registerAdapters);
+	}
+
+
+
+	public INodeAdapterFactory copy() {
+
+		return new ModelQueryAdapterFactoryForHTML();
+	}
+
+	public void release() {
+		super.release();
+		if (modelStateNotifier != null) {
+			modelStateNotifier.removeModelStateListener(internalModelStateListener);
+		}
+
+		modelStateNotifier = null;
+
+		if (modelQueryAdapter != null) {
+			modelQueryAdapter.release();
+		}
+	}
+
+	/**
+	 * createAdapter method comment.
+	 * 
+	 * XXX: we must make this method more independent of 'location' (at least
+	 * provide some fall-back method).
+	 */
+	protected INodeAdapter createAdapter(INodeNotifier target) {
+
+		if (Debug.displayInfo) {
+			Logger.log(Logger.INFO_DEBUG, "-----------------------ModelQueryAdapterFactoryForHTML.createAdapter" + target); //$NON-NLS-1$
+		}
+		if (modelQueryAdapter == null) {
+			if (target instanceof IDOMNode) {
+				IDOMNode xmlNode = (IDOMNode) target;
+				modelStateNotifier = xmlNode.getModel();
+				modelStateNotifier.addModelStateListener(getInternalModelStateListener());
+
+				IStructuredModel model = xmlNode.getModel();
+				org.eclipse.wst.sse.core.internal.util.URIResolver resolver = model.getResolver();
+				if (Debug.displayInfo)
+					System.out.println("----------------ModelQueryAdapterFactoryForHTML... baseLocation : " + resolver.getFileBaseLocation()); //$NON-NLS-1$
+
+				/**
+				 * XMLCatalogIdResolver currently requires a filesystem
+				 * location string. Customarily this will be what is in the
+				 * deprecated SSE URIResolver and required by the Common URI
+				 * Resolver.
+				 */
+				URIResolver idResolver = null;
+				if (resolver != null) {
+					idResolver = new XMLCatalogIdResolver(resolver.getFileBaseLocation(), resolver);
+				}
+				else {
+					/*
+					 * 203649 - this block may be necessary due to ordering of
+					 * setting the resolver into the model
+					 */
+					String baseLocation = null;
+					String modelsBaseLocation = model.getBaseLocation();
+					if (modelsBaseLocation != null) {
+						File file = new Path(modelsBaseLocation).toFile();
+						if (file.exists()) {
+							baseLocation = file.getAbsolutePath();
+						}
+						else {
+							IPath basePath = new Path(model.getBaseLocation());
+							IResource derivedResource = null;
+							if (basePath.segmentCount() > 1)
+								derivedResource = ResourcesPlugin.getWorkspace().getRoot().getFile(basePath);
+							else
+								derivedResource = ResourcesPlugin.getWorkspace().getRoot().getProject(basePath.segment(0));
+							IPath derivedPath = derivedResource.getLocation();
+							if (derivedPath != null) {
+								baseLocation = derivedPath.toString();
+							}
+							else {
+								URI uri = derivedResource.getLocationURI();
+								if (uri != null) {
+									baseLocation = uri.toString();
+								}
+							}
+						}
+						if(baseLocation == null) {
+							baseLocation = modelsBaseLocation;
+						}
+					}
+					idResolver = new XMLCatalogIdResolver(baseLocation, null);
+				}
+				CMDocumentCache documentCache = new CMDocumentCache();
+				ModelQuery modelQuery = new HTMLModelQueryImpl(documentCache, idResolver);
+				modelQuery.setEditMode(ModelQuery.EDIT_MODE_UNCONSTRAINED);
+				modelQueryAdapter = new ModelQueryAdapterImpl(documentCache, modelQuery, idResolver);
+			}
+		}
+		return modelQueryAdapter;
+	}
+
+
+
+	private final InternalModelStateListener getInternalModelStateListener() {
+		if (internalModelStateListener == null) {
+			internalModelStateListener = new InternalModelStateListener();
+		}
+		return internalModelStateListener;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/modelquery/XHTMLAssociationProvider.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/modelquery/XHTMLAssociationProvider.java
new file mode 100644
index 0000000..4c44297
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/modelquery/XHTMLAssociationProvider.java
@@ -0,0 +1,209 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.modelquery;
+
+
+import java.lang.ref.Reference;
+import java.lang.ref.SoftReference;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtension;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.wst.common.uriresolver.internal.provisional.URIResolver;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.CMDocumentManager;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelqueryimpl.XMLAssociationProvider;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.CMDocumentCache;
+import org.w3c.dom.Document;
+
+/**
+ * A Class to provide an association between XHTML documents and DTDs for
+ * XHTML. This class is intended to be used only in HTMLModelQueryCMProvider.
+ */
+/*
+ * This class closely resemble XMLModelQueryAssociationProvider.
+ */
+class XHTMLAssociationProvider extends XMLAssociationProvider {
+	
+	/**
+	 * set CACHE_FIXED_DOCUMENTS to false to test effects of not caching certain catalog-contributed schemas.
+	 */
+	private static final boolean CACHE_FIXED_DOCUMENTS = true;
+	private static final String[] STANDARD_SCHEMA_BUNDLES = new String[] {"org.eclipse.wst.standard.schemas","org.eclipse.jst.standard.schemas"};
+	private static final String XML_CATALOG_EXT_POINT = "org.eclipse.wst.xml.core.catalogContributions"; 
+	private static Collection fFixedPublicIDs = null;
+	private static Map fFixedCMDocuments = new HashMap();
+
+	/**
+	 * set USE_QUICK_CACHE to false to test effects of not caching at all.
+	 */
+	private static final boolean USE_QUICK_CACHE = true;
+	protected URIResolver idResolver;
+	private String fCachedGrammerURI;
+	private String fCachedPublicID;
+	private String fCachedSystemID;
+	private boolean cached;
+
+	public XHTMLAssociationProvider(CMDocumentCache cache, URIResolver idResolver) {
+		super(cache);
+		this.idResolver = idResolver;
+		   
+		// See https://bugs.eclipse.org/bugs/show_bug.cgi?id=136399. If the CM document URI
+		// is resolved and cached at this level instruct the CM model manager to avoid 
+		// re-resolving the URI.
+
+		if (USE_QUICK_CACHE) {
+		  documentManager.setPropertyEnabled(CMDocumentManager.PROPERTY_PERFORM_URI_RESOLUTION, false);
+		}
+	}
+
+	/**
+	 * 
+	 * @param publicId
+	 * @param systemId
+	 * @return
+	 */
+	public CMDocument getXHTMLCMDocument(String publicId, String systemId) {
+		if (idResolver == null)
+			return null;
+		
+		String grammerURI = null;
+		if (USE_QUICK_CACHE) {
+			/*
+			 * In parsing a document, we get many identical requests to this
+			 * method, so instead of looking up (resolving) grammerURI each
+			 * time, we'll just return previously cached one. Probably not
+			 * worth have a more complex cache than that.
+			 */
+			if (cached && sameAs(fCachedPublicID, publicId) && sameAs(fCachedSystemID, systemId)) {
+				grammerURI = fCachedGrammerURI;
+			}
+			else {
+				grammerURI = idResolver.resolve(null, publicId, systemId);
+				fCachedGrammerURI = grammerURI;
+				fCachedPublicID = publicId;
+				fCachedSystemID = systemId;
+				cached = true;
+			}
+		}
+		else {
+			grammerURI = idResolver.resolve(null, publicId, systemId);
+		}
+
+		if (grammerURI == null)
+			return null;
+		
+		CMDocument cmDocument = null;
+		if (CACHE_FIXED_DOCUMENTS) {
+			Reference ref = (Reference) fFixedCMDocuments.get(publicId);
+			if (ref != null) {
+				cmDocument = (CMDocument) ref.get();
+				if (cmDocument != null) {
+					return cmDocument;
+				}
+			}
+		}
+		
+		/*
+		 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=88896
+		 * 
+		 * We once called the deprecated 2 argument form of getCMDocument.
+		 * 
+		 * CMDocument cmDocument = documentManager.getCMDocument(publicId,
+		 * grammerURI);
+		 * 
+		 * which eventually resulted in empty string for type, which I don't
+		 * think the infrastructure handles any longer. So, I deleted
+		 * deprecated methods, and switched to null for type argument.
+		 * 
+		 * 'null' means to "create based on uri".
+		 * 
+		 * FYI, 'dtd' would mean load only those registered as dtd's
+		 * 
+		 * CMDocument cmDocument = documentManager.getCMDocument(publicId,
+		 * grammerURI); CMDocument cmDocument =
+		 * documentManager.getCMDocument(publicId, grammerURI, "dtd");
+		 */
+		synchronized (grammerURI) {
+			cmDocument = documentManager.getCMDocument(publicId, grammerURI, null);
+		}
+		
+		if (CACHE_FIXED_DOCUMENTS && getFixedPublicIDs().contains(publicId)) {
+			fFixedCMDocuments.put(publicId, new SoftReference(cmDocument));
+		}
+		
+		return cmDocument;
+	}
+
+	/**
+	 */
+	protected String resolveGrammarURI(Document document, String publicId, String systemId) {
+		return idResolver.resolve(null, publicId, systemId);
+	}
+
+	private boolean sameAs(String a, String b) {
+		boolean result = false;
+		if (a == null) {
+			result = b == null;
+		}
+		else {
+			result = a.equals(b);
+		}
+		return result;
+	}
+
+	/**
+	 * This added and/or made public specifically for experimentation. It
+	 * will change as this functionality becomes API. See
+	 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=119084
+	 */
+	public String getCachedGrammerURI() {
+		return fCachedGrammerURI;
+	}
+
+	/**
+	 * @return the fFixedPublicIDs, a collection of contributed Public
+	 *         Identifiers from the known schema plug-ins.
+	 */
+	private static Collection getFixedPublicIDs() {
+		/**
+		 * public:publicId
+		 * TODO: system:systemId and uri:name in their own methods and maps?
+		 */
+		synchronized (STANDARD_SCHEMA_BUNDLES) {
+			if (fFixedPublicIDs == null) {
+				fFixedPublicIDs = new HashSet();
+				for (int i = 0; i < STANDARD_SCHEMA_BUNDLES.length; i++) {
+					IExtension[] extensions = Platform.getExtensionRegistry().getExtensions(STANDARD_SCHEMA_BUNDLES[i]);
+					for (int j = 0; j < extensions.length; j++) {
+						if (XML_CATALOG_EXT_POINT.equals(extensions[j].getExtensionPointUniqueIdentifier())) {
+							IConfigurationElement[] configurationElements = extensions[j].getConfigurationElements();
+							for (int k = 0; k < configurationElements.length; k++) {
+								IConfigurationElement[] publics = configurationElements[k].getChildren("public");
+								for (int l = 0; l < publics.length; l++) {
+									String publicId = publics[l].getAttribute("publicId");
+									if (publicId != null && publicId.length() > 0) {
+										fFixedPublicIDs.add(publicId);
+									}
+								}
+							}
+						}
+					}
+				}
+			}
+		}
+		return fFixedPublicIDs;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/preferences/HTMLCorePreferenceInitializer.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/preferences/HTMLCorePreferenceInitializer.java
new file mode 100644
index 0000000..3130e16
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/preferences/HTMLCorePreferenceInitializer.java
@@ -0,0 +1,131 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.preferences;
+
+import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer;
+import org.eclipse.core.runtime.preferences.DefaultScope;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences;
+import org.eclipse.wst.html.core.internal.HTMLCorePlugin;
+import org.eclipse.wst.sse.core.internal.encoding.CommonCharsetNames;
+import org.eclipse.wst.sse.core.internal.encoding.CommonEncodingPreferenceNames;
+import org.eclipse.wst.sse.core.internal.validate.ValidationMessage;
+
+/**
+ * Sets default values for HTML Core preferences
+ */
+public class HTMLCorePreferenceInitializer extends AbstractPreferenceInitializer {
+
+	public void initializeDefaultPreferences() {
+		IEclipsePreferences node = new DefaultScope().getNode(HTMLCorePlugin.getDefault().getBundle().getSymbolicName());
+
+		// formatting preferences
+		node.putInt(HTMLCorePreferenceNames.LINE_WIDTH, 72);
+		node.putBoolean(HTMLCorePreferenceNames.CLEAR_ALL_BLANK_LINES, false);
+		node.put(HTMLCorePreferenceNames.INDENTATION_CHAR, HTMLCorePreferenceNames.TAB);
+		node.putInt(HTMLCorePreferenceNames.INDENTATION_SIZE, 1);
+		node.putBoolean(HTMLCorePreferenceNames.SPLIT_MULTI_ATTRS, false);
+		node.putBoolean(HTMLCorePreferenceNames.ALIGN_END_BRACKET, false);
+
+		// cleanup preferences
+		node.putInt(HTMLCorePreferenceNames.CLEANUP_TAG_NAME_CASE, HTMLCorePreferenceNames.ASIS);
+		node.putInt(HTMLCorePreferenceNames.CLEANUP_ATTR_NAME_CASE, HTMLCorePreferenceNames.ASIS);
+		// node.putBoolean(HTMLCorePreferenceNames.COMPRESS_EMPTY_ELEMENT_TAGS,
+		// true);
+		node.putBoolean(HTMLCorePreferenceNames.INSERT_REQUIRED_ATTRS, true);
+		node.putBoolean(HTMLCorePreferenceNames.INSERT_MISSING_TAGS, true);
+		node.putBoolean(HTMLCorePreferenceNames.QUOTE_ATTR_VALUES, true);
+		node.putBoolean(HTMLCorePreferenceNames.FORMAT_SOURCE, true);
+		node.putBoolean(HTMLCorePreferenceNames.CONVERT_EOL_CODES, false);
+
+		// code generation preferences
+		node.put(CommonEncodingPreferenceNames.INPUT_CODESET, ""); //$NON-NLS-1$
+		String defaultEnc = "UTF-8";//$NON-NLS-1$
+		String systemEnc = System.getProperty("file.encoding"); //$NON-NLS-1$
+		if (systemEnc != null) {
+			defaultEnc = CommonCharsetNames.getPreferredDefaultIanaName(systemEnc, "UTF-8");//$NON-NLS-1$
+		}
+		node.put(CommonEncodingPreferenceNames.OUTPUT_CODESET, defaultEnc);
+		node.put(CommonEncodingPreferenceNames.END_OF_LINE_CODE, ""); //$NON-NLS-1$
+
+		node.putInt(HTMLCorePreferenceNames.TAG_NAME_CASE, HTMLCorePreferenceNames.LOWER);
+		node.putInt(HTMLCorePreferenceNames.ATTR_NAME_CASE, HTMLCorePreferenceNames.LOWER);
+
+		// this could be made smarter by actually looking up the content
+		// type's valid extensions
+		node.put(HTMLCorePreferenceNames.DEFAULT_EXTENSION, "html"); //$NON-NLS-1$
+
+		node.put(HTMLCorePreferenceNames.INLINE_ELEMENTS, "a,abbr,acronym,b,basefont,big,br,cite,em,font,i,img,input,label,li,q,s,select,small,span,strike,strong,sub,sup,td,th,title,u");
+		
+		initializeValidationPreferences(node);
+	}
+	
+	/**
+	 * Initializes the default validation preferences
+	 * @param node the Eclipse preference node
+	 */
+	private void initializeValidationPreferences(IEclipsePreferences node) {
+		// Attributes
+		node.putInt(HTMLCorePreferenceNames.ATTRIBUTE_UNDEFINED_NAME, ValidationMessage.WARNING);
+		node.putInt(HTMLCorePreferenceNames.ATTRIBUTE_UNDEFINED_VALUE, ValidationMessage.WARNING);
+		node.putInt(HTMLCorePreferenceNames.ATTRIBUTE_NAME_MISMATCH, ValidationMessage.WARNING);
+		node.putInt(HTMLCorePreferenceNames.ATTRIBUTE_INVALID_NAME, ValidationMessage.WARNING);
+		node.putInt(HTMLCorePreferenceNames.ATTRIBUTE_INVALID_VALUE, ValidationMessage.WARNING);
+		node.putInt(HTMLCorePreferenceNames.ATTRIBUTE_DUPLICATE, ValidationMessage.WARNING);
+		node.putInt(HTMLCorePreferenceNames.ATTRIBUTE_VALUE_MISMATCH, ValidationMessage.ERROR);
+		node.putInt(HTMLCorePreferenceNames.ATTRIBUTE_VALUE_UNCLOSED, ValidationMessage.WARNING);
+		node.putInt(HTMLCorePreferenceNames.ATTRIBUTE_VALUE_RESOURCE_NOT_FOUND, ValidationMessage.IGNORE);
+		node.putInt(HTMLCorePreferenceNames.ATTRIBUTE_OBSOLETE_NAME, ValidationMessage.WARNING);
+		
+		
+		// Elements
+		node.putInt(HTMLCorePreferenceNames.ELEM_UNKNOWN_NAME, ValidationMessage.WARNING);
+		node.putInt(HTMLCorePreferenceNames.ELEM_INVALID_NAME, ValidationMessage.ERROR);
+		node.putInt(HTMLCorePreferenceNames.ELEM_START_INVALID_CASE, ValidationMessage.WARNING);
+		node.putInt(HTMLCorePreferenceNames.ELEM_END_INVALID_CASE, ValidationMessage.ERROR);
+		node.putInt(HTMLCorePreferenceNames.ELEM_MISSING_START, ValidationMessage.WARNING);
+		node.putInt(HTMLCorePreferenceNames.ELEM_MISSING_END, ValidationMessage.WARNING);
+		node.putInt(HTMLCorePreferenceNames.ELEM_UNNECESSARY_END, ValidationMessage.WARNING);
+		node.putInt(HTMLCorePreferenceNames.ELEM_INVALID_DIRECTIVE, ValidationMessage.ERROR);
+		node.putInt(HTMLCorePreferenceNames.ELEM_INVALID_CONTENT, ValidationMessage.WARNING);
+		node.putInt(HTMLCorePreferenceNames.ELEM_DUPLICATE, ValidationMessage.WARNING);
+		node.putInt(HTMLCorePreferenceNames.ELEM_COEXISTENCE, ValidationMessage.WARNING);
+		node.putInt(HTMLCorePreferenceNames.ELEM_UNCLOSED_START_TAG, ValidationMessage.ERROR);
+		node.putInt(HTMLCorePreferenceNames.ELEM_UNCLOSED_END_TAG, ValidationMessage.ERROR);
+		node.putInt(HTMLCorePreferenceNames.ELEM_INVALID_EMPTY_TAG, ValidationMessage.WARNING);
+		node.putInt(HTMLCorePreferenceNames.ELEM_OBSOLETE_NAME, ValidationMessage.WARNING);
+		
+		
+		// DOCTYPE
+		node.putInt(HTMLCorePreferenceNames.DOC_DUPLICATE, ValidationMessage.ERROR);
+		node.putInt(HTMLCorePreferenceNames.DOC_INVALID_CONTENT, ValidationMessage.WARNING);
+		node.putInt(HTMLCorePreferenceNames.DOC_DOCTYPE_UNCLOSED, ValidationMessage.ERROR);
+		
+		// Text
+		node.putInt(HTMLCorePreferenceNames.TEXT_INVALID_CONTENT, ValidationMessage.WARNING);
+		node.putInt(HTMLCorePreferenceNames.TEXT_INVALID_CHAR, ValidationMessage.WARNING);
+		
+		// Comment
+		node.putInt(HTMLCorePreferenceNames.COMMENT_INVALID_CONTENT, ValidationMessage.WARNING);
+		node.putInt(HTMLCorePreferenceNames.COMMENT_UNCLOSED, ValidationMessage.ERROR);
+		
+		// CDATA
+		node.putInt(HTMLCorePreferenceNames.CDATA_INVALID_CONTENT, ValidationMessage.WARNING);
+		node.putInt(HTMLCorePreferenceNames.CDATA_UNCLOSED, ValidationMessage.ERROR);
+		
+		// Processing Instructions
+		node.putInt(HTMLCorePreferenceNames.PI_INVALID_CONTENT, ValidationMessage.WARNING);
+		node.putInt(HTMLCorePreferenceNames.PI_UNCLOSED, ValidationMessage.ERROR);
+		
+		// Entity Reference
+		node.putInt(HTMLCorePreferenceNames.REF_UNDEFINED, ValidationMessage.WARNING);
+		node.putInt(HTMLCorePreferenceNames.REF_INVALID_CONTENT, ValidationMessage.WARNING);
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/preferences/HTMLCorePreferenceNames.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/preferences/HTMLCorePreferenceNames.java
new file mode 100644
index 0000000..af1e90f
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/preferences/HTMLCorePreferenceNames.java
@@ -0,0 +1,289 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.preferences;
+
+/**
+ * Common preference keys used by HTML core
+ * 
+ * @plannedfor 1.0
+ */
+public class HTMLCorePreferenceNames {
+	private HTMLCorePreferenceNames() {
+		// empty private constructor so users cannot instantiate class
+	}
+
+	/**
+	 * The default extension to use when none is specified in the New HTML
+	 * File Wizard.
+	 * <p>
+	 * Value is of type <code>String</code>.
+	 * </p>
+	 */
+	public static final String DEFAULT_EXTENSION = "defaultExtension"; //$NON-NLS-1$
+
+	/**
+	 * The maximum width of a line before a line split is needed.
+	 * <p>
+	 * Value is of type <code>Integer</code>.
+	 * </p>
+	 */
+	public static final String LINE_WIDTH = "lineWidth";//$NON-NLS-1$
+
+	/**
+	 * Indicates if all blanks lines should be cleared during formatting.
+	 * Blank lines will be kept when false.
+	 * <p>
+	 * Value is of type <code>Boolean</code>.
+	 * </p>
+	 */
+	public static final String CLEAR_ALL_BLANK_LINES = "clearAllBlankLines";//$NON-NLS-1$
+
+	/**
+	 * The number of #INDENTATION_CHAR for 1 indentation.
+	 * <p>
+	 * Value is of type <code>Integer</code>.
+	 * </p>
+	 */
+	public static final String INDENTATION_SIZE = "indentationSize";//$NON-NLS-1$
+
+	/**
+	 * The character used for indentation.
+	 * <p>
+	 * Value is of type <code>String</code>.<br />
+	 * Possible values: {TAB, SPACE}
+	 * </p>
+	 */
+	public static final String INDENTATION_CHAR = "indentationChar";//$NON-NLS-1$
+
+	/**
+	 * Possible value for the preference #INDENTATION_CHAR. Indicates to use
+	 * tab character when formatting.
+	 * 
+	 * @see #SPACE
+	 * @see #INDENTATION_CHAR
+	 */
+	public static final String TAB = "tab"; //$NON-NLS-1$
+
+	/**
+	 * Possible value for the preference #INDENTATION_CHAR. Indicates to use
+	 * space character when formatting.
+	 * 
+	 * @see #TAB
+	 * @see #INDENTATION_CHAR
+	 */
+	public static final String SPACE = "space"; //$NON-NLS-1$
+
+	/**
+	 * Indicates if tags with multiple attributes should be formatted
+	 * (splitting each attr on a new line).
+	 * <p>
+	 * Value is of type <code>Boolean</code>.
+	 * </p>
+	 */
+	public static final String SPLIT_MULTI_ATTRS = "splitMultiAttrs";//$NON-NLS-1$
+
+	/**
+	 * Indicates if end brackets of start tags should be placed on a new line
+	 * if the start tag spans more than one line.
+	 * <p>
+	 * Value is of type <code>Boolean</code>.
+	 * </p>
+	 */
+	public static final String ALIGN_END_BRACKET = "alignEndBracket";//$NON-NLS-1$
+
+	/**
+	 * Indicates whether or not cleanup processor should format source.
+	 * <p>
+	 * Value is of type <code>Boolean</code>.
+	 * </p>
+	 */
+	public static final String FORMAT_SOURCE = "formatSource";//$NON-NLS-1$
+
+	/**
+	 * Indicates whether or not empty elements should be compressed during
+	 * cleanup.
+	 * <p>
+	 * Value is of type <code>Boolean</code>.
+	 * </p>
+	 */
+	public static final String COMPRESS_EMPTY_ELEMENT_TAGS = "compressEmptyElementTags";//$NON-NLS-1$
+
+	/**
+	 * Indicates whether or not to insert required attributes during cleanup.
+	 * <p>
+	 * Value is of type <code>Boolean</code>.
+	 * </p>
+	 */
+	public static final String INSERT_REQUIRED_ATTRS = "insertRequiredAttrs";//$NON-NLS-1$
+
+	/**
+	 * Indicates whether or not to insert missing tags during cleanup.
+	 * <p>
+	 * Value is of type <code>Boolean</code>.
+	 * </p>
+	 */
+	public static final String INSERT_MISSING_TAGS = "insertMissingTags";//$NON-NLS-1$
+
+	/**
+	 * Indicates whether or not to quote all attribute values during cleanup.
+	 * <p>
+	 * Value is of type <code>Boolean</code>.
+	 * </p>
+	 */
+	public static final String QUOTE_ATTR_VALUES = "quoteAttrValues";//$NON-NLS-1$
+
+	/**
+	 * Indicates whether or not to convert all line delimiters during cleanup.
+	 * <p>
+	 * Value is of type <code>Boolean</code>.
+	 * </p>
+	 */
+	public static final String CONVERT_EOL_CODES = "convertEOLCodes";//$NON-NLS-1$
+
+	/**
+	 * Indicates the line delimiter to use during cleanup if converting line
+	 * delimiters.
+	 * <p>
+	 * Value is of type <code>String</code>.<br />
+	 * Possible values: {CR, CRLF, LF, NO_TRANSLATION}
+	 * </p>
+	 * 
+	 */
+	public static final String CLEANUP_EOL_CODE = "cleanupEOLCode";//$NON-NLS-1$
+
+	/**
+	 * Indicates case to use on all tag names during cleanup.
+	 * <p>
+	 * Value is of type <code>Integer</code>.<br />
+	 * Possible values: {LOWER, UPPER, ASIS}
+	 * </p>
+	 */
+	public static final String CLEANUP_TAG_NAME_CASE = "cleanupTagNameCase";//$NON-NLS-1$
+
+	/**
+	 * Indicates case to use on all attribute names during cleanup.
+	 * <p>
+	 * Value is of type <code>Integer</code>.<br />
+	 * Possible values: {LOWER, UPPER, ASIS}
+	 * </p>
+	 */
+	public static final String CLEANUP_ATTR_NAME_CASE = "cleanupAttrNameCase";//$NON-NLS-1$
+
+	/**
+	 * Preferred markup case for tag names in code generation
+	 * <p>
+	 * Value is of type <code>Integer</code>.<br />
+	 * Possible values: {LOWER, UPPER}
+	 * </p>
+	 */
+	public static final String TAG_NAME_CASE = "tagNameCase";//$NON-NLS-1$
+
+	/**
+	 * Preferred markup case for attribute names in code generation
+	 * <p>
+	 * Value is of type <code>Integer</code>.<br />
+	 * Possible values: {LOWER, UPPER}
+	 * </p>
+	 */
+	public static final String ATTR_NAME_CASE = "attrNameCase";//$NON-NLS-1$
+
+	/**
+	 * Preferred elements to be considered as inline for the purposes of formatting
+	 * <p>
+	 * Value is a comma-separated list of element names
+	 * </p>
+	 */
+	public static final String INLINE_ELEMENTS = "inlineElements"; //$NON-NLS-1$
+
+	/**
+	 * Possible value for the preference #TAG_NAME_CASE or #ATTR_NAME_CASE.
+	 * Indicates to leave case as is.
+	 * 
+	 * @see #LOWER
+	 * @see #UPPER
+	 * @see #TAG_NAME_CASE
+	 * @see #ATTR_NAME_CASE
+	 */
+	public static final int ASIS = 0;
+
+	/**
+	 * Possible value for the preference #TAG_NAME_CASE or #ATTR_NAME_CASE.
+	 * Indicates to make name lowercase.
+	 * 
+	 * @see #ASIS
+	 * @see #UPPER
+	 * @see #TAG_NAME_CASE
+	 * @see #ATTR_NAME_CASE
+	 */
+	public static final int LOWER = 1;
+
+	/**
+	 * Possible value for the preference #TAG_NAME_CASE or #ATTR_NAME_CASE.
+	 * Indicates to make name uppercase.
+	 * 
+	 * @see #LOWER
+	 * @see #ASIS
+	 * @see #TAG_NAME_CASE
+	 * @see #ATTR_NAME_CASE
+	 */
+	public static final int UPPER = 2;
+	
+	public static final String USE_PROJECT_SETTINGS = "use-project-settings";//$NON-NLS-1$
+	
+	public static final String ATTRIBUTE_UNDEFINED_NAME = "attrUndefName";//$NON-NLS-1$
+	public static final String ATTRIBUTE_UNDEFINED_VALUE = "attrUndefValue";//$NON-NLS-1$
+	public static final String ATTRIBUTE_NAME_MISMATCH = "attrNameMismatch";//$NON-NLS-1$
+	public static final String ATTRIBUTE_INVALID_NAME = "attrInvalidName";//$NON-NLS-1$
+	public static final String ATTRIBUTE_INVALID_VALUE = "attrInvalidValue";//$NON-NLS-1$
+	public static final String ATTRIBUTE_DUPLICATE = "attrDuplicate";//$NON-NLS-1$
+	public static final String ATTRIBUTE_VALUE_MISMATCH = "attrValueMismatch";//$NON-NLS-1$
+	public static final String ATTRIBUTE_VALUE_UNCLOSED = "attrValueUnclosed";//$NON-NLS-1$
+	public static final String ATTRIBUTE_VALUE_RESOURCE_NOT_FOUND = "resourceNotFound";//$NON-NLS-1$
+	public static final String ATTRIBUTE_OBSOLETE_NAME = "attrObsoleteName";//$NON-NLS-1$
+	
+	
+	public static final String ELEM_UNKNOWN_NAME = "elemUnknownName";//$NON-NLS-1$
+	public static final String ELEM_INVALID_NAME = "elemInvalidName";//$NON-NLS-1$
+	public static final String ELEM_START_INVALID_CASE = "elemStartInvalidCase";//$NON-NLS-1$
+	public static final String ELEM_END_INVALID_CASE = "elemEndInvalidCase";//$NON-NLS-1$
+	public static final String ELEM_MISSING_START = "elemMissingStart";//$NON-NLS-1$
+	public static final String ELEM_MISSING_END = "elemMissingEnd";//$NON-NLS-1$
+	public static final String ELEM_UNNECESSARY_END = "elemUnnecessaryEnd";//$NON-NLS-1$
+	public static final String ELEM_INVALID_DIRECTIVE = "elemInvalidDirective";//$NON-NLS-1$
+	public static final String ELEM_INVALID_CONTENT = "elemInvalidContent";//$NON-NLS-1$
+	public static final String ELEM_DUPLICATE = "elemDuplicate";//$NON-NLS-1$
+	public static final String ELEM_COEXISTENCE = "elemCoexistence";//$NON-NLS-1$
+	public static final String ELEM_UNCLOSED_START_TAG = "elemUnclosedStartTag";//$NON-NLS-1$
+	public static final String ELEM_UNCLOSED_END_TAG = "elemUnclosedEndTag";//$NON-NLS-1$
+	public static final String ELEM_INVALID_EMPTY_TAG = "elemInvalidEmptyTag";//$NON-NLS-1$
+	public static final String ELEM_OBSOLETE_NAME = "elemObsoleteName";//$NON-NLS-1$
+	
+	public static final String DOC_DUPLICATE = "docDuplicateTag";//$NON-NLS-1$
+	public static final String DOC_INVALID_CONTENT = "docInvalidContent";//$NON-NLS-1$
+	public static final String DOC_DOCTYPE_UNCLOSED = "docDoctypeUnclosed";//$NON-NLS-1$
+	
+	public static final String TEXT_INVALID_CONTENT = "docInvalidContent";//$NON-NLS-1$
+	public static final String TEXT_INVALID_CHAR = "docInvalidChar";//$NON-NLS-1$
+	
+	public static final String COMMENT_INVALID_CONTENT = "commentInvalidContent";//$NON-NLS-1$
+	public static final String COMMENT_UNCLOSED = "commentUnclosed";//$NON-NLS-1$
+	
+	public static final String CDATA_INVALID_CONTENT = "cdataInvalidContent";//$NON-NLS-1$
+	public static final String CDATA_UNCLOSED = "cdataUnclosed";//$NON-NLS-1$
+	
+	public static final String PI_INVALID_CONTENT = "piInvalidContent";//$NON-NLS-1$
+	public static final String PI_UNCLOSED = "piUnclosed";//$NON-NLS-1$
+	
+	public static final String REF_INVALID_CONTENT = "refInvalidContent";//$NON-NLS-1$
+	public static final String REF_UNDEFINED = "piUndefined";//$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/provisional/HTML40Namespace.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/provisional/HTML40Namespace.java
new file mode 100644
index 0000000..5d1a53a
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/provisional/HTML40Namespace.java
Binary files differ
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/provisional/HTML50Namespace.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/provisional/HTML50Namespace.java
new file mode 100644
index 0000000..e20fdac
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/provisional/HTML50Namespace.java
@@ -0,0 +1,180 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.provisional;
+
+public interface HTML50Namespace extends HTML40Namespace {
+
+	public static interface ElementName extends HTML40Namespace.ElementName {
+		String ARTICLE = "article"; //$NON-NLS-1$
+		String ASIDE = "aside"; //$NON-NLS-1$
+		String AUDIO = "audio";
+		String CANVAS = "canvas";
+		String COMMAND = "command";
+		String DATALIST = "datalist";
+		String DETAILS = "details";
+		String FIGURE = "figure"; //$NON-NLS-1$
+		String FIGCAPTION = "figcaption"; //$NON-NLS-1$
+		String FOOTER = "footer"; //$NON-NLS-1$
+		String HEADER = "header";
+		String HGROUP = "hgroup";
+		String KEYGEN = "keygen";
+		String MARK = "mark";
+		String MATH = "math";
+		String METER = "meter";
+		String NAV = "nav";
+		String OUTPUT = "output";
+		String PROGRESS = "progress";
+		String RP = "rp";
+		String RT = "rt";
+		String RUBY = "ruby";
+		String SECTION = "section"; //$NON-NLS-1$
+		String SOURCE = "source";
+		String SUMMARY = "summary";
+		String SVG = "svg";
+		String TIME = "time";
+		String VIDEO = "video";
+	}
+
+	String HTML50_URI = "http://www.w3.org/TR/html50/";
+	String HTML50_TAG_PREFIX = "";
+
+	// global attribute names
+	String ATTR_NAME_CONTENT_EDITABLE = "contenteditable"; // %coreattrs; //$NON-NLS-1$
+	String ATTR_NAME_CONTEXT_MENU = "contextmenu"; // %coreattrs; //$NON-NLS-1$
+	String ATTR_NAME_DRAGGABLE = "draggable"; // %coreattrs; //$NON-NLS-1$
+	String ATTR_NAME_ROLE = "role"; // %coreattrs; //$NON_NLS-1$
+	String ATTR_NAME_SPELLCHECK = "spellcheck"; // %coreattrs; //$NON-NLS-1$
+	String ATTR_NAME_ONABORT = "onabort"; // %event; //$NON-NLS-1$
+	String ATTR_NAME_ONCAN_PLAY = "oncanplay"; // %event; //$NON-NLS-1$
+	String ATTR_NAME_ONCAN_PLAY_THROUGH = "oncanplaythrough"; // %event; //$NON-NLS-1$
+	String ATTR_NAME_ONCONTEXT_MENU = "oncontextmenu"; // %event; //$NON-NLS-1$
+	String ATTR_NAME_ONDRAG = "ondrag"; // %event; //$NON-NLS-1$
+	String ATTR_NAME_ONDRAG_END = "ondragend"; // %event; //$NON-NLS-1$
+	String ATTR_NAME_ONDRAG_OVER = "ondragover"; // %event; //$NON-NLS-1$
+	String ATTR_NAME_ONDRAG_ENTER = "ondragenter"; // %event; //$NON-NLS-1$
+	String ATTR_NAME_ONDRAG_LEAVE = "ondragleave"; // %event; //$NON-NLS-1$
+	String ATTR_NAME_ONDRAG_START = "ondragstart"; // %event; //$NON-NLS-1$
+	String ATTR_NAME_ONDROP = "ondrop"; // %event; //$NON-NLS-1$
+	String ATTR_NAME_ONDURATION_CHANGE = "ondurationchange"; // %event; //$NON-NLS-1$
+	String ATTR_NAME_ONEMPTIED = "onemptied"; // %event; //$NON-NLS-1$
+	String ATTR_NAME_ONENDED = "onended"; // %event; //$NON-NLS-1$
+	String ATTR_NAME_ONERROR = "onerror"; // %event; //$NON-NLS-1$
+	String ATTR_NAME_ONFORM_CHANGE = "onformchange"; // %event; //$NON-NLS-1$
+	String ATTR_NAME_ONFORM_INPUT = "onforminput"; // %event; //$NON-NLS-1$
+	String ATTR_NAME_ONINPUT = "oninput"; // %event; //$NON-NLS-1$
+	String ATTR_NAME_ONINVALID = "oninvalid"; // %event; //$NON-NLS-1$
+	String ATTR_NAME_ONLOADED_DATA = "onloadeddata"; // %event; //$NON-NLS-1$
+	String ATTR_NAME_ONLOADED_METADATA = "onloadedmetadeta"; // %event; //$NON-NLS-1$
+	String ATTR_NAME_ONLOAD_START = "onloadstart"; // %event; //$NON-NLS-1$
+	String ATTR_NAME_ONMOUSE_WHEEL = "onmousewheel"; // %event; //$NON-NLS-1$
+	String ATTR_NAME_ONPAUSE = "onpause"; // %event; //$NON-NLS-1$
+	String ATTR_NAME_ONPLAY = "onplay"; // %event; //$NON-NLS-1$
+	String ATTR_NAME_ONPLAYING = "onplaying"; // %event; //$NON-NLS-1$
+	String ATTR_NAME_ONPROGRESS = "onprogress"; // %event; //$NON-NLS-1$
+	String ATTR_NAME_ONRATE_CHANGE = "onratechange"; // %event; //$NON-NLS-1$
+	String ATTR_NAME_ONREADY_STATE_CHANGE = "onreadystatechange"; // %event; //$NON-NLS-1$
+	String ATTR_NAME_ONSCROLL = "onscroll"; // %event; //$NON-NLS-1$
+	String ATTR_NAME_ONSEEKED = "onseeked"; // %event; //$NON-NLS-1$
+	String ATTR_NAME_ONSEEKING = "onseeking"; // %event; //$NON-NLS-1$
+	String ATTR_NAME_ONSHOW = "onshow"; // %event; //$NON-NLS-1$
+	String ATTR_NAME_ONSTALLED = "onstalled"; // %event; //$NON-NLS-1$
+	String ATTR_NAME_ONSUSPEND = "onsuspend"; // %event; //$NON-NLS-1$
+	String ATTR_NAME_ONTIME_UPDATE = "ontimeupdate"; // %event; //$NON-NLS-1$
+	String ATTR_NAME_ONVOLUME_UPDATE = "onvolumeupdate"; // %event; //$NON-NLS-1$
+	String ATTR_NAME_ONWAITING = "onwaiting"; // %event; //$NON-NLS-1$
+
+	String ATTR_NAME_PING = "ping";
+	String ATTR_NAME_AUTOFOCUS = "autofocus";
+	String ATTR_NAME_CHALLENGE = "challenge";
+	String ATTR_NAME_FORM = "form";
+	String ATTR_NAME_KEYTYPE = "keytype";
+	String ATTR_NAME_REQUIRED = "required";
+	String ATTR_NAME_AUTOCOMPLETE = "autocomplete"; // input
+	String ATTR_NAME_MIN = "min"; // input
+	String ATTR_NAME_MAX = "max"; // input
+	String ATTR_NAME_PATTERN = "pattern"; // input
+	String ATTR_NAME_STEP = "step"; // input
+	String ATTR_NAME_NOVALIDATE = "novalidate"; // form
+	String ATTR_NAME_FORMACTION = "formaction"; // input|button
+	String ATTR_NAME_FORMENCTYPE = "formenctype"; // input|button
+	String ATTR_NAME_FORMMETHOD = "formmethod"; // input|button
+	String ATTR_NAME_FORMNOVALIDATE = "formnovalidate"; // input|button
+	String ATTR_NAME_FORMTARGET = "formtarget"; // input|button
+	String ATTR_NAME_SCOPED = "scoped"; // style
+	String ATTR_NAME_ASYNC = "async"; // script
+	String ATTR_NAME_MANIFEST = "manifest"; // html
+	String ATTR_NAME_SIZES = "sizes"; // link
+	String ATTR_NAME_REVERSED = "reversed"; // ol
+	String ATTR_NAME_SANDBOX = "sandbox"; // iframe
+	String ATTR_NAME_SEAMLESS = "seamless"; // iframe
+	String ATTR_NAME_SRCDOC = "srcdoc"; // iframe
+	String ATTR_NAME_PRELOAD = "preload"; // %mediaElement; //$NON-NLS-1$
+	String ATTR_NAME_AUTOPLAY = "autoplay"; // %mediaElement; //$NON-NLS-1$
+	String ATTR_NAME_LOOP = "loop"; // %mediaElement; //$NON-NLS-1$
+	String ATTR_NAME_CONTROLS = "controls"; // %mediaElement; //$NON-NLS-1$
+	String ATTR_NAME_POSTER = "poster"; // %video; //$NON-NLS-1$
+	String ATTR_NAME_OPEN = "open"; // details //$NON-NLS-1$
+	String ATTR_NAME_PUBDATE = "pubdate"; //time //$NON-NLS-1$
+	String ATTR_NAME_LOW = "low"; //meter //$NON-NLS-1$
+	String ATTR_NAME_HIGH = "high"; //meter //$NON-NLS-1$
+	String ATTR_NAME_OPTIMUM = "optimum"; //meter //$NON-NLS-1$
+	String ATTR_NAME_ICON = "icon"; //command //$NON-NLS-1$
+	String ATTR_NAME_RADIOGROUP = "radiogroup"; //command //$NON-NLS-1$
+	String ATTR_NAME_LIST = "list"; //input //$NON-NLS-1$
+	String ATTR_NAME_PLACEHOLDER = "placeholder"; //input //$NON-NLS-1$
+	String ATTR_NAME_WRAP = "wrap"; //textarea //$NON-NLS-1$
+	String ATTR_NAME_XMLNS = "xmlns"; //html //$NON-NLS-1$
+	
+	// Global attributes properties
+
+	// for contenteditable (EMPTY|TRUE|FALSE|INHERIT)
+	String ATTR_VALUE_EMPTY = ""; // contenteditable //$NON-NLS-1$
+	String ATTR_VALUE_INHERIT = "inherit"; // contenteditable //$NON-NLS-1$
+	
+	// for MediaElement (Audio/Video) 
+	String ATTR_VALUE_METADATA = "metadata"; // mediaelement //$NON-NLS-1$
+	
+	// for Command
+	String ATTR_VALUE_COMMAND = "command"; //command //$NON-NLS-1$
+	
+	//Input type
+	String ATTR_VALUE_SEARCH = "search"; //input type //$NON-NLS-1$
+	String ATTR_VALUE_TEL = "tel"; //input type //$NON-NLS-1$
+	String ATTR_VALUE_URL = "url"; //input type //$NON-NLS-1$
+	String ATTR_VALUE_EMAIL = "email"; //input type //$NON-NLS-1$
+	String ATTR_VALUE_DATE = "date"; //input type //$NON-NLS-1$
+	String ATTR_VALUE_DATETIME = "datetime"; //input type //$NON-NLS-1$
+	String ATTR_VALUE_MONTH = "month"; //input type //$NON-NLS-1$
+	String ATTR_VALUE_WEEK = "week"; //input type //$NON-NLS-1$
+	String ATTR_VALUE_TIME = "time"; //input type //$NON-NLS-1$
+	String ATTR_VALUE_DATETIME_LOCAL = "datetime-local"; //input type //$NON-NLS-1$
+	String ATTR_VALUE_RANGE = "range"; //input type //$NON-NLS-1$
+	String ATTR_VALUE_COLOR = "color"; //input type //$NON-NLS-1$
+	String ATTR_VALUE_NUMBER_STRING = "number"; //input type //$NON-NLS-1$
+
+	String ATTR_VALUE_ON = "on"; //input autocomplete //$NON-NLS-1$
+	String ATTR_VALUE_OFF = "off"; //input autocomplete //$NON-NLS-1$
+	
+	String ATTR_VALUE_PUT = "PUT"; //input formmethod //$NON-NLS-1$
+	String ATTR_VALUE_DELETE = "DELETE"; //input formmethod //$NON-NLS-1$
+	
+	String ATTR_VALUE_FORM_DATA = "multipart/form-data"; //input formencType //$NON-NLS-1$
+	String ATTR_VALUE_PLAIN = "text/plain"; //input formencType //$NON-NLS-1$
+	
+	String ATTR_VALUE_SOFT = "soft"; //textarea wrap //$NON-NLS-1$
+	String ATTR_VALUE_HARD = "hard"; //textarea wrap //$NON-NLS-1$
+	
+	
+	String ATTR_VALUE_CONTEXT = "context"; //menu type //$NON-NLS-1$
+	String ATTR_VALUE_TOOLBAR = "toolbar"; //menu type //$NON-NLS-1$
+	String ATTR_VALUE_LIST = "list"; //menu type //$NON-NLS-1$
+		
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/provisional/HTMLCMProperties.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/provisional/HTMLCMProperties.java
new file mode 100644
index 0000000..8098721
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/provisional/HTMLCMProperties.java
@@ -0,0 +1,121 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.provisional;
+
+
+/**
+ * HTMLCMProperties defines all property names and pre-defined values in HTML CM.
+ * All of those properties can be retreived from element declarations of HTML CM
+ * via CMNode#getProperty(String propName).
+ */
+public interface HTMLCMProperties {
+
+	/**
+	 * "shouldIgnoreCase" returns java.lang.Boolean object.
+	 */
+	public static final String SHOULD_IGNORE_CASE = "shouldIgnoreCase";//$NON-NLS-1$
+	/**
+	 * "shouldKeepSpace" returns java.lang.Boolean object.
+	 */
+	public static final String SHOULD_KEEP_SPACE = "shouldKeepSpace";//$NON-NLS-1$
+	/**
+	 * "indentChildSource" returns java.lang.Boolean object.
+	 */
+	public static final String SHOULD_INDENT_CHILD_SOURCE = "shouldIndentChildSource";//$NON-NLS-1$
+	/**
+	 * "terminators" returns java.util.Iterator (an array of String objects).
+	 */
+	public static final String TERMINATORS = "terminators";//$NON-NLS-1$
+	/**
+	 * "contentHint" returns CMElementDeclaration instnace.
+	 */
+	public static final String CONTENT_HINT = "contentHint";//$NON-NLS-1$
+	/**
+	 * "prohibitedAncestors" returns org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap.
+	 */
+	public static final String PROHIBITED_ANCESTORS = "prohibitedAncestors";//$NON-NLS-1$
+	/**
+	 * "isJSP" returns java.lang.Boolean object.
+	 */
+	public static final String IS_JSP = "isJSP";//$NON-NLS-1$
+	/**
+	 * "isXHTML" returns java.lang.Boolean object.
+	 */
+	public static final String IS_XHTML = "isXHTML";//$NON-NLS-1$
+	/**
+	 * "isSSI" returns java.lang.Boolean object.
+	 */
+	public static final String IS_SSI = "isSSI";//$NON-NLS-1$
+	/**
+	 * "lineBreakHint" returns String (one of pre-defined values in Values).
+	 */
+	public static final String LINE_BREAK_HINT = "lineBreakHint";//$NON-NLS-1$
+	/**
+	 * "layoutType" returns String (one of pre-defined values in Values).
+	 */
+	public static final String LAYOUT_TYPE = "layoutType";//$NON-NLS-1$
+	/**
+	 * "tagInfo" returns String (documentation for this element).
+	 */
+	public static final String TAGINFO = "tagInfo";//$NON-NLS-1$
+	/**
+	 * "omitType" returns String (one of pre-defined values in Values).
+	 */
+	public static final String OMIT_TYPE = "omitType";//$NON-NLS-1$
+	/**
+	 * "inclusion" returns org.eclipse.wst.xml.core.internal.contentmodel.CMContent.
+	 */
+	public static final String INCLUSION = "inclusion";//$NON-NLS-1$
+	/**
+	 * "isScriptable" returns java.lang.Boolean object.
+	 */
+	public static final String IS_SCRIPTABLE = "isScriptable"; //$NON-NLS-1$
+	/**
+	 * "isObsolete" returns java.lang.Boolean object.
+	 */
+	public static final String IS_OBSOLETE = "isObsolete";//$NON-NLS-1$
+	
+
+	public static interface Values {
+		/*
+		 * for LINE_BREAK_HINT = "lineBreakHint".
+		 */
+		public static final String BREAK_NONE = "breakNone";//$NON-NLS-1$
+		public static final String BREAK_AFTER_START = "breakAfterStart";//$NON-NLS-1$
+		public static final String BREAK_BEFORE_START_AND_AFTER_END = "breakBeforeStartAndAfterEnd";//$NON-NLS-1$
+		/*
+		 * for LAYOUT_TYPE = "layoutType"
+		 */
+		public static final String LAYOUT_BLOCK = "layoutBlock";//$NON-NLS-1$
+		/** BR */
+		public static final String LAYOUT_BREAK = "layoutBreak";//$NON-NLS-1$
+		/** Hidden object; like HTML or HEAD */
+		public static final String LAYOUT_HIDDEN = "layoutHidden";//$NON-NLS-1$
+		public static final String LAYOUT_NONE = "layoutNone";//$NON-NLS-1$
+		/** No wrap object; like IMG, APPLET,... */
+		public static final String LAYOUT_OBJECT = "layoutObject";//$NON-NLS-1$
+		public static final String LAYOUT_WRAP = "layoutWrap";//$NON-NLS-1$
+		/*
+		 * for OMIT_TYPE = "omitType"
+		 */
+		/** Not ommisible. */
+		public static final String OMIT_NONE = "omitNone";//$NON-NLS-1$
+		/** Both tags are ommisible. */
+		public static final String OMIT_BOTH = "omitBoth";//$NON-NLS-1$
+		/** The end tag is ommisible. */
+		public static final String OMIT_END = "omitEnd";//$NON-NLS-1$
+		/** The end tag is ommitted when created. */
+		public static final String OMIT_END_DEFAULT = "omitEndDefault";//$NON-NLS-1$
+		/** The end tag must be omitted. */
+		public static final String OMIT_END_MUST = "omitEndMust";//$NON-NLS-1$
+
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/provisional/HTMLFilesPreferenceNames.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/provisional/HTMLFilesPreferenceNames.java
new file mode 100644
index 0000000..88bb2ea
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/provisional/HTMLFilesPreferenceNames.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.provisional;
+
+import org.eclipse.core.runtime.IProduct;
+import org.eclipse.core.runtime.Platform;
+
+/**
+ * @deprecated not used in WTP
+ */
+public interface HTMLFilesPreferenceNames {
+
+	static final String DEFAULT_SUFFIX = "defaultSuffix";//$NON-NLS-1$
+	static final String HTML_SUFFIX = "html";//$NON-NLS-1$
+	static final String GENERATE_DOCUMENT_TYPE = "generateDocumentType";//$NON-NLS-1$
+	static final String GENERATE_GENERATOR = "generateGenerator";//$NON-NLS-1$
+	// added this as a potential way to handle changing
+	// product names "up" the stack. Note, not declared final 
+	// to avoid getting 'inlined' by compiler.
+	static IProduct product = Platform.getProduct();
+	// Platform.getProduct() is spec'd so it might return null.
+	// Its expected for any final product it would not be, so we'll return 
+	// "WTP" for development/interim builds. No need to translate. 
+	static String GENERATOR = (product == null) ? "WTP": product.getName(); //$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/provisional/HTMLFormatContraints.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/provisional/HTMLFormatContraints.java
new file mode 100644
index 0000000..db3217e
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/provisional/HTMLFormatContraints.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.provisional;
+
+import org.eclipse.wst.sse.core.internal.format.IStructuredFormatContraints;
+
+/**
+ * @deprecated
+ * Please un-deprecate this if Page Designer thinks they are needed.
+ */
+public interface HTMLFormatContraints extends IStructuredFormatContraints {
+	/**
+	 * @deprecated
+	 * 	It's very hard to keep the available line width accurate.
+	 * 	Sometimes a node wants to start on a new line, sometimes it doesn't.
+	 * 	It's best for the node to figure out the available line width on the fly.
+	 */
+	int getAvailableLineWidth();
+
+	/**
+	 * @deprecated
+	 * 	It's very hard to keep the available line width accurate.
+	 * 	Sometimes a node wants to start on a new line, sometimes it doesn't.
+	 * 	It's best for the node to figure out the available line width on the fly.
+	 */
+	void setAvailableLineWidth(int availableLineWidth);
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/provisional/PreferenceNames.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/provisional/PreferenceNames.java
new file mode 100644
index 0000000..5d1018a
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/provisional/PreferenceNames.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.provisional;
+
+
+public interface PreferenceNames {
+
+	String TRUE = "true"; //$NON-NLS-1$
+	String FALSE = "false"; //$NON-NLS-1$
+	String YES = "yes"; //$NON-NLS-1$
+	String NO = "no"; //$NON-NLS-1$
+
+
+	String SETTINGS = "settings"; //$NON-NLS-1$
+
+	String TREEVIEW = "treeview"; //$NON-NLS-1$
+	String DEFAULT_DEPTH = "defaultdepth"; //$NON-NLS-1$
+
+	String ASIS = "as-is"; //$NON-NLS-1$
+	String LOWER = "lower"; //$NON-NLS-1$
+	String UPPER = "upper"; //$NON-NLS-1$
+
+	String PREFERRED_CASE = "preferred-case"; //$NON-NLS-1$
+	String TAGNAME = "tagname"; //$NON-NLS-1$
+	String ATTRIBUTENAME = "attributename"; //$NON-NLS-1$
+
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/provisional/contenttype/ContentTypeFamilyForHTML.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/provisional/contenttype/ContentTypeFamilyForHTML.java
new file mode 100644
index 0000000..35f17ff
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/provisional/contenttype/ContentTypeFamilyForHTML.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+
+package org.eclipse.wst.html.core.internal.provisional.contenttype;
+
+/**
+ * The value of the contenttype id field must match what is specified in
+ * plugin.xml file. Note: this value is intentially set with default protected
+ * method so it will not be inlined.
+ */
+
+public class ContentTypeFamilyForHTML {
+	/**
+	 * The value of the contenttype id field must match what is specified in
+	 * plugin.xml file. Note: this value is intentially not declared as final,
+	 * so it will not be inlined.
+	 */
+	public final static String HTML_FAMILY = getConstantString();
+
+	/**
+	 * Don't allow instantiation.
+	 */
+	private ContentTypeFamilyForHTML() {
+		super();
+	}
+
+	static String getConstantString() {
+		return "org.eclipse.wst.html.core.contentfamily.html"; //$NON-NLS-1$
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/provisional/contenttype/ContentTypeIdForHTML.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/provisional/contenttype/ContentTypeIdForHTML.java
new file mode 100644
index 0000000..6649119
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/provisional/contenttype/ContentTypeIdForHTML.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+
+package org.eclipse.wst.html.core.internal.provisional.contenttype;
+
+/**
+ * The value of the contenttype id field must match what is specified in
+ * plugin.xml file. Note: this value is intentially set with default protected
+ * method so it will not be inlined.
+ */
+
+public class ContentTypeIdForHTML {
+	/**
+	 * The value of the contenttype id field must match what is specified in
+	 * plugin.xml file. Note: this value is intentially not declared as final,
+	 * so it will not be inlined.
+	 */
+	public final static String ContentTypeID_HTML = getConstantString();
+
+	/**
+	 * Don't allow instantiation.
+	 */
+	private ContentTypeIdForHTML() {
+		super();
+	}
+
+	static String getConstantString() {
+		return "org.eclipse.wst.html.core.htmlsource"; //$NON-NLS-1$
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/provisional/text/IHTMLPartitionTypes.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/provisional/text/IHTMLPartitionTypes.java
new file mode 100644
index 0000000..50f61db
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/provisional/text/IHTMLPartitionTypes.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.provisional.text;
+
+
+/**
+ * This interface is not intended to be implemented. It defines the partition
+ * types for HTML. Clients should reference the partition type Strings defined
+ * here directly.
+ * 
+ * @deprecated use org.eclipse.wst.html.core.text.IHTMLPartitions
+ */
+public interface IHTMLPartitionTypes {
+
+	String HTML_DEFAULT = "org.eclipse.wst.html.HTML_DEFAULT"; //$NON-NLS-1$
+	String HTML_DECLARATION = "org.eclipse.wst.html.HTML_DECLARATION"; //$NON-NLS-1$
+	String HTML_COMMENT = "org.eclipse.wst.html.HTML_COMMENT"; //$NON-NLS-1$
+
+	String SCRIPT = "org.eclipse.wst.html.SCRIPT"; //$NON-NLS-1$
+	String STYLE = "org.eclipse.wst.html.STYLE"; //$NON-NLS-1$
+
+	// ISSUE: I think meta tag areas are here too?
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/text/StructuredTextPartitionerForHTML.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/text/StructuredTextPartitionerForHTML.java
new file mode 100644
index 0000000..08c61ee
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/text/StructuredTextPartitionerForHTML.java
@@ -0,0 +1,318 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.text;
+
+import java.util.Locale;
+
+import org.eclipse.jface.text.IDocumentPartitioner;
+import org.eclipse.wst.css.core.text.ICSSPartitions;
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.html.core.text.IHTMLPartitions;
+import org.eclipse.wst.sse.core.internal.parser.ForeignRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredTextPartitioner;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList;
+import org.eclipse.wst.sse.core.internal.text.IRegionComparible;
+import org.eclipse.wst.sse.core.internal.text.rules.IStructuredTypedRegion;
+import org.eclipse.wst.sse.core.internal.util.ScriptLanguageKeys;
+import org.eclipse.wst.sse.core.utils.StringUtils;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+import org.eclipse.wst.xml.core.internal.text.rules.StructuredTextPartitionerForXML;
+
+/**
+ * Document partitioner for HTML. Client-side scripts of type JavaScript are
+ * reported as ST_SCRIPT, all others for <script language="foo" type="foo2">
+ * as SCRIPT.language:FOO and SCRIPT.type:FOO2.
+ */
+public class StructuredTextPartitionerForHTML extends StructuredTextPartitionerForXML implements IStructuredTextPartitioner {
+
+	private final static String[] configuredContentTypes = new String[]{IHTMLPartitions.HTML_DEFAULT, IHTMLPartitions.HTML_DECLARATION, IHTMLPartitions.HTML_COMMENT, IHTMLPartitions.SCRIPT, ICSSPartitions.STYLE,IHTMLPartitions.SCRIPT_EVENTHANDLER};
+
+	public static final String JAVASCRIPT = "javascript"; //$NON-NLS-1$
+	public static final String JAVASCRIPT_APPLICATION = "application/x-javascript"; //$NON-NLS-1$
+	
+	private static final String[] EVENT_ATTRIBUTE_NAMES = 
+		{HTML40Namespace.ATTR_NAME_ONCLICK, 
+		HTML40Namespace.ATTR_NAME_ONDBLCLICK,
+		HTML40Namespace.ATTR_NAME_ONMOUSEDOWN,
+		HTML40Namespace.ATTR_NAME_ONMOUSEUP,
+		HTML40Namespace.ATTR_NAME_ONMOUSEOVER,
+		HTML40Namespace.ATTR_NAME_ONMOUSEMOVE,
+		HTML40Namespace.ATTR_NAME_ONMOUSEOUT,
+		HTML40Namespace.ATTR_NAME_ONKEYPRESS,
+		HTML40Namespace.ATTR_NAME_ONKEYDOWN,
+		HTML40Namespace.ATTR_NAME_ONKEYUP,
+		HTML40Namespace.ATTR_NAME_ONHELP,
+		HTML40Namespace.ATTR_NAME_ONBLUR,
+		HTML40Namespace.ATTR_NAME_ONFOCUS,
+		HTML40Namespace.ATTR_NAME_ONLOAD,
+		HTML40Namespace.ATTR_NAME_ONUNLOAD,
+		HTML40Namespace.ATTR_NAME_ONSUBMIT};
+	
+	/** array of style attribute names */
+	private static final String[] STYLE_ATTRIBUTE_NAMES =  {HTML40Namespace.ATTR_NAME_STYLE};
+	
+	public StructuredTextPartitionerForHTML() {
+		super();
+	}
+
+	public IStructuredTypedRegion createPartition(int offset, int length, String type) {
+		if (type == IHTMLPartitions.SCRIPT) {
+			IStructuredDocumentRegion node = fStructuredDocument.getRegionAtCharacterOffset(offset);
+			if (node != null) {
+				String stype = getScriptingPartitionType(node);
+				return super.createPartition(offset, length, stype);
+			}
+		}
+		return super.createPartition(offset, length, type);
+	}
+
+	protected void setInternalPartition(int offset, int length, String type) {
+		String localType = type;
+		if (type == IHTMLPartitions.SCRIPT) {
+			IStructuredDocumentRegion node = fStructuredDocument.getRegionAtCharacterOffset(offset);
+			if (node != null) {
+				localType = getScriptingPartitionType(node);
+			}
+		}
+		super.setInternalPartition(offset, length, localType);
+	}
+
+	private String getScriptingPartitionType(IStructuredDocumentRegion coreNode) {
+		String language = null;
+		String type = null;
+		String result = IHTMLPartitions.SCRIPT;
+		IStructuredDocumentRegion node = coreNode;
+		ITextRegion attrNameRegion = null;
+		while (node != null && isValidScriptingRegionType(node.getType())) {
+			node = node.getPrevious();
+		}
+
+		ITextRegionList regions = node.getRegions();
+		if (regions.size() > 4 && regions.get(1).getType() == DOMRegionContext.XML_TAG_NAME) {
+			ITextRegion potentialLanguageRegion = regions.get(1);
+			String potentialLanguageString = node.getText(potentialLanguageRegion);
+			if (potentialLanguageString.equalsIgnoreCase(HTML40Namespace.ElementName.SCRIPT)) {
+				for (int i = 0; i < regions.size(); i++) {
+					ITextRegion region = regions.get(i);
+					String regionType = region.getType();
+					if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME)
+						attrNameRegion = region;
+					else if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
+						String attrName = node.getText(attrNameRegion);
+						if (attrName.equalsIgnoreCase(HTML40Namespace.ATTR_NAME_LANGUAGE))
+							language = StringUtils.strip(node.getText(region));
+						else if (attrName.equalsIgnoreCase(HTML40Namespace.ATTR_NAME_TYPE)) {
+							type = StringUtils.strip(node.getText(region));
+							/*
+							 * Avoid partition names built with MIME subtypes,
+							 * e.g. type="text/javascript;e4x=1"
+							 */
+							if (type != null) {
+								int index = type.indexOf(';');
+								if (index > 1)
+									type = type.substring(0, index);
+							}
+							break;
+						}
+						attrNameRegion = null;
+					}
+				}
+			}
+		}
+		if (type != null)
+			result = lookupScriptType(type);
+		else if (language != null)
+			result = lookupScriptLanguage(language);
+		return result;
+	}
+
+	private boolean isValidScriptingRegionType(String type) {
+		return type == DOMRegionContext.BLOCK_TEXT || type == DOMRegionContext.XML_CDATA_OPEN || type == DOMRegionContext.XML_CDATA_TEXT || type == DOMRegionContext.XML_CDATA_CLOSE;
+	}
+
+	protected void initLegalContentTypes() {
+		fSupportedTypes = getConfiguredContentTypes();
+	}
+
+	private String lookupScriptType(String type) {
+		for (int i = 0; i < ScriptLanguageKeys.JAVASCRIPT_MIME_TYPE_KEYS.length; i++)
+			if (ScriptLanguageKeys.JAVASCRIPT_MIME_TYPE_KEYS[i].equalsIgnoreCase(type))
+				return IHTMLPartitions.SCRIPT;
+		return IHTMLPartitions.SCRIPT + ".type." + type.toUpperCase(Locale.ENGLISH); //$NON-NLS-1$
+	}
+
+	private String lookupScriptLanguage(String language) {
+		for (int i = 0; i < ScriptLanguageKeys.JAVASCRIPT_LANGUAGE_KEYS.length; i++)
+			if (ScriptLanguageKeys.JAVASCRIPT_LANGUAGE_KEYS[i].equalsIgnoreCase(language))
+				return IHTMLPartitions.SCRIPT;
+		return IHTMLPartitions.SCRIPT + ".language." + language.toUpperCase(Locale.ENGLISH); //$NON-NLS-1$
+	}
+
+	public String getPartitionType(ITextRegion region, int offset) {
+		String result = null;
+		if (region.getType() == DOMRegionContext.XML_COMMENT_TEXT || region.getType() == DOMRegionContext.XML_COMMENT_OPEN || region.getType() == DOMRegionContext.XML_COMMENT_CLOSE)
+			result = IHTMLPartitions.HTML_COMMENT;
+		else if (region.getType() == DOMRegionContext.XML_DOCTYPE_DECLARATION || region.getType() == DOMRegionContext.XML_DECLARATION_OPEN)
+			result = IHTMLPartitions.HTML_DECLARATION;
+		else if (region.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE && isScriptAttributeValue(region, offset))
+			result = IHTMLPartitions.SCRIPT_EVENTHANDLER;
+		else if (isStyleAttributeValue(region, offset))
+			result = ICSSPartitions.STYLE;
+		else
+			result = super.getPartitionType(region, offset);
+		return result;
+	}
+
+	public String getPartitionTypeBetween(IStructuredDocumentRegion previousNode, IStructuredDocumentRegion nextNode) {
+		
+		ITextRegion previousStartTagNameRegion = null;
+		ITextRegion nextEndTagNameRegion = null;
+		
+		ITextRegion[] regions = previousNode.getRegions().toArray();
+		for (int i = 0; i < regions.length; i++) {
+			if(regions[i].getType() == DOMRegionContext.XML_TAG_NAME) {
+				previousStartTagNameRegion = regions[i];
+				break;
+			}
+		}
+		regions = nextNode.getRegions().toArray();
+		for (int i = 0; i < regions.length; i++) {
+			if(regions[i].getType() == DOMRegionContext.XML_TAG_NAME) {
+				nextEndTagNameRegion = regions[i];
+				break;
+			}
+		}
+		
+		if(previousStartTagNameRegion == null || nextEndTagNameRegion == null)
+			return IHTMLPartitions.HTML_DEFAULT;
+		
+		String name1 = previousNode.getText(previousStartTagNameRegion);
+		String name2 = nextNode.getText(nextEndTagNameRegion);
+		if (name1.equalsIgnoreCase(HTML40Namespace.ElementName.SCRIPT) && name2.equalsIgnoreCase(HTML40Namespace.ElementName.SCRIPT))
+			//			return ST_SCRIPT;
+			return getScriptingPartitionType(fStructuredDocument.getRegionAtCharacterOffset(previousNode.getStartOffset(previousStartTagNameRegion)));
+		else if (name1.equalsIgnoreCase(HTML40Namespace.ElementName.STYLE) && name2.equalsIgnoreCase(HTML40Namespace.ElementName.STYLE))
+			return ICSSPartitions.STYLE;
+		return super.getPartitionTypeBetween(previousNode, nextNode);
+	}
+
+
+	protected String getPartitionType(ForeignRegion region, int offset) {
+		String tagname = region.getSurroundingTag();
+		String result = null;
+		// tagname should not be null,
+		// but see https://w3.opensource.ibm.com/bugzilla/show_bug.cgi?id=4911
+		if (tagname == null) {
+			result = getUnknown();
+		}
+		else if (tagname.equalsIgnoreCase(HTML40Namespace.ElementName.SCRIPT))
+			result = IHTMLPartitions.SCRIPT;
+		else if (tagname.equalsIgnoreCase(HTML40Namespace.ElementName.STYLE) || isStyleAttributeValue(region,offset))
+			result = ICSSPartitions.STYLE;
+		else if (region.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE && isScriptAttributeValue(region, offset))
+			result = IHTMLPartitions.SCRIPT_EVENTHANDLER;
+		else
+			result = super.getPartitionType(region, offset);
+
+		return result;
+	}
+
+	public String getDefaultPartitionType() {
+		return IHTMLPartitions.HTML_DEFAULT;
+	}
+
+	public IDocumentPartitioner newInstance() {
+		return new StructuredTextPartitionerForHTML();
+	}
+
+	/**
+	 * @return
+	 */
+	public static String[] getConfiguredContentTypes() {
+		return configuredContentTypes;
+	}
+	
+	private boolean isScriptAttributeValue(ITextRegion region, int offset) {
+		if (region.getType() != DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE)
+			return false;
+
+		return isAttributeNameForValueInArray(EVENT_ATTRIBUTE_NAMES, region, offset);
+	}
+	
+	/**
+	 * @param region {@link ITextRegion} containing <code>offset</code>
+	 * @param offset offset in the given <code>region</code> to check if it is in
+	 * the attribute value region of a style attribute
+	 * @return <code>true</code> if the given offset in the given region is
+	 * in the value region of a style attribute, <code>false</code> otherwise
+	 */
+	private boolean isStyleAttributeValue(ITextRegion region, int offset) {
+		boolean isStyleAttributeValue = false;
+		if (region.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
+			isStyleAttributeValue = isAttributeNameForValueInArray(STYLE_ATTRIBUTE_NAMES, region, offset);
+		}
+
+		return isStyleAttributeValue;
+	}
+	
+	/**
+	 * <p>determines if the attribute name associated with the given attribute region
+	 * is in the given array of attribute names</p>
+	 * 
+	 * @param attributeNames determine if the attribute name associated with the given offset
+	 * is in this array of attribute names
+	 * @param attrValueRegion {@link ITextRegion} of the attribute region containing the given offset
+	 * @param offset offset in an attribute region to determine if it is in the list of given attribute names
+	 * @return <code>true</code> if the attribute name associated with the given offset is in the given
+	 * list of attribute names, <code>false</code> otherwise
+	 */
+	private boolean isAttributeNameForValueInArray(String[] attributeNames, ITextRegion attrValueRegion, int offset) {
+		IStructuredDocumentRegion node = fStructuredDocument.getRegionAtCharacterOffset(offset);
+		ITextRegionList regionList = node.getRegions();
+		int currentIndex = regionList.indexOf(attrValueRegion);
+		
+		/*
+		 * 4 is the minimum index allowing for the tag's open, name, attribute
+		 * name and equals character to appear first
+		 */
+		if (currentIndex < 4)
+			return false;
+		ITextRegion tagAttrNameRegion = regionList.get(currentIndex - 2);
+		
+		boolean foundAttributeName = false;
+		if (fStructuredDocument instanceof IRegionComparible) {
+			int start = node.getStartOffset(tagAttrNameRegion);
+			for (int i = 0; !foundAttributeName && i < attributeNames.length; i++) {
+				foundAttributeName = ((IRegionComparible) fStructuredDocument).regionMatchesIgnoreCase(start, tagAttrNameRegion.getTextLength(), attributeNames[i]);
+			}
+		}
+		else {
+			String tagAttrName = node.getText(tagAttrNameRegion);
+			foundAttributeName = StringUtils.contains(attributeNames, tagAttrName, false);
+		}
+		return foundAttributeName;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.sse.core.internal.text.rules.StructuredTextPartitioner#getParserSpecificPreviousRegion(org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion)
+	 */
+	protected IStructuredDocumentRegion getParserSpecificPreviousRegion(IStructuredDocumentRegion currentRegion) {
+		if (currentRegion == null)
+			return null;
+		do {
+			currentRegion = currentRegion.getPrevious();
+		} while (currentRegion != null && currentRegion.getType().equals(DOMRegionContext.BLOCK_TEXT));
+
+		return currentRegion;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/AbstractErrorInfo.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/AbstractErrorInfo.java
new file mode 100644
index 0000000..3e9d85d
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/AbstractErrorInfo.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.validate;
+
+import org.eclipse.wst.sse.core.internal.validate.ErrorInfo;
+
+abstract class AbstractErrorInfo implements ErrorInfo, ErrorState {
+
+
+	private int state = NONE_ERROR;
+	private Segment seg = null;
+
+	public AbstractErrorInfo(int state, Segment seg) {
+		super();
+		this.state = state;
+		this.seg = seg;
+	}
+
+	abstract public String getHint();
+
+	abstract public short getTargetType();
+
+	public int getLength() {
+		return (seg == null) ? 0 : seg.getLength();
+	}
+
+	public int getOffset() {
+		return (seg == null) ? 0 : seg.getOffset();
+	}
+
+	public int getState() {
+		return this.state;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/CMUtil.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/CMUtil.java
new file mode 100644
index 0000000..9633916
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/CMUtil.java
@@ -0,0 +1,212 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.validate;
+
+
+import java.util.Iterator;
+
+import org.eclipse.wst.html.core.internal.modelquery.HMQUtil;
+import org.eclipse.wst.html.core.internal.provisional.HTMLCMProperties;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMContent;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNodeList;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.modelquery.ModelQueryUtil;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+final class CMUtil {
+
+	/**
+	 * Never instantiate!
+	 */
+	private CMUtil() {
+		super();
+	}
+
+	/**
+	 * You cannot always retrieve HTMLElementDeclaration via an Element instance.
+	 * Because, it occasionally a JSP custom tag. -- 9/7/2001
+	 */
+	public static CMElementDeclaration getDeclaration(Element target) {
+		Document doc = target.getOwnerDocument();
+		ModelQuery query = ModelQueryUtil.getModelQuery(doc);
+		return query.getCMElementDeclaration(target);
+	}
+
+	/**
+	 */
+	public static boolean isCaseSensitive(CMElementDeclaration decl) {
+		if (decl == null || (!decl.supports(HTMLCMProperties.SHOULD_IGNORE_CASE)))
+			return false;
+		return !((Boolean) decl.getProperty(HTMLCMProperties.SHOULD_IGNORE_CASE)).booleanValue();
+	}
+
+	/**
+	 */
+	private static boolean isChild(CMContent content, CMElementDeclaration target) {
+		switch (content.getNodeType()) {
+			case CMNode.ELEMENT_DECLARATION :
+				if (isWholeTagOmissible((CMElementDeclaration) content))
+					if (isChild(((CMElementDeclaration) content).getContent(), target))
+						return true;
+				return isSameDeclaration((CMElementDeclaration) content, target);
+			case CMNode.GROUP :
+				CMNodeList children = ((CMGroup) content).getChildNodes();
+				for (int i = 0; i < children.getLength(); i++) {
+					CMNode child = children.item(i);
+					switch (child.getNodeType()) {
+						case CMNode.ELEMENT_DECLARATION :
+							if (isWholeTagOmissible((CMElementDeclaration) child))
+								if (isChild(((CMElementDeclaration) child).getContent(), target))
+									return true;
+							if (isSameDeclaration((CMElementDeclaration) child, target))
+								return true;
+							continue; // Go next child.
+						case CMNode.GROUP :
+							if (isChild((CMContent) child, target))
+								return true;
+							continue; // Go next child.
+						default :
+							continue; // Go next child.
+					}
+				}
+		}
+		return false;
+	}
+
+	/**
+	 */
+	public static boolean isEndTagOmissible(CMElementDeclaration decl) {
+		if (!(decl.supports(HTMLCMProperties.OMIT_TYPE)))
+			return false;
+		String omitType = (String) decl.getProperty(HTMLCMProperties.OMIT_TYPE);
+		return !omitType.equals(HTMLCMProperties.Values.OMIT_NONE);
+	}
+
+	/**
+	 */
+	public static boolean isWholeTagOmissible(CMElementDeclaration decl) {
+		if (!(decl.supports(HTMLCMProperties.OMIT_TYPE)))
+			return false;
+		String omitType = (String) decl.getProperty(HTMLCMProperties.OMIT_TYPE);
+		return omitType.equals(HTMLCMProperties.Values.OMIT_BOTH);
+	}
+	
+	/**
+	 */
+	public static boolean isJSP(CMElementDeclaration decl) {
+		if (!decl.supports(HTMLCMProperties.IS_JSP))
+			return false;
+		return ((Boolean) decl.getProperty(HTMLCMProperties.IS_JSP)).booleanValue();
+	}
+
+	/**
+	 */
+	public static boolean isXHTML(CMElementDeclaration decl) {
+		if (!decl.supports(HTMLCMProperties.IS_XHTML))
+			return false;
+		return ((Boolean) decl.getProperty(HTMLCMProperties.IS_XHTML)).booleanValue();
+	}
+
+	/**
+	 * The method to distinguish HTML and XHTML from other mark up.
+	 * This method returns true if the target is,
+	 * (1) not JSP,
+	 * (2) not SSI.
+	 */
+	public static boolean isHTML(CMElementDeclaration decl) {
+		return (!isJSP(decl)) && (!isSSI(decl));
+	}
+
+	/**
+	 */
+	private static boolean isSameDeclaration(CMElementDeclaration aDec, CMElementDeclaration otherDec) {
+		return aDec.getElementName() == otherDec.getElementName();
+	}
+
+	/**
+	 */
+	public static boolean isSSI(CMElementDeclaration edec) {
+		if (edec == null)
+			return false;
+		if (!edec.supports(HTMLCMProperties.IS_SSI))
+			return false;
+		return ((Boolean) edec.getProperty(HTMLCMProperties.IS_SSI)).booleanValue();
+	}
+
+	/**
+	 * Call this method only when the parent content type is one of
+	 * the following: ANY, ELEMENT, or MIXED.
+	 */
+	public static boolean isValidChild(CMElementDeclaration parent, CMElementDeclaration child) {
+		if (parent == null || child == null)
+			return false;
+		if (isHTML(parent) && (!isHTML(child)))
+			return true;
+		CMContent content = parent.getContent();
+		if (content == null)
+			return false;
+		return isChild(content, child);
+	}
+
+	public static boolean isForeign(Element target) {
+		if (!(target instanceof IDOMElement))
+			return true;
+		IDOMElement element = (IDOMElement) target;
+		return !element.isGlobalTag();
+	}
+
+	/**
+	 * This method returns true if all of the following conditions are met:
+	 * (1) value type is ENUM,
+	 * (2) only one value is defined in the enumeration,
+	 * (3) the value has same name to the attribute name.
+	 */
+	public static boolean isBooleanAttr(CMAttributeDeclaration adec) {
+		CMDataType attrtype = adec.getAttrType();
+		if (attrtype == null)
+			return false;
+		if (attrtype.getDataTypeName() != CMDataType.ENUM)
+			return false;
+		String[] values = attrtype.getEnumeratedValues();
+		if (values.length != 1)
+			return false;
+		return values[0].equals(adec.getAttrName());
+	}
+
+	public static boolean isValidInclusion(CMElementDeclaration decl, Element parent) {
+		Iterator iter = HMQUtil.getInclusions(parent).iterator();
+		while (iter.hasNext()) {
+			CMElementDeclaration inclusion = (CMElementDeclaration) iter.next();
+			if (isSameDeclaration(decl, inclusion))
+				return true;
+		}
+		return false;
+	}
+	
+	/**
+	 * The method to distinguish HTML and XHTML from other mark up.
+	 * This method returns true if the target is,
+	 * (1) not JSP,
+	 * (2) not SSI.
+	 */
+	public static boolean isObsolete(CMNode decl) {
+		return decl.supports(HTMLCMProperties.IS_OBSOLETE) && ((Boolean)(decl.getProperty(HTMLCMProperties.IS_OBSOLETE))).booleanValue();
+	}
+	
+	
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/CompositeValidator.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/CompositeValidator.java
new file mode 100644
index 0000000..b0e7523
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/CompositeValidator.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.validate;
+
+import java.util.Iterator;
+import java.util.Vector;
+
+import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
+import org.eclipse.wst.sse.core.internal.validate.ValidationAdapter;
+import org.eclipse.wst.sse.core.internal.validate.ValidationReporter;
+import org.eclipse.wst.xml.core.internal.validate.ValidationComponent;
+
+abstract class CompositeValidator extends ValidationComponent {
+
+	protected Vector components = new Vector();
+
+	/**
+	 * CompositeValidator constructor comment.
+	 */
+	public CompositeValidator() {
+		super();
+	}
+
+	/**
+	 */
+	public void setReporter(ValidationReporter reporter) {
+		super.setReporter(reporter);
+
+		Iterator i = components.iterator();
+		while (i.hasNext()) {
+			ValidationAdapter component = (ValidationAdapter) i.next();
+			if (component == null)
+				continue;
+			component.setReporter(reporter);
+		}
+	}
+
+	/**
+	 */
+	public void validate(IndexedRegion node) {
+		Iterator i = components.iterator();
+		while (i.hasNext()) {
+			ValidationComponent component = (ValidationComponent) i.next();
+			if (component == null)
+				continue;
+			component.validate(node);
+		}
+	}
+
+	/**
+	 */
+	void add(ValidationComponent validator) {
+		components.add(validator);
+	}
+
+	/**
+	 * This method registers all components in 'validators'.
+	 * Each derivative must call this methid in its constructor.
+	 */
+	protected void register(ValidationComponent[] validators) {
+		for (int i = 0; i < validators.length; i++) {
+			if (validators[i] != null)
+				add(validators[i]);
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/DocumentPropagatingValidator.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/DocumentPropagatingValidator.java
new file mode 100644
index 0000000..562915b
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/DocumentPropagatingValidator.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.validate;
+
+
+import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
+import org.eclipse.wst.sse.core.internal.validate.ValidationAdapter;
+import org.eclipse.wst.sse.core.internal.validate.ValidationReporter;
+import org.eclipse.wst.xml.core.internal.validate.AbstractPropagatingValidator;
+import org.eclipse.wst.xml.core.internal.validate.ValidationComponent;
+
+class DocumentPropagatingValidator extends AbstractPropagatingValidator {
+
+
+	private ValidationComponent validator = new HTMLSimpleDocumentValidator();
+	private ElementPropagatingValidator propagatee = new ElementPropagatingValidator();
+
+	public DocumentPropagatingValidator() {
+		super();
+	}
+
+	public void validate(IndexedRegion node) {
+		getPropagatee().setReporter(this.reporter);
+		super.validate(node);
+	}
+
+	public boolean isAdapterForType(Object type) {
+		return (type == DocumentPropagatingValidator.class || super.isAdapterForType(type));
+	}
+
+	public void setReporter(ValidationReporter reporter) {
+		super.setReporter(reporter);
+		validator.setReporter(reporter);
+		propagatee.setReporter(reporter);
+	}
+
+	protected final ValidationComponent getPropagatee() {
+		return propagatee;
+	}
+
+	protected final ValidationAdapter getValidator() {
+		return validator;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/ElementPropagatingValidator.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/ElementPropagatingValidator.java
new file mode 100644
index 0000000..c290b62
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/ElementPropagatingValidator.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.validate;
+
+
+import org.eclipse.wst.sse.core.internal.validate.ValidationAdapter;
+import org.eclipse.wst.sse.core.internal.validate.ValidationReporter;
+import org.eclipse.wst.xml.core.internal.validate.AbstractPropagatingValidator;
+import org.eclipse.wst.xml.core.internal.validate.ValidationComponent;
+
+class ElementPropagatingValidator extends AbstractPropagatingValidator {
+
+
+	private ValidationComponent validator = new HTMLSimpleValidator();
+
+	public ElementPropagatingValidator() {
+		super();
+	}
+
+	public boolean isAdapterForType(Object type) {
+		return (type == ElementPropagatingValidator.class || super.isAdapterForType(type));
+	}
+
+	public void setReporter(ValidationReporter reporter) {
+		super.setReporter(reporter);
+		validator.setReporter(reporter);
+	}
+
+	protected ValidationComponent getPropagatee() {
+		return this;
+	}
+
+	protected ValidationAdapter getValidator() {
+		return validator;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/ErrorInfoImpl.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/ErrorInfoImpl.java
new file mode 100644
index 0000000..4710a1e
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/ErrorInfoImpl.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.validate;
+
+
+
+import org.w3c.dom.Attr;
+import org.w3c.dom.Node;
+import org.w3c.dom.Text;
+
+final class ErrorInfoImpl extends AbstractErrorInfo {
+
+	private Node target = null;
+
+	//	private Segment seg = null;
+	/**
+	 */
+	public ErrorInfoImpl(int state, Segment errorSeg, Node target) {
+		super(state, errorSeg);
+		this.target = target;
+	}
+
+	/**
+	 */
+	public String getHint() {
+		switch (target.getNodeType()) {
+			case Node.ATTRIBUTE_NODE :
+				switch (getState()) {
+					case UNDEFINED_VALUE_ERROR :
+					case MISMATCHED_VALUE_ERROR :
+					case UNCLOSED_ATTR_VALUE :
+					case RESOURCE_NOT_FOUND :
+						//D210422
+						return ((Attr) target).getValue();
+					default :
+						return target.getNodeName();
+				}
+			case Node.TEXT_NODE :
+				return ((Text) target).getData();
+			case Node.ELEMENT_NODE :
+			default :
+				return target.getNodeName();
+		}
+	}
+
+	public short getTargetType() {
+		return target.getNodeType();
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/ErrorState.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/ErrorState.java
new file mode 100644
index 0000000..f64d50e
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/ErrorState.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.validate;
+
+
+
+interface ErrorState {
+	static final int NONE_ERROR = 0;
+	// generic error
+	static final int UNDEFINED_NAME_ERROR = 11;
+	static final int UNDEFINED_VALUE_ERROR = 12;
+	static final int MISMATCHED_VALUE_ERROR = 13;
+	static final int OBSOLETE_ATTR_NAME_ERROR = 14;
+	static final int OBSOLETE_TAG_NAME_ERROR = 15;
+	
+	// format error
+	static final int FORMAT_ERROR_LEVEL = 100;
+	static final int INVALID_NAME_ERROR = 101;
+	static final int INVALID_CHAR_ERROR = 102;
+	static final int MISMATCHED_ERROR = 103;
+	static final int MISMATCHED_END_TAG_ERROR = 104;
+	static final int MISSING_START_TAG_ERROR = 105;
+	static final int MISSING_END_TAG_ERROR = 106;
+	static final int UNNECESSARY_END_TAG_ERROR = 107;
+	static final int INVALID_ATTR_ERROR = 108;
+	static final int INVALID_DIRECTIVE_ERROR = 109;
+	static final int UNCLOSED_TAG_ERROR = 110;
+	static final int UNCLOSED_END_TAG_ERROR = 111;
+	static final int INVALID_EMPTY_ELEMENT_TAG = 112;
+	static final int UNCLOSED_ATTR_VALUE = 113; //D210422
+	static final int RESOURCE_NOT_FOUND = 114; //D210422
+	// layout error
+	static final int LAYOUT_ERROR_LEVEL = 1000;
+	static final int INVALID_CONTENT_ERROR = 1001;
+	static final int DUPLICATE_ERROR = 1002;
+	static final int COEXISTENCE_ERROR = 1003;
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/FMUtil.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/FMUtil.java
new file mode 100644
index 0000000..f3ee02a
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/FMUtil.java
@@ -0,0 +1,120 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.validate;
+
+
+
+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.ITextRegionList;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+
+final class FMUtil {
+
+	public final static int SEG_NONE = 0;
+	public final static int SEG_WHOLE_TAG = 1;
+	public final static int SEG_START_TAG = 2;
+	public final static int SEG_END_TAG = 3;
+	public final static int SEG_START_TAG_NAME = 4;
+	public final static int SEG_END_TAG_NAME = 5;
+
+	/**
+	 */
+	private FMUtil() {
+		super();
+	}
+
+	/**
+	 */
+	public final static Segment getSegment(IDOMNode target, int segType) {
+		if (target == null)
+			return new Segment(0, 0);
+		Segment seg = null;
+		IStructuredDocumentRegion startTag = null;
+		IStructuredDocumentRegion endTag = null;
+		switch (segType) {
+			case SEG_WHOLE_TAG :
+				startTag = target.getFirstStructuredDocumentRegion();
+				if (startTag != null) {
+					endTag = target.getLastStructuredDocumentRegion();
+					seg = new Segment(startTag, endTag);
+				}
+				else {
+					int startOffset = target.getStartOffset();
+					int endOffset = target.getEndOffset();
+					seg = new Segment(startOffset, endOffset - startOffset);
+				}
+				break;
+			case SEG_START_TAG :
+				startTag = target.getStartStructuredDocumentRegion();
+				if (startTag != null) {
+					seg = new Segment(startTag);
+				}
+				else {
+					seg = new Segment(target.getStartOffset(), 1);
+				}
+				break;
+			case SEG_END_TAG :
+				endTag = target.getEndStructuredDocumentRegion();
+				if (endTag != null) {
+					seg = new Segment(endTag);
+				}
+				else {
+					seg = new Segment(target.getEndOffset(), 1);
+				}
+				break;
+			case SEG_START_TAG_NAME :
+				startTag = target.getStartStructuredDocumentRegion();
+				if (startTag != null) {
+					ITextRegion nameRegion = getNameRegion(startTag);
+					if (nameRegion != null) {
+						seg = new Segment(startTag.getStartOffset(nameRegion), nameRegion.getTextLength());
+					}
+				}
+				if (seg == null) {
+					seg = getSegment(target, SEG_START_TAG);
+				}
+				break;
+			case SEG_END_TAG_NAME :
+				endTag = target.getEndStructuredDocumentRegion();
+				if (endTag != null) {
+					ITextRegion nameRegion = getNameRegion(endTag);
+					if (nameRegion != null) {
+						seg = new Segment(endTag.getStartOffset(nameRegion), nameRegion.getTextLength());
+					}
+				}
+				if (seg == null) {
+					seg = getSegment(target, SEG_END_TAG);
+				}
+				break;
+			case SEG_NONE :
+			default :
+				return new Segment(0, 0);
+		}
+		return seg;
+	}
+
+	private static ITextRegion getNameRegion(ITextRegionCollection containerRegion) {
+		ITextRegionList regions = containerRegion.getRegions();
+		ITextRegion nameRegion = null;
+		for (int i = 0; i < regions.size(); i++) {
+			ITextRegion r = regions.get(i);
+			if (r.getType() == DOMRegionContext.XML_TAG_NAME) {
+				nameRegion = r;
+				break;
+			}
+		}
+		return nameRegion ;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/HTMLAttributeValidator.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/HTMLAttributeValidator.java
new file mode 100644
index 0000000..76e9d2f
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/HTMLAttributeValidator.java
@@ -0,0 +1,312 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.validate;
+
+import java.util.List;
+import java.util.Locale;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.wst.html.core.internal.document.HTMLDocumentTypeConstants;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
+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.ITextRegionContainer;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.document.DocumentTypeAdapter;
+import org.eclipse.wst.xml.core.internal.modelquery.ModelQueryUtil;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMAttr;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+
+public class HTMLAttributeValidator extends PrimeValidator {
+
+	private static final int REGION_NAME = 1;
+	private static final int REGION_VALUE = 2;
+	// <<D210422
+	private static final char SINGLE_QUOTE = '\'';
+	private static final char DOUBLE_QUOTE = '\"';
+
+	private static final String ATTR_NAME_DATA = "data-"; //$NON-NLS-1$
+	//WHATWG x-vendor-feature attributes
+	private static final String ATTR_NAME_USER_AGENT_FEATURE = "x-"; //$NON-NLS-1$
+	private static final int ATTR_NAME_USER_AGENT_FEATURE_LENGTH = ATTR_NAME_USER_AGENT_FEATURE.length();
+
+	// D210422
+	/**
+	 * HTMLAttributeValidator constructor comment.
+	 */
+	public HTMLAttributeValidator() {
+		super();
+	}
+
+	/**
+	 */
+	private Segment getErrorSegment(IDOMNode errorNode, int regionType) {
+		ITextRegion rgn = null;
+		switch (regionType) {
+			case REGION_NAME :
+				rgn = errorNode.getNameRegion();
+				break;
+			case REGION_VALUE :
+				rgn = errorNode.getValueRegion();
+				break;
+			default :
+				// nothing to do.
+				break;
+		}
+		if (rgn != null) {
+			if (errorNode instanceof IDOMAttr) {
+				IDOMElement ownerElement = (IDOMElement) ((IDOMAttr) errorNode).getOwnerElement();
+				if (ownerElement != null) {
+					//if editor closed during validation this could be null
+					IStructuredDocumentRegion firstRegion = ownerElement.getFirstStructuredDocumentRegion();
+					if(firstRegion != null) {
+						int regionStartOffset = firstRegion.getStartOffset(rgn);
+						int regionLength = rgn.getTextLength();
+						return new Segment(regionStartOffset, regionLength);
+					}
+				}
+			}
+		}
+		return new Segment(errorNode.getStartOffset(), 1);
+	}
+
+	/**
+	 * Allowing the INodeAdapter to compare itself against the type allows it
+	 * to return true in more than one case.
+	 */
+	public boolean isAdapterForType(Object type) {
+		return ((type == HTMLAttributeValidator.class) || super.isAdapterForType(type));
+	}
+
+	/**
+	 */
+	public void validate(IndexedRegion node) {
+		Element target = (Element) node;
+		if (CMUtil.isForeign(target))
+			return;
+		CMElementDeclaration edec = CMUtil.getDeclaration(target);
+		if (edec == null)
+			return;
+		CMNamedNodeMap declarations = edec.getAttributes();
+
+		List modelQueryNodes = null;
+		NamedNodeMap attrs = target.getAttributes();
+		for (int i = 0; i < attrs.getLength(); i++) {
+			int rgnType = REGION_NAME;
+			int state = ErrorState.NONE_ERROR;
+			Attr a = (Attr) attrs.item(i);
+			// D203637; If the target attr has prefix, the validator should
+			// not
+			// warn about it. That is, just ignore. It is able to check
+			// whether
+			// an attr has prefix or not by calling XMLAttr#isGlobalAttr().
+			// When a attr has prefix (not global), it returns false.
+			boolean isXMLAttr = a instanceof IDOMAttr;
+			if (isXMLAttr) {
+				IDOMAttr xmlattr = (IDOMAttr) a;
+				if (!xmlattr.isGlobalAttr())
+					continue; // skip futher validation and begin next loop.
+			}
+
+			CMAttributeDeclaration adec = (CMAttributeDeclaration) declarations.getNamedItem(a.getName());
+			final String attrName = a.getName().toLowerCase(Locale.US);
+			/* Check the modelquery if nothing is declared by the element declaration */
+			if (adec == null) {
+				if (modelQueryNodes == null)
+					modelQueryNodes = ModelQueryUtil.getModelQuery(target.getOwnerDocument()).getAvailableContent((Element) node, edec, ModelQuery.INCLUDE_ATTRIBUTES);
+				
+				
+				for (int k = 0; k < modelQueryNodes.size(); k++) {
+					CMNode cmnode = (CMNode) modelQueryNodes.get(k);
+					if (cmnode.getNodeType() == CMNode.ATTRIBUTE_DECLARATION && cmnode.getNodeName().toLowerCase(Locale.US).equals(attrName)) {
+						adec = (CMAttributeDeclaration) cmnode;
+						break;
+					}
+				}
+			}
+			
+			if (adec == null) {
+				if ((attrName.startsWith(ATTR_NAME_DATA) && attrName.length() > ATTR_NAME_DATA.length()) || (attrName.startsWith(ATTR_NAME_USER_AGENT_FEATURE) && attrName.length() > ATTR_NAME_USER_AGENT_FEATURE_LENGTH)) {
+					DocumentTypeAdapter documentTypeAdapter = (DocumentTypeAdapter) ((INodeNotifier) target.getOwnerDocument()).getAdapterFor(DocumentTypeAdapter.class);
+					if (documentTypeAdapter != null && documentTypeAdapter.hasFeature(HTMLDocumentTypeConstants.HTML5))
+						continue;
+				}
+				// No attr declaration was found. That is, the attr name is
+				// undefined.
+				// but not regard it as undefined name if it includes nested
+				// region
+				if (!hasNestedRegion(((IDOMNode) a).getNameRegion())) {
+					rgnType = REGION_NAME;
+					state = ErrorState.UNDEFINED_NAME_ERROR;
+				}
+			} else {
+				// The attr declaration was found.
+				// At 1st, the name should be checked.
+				if (CMUtil.isObsolete(adec)){
+					state = ErrorState.OBSOLETE_ATTR_NAME_ERROR;
+				}
+				if (CMUtil.isHTML(edec) && (!CMUtil.isXHTML(edec))) {
+					// If the target element is pure HTML (not XHTML), some
+					// attributes
+					// might be written in boolean format. It should be check
+					// specifically.
+					if (CMUtil.isBooleanAttr(adec) && ((IDOMAttr) a).hasNameOnly())
+						continue; // OK, keep going. No more check is needed
+					// against this attr.
+				} else {
+					// If the target is other than pure HTML (JSP or XHTML),
+					// the name
+					// must be checked exactly (ie in case sensitive way).
+					String actual = a.getName();
+					String desired = adec.getAttrName();
+					if (!actual.equals(desired)) { // case mismatch
+						rgnType = REGION_NAME;
+						state = ErrorState.MISMATCHED_ERROR;
+					}
+				}
+				// Then, the value must be checked.
+				if (state == ErrorState.NONE_ERROR) { // Need more check.
+					// Now, the value should be checked, if the type is ENUM.
+					CMDataType attrType = adec.getAttrType();
+					String actualValue = a.getValue();
+					if (attrType.getImpliedValueKind() == CMDataType.IMPLIED_VALUE_FIXED) {
+						// Check FIXED value.
+						String validValue = attrType.getImpliedValue();
+						if (!actualValue.equals(validValue)) {
+							rgnType = REGION_VALUE;
+							state = ErrorState.UNDEFINED_VALUE_ERROR;
+						}
+					}
+					else if (CMDataType.URI.equals(attrType.getDataTypeName())) {
+						// TODO: URI validation?
+						if (false && actualValue.indexOf('#') < 0 && actualValue.indexOf(":/") == -1 && CMUtil.isHTML(edec)) { //$NON-NLS-1$ //$NON-NLS-2$
+							IStructuredDocumentRegion start = ((IDOMNode) node).getStartStructuredDocumentRegion();
+							if (start != null && start.getFirstRegion().getTextLength() == 1) {
+								IPath basePath = new Path(((IDOMNode) node).getModel().getBaseLocation());
+								if (basePath.segmentCount() > 1) {
+									IPath path = ModuleCoreSupport.resolve(basePath, actualValue);
+									IResource found = ResourcesPlugin.getWorkspace().getRoot().findMember(path);
+									if (found == null || !found.isAccessible()) {
+										rgnType = REGION_VALUE;
+										state = ErrorState.RESOURCE_NOT_FOUND;
+									}
+								}
+							}
+						}
+					}
+					else if (CMDataType.ENUM.equals(attrType.getDataTypeName())) {
+						/*
+						 * Check current value is valid among a known list.
+						 * There may be enumerated values provided even when
+						 * the datatype is not ENUM, but we'll only validate
+						 * against that list if the type matches.
+						 */
+						String[] enumeratedValues = attrType.getEnumeratedValues();
+						// several candidates are found.
+						boolean found = false;
+						for (int j = 0; j < enumeratedValues.length; j++) {
+							// At 1st, compare ignoring case.
+							if (actualValue.equalsIgnoreCase(enumeratedValues[j])) {
+								found = true;
+								if (CMUtil.isCaseSensitive(edec) && (!actualValue.equals(enumeratedValues[j]))) {
+									rgnType = REGION_VALUE;
+									state = ErrorState.MISMATCHED_VALUE_ERROR;
+								}
+								break; // exit the loop.
+							}
+						}
+						if (!found) {
+							// retrieve and check extended values (retrieval can call extensions, which may take longer)
+							String[] modelQueryExtensionValues = ModelQueryUtil.getModelQuery(target.getOwnerDocument()).getPossibleDataTypeValues((Element) node, adec);
+							// copied loop from above
+							for (int j = 0; j < modelQueryExtensionValues.length; j++) {
+								// At 1st, compare ignoring case.
+								if (actualValue.equalsIgnoreCase(modelQueryExtensionValues[j])) {
+									found = true;
+									if (CMUtil.isCaseSensitive(edec) && (!actualValue.equals(modelQueryExtensionValues[j]))) {
+										rgnType = REGION_VALUE;
+										state = ErrorState.MISMATCHED_VALUE_ERROR;
+									}
+									break; // exit the loop.
+								}
+							}
+							// No candidate was found. That is,
+							// actualValue is invalid.
+							// but not regard it as undefined value if it
+							// includes nested region.
+							if (!hasNestedRegion(((IDOMNode) a).getValueRegion())) {
+								rgnType = REGION_VALUE;
+								state = ErrorState.UNDEFINED_VALUE_ERROR;
+							}
+						}
+					}
+				}
+				// <<D210422
+				if (state == ErrorState.NONE_ERROR) { // Need more check.
+					if (isXMLAttr) {
+						String source = ((IDOMAttr) a).getValueRegionText();
+						if (source != null) {
+							char firstChar = source.charAt(0);
+							char lastChar = source.charAt(source.length() - 1);
+							if (isQuote(firstChar) || isQuote(lastChar)) {
+								if (lastChar != firstChar) {
+									rgnType = REGION_VALUE;
+									state = ErrorState.UNCLOSED_ATTR_VALUE;
+								}
+							}
+						}
+					}
+				}
+				// D210422
+			}
+			if (state != ErrorState.NONE_ERROR) {
+				Segment seg = getErrorSegment((IDOMNode) a, rgnType);
+				if (seg != null)
+					reporter.report(new ErrorInfoImpl(state, seg, a));
+			}
+		}
+	}
+
+	/**
+	 * True if container has nested regions, meaning container is probably too
+	 * complicated (like JSP regions) to validate with this validator.
+	 */
+	private boolean hasNestedRegion(ITextRegion container) {
+		if (!(container instanceof ITextRegionContainer))
+			return false;
+		ITextRegionList regions = ((ITextRegionContainer) container).getRegions();
+		if (regions == null)
+			return false;
+		// BUG207194: return true by default as long as container is an
+		// ITextRegionContainer with at least 1 region
+		return true;
+	}
+
+	// <<D214022
+	private boolean isQuote(char c) {
+		return (c == SINGLE_QUOTE) || (c == DOUBLE_QUOTE);
+	}
+	// D210422
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/HTMLDocumentContentValidator.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/HTMLDocumentContentValidator.java
new file mode 100644
index 0000000..cb6cab3
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/HTMLDocumentContentValidator.java
@@ -0,0 +1,196 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.validate;
+
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.document.DocumentTypeAdapter;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMText;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+public class HTMLDocumentContentValidator extends PrimeValidator {
+
+
+	private final static class Division {
+		private Vector explicitHtmls = new Vector();
+		private Vector rest = new Vector();
+
+		public Division(Document document, NodeList children) {
+			String rootTagName = getRootTagName(document);
+			for (int i = 0; i < children.getLength(); i++) {
+				Node child = children.item(i);
+				if (isHtmlTag(child, rootTagName)) {
+					explicitHtmls.add(child);
+				}
+				else {
+					rest.add(child);
+				}
+			}
+		}
+
+		public boolean hasExplicitHtmls() {
+			return explicitHtmls.size() > 0;
+		}
+
+		public List getExplicitHtmls() {
+			return explicitHtmls;
+		}
+
+		public Iterator getRestNodes() {
+			return rest.iterator();
+		}
+
+		/* utilities */
+		private static boolean isHtmlTag(Node node, String tagName) {
+			if (node.getNodeType() != Node.ELEMENT_NODE)
+				return false;
+			return ((Element) node).getTagName().equalsIgnoreCase(tagName);
+		}
+
+		private static String getRootTagName(Document document) {
+			DocumentTypeAdapter adapter = (DocumentTypeAdapter) ((IDOMDocument) document).getAdapterFor(DocumentTypeAdapter.class);
+			if (adapter != null) {
+				DocumentType docType = adapter.getDocumentType();
+				if (docType != null) {
+					return docType.getName();
+				}
+			}
+
+			return HTML40Namespace.ElementName.HTML;
+		}
+	}
+
+	/**
+	 * HTMLDocumentContentValidator constructor comment.
+	 */
+	public HTMLDocumentContentValidator() {
+		super();
+	}
+
+	/**
+	 * Allowing the INodeAdapter to compare itself against the type allows it
+	 * to return true in more than one case.
+	 */
+	public boolean isAdapterForType(Object type) {
+		return ((type == HTMLDocumentContentValidator.class) || super.isAdapterForType(type));
+	}
+
+	/**
+	 */
+	public void validate(IndexedRegion node) {
+		// isFragment check should be more intelligent.
+		boolean isFragment = true;
+
+		Document target = (Document) node;
+		NodeList children = target.getChildNodes();
+		if (children == null)
+			return;
+
+		Division division = new Division(target, children);
+		if (division.hasExplicitHtmls()) {
+			isFragment = false;
+
+			List explicits = division.getExplicitHtmls();
+			if (explicits.size() > 1) {
+				for (int i = 1; i < explicits.size(); i++) {
+					Element html = (Element) explicits.get(i);
+					// report error (duplicate)
+					Segment errorSeg = FMUtil.getSegment((IDOMNode) html, FMUtil.SEG_START_TAG);
+					if (errorSeg != null)
+						reporter.report(new ErrorInfoImpl(ErrorState.DUPLICATE_ERROR, errorSeg, html));
+				}
+			}
+		}
+		validateContent(division.getRestNodes(), isFragment);
+	}
+
+	/*
+	 * This methods validate nodes other than HTML elements.
+	 */
+	private void validateContent(Iterator children, boolean isFragment) {
+		boolean foundDoctype = false;
+		while (children.hasNext()) {
+			IDOMNode child = (IDOMNode) children.next();
+
+			int error = ErrorState.NONE_ERROR;
+			int segType = FMUtil.SEG_WHOLE_TAG;
+
+			switch (child.getNodeType()) {
+				case Node.ELEMENT_NODE :
+					if (!isFragment) {
+						Element childElem = (Element) child;
+						CMElementDeclaration ced = CMUtil.getDeclaration(childElem);
+						// Undefined element is valid.
+						if (ced == null)
+							continue;
+						// JSP (includes custom tags) and SSI are valid.
+						if (CMUtil.isForeign(childElem) || CMUtil.isSSI(ced))
+							continue; // Defect 186774
+
+						// report error (invalid content)
+						error = ErrorState.INVALID_CONTENT_ERROR;
+						// mark the whole start tag as error.
+						segType = FMUtil.SEG_START_TAG;
+					}
+					break;
+				case Node.TEXT_NODE :
+					if (!isFragment) {
+						// TEXT node is valid when it contains white space
+						// characters only.
+						// Otherwise, it is invalid content.
+						if (((IDOMText) child).isElementContentWhitespace())
+							continue;
+						error = ErrorState.INVALID_CONTENT_ERROR;
+						segType = FMUtil.SEG_WHOLE_TAG;
+					}
+					break;
+				case Node.DOCUMENT_TYPE_NODE :
+					// DOCTYPE is also valid when it appears once and only
+					// once.
+					if (!foundDoctype) {
+						foundDoctype = true;
+						continue;
+					}
+					error = ErrorState.DUPLICATE_ERROR;
+					segType = FMUtil.SEG_WHOLE_TAG;
+					break;
+				case Node.COMMENT_NODE :
+				// always valid.
+				case Node.PROCESSING_INSTRUCTION_NODE :
+					continue;
+				default :
+					if (!isFragment) {
+						error = ErrorState.INVALID_CONTENT_ERROR;
+						segType = FMUtil.SEG_WHOLE_TAG;
+					}
+					break;
+			}
+			if (error != ErrorState.NONE_ERROR) {
+				Segment errorSeg = FMUtil.getSegment(child, segType);
+				if (errorSeg != null)
+					reporter.report(new ErrorInfoImpl(error, errorSeg, child));
+			}
+		}
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/HTMLElementAncestorValidator.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/HTMLElementAncestorValidator.java
new file mode 100644
index 0000000..0c61edd
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/HTMLElementAncestorValidator.java
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.validate;
+
+
+
+import org.eclipse.wst.html.core.internal.provisional.HTMLCMProperties;
+import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.w3c.dom.Element;
+
+public class HTMLElementAncestorValidator extends PrimeValidator {
+
+	/**
+	 * HTMLElementAncestorValidator constructor comment.
+	 */
+	public HTMLElementAncestorValidator() {
+		super();
+	}
+
+	/**
+	 * Allowing the INodeAdapter to compare itself against the type
+	 * allows it to return true in more than one case.
+	 */
+	public boolean isAdapterForType(Object type) {
+		return ((type == HTMLElementAncestorValidator.class) || super.isAdapterForType(type));
+	}
+
+	/**
+	 * Check exclusion which is defined in only HTML DTD (SGML).
+	 */
+	public void validate(IndexedRegion node) {
+		Element target = (Element) node;
+		if (CMUtil.isForeign(target))
+			return;
+		CMElementDeclaration dec = CMUtil.getDeclaration(target);
+		if (dec == null)
+			return; // cannot validate.
+		if (!CMUtil.isHTML(dec))
+			return; // no need to validate
+		if (!dec.supports(HTMLCMProperties.PROHIBITED_ANCESTORS))
+			return; // cannot validate.
+		CMNamedNodeMap prohibited = (CMNamedNodeMap) dec.getProperty(HTMLCMProperties.PROHIBITED_ANCESTORS);
+		if (prohibited.getLength() <= 0)
+			return; // no prohibited ancestors.
+
+		Element parent = SMUtil.getParentElement(target);
+		while (parent != null) {
+			CMNode pdec = prohibited.getNamedItem(parent.getNodeName());
+			if (pdec != null) { // prohibited element is found in ancestors.
+				Segment errorSeg = FMUtil.getSegment((IDOMNode) node, FMUtil.SEG_START_TAG);
+				if (errorSeg != null)
+					reporter.report(new ErrorInfoImpl(ErrorState.INVALID_CONTENT_ERROR, errorSeg, target));
+				break; // If one prohibited ancestor is found, it's enough.
+			}
+			parent = SMUtil.getParentElement(parent);
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/HTMLElementContentValidator.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/HTMLElementContentValidator.java
new file mode 100644
index 0000000..d7462fe
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/HTMLElementContentValidator.java
@@ -0,0 +1,235 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.validate;
+
+import java.util.List;
+import java.util.Locale;
+
+import org.eclipse.wst.html.core.internal.provisional.HTMLCMProperties;
+import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.modelquery.ModelQueryUtil;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMText;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+public class HTMLElementContentValidator extends PrimeValidator {
+
+	/**
+	 * HTMLElementContentValidator constructor comment.
+	 */
+	public HTMLElementContentValidator() {
+		super();
+	}
+
+	/**
+	 * Allowing the INodeAdapter to compare itself against the type allows it
+	 * to return true in more than one case.
+	 */
+	public boolean isAdapterForType(Object type) {
+		return ((type == HTMLElementContentValidator.class) || super.isAdapterForType(type));
+	}
+
+	/**
+	 */
+	public void validate(IndexedRegion node) {
+		Element target = (Element) node;
+		if (CMUtil.isForeign(target))
+			return;
+
+		validateContent(target, target.getFirstChild());
+	}
+	
+	private void validateContent(Element parent, Node child) {
+		if (child == null)
+			return;
+
+		CMElementDeclaration ed = CMUtil.getDeclaration(parent);
+		if(ed == null || ed.getContentType() == CMElementDeclaration.ANY)
+			return;
+		
+		List[] extendedContent = new List[1];
+		while (child != null) {
+			// perform actual validation
+			validateNode(parent, child, ed, extendedContent);
+			child = child.getNextSibling();
+		}
+	}
+
+	// private int countExplicitSiblings(Element parent, String tagName) {
+	// NodeList children = parent.getChildNodes();
+	// int count = 0;
+	// for (int i = 0; i < children.getLength(); i++) {
+	// Node child = children.item(i);
+	// if (child.getNodeType() != Node.ELEMENT_NODE)
+	// continue;
+	// if (tagName.equalsIgnoreCase(((Element) child).getTagName())) {
+	// count++;
+	// }
+	// }
+	// return count;
+	// }
+
+	/*
+	 * The implementation of the following method is practical but accurate.
+	 * The accurate maximum occurrence should be retrieve from the content
+	 * model. However, it is useful enough, since almost implicit elements are
+	 * HTML, HEAD, or BODY.
+	 */
+	// private int getMaxOccur(Element parent, String childTag) {
+	// return 1;
+	// }
+
+//	private boolean containsName(String name, Object[] possible) {
+//		if (name != null && possible != null) {
+//			for (int i = 0; i < possible.length; i++) {
+//				if(name.equals(possible[i]))
+//				return true;
+//			}
+//		}
+//		return false;
+//	}
+
+	private void validateNode(Element target, Node child, CMElementDeclaration edec, List[] extendedContent) {
+		// NOTE: If the target element is 'UNKNOWN', that is, it has no
+		// element declaration, the content type of the element should be
+		// regarded as 'ANY'. -- 9/10/2001
+		int contentType = CMElementDeclaration.ANY;
+		if (edec != null)
+			contentType = edec.getContentType();
+
+		int error = ErrorState.NONE_ERROR;
+		int segType = FMUtil.SEG_WHOLE_TAG;
+		
+		switch (child.getNodeType()) {
+			case Node.ELEMENT_NODE :
+				Element childElem = (Element) child;
+				// Defect 200321:
+				// This validator cares only HTML/XHTML elements. If a child
+				// is
+				// an element of foreign markup languages, just ignore it.
+				if (CMUtil.isForeign(childElem))
+					return;
+
+				CMElementDeclaration ced = CMUtil.getDeclaration((Element) child);
+				// Defect 186774: If a child is not one of HTML elements,
+				// it should be regarded as a valid child regardless the
+				// type of the parent content model. -- 10/12/2001
+				if (ced == null || CMUtil.isSSI(ced) || (!CMUtil.isHTML(ced)))
+					return;
+				if (CMUtil.isObsolete(ced)){
+					error = ErrorState.OBSOLETE_TAG_NAME_ERROR;
+					break;
+				}
+				
+				switch (contentType) {
+					case CMElementDeclaration.ANY :
+						// Keep going.
+						return;
+					case CMElementDeclaration.ELEMENT :
+					case CMElementDeclaration.MIXED :
+						if (ced == null)
+							return;
+						if (CMUtil.isValidChild(edec, ced))
+							return;
+						// Now, it is the time to check inclusion, unless the
+						// target
+						// document is not a XHTML.
+						if (!CMUtil.isXHTML(edec)) {
+							// pure HTML
+							if (CMUtil.isValidInclusion(ced, target))
+								return;
+						}
+						
+						/*
+						 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=218143 - 
+						 * ModelQuery use not pervasive enough
+						 */
+						if (extendedContent[0] == null) {
+							extendedContent[0] = ModelQueryUtil.getModelQuery(target.getOwnerDocument()).getAvailableContent(target, edec, ModelQuery.INCLUDE_CHILD_NODES);
+						}
+
+						List availableChildElementDeclarations = extendedContent[0];
+						/*
+						 * Retrieve and set aside just the element names for faster checking
+						 * later.
+						 */
+						int availableChildCount = availableChildElementDeclarations.size();
+						String elementName = ced.getElementName().toLowerCase(Locale.US);
+						for (int i = 0; i < availableChildCount; i++) {
+							CMNode cmnode = (CMNode) availableChildElementDeclarations.get(i);
+							if (cmnode.getNodeType() == CMNode.ELEMENT_DECLARATION && cmnode.getNodeName().toLowerCase(Locale.US).equals(elementName)) {
+								return;
+							}
+						}
+						
+						error = ErrorState.INVALID_CONTENT_ERROR;
+						break;
+					default :
+						error = ErrorState.INVALID_CONTENT_ERROR;
+						break;
+				}
+				// Mark the whole START tag as an error segment.
+				segType = FMUtil.SEG_START_TAG;
+				break;
+			case Node.TEXT_NODE :
+				switch (contentType) {
+					case CMElementDeclaration.ANY :
+					case CMElementDeclaration.MIXED :
+					case CMElementDeclaration.PCDATA :
+					case CMElementDeclaration.CDATA :
+						// D184339
+						// Keep going.
+						return;
+					case CMElementDeclaration.ELEMENT :
+					case CMElementDeclaration.EMPTY :
+						if (((IDOMText) child).isElementContentWhitespace())
+							return;
+						error = ErrorState.INVALID_CONTENT_ERROR;
+						break;
+					default :
+						error = ErrorState.INVALID_CONTENT_ERROR;
+						break;
+				}
+				// Mark the whole node as an error segment.
+				segType = FMUtil.SEG_WHOLE_TAG;
+				break;
+			case Node.COMMENT_NODE :
+			case Node.PROCESSING_INSTRUCTION_NODE :
+				if (contentType != CMElementDeclaration.EMPTY)
+					return;
+				error = ErrorState.INVALID_CONTENT_ERROR;
+				// Mark the whole node as an error segment.
+				segType = FMUtil.SEG_WHOLE_TAG;
+				break;
+			case Node.CDATA_SECTION_NODE :
+				if (edec.supports(HTMLCMProperties.IS_XHTML) && Boolean.TRUE.equals(edec.getProperty(HTMLCMProperties.IS_XHTML)))
+					return;
+				// Mark the whole CDATA section as an error segment
+				error = ErrorState.INVALID_CONTENT_ERROR;
+				segType = FMUtil.SEG_WHOLE_TAG;
+				break;
+			default :
+				error = ErrorState.INVALID_CONTENT_ERROR;
+				// Mark the whole node as an error segment.
+				segType = FMUtil.SEG_WHOLE_TAG;
+				break;
+		}
+		if (error != ErrorState.NONE_ERROR) {
+			Segment errorSeg = FMUtil.getSegment((IDOMNode) child, segType);
+			if (errorSeg != null)
+				reporter.report(new ErrorInfoImpl(error, errorSeg, child));
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/HTMLSimpleDocumentValidator.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/HTMLSimpleDocumentValidator.java
new file mode 100644
index 0000000..65795b3
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/HTMLSimpleDocumentValidator.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.validate;
+
+
+import org.eclipse.wst.xml.core.internal.validate.ValidationComponent;
+
+class HTMLSimpleDocumentValidator extends CompositeValidator {
+
+	/**
+	 * HTMLSimpleDocumentValidator constructor comment.
+	 */
+	public HTMLSimpleDocumentValidator() {
+		super();
+
+		ValidationComponent[] validators = new ValidationComponent[2];
+
+		validators[0] = new HTMLDocumentContentValidator();
+		validators[1] = new SyntaxValidator();
+
+		register(validators);
+	}
+
+	/**
+	 * Allowing the INodeAdapter to compare itself against the type
+	 * allows it to return true in more than one case.
+	 */
+	public boolean isAdapterForType(Object type) {
+		return ((type == HTMLSimpleDocumentValidator.class) || super.isAdapterForType(type));
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/HTMLSimpleValidator.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/HTMLSimpleValidator.java
new file mode 100644
index 0000000..7276fd8
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/HTMLSimpleValidator.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.validate;
+
+
+import org.eclipse.wst.xml.core.internal.validate.ValidationComponent;
+
+class HTMLSimpleValidator extends CompositeValidator {
+
+	/**
+	 * HTMLSimpleValidator constructor comment.
+	 */
+	public HTMLSimpleValidator() {
+		super();
+
+		ValidationComponent[] validators = new ValidationComponent[5];
+
+		validators[0] = new HTMLAttributeValidator();
+		validators[1] = new HTMLElementContentValidator();
+		validators[2] = new SyntaxValidator();
+		validators[3] = new HTMLElementAncestorValidator();
+		validators[4] = new NamespaceValidator();
+
+		register(validators);
+	}
+
+	/**
+	 * Allowing the INodeAdapter to compare itself against the type
+	 * allows it to return true in more than one case.
+	 */
+	public boolean isAdapterForType(Object type) {
+		return ((type == HTMLSimpleValidator.class) || super.isAdapterForType(type));
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/HTMLValidationAdapterFactory.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/HTMLValidationAdapterFactory.java
new file mode 100644
index 0000000..1010e04
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/HTMLValidationAdapterFactory.java
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.validate;
+
+
+
+import org.eclipse.wst.sse.core.internal.provisional.AbstractAdapterFactory;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapter;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapterFactory;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.sse.core.internal.validate.ValidationAdapter;
+import org.w3c.dom.Node;
+
+public class HTMLValidationAdapterFactory extends AbstractAdapterFactory {
+
+	private static HTMLValidationAdapterFactory instance = null;
+
+	/**
+	 * HTMLValidationAdapterFactory constructor comment.
+	 */
+	public HTMLValidationAdapterFactory() {
+		super(ValidationAdapter.class, true);
+	}
+
+	/**
+	 * HTMLValidationAdapterFactory constructor comment.
+	 * @param adapterKey java.lang.Object
+	 * @param registerAdapters boolean
+	 */
+	public HTMLValidationAdapterFactory(Object adapterKey, boolean registerAdapters) {
+		super(adapterKey, registerAdapters);
+	}
+
+	/**
+	 */
+	protected INodeAdapter createAdapter(INodeNotifier target) {
+		Node node = (Node) target;
+		switch (node.getNodeType()) {
+			case Node.DOCUMENT_NODE :
+				return new DocumentPropagatingValidator();
+			case Node.ELEMENT_NODE :
+				return new ElementPropagatingValidator();
+			default :
+				return new NullValidator();
+		}
+	}
+
+	/**
+	 */
+	public synchronized static HTMLValidationAdapterFactory getInstance() {
+		if (instance != null)
+			return instance;
+		instance = new HTMLValidationAdapterFactory();
+		return instance;
+	}
+
+	/**
+	 * Overriding Object's clone() method
+	 * This is used in IModelManager's IStructuredModel copying.
+	 */
+	public INodeAdapterFactory copy() {
+		return getInstance();
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/MessageFactory.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/MessageFactory.java
new file mode 100644
index 0000000..d7ed235
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/MessageFactory.java
@@ -0,0 +1,391 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.validate;
+
+import java.util.Hashtable;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.ProjectScope;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.core.runtime.preferences.DefaultScope;
+import org.eclipse.core.runtime.preferences.IPreferencesService;
+import org.eclipse.core.runtime.preferences.IScopeContext;
+import org.eclipse.core.runtime.preferences.InstanceScope;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.wst.html.core.internal.HTMLCoreMessages;
+import org.eclipse.wst.html.core.internal.HTMLCorePlugin;
+import org.eclipse.wst.html.core.internal.Logger;
+import org.eclipse.wst.html.core.internal.preferences.HTMLCorePreferenceNames;
+import org.eclipse.wst.sse.core.internal.validate.ErrorInfo;
+import org.eclipse.wst.sse.core.internal.validate.ValidationMessage;
+import org.w3c.dom.Node;
+
+public class MessageFactory implements ErrorState {
+
+
+	private IProject fProject;
+	private IScopeContext[] fLookupOrder;
+	private IPreferencesService fPreferenceService;
+	
+	public MessageFactory() {
+		init();
+	}
+	
+	public MessageFactory(IProject project) {
+		fProject = project;
+		init();
+	}
+	
+	protected Preferences getModelPreferences() {
+		return HTMLCorePlugin.getDefault().getPluginPreferences();
+	}
+	
+	/**
+	 * Creates a packet for the error table based on the state, message, and the
+	 * severity defined in the preference store. This packet, in addition to
+	 * being added to the error table, is also placed in a map based on the
+	 * supplied preference key
+	 * 
+	 * @param key the preference key for the error severity
+	 * @param errorTable the error table to store the packet information in
+	 * @param state the error state
+	 * @param msg the message for the error
+	 */
+	private void mapToKey(String key, ErrorTable errorTable, int state, String msg) {
+		int severity = ValidationMessage.WARNING;
+		severity = fPreferenceService.getInt(HTMLCorePlugin.getDefault().getBundle().getSymbolicName(), key, ValidationMessage.WARNING, fLookupOrder);
+		errorTable.put(state, msg, severity);
+	}
+	
+	private void init() {
+		fPreferenceService = Platform.getPreferencesService();
+		fLookupOrder = new IScopeContext[] {new InstanceScope(), new DefaultScope()};
+		
+		if (fProject != null) {
+			ProjectScope projectScope = new ProjectScope(fProject);
+			if(projectScope.getNode(HTMLCorePlugin.getDefault().getBundle().getSymbolicName()).getBoolean(HTMLCorePreferenceNames.USE_PROJECT_SETTINGS, false))
+				fLookupOrder = new IScopeContext[] {projectScope, new InstanceScope(), new DefaultScope()};
+		}
+		
+		for (int i = 0; i < NodeType.MAX_TYPE; i++) {
+			errTables[i] = new ErrorTable();
+		}
+		// NOTE: The severities are just stub.  They must be reviewed.
+		// -- 8/30/2001
+
+		// attribute error map
+		ErrorTable attrTable = errTables[NodeType.ATTRIBUTE];// short hand
+		attrTable.put(NONE_ERROR, MSG_NO_ERROR, 0);
+		mapToKey(HTMLCorePreferenceNames.ATTRIBUTE_UNDEFINED_NAME, attrTable, UNDEFINED_NAME_ERROR, MSG_UNDEFINED_ATTR_ERROR);
+		mapToKey(HTMLCorePreferenceNames.ATTRIBUTE_UNDEFINED_VALUE, attrTable, UNDEFINED_VALUE_ERROR, MSG_UNDEFINED_VALUE_ERROR);
+		mapToKey(HTMLCorePreferenceNames.ATTRIBUTE_NAME_MISMATCH, attrTable, MISMATCHED_ERROR, MSG_MISMATCHED_ATTR_ERROR);
+		mapToKey(HTMLCorePreferenceNames.ATTRIBUTE_INVALID_NAME, attrTable, INVALID_NAME_ERROR, MSG_INVALID_ATTR_ERROR);
+		mapToKey(HTMLCorePreferenceNames.ATTRIBUTE_INVALID_VALUE, attrTable, INVALID_ATTR_ERROR, MSG_ATTR_NO_VALUE_ERROR);
+		mapToKey(HTMLCorePreferenceNames.ATTRIBUTE_DUPLICATE, attrTable, DUPLICATE_ERROR, MSG_DUPLICATE_ATTR_ERROR);
+		mapToKey(HTMLCorePreferenceNames.ATTRIBUTE_VALUE_MISMATCH, attrTable, MISMATCHED_VALUE_ERROR, MSG_MISMATCHED_ATTR_VALUE_ERROR);
+		mapToKey(HTMLCorePreferenceNames.ATTRIBUTE_VALUE_UNCLOSED, attrTable, UNCLOSED_ATTR_VALUE, MSG_UNCLOSED_ATTR_VALUE_ERROR);
+		mapToKey(HTMLCorePreferenceNames.ATTRIBUTE_VALUE_RESOURCE_NOT_FOUND, attrTable, RESOURCE_NOT_FOUND, MSG_RESOURCE_NOT_FOUND);
+		mapToKey(HTMLCorePreferenceNames.ATTRIBUTE_OBSOLETE_NAME, attrTable, OBSOLETE_ATTR_NAME_ERROR, MSG_OBSOLETE_ATTR_ERROR);
+
+		// element error map
+		ErrorTable elemTable = errTables[NodeType.ELEMENT];// short hand
+		elemTable.put(NONE_ERROR, MSG_NO_ERROR, 0);
+		mapToKey(HTMLCorePreferenceNames.ELEM_UNKNOWN_NAME, elemTable, UNDEFINED_NAME_ERROR, MSG_UNDEFINED_TAG_ERROR);
+		mapToKey(HTMLCorePreferenceNames.ELEM_INVALID_NAME, elemTable, INVALID_NAME_ERROR, MSG_INVALID_TAG_ERROR);
+		mapToKey(HTMLCorePreferenceNames.ELEM_START_INVALID_CASE, elemTable, MISMATCHED_ERROR, MSG_MISMATCHED_TAG_ERROR);
+		mapToKey(HTMLCorePreferenceNames.ELEM_END_INVALID_CASE, elemTable, MISMATCHED_END_TAG_ERROR, MSG_MISMATCHED_TAG_ERROR);
+		mapToKey(HTMLCorePreferenceNames.ELEM_MISSING_START, elemTable, MISSING_START_TAG_ERROR, MSG_MISSING_START_TAG_ERROR);
+		mapToKey(HTMLCorePreferenceNames.ELEM_MISSING_END, elemTable, MISSING_END_TAG_ERROR, MSG_MISSING_END_TAG_ERROR);
+		mapToKey(HTMLCorePreferenceNames.ELEM_UNNECESSARY_END, elemTable, UNNECESSARY_END_TAG_ERROR, MSG_UNNECESSARY_END_TAG_ERROR);
+		mapToKey(HTMLCorePreferenceNames.ELEM_INVALID_DIRECTIVE, elemTable, INVALID_DIRECTIVE_ERROR, MSG_INVALID_DIRECTIVE_ERROR);
+		mapToKey(HTMLCorePreferenceNames.ELEM_INVALID_CONTENT, elemTable, INVALID_CONTENT_ERROR, MSG_INVALID_CONTENT_ERROR);
+		mapToKey(HTMLCorePreferenceNames.ELEM_DUPLICATE, elemTable, DUPLICATE_ERROR, MSG_DUPLICATE_TAG_ERROR);
+		mapToKey(HTMLCorePreferenceNames.ELEM_COEXISTENCE, elemTable, COEXISTENCE_ERROR, MSG_INVALID_CONTENT_ERROR);
+		mapToKey(HTMLCorePreferenceNames.ELEM_UNCLOSED_START_TAG, elemTable, UNCLOSED_TAG_ERROR, MSG_UNCLOSED_START_TAG_ERROR);
+		mapToKey(HTMLCorePreferenceNames.ELEM_UNCLOSED_END_TAG, elemTable, UNCLOSED_END_TAG_ERROR, MSG_UNCLOSED_END_TAG_ERROR);
+		mapToKey(HTMLCorePreferenceNames.ELEM_INVALID_EMPTY_TAG, elemTable, INVALID_EMPTY_ELEMENT_TAG, MSG_INVALID_EMPTY_ELEMENT_TAG);
+		mapToKey(HTMLCorePreferenceNames.ELEM_OBSOLETE_NAME, elemTable, OBSOLETE_TAG_NAME_ERROR, MSG_OBSOLETE_TAG_ERROR);
+
+
+		// document type error map
+		ErrorTable docTable = errTables[NodeType.DOCUMENT_TYPE];// short hand
+		docTable.put(NONE_ERROR, MSG_NO_ERROR, 0);
+		mapToKey(HTMLCorePreferenceNames.DOC_DUPLICATE, docTable, DUPLICATE_ERROR, MSG_DUPLICATE_TAG_ERROR);
+		mapToKey(HTMLCorePreferenceNames.DOC_INVALID_CONTENT, docTable, INVALID_CONTENT_ERROR, MSG_INVALID_CONTENT_ERROR);
+		mapToKey(HTMLCorePreferenceNames.DOC_DOCTYPE_UNCLOSED, docTable, UNCLOSED_TAG_ERROR, MSG_UNCLOSED_DOCTYPE_ERROR);
+
+		// text error map
+		ErrorTable textTable = errTables[NodeType.TEXT];
+		textTable.put(NONE_ERROR, MSG_NO_ERROR, 0);
+		mapToKey(HTMLCorePreferenceNames.TEXT_INVALID_CONTENT, textTable, INVALID_CONTENT_ERROR, MSG_INVALID_TEXT_ERROR);
+		mapToKey(HTMLCorePreferenceNames.TEXT_INVALID_CHAR, textTable, INVALID_CHAR_ERROR, MSG_INVALID_CHAR_ERROR);
+
+		// comment error map
+		ErrorTable commTable = errTables[NodeType.COMMENT];
+		commTable.put(NONE_ERROR, MSG_NO_ERROR, 0);
+		mapToKey(HTMLCorePreferenceNames.COMMENT_INVALID_CONTENT, commTable, INVALID_CONTENT_ERROR, MSG_INVALID_CONTENT_ERROR);
+		mapToKey(HTMLCorePreferenceNames.COMMENT_UNCLOSED, commTable, UNCLOSED_TAG_ERROR, MSG_UNCLOSED_COMMENT_ERROR);
+
+		// cdata section error map
+		ErrorTable cdatTable = errTables[NodeType.CDATA_SECTION];
+		cdatTable.put(NONE_ERROR, MSG_NO_ERROR, 0);
+		mapToKey(HTMLCorePreferenceNames.CDATA_INVALID_CONTENT, cdatTable, INVALID_CONTENT_ERROR, MSG_INVALID_CONTENT_ERROR);
+		mapToKey(HTMLCorePreferenceNames.CDATA_UNCLOSED, cdatTable, UNCLOSED_TAG_ERROR, MSG_UNCLOSED_CDATA_SECTION_ERROR);
+
+		// processing instruction error map
+		ErrorTable piTable = errTables[NodeType.PROCESSING_INSTRUCTION];
+		piTable.put(NONE_ERROR, MSG_NO_ERROR, 0);
+		mapToKey(HTMLCorePreferenceNames.PI_INVALID_CONTENT, piTable, INVALID_CONTENT_ERROR, MSG_INVALID_CONTENT_ERROR);
+		mapToKey(HTMLCorePreferenceNames.PI_UNCLOSED, piTable, UNCLOSED_TAG_ERROR, MSG_UNCLOSED_PI_ERROR);
+
+		// entity reference error map
+		ErrorTable erTable = errTables[NodeType.ENTITY_REFERENCE];
+		erTable.put(NONE_ERROR, MSG_NO_ERROR, 0);
+		mapToKey(HTMLCorePreferenceNames.REF_UNDEFINED, erTable, UNDEFINED_NAME_ERROR, MSG_UNDEFINED_TAG_ERROR);
+		mapToKey(HTMLCorePreferenceNames.REF_INVALID_CONTENT, erTable, INVALID_CONTENT_ERROR, MSG_INVALID_CONTENT_ERROR);
+	}
+	
+	private static class ErrorTable {
+		private class Packet {
+			public Packet(String msg, int severity) {
+				this.msg = msg;
+				this.severity = severity;
+			}
+
+			public String getMessage() {
+				return msg;
+			}
+
+			public int getSeverity() {
+				return severity;
+			}
+
+			private String msg = null;
+			private int severity = -1;
+		}
+
+		public ErrorTable() {
+		}
+
+		public Packet put(int state, String msg, int severity) {
+			Packet packet = new Packet(msg, severity);
+			map.put(new Integer(state), packet);
+			return packet;
+		}
+
+		public String getMessage(int state) {
+			return getPacket(state).getMessage();
+		}
+
+		public int getSeverity(int state) {
+			return getPacket(state).getSeverity();
+		}
+
+		private Packet getPacket(int state) {
+			return (Packet) map.get(new Integer(state));
+		}
+
+		private Hashtable map = new Hashtable();
+	}
+
+	private static interface NodeType {
+		static final int ATTRIBUTE = 0;
+		static final int ELEMENT = 1;
+		static final int DOCUMENT_TYPE = 2;
+		static final int TEXT = 3;
+		static final int COMMENT = 4;
+		static final int CDATA_SECTION = 5;
+		static final int PROCESSING_INSTRUCTION = 6;
+		static final int ENTITY_REFERENCE = 7;
+
+		static final int MAX_TYPE = 8;
+	}
+
+	// error messages
+	private static final String MSG_NO_ERROR = HTMLCoreMessages.No_error__UI_;
+	private static final String MSG_UNDEFINED_ATTR_ERROR = HTMLCoreMessages.Undefined_attribute_name___ERROR_;
+	private static final String MSG_UNDEFINED_VALUE_ERROR = HTMLCoreMessages.Undefined_attribute_value__ERROR_;
+	private static final String MSG_DUPLICATE_ATTR_ERROR = HTMLCoreMessages.Multiple_values_specified__ERROR_;
+	private static final String MSG_MISMATCHED_ATTR_ERROR = HTMLCoreMessages.Attribute_name___0___uses__ERROR_;
+	private static final String MSG_INVALID_ATTR_ERROR = HTMLCoreMessages.Invalid_attribute_name___0_ERROR_;
+	private static final String MSG_ATTR_NO_VALUE_ERROR = HTMLCoreMessages.Invalid_attribute___0____ERROR_;
+	private static final String MSG_INVALID_CONTENT_ERROR = HTMLCoreMessages.Invalid_location_of_tag____ERROR_;
+	private static final String MSG_DUPLICATE_TAG_ERROR = HTMLCoreMessages.Duplicate_tag___0____ERROR_;
+	private static final String MSG_MISSING_START_TAG_ERROR = HTMLCoreMessages.No_start_tag____0_____ERROR_;
+	private static final String MSG_MISSING_END_TAG_ERROR = HTMLCoreMessages.No_end_tag_____0_____ERROR_;
+	private static final String MSG_UNNECESSARY_END_TAG_ERROR = HTMLCoreMessages.End_tag_____0____not_neede_ERROR_;
+	private static final String MSG_UNDEFINED_TAG_ERROR = HTMLCoreMessages.Unknown_tag___0____ERROR_;
+	private static final String MSG_MISMATCHED_TAG_ERROR = HTMLCoreMessages.Tag_name___0___uses_wrong__ERROR_;
+	private static final String MSG_INVALID_TAG_ERROR = HTMLCoreMessages.Invalid_tag_name___0____ERROR_;
+	private static final String MSG_INVALID_DIRECTIVE_ERROR = HTMLCoreMessages.Invalid_JSP_directive___0__ERROR_;
+	private static final String MSG_INVALID_TEXT_ERROR = HTMLCoreMessages.Invalid_text_string___0____ERROR_;
+	private static final String MSG_INVALID_CHAR_ERROR = HTMLCoreMessages.Invalid_character_used_in__ERROR_;
+	private static final String MSG_UNKNOWN_ERROR = HTMLCoreMessages.Unknown_error__ERROR_;
+	private static final String MSG_UNCLOSED_START_TAG_ERROR = HTMLCoreMessages.Start_tag____0____not_clos_ERROR_;
+	private static final String MSG_UNCLOSED_END_TAG_ERROR = HTMLCoreMessages.End_tag_____0____not_close_ERROR_;
+	private static final String MSG_MISMATCHED_ATTR_VALUE_ERROR = HTMLCoreMessages.Attribute_value___0___uses_ERROR_;
+	private static final String MSG_UNCLOSED_COMMENT_ERROR = HTMLCoreMessages.Comment_not_closed__ERROR_;
+	private static final String MSG_UNCLOSED_DOCTYPE_ERROR = HTMLCoreMessages.DOCTYPE_declaration_not_cl_ERROR_;
+	private static final String MSG_UNCLOSED_PI_ERROR = HTMLCoreMessages.Processing_instruction_not_ERROR_;
+	private static final String MSG_UNCLOSED_CDATA_SECTION_ERROR = HTMLCoreMessages.CDATA_section_not_closed__ERROR_;
+	private static final String MSG_INVALID_EMPTY_ELEMENT_TAG = HTMLCoreMessages._ERROR_Tag___0___should_be_an_empty_element_tag_1;
+	private static final String MSG_UNCLOSED_ATTR_VALUE_ERROR = HTMLCoreMessages._ERROR_Attribute_value___0___not_closed__1;
+	private static final String MSG_RESOURCE_NOT_FOUND = HTMLCoreMessages._ERROR_Resource_not_found_0;
+	private static final String MSG_OBSOLETE_ATTR_ERROR = HTMLCoreMessages.Obsolete_attribute_name___ERROR_;
+	private static final String MSG_OBSOLETE_TAG_ERROR = HTMLCoreMessages.Obsolete_tag___ERROR_;
+	
+	private ErrorTable[] errTables = new ErrorTable[NodeType.MAX_TYPE];
+
+//	static {
+//		for (int i = 0; i < NodeType.MAX_TYPE; i++) {
+//			errTables[i] = new ErrorTable();
+//		}
+//		// NOTE: The severities are just stub.  They must be reviewed.
+//		// -- 8/30/2001
+//
+//		// attribute error map
+//		ErrorTable attrTable = errTables[NodeType.ATTRIBUTE];// short hand
+//		attrTable.put(NONE_ERROR, MSG_NO_ERROR, 0);
+//		attrTable.put(UNDEFINED_NAME_ERROR, MSG_UNDEFINED_ATTR_ERROR, ValidationMessage.WARNING);
+//		attrTable.put(UNDEFINED_VALUE_ERROR, MSG_UNDEFINED_VALUE_ERROR, ValidationMessage.WARNING);
+//		attrTable.put(MISMATCHED_ERROR, MSG_MISMATCHED_ATTR_ERROR, ValidationMessage.WARNING);
+//		attrTable.put(INVALID_NAME_ERROR, MSG_INVALID_ATTR_ERROR, ValidationMessage.WARNING);
+//		attrTable.put(INVALID_ATTR_ERROR, MSG_ATTR_NO_VALUE_ERROR, ValidationMessage.WARNING);
+//		attrTable.put(DUPLICATE_ERROR, MSG_DUPLICATE_ATTR_ERROR, ValidationMessage.WARNING);
+//		attrTable.put(MISMATCHED_VALUE_ERROR, MSG_MISMATCHED_ATTR_VALUE_ERROR, ValidationMessage.ERROR);
+//		//<<D210422
+//		attrTable.put(UNCLOSED_ATTR_VALUE, MSG_UNCLOSED_ATTR_VALUE_ERROR, ValidationMessage.WARNING);
+//		//D210422
+//		// element error map
+//		ErrorTable elemTable = errTables[NodeType.ELEMENT];// short hand
+//		elemTable.put(NONE_ERROR, MSG_NO_ERROR, 0);
+//		elemTable.put(UNDEFINED_NAME_ERROR, MSG_UNDEFINED_TAG_ERROR, ValidationMessage.WARNING);
+//		elemTable.put(INVALID_NAME_ERROR, MSG_INVALID_TAG_ERROR, ValidationMessage.ERROR);
+//		elemTable.put(MISMATCHED_ERROR, MSG_MISMATCHED_TAG_ERROR, ValidationMessage.WARNING);
+//		elemTable.put(MISMATCHED_END_TAG_ERROR, MSG_MISMATCHED_TAG_ERROR, ValidationMessage.ERROR);
+//		elemTable.put(MISSING_START_TAG_ERROR, MSG_MISSING_START_TAG_ERROR, ValidationMessage.ERROR);
+//		elemTable.put(MISSING_END_TAG_ERROR, MSG_MISSING_END_TAG_ERROR, ValidationMessage.WARNING);
+//		elemTable.put(UNNECESSARY_END_TAG_ERROR, MSG_UNNECESSARY_END_TAG_ERROR, ValidationMessage.WARNING);
+//		elemTable.put(INVALID_DIRECTIVE_ERROR, MSG_INVALID_DIRECTIVE_ERROR, ValidationMessage.ERROR);
+//		elemTable.put(INVALID_CONTENT_ERROR, MSG_INVALID_CONTENT_ERROR, ValidationMessage.WARNING);
+//		elemTable.put(DUPLICATE_ERROR, MSG_DUPLICATE_TAG_ERROR, ValidationMessage.WARNING);
+//		elemTable.put(COEXISTENCE_ERROR, MSG_INVALID_CONTENT_ERROR, ValidationMessage.WARNING);
+//		elemTable.put(UNCLOSED_TAG_ERROR, MSG_UNCLOSED_START_TAG_ERROR, ValidationMessage.ERROR);
+//		elemTable.put(UNCLOSED_END_TAG_ERROR, MSG_UNCLOSED_END_TAG_ERROR, ValidationMessage.ERROR);
+//		elemTable.put(INVALID_EMPTY_ELEMENT_TAG, MSG_INVALID_EMPTY_ELEMENT_TAG, ValidationMessage.WARNING);
+//
+//		// document type error map
+//		ErrorTable docTable = errTables[NodeType.DOCUMENT_TYPE];// short hand
+//		docTable.put(NONE_ERROR, MSG_NO_ERROR, 0);
+//		docTable.put(DUPLICATE_ERROR, MSG_DUPLICATE_TAG_ERROR, ValidationMessage.ERROR);
+//		docTable.put(INVALID_CONTENT_ERROR, MSG_INVALID_CONTENT_ERROR, ValidationMessage.WARNING);
+//		docTable.put(UNCLOSED_TAG_ERROR, MSG_UNCLOSED_DOCTYPE_ERROR, ValidationMessage.ERROR);
+//
+//		// text error map
+//		ErrorTable textTable = errTables[NodeType.TEXT];
+//		textTable.put(NONE_ERROR, MSG_NO_ERROR, 0);
+//		textTable.put(INVALID_CONTENT_ERROR, MSG_INVALID_TEXT_ERROR, ValidationMessage.WARNING);
+//		textTable.put(INVALID_CHAR_ERROR, MSG_INVALID_CHAR_ERROR, ValidationMessage.WARNING);
+//
+//		// comment error map
+//		ErrorTable commTable = errTables[NodeType.COMMENT];
+//		commTable.put(NONE_ERROR, MSG_NO_ERROR, 0);
+//		commTable.put(INVALID_CONTENT_ERROR, MSG_INVALID_CONTENT_ERROR, ValidationMessage.WARNING);
+//		commTable.put(UNCLOSED_TAG_ERROR, MSG_UNCLOSED_COMMENT_ERROR, ValidationMessage.ERROR);
+//
+//		// cdata section error map
+//		ErrorTable cdatTable = errTables[NodeType.CDATA_SECTION];
+//		cdatTable.put(NONE_ERROR, MSG_NO_ERROR, 0);
+//		cdatTable.put(INVALID_CONTENT_ERROR, MSG_INVALID_CONTENT_ERROR, ValidationMessage.WARNING);
+//		cdatTable.put(UNCLOSED_TAG_ERROR, MSG_UNCLOSED_CDATA_SECTION_ERROR, ValidationMessage.ERROR);
+//
+//		// processing instruction error map
+//		ErrorTable piTable = errTables[NodeType.PROCESSING_INSTRUCTION];
+//		piTable.put(NONE_ERROR, MSG_NO_ERROR, 0);
+//		piTable.put(INVALID_CONTENT_ERROR, MSG_INVALID_CONTENT_ERROR, ValidationMessage.WARNING);
+//		piTable.put(UNCLOSED_TAG_ERROR, MSG_UNCLOSED_PI_ERROR, ValidationMessage.ERROR);
+//
+//		// entity reference error map
+//		ErrorTable erTable = errTables[NodeType.ENTITY_REFERENCE];
+//		erTable.put(NONE_ERROR, MSG_NO_ERROR, 0);
+//		erTable.put(UNDEFINED_NAME_ERROR, MSG_UNDEFINED_TAG_ERROR, ValidationMessage.WARNING);
+//		erTable.put(INVALID_CONTENT_ERROR, MSG_INVALID_CONTENT_ERROR, ValidationMessage.WARNING);
+//	}
+
+	/**
+	 */
+	public ValidationMessage createMessage(ErrorInfo info) {
+		String errorMsg = getErrorMessage(info);
+		int errorSeverity = getErrorSeverity(info);
+		return new ValidationMessage(errorMsg, info.getOffset(), info.getLength(), errorSeverity);
+	}
+
+	private String getErrorMessage(ErrorInfo info) {
+		ErrorTable tab = getErrorTable(info.getTargetType());
+		if (tab == null)
+			return MSG_UNKNOWN_ERROR;
+
+		String template = tab.getMessage(info.getState());
+		Object[] arguments = {info.getHint()};
+		String s = null;
+		try {
+			s = NLS.bind(template, arguments);
+		}
+		catch (IllegalArgumentException e) {
+			Logger.logException(e);
+			s = template + ":" + arguments.toString(); //$NON-NLS-1$
+		}
+		return s;
+	}
+
+	/**
+	 */
+	private int getErrorSeverity(ErrorInfo info) {
+		ErrorTable tab = getErrorTable(info.getTargetType());
+		if (tab == null)
+			return 0;
+		return tab.getSeverity(info.getState());
+	}
+
+	private ErrorTable getErrorTable(short nodetype) {
+		ErrorTable tab = null;
+		switch (nodetype) {
+			case Node.ATTRIBUTE_NODE :
+				tab = errTables[NodeType.ATTRIBUTE];
+				break;
+			case Node.ELEMENT_NODE :
+				tab = errTables[NodeType.ELEMENT];
+				break;
+			case Node.DOCUMENT_TYPE_NODE :
+				tab = errTables[NodeType.DOCUMENT_TYPE];
+				break;
+			case Node.TEXT_NODE :
+				tab = errTables[NodeType.TEXT];
+				break;
+			case Node.COMMENT_NODE :
+				tab = errTables[NodeType.COMMENT];
+				break;
+			case Node.CDATA_SECTION_NODE :
+				tab = errTables[NodeType.CDATA_SECTION];
+				break;
+			case Node.PROCESSING_INSTRUCTION_NODE :
+				tab = errTables[NodeType.PROCESSING_INSTRUCTION];
+				break;
+			case Node.ENTITY_REFERENCE_NODE :
+				tab = errTables[NodeType.ENTITY_REFERENCE];
+				break;
+			default :
+				return null;
+		}
+		return tab;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/ModuleCoreSupport.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/ModuleCoreSupport.java
new file mode 100644
index 0000000..1bce59a
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/ModuleCoreSupport.java
@@ -0,0 +1,198 @@
+/*******************************************************************************

+ * Copyright (c) 2007, 2008 IBM Corporation and others.

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ * 

+ * Contributors:

+ *     IBM Corporation - initial API and implementation

+ *******************************************************************************/

+package org.eclipse.wst.html.core.internal.validate;

+

+import org.eclipse.core.filebuffers.FileBuffers;

+import org.eclipse.core.resources.IContainer;

+import org.eclipse.core.resources.IFile;

+import org.eclipse.core.resources.IFolder;

+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.IPath;

+import org.eclipse.core.runtime.Path;

+

+/**

+ * This class encapsulates any used Module Core APIs along with fallbacks for

+ * use on non-compliant projects and when those services are not available at

+ * runtime.

+ * 

+ * Because ModuleCore API calls can result in locks needing to be acquired,

+ * none of these methods should be called while other thread locks have

+ * already been acquired.

+ */

+public final class ModuleCoreSupport {

+	static final boolean _dump_NCDFE = false;

+	private static final String WEB_INF = "WEB-INF"; //$NON-NLS-1$

+	private static final IPath WEB_INF_PATH = new Path(WEB_INF);

+

+	/**

+	 * @param project

+	 * @return the computed IPath to the "root" of the web contents, either

+	 *         from facet knowledge or hueristics, or null if one can not be

+	 *         determined

+	 */

+	public static IPath computeWebContentRootPath(IPath path) {

+		IPath root = null;

+		try {

+			root = ModuleCoreSupportDelegate.getWebContentRootPath(ResourcesPlugin.getWorkspace().getRoot().getProject(path.segment(0)));

+		}

+		catch (NoClassDefFoundError e) {

+			if (_dump_NCDFE)

+				e.printStackTrace();

+		}

+		if (root == null) {

+			/*

+			 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=213245

+			 * 

+			 * NPE in JSPTaglibDirectiveContentAssistProcessor with

+			 * non-faceted project

+			 */

+			root = getLocalRoot(path);

+		}

+		return root;

+	}

+

+	/**

+	 * @param project

+	 * @return the IPath to the "root" of the web contents

+	 */

+	public static IPath getWebContentRootPath(IProject project) {

+		if (project == null)

+			return null;

+

+		IPath path = null;

+		try {

+			path = ModuleCoreSupportDelegate.getWebContentRootPath(project);

+		}

+		catch (NoClassDefFoundError e) {

+			if (_dump_NCDFE)

+				e.printStackTrace();

+		}

+		return path;

+	}

+

+	/**

+	 * @param path

+	 *            - the full path to a resource within the workspace

+	 * @return - the runtime path of the resource if one exists, null

+	 *         otherwise

+	 */

+	public static IPath getRuntimePath(IPath path) {

+		IPath result = null;

+		try {

+			result = ModuleCoreSupportDelegate.getRuntimePath(path);

+		}

+		catch (NoClassDefFoundError e) {

+			if (_dump_NCDFE)

+				e.printStackTrace();

+		}

+		if (result == null) {

+			IPath root = getLocalRoot(path);

+			result = path.removeFirstSegments(root.segmentCount()).makeAbsolute();

+		}

+		return result;

+	}

+

+	/**

+	 * @param basePath

+	 *            - the full path to a resource within the workspace

+	 * @param reference

+	 *            - the reference string to resolve

+	 * @return - the full path within the workspace that corresponds to the

+	 *         given reference according to the virtual pathing support

+	 */

+	public static IPath resolve(IPath basePath, String reference) {

+		IPath resolvedPath = null;

+		try {

+			resolvedPath = ModuleCoreSupportDelegate.resolve(basePath, reference);

+		}

+		catch (NoClassDefFoundError e) {

+			if (_dump_NCDFE)

+				e.printStackTrace();

+		}

+

+		if (resolvedPath == null) {

+			IPath rootPath = getLocalRoot(basePath);

+			if (reference.startsWith(Path.ROOT.toString())) {

+				resolvedPath = rootPath.append(reference);

+			}

+			else {

+				resolvedPath = basePath.removeLastSegments(1).append(reference);

+			}

+		}

+

+		return resolvedPath;

+	}

+

+	/**

+	 * @param basePath

+	 * @return the applicable Web context root path, if one exists

+	 */

+	private static IPath getLocalRoot(IPath basePath) {

+		IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();

+

+		// existing workspace resources - this is the 93% case

+		IResource file = FileBuffers.getWorkspaceFileAtLocation(basePath);

+

+		// Try the base path as a folder first

+		if (file == null && basePath.segmentCount() > 1) {

+			file = workspaceRoot.getFolder(basePath);

+		}

+		// If not a folder, then try base path as a file

+		if (file != null && !file.exists() && basePath.segmentCount() > 1) {

+			file = workspaceRoot.getFile(basePath);

+		}

+

+		if (file == null && basePath.segmentCount() == 1) {

+			file = workspaceRoot.getProject(basePath.segment(0));

+		}

+

+		if (file == null) {

+			/*

+			 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=116529

+			 * 

+			 * This method produces a less accurate result, but doesn't

+			 * require that the file exist yet.

+			 */

+			IFile[] files = ResourcesPlugin.getWorkspace().getRoot().findFilesForLocation(basePath);

+			if (files.length > 0)

+				file = files[0];

+		}

+

+		while (file != null) {

+			/**

+			 * Treat any parent folder with a WEB-INF subfolder as a web-app

+			 * root

+			 */

+			IContainer folder = null;

+			if ((file.getType() & IResource.FOLDER) != 0) {

+				folder = (IContainer) file;

+			}

+			else {

+				folder = file.getParent();

+			}

+			// getFolder on a workspace root must use a full path, skip

+			if (folder != null && (folder.getType() & IResource.ROOT) == 0) {

+				IFolder webinf = folder.getFolder(WEB_INF_PATH);

+				if (webinf != null && webinf.exists()) {

+					return folder.getFullPath();

+				}

+			}

+			file = file.getParent();

+		}

+

+		return basePath.uptoSegment(1);

+	}

+

+

+}

diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/ModuleCoreSupportDelegate.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/ModuleCoreSupportDelegate.java
new file mode 100644
index 0000000..818d340
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/ModuleCoreSupportDelegate.java
@@ -0,0 +1,151 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.validate;
+
+import java.lang.ref.Reference;
+import java.lang.ref.SoftReference;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.wst.common.componentcore.ComponentCore;
+import org.eclipse.wst.common.componentcore.ModuleCoreNature;
+import org.eclipse.wst.common.componentcore.resources.IVirtualComponent;
+import org.eclipse.wst.common.componentcore.resources.IVirtualFile;
+import org.eclipse.wst.common.componentcore.resources.IVirtualResource;
+
+/**
+ * Wrapper class for all Facet-related calls. If the Facet or ModuleCore
+ * bundles are not available, this class will not load, or if it does, its
+ * methods will cause NoClassDefFoundErrors. This allows us to
+ * compartmentalize the dependencies.
+ * 
+ */
+final class ModuleCoreSupportDelegate {
+	private static final String SLASH = "/";
+	private static Map fResolvedMap = new HashMap();
+
+	/**
+	 * @param path
+	 *            - the full path to a resource within the workspace
+	 * @return - the runtime path of the resource if one exists, null
+	 *         otherwise
+	 */
+	static IPath getRuntimePath(IPath path) {
+		if (path == null)
+			return null;
+
+		IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(path.segment(0));
+
+		if (!ModuleCoreNature.isFlexibleProject(project))
+			return null;
+
+		IVirtualResource[] virtualResources = ComponentCore.createResources(ResourcesPlugin.getWorkspace().getRoot().getFile(path));
+		if (virtualResources != null && virtualResources.length > 0) {
+			return virtualResources[0].getRuntimePath();
+		}
+		return null;
+	}
+
+	/**
+	 * @param project
+	 * @return the IPath to the "root" of the web contents
+	 */
+	static IPath getWebContentRootPath(IProject project) {
+		if (project == null)
+			return null;
+
+		if (!ModuleCoreNature.isFlexibleProject(project))
+			return null;
+
+		IPath path = null;
+		IVirtualComponent component = ComponentCore.createComponent(project);
+		if (component != null && component.exists()) {
+			path = component.getRootFolder().getWorkspaceRelativePath();
+		}
+		return path;
+	}
+
+	/**
+	 * @param basePath
+	 *            - the full path to a resource within the workspace
+	 * @param reference
+	 *            - the reference string to resolve
+	 * @return - the full path within the workspace that corresponds to the
+	 *         given reference according to the virtual pathing support
+	 */
+	static IPath resolve(IPath basePath, String reference) {
+		if (reference == null || basePath == null || basePath.segmentCount() == 0)
+			return null;
+
+		IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(basePath.segment(0));
+
+		if (!ModuleCoreNature.isFlexibleProject(project))
+			return null;
+
+		if (basePath.segmentCount() > 1) {
+			/*
+			 * It can take the better part of a full second to do this, so
+			 * cache the result.
+			 */
+			IPath resolved = null;
+			Map mapForBaseResource = null;
+			mapForBaseResource = (Map) fResolvedMap.get(basePath);
+			if (mapForBaseResource != null) {
+				Reference resolvedReference = (Reference) mapForBaseResource.get(reference);
+				if (resolvedReference != null)
+					resolved = (IPath) resolvedReference.get();
+			}
+			else {
+				mapForBaseResource = new HashMap();
+				fResolvedMap.put(basePath, mapForBaseResource);
+			}
+
+			if (resolved == null) {
+				IFile baseFile = ResourcesPlugin.getWorkspace().getRoot().getFile(basePath);
+				IVirtualResource[] virtualResources = ComponentCore.createResources(baseFile);
+				for (int i = 0; i < virtualResources.length; i++) {
+					IPath baseRuntimePath = virtualResources[i].getRuntimePath();
+					IPath referenceRuntimePath = null;
+					if (reference.startsWith(SLASH)) {
+						referenceRuntimePath = new Path(reference);
+					}
+					else {
+						referenceRuntimePath = baseRuntimePath.removeLastSegments(1).append(reference);
+					}
+					IVirtualFile virtualFile = ComponentCore.createFile(project, referenceRuntimePath);
+					if (virtualFile != null && virtualFile.exists()) {
+						IFile[] underlyingFiles = virtualFile.getUnderlyingFiles();
+						for (int j = 0; j < underlyingFiles.length; j++) {
+							if (underlyingFiles[j].getProject().equals(project) && underlyingFiles[j].exists()) {
+								mapForBaseResource.put(reference, new SoftReference(underlyingFiles[j].getFullPath()));
+								resolved = underlyingFiles[j].getFullPath();
+							}
+
+						}
+					}
+				}
+			}
+			return resolved;
+		}
+		else {
+			IVirtualFile virtualFile = ComponentCore.createFile(project, new Path(reference));
+			if (virtualFile != null && virtualFile.exists()) {
+				return virtualFile.getUnderlyingFile().getFullPath();
+			}
+		}
+		return null;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/NamespaceValidator.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/NamespaceValidator.java
new file mode 100644
index 0000000..0df91b7
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/NamespaceValidator.java
@@ -0,0 +1,132 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.validate;
+
+import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMAttr;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+public class NamespaceValidator extends PrimeValidator implements ErrorState {
+
+	private final static String XMLNS_PREFIX = "xmlns";//$NON-NLS-1$
+	private final static String NS_SEPARATOR = ":";//$NON-NLS-1$
+
+	public NamespaceValidator() {
+		super();
+	}
+
+	public boolean isAdapterForType(Object type) {
+		return ((type == NamespaceValidator.class) || super.isAdapterForType(type));
+	}
+
+	public void validate(IndexedRegion node) {
+		Element target = (Element) node;
+		if (isXMLElement(target) && hasUnknownPrefix(target)) {
+			IDOMElement e = (IDOMElement) target;
+			if (!isValidPrefix(e.getPrefix(), target) && !e.isCommentTag()) {
+				// report unknown tag error.
+				Segment errorSeg = null;
+				if (e.hasStartTag())
+					errorSeg = FMUtil.getSegment(e, FMUtil.SEG_START_TAG);
+				else if (e.hasEndTag())
+					errorSeg = FMUtil.getSegment(e, FMUtil.SEG_END_TAG);
+
+				if (errorSeg != null)
+					reporter.report(new ErrorInfoImpl(UNDEFINED_NAME_ERROR, errorSeg, e));
+			}
+		}
+		// (2) check prefix of each attr 
+		NamedNodeMap attrs = target.getAttributes();
+		for (int i = 0; i < attrs.getLength(); i++) {
+			Node n = attrs.item(i);
+			if (!(n instanceof IDOMAttr))
+				continue;
+			IDOMAttr a = (IDOMAttr) n;
+			String prefix = a.getPrefix();
+			if ((prefix != null) && isUnknownAttr(a, target)) {
+				// The attr has unknown prefix.  So, check it.
+				if (!isValidPrefix(prefix, target)) {
+					// report unknown attr error.
+					ITextRegion r = a.getNameRegion();
+					if (r == null)
+						continue;
+					int a_offset = a.getNameRegionStartOffset();
+					int a_length = a.getNameRegion().getLength();
+					reporter.report(new ErrorInfoImpl(UNDEFINED_NAME_ERROR, new Segment(a_offset, a_length), a));
+				}
+			}
+		}
+	}
+
+	// private methods	
+	private boolean isXMLElement(Element target) {
+		return target instanceof IDOMElement;
+	}
+
+	private boolean hasUnknownPrefix(Element target) {
+		return isUnknownElement(target) && CMUtil.isForeign(target);
+	}
+
+	private boolean isUnknownElement(Element target) {
+		CMElementDeclaration dec = CMUtil.getDeclaration(target);
+		return dec == null;
+	}
+
+	private boolean isUnknownAttr(IDOMAttr attr, Element target) {
+		CMElementDeclaration dec = CMUtil.getDeclaration(target);
+		if (dec == null)
+			return true; // unknown.
+		CMNamedNodeMap adecls = dec.getAttributes();
+		CMAttributeDeclaration adec = (CMAttributeDeclaration) adecls.getNamedItem(attr.getName());
+		return adec == null;
+	}
+
+	private boolean isValidPrefix(String prefix, Element e) {
+		if (prefix.equals(XMLNS_PREFIX))
+			return true; // "xmlns:foo" attr is always valid.
+
+		// (1) check the element has the namespace definition or not.
+		if (isValidPrefixWithinElement(prefix, e))
+			return true;
+
+		// (2) check ancestors of the element have the namespace definition or not.
+		Element parent = SMUtil.getParentElement(e);
+		while (parent != null) {
+			if (isValidPrefixWithinElement(prefix, parent))
+				return true;
+			parent = SMUtil.getParentElement(parent);
+		}
+		return false;
+	}
+
+	private boolean isValidPrefixWithinElement(String prefix, Element e) {
+		String ns = XMLNS_PREFIX + NS_SEPARATOR + prefix;
+		NamedNodeMap attrs = e.getAttributes();
+		for (int i = 0; i < attrs.getLength(); i++) {
+			Node n = attrs.item(i);
+			if (n == null)
+				continue;
+			if (n.getNodeType() != Node.ATTRIBUTE_NODE)
+				continue;
+			if (ns.equals(((Attr) n).getName()))
+				return true;
+		}
+		return false;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/NullValidator.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/NullValidator.java
new file mode 100644
index 0000000..165c4a6
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/NullValidator.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.validate;
+
+import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
+import org.eclipse.wst.sse.core.internal.validate.ValidationReporter;
+import org.eclipse.wst.xml.core.internal.validate.ValidationComponent;
+
+/**
+ * NullValidator class is intended to be a replacement of null
+ * for ValidationComponent type.
+ */
+final class NullValidator extends ValidationComponent {
+
+	public NullValidator() {
+		super();
+	}
+
+	public void validate(IndexedRegion node) {
+		return;
+	}
+
+	public void setReporter(ValidationReporter reporter) {
+		return;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/PrimeValidator.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/PrimeValidator.java
new file mode 100644
index 0000000..f9aa0e5
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/PrimeValidator.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.validate;
+
+
+
+import org.eclipse.wst.xml.core.internal.validate.ValidationComponent;
+
+abstract class PrimeValidator extends ValidationComponent {
+
+	/**
+	 * PrimeValidator constructor comment.
+	 */
+	public PrimeValidator() {
+		super();
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/SMUtil.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/SMUtil.java
new file mode 100644
index 0000000..8d3b9c0
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/SMUtil.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.validate;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+final class SMUtil {
+
+	private SMUtil() {
+		super();
+	}
+
+	/* get an ancestor element ignoring implicit ones. */
+	public static Element getParentElement(Node child) {
+		if (child == null)
+			return null;
+
+		Node p = child.getParentNode();
+		while (p != null) {
+			if (p.getNodeType() == Node.ELEMENT_NODE) {
+				return (Element) p;
+			}
+			p = p.getParentNode();
+		}
+		return null;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/Segment.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/Segment.java
new file mode 100644
index 0000000..48baf4e
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/Segment.java
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.validate;
+
+
+
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+
+public class Segment {
+
+	private int offset = 0;
+	private int length = 0;
+
+	/**
+	 */
+	public Segment(int offset, int length) {
+		super();
+		this.offset = offset;
+		this.length = length;
+	}
+
+	public Segment(IStructuredDocumentRegion region) {
+		super();
+		this.offset = region.getStartOffset();
+		this.length = region.getLength();
+	}
+
+	/**
+	 * NOTE: 'start' and 'end' must be the start and end of the contiguous regions.
+	 * Otherwise, this class cannot work correctly.
+	 */
+	public Segment(IStructuredDocumentRegion start, IStructuredDocumentRegion end) {
+		super();
+		this.offset = start.getStartOffset();
+		int endOffset = (end == null) ? start.getEndOffset() : end.getEndOffset();
+		this.length = endOffset - this.offset;
+	}
+
+	//public Segment(ITextRegion start, ITextRegion end) {
+	//	super();
+	//	this.offset = start.getStartOffset();
+	//	int endOffset = (end == null) ? start.getEndOffset() : end.getEndOffset();
+	//	this.length = endOffset - this.offset;
+	//}
+	/**
+	 */
+	public int getLength() {
+		return this.length;
+	}
+
+	/**
+	 */
+	public int getOffset() {
+		return this.offset;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/SyntaxValidator.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/SyntaxValidator.java
new file mode 100644
index 0000000..4dd8979
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/SyntaxValidator.java
@@ -0,0 +1,413 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.internal.validate;
+
+import java.util.Iterator;
+
+import org.eclipse.wst.html.core.internal.contentmodel.HTMLElementDeclaration;
+import org.eclipse.wst.html.core.internal.contentmodel.HTMLPropertyDeclaration;
+import org.eclipse.wst.html.core.internal.document.HTMLDocumentTypeEntry;
+import org.eclipse.wst.html.core.internal.document.HTMLDocumentTypeRegistry;
+import org.eclipse.wst.html.core.internal.provisional.HTML50Namespace;
+import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
+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.ITextRegionList;
+import org.eclipse.wst.sse.core.internal.validate.ErrorInfo;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.document.InvalidCharacterException;
+import org.eclipse.wst.xml.core.internal.document.SourceValidator;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+class SyntaxValidator extends PrimeValidator implements ErrorState {
+
+
+	static private boolean isValidRegion(ITextRegion rgn) {
+		String type = rgn.getType();
+		if (type == null)
+			return false; // no type is invalid.
+		if (type == DOMRegionContext.XML_END_TAG_OPEN || type == DOMRegionContext.XML_TAG_NAME || type == DOMRegionContext.XML_TAG_CLOSE) {
+			return true;
+		}
+		return false;
+	}
+
+	static private String getTagName(IStructuredDocumentRegion tag) {
+		ITextRegionList regions = tag.getRegions();
+		Iterator iter = regions.iterator();
+		while (iter.hasNext()) {
+			ITextRegion rgn = (ITextRegion) iter.next();
+			if (rgn.getType() == DOMRegionContext.XML_TAG_NAME)
+				return tag.getText(rgn);
+		}
+		return "";//$NON-NLS-1$
+	}
+
+	static private boolean isEmptyContent(CMElementDeclaration decl) {
+		return (decl != null) && (decl.getContentType() == CMElementDeclaration.EMPTY);
+	}
+
+	public SyntaxValidator() {
+		super();
+	}
+
+	public boolean isAdapterForType(Object type) {
+		return ((type == SyntaxValidator.class) || super.isAdapterForType(type));
+	}
+
+	class ElementInfo {
+		public ElementInfo() {
+			super();
+		}
+
+		public IDOMElement target = null;
+		public CMElementDeclaration decl = null;
+		public IStructuredDocumentRegion startTag = null;
+		public IStructuredDocumentRegion endTag = null;
+		public boolean hasStartTag() {return startTag != null;}
+		public boolean hasEndTag() {return endTag != null;}
+		public boolean isXHTML = false;
+		public boolean isXHTML5 = false;
+	}
+
+	public void validate(IndexedRegion indexedNode) {
+		Node node = (Node) indexedNode;
+		validateChildren(node);
+
+		if (node.getNodeType() != Node.ELEMENT_NODE)
+			return;
+		if (!(node instanceof IDOMElement))
+			return;
+
+		ElementInfo info = new ElementInfo();
+		info.target = (IDOMElement) node;
+
+		// gather information to validate from target at once.
+		getInfo(info);
+
+		validateTags(info);
+		if (info.target.isGlobalTag()) {
+			validateNames(info);
+			if (info.decl != null && info.isXHTML) {
+				validateTagCase(info);
+			}
+		}
+	}
+
+	private void getInfo(ElementInfo info) {
+		info.decl = CMUtil.getDeclaration(info.target);
+		info.startTag = info.target.getStartStructuredDocumentRegion();
+		info.endTag = info.target.getEndStructuredDocumentRegion();
+
+		Document doc = info.target.getOwnerDocument();
+		if (!(doc instanceof IDOMDocument))
+			return;
+		String typeid = ((IDOMDocument) doc).getDocumentTypeId();
+		if (typeid != null) {
+			if (typeid.trim().length()!= 0){
+				HTMLDocumentTypeEntry entry = HTMLDocumentTypeRegistry.getInstance().getEntry(typeid);
+				info.isXHTML = (entry != null && entry.isXMLType());
+			}
+			else {
+				info.isXHTML = getXMLTarget(doc);
+				info.isXHTML5 = info.isXHTML;
+			}
+		}
+	}
+	
+	private boolean getXMLTarget(Document doc) {
+		if (doc == null)
+			return false;
+		Node child = doc.getFirstChild();
+		while (child != null) {
+			if (child.getNodeType() == Node.ELEMENT_NODE) {
+				if (child.getNodeName().equalsIgnoreCase("html")){
+					if (child.getAttributes()!= null){
+						NamedNodeMap attrs = child.getAttributes();
+						for (int i = 0; i < attrs.getLength(); i++) {
+							Attr a = (Attr) attrs.item(i);
+							if (a.getName().equalsIgnoreCase(HTML50Namespace.ATTR_NAME_XMLNS))
+									return true;
+						}
+					}
+					return false;
+				}
+				
+			}
+			child = child.getNextSibling();
+		}
+		return false;
+	}
+
+	class TagErrorInfoImpl extends AbstractErrorInfo {
+		private String hint = null;
+
+		public TagErrorInfoImpl(int state, IStructuredDocumentRegion tag, String hint) {
+			super(state, new Segment(tag));
+			this.hint = hint;
+		}
+
+		public String getHint() {
+			return hint;
+		}
+
+		public short getTargetType() {
+			return Node.ELEMENT_NODE;
+		}
+	}
+
+	private boolean isEndTagCorrupted(ElementInfo info) {
+		ITextRegionList regions = info.endTag.getRegions();
+		if (regions == null || regions.isEmpty())
+			return false;
+		Iterator iter = regions.iterator();
+		while (iter.hasNext()) {
+			ITextRegion rgn = (ITextRegion) iter.next();
+			if (!isValidRegion(rgn))
+				return true; // found invalid region type.
+		}
+		return false; // all regions are valid.
+	}
+
+	private String getEndTagFullText(ElementInfo info) {
+		String hint = "";//$NON-NLS-1$
+		ITextRegionList regions = info.endTag.getRegions();
+		Iterator iter = regions.iterator();
+		while (iter.hasNext()) {
+			ITextRegion rgn = (ITextRegion) iter.next();
+			String type = rgn.getType();
+			if (type == null)
+				continue;
+			if (type == DOMRegionContext.XML_END_TAG_OPEN || type == DOMRegionContext.XML_TAG_CLOSE)
+				continue;
+			hint += info.endTag.getFullText(rgn);
+		}
+		return hint;
+	}
+
+	private void reportCorruptedEndTagError(ElementInfo info) {
+		String hint = getEndTagFullText(info);
+		TagErrorInfoImpl error = new TagErrorInfoImpl(UNDEFINED_NAME_ERROR, info.endTag, hint);
+		this.reporter.report(error);
+	}
+
+	private void validateTags(ElementInfo info) {
+		if (info.hasStartTag()) {
+			if (!info.target.isStartTagClosed()) {
+				// Mark the whole START tag as an error segment.
+				Segment errorSeg = new Segment(info.startTag);
+				report(UNCLOSED_TAG_ERROR, errorSeg, info.target);
+			}
+		}
+		else {
+			if (info.hasEndTag()) {
+				if (info.decl != null) {
+					//if xhtml then must have end tag
+					//else determine if end tag is omissible
+					if (info.isXHTML) {
+						Segment errorSeg = FMUtil.getSegment(info.target, FMUtil.SEG_END_TAG_NAME);
+						report(MISSING_START_TAG_ERROR, errorSeg, info.target);
+					} else {
+						//determine if the end tag is omissible
+						boolean canOmitStartTag = false;
+						if(info.decl instanceof HTMLPropertyDeclaration) {
+							int omitType = ((HTMLPropertyDeclaration)info.decl).getOmitType();
+							canOmitStartTag = omitType == HTMLElementDeclaration.OMIT_BOTH;
+						}
+					
+						if (!canOmitStartTag && !info.target.hasChildNodes()) {
+							if (info.target.isContainer()) {
+								// Set the error mark to the start of the element.
+								Segment errorSeg = FMUtil.getSegment(info.target, FMUtil.SEG_END_TAG);
+								report(MISSING_START_TAG_ERROR, errorSeg, info.target);
+							}
+							else {
+								// Mark the whole END tag as an error segment.
+								Segment errorSeg = new Segment(info.endTag);
+								report(UNNECESSARY_END_TAG_ERROR, errorSeg, info.target);
+							}
+						}
+					}
+				}
+			}
+		}
+
+		if (info.hasEndTag()) {
+			if (!info.target.isClosed()) {
+				// Set the whole END tag as error segment.
+				Segment errorSeg = new Segment(info.endTag);
+				report(UNCLOSED_END_TAG_ERROR, errorSeg, info.target);
+			}
+		}
+		else {
+			if (info.isXHTML) { // XHTML
+				//if editor closed during validation this could be null
+				IStructuredDocumentRegion structRegion = info.target.getStartStructuredDocumentRegion();
+				if (!info.target.isEmptyTag() && structRegion != null && DOMRegionContext.XML_TAG_OPEN.equals(structRegion.getFirstRegion().getType())) {
+					/*
+					 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=248963 :
+					 * report empty tags not written as such, but only when
+					 * they follow actual XML/HTML syntax
+					 */
+					if (isEmptyContent(info.decl)) {
+						// EMPTY element should be written in <.../> form
+						Segment errorSeg = FMUtil.getSegment(info.target, FMUtil.SEG_START_TAG);
+						report(INVALID_EMPTY_ELEMENT_TAG, errorSeg, info.target);
+					}
+					else {
+						// end tag is required.
+						Segment errorSeg = FMUtil.getSegment(info.target, FMUtil.SEG_START_TAG);
+						report(MISSING_END_TAG_ERROR, errorSeg, info.target);
+					}
+				}
+			}
+			else { // HTML
+				if (info.hasStartTag()) {
+					if (info.decl != null && CMUtil.isHTML(info.decl) && !info.target.isEmptyTag() && !CMUtil.isEndTagOmissible(info.decl) && DOMRegionContext.XML_TAG_OPEN.equals(info.startTag.getFirstRegion().getType())) {
+						// Set the error mark to the end of the element.
+						Segment errorSeg = FMUtil.getSegment(info.target, FMUtil.SEG_START_TAG);
+						report(MISSING_END_TAG_ERROR, errorSeg, info.target);
+					}
+				}
+			}
+		}
+	}
+
+	/* perform validation about tag name definition. */
+	private void validateNames(ElementInfo info) {
+		boolean corrupted = info.hasEndTag() && isEndTagCorrupted(info);
+		if (info.decl == null) {
+			// If no declaration is retrieved, the target is really
+			// unknown element.
+			if (!info.hasStartTag() && corrupted) {
+				reportCorruptedEndTagError(info);
+			}
+			else {
+				Segment errorSeg = FMUtil.getSegment(info.target, FMUtil.SEG_START_TAG_NAME);
+				report(UNDEFINED_NAME_ERROR, errorSeg, info.target);
+			}
+		}
+		else {
+			// Even if a declaration could be retrieved, if the end
+			// tag is corrupted, it should be reported as undefined
+			// name. (D202493)
+			if (corrupted) {
+				reportCorruptedEndTagError(info);
+			}
+		}
+	}
+
+	/* perform validation tag case only for XHTML document */
+	private void validateTagCase(ElementInfo info) {
+		String declared = info.decl.getElementName();
+		String startTagName = "";//$NON-NLS-1$
+		String endTagName = "";//$NON-NLS-1$
+		if (declared == null)
+			return;
+
+		if (info.isXHTML5){
+			if (info.hasStartTag()) {
+				startTagName = getTagName(info.startTag);
+				if (info.hasEndTag()) {
+					endTagName = getTagName(info.endTag);
+					if (!endTagName.equals(startTagName)){
+						TagErrorInfoImpl error = new TagErrorInfoImpl(MISMATCHED_ERROR, info.endTag, endTagName);
+						this.reporter.report(error);
+					}
+				}
+			}
+			
+		}
+		else
+		{
+			// start tag
+			if (info.hasStartTag()) {
+				startTagName = getTagName(info.startTag);
+				if (!declared.equals(startTagName)) {
+					TagErrorInfoImpl error = new TagErrorInfoImpl(MISMATCHED_ERROR, info.startTag, startTagName);
+					this.reporter.report(error);
+				}
+			}
+			// end tag
+			if (info.hasEndTag()) {
+				endTagName = getTagName(info.endTag);
+				if (!info.hasStartTag() || (!endTagName.equals(startTagName))) {
+					if (!declared.equals(endTagName)) {
+						TagErrorInfoImpl error = new TagErrorInfoImpl(MISMATCHED_ERROR, info.endTag, endTagName);
+						this.reporter.report(error);
+					}
+				}
+			}
+		}
+		
+	}
+
+	private void validateChildren(Node target) {
+		if ((target.getNodeType() == Node.ELEMENT_NODE) && CMUtil.isForeign((Element) target))
+			return;
+
+		for (Node child = target.getFirstChild(); child != null; child = child.getNextSibling()) {
+			switch (child.getNodeType()) {
+				case Node.TEXT_NODE :
+					{
+						IDOMNode text = (IDOMNode) child;
+						int charOffset = validateTextSource(text);
+						if (charOffset >= 0) {
+							charOffset += text.getStartOffset();
+							Segment errorSeg = new Segment(charOffset, 1);
+							if (errorSeg != null)
+								report(INVALID_CHAR_ERROR, errorSeg, text);
+						}
+						break;
+					}
+				case Node.COMMENT_NODE :
+				case Node.DOCUMENT_TYPE_NODE :
+				case Node.PROCESSING_INSTRUCTION_NODE :
+				case Node.CDATA_SECTION_NODE :
+					{
+						IDOMNode tag = (IDOMNode) child;
+						if (!tag.isClosed()) {
+							Segment errorSeg = FMUtil.getSegment(tag, FMUtil.SEG_WHOLE_TAG);
+							if (errorSeg != null)
+								report(UNCLOSED_TAG_ERROR, errorSeg, tag);
+						}
+						break;
+					}
+				default :
+					break;
+			}
+		}
+	}
+
+	private int validateTextSource(IDOMNode text) {
+		try {
+			SourceValidator validator = new SourceValidator(text);
+			validator.validateSource(text.getSource());
+		}
+		catch (InvalidCharacterException ex) {
+			return ex.getOffset();
+		}
+		return -1;
+	}
+
+	private void report(int state, Segment errorSeg, Node node) {
+		ErrorInfo info = new ErrorInfoImpl(state, errorSeg, node);
+		reporter.report(info);
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/text/IHTMLPartitions.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/text/IHTMLPartitions.java
new file mode 100644
index 0000000..f5e98cd
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/text/IHTMLPartitions.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 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
+ *******************************************************************************/
+package org.eclipse.wst.html.core.text;
+
+
+/**
+ * This interface is not intended to be implemented. It defines the partition
+ * types for HTML. Clients should reference the partition type Strings defined
+ * here directly.
+ * 
+ * @since 1.1
+ */
+public interface IHTMLPartitions {
+
+	String HTML_DEFAULT = "org.eclipse.wst.html.HTML_DEFAULT"; //$NON-NLS-1$
+	String HTML_DECLARATION = "org.eclipse.wst.html.HTML_DECLARATION"; //$NON-NLS-1$
+	String HTML_COMMENT = "org.eclipse.wst.html.HTML_COMMENT"; //$NON-NLS-1$
+
+	String SCRIPT = "org.eclipse.wst.html.SCRIPT"; //$NON-NLS-1$
+	String SCRIPT_EVENTHANDLER = SCRIPT + ".EVENTHANDLER"; //$NON-NLS-1$
+	
+	/**
+	 * @deprecated this partition type is not used locally any longer
+	 */
+	String STYLE = "org.eclipse.wst.html.STYLE"; //$NON-NLS-1$
+
+	// ISSUE: I think meta tag areas are here too?
+}
diff --git a/bundles/org.eclipse.wst.html.ui/.classpath b/bundles/org.eclipse.wst.html.ui/.classpath
new file mode 100644
index 0000000..ce55878
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/.classpath
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="src" path="src-html-validation"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.4"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins">
+		<accessrules>
+			<accessrule kind="accessible" pattern="org/eclipse/wst/**"/>
+		</accessrules>
+	</classpathentry>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/bundles/org.eclipse.wst.html.ui/.cvsignore b/bundles/org.eclipse.wst.html.ui/.cvsignore
new file mode 100644
index 0000000..e4239f5
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/.cvsignore
@@ -0,0 +1,7 @@
+bin
+htmleditor.jar
+temp.folder
+build.xml
+@dot
+src.zip
+javaCompiler...args
diff --git a/bundles/org.eclipse.wst.html.ui/.options b/bundles/org.eclipse.wst.html.ui/.options
new file mode 100644
index 0000000..6d015ff
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/.options
@@ -0,0 +1 @@
+org.eclipse.wst.html.ui/projectionperf=false
diff --git a/bundles/org.eclipse.wst.html.ui/.project b/bundles/org.eclipse.wst.html.ui/.project
new file mode 100644
index 0000000..38bee73
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.wst.html.ui</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.ManifestBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.SchemaBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.PluginNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
diff --git a/bundles/org.eclipse.wst.html.ui/.settings/org.eclipse.core.resources.prefs b/bundles/org.eclipse.wst.html.ui/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..afa5c91
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+#Tue Apr 04 03:36:32 EDT 2006
+eclipse.preferences.version=1
+encoding/<project>=ISO-8859-1
diff --git a/bundles/org.eclipse.wst.html.ui/.settings/org.eclipse.core.runtime.prefs b/bundles/org.eclipse.wst.html.ui/.settings/org.eclipse.core.runtime.prefs
new file mode 100644
index 0000000..7ec5750
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/.settings/org.eclipse.core.runtime.prefs
@@ -0,0 +1,3 @@
+#Mon Apr 17 01:48:39 EDT 2006
+eclipse.preferences.version=1
+line.separator=\r\n
diff --git a/bundles/org.eclipse.wst.html.ui/.settings/org.eclipse.jdt.core.prefs b/bundles/org.eclipse.wst.html.ui/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..ecc10e4
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,79 @@
+#Wed Mar 28 03:26:40 EDT 2007
+eclipse.preferences.version=1
+org.eclipse.jdt.core.builder.cleanOutputFolder=clean
+org.eclipse.jdt.core.builder.duplicateResourceTask=warning
+org.eclipse.jdt.core.builder.invalidClasspath=ignore
+org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch
+org.eclipse.jdt.core.circularClasspath=error
+org.eclipse.jdt.core.classpath.exclusionPatterns=enabled
+org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=disabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.2
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.4
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.doc.comment.support=enabled
+org.eclipse.jdt.core.compiler.maxProblemPerUnit=100
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=warning
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.deprecation=ignore
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=enabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=warning
+org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=ignore
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=error
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=error
+org.eclipse.jdt.core.compiler.problem.invalidJavadoc=ignore
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=private
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=error
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=enabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public
+org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=enabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=private
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=error
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=error
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=error
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=enabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=error
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=ignore
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=error
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedImport=error
+org.eclipse.jdt.core.compiler.problem.unusedLabel=error
+org.eclipse.jdt.core.compiler.problem.unusedLocal=error
+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=error
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.3
+org.eclipse.jdt.core.incompatibleJDKLevel=ignore
+org.eclipse.jdt.core.incompleteClasspath=error
diff --git a/bundles/org.eclipse.wst.html.ui/.settings/org.eclipse.jdt.ui.prefs b/bundles/org.eclipse.wst.html.ui/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000..301c7ad
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,4 @@
+#Mon Apr 17 01:48:39 EDT 2006
+eclipse.preferences.version=1
+internal.default.compliance=default
+org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8"?>\r\n<templates/>
diff --git a/bundles/org.eclipse.wst.html.ui/.settings/org.eclipse.ltk.core.refactoring.prefs b/bundles/org.eclipse.wst.html.ui/.settings/org.eclipse.ltk.core.refactoring.prefs
new file mode 100644
index 0000000..c59368c
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/.settings/org.eclipse.ltk.core.refactoring.prefs
@@ -0,0 +1,3 @@
+#Tue Apr 04 03:36:32 EDT 2006
+eclipse.preferences.version=1
+org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false
diff --git a/bundles/org.eclipse.wst.html.ui/.settings/org.eclipse.pde.prefs b/bundles/org.eclipse.wst.html.ui/.settings/org.eclipse.pde.prefs
new file mode 100644
index 0000000..fc522bb
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/.settings/org.eclipse.pde.prefs
@@ -0,0 +1,16 @@
+#Mon Apr 17 02:01:33 EDT 2006
+compilers.incompatible-environment=0
+compilers.p.build=0
+compilers.p.deprecated=1
+compilers.p.illegal-att-value=0
+compilers.p.no-required-att=0
+compilers.p.not-externalized-att=0
+compilers.p.unknown-attribute=0
+compilers.p.unknown-class=0
+compilers.p.unknown-element=0
+compilers.p.unknown-resource=0
+compilers.p.unresolved-ex-points=0
+compilers.p.unresolved-import=0
+compilers.p.unused-element-or-attribute=0
+compilers.use-project=true
+eclipse.preferences.version=1
diff --git a/bundles/org.eclipse.wst.html.ui/META-INF/MANIFEST.MF b/bundles/org.eclipse.wst.html.ui/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..40d2506
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/META-INF/MANIFEST.MF
@@ -0,0 +1,52 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %pluginName
+Bundle-SymbolicName: org.eclipse.wst.html.ui; singleton:=true
+Bundle-Version: 1.0.505.qualifier
+Bundle-Activator: org.eclipse.wst.html.ui.internal.HTMLUIPlugin
+Bundle-Vendor: %providerName
+Bundle-Localization: plugin
+Export-Package: org.eclipse.wst.html.internal.validation;x-internal:=true,
+ org.eclipse.wst.html.ui,
+ org.eclipse.wst.html.ui.internal;x-internal:=true,
+ org.eclipse.wst.html.ui.internal.autoedit;x-internal:=true,
+ org.eclipse.wst.html.ui.internal.contentassist;x-internal:=true,
+ org.eclipse.wst.html.ui.internal.contentoutline;x-internal:=true,
+ org.eclipse.wst.html.ui.internal.contentproperties.ui;x-internal:=true,
+ org.eclipse.wst.html.ui.internal.correction;x-internal:=true,
+ org.eclipse.wst.html.ui.internal.derived;x-internal:=true,
+ org.eclipse.wst.html.ui.internal.edit.ui;x-internal:=true,
+ org.eclipse.wst.html.ui.internal.editor;x-internal:=true,
+ org.eclipse.wst.html.ui.internal.handlers;x-internal:=true,
+ org.eclipse.wst.html.ui.internal.hyperlink;x-internal:=true,
+ org.eclipse.wst.html.ui.internal.preferences;x-internal:=true,
+ org.eclipse.wst.html.ui.internal.preferences.ui;x-internal:=true,
+ org.eclipse.wst.html.ui.internal.registry;x-internal:=true,
+ org.eclipse.wst.html.ui.internal.search;x-internal:=true,
+ org.eclipse.wst.html.ui.internal.style;x-internal:=true,
+ org.eclipse.wst.html.ui.internal.taginfo;x-internal:=true,
+ org.eclipse.wst.html.ui.internal.templates;x-internal:=true,
+ org.eclipse.wst.html.ui.internal.text;x-internal:=true,
+ org.eclipse.wst.html.ui.internal.wizard;x-internal:=true,
+ org.eclipse.wst.html.ui.views.contentoutline
+Import-Package: com.ibm.icu.util; version="3.8",
+ com.ibm.icu.text; version="3.8"
+Require-Bundle: org.eclipse.ui.ide;bundle-version="[3.5.0,4.0.0)",
+ org.eclipse.jface.text;bundle-version="[3.5.0,4.0.0)",
+ org.eclipse.ui.workbench.texteditor;bundle-version="[3.5.0,4.0.0)",
+ org.eclipse.ui.forms;bundle-version="[3.4.0,4.0.0)",
+ org.eclipse.ui;bundle-version="[3.5.0,4.0.0)",
+ org.eclipse.wst.sse.ui;bundle-version="[1.2.0,1.3.0)",
+ org.eclipse.wst.xml.ui;bundle-version="[1.1.100,1.2.0)",
+ org.eclipse.wst.css.ui;bundle-version="[1.0.500,1.1.0)",
+ org.eclipse.wst.sse.core;bundle-version="[1.1.500,1.2.0)",
+ org.eclipse.wst.css.core;bundle-version="[1.1.400,1.2.0)",
+ org.eclipse.wst.html.core;bundle-version="[1.1.400,1.2.0)",
+ org.eclipse.wst.xml.core;bundle-version="[1.1.500,1.2.0)",
+ org.eclipse.core.resources;bundle-version="[3.5.0,4.0.0)",
+ org.eclipse.core.runtime;bundle-version="[3.5.0,4.0.0)",
+ org.eclipse.wst.validation;bundle-version="[1.2.100,1.3.0)",
+ org.eclipse.wst.common.project.facet.core;bundle-version="[1.4.0,2.0.0)";resolution:=optional,
+ org.eclipse.wst.common.modulecore;bundle-version="[1.2.0,2.0.0)";resolution:=optional
+Bundle-ActivationPolicy: lazy
+Bundle-RequiredExecutionEnvironment: J2SE-1.4
diff --git a/bundles/org.eclipse.wst.html.ui/about.html b/bundles/org.eclipse.wst.html.ui/about.html
new file mode 100644
index 0000000..2199df3
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/about.html
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
+<HTML>
+
+<head>
+<title>About</title>
+<meta http-equiv=Content-Type content="text/html; charset=ISO-8859-1">
+</head>
+
+<BODY lang="EN-US">
+
+<H3>About This Content</H3>
+
+<P>June, 2008</P>
+
+<H3>License</H3>
+
+<P>The Eclipse Foundation makes available all content in this plug-in 
+("Content"). Unless otherwise indicated below, the Content is provided to you 
+under the terms and conditions of the Eclipse Public License Version 1.0 
+("EPL"). A copy of the EPL is available at
+<A href="http://www.eclipse.org/org/documents/epl-v10.php">http://www.eclipse.org/org/documents/epl-v10.php</A>. 
+For purposes of the EPL, "Program" will mean the Content.</P>
+
+<P>If you did not receive this Content directly from the Eclipse Foundation, the 
+Content is being redistributed by another party ("Redistributor") and different 
+terms and conditions may apply to your use of any object code in the Content. 
+Check the RedistributorÂ’s license that was provided with the Content. If no such 
+license exists, contact the Redistributor. Unless otherwise indicated below, the 
+terms and conditions of the EPL still apply to any source code in the Content 
+and such source code may be obtained at
+<A href="http://www.eclipse.org/">http://www.eclipse.org/</A>.</P>
+
+</BODY>
+</HTML>
diff --git a/bundles/org.eclipse.wst.html.ui/build.properties b/bundles/org.eclipse.wst.html.ui/build.properties
new file mode 100644
index 0000000..be98a59
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/build.properties
@@ -0,0 +1,22 @@
+###############################################################################
+# Copyright (c) 2004, 2005 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
+###############################################################################
+bin.includes = plugin.xml,\
+               icons/,\
+               plugin.properties,\
+               templates/,\
+               META-INF/,\
+               .,\
+               about.html
+bin.excludes = bin/**,\
+               @dot/**,\
+               temp.folder/**
+source.. = src/,\
+           src-html-validation/
diff --git a/bundles/org.eclipse.wst.html.ui/icons/full/dtool16/newhtml_wiz.gif b/bundles/org.eclipse.wst.html.ui/icons/full/dtool16/newhtml_wiz.gif
new file mode 100644
index 0000000..8175aa9
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/icons/full/dtool16/newhtml_wiz.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.html.ui/icons/full/etool16/newhtml_wiz.gif b/bundles/org.eclipse.wst.html.ui/icons/full/etool16/newhtml_wiz.gif
new file mode 100644
index 0000000..976e18d
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/icons/full/etool16/newhtml_wiz.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.html.ui/icons/full/obj16/sourceEditor.gif b/bundles/org.eclipse.wst.html.ui/icons/full/obj16/sourceEditor.gif
new file mode 100644
index 0000000..75ebdb8
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/icons/full/obj16/sourceEditor.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.html.ui/icons/full/obj16/table.gif b/bundles/org.eclipse.wst.html.ui/icons/full/obj16/table.gif
new file mode 100644
index 0000000..b99b45c
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/icons/full/obj16/table.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.html.ui/icons/full/obj16/tag-anchor.gif b/bundles/org.eclipse.wst.html.ui/icons/full/obj16/tag-anchor.gif
new file mode 100644
index 0000000..f58992d
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/icons/full/obj16/tag-anchor.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.html.ui/icons/full/obj16/tag-body.gif b/bundles/org.eclipse.wst.html.ui/icons/full/obj16/tag-body.gif
new file mode 100644
index 0000000..005fa99
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/icons/full/obj16/tag-body.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.html.ui/icons/full/obj16/tag-button.gif b/bundles/org.eclipse.wst.html.ui/icons/full/obj16/tag-button.gif
new file mode 100644
index 0000000..d143fcf
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/icons/full/obj16/tag-button.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.html.ui/icons/full/obj16/tag-font.gif b/bundles/org.eclipse.wst.html.ui/icons/full/obj16/tag-font.gif
new file mode 100644
index 0000000..bbb40cb
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/icons/full/obj16/tag-font.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.html.ui/icons/full/obj16/tag-form.gif b/bundles/org.eclipse.wst.html.ui/icons/full/obj16/tag-form.gif
new file mode 100644
index 0000000..3b13958
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/icons/full/obj16/tag-form.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.html.ui/icons/full/obj16/tag-generic.gif b/bundles/org.eclipse.wst.html.ui/icons/full/obj16/tag-generic.gif
new file mode 100644
index 0000000..65f516e
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/icons/full/obj16/tag-generic.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.html.ui/icons/full/obj16/tag-html.gif b/bundles/org.eclipse.wst.html.ui/icons/full/obj16/tag-html.gif
new file mode 100644
index 0000000..fb39ba6
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/icons/full/obj16/tag-html.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.html.ui/icons/full/obj16/tag-image-map.gif b/bundles/org.eclipse.wst.html.ui/icons/full/obj16/tag-image-map.gif
new file mode 100644
index 0000000..ef3235d
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/icons/full/obj16/tag-image-map.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.html.ui/icons/full/obj16/tag-image.gif b/bundles/org.eclipse.wst.html.ui/icons/full/obj16/tag-image.gif
new file mode 100644
index 0000000..a988c1d
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/icons/full/obj16/tag-image.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.html.ui/icons/full/obj16/tag-jsp.gif b/bundles/org.eclipse.wst.html.ui/icons/full/obj16/tag-jsp.gif
new file mode 100644
index 0000000..4084602
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/icons/full/obj16/tag-jsp.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.html.ui/icons/full/obj16/tag-template.gif b/bundles/org.eclipse.wst.html.ui/icons/full/obj16/tag-template.gif
new file mode 100644
index 0000000..5d1f81b
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/icons/full/obj16/tag-template.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.html.ui/icons/full/obj16/tag-title.gif b/bundles/org.eclipse.wst.html.ui/icons/full/obj16/tag-title.gif
new file mode 100644
index 0000000..b129090
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/icons/full/obj16/tag-title.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.html.ui/icons/full/obj16/tag.gif b/bundles/org.eclipse.wst.html.ui/icons/full/obj16/tag.gif
new file mode 100644
index 0000000..5e7fb33
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/icons/full/obj16/tag.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.html.ui/icons/full/wizban/newhfile_wiz.png b/bundles/org.eclipse.wst.html.ui/icons/full/wizban/newhfile_wiz.png
new file mode 100644
index 0000000..a4fa448
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/icons/full/wizban/newhfile_wiz.png
Binary files differ
diff --git a/bundles/org.eclipse.wst.html.ui/plugin.properties b/bundles/org.eclipse.wst.html.ui/plugin.properties
new file mode 100644
index 0000000..3232def
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/plugin.properties
@@ -0,0 +1,82 @@
+###############################################################################
+# Copyright (c) 2005, 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
+###############################################################################
+providerName=Eclipse Web Tools Platform
+pluginName=HTML UI Source Editor
+HTML_Source_Page_Editor.name=HTML Editor
+WEB.name=Web
+HTML_Files.name=HTML Files
+HTML_Source.name=Editor
+HTML_Content_Assist.name=Content Assist
+HTML_Templates.name=Templates
+HTML_Styles.name=Styles
+HTML_Syntax_Coloring=Syntax Coloring
+HTML_Typing=Typing
+HTML_Validation=Validation
+HTML_Property_validation=HTML Syntax
+WebContentSettings.name=Web Content Settings
+Device_Profile_Entry_Provider_Extension.name=Device Profile Entry Provider Extension
+All_HTML_context_type_Extension_Element.name=All HTML
+HTML_New_context_type_Extension_Element.name=New HTML
+HTML_Tag_context_type_Extension_Element.name=HTML Tag
+HTML_Attribute_context_type_Extension_Element.name=HTML Attribute
+HTML_Attribute_value_context_type_Extension_Element.name=HTML Attribute value
+HTML_Syntax_Validator.name=HTML Syntax Validator
+###############################################################################
+#org.eclipse.ui.newWizards extension point
+_UI_WIZARD_NAME = HTML File
+_UI_WIZARD_CREATE_NEW_FILE = Create a new HTML file
+##
+AddTask.label=Add &Task...
+AddTask.tooltip=Add Task...
+AddBookmark.label=Add Boo&kmark...
+AddBookmark.tooltip=Add Bookmark...
+SelectRuler.label=Select Ruler
+##
+CleanupDocument_label=Cleanup Document...
+CleanupDocument_tooltip=Cleanup Document
+ToggleComment_label=Toggle Comment
+ToggleComment_tooltip=Toggle Comment
+AddBlockComment_label=Add Block Comment
+AddBlockComment_tooltip=Add Block Comment
+RemoveBlockComment_label=Remove Block Comment
+RemoveBlockComment_tooltip=Remove Block Comment
+FindOccurrences_label=Occurrences in File
+StructureSelectEnclosing_label=Enclosing Element
+StructureSelectEnclosing_tooltip=Expand selection to include enclosing element
+StructureSelectNext_label=Next Element
+StructureSelectNext_tooltip=Expand selection to include next sibling
+StructureSelectPrevious_label=Previous Element
+StructureSelectPrevious_tooltip=Expand selection to include previous sibling
+StructureSelectHistory_label=Restore Last Selection
+StructureSelectHistory_tooltip=Restore last selection
+##
+preferenceKeywords.files=editor html creating saving files suffix specified encoding iana loading
+preferenceKeywords.source=editor html source formatting line width split multiple attributes new clear blank indent tabs spaces size content assist automatically suggestions prompt characters inserted strategy lax strict markup case code generation tag names capitalization uppercase lowercase
+preferenceKeywords.contentassist=html editor content code assist complete completion insert overwrite single proposal common prefix automatically import fill argument name guess alphabetical hide auto activation trigger category categories separate specific
+preferenceKeywords.templates=editor html templates snippet macros
+preferenceKeywords.styles=editor html style customize syntax highlighting type text content foreground background bold color
+preferenceKeywords.webcontent=editor html web content settings profile style document type doctype public system css
+preferenceKeywords.severities=html errors warnings ignore options severity severities suppress project specific projectspecific
+##
+HTML_Editors_target_name=HTML Editors
+
+scope.structured.text.editor.html.name=Editing HTML Source
+scope.structured.text.editor.html.description=Editing HTML Source
+scope.structured.text.editor.html.occurrences.name=HTML Source Occurrences
+scope.structured.text.editor.html.occurrences.description=HTML Source Occurrences
+
+Colors.scriptAreaBorder=Script Area Border
+hyperlinkDetector.anchor.name=Anchors
+hyperlink.target.script.name=HTML Client Script
+hyperlink.target.eventhandler.name=HTML Event Handlers
+
+proposalCategory.htmlTags=HTML Tag Proposals
+proposalCategory.htmlTemplates=HTML Template Proposals
diff --git a/bundles/org.eclipse.wst.html.ui/plugin.xml b/bundles/org.eclipse.wst.html.ui/plugin.xml
new file mode 100644
index 0000000..4652ead
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/plugin.xml
@@ -0,0 +1,738 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+<plugin>
+
+	<extension-point id="deviceProfileEntryProvider" name="%Device_Profile_Entry_Provider_Extension.name" schema="schema/deviceProfileEntryProvider.exsd"/>
+
+	<extension point="org.eclipse.ui.editors">
+		<editor
+			name="%HTML_Source_Page_Editor.name"
+			icon="$nl$/icons/full/obj16/sourceEditor.gif"
+			contributorClass="org.eclipse.wst.html.ui.internal.edit.ui.ActionContributorHTML"
+			class="org.eclipse.wst.sse.ui.StructuredTextEditor"
+			symbolicFontName="org.eclipse.wst.sse.ui.textfont"
+			id="org.eclipse.wst.html.core.htmlsource.source">
+			<contentTypeBinding
+				contentTypeId="org.eclipse.wst.html.core.htmlsource" />
+		</editor>
+	</extension>
+	<extension point="org.eclipse.wst.sse.ui.editorConfiguration">
+		<sourceViewerConfiguration
+			class="org.eclipse.wst.html.ui.StructuredTextViewerConfigurationHTML"
+			target="org.eclipse.wst.html.core.htmlsource" />
+		<contentOutlineConfiguration
+			class="org.eclipse.wst.html.ui.views.contentoutline.HTMLContentOutlineConfiguration"
+			target="org.eclipse.wst.html.core.htmlsource" />
+		<quickOutlineConfiguration
+			class="org.eclipse.wst.xml.ui.internal.quickoutline.XMLQuickOutlineConfiguration"
+			target="org.eclipse.wst.html.core.htmlsource"/>
+		<propertySheetConfiguration
+			class="org.eclipse.wst.xml.ui.views.properties.XMLPropertySheetConfiguration"
+			target="org.eclipse.wst.html.core.htmlsource" />
+  		<documentationTextHover
+        	class="org.eclipse.wst.html.ui.internal.taginfo.HTMLTagInfoHoverProcessor"
+        	target="org.eclipse.wst.html.HTML_DEFAULT">
+  		</documentationTextHover>
+		<provisionalConfiguration
+			type="sourceeditingtexttools"
+			class="org.eclipse.wst.xml.ui.internal.provisional.XMLSourceEditingTextTools"
+			target="org.eclipse.wst.html.core.htmlsource" />
+		<provisionalConfiguration
+			type="characterpairmatcher"
+			class="org.eclipse.wst.html.ui.internal.text.HTMLDocumentRegionEdgeMatcher"
+			target="org.eclipse.wst.html.core.htmlsource" />
+		<provisionalConfiguration
+			type="foldingstrategy"
+			class="org.eclipse.wst.xml.ui.internal.projection.XMLFoldingStrategy"
+			target="org.eclipse.wst.html.core.htmlsource" />
+		<provisionalConfiguration
+			type="org.eclipse.jface.text.quickassist.IQuickAssistProcessor"
+			class="org.eclipse.wst.xml.ui.internal.correction.XMLQuickAssistProcessor"
+			target="org.eclipse.wst.html.HTML_DEFAULT" />
+		<provisionalConfiguration
+			type="autoeditstrategy"
+			class="org.eclipse.wst.html.ui.internal.autoedit.StructuredAutoEditStrategyHTML"
+			target="org.eclipse.wst.html.HTML_DEFAULT, org.eclipse.wst.html.HTML_DECLARATION" />
+		<provisionalDefinition
+			type="preferencepages"
+			value="org.eclipse.wst.html.ui.preferences.html, org.eclipse.wst.html.ui.preferences.source, org.eclipse.wst.html.ui.preferences.templates, org.eclipse.wst.html.ui.preferences.styles,org.eclipse.wst.html.ui.preferences.validation, org.eclipse.wst.html.ui.preferences.contentassist"
+			target="org.eclipse.wst.html.core.htmlsource" />
+		<provisionalDefinition
+			type="spellingregions"
+			value="XML_COMMENT_TEXT, XML_CONTENT"
+			target="org.eclipse.wst.html.core.htmlsource" />
+		<provisionalDefinition
+			type="activecontexts"
+			value="org.eclipse.wst.html.core.htmlsource, org.eclipse.wst.html.occurrences, org.eclipse.core.runtime.xml, org.eclipse.wst.xml.navigation, org.eclipse.wst.xml.selection, org.eclipse.wst.sse.comments"
+        	target="org.eclipse.wst.html.core.htmlsource" />
+	</extension>
+	<extension
+		point="org.eclipse.core.filebuffers.annotationModelCreation">
+		<factory
+			contentTypeId="org.eclipse.wst.html.core.htmlsource"
+			class="org.eclipse.wst.sse.ui.internal.StructuredResourceMarkerAnnotationModelFactory" />
+	</extension>
+	<extension
+		point="org.eclipse.wst.sse.ui.adapterFactoryDescription">
+		<adapterFactoryDescription
+			class="org.eclipse.wst.html.ui.internal.registry.AdapterFactoryProviderForHTML">
+			<contentType id="org.eclipse.wst.html.core.htmlsource" />
+		</adapterFactoryDescription>
+	</extension>
+	<extension point="org.eclipse.ui.preferencePages">
+		<page
+			name="%WEB.name"
+			class="org.eclipse.wst.html.ui.internal.preferences.ui.EmptyFilePreferencePage"
+			id="org.eclipse.wst.html.ui.preferences.web">
+		</page>
+		<!-- HTML PREFERENCE PAGES-->
+		<page
+			name="%HTML_Files.name"
+			category="org.eclipse.wst.html.ui.preferences.web"
+			class="org.eclipse.wst.html.ui.internal.preferences.ui.HTMLFilesPreferencePage"
+			id="org.eclipse.wst.html.ui.preferences.html">
+			<keywordReference id="org.eclipse.wst.html.ui.files"/>
+		</page>
+		<page
+			name="%HTML_Source.name"
+			category="org.eclipse.wst.html.ui.preferences.html"
+			class="org.eclipse.wst.html.ui.internal.preferences.ui.HTMLSourcePreferencePage"
+			id="org.eclipse.wst.html.ui.preferences.source">
+			<keywordReference id="org.eclipse.wst.html.ui.source"/>
+		</page>
+  <page
+        category="org.eclipse.wst.html.ui.preferences.source"
+        class="org.eclipse.wst.html.ui.internal.preferences.ui.HTMLContentAssistPreferencePage"
+        id="org.eclipse.wst.html.ui.preferences.contentassist"
+        name="%HTML_Content_Assist.name">
+     <keywordReference
+           id="org.eclipse.wst.html.ui.contentassist">
+     </keywordReference>
+  </page>
+		<page
+			name="%HTML_Templates.name"
+			category="org.eclipse.wst.html.ui.preferences.source"
+			class="org.eclipse.wst.html.ui.internal.preferences.ui.HTMLTemplatePreferencePage"
+			id="org.eclipse.wst.html.ui.preferences.templates">
+			<keywordReference id="org.eclipse.wst.html.ui.templates"/>
+		</page>
+		<page
+			name="%HTML_Syntax_Coloring"
+			category="org.eclipse.wst.html.ui.preferences.source"
+			class="org.eclipse.wst.html.ui.internal.preferences.ui.HTMLSyntaxColoringPage"
+			id="org.eclipse.wst.html.ui.preferences.styles">
+			<keywordReference id="org.eclipse.wst.html.ui.styles"/>
+		</page>
+		<page
+			name="%HTML_Validation"
+			category="org.eclipse.wst.html.ui.preferences.html"
+			class="org.eclipse.wst.html.ui.internal.preferences.ui.HTMLValidationPreferencePage"
+			id="org.eclipse.wst.html.ui.preferences.validation">
+		</page>
+		<page
+			name="%HTML_Typing"
+			category="org.eclipse.wst.html.ui.preferences.source"
+			class="org.eclipse.wst.html.ui.internal.preferences.ui.HTMLTypingPreferencePage"
+			id="org.eclipse.wst.html.ui.preferences.typing">
+		</page>
+	</extension>
+	<!-- Web content settings -->
+	<extension point="org.eclipse.ui.propertyPages">
+		<!-- for dynamic web project -->
+		<page
+			name="%WebContentSettings.name"
+			class="org.eclipse.wst.html.ui.internal.contentproperties.ui.ProjectWebContentSettingsPropertyPage"
+			id="org.eclipse.wst.html.ui.dynamicprojectpropertypage">
+         	<enabledWhen>
+               	<and>
+					<adapt type="org.eclipse.core.resources.IProject">
+						<or> 
+							<test 
+								forcePluginActivation="true"
+								property="org.eclipse.wst.common.project.facet.core.projectFacet"
+								value="jst.web" />
+							<test 
+								forcePluginActivation="true"
+								property="org.eclipse.wst.common.project.facet.core.projectFacet"
+								value="wst.web" />
+						</or>
+					</adapt>
+				</and> 
+			</enabledWhen>
+         	<keywordReference id="org.eclipse.wst.html.ui.webcontent"/>
+		</page>
+		<page
+			name="%WebContentSettings.name"
+			class="org.eclipse.wst.html.ui.internal.contentproperties.ui.WebContentSettingsPropertyPage"
+			id="org.eclipse.wst.html.ui.internal.contentproperties.ui.WebContentSettingsPropertyPage">
+         	<enabledWhen>
+               	<and>
+					<adapt type="org.eclipse.core.resources.IFile">
+						<or> 
+							<test 
+								forcePluginActivation="true"
+								property="org.eclipse.core.resources.contentTypeId"
+								value="org.eclipse.wst.html.core.htmlsource" />
+							<test 
+								forcePluginActivation="true"
+								property="org.eclipse.core.resources.contentTypeId"
+								value="org.eclipse.jst.jsp.core.jspsource" />
+							<test 
+								forcePluginActivation="true"
+								property="org.eclipse.core.resources.contentTypeId"
+								value="org.eclipse.jst.jsp.core.jspfragmentsource" />
+							<test 
+								forcePluginActivation="true"
+								property="org.eclipse.core.resources.contentTypeId"
+								value="org.eclipse.jst.jsp.core.cssjspfragmentsource" />
+						</or>
+					</adapt>
+				</and> 
+			</enabledWhen>
+         	<keywordReference id="org.eclipse.wst.html.ui.webcontent"/>
+		</page>
+		<page
+			name="%HTML_Property_validation"
+			class="org.eclipse.wst.html.ui.internal.preferences.ui.HTMLValidationPreferencePage"
+			id="org.eclipse.wst.html.ui.propertyPage.project.validation"
+			category="ValidationPropertiesPage">
+			<enabledWhen>
+				<adapt type="org.eclipse.core.resources.IProject">
+					
+				</adapt>
+			</enabledWhen>
+		</page>
+	</extension>
+	
+	<!-- Keywords for preference and properties pages -->
+	<extension point="org.eclipse.ui.keywords">
+		<keyword
+			label="%preferenceKeywords.files"
+			id="org.eclipse.wst.html.ui.files"/>
+		<keyword
+			label="%preferenceKeywords.source"
+			id="org.eclipse.wst.html.ui.source"/>
+		<keyword
+			label="%preferenceKeywords.contentassist"
+			id="org.eclipse.wst.html.ui.contentassist"/>
+		<keyword
+			label="%preferenceKeywords.templates"
+			id="org.eclipse.wst.html.ui.templates"/>
+		<keyword
+			label="%preferenceKeywords.styles"
+			id="org.eclipse.wst.html.ui.styles"/>
+		<keyword
+			label="%preferenceKeywords.webcontent"
+			id="org.eclipse.wst.html.ui.webcontent"/>
+		<keyword
+			label="%preferenceKeywords.severities"
+			id="org.eclipse.wst.html.ui.severities"/>
+    </extension>
+	
+	<!-- Editor actionsets -->
+	<extension point="org.eclipse.ui.actionSetPartAssociations">
+		<actionSetPartAssociation
+			targetID="org.eclipse.ui.edit.text.actionSet.annotationNavigation">
+			<part id="org.eclipse.wst.html.core.htmlsource.source">
+			</part>
+		</actionSetPartAssociation>
+		<actionSetPartAssociation
+			targetID="org.eclipse.ui.NavigateActionSet">
+			<part id="org.eclipse.wst.html.core.htmlsource.source">
+			</part>
+		</actionSetPartAssociation>
+	</extension>
+
+	<!-- Templates -->
+	<extension point="org.eclipse.ui.editors.templates">
+		<contextType
+			name="%All_HTML_context_type_Extension_Element.name"
+			class="org.eclipse.wst.html.ui.internal.templates.TemplateContextTypeHTML"
+			id="html_all">
+		</contextType>
+		<contextType
+			name="%HTML_New_context_type_Extension_Element.name"
+			class="org.eclipse.wst.html.ui.internal.templates.TemplateContextTypeHTML"
+			id="html_new">
+		</contextType>
+		<contextType
+			name="%HTML_Tag_context_type_Extension_Element.name"
+			class="org.eclipse.wst.html.ui.internal.templates.TemplateContextTypeHTML"
+			id="html_tag">
+		</contextType>
+		<contextType
+			name="%HTML_Attribute_context_type_Extension_Element.name"
+			class="org.eclipse.wst.html.ui.internal.templates.TemplateContextTypeHTML"
+			id="html_attribute">
+		</contextType>
+		<contextType
+			name="%HTML_Attribute_value_context_type_Extension_Element.name"
+			class="org.eclipse.wst.html.ui.internal.templates.TemplateContextTypeHTML"
+			id="html_attribute_value">
+		</contextType>
+		<include
+			file="templates/htmldefault-templates.xml"
+			translations="$nl$/templates/htmldefault-templates.properties">
+		</include>
+	</extension>
+	
+	<!-- Define the HTML Contexts -->
+	<extension point="org.eclipse.ui.contexts">
+		<context
+			name="%scope.structured.text.editor.html.name"
+			parentId="org.eclipse.wst.sse.ui.structuredTextEditorScope"
+			description="%scope.structured.text.editor.html.description"
+			id="org.eclipse.wst.html.core.htmlsource">
+		</context>
+		<context
+			name="%scope.structured.text.editor.html.occurrences.name"
+			parentId="org.eclipse.wst.sse.ui.structuredTextEditorScope"
+			description="%scope.structured.text.editor.html.occurrences.description"
+			id="org.eclipse.wst.html.occurrences">
+		</context>
+	</extension>
+	
+	<!-- initialize html ui preferences -->
+	<extension point="org.eclipse.core.runtime.preferences">
+		<initializer
+			class="org.eclipse.wst.html.ui.internal.preferences.HTMLUIPreferenceInitializer" />
+	</extension>
+
+	<!--======================================================================================-->
+	<!-- Document provider for ExternalFileEditorInput                                        -->
+	<!--======================================================================================-->
+	<extension point="org.eclipse.ui.editors.documentProviders">
+		<provider
+			inputTypes="org.eclipse.wst.html.ui.internal.hyperlink.ExternalFileEditorInput"
+			class="org.eclipse.ui.editors.text.TextFileDocumentProvider"
+			id="org.eclipse.wst.html.ui.internal.ExternalFileDocumentProvider">
+		</provider>
+	</extension>
+
+	<!--======================================================================================-->
+	<!-- Workbench validation                                       						  -->
+	<!--======================================================================================-->
+   <extension id="HTMLValidator" name="%HTML_Syntax_Validator.name" point="org.eclipse.wst.validation.validatorV2">
+      <validator
+            build="true"
+            class="org.eclipse.wst.html.internal.validation.HTMLValidator"
+            manual="true"
+            sourceid="org.eclipse.wst.html.ui.internal.validation.htmlsyntaxvalidator"
+            version="1"
+            markerId="org.eclipse.wst.html.core.validationMarker">
+         <include>
+            <rules>
+               <contentType id="org.eclipse.wst.html.core.htmlsource"></contentType>
+               <fileext caseSensitive="false" ext="html"/>
+               <fileext caseSensitive="false" ext="xhtml"/>
+               <fileext caseSensitive="false" ext="htm"/>
+               <fileext caseSensitive="false" ext="htpl"/>
+               <fileext caseSensitive="false" ext="wml"/>
+            </rules>
+         </include>
+         <group id="org.eclipse.wst.sse.core.structuredModelGroup"/>
+      </validator>
+   </extension>
+
+	<!--======================================================================================-->
+	<!-- As you type validation                                      						  -->
+	<!--======================================================================================-->
+
+	<extension point="org.eclipse.wst.sse.ui.sourcevalidation">
+		<validator
+			scope="total"
+			class="org.eclipse.wst.html.internal.validation.HTMLValidator"
+			id="org.eclipse.wst.html.ui.internal.validation.htmlsyntaxvalidator">
+			<contentTypeIdentifier
+				id="org.eclipse.wst.html.core.htmlsource">
+				<partitionType id="org.eclipse.wst.html.HTML_DEFAULT"/>
+				<partitionType id="org.eclipse.wst.html.HTML_DECLARATION"/>
+				<partitionType id="org.eclipse.wst.html.HTML_COMMENT"/>
+				<partitionType id="org.eclipse.wst.xml.XML_DEFAULT"/>
+				<partitionType id="org.eclipse.wst.sse.ST_DEFAULT"/>
+			</contentTypeIdentifier>
+		</validator>
+	</extension>
+
+	<!-- New HTML wizard -->
+	<extension point="org.eclipse.ui.newWizards">
+		<wizard
+			id="org.eclipse.wst.html.ui.internal.wizard.NewHTMLWizard"
+			name="%_UI_WIZARD_NAME"
+			class="org.eclipse.wst.html.ui.internal.wizard.NewHTMLWizard"
+			category="org.eclipse.wst.web.ui"
+			icon="$nl$/icons/full/etool16/newhtml_wiz.gif">
+			<description>%_UI_WIZARD_CREATE_NEW_FILE</description>
+			<selection class="org.eclipse.core.resources.IResource" />
+		</wizard>
+	</extension>
+
+	<!-- Add new HTML wizard to Common Navigator -->
+	<extension
+		id="org.eclipse.wst.html.commonWizard.newHTML"
+		point="org.eclipse.ui.navigator.navigatorContent">
+		<commonWizard
+        menuGroupId="org.eclipse.wst.web.ui"
+        type="new"
+        wizardId="org.eclipse.wst.html.ui.internal.wizard.NewHTMLWizard">
+			<enablement>
+				<or>
+					<adapt type="org.eclipse.core.resources.IResource">
+						<or>
+							<test
+								property="org.eclipse.wst.common.project.facet.core.projectFacet"
+								value="wst.web"/>
+							<test
+								property="org.eclipse.wst.common.project.facet.core.projectFacet"
+								value="jst.web"/>
+						</or>
+					</adapt>
+				</or>
+			</enablement>
+		</commonWizard>
+	</extension>
+
+	<extension point="org.eclipse.ui.popupMenus">
+		<viewerContribution
+			targetID="org.eclipse.wst.html.core.htmlsource.source.RulerContext"
+			id="org.eclipse.ui.texteditor.ruler.context.actions">
+			<action
+				label="%AddTask.label"
+				helpContextId="org.eclipse.ui.AddTask_action_context"
+				class="org.eclipse.ui.texteditor.TaskRulerAction"
+				tooltip="%AddTask.tooltip"
+				menubarPath="additions"
+				id="org.eclipse.ui.texteditor.TaskRulerAction">
+			</action>
+			<action
+				label="%AddBookmark.label"
+				helpContextId="org.eclipse.ui.bookmark_action_context"
+				class="org.eclipse.ui.texteditor.BookmarkRulerAction"
+				tooltip="%AddBookmark.tooltip"
+				menubarPath="additions"
+				id="org.eclipse.ui.texteditor.BookmarkRulerAction">
+			</action>
+		</viewerContribution>
+	</extension>
+	
+	<extension point="org.eclipse.ui.editorActions">
+	<!--	<editorContribution
+			id="org.eclipse.wst.html.core.htmlsource.source.editorActions"
+			targetID="org.eclipse.wst.html.core.htmlsource.source">
+			<action
+				id="CleanupDocument"
+				label="%CleanupDocument_label"
+				definitionId="org.eclipse.wst.sse.ui.cleanup.document"
+				tooltip="%CleanupDocument_tooltip"
+				class="org.eclipse.wst.html.ui.internal.edit.ui.CleanupActionHTMLDelegate"
+				actionID="CleanupDocument">
+			</action>
+			<action
+				id="ToggleComment"
+				label="%ToggleComment_label"
+				definitionId="org.eclipse.wst.sse.ui.toggle.comment"
+				tooltip="%ToggleComment_tooltip"
+				class="org.eclipse.wst.xml.ui.internal.actions.ToggleCommentActionXMLDelegate"
+				actionID="ToggleComment">
+			</action>
+			<action
+				id="AddBlockComment"
+				label="%AddBlockComment_label"
+				definitionId="org.eclipse.wst.sse.ui.add.block.comment"
+				tooltip="%AddBlockComment_tooltip"
+				class="org.eclipse.wst.xml.ui.internal.actions.AddBlockCommentActionXMLDelegate"
+				actionID="AddBlockComment">
+			</action>
+			<action
+				id="RemoveBlockComment"
+				label="%RemoveBlockComment_label"
+				definitionId="org.eclipse.wst.sse.ui.remove.block.comment"
+				tooltip="%RemoveBlockComment_tooltip"
+				class="org.eclipse.wst.xml.ui.internal.actions.RemoveBlockCommentActionXMLDelegate"
+				actionID="RemoveBlockComment">
+			</action>
+			<action
+				id="FindOccurrences"
+				label="%FindOccurrences_label"
+				definitionId="org.eclipse.wst.sse.ui.search.find.occurrences"
+				class="org.eclipse.wst.html.ui.internal.search.HTMLFindOccurrencesActionDelegate"
+				actionID="FindOccurrences">
+			</action>
+			<action
+				id="StructureSelectEnclosing"
+				label="%StructureSelectEnclosing_label"
+				definitionId="org.eclipse.wst.sse.ui.structure.select.enclosing"
+				tooltip="%StructureSelectEnclosing_tooltip"
+				class="org.eclipse.wst.xml.ui.internal.selection.StructuredSelectEnclosingXMLActionDelegate"
+				actionID="StructureSelectEnclosing">
+			</action>
+			<action
+				id="StructureSelectNext"
+				label="%StructureSelectNext_label"
+				definitionId="org.eclipse.wst.sse.ui.structure.select.next"
+				tooltip="%StructureSelectNext_tooltip"
+				class="org.eclipse.wst.xml.ui.internal.selection.StructuredSelectNextXMLActionDelegate"
+				actionID="StructureSelectNext">
+			</action>
+			<action
+				id="StructureSelectPrevious"
+				label="%StructureSelectPrevious_label"
+				definitionId="org.eclipse.wst.sse.ui.structure.select.previous"
+				tooltip="%StructureSelectPrevious_tooltip"
+				class="org.eclipse.wst.xml.ui.internal.selection.StructuredSelectPreviousXMLActionDelegate"
+				actionID="StructureSelectPrevious">
+			</action>
+			<action
+				id="StructureSelectHistory"
+				label="%StructureSelectHistory_label"
+				definitionId="org.eclipse.wst.sse.ui.structure.select.last"
+				tooltip="%StructureSelectHistory_tooltip"
+				class="org.eclipse.wst.sse.ui.internal.selection.StructuredSelectHistoryActionDelegate"
+				actionID="StructureSelectHistory">
+			</action>
+		</editorContribution>-->
+        <editorContribution
+            targetID="org.eclipse.wst.html.core.htmlsource.source"
+            id="org.eclipse.wst.html.core.htmlsource.ruler.actions">
+         <action
+               label="%AddBookmark.label"
+               helpContextId="org.eclipse.ui.bookmark_action_context"
+               class="org.eclipse.ui.texteditor.BookmarkRulerAction"
+               actionID="RulerDoubleClick"
+               id="org.eclipse.ui.texteditor.BookmarkRulerAction"/>
+         <action
+               label="%SelectRuler.label"
+               class="org.eclipse.ui.texteditor.SelectRulerAction"
+               actionID="RulerClick"
+               id="org.eclipse.ui.texteditor.SelectRulerAction"/>
+        </editorContribution>
+	</extension>
+	
+	<extension
+       point="org.eclipse.ui.handlers">
+       <handler
+             class="org.eclipse.wst.html.ui.internal.edit.ui.CleanupDocumentHandler"
+             commandId="org.eclipse.wst.sse.ui.cleanup.document">
+             <activeWhen>
+             	<reference
+                    definitionId="org.eclipse.wst.html.ui.htmlSourceContributions.definition">
+             	</reference>
+             </activeWhen>
+             <enabledWhen>
+             	<reference
+                    definitionId="org.eclipse.wst.html.ui.htmlSourceContributions.definition">
+             	</reference>
+             </enabledWhen>
+       </handler>
+       <handler
+             class="org.eclipse.wst.html.ui.internal.handlers.HTMLFindOccurrencesHandler"
+             commandId="org.eclipse.wst.sse.ui.search.find.occurrences">
+             <activeWhen>
+             	<reference
+                    definitionId="org.eclipse.wst.html.ui.occurrences">
+             	</reference>
+             </activeWhen>
+             <enabledWhen>
+             	<reference
+                    definitionId="org.eclipse.wst.html.ui.occurrences">
+             	</reference>
+             </enabledWhen>
+       </handler>
+       
+	</extension>
+	
+	<extension
+		point="org.eclipse.ui.workbench.texteditor.hyperlinkDetectorTargets">
+		<target
+			id="org.eclipse.wst.html.core.htmlsource"
+			name="%HTML_Editors_target_name"/>
+		<target
+			id="org.eclipse.wst.html.SCRIPT"
+			name="%hyperlink.target.script.name"/>
+		<target
+			id="org.eclipse.wst.html.SCRIPT.EVENTHANDLER"
+			name="%hyperlink.target.eventhandler.name"/>
+	</extension>
+	
+	<extension
+		point="org.eclipse.ui.workbench.texteditor.hyperlinkDetectors">
+		<hyperlinkDetector
+			class="org.eclipse.wst.html.ui.internal.hyperlink.AnchorHyperlinkDetector"
+			id="org.eclipse.wst.html.ui.internal.hyperlink.AnchorHyperlinkDetector"
+			name="%hyperlinkDetector.anchor.name"
+			targetId="org.eclipse.core.runtime.xml">
+		</hyperlinkDetector>
+		
+   </extension>
+
+	<extension point="org.eclipse.core.expressions.definitions">
+		<definition id="org.eclipse.wst.html.ui.htmlSourceContributions.definition">
+            <with variable="activeContexts">
+	           <iterate operator="or">
+	              <equals value="org.eclipse.wst.html.core.htmlsource"/>
+	           </iterate>
+            </with>
+		</definition>
+	</extension>
+	
+	<extension point="org.eclipse.core.expressions.definitions">
+		<definition id="org.eclipse.wst.html.ui.occurrences">
+            <with variable="activeContexts">
+	           <iterate operator="or">
+	              <equals value="org.eclipse.wst.html.occurrences"/>
+	           </iterate>
+            </with>
+		</definition>
+	</extension>
+	
+	<!-- Define theme - Many of the color overrides and definitions come from 
+	     the XML plugin -->
+	<extension
+		point="org.eclipse.ui.themes">
+		<theme
+			id="org.eclipse.ui.ide.systemDefault">
+			<colorOverride
+				id="SCRIPT_AREA_BORDER"
+				value="COLOR_LIST_FOREGROUND">
+			</colorOverride>
+		</theme>
+		<colorDefinition
+			id="SCRIPT_AREA_BORDER"
+			isEditable="false"
+			label="%Colors.scriptAreaBorder"
+			value="191, 95, 63">
+		</colorDefinition>
+	</extension>
+	
+	<!-- Enable the FormatHandler for HTML Content Type -->
+	<extension point="org.eclipse.ui.handlers">
+		<handler 
+			class="org.eclipse.wst.sse.ui.internal.handlers.FormatHandler"
+			commandId="org.eclipse.wst.sse.ui.format">
+			<activeWhen>
+				<reference definitionId="org.eclipse.wst.html.ui.htmlContentType.definition"></reference>
+			</activeWhen>
+			<enabledWhen>
+				<reference definitionId="org.eclipse.wst.html.ui.htmlContentType.definition"></reference>
+			</enabledWhen>
+		</handler>
+	</extension>
+
+	<extension
+       point="org.eclipse.wst.sse.ui.commentingStrategy">
+    <blockCommentingStrategy
+          prefix="&lt;!--"
+          suffix="--&gt;">
+       <contentType
+             id="org.eclipse.wst.html.core.htmlsource"
+             associatedCommentPartitionTypeID="org.eclipse.wst.html.HTML_COMMENT">
+          <requiredPartitionTypes>
+             <partitionType
+                   id="org.eclipse.wst.html.HTML_DEFAULT">
+             </partitionType>
+             <partitionType
+                   id="org.eclipse.wst.html.HTML_DECLARATION">
+             </partitionType>
+             <partitionType
+                   id="org.eclipse.wst.html.SCRIPT.EVENTHANDLER">
+             </partitionType>
+             <partitionType
+                   id="org.eclipse.wst.xml.XML_PI">
+             </partitionType>
+          </requiredPartitionTypes>
+          <allowablePartitionTypes
+                anyPartitionType="false">
+             <partitionType
+                   id="org.eclipse.wst.css.STYLE">
+             </partitionType>
+             <partitionType
+                   id="org.eclipse.wst.html.SCRIPT">
+             </partitionType>
+          </allowablePartitionTypes>
+       </contentType>
+    </blockCommentingStrategy>
+ </extension>
+	<!-- Set up a definition for HTML Content Types -->
+	<extension point="org.eclipse.core.expressions.definitions">
+		<definition id="org.eclipse.wst.html.ui.htmlContentType.definition">
+			<iterate ifEmpty="false">
+				<adapt type="org.eclipse.core.resources.IFile">
+					<!-- Force property tester to load, should not cause entire plug-in to start -->
+					<test property="org.eclipse.wst.sse.core.resources.contentTypeId"
+						value="org.eclipse.wst.html.core.htmlsource" forcePluginActivation="true"/>
+				</adapt>
+			</iterate>
+		</definition>
+	</extension>
+	<extension point="org.eclipse.wst.sse.ui.characterPairing">
+		<inserter class="org.eclipse.wst.html.ui.internal.text.CharacterPairInserter" id="org.eclipse.wst.html.ui.inserter">
+			<contentTypeIdentifier
+				id="org.eclipse.wst.html.core.htmlsource"
+				partitions="org.eclipse.wst.html.HTML_DEFAULT">
+			</contentTypeIdentifier>
+		</inserter>
+	</extension>
+ <extension
+       point="org.eclipse.wst.sse.ui.completionProposal">
+    <proposalCategory
+          icon="icons/full/obj16/tag-generic.gif"
+          id="org.eclipse.wst.html.ui.proposalCategory.htmlTags"
+          name="%proposalCategory.htmlTags">
+    </proposalCategory>
+    <proposalCategory
+          icon="icons/full/obj16/tag-template.gif"
+          id="org.eclipse.wst.html.ui.proposalCategory.htmlTemplates"
+          name="%proposalCategory.htmlTemplates">
+    </proposalCategory>
+    <proposalComputer
+          activate="false"
+          categoryId="org.eclipse.wst.html.ui.proposalCategory.htmlTags"
+          class="org.eclipse.wst.html.ui.internal.contentassist.HTMLTagsCompletionProposalComputer"
+          id="org.eclipse.wst.html.ui.proposalComputer.htmlTags">
+       <contentType
+             id="org.eclipse.wst.html.core.htmlsource">
+          <partitionType
+                id="org.eclipse.wst.html.HTML_DEFAULT">
+          </partitionType>
+       </contentType>
+    </proposalComputer>
+    <proposalComputer
+          activate="false"
+          categoryId="org.eclipse.wst.html.ui.proposalCategory.htmlTemplates"
+          class="org.eclipse.wst.html.ui.internal.contentassist.HTMLTemplatesCompletionProposalComputer"
+          id="org.eclipse.wst.html.ui.proposalComputer.htmlTemplates">
+       <contentType
+             id="org.eclipse.wst.html.core.htmlsource">
+          <partitionType
+                id="org.eclipse.wst.html.HTML_DEFAULT">
+          </partitionType>
+       </contentType>
+    </proposalComputer>
+    <proposalComputerExtendedActivation
+          id="org.eclipse.wst.css.ui.proposalComputer.css">
+       <contentType
+             id="org.eclipse.wst.html.core.htmlsource">
+          <partitionType
+                id="org.eclipse.wst.css.STYLE">
+          </partitionType>
+       </contentType>
+    </proposalComputerExtendedActivation>
+    <proposalComputerExtendedActivation
+          id="org.eclipse.wst.css.ui.proposalComputer.cssTemplates">
+       <contentType
+             id="org.eclipse.wst.html.core.htmlsource">
+          <partitionType
+                id="org.eclipse.wst.css.STYLE">
+          </partitionType>
+       </contentType>
+    </proposalComputerExtendedActivation>
+ </extension>
+ <extension
+       point="org.eclipse.wst.sse.ui.completionProposalCategoriesConfiguration">
+    <categoriesConfiguration
+          class="org.eclipse.wst.html.ui.internal.preferences.HTMLCompletionProposalCategoriesConfiguration"
+          contentTypeID="org.eclipse.wst.html.core.htmlsource">
+    </categoriesConfiguration>
+ </extension>
+	
+</plugin>
diff --git a/bundles/org.eclipse.wst.html.ui/schema/deviceProfileEntryProvider.exsd b/bundles/org.eclipse.wst.html.ui/schema/deviceProfileEntryProvider.exsd
new file mode 100644
index 0000000..742f82f
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/schema/deviceProfileEntryProvider.exsd
@@ -0,0 +1,109 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.wst.html.ui">
+<annotation>
+      <appInfo>
+         <meta.schema plugin="org.eclipse.wst.html.ui" id="deviceProfileEntryProvider" name="Device Profile Entry Provider Extension"/>
+      </appInfo>
+      <documentation>
+         
+      </documentation>
+   </annotation>
+
+   <element name="extension">
+      <complexType>
+         <sequence>
+            <element ref="deviceProfileEntryProvider"/>
+         </sequence>
+         <attribute name="point" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="id" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="name" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+               <appInfo>
+                  <meta.attribute translatable="true"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <element name="deviceProfileEntryProvider">
+      <complexType>
+         <attribute name="class" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+               <appInfo>
+                  <meta.attribute kind="java"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="since"/>
+      </appInfo>
+      <documentation>
+         &lt;b&gt;This extension point is deprecated and should not be used by any other plugins.&lt;/b&gt;
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="examples"/>
+      </appInfo>
+      <documentation>
+         
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="apiInfo"/>
+      </appInfo>
+      <documentation>
+         
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="implementation"/>
+      </appInfo>
+      <documentation>
+         
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="copyright"/>
+      </appInfo>
+      <documentation>
+         Copyright (c) 2000, 2005 IBM Corporation and others.&lt;br&gt;
+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 &lt;a
+href=&quot;http://www.eclipse.org/legal/epl-v10.html&quot;&gt;http://www.eclipse.org/legal/epl-v10.html&lt;/a&gt;
+      </documentation>
+   </annotation>
+
+</schema>
diff --git a/bundles/org.eclipse.wst.html.ui/src-html-validation/org/eclipse/wst/html/internal/validation/HTMLValidationReporter.java b/bundles/org.eclipse.wst.html.ui/src-html-validation/org/eclipse/wst/html/internal/validation/HTMLValidationReporter.java
new file mode 100644
index 0000000..4d1068c
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src-html-validation/org/eclipse/wst/html/internal/validation/HTMLValidationReporter.java
@@ -0,0 +1,150 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.internal.validation;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.wst.html.core.internal.validate.MessageFactory;
+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.validate.ErrorInfo;
+import org.eclipse.wst.sse.core.internal.validate.ValidationMessage;
+import org.eclipse.wst.sse.core.internal.validate.ValidationReporter;
+import org.eclipse.wst.validation.internal.provisional.core.IMessage;
+import org.eclipse.wst.validation.internal.provisional.core.IReporter;
+import org.eclipse.wst.validation.internal.provisional.core.IValidator;
+
+public class HTMLValidationReporter implements ValidationReporter {
+
+	private IValidator owner = null;
+	private IReporter reporter = null;
+	private IFile file = null;
+	private IStructuredModel model = null;
+	private HTMLValidationResult result = null;
+	private MessageFactory fFactory = null;
+	
+	/**
+	 */
+	public HTMLValidationReporter(IValidator owner, IReporter reporter, IFile file, IStructuredModel model) {
+		super();
+		this.owner = owner;
+		this.reporter = reporter;
+		this.file = file;
+		this.model = model;
+		fFactory = new MessageFactory(file != null ? file.getProject() : null);
+	}
+
+	/**
+	 */
+	public void clear() {
+		if (this.file == null)
+			return;
+
+		this.result = null;
+
+		if (this.reporter != null) {
+			this.reporter.removeAllMessages(this.owner, this.file);
+		}
+		else {
+			// remove by myself?
+			String id = HTMLValidator.class.getName();
+			try {
+				// TaskListHelper API changed
+				// TaskListHelper.getTaskList().removeAllTasks(id, this.file,
+				// null);
+				TaskListHelper.getTaskList().removeAllTasks(this.file, id, null);
+			}
+			catch (CoreException ex) {
+			}
+		}
+	}
+
+
+	/**
+	 */
+	public HTMLValidationResult getResult() {
+		if (this.result == null)
+			this.result = new HTMLValidationResult();
+		return this.result;
+	}
+
+	/**
+	 */
+	public void report(ValidationMessage message) {
+		if (message == null || message.getSeverity() == ValidationMessage.IGNORE)
+			return;
+		IMessage mes = translateMessage(message);
+
+		if (this.reporter != null) {
+			this.reporter.addMessage(this.owner, mes);
+		}
+		else {
+			if (this.file == null)
+				return;
+
+			// add by myself?
+			String id = HTMLValidator.class.getName();
+			String location = Integer.toString(mes.getLineNumber());
+			String name = ""; //$NON-NLS-1$
+			IPath filePath = this.file.getFullPath();
+			if (filePath != null) {
+				name = filePath.toString();
+			}
+			try {
+				TaskListHelper.getTaskList().addTask(id, this.file, location, mes.getId(), mes.getText(), mes.getSeverity(), name, mes.getGroupName(), mes.getOffset(), mes.getLength());
+			}
+			catch (CoreException ex) {
+			}
+		}
+	}
+
+	/**
+	 * Translate ValidationMessage to IMessage and generate result log
+	 */
+	private IMessage translateMessage(ValidationMessage message) {
+		int severity = IMessage.LOW_SEVERITY;
+		HTMLValidationResult result = getResult();
+		switch (message.getSeverity()) {
+			case ValidationMessage.ERROR :
+				severity = IMessage.HIGH_SEVERITY;
+				result.addError();
+				break;
+			case ValidationMessage.WARNING :
+				severity = IMessage.NORMAL_SEVERITY;
+				result.addWarning();
+				break;
+			case ValidationMessage.INFORMATION :
+				result.addInformation();
+				break;
+			default :
+//				result.addInformation();
+				break;
+		}
+
+		IMessage mes = new LocalizedMessage(severity, message.getMessage(), this.file);
+		mes.setOffset(message.getOffset());
+		mes.setLength(message.getLength());
+		if (this.model != null) {
+			IStructuredDocument flatModel = this.model.getStructuredDocument();
+			if (flatModel != null) {
+				int line = flatModel.getLineOfOffset(message.getOffset());
+				mes.setLineNo(line + 1);
+			}
+		}
+
+		return mes;
+	}
+
+	public void report(ErrorInfo info) {
+		report(fFactory.createMessage(info));
+	}
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.html.ui/src-html-validation/org/eclipse/wst/html/internal/validation/HTMLValidationResult.java b/bundles/org.eclipse.wst.html.ui/src-html-validation/org/eclipse/wst/html/internal/validation/HTMLValidationResult.java
new file mode 100644
index 0000000..26c5f08
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src-html-validation/org/eclipse/wst/html/internal/validation/HTMLValidationResult.java
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.internal.validation;
+
+public class HTMLValidationResult {
+	private int errors = 0;
+	private int warnings = 0;
+	private int informations = 0;
+
+	/**
+	 */
+	public HTMLValidationResult() {
+	}
+
+	/**
+	 */
+	public void addError() {
+		this.errors++;
+	}
+
+	/**
+	 */
+	public void addInformation() {
+		this.informations++;
+	}
+
+	/**
+	 */
+	public void addWarning() {
+		this.warnings++;
+	}
+
+	/**
+	 */
+	public int getErrors() {
+		return this.errors;
+	}
+
+	/**
+	 */
+	public int getInformations() {
+		return this.informations;
+	}
+
+	/**
+	 */
+	public int getWarnings() {
+		return this.warnings;
+	}
+
+	/**
+	 */
+	public boolean isValid() {
+		return (this.errors == 0 && this.warnings == 0 && this.informations == 0);
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src-html-validation/org/eclipse/wst/html/internal/validation/HTMLValidationWorkbenchHelper.java b/bundles/org.eclipse.wst.html.ui/src-html-validation/org/eclipse/wst/html/internal/validation/HTMLValidationWorkbenchHelper.java
new file mode 100644
index 0000000..90bfde5
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src-html-validation/org/eclipse/wst/html/internal/validation/HTMLValidationWorkbenchHelper.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.internal.validation;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.wst.validation.internal.operations.WorkbenchContext;
+
+public class HTMLValidationWorkbenchHelper extends WorkbenchContext {
+	/**
+	 */
+	public HTMLValidationWorkbenchHelper() {
+		super();
+	}
+
+	/**
+	 * When an IValidator associates a target object with an IMessage, the
+	 * WorkbenchReporter eventually resolves that target object with an
+	 * IResource. Sometimes more than one target object resolves to the same
+	 * IResource (usually the IProject, which is the default IResource when an
+	 * IFile cannot be found). This method is called, by the
+	 * WorkbenchReporter, so that the WorkbenchReporter can distinguish
+	 * between the IMessages which are on the same IResource, but refer to
+	 * different target objects. This is needed for the
+	 * removeAllMessages(IValidator, Object) method, so that when one target
+	 * object removes all of its messages, that it doesn't remove another
+	 * target object's messages.
+	 * 
+	 * This method may return null only if object is null. Otherwise, an id
+	 * which can uniquely identify a particular object must be returned. The
+	 * id needs to be unique only within one particular IValidator.
+	 */
+	public String getTargetObjectName(Object object) {
+		if (object == null)
+			return null;
+		if (object instanceof IFile)
+			return getPortableName((IFile) object);
+		return object.toString();
+	}
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.html.ui/src-html-validation/org/eclipse/wst/html/internal/validation/HTMLValidator.java b/bundles/org.eclipse.wst.html.ui/src-html-validation/org/eclipse/wst/html/internal/validation/HTMLValidator.java
new file mode 100644
index 0000000..2efc77b
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src-html-validation/org/eclipse/wst/html/internal/validation/HTMLValidator.java
@@ -0,0 +1,563 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.internal.validation;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.filebuffers.ITextFileBuffer;
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExecutableExtension;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.content.IContentDescription;
+import org.eclipse.core.runtime.content.IContentType;
+import org.eclipse.core.runtime.content.IContentTypeManager;
+import org.eclipse.core.runtime.jobs.ISchedulingRule;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.wst.html.core.internal.document.HTMLDocumentTypeConstants;
+import org.eclipse.wst.html.core.internal.validate.HTMLValidationAdapterFactory;
+import org.eclipse.wst.html.ui.internal.Logger;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.FileBufferModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.IModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapterFactory;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
+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.util.URIResolver;
+import org.eclipse.wst.sse.core.internal.validate.ValidationAdapter;
+import org.eclipse.wst.sse.core.utils.StringUtils;
+import org.eclipse.wst.sse.ui.internal.reconcile.validator.ISourceValidator;
+import org.eclipse.wst.validation.AbstractValidator;
+import org.eclipse.wst.validation.ValidationResult;
+import org.eclipse.wst.validation.ValidationState;
+import org.eclipse.wst.validation.internal.core.Message;
+import org.eclipse.wst.validation.internal.core.ValidationException;
+import org.eclipse.wst.validation.internal.operations.IWorkbenchContext;
+import org.eclipse.wst.validation.internal.operations.WorkbenchReporter;
+import org.eclipse.wst.validation.internal.provisional.core.IMessage;
+import org.eclipse.wst.validation.internal.provisional.core.IReporter;
+import org.eclipse.wst.validation.internal.provisional.core.IValidationContext;
+import org.eclipse.wst.validation.internal.provisional.core.IValidatorJob;
+import org.eclipse.wst.xml.core.internal.document.DocumentTypeAdapter;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
+import org.w3c.dom.Text;
+
+public class HTMLValidator extends AbstractValidator implements IValidatorJob, ISourceValidator, IExecutableExtension {
+	private static final String ORG_ECLIPSE_WST_HTML_CORE_HTMLSOURCE = "org.eclipse.wst.html.core.htmlsource"; //$NON-NLS-1$
+
+	static boolean shouldValidate(IFile file) {
+		IResource resource = file;
+		do {
+			if (resource.isDerived() || resource.isTeamPrivateMember() || !resource.isAccessible() || (resource.getName().charAt(0) == '.' && resource.getType() == IResource.FOLDER)) {
+				return false;
+			}
+			resource = resource.getParent();
+		}
+		while ((resource.getType() & IResource.PROJECT) == 0);
+		return true;
+	}
+
+	private IDocument fDocument;
+	private IContentTypeManager fContentTypeManager;
+	private IContentType[] fOtherSupportedContentTypes = null;
+	private String[] fAdditionalContentTypesIDs = null;
+	private IContentType fHTMLContentType;
+
+	public HTMLValidator() {
+		super();
+		fContentTypeManager = Platform.getContentTypeManager();
+		fHTMLContentType = fContentTypeManager.getContentType(ORG_ECLIPSE_WST_HTML_CORE_HTMLSOURCE);
+	}
+
+	/**
+	 */
+	public void cleanup(IReporter reporter) {
+		// nothing to do
+	}
+
+	/**
+	 * Gets list of content types this validator is interested in
+	 * 
+	 * @return All HTML-related content types
+	 */
+	private IContentType[] getOtherSupportedContentTypes() {
+		if (fOtherSupportedContentTypes == null) {
+			List contentTypes = new ArrayList(3);
+			if (fAdditionalContentTypesIDs != null) {
+				for (int i = 0; i < fAdditionalContentTypesIDs.length; i++) {
+					IContentType type = Platform.getContentTypeManager().getContentType(fAdditionalContentTypesIDs[i]);
+					if (type != null) {
+						contentTypes.add(type);
+					}
+				}
+			}
+			fOtherSupportedContentTypes = (IContentType[]) contentTypes.toArray(new IContentType[contentTypes.size()]);
+		}
+		return fOtherSupportedContentTypes;
+	}
+
+
+	/**
+	 */
+	protected IDOMModel getModel(IProject project, IFile file) {
+		if (project == null || file == null)
+			return null;
+		if (!file.exists())
+			return null;
+		if (!canHandle(file))
+			return null;
+
+		IModelManager manager = StructuredModelManager.getModelManager();
+		if (manager == null)
+			return null;
+
+		IStructuredModel model = null;
+		try {
+			file.refreshLocal(IResource.DEPTH_ZERO, new NullProgressMonitor());
+		}
+		catch (CoreException e) {
+			Logger.logException(e);
+		}
+		try {
+			try {
+				model = manager.getModelForRead(file);
+			}
+			catch (UnsupportedEncodingException ex) {
+				// retry ignoring META charset for invalid META charset
+				// specification
+				// recreate input stream, because it is already partially read
+				model = manager.getModelForRead(file, new String(), null);
+			}
+		}
+		catch (UnsupportedEncodingException ex) {
+		}
+		catch (IOException ex) {
+		}
+		catch (CoreException e) {
+			Logger.logException(e);
+		}
+
+		if (model == null)
+			return null;
+		if (!(model instanceof IDOMModel)) {
+			releaseModel(model);
+			return null;
+		}
+		return (IDOMModel) model;
+	}
+
+	/**
+	 */
+	protected HTMLValidationReporter getReporter(IReporter reporter, IFile file, IDOMModel model) {
+		return new HTMLValidationReporter(this, reporter, file, model);
+	}
+
+	/**
+	 * Check file extension to validate
+	 */
+	private boolean canHandle(IFile file) {
+		boolean result = false;
+		if (file != null) {
+			try {
+				IContentDescription contentDescription = file.getContentDescription();
+				if (contentDescription != null) {
+					IContentType fileContentType = contentDescription.getContentType();
+					if (fileContentType.isKindOf(fHTMLContentType)) {
+						result = true;
+					}
+					else {
+						IContentType[] otherTypes = getOtherSupportedContentTypes();
+						for (int i = 0; i < otherTypes.length; i++) {
+							result = result || fileContentType.isKindOf(otherTypes[i]);
+						}
+					}
+				}
+				else if (fHTMLContentType != null) {
+					result = fHTMLContentType.isAssociatedWith(file.getName());
+				}
+			}
+			catch (CoreException e) {
+				// should be rare, but will ignore to avoid logging "encoding
+				// exceptions" and the like here.
+				// Logger.logException(e);
+			}
+		}
+		return result;
+	}
+
+	/**
+	 */
+	private boolean hasHTMLFeature(IDOMDocument document) {
+		DocumentTypeAdapter adapter = (DocumentTypeAdapter) document.getAdapterFor(DocumentTypeAdapter.class);
+		if (adapter == null)
+			return false;
+		return adapter.hasFeature(HTMLDocumentTypeConstants.HTML);
+	}
+
+	/**
+	 */
+	protected void releaseModel(IStructuredModel model) {
+		if (model != null)
+			model.releaseFromRead();
+	}
+
+	/**
+	 */
+	public void validate(IValidationContext helper, IReporter reporter) {
+		if (helper == null)
+			return;
+		if ((reporter != null) && (reporter.isCancelled() == true)) {
+			throw new OperationCanceledException();
+		}
+		String[] deltaArray = helper.getURIs();
+		if (deltaArray != null && deltaArray.length > 0) {
+			validateDelta(helper, reporter);
+		}
+		else {
+			validateFull(helper, reporter);
+		}
+	}
+
+	/**
+	 * This validate call is for the ISourceValidator partial document
+	 * validation approach
+	 * 
+	 * @param dirtyRegion
+	 * @param helper
+	 * @param reporter
+	 * @see org.eclipse.wst.sse.ui.internal.reconcile.validator.ISourceValidator
+	 */
+	public void validate(IRegion dirtyRegion, IValidationContext helper, IReporter reporter) {
+
+		if (helper == null || fDocument == null)
+			return;
+
+		if ((reporter != null) && (reporter.isCancelled() == true)) {
+			throw new OperationCanceledException();
+		}
+
+		IStructuredModel model = StructuredModelManager.getModelManager().getExistingModelForRead(fDocument);
+		if (model == null)
+			return; // error
+
+		try {
+
+			IDOMDocument document = null;
+			if (model instanceof IDOMModel) {
+				document = ((IDOMModel) model).getDocument();
+			}
+
+			if (document == null || !hasHTMLFeature(document)) {
+				// handled in finally clause
+				// model.releaseFromRead();
+				return; //ignore
+			}
+			
+			IPath filePath = null;
+			IFile file = null;
+
+			ITextFileBuffer fb = FileBufferModelManager.getInstance().getBuffer(fDocument);
+			if (fb != null) {
+				filePath = fb.getLocation();
+
+				if (filePath.segmentCount() > 1) {
+					file = ResourcesPlugin.getWorkspace().getRoot().getFile(filePath);
+					if (!file.isAccessible()) {
+						file = null;
+					}
+				}
+			}
+			else {
+				filePath = new Path(model.getId());
+			}
+
+			// this will be the wrong region if it's Text (instead of Element)
+			// we don't know how to validate Text
+			IndexedRegion ir = getCoveringNode(dirtyRegion); //  model.getIndexedRegion(dirtyRegion.getOffset());
+			if (ir instanceof Text) {
+				while (ir != null && ir instanceof Text) {
+					// it's assumed that this gets the IndexedRegion to
+					// the right of the end offset
+					ir = model.getIndexedRegion(ir.getEndOffset());
+				}
+			}
+			
+			if (ir instanceof INodeNotifier) {
+
+				INodeAdapterFactory factory = HTMLValidationAdapterFactory.getInstance();
+				ValidationAdapter adapter = (ValidationAdapter) factory.adapt((INodeNotifier) ir);
+				if (adapter == null)
+					return; // error
+
+				if (reporter != null) {
+					HTMLValidationReporter rep = null;
+					rep = getReporter(reporter, file, (IDOMModel) model);
+					rep.clear();
+					adapter.setReporter(rep);
+
+					Message mess = new LocalizedMessage(IMessage.LOW_SEVERITY, filePath.toString().substring(1));
+					reporter.displaySubtask(this, mess);
+				}
+				adapter.validate(ir);
+			}
+		}
+		finally {
+			if (model != null)
+				model.releaseFromRead();
+		}
+	}
+
+	private IndexedRegion getCoveringNode(IRegion dirtyRegion) {
+		
+		IndexedRegion largestRegion = null;
+		if(fDocument instanceof IStructuredDocument) {
+			IStructuredDocumentRegion[] regions = ((IStructuredDocument) fDocument).getStructuredDocumentRegions(dirtyRegion.getOffset(), dirtyRegion.getLength());
+			largestRegion = getLargest(regions);
+		}
+		return largestRegion;
+	}
+	protected IndexedRegion getLargest(IStructuredDocumentRegion[] sdRegions) {
+		
+		if(sdRegions == null || sdRegions.length == 0)
+			return null;
+		 
+		IndexedRegion currentLargest = getCorrespondingNode(sdRegions[0]);
+		for (int i = 0; i < sdRegions.length; i++) {
+		    if(!sdRegions[i].isDeleted()) {
+    			IndexedRegion corresponding = getCorrespondingNode(sdRegions[i]);
+    			
+    			if(currentLargest instanceof Text)
+    				currentLargest = corresponding;
+    			
+                if(corresponding != null) {
+                	if(!(corresponding instanceof Text)) {
+	        			if (corresponding.getStartOffset() <= currentLargest.getStartOffset()  
+	        						&&  corresponding.getEndOffset() >= currentLargest.getEndOffset() )
+	        				currentLargest = corresponding;
+                	}
+                }
+                
+            }
+		}
+		return currentLargest;
+	}
+	protected IndexedRegion getCorrespondingNode(IStructuredDocumentRegion sdRegion) {
+		IStructuredModel sModel = StructuredModelManager.getModelManager().getExistingModelForRead(fDocument);
+        IndexedRegion indexedRegion = null;
+        try {
+            if (sModel != null) 
+                indexedRegion = sModel.getIndexedRegion(sdRegion.getStart());    
+        } finally {
+            if (sModel != null)
+                sModel.releaseFromRead();
+        }
+        return indexedRegion;
+    }
+
+	/**
+	 * @see org.eclipse.wst.sse.ui.internal.reconcile.validator.ISourceValidator
+	 */
+	public void connect(IDocument document) {
+		fDocument = document;
+	}
+
+	/**
+	 * @see org.eclipse.wst.sse.ui.internal.reconcile.validator.ISourceValidator
+	 */
+	public void disconnect(IDocument document) {
+		fDocument = null;
+	}
+
+	/**
+	 */
+	protected HTMLValidationResult validate(IDOMModel model, IFile file) {
+		IProject prj = null;
+		if (file != null) {
+			prj = file.getProject();
+		}
+		if ((prj == null) && (model != null)) {
+			URIResolver res = model.getResolver();
+			if (res != null) {
+				prj = res.getProject();
+			}
+		}
+		final WorkbenchReporter reporter = new WorkbenchReporter(prj, new NullProgressMonitor());
+		return validate(reporter, file, model);
+	}
+
+	/**
+	 */
+	private HTMLValidationResult validate(IReporter reporter, IFile file, IDOMModel model) {
+		if (file == null || model == null)
+			return null; // error
+		IDOMDocument document = model.getDocument();
+		if (document == null)
+			return null; // error
+		if (!hasHTMLFeature(document))
+			return null; // ignore
+
+		INodeAdapterFactory factory = HTMLValidationAdapterFactory.getInstance();
+		ValidationAdapter adapter = (ValidationAdapter) factory.adapt(document);
+		if (adapter == null)
+			return null; // error
+
+		HTMLValidationReporter rep = getReporter(reporter, file, model);
+		rep.clear();
+		adapter.setReporter(rep);
+		adapter.validate(document);
+		return rep.getResult();
+	}
+
+	/**
+	 */
+	private void validateContainer(IValidationContext helper, IReporter reporter, IContainer container) {
+		try {
+			IResource[] resourceArray = container.members(false);
+			for (int i = 0; i < resourceArray.length; i++) {
+				IResource resource = resourceArray[i];
+				if (resource == null || reporter.isCancelled())
+					continue;
+				if (resource instanceof IFile) {
+					Message message = new LocalizedMessage(IMessage.LOW_SEVERITY, resource.getFullPath().toString().substring(1));
+					reporter.displaySubtask(this, message);
+					validateFile(helper, reporter, (IFile) resource);
+				}
+				else if (resource instanceof IContainer) {
+					validateContainer(helper, reporter, (IContainer) resource);
+				}
+			}
+		}
+		catch (CoreException ex) {
+		}
+	}
+
+	/**
+	 */
+	private void validateDelta(IValidationContext helper, IReporter reporter) {
+		String[] deltaArray = helper.getURIs();
+		for (int i = 0; i < deltaArray.length; i++) {
+			String delta = deltaArray[i];
+			if (delta == null)
+				continue;
+
+			if (reporter != null) {
+				Message message = new LocalizedMessage(IMessage.LOW_SEVERITY, delta.substring(1));
+				reporter.displaySubtask(this, message);
+			}
+
+			IResource resource = getResource(delta);
+			if (resource == null || !(resource instanceof IFile))
+				continue;
+			validateFile(helper, reporter, (IFile) resource);
+		}
+	}
+
+	/**
+	 */
+	private void validateFile(IValidationContext helper, IReporter reporter, IFile file) {
+		if ((reporter != null) && (reporter.isCancelled() == true)) {
+			throw new OperationCanceledException();
+		}
+		if (!shouldValidate(file)) {
+			return;
+		}
+		IDOMModel model = getModel(file.getProject(), file);
+		if (model == null)
+			return;
+
+		try {
+			validate(reporter, file, model);
+		}
+		finally {
+			releaseModel(model);
+		}
+	}
+
+	/**
+	 */
+	private void validateFull(IValidationContext helper, IReporter reporter) {
+		IProject project = null;
+		String[] fileDelta = helper.getURIs();
+		if (helper instanceof IWorkbenchContext) {
+			IWorkbenchContext wbHelper = (IWorkbenchContext) helper;
+			project = wbHelper.getProject();
+		}
+		else if(fileDelta.length > 0){
+			// won't work for project validation (b/c nothing in file delta)
+			project = getResource(fileDelta[0]).getProject();
+		}
+		if (project == null)
+			return;
+		validateContainer(helper, reporter, project);
+	}
+
+	/*
+	 * added to get rid or dependency on IWorkbenchHelper
+	 * 
+	 */
+	public IResource getResource(String delta) {
+		return ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(delta));
+	}
+
+	public ISchedulingRule getSchedulingRule(IValidationContext helper) {
+		return null;
+	}
+
+	public IStatus validateInJob(IValidationContext helper, IReporter reporter) throws ValidationException {
+		// Exception catching was removed, see
+		// https://bugs.eclipse.org/bugs/show_bug.cgi?id=123600
+		IStatus status = Status.OK_STATUS;
+		validate(helper, reporter);
+		return status;
+	}
+	
+	/**
+	 * @see org.eclipse.core.runtime.IExecutableExtension#setInitializationData(org.eclipse.core.runtime.IConfigurationElement,
+	 *      java.lang.String, java.lang.Object)
+	 */
+	public void setInitializationData(IConfigurationElement config, String propertyName, Object data) throws CoreException {
+		fAdditionalContentTypesIDs = new String[0];
+		if (data != null) {
+			if (data instanceof String && data.toString().length() > 0) {
+				fAdditionalContentTypesIDs = StringUtils.unpack(data.toString());
+			}
+		}
+	}
+
+	public ValidationResult validate(IResource resource, int kind, ValidationState state, IProgressMonitor monitor) {
+		if (resource.getType() != IResource.FILE)
+			return null;
+		ValidationResult result = new ValidationResult();
+		IReporter reporter = result.getReporter(monitor);
+		validateFile(null, reporter, (IFile) resource);
+		return result;
+	}
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.html.ui/src-html-validation/org/eclipse/wst/html/internal/validation/LocalizedMessage.java b/bundles/org.eclipse.wst.html.ui/src-html-validation/org/eclipse/wst/html/internal/validation/LocalizedMessage.java
new file mode 100644
index 0000000..1e38729
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src-html-validation/org/eclipse/wst/html/internal/validation/LocalizedMessage.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.internal.validation;
+
+import java.util.Locale;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.wst.validation.internal.core.Message;
+
+/**
+ * copied from org.eclipse.wst.validation.internal.operations.LocalizedMessage
+ * 
+ * This class is provided for validators which run only in Eclipse and whose messages, because they
+ * come from another tool, are already localized. LocalizedMessage cannot be used by any validator
+ * which needs to run in both WebSphere and Eclipse.
+ */
+public class LocalizedMessage extends Message {
+	private String _message = null;
+
+	public LocalizedMessage(int severity, String messageText) {
+		this(severity, messageText, null);
+	}
+
+	public LocalizedMessage(int severity, String messageText, IResource targetObject) {
+		this(severity, messageText, (Object) targetObject);
+	}
+
+	public LocalizedMessage(int severity, String messageText, Object targetObject) {
+		super(null, severity, null);
+		setLocalizedMessage(messageText);
+		setTargetObject(targetObject);
+	}
+
+	public void setLocalizedMessage(String message) {
+		_message = message;
+	}
+
+	public String getLocalizedMessage() {
+		return _message;
+	}
+
+	public String getText() {
+		return getLocalizedMessage();
+	}
+
+	public String getText(ClassLoader cl) {
+		return getLocalizedMessage();
+	}
+
+	public String getText(Locale l) {
+		return getLocalizedMessage();
+	}
+
+	public String getText(Locale l, ClassLoader cl) {
+		return getLocalizedMessage();
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src-html-validation/org/eclipse/wst/html/internal/validation/TaskListHelper.java b/bundles/org.eclipse.wst.html.ui/src-html-validation/org/eclipse/wst/html/internal/validation/TaskListHelper.java
new file mode 100644
index 0000000..71ede2d
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src-html-validation/org/eclipse/wst/html/internal/validation/TaskListHelper.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.internal.validation;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+
+/**
+ * 
+ * Class to help this Problem's list.
+ * 
+ */
+class TaskListHelper {
+	private static TaskListHelper _taskListHelper = null;
+
+	public static TaskListHelper getTaskList() {
+		if (_taskListHelper == null) {
+			_taskListHelper = new TaskListHelper();
+		}
+		return _taskListHelper;
+	}
+
+	/**
+	 * This method adds a message to a resource in the task list.
+	 */
+	public void addTask(String pluginId, IResource resource, String location, String messageId, String message, int markerType, String targetObjectName, String groupName, int offset, int length) throws CoreException {
+		TaskListUtility.addTask(pluginId, resource, location, messageId, message, markerType, targetObjectName, groupName, offset, length);
+	}
+
+	/**
+	 * This method removes all messages from a resource in the task list.
+	 */
+	public void removeAllTasks(IResource resource, String owner, String objectName) throws CoreException {
+		TaskListUtility.removeAllTasks(resource, owner, objectName);
+	}
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.html.ui/src-html-validation/org/eclipse/wst/html/internal/validation/TaskListUtility.java b/bundles/org.eclipse.wst.html.ui/src-html-validation/org/eclipse/wst/html/internal/validation/TaskListUtility.java
new file mode 100644
index 0000000..3de0a92
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src-html-validation/org/eclipse/wst/html/internal/validation/TaskListUtility.java
@@ -0,0 +1,436 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.internal.validation;
+
+import org.eclipse.core.resources.IMarker;
+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.wst.html.ui.internal.HTMLUIPlugin;
+import org.eclipse.wst.validation.internal.provisional.core.IMessage;
+
+/**
+ * This class must be called only by the validation framework.
+ * 
+ * This singleton interacts with the eclipse workbench's Task list.
+ * TaskListUtility adds and removes tasks from the list.
+ * 
+ * This class must not be called outside of an IWorkspaceRunnable or
+ * IRunnableWithProgress. Many resource deltas can be generated by the methods
+ * in this class.
+ * 
+ * This came from TaskListUtility
+ */
+public class TaskListUtility {
+	// private static final String PLUGIN_ID = ValidationPlugin.PLUGIN_ID;
+	private static final String PLUGIN_ID = HTMLUIPlugin.ID;
+	private static final String VALIDATION_MARKER = PLUGIN_ID + ".problemmarker"; //$NON-NLS-1$ // The extension which is used to add validation markers to the task list
+	private static final String VALIDATION_MARKER_OWNER = "owner"; //$NON-NLS-1$ // The IValidator who owns the IMarker on the task list
+	private static final String VALIDATION_MARKER_SEVERITY = "validationSeverity"; //$NON-NLS-1$ // one of the IMessage values
+	private static final String VALIDATION_MARKER_TARGETOBJECT = "targetObject"; //$NON-NLS-1$ // When more than one target object resolves to the same IResource, this field identifies which targetObject owns a particular message.
+	private static final String VALIDATION_MARKER_GROUP = "groupName"; //$NON-NLS-1$ // For incremental validation, this field associates a message with a group, so that a subset of messages may be removed from a file.
+	private static final String VALIDATION_MARKER_MESSAGEID = "messageId"; //$NON-NLS-1$ // Persist the message id of the message, not just the translated text.
+	private static final int DEPTH_INFINITE = IResource.DEPTH_INFINITE;
+	private static final int DEPTH_ZERO = IResource.DEPTH_ZERO;
+	private final static IMarker[] NO_MARKERS = new IMarker[0];
+
+	/**
+	 * This method adds a message to a resource in the task list.
+	 */
+	public static IMarker addTask(String pluginId, IResource resource, String location, String messageId, String message, int markerType, String targetObjectName, String groupName, int offset, int length) throws CoreException {
+		if ((message == null) || (resource == null)) {
+			return null;
+		}
+
+		int severity = getSeverity(markerType);
+
+		// Allow duplicate entries in the task list.
+		// Prior to a full validation, the validation framework will remove
+		// all messages owned
+		// by a validator before it is executed.
+		// Prior to an incremental validation, the validation framework will
+		// remove all messages,
+		// on each of the changed resources, owned by a validator before it is
+		// invoked.
+		// 
+		// It is up to the validator to make sure that it is not adding the
+		// same message
+		// in more than one place, and also to clear out any old messages
+		// which are not cleared
+		// by the validation framework.
+		IMarker item = resource.createMarker(VALIDATION_MARKER); // add a
+																	// validation
+																	// marker
+
+		// For performance reasons, replace the multiple setAttribute
+		// calls above with a single setAttributes call.
+		boolean offsetSet = ((offset != IMessage.OFFSET_UNSET) && (length != IMessage.OFFSET_UNSET));
+		int size = (offsetSet) ? 10 : 8; // add CHAR_START, CHAR_END only
+											// if the offset is set. If the
+											// offset is set, it takes
+											// precendence over the line
+											// number. (eclipse's rule, not
+											// mine.)
+		String[] attribNames = new String[size];
+		Object[] attribValues = new Object[size];
+
+		// Very first thing, add the owner. That way, if the code dies
+		// before things are persisted, hopefully this marker will be
+		// persisted.
+		// Hopefully, eclipse WILL persist this field, as requested.
+		attribNames[0] = VALIDATION_MARKER_OWNER;
+		attribValues[0] = pluginId;
+		attribNames[1] = VALIDATION_MARKER_SEVERITY; // this validation
+														// severity is stored,
+														// in addition to the
+														// marker severity, to
+														// enable more than
+														// one severity of
+														// message to be
+														// displayed. e.g.
+														// ERROR | WARNING
+														// (using binary OR).
+														// The IMarker
+														// constants are
+														// regular decimal
+														// constants.
+		attribValues[1] = new Integer(markerType);
+		attribNames[2] = VALIDATION_MARKER_TARGETOBJECT; // to distinguish
+															// between
+															// messages which
+															// are registered
+															// on an
+															// IResource, but
+															// against
+															// different
+															// target objects
+		attribValues[2] = ((targetObjectName == null) ? "" : targetObjectName); //$NON-NLS-1$
+		attribNames[3] = VALIDATION_MARKER_GROUP;
+		attribValues[3] = ((groupName == null) ? "" : groupName); //$NON-NLS-1$
+		attribNames[4] = IMarker.MESSAGE;
+		attribValues[4] = message;
+		attribNames[5] = VALIDATION_MARKER_MESSAGEID;
+		attribValues[5] = messageId;
+
+		attribNames[6] = IMarker.SEVERITY; // IMarker.SEVERITY_ERROR,
+											// IMarker.SEVERITY_WARNING,
+											// IMarker.SEVERITY_INFO
+		attribValues[6] = new Integer(severity);
+		try {
+			// If the location is a line number, store it as a line number
+			Integer lineNumber = Integer.valueOf(location);
+			attribNames[7] = IMarker.LINE_NUMBER;
+			attribValues[7] = lineNumber;
+		}
+		catch (NumberFormatException exc) {
+			// Otherwise, store it as a text location
+			attribNames[7] = IMarker.LOCATION;
+			attribValues[7] = location;
+		}
+
+		if (offsetSet) {
+			attribNames[8] = IMarker.CHAR_START;
+			attribValues[8] = new Integer(offset);
+			attribNames[9] = IMarker.CHAR_END;
+			attribValues[9] = new Integer(offset + length);
+		}
+
+		item.setAttributes(attribNames, attribValues);
+
+		return item;
+	}
+
+	/**
+	 * Given one of the SeverityEnum severities, return the IMarker severity
+	 * int that is its equivalent.
+	 */
+	private static int getSeverity(int severityEnumValue) {
+		switch (severityEnumValue) {
+			case (IMessage.HIGH_SEVERITY) : {
+				return IMarker.SEVERITY_ERROR;
+			}
+
+			case (IMessage.LOW_SEVERITY) : {
+				return IMarker.SEVERITY_INFO;
+			}
+
+			case (IMessage.NORMAL_SEVERITY) : {
+				return IMarker.SEVERITY_WARNING;
+			}
+
+			case (IMessage.ALL_MESSAGES) :
+			case (IMessage.ERROR_AND_WARNING) :
+			default : {
+				// assume it's a warning.
+				return IMarker.SEVERITY_WARNING;
+			}
+		}
+	}
+
+	private static int getDepth(IResource resource) {
+		if (resource instanceof IProject) {
+			return DEPTH_INFINITE; // DEPTH_INFINITE means get this project's
+									// markers, and the markers belonging to
+									// the project's children.
+		}
+		else if (resource instanceof IWorkspaceRoot) {
+			// Needed for the ValidationMigrator when it checks for orphan
+			// tasks.
+			return DEPTH_INFINITE; // DEPTH_INFINITE means get all of the
+									// markers in the workspace
+		}
+
+		return DEPTH_ZERO; // DEPTH_ZERO means just this resource, not its
+							// children
+	}
+
+	private static IMarker[] getValidationTasks(IResource resource, int severity, int depth) {
+		IMarker[] tempMarkers = null;
+		int validCount = 0;
+		try {
+			IMarker[] allMarkers = null;
+			try {
+				allMarkers = resource.findMarkers(VALIDATION_MARKER, false, depth); // false
+																					// means
+																					// only
+																					// consider
+																					// PROBLEM_MARKER,
+																					// not
+																					// variants
+																					// of
+																					// PROBLEM_MARKER.
+																					// Since
+																					// addTask
+																					// only
+																					// adds
+																					// PROBLEM_MARKER,
+																					// we
+																					// don't
+																					// need
+																					// to
+																					// consider
+																					// its
+																					// subtypes.
+			}
+			catch (CoreException exc) {
+				// Logger logger =
+				// ValidationPlugin.getPlugin().getMsgLogger();
+				// if (logger.isLoggingLevel(Level.SEVERE)) {
+				// LogEntry entry = ValidationPlugin.getLogEntry();
+				// entry.setSourceID("TaskListUtility.getValidationTasks(IResource,
+				// int)"); //$NON-NLS-1$
+				// entry.setTargetException(exc);
+				// logger.write(Level.SEVERE, entry);
+				// }
+				return NO_MARKERS;
+			}
+
+			// Now filter in the markers, based on severity type.
+			if (allMarkers.length != 0) {
+				tempMarkers = new IMarker[allMarkers.length];
+				for (int i = 0; i < allMarkers.length; i++) {
+					IMarker marker = allMarkers[i];
+					Integer filterSeverity = (Integer) marker.getAttribute(VALIDATION_MARKER_SEVERITY);
+					if (filterSeverity == null) {
+						// odd...marker wasn't created correctly. How could
+						// this happen?
+						// Default to the current severity and add it to the
+						// list.
+						try {
+							marker.setAttribute(IMarker.SEVERITY, getSeverity(severity));
+						}
+						catch (CoreException exc) {
+							// Logger logger =
+							// ValidationPlugin.getPlugin().getMsgLogger();
+							// if (logger.isLoggingLevel(Level.SEVERE)) {
+							// LogEntry entry =
+							// ValidationPlugin.getLogEntry();
+							// entry.setSourceID("TaskListUtility.getValidationTasks(int,
+							// IResource, int)"); //$NON-NLS-1$
+							// entry.setTargetException(exc);
+							// logger.write(Level.SEVERE, entry);
+							// }
+							continue;
+						}
+						catch (Exception exc) {
+							// Logger logger =
+							// ValidationPlugin.getPlugin().getMsgLogger();
+							// if (logger.isLoggingLevel(Level.SEVERE)) {
+							// LogEntry entry =
+							// ValidationPlugin.getLogEntry();
+							// entry.setSourceID("TaskListUtility.getValidationTasks(int,
+							// IResource, int)"); //$NON-NLS-1$
+							// entry.setTargetException(exc);
+							// logger.write(Level.SEVERE, entry);
+							// }
+							continue;
+						}
+					}
+					else if ((severity & filterSeverity.intValue()) == 0) {
+						continue;
+					}
+					tempMarkers[validCount++] = marker;
+				}
+			}
+		}
+		catch (CoreException exc) {
+			// Logger logger = ValidationPlugin.getPlugin().getMsgLogger();
+			// if (logger.isLoggingLevel(Level.SEVERE)) {
+			// LogEntry entry = ValidationPlugin.getLogEntry();
+			// entry.setSourceID("TaskListUtility.getValidationTasks(int,
+			// IResource, int)"); //$NON-NLS-1$
+			// entry.setTargetException(exc);
+			// logger.write(Level.SEVERE, entry);
+			// }
+		}
+
+		if (validCount == 0) {
+			return NO_MARKERS;
+		}
+
+		IMarker[] validMarkers = new IMarker[validCount];
+		System.arraycopy(tempMarkers, 0, validMarkers, 0, validCount);
+		return validMarkers;
+	}
+
+	private static IMarker[] getValidationTasks(IResource resource, String[] messageOwners, int depth) {
+		IMarker[] markers = getValidationTasks(resource, IMessage.ALL_MESSAGES, depth);
+		if (markers.length == 0) {
+			return NO_MARKERS;
+		}
+
+		IMarker[] temp = new IMarker[markers.length];
+		int validCount = 0;
+		for (int i = 0; i < markers.length; i++) {
+			IMarker marker = markers[i];
+
+			try {
+				Object owner = marker.getAttribute(VALIDATION_MARKER_OWNER);
+				if ((owner == null) || !(owner instanceof String)) {
+					// The ValidationMigrator will remove any "unowned"
+					// validation markers.
+					continue;
+				}
+
+				for (int j = 0; j < messageOwners.length; j++) {
+					String messageOwner = messageOwners[j];
+					if (((String) owner).equals(messageOwner)) {
+						temp[validCount++] = marker;
+						break;
+					}
+				}
+			}
+			catch (CoreException exc) {
+				// Logger logger =
+				// ValidationPlugin.getPlugin().getMsgLogger();
+				// if (logger.isLoggingLevel(Level.SEVERE)) {
+				// LogEntry entry = ValidationPlugin.getLogEntry();
+				// entry.setSourceID("TaskListUtility.getValidationTasks(project,
+				// String[])"); //$NON-NLS-1$
+				// entry.setTargetException(exc);
+				// logger.write(Level.SEVERE, entry);
+				// }
+				return NO_MARKERS;
+			}
+		}
+
+		IMarker[] result = new IMarker[validCount];
+		System.arraycopy(temp, 0, result, 0, validCount);
+		return result;
+	}
+
+	/**
+	 * This method retrieves all validation tasks from the resource. If depth
+	 * is INFINITE, child tasks are returned as well. Only the tasks which are
+	 * owned by the specified messageOwner, and apply to the named IMessage's
+	 * target object (objectName) will be returned.
+	 */
+	private static IMarker[] getValidationTasks(IResource resource, String[] messageOwner, String objectName, String groupName, int depth) throws CoreException {
+		if ((messageOwner == null) || (resource == null)) {
+			return NO_MARKERS;
+		}
+
+		int validCount = 0;
+		IMarker[] validList = null;
+		IMarker[] markers = getValidationTasks(resource, messageOwner, depth);
+		if (markers != null) {
+			validList = new IMarker[markers.length];
+			for (int i = 0; i < markers.length; i++) {
+				IMarker marker = markers[i];
+
+				// If more than one target object resolves to the same
+				// resource, removing one target's
+				// messages should not remove the other target object's
+				// messages.
+				if (objectName != null) {
+					Object targetObject = marker.getAttribute(VALIDATION_MARKER_TARGETOBJECT);
+					if ((targetObject == null) || !(targetObject instanceof String) || !(((String) targetObject).equals(objectName))) {
+						continue;
+					}
+				}
+
+				if (groupName != null) {
+					Object group = marker.getAttribute(VALIDATION_MARKER_GROUP);
+					if ((group == null) || !(group instanceof String) || !(((String) group).equals(groupName))) {
+						continue;
+					}
+				}
+
+				validList[validCount++] = marker;
+			}
+		}
+
+		if (validCount == 0) {
+			return NO_MARKERS;
+		}
+
+		IMarker[] result = new IMarker[validCount];
+		System.arraycopy(validList, 0, result, 0, validCount);
+		return result;
+	}
+
+	/**
+	 * This method removes all messages from a resource in the task list.
+	 */
+	public static void removeAllTasks(IResource resource, String owner, String objectName) throws CoreException {
+		removeAllTasks(resource, new String[]{owner}, objectName);
+	}
+
+	public static void removeAllTasks(IResource resource, String[] owners, String objectName) throws CoreException {
+		removeAllTasks(resource, owners, objectName, getDepth(resource));
+	}
+
+	protected static void removeAllTasks(IResource resource, String[] owners, String objectName, int depth) throws CoreException {
+		removeTaskSubset(resource, owners, objectName, null, depth); // null
+																		// means
+																		// no
+																		// group
+																		// name
+	}
+
+	/**
+	 * This method removes a subset of tasks from the project, including child
+	 * tasks. Every task which belongs to the group, identified by groupName,
+	 * will be removed.
+	 */
+	protected static void removeTaskSubset(IResource resource, String[] owners, String objectName, String groupName, int depth) throws CoreException {
+		if ((owners == null) || (resource == null)) {
+			return;
+		}
+
+		IMarker[] allTasks = getValidationTasks(resource, owners, objectName, groupName, depth);
+		if (allTasks.length > 0) {
+			ResourcesPlugin.getWorkspace().deleteMarkers(allTasks);
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/StructuredTextViewerConfigurationHTML.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/StructuredTextViewerConfigurationHTML.java
new file mode 100644
index 0000000..a38409f
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/StructuredTextViewerConfigurationHTML.java
@@ -0,0 +1,269 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.wst.html.ui;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Vector;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.jface.text.IAutoEditStrategy;
+import org.eclipse.jface.text.ITextDoubleClickStrategy;
+import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
+import org.eclipse.jface.text.formatter.IContentFormatter;
+import org.eclipse.jface.text.formatter.MultiPassContentFormatter;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.wst.css.core.text.ICSSPartitions;
+import org.eclipse.wst.css.ui.internal.style.LineStyleProviderForEmbeddedCSS;
+import org.eclipse.wst.html.core.internal.HTMLCorePlugin;
+import org.eclipse.wst.html.core.internal.format.HTMLFormatProcessorImpl;
+import org.eclipse.wst.html.core.internal.preferences.HTMLCorePreferenceNames;
+import org.eclipse.wst.html.core.internal.provisional.contenttype.ContentTypeIdForHTML;
+import org.eclipse.wst.html.core.internal.text.StructuredTextPartitionerForHTML;
+import org.eclipse.wst.html.core.text.IHTMLPartitions;
+import org.eclipse.wst.html.ui.internal.autoedit.AutoEditStrategyForTabs;
+import org.eclipse.wst.html.ui.internal.contentassist.HTMLStructuredContentAssistProcessor;
+import org.eclipse.wst.html.ui.internal.style.LineStyleProviderForHTML;
+import org.eclipse.wst.sse.core.text.IStructuredPartitions;
+import org.eclipse.wst.sse.ui.StructuredTextViewerConfiguration;
+import org.eclipse.wst.sse.ui.internal.format.StructuredFormattingStrategy;
+import org.eclipse.wst.sse.ui.internal.provisional.style.LineStyleProvider;
+import org.eclipse.wst.xml.core.internal.provisional.contenttype.ContentTypeIdForXML;
+import org.eclipse.wst.xml.core.internal.text.rules.StructuredTextPartitionerForXML;
+import org.eclipse.wst.xml.core.text.IXMLPartitions;
+import org.eclipse.wst.xml.ui.StructuredTextViewerConfigurationXML;
+import org.eclipse.wst.xml.ui.internal.contentoutline.JFaceNodeLabelProvider;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Node;
+
+/**
+ * Configuration for a source viewer which shows HTML content.
+ * <p>
+ * Clients can subclass and override just those methods which must be specific
+ * to their needs.
+ * </p>
+ * 
+ * @see org.eclipse.wst.sse.ui.StructuredTextViewerConfiguration
+ * @since 1.0
+ */
+public class StructuredTextViewerConfigurationHTML extends StructuredTextViewerConfiguration {
+	/*
+	 * One instance per configuration because not sourceviewer-specific and
+	 * it's a String array
+	 */
+	private String[] fConfiguredContentTypes;
+	/*
+	 * One instance per configuration
+	 */
+	private LineStyleProvider fLineStyleProviderForEmbeddedCSS;
+	/*
+	 * One instance per configuration
+	 */
+	private LineStyleProvider fLineStyleProviderForHTML;
+	/*
+	 * One instance per configuration
+	 */
+	private StructuredTextViewerConfiguration fXMLSourceViewerConfiguration;
+	private ILabelProvider fStatusLineLabelProvider;
+
+	/**
+	 * Create new instance of StructuredTextViewerConfigurationHTML
+	 */
+	public StructuredTextViewerConfigurationHTML() {
+		// Must have empty constructor to createExecutableExtension
+		super();
+	}
+
+	public IAutoEditStrategy[] getAutoEditStrategies(ISourceViewer sourceViewer, String contentType) {
+		List allStrategies = new ArrayList(0);
+
+		IAutoEditStrategy[] superStrategies = super.getAutoEditStrategies(sourceViewer, contentType);
+		for (int i = 0; i < superStrategies.length; i++) {
+			allStrategies.add(superStrategies[i]);
+		}
+
+		// be sure this is added last in list, so it has a change to modify
+		// previous results.
+		// add auto edit strategy that handles when tab key is pressed
+		allStrategies.add(new AutoEditStrategyForTabs());
+
+		return (IAutoEditStrategy[]) allStrategies.toArray(new IAutoEditStrategy[allStrategies.size()]);
+	}
+
+	public String[] getConfiguredContentTypes(ISourceViewer sourceViewer) {
+		if (fConfiguredContentTypes == null) {
+			String[] xmlTypes = StructuredTextPartitionerForXML.getConfiguredContentTypes();
+			String[] htmlTypes = StructuredTextPartitionerForHTML.getConfiguredContentTypes();
+			fConfiguredContentTypes = new String[2 + xmlTypes.length + htmlTypes.length];
+
+			fConfiguredContentTypes[0] = IStructuredPartitions.DEFAULT_PARTITION;
+			fConfiguredContentTypes[1] = IStructuredPartitions.UNKNOWN_PARTITION;
+
+			int index = 0;
+			System.arraycopy(xmlTypes, 0, fConfiguredContentTypes, index += 2, xmlTypes.length);
+			System.arraycopy(htmlTypes, 0, fConfiguredContentTypes, index += xmlTypes.length, htmlTypes.length);
+		}
+
+		return fConfiguredContentTypes;
+	}
+
+	protected IContentAssistProcessor[] getContentAssistProcessors(
+			ISourceViewer sourceViewer, String partitionType) {
+		
+		IContentAssistProcessor processor = new HTMLStructuredContentAssistProcessor(
+				this.getContentAssistant(), partitionType, sourceViewer);
+		return new IContentAssistProcessor[]{processor};
+	}
+
+	public IContentFormatter getContentFormatter(ISourceViewer sourceViewer) {
+		IContentFormatter formatter = super.getContentFormatter(sourceViewer);
+		// super was unable to create a formatter, probably because
+		// sourceViewer does not have document set yet, so just create a
+		// generic one
+		if (!(formatter instanceof MultiPassContentFormatter))
+			formatter = new MultiPassContentFormatter(getConfiguredDocumentPartitioning(sourceViewer), IHTMLPartitions.HTML_DEFAULT);
+		((MultiPassContentFormatter) formatter).setMasterStrategy(new StructuredFormattingStrategy(new HTMLFormatProcessorImpl()));
+
+		return formatter;
+	}
+
+	public ITextDoubleClickStrategy getDoubleClickStrategy(ISourceViewer sourceViewer, String contentType) {
+		if (contentType == IHTMLPartitions.HTML_DEFAULT) {
+			// use xml's doubleclick strategy
+			return getXMLSourceViewerConfiguration().getDoubleClickStrategy(sourceViewer, IXMLPartitions.XML_DEFAULT);
+		}
+		else
+			return super.getDoubleClickStrategy(sourceViewer, contentType);
+
+	}
+
+	public String[] getIndentPrefixes(ISourceViewer sourceViewer, String contentType) {
+		Vector vector = new Vector();
+
+		// prefix[0] is either '\t' or ' ' x tabWidth, depending on preference
+		Preferences preferences = HTMLCorePlugin.getDefault().getPluginPreferences();
+		int indentationWidth = preferences.getInt(HTMLCorePreferenceNames.INDENTATION_SIZE);
+		String indentCharPref = preferences.getString(HTMLCorePreferenceNames.INDENTATION_CHAR);
+		boolean useSpaces = HTMLCorePreferenceNames.SPACE.equals(indentCharPref);
+
+		for (int i = 0; i <= indentationWidth; i++) {
+			StringBuffer prefix = new StringBuffer();
+			boolean appendTab = false;
+
+			if (useSpaces) {
+				for (int j = 0; j + i < indentationWidth; j++)
+					prefix.append(' ');
+
+				if (i != 0)
+					appendTab = true;
+			}
+			else {
+				for (int j = 0; j < i; j++)
+					prefix.append(' ');
+
+				if (i != indentationWidth)
+					appendTab = true;
+			}
+
+			if (appendTab) {
+				prefix.append('\t');
+				vector.add(prefix.toString());
+				// remove the tab so that indentation - tab is also an indent
+				// prefix
+				prefix.deleteCharAt(prefix.length() - 1);
+			}
+			vector.add(prefix.toString());
+		}
+
+		vector.add(""); //$NON-NLS-1$
+
+		return (String[]) vector.toArray(new String[vector.size()]);
+	}
+
+	public LineStyleProvider[] getLineStyleProviders(ISourceViewer sourceViewer, String partitionType) {
+		LineStyleProvider[] providers = null;
+
+		// workaround IXMLPartitions.XML_PI
+		if (partitionType == IHTMLPartitions.HTML_DEFAULT || partitionType == IHTMLPartitions.HTML_COMMENT || partitionType == IHTMLPartitions.HTML_DECLARATION || partitionType == IXMLPartitions.XML_PI) {
+			providers = new LineStyleProvider[]{getLineStyleProviderForHTML()};
+		}
+		else if (partitionType == ICSSPartitions.STYLE || partitionType == ICSSPartitions.COMMENT) {
+			providers = new LineStyleProvider[]{getLineStyleProviderForEmbeddedCSS()};
+		}
+
+		return providers;
+	}
+
+	private LineStyleProvider getLineStyleProviderForEmbeddedCSS() {
+		if (fLineStyleProviderForEmbeddedCSS == null) {
+			fLineStyleProviderForEmbeddedCSS = new LineStyleProviderForEmbeddedCSS();
+		}
+		return fLineStyleProviderForEmbeddedCSS;
+	}
+
+	private LineStyleProvider getLineStyleProviderForHTML() {
+		if (fLineStyleProviderForHTML == null) {
+			fLineStyleProviderForHTML = new LineStyleProviderForHTML();
+		}
+		return fLineStyleProviderForHTML;
+	}
+
+	public ILabelProvider getStatusLineLabelProvider(ISourceViewer sourceViewer) {
+		if (fStatusLineLabelProvider == null) {
+			fStatusLineLabelProvider = new JFaceNodeLabelProvider() {
+				public String getText(Object element) {
+					if (element == null)
+						return null;
+
+					StringBuffer s = new StringBuffer();
+					Node node = (Node) element;
+					while (node != null) {
+						if (node.getNodeType() != Node.DOCUMENT_NODE) {
+							s.insert(0, super.getText(node));
+						}
+
+						if (node.getNodeType() == Node.ATTRIBUTE_NODE)
+							node = ((Attr) node).getOwnerElement();
+						else
+							node = node.getParentNode();
+					
+						if (node != null && node.getNodeType() != Node.DOCUMENT_NODE) {
+							s.insert(0, IPath.SEPARATOR);
+						}
+					}
+					return s.toString();
+				}
+
+			};
+		}
+		return fStatusLineLabelProvider;
+	}
+
+	private StructuredTextViewerConfiguration getXMLSourceViewerConfiguration() {
+		if (fXMLSourceViewerConfiguration == null) {
+			fXMLSourceViewerConfiguration = new StructuredTextViewerConfigurationXML();
+		}
+		return fXMLSourceViewerConfiguration;
+	}
+
+	protected Map getHyperlinkDetectorTargets(ISourceViewer sourceViewer) {
+		Map targets = super.getHyperlinkDetectorTargets(sourceViewer);
+		targets.put(ContentTypeIdForHTML.ContentTypeID_HTML, null);
+
+		// also add xml since there could be xml content in html
+		// (just hope the hyperlink detectors will do additional checking)
+		targets.put(ContentTypeIdForXML.ContentTypeID_XML, null);
+		return targets;
+	}
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/HTMLUIMessages.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/HTMLUIMessages.java
new file mode 100644
index 0000000..71f86b4
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/HTMLUIMessages.java
@@ -0,0 +1,208 @@
+/**********************************************************************
+ * Copyright (c) 2005, 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 - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.html.ui.internal;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Strings used by HTML UI
+ * 
+ * @plannedfor 1.0
+ */
+public class HTMLUIMessages extends NLS {
+	private static final String BUNDLE_NAME = "org.eclipse.wst.html.ui.internal.HTMLUIPluginResources";//$NON-NLS-1$
+	private static ResourceBundle fResourceBundle;
+
+	static {
+		// load message values from bundle file
+		NLS.initializeMessages(BUNDLE_NAME, HTMLUIMessages.class);
+	}
+	
+	private HTMLUIMessages() {
+		// cannot create new instance of this class
+	}
+	
+	public static ResourceBundle getResourceBundle() {
+		try {
+			if (fResourceBundle == null)
+				fResourceBundle = ResourceBundle.getBundle(BUNDLE_NAME);
+		}
+		catch (MissingResourceException x) {
+			fResourceBundle = null;
+		}
+		return fResourceBundle;
+	}
+	
+	public static String Sample_HTML_doc;
+	public static String HTMLFilesPreferencePage_0;
+	public static String _UI_WIZARD_NEW_TITLE;
+	public static String _UI_WIZARD_NEW_HEADING;
+	public static String _UI_WIZARD_NEW_DESCRIPTION;
+	public static String _ERROR_FILENAME_MUST_END_HTML;
+	public static String _WARNING_FOLDER_MUST_BE_INSIDE_WEB_CONTENT;
+	public static String ResourceGroup_nameExists;
+	public static String NewHTMLTemplatesWizardPage_0;
+	public static String NewHTMLTemplatesWizardPage_1;
+	public static String NewHTMLTemplatesWizardPage_2;
+	public static String NewHTMLTemplatesWizardPage_3;
+	public static String NewHTMLTemplatesWizardPage_4;
+	public static String NewHTMLTemplatesWizardPage_5;
+	public static String NewHTMLTemplatesWizardPage_6;
+	public static String NewHTMLTemplatesWizardPage_7;
+	public static String Creating_files_encoding;
+	public static String CleanupDocument_label; // resource bundle
+	public static String CleanupDocument_tooltip; // resource bundle
+	public static String CleanupDocument_description; // resource bundle
+	public static String ToggleComment_label; // resource bundle
+	public static String ToggleComment_tooltip; // resource bundle
+	public static String ToggleComment_description; // resource bundle
+	public static String AddBlockComment_label; // resource bundle
+	public static String AddBlockComment_tooltip; // resource bundle
+	public static String AddBlockComment_description; // resource bundle
+	public static String RemoveBlockComment_label; // resource bundle
+	public static String RemoveBlockComment_tooltip; // resource bundle
+	public static String RemoveBlockComment_description; // resource bundle
+	public static String FindOccurrences_label;	// resource bundle
+	public static String Creating_files;
+	public static String Encoding_desc;
+	public static String UI_Description_of_role_of_following_DOCTYPE;
+	public static String UI_Default_HTML_DOCTYPE_ID___1;
+	public static String UI_Public_ID;
+	public static String UI_System_ID;
+	public static String UI_none;
+	public static String UI_CSS_profile___2;
+	public static String WebContentSettingsPropertyPage_0;
+	public static String ProjectWebContentSettingsPropertyPage_0;
+	
+	public static String Auto_Activation_UI_;
+	public static String Automatically_make_suggest_UI_;
+	public static String Prompt_when_these_characte_UI_;
+	public static String Cycling_UI_;
+	public static String Formatting_UI_;
+	public static String Line_width__UI_;
+	public static String Split_multiple_attributes;
+	public static String Align_final_bracket;
+	public static String Indent_using_tabs;
+	public static String Indent_using_spaces;
+	public static String Indentation_size;
+	public static String Indentation_size_tip;
+	public static String Clear_all_blank_lines_UI_;
+	public static String Preferred_markup_case_UI_;
+	public static String Tag_names__UI_;
+	public static String Tag_names_Upper_case_UI_;
+	public static String Tag_names_Lower_case_UI_;
+	public static String Attribute_names__UI_;
+	public static String Attribute_names_Upper_case_UI_;
+	public static String Attribute_names_Lower_case_UI_;
+	public static String Cleanup_UI_;
+	public static String Tag_name_case_for_HTML_UI_;
+	public static String Tag_name_case_As_is_UI_;
+	public static String Tag_name_case_Lower_UI_;
+	public static String Tag_name_case_Upper_UI_;
+	public static String Attribute_name_case_for_HTML_UI_;
+	public static String Attribute_name_case_As_is_UI_;
+	public static String Attribute_name_case_Lower_UI_;
+	public static String Attribute_name_case_Upper_UI_;
+	public static String Insert_required_attributes_UI_;
+	public static String Insert_missing_tags_UI_;
+	public static String Quote_attribute_values_UI_;
+	public static String Format_source_UI_;
+	public static String Convert_EOL_codes_UI_;
+	public static String EOL_Windows_UI;
+	public static String EOL_Unix_UI;
+	public static String EOL_Mac_UI;
+	public static String SyntaxColoringPage_0;
+	public static String SyntaxColoringPage_2;
+	public static String SyntaxColoringPage_3;
+	public static String SyntaxColoringPage_4;
+	public static String SyntaxColoringPage_5;
+	public static String SyntaxColoringPage_6;
+	
+	// below are possibly unused strings that may be deleted
+	public static String HTMLFilesPreferencePage_1;
+	public static String HTMLFilesPreferencePage_2;
+	public static String HTMLFilesPreferencePage_3;
+	// above are possibly unused strings that may be deleted
+	public static String EmptyFilePreferencePage_0;
+	public static String _UI_STRUCTURED_TEXT_EDITOR_PREFS_LINK;
+	
+	// HTML Typing Preferences
+	public static String HTMLTyping_Auto_Complete;
+	public static String HTMLTyping_Auto_Remove;
+	public static String HTMLTyping_Complete_Comments;
+	public static String HTMLTyping_Complete_End_Tags;
+	public static String HTMLTyping_Remove_End_Tags;
+	public static String HTMLTyping_Close_Strings;
+	public static String HTMLTyping_Close_Brackets;
+	
+	// below are the strings for the validation page
+	public static String Validation_description;
+	public static String Validation_Warning;
+	public static String Validation_Error;
+	public static String Validation_Ignore;
+	public static String Expandable_label_attributes;
+	public static String Expandable_label_elements;
+	public static String Expandable_label_document_type;
+	public static String Expandable_label_text;
+	public static String Expandable_label_comment;
+	public static String Expandable_label_cdata;
+	public static String Expandable_label_pi;
+	public static String Expandable_label_entity_ref;
+	
+	public static String HTMLValidationPreferencePage_0;
+	public static String HTMLValidationPreferencePage_1;
+	public static String HTMLValidationPreferencePage_10;
+	public static String HTMLValidationPreferencePage_11;
+	public static String HTMLValidationPreferencePage_12;
+	public static String HTMLValidationPreferencePage_13;
+	public static String HTMLValidationPreferencePage_14;
+	public static String HTMLValidationPreferencePage_15;
+	public static String HTMLValidationPreferencePage_16;
+	public static String HTMLValidationPreferencePage_17;
+	public static String HTMLValidationPreferencePage_18;
+	public static String HTMLValidationPreferencePage_19;
+	public static String HTMLValidationPreferencePage_2;
+	public static String HTMLValidationPreferencePage_20;
+	public static String HTMLValidationPreferencePage_21;
+	public static String HTMLValidationPreferencePage_22;
+	public static String HTMLValidationPreferencePage_23;
+	public static String HTMLValidationPreferencePage_24;
+	public static String HTMLValidationPreferencePage_25;
+	public static String HTMLValidationPreferencePage_26;
+	public static String HTMLValidationPreferencePage_27;
+	public static String HTMLValidationPreferencePage_28;
+	public static String HTMLValidationPreferencePage_29;
+	public static String HTMLValidationPreferencePage_3;
+	public static String HTMLValidationPreferencePage_30;
+	public static String HTMLValidationPreferencePage_31;
+	public static String HTMLValidationPreferencePage_32;
+	public static String HTMLValidationPreferencePage_33;
+	public static String HTMLValidationPreferencePage_34;
+	public static String HTMLValidationPreferencePage_35;
+	public static String HTMLValidationPreferencePage_4;
+	public static String HTMLValidationPreferencePage_5;
+	public static String HTMLValidationPreferencePage_6;
+	public static String HTMLValidationPreferencePage_7;
+	public static String HTMLValidationPreferencePage_8;
+	public static String HTMLValidationPreferencePage_9;
+	
+	// Validation
+	public static String Validation_Title;
+	public static String Validation_Workspace;
+	public static String Validation_Project;
+	public static String Validation_jobName;
+	
+	// Hyperlinks
+	public static String Hyperlink_line;
+	public static String Open;
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/HTMLUIPlugin.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/HTMLUIPlugin.java
new file mode 100644
index 0000000..6d04933
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/HTMLUIPlugin.java
@@ -0,0 +1,98 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal;
+
+import java.io.IOException;
+
+import org.eclipse.jface.text.templates.ContextTypeRegistry;
+import org.eclipse.jface.text.templates.persistence.TemplateStore;
+import org.eclipse.ui.editors.text.templates.ContributionContextTypeRegistry;
+import org.eclipse.ui.editors.text.templates.ContributionTemplateStore;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.eclipse.wst.html.ui.internal.preferences.HTMLUIPreferenceNames;
+import org.eclipse.wst.html.ui.internal.templates.TemplateContextTypeIdsHTML;
+import org.eclipse.wst.sse.ui.internal.provisional.registry.AdapterFactoryRegistry;
+import org.eclipse.wst.sse.ui.internal.provisional.registry.AdapterFactoryRegistryImpl;
+
+/**
+ * The main plugin class to be used in the desktop.
+ */
+public class HTMLUIPlugin extends AbstractUIPlugin {
+	public final static String ID = "org.eclipse.wst.html.ui"; //$NON-NLS-1$
+
+	protected static HTMLUIPlugin instance = null;	
+
+	/**
+	 * The template store for the html editor.
+	 */
+	private TemplateStore fTemplateStore;
+
+	/**
+	 * The template context type registry for the html editor.
+	 */
+	private ContextTypeRegistry fContextTypeRegistry;
+
+	public HTMLUIPlugin() {
+		super();
+		instance = this;
+	}
+
+	public static HTMLUIPlugin getDefault() {
+		return instance;
+	}
+
+	public synchronized static HTMLUIPlugin getInstance() {
+		return instance;
+	}
+
+	public AdapterFactoryRegistry getAdapterFactoryRegistry() {
+		return AdapterFactoryRegistryImpl.getInstance();
+
+	}
+
+	/**
+	 * Returns the template store for the html editor templates.
+	 * 
+	 * @return the template store for the html editor templates
+	 */
+	public TemplateStore getTemplateStore() {
+		if (fTemplateStore == null) {
+			fTemplateStore = new ContributionTemplateStore(getTemplateContextRegistry(), getPreferenceStore(), HTMLUIPreferenceNames.TEMPLATES_KEY);
+
+			try {
+				fTemplateStore.load();
+			} catch (IOException e) {
+				Logger.logException(e);
+			}
+		}
+		return fTemplateStore;
+	}
+
+	/**
+	 * Returns the template context type registry for the html plugin.
+	 * 
+	 * @return the template context type registry for the html plugin
+	 */
+	public ContextTypeRegistry getTemplateContextRegistry() {
+		if (fContextTypeRegistry == null) {
+			ContributionContextTypeRegistry registry = new ContributionContextTypeRegistry();
+			registry.addContextType(TemplateContextTypeIdsHTML.ALL);
+			registry.addContextType(TemplateContextTypeIdsHTML.NEW);
+			registry.addContextType(TemplateContextTypeIdsHTML.TAG);
+			registry.addContextType(TemplateContextTypeIdsHTML.ATTRIBUTE);
+			registry.addContextType(TemplateContextTypeIdsHTML.ATTRIBUTE_VALUE);
+
+			fContextTypeRegistry = registry;
+		}
+
+		return fContextTypeRegistry;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/HTMLUIPluginResources.properties b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/HTMLUIPluginResources.properties
new file mode 100644
index 0000000..3caf87c
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/HTMLUIPluginResources.properties
@@ -0,0 +1,180 @@
+###############################################################################
+# Copyright (c) 2004, 2009 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
+#     Benjamin Muskalla, b.muskalla@gmx.net - [158660] character entities should have their own syntax highlighting preference      
+###############################################################################
+## The following line is a sample HTML document.  Please translate only the following parts:
+## HTML Highlighting Preferences
+## we need a flaming logo
+Sample_HTML_doc=<!DOCTYPE html\n\tPUBLIC \"-//W3C/DTD/ HTML 4.01 Transitional//EN\"\n\t\"http://www.w3.org/TR/html4/loose.dtd\">\n<html>\n\t<head>\n\t\t<meta content=\"text/html\">\n\t\t<title>HTML Highlighting Preferences</title>\n\t</head>\n<body>\n\t<!--\n\t\twe need a flaming logo!\n\t-->\n\t<p>three&nbsp;&nbsp;&nbsp;spaces</p>\n</body>\n</html>
+
+HTMLFilesPreferencePage_0=Loading files
+#
+_UI_WIZARD_NEW_TITLE = New HTML File
+_UI_WIZARD_NEW_HEADING = HTML
+_UI_WIZARD_NEW_DESCRIPTION = Create a new HTML file.
+_ERROR_FILENAME_MUST_END_HTML = The file name must end in one of the following extensions {0}.
+_WARNING_FOLDER_MUST_BE_INSIDE_WEB_CONTENT = Files created outside of the Web Content folder will not be included in your deployed Web application. 
+ResourceGroup_nameExists = The same name already exists.
+NewHTMLTemplatesWizardPage_0=Select HTML Template
+NewHTMLTemplatesWizardPage_1=Select a template as initial content in the HTML page.
+NewHTMLTemplatesWizardPage_2=Name
+NewHTMLTemplatesWizardPage_3=Description
+NewHTMLTemplatesWizardPage_4=&Use HTML Template
+NewHTMLTemplatesWizardPage_5=&Preview:
+NewHTMLTemplatesWizardPage_6=Templates are 'New HTML' templates found in the <a>HTML Templates</a> preference page.
+NewHTMLTemplatesWizardPage_7=&Templates:
+#
+Creating_files_encoding=Creating files encoding preference
+# Copied from sse.ui
+CleanupDocument_label=Cleanup Document...
+CleanupDocument_tooltip=Cleanup Document
+CleanupDocument_description=Cleanup Document
+ToggleComment_label=Toggle Comment
+ToggleComment_tooltip=Toggle Comment
+ToggleComment_description=Toggle Comment
+AddBlockComment_label=Add Block Comment
+AddBlockComment_tooltip=Add Block Comment
+AddBlockComment_description=Add Block Comment
+RemoveBlockComment_label=Remove Block Comment
+RemoveBlockComment_tooltip=Remove Block Comment
+RemoveBlockComment_description=Remove Block Comment
+FindOccurrences_label=Occurrences in File
+Creating_files=Creating files
+Encoding_desc=The following encoding will apply:
+## HTML Source preference page
+Auto_Activation_UI_=Auto Activation
+Automatically_make_suggest_UI_=Automatically ma&ke suggestions
+Prompt_when_these_characte_UI_=P&rompt when these characters are inserted:
+Cycling_UI_=Cycling
+Formatting_UI_=Formatting
+Line_width__UI_=Line &width:
+Split_multiple_attributes=Split &multiple attributes each on a new line
+Align_final_bracket=&Align final bracket in multi-line element tags
+Indent_using_tabs=&Indent using tabs
+Indent_using_spaces=I&ndent using spaces
+Indentation_size=In&dentation size:
+Indentation_size_tip=Indentation size
+Clear_all_blank_lines_UI_=Clear all &blank lines
+Preferred_markup_case_UI_=Preferred markup case for content assist, and code generation
+Tag_names__UI_=Tag names:
+Tag_names_Upper_case_UI_=&Uppercase
+Tag_names_Lower_case_UI_=&Lowercase
+Attribute_names__UI_=Attribute names:
+Attribute_names_Upper_case_UI_=U&ppercase
+Attribute_names_Lower_case_UI_=L&owercase
+Cleanup_UI_=Cleanup
+Tag_name_case_for_HTML_UI_=Tag name case for HTML:
+Tag_name_case_As_is_UI_=&As-is
+Tag_name_case_Lower_UI_=&Lower
+Tag_name_case_Upper_UI_=&Upper
+Attribute_name_case_for_HTML_UI_=Attribute name case for HTML:
+Attribute_name_case_As_is_UI_=A&s-is
+Attribute_name_case_Lower_UI_=L&ower
+Attribute_name_case_Upper_UI_=U&pper
+Insert_required_attributes_UI_=Insert &required attributes
+Insert_missing_tags_UI_=&Insert missing tags
+Quote_attribute_values_UI_=&Quote attribute values
+Format_source_UI_=&Format source
+Convert_EOL_codes_UI_=Convert line &delimiters to
+EOL_Windows_UI=&Windows
+EOL_Unix_UI=U&NIX
+EOL_Mac_UI=&Mac
+
+# web content settings
+UI_Description_of_role_of_following_DOCTYPE=Use the following default document type when no DOCTYPE is declared in a file:
+UI_Default_HTML_DOCTYPE_ID___1=Document type:
+UI_Public_ID=Public ID:
+UI_System_ID=System ID:
+UI_none=none
+UI_CSS_profile___2=CSS profile:
+WebContentSettingsPropertyPage_0=The properties used that cannot or are not specified in web files.  The project setting is used if you specify "none."
+ProjectWebContentSettingsPropertyPage_0=These values are used when the corresponding properties are not specified within a web page.
+SyntaxColoringPage_0=Syntax Element:
+SyntaxColoringPage_2=Enable
+SyntaxColoringPage_3=&Bold
+SyntaxColoringPage_4=&Italic
+SyntaxColoringPage_5=&Strikethrough
+SyntaxColoringPage_6=&Underline
+# below are possibly unused strings that may be deleted
+HTMLFilesPreferencePage_1=Add this suffix (if not specified):
+HTMLFilesPreferencePage_2=Insert DOCTYPE declaration
+HTMLFilesPreferencePage_3=Insert GENERATOR with META tag
+EmptyFilePreferencePage_0=Expand the tree to edit preferences for a specific feature.
+_UI_STRUCTURED_TEXT_EDITOR_PREFS_LINK=HTML editing preferences.  Note that some preferences may be set on the <a>{0}</a> preference page.
+# above are possibly unused strings that may be deleted
+
+# HTML Typing Preference Page
+HTMLTyping_Auto_Complete=Automatically close
+HTMLTyping_Auto_Remove=Automatically remove
+HTMLTyping_Complete_Comments=&Comments
+HTMLTyping_Close_Strings=A&ttribute values
+HTMLTyping_Close_Brackets=(Parentheses) and [square] brac&kets
+HTMLTyping_Complete_End_Tags=&End tags
+HTMLTyping_Remove_End_Tags=E&nd tags when creating empty self-closing tags
+
+
+# Validation strings
+Validation_description=Select the severity level for the following validation problems:
+Validation_Warning=Warning
+Validation_Error=Error
+Validation_Ignore=Ignore
+Expandable_label_attributes=Attributes
+Expandable_label_elements=Elements
+Expandable_label_document_type=Document Type
+Expandable_label_text=Text Regions
+Expandable_label_comment=Comments
+Expandable_label_cdata=CDATA Sections
+Expandable_label_pi=Processing Instructions
+Expandable_label_entity_ref=Entity References
+
+HTMLValidationPreferencePage_0=Undefined attribute name:
+HTMLValidationPreferencePage_1=Undefined attribute value:
+HTMLValidationPreferencePage_10=Start-tag uses invalid case:
+HTMLValidationPreferencePage_11=End tag uses invalid case:
+HTMLValidationPreferencePage_12=Missing start tag:
+HTMLValidationPreferencePage_13=Missing end tag:
+HTMLValidationPreferencePage_14=Unnecessary end tag:
+HTMLValidationPreferencePage_15=Invalid directive:
+HTMLValidationPreferencePage_16=Invalid tag location:
+HTMLValidationPreferencePage_17=Duplicate tag:
+HTMLValidationPreferencePage_18=Coexistence:
+HTMLValidationPreferencePage_19=Unclosed start tag:
+HTMLValidationPreferencePage_2=Attribute name using wrong case character:
+HTMLValidationPreferencePage_20=Unclosed end tag:
+HTMLValidationPreferencePage_21=Invalid empty element tag:
+HTMLValidationPreferencePage_22=Duplicate DOCTYPE declaration:
+HTMLValidationPreferencePage_23=Invalid location:
+HTMLValidationPreferencePage_24=DOCTYPE declaration unclosed:
+HTMLValidationPreferencePage_25=Invalid text string:
+HTMLValidationPreferencePage_26=Invalid characters used in text string:
+HTMLValidationPreferencePage_27=Invalid location:
+HTMLValidationPreferencePage_28=Unclosed comment:
+HTMLValidationPreferencePage_29=Invalid location:
+HTMLValidationPreferencePage_3=Invalid attribute name:
+HTMLValidationPreferencePage_30=Unclosed CDATA section:
+HTMLValidationPreferencePage_31=Invalid location:
+HTMLValidationPreferencePage_32=Unclosed processing instruction:
+HTMLValidationPreferencePage_33=Invalid location:
+HTMLValidationPreferencePage_34=Unknown entity:
+HTMLValidationPreferencePage_4=Invalid attribute:
+HTMLValidationPreferencePage_5=Multiple values specified for an attribute:
+HTMLValidationPreferencePage_6=Attribute value using wrong case character:
+HTMLValidationPreferencePage_7=Unclosed attribute value:
+HTMLValidationPreferencePage_8=Unknown tag name:
+HTMLValidationPreferencePage_9=Invalid tag name:
+HTMLValidationPreferencePage_35=Attribute value refers to missing resource:
+
+Validation_Title=Validation Settings Changed
+Validation_Workspace=The validation settings have changed. A full validation is required for changes to take effect. Validate now?
+Validation_Project=The validation settings have changed. A validation of the project is required for changes to take effect. Validate the project now?
+Validation_jobName=Validating...
+
+Hyperlink_line={0}={1} : line {2}
+Open=Open ''{0}''
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/Logger.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/Logger.java
new file mode 100644
index 0000000..580f3fe
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/Logger.java
@@ -0,0 +1,160 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal;
+
+
+
+import com.ibm.icu.util.StringTokenizer;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.osgi.framework.Bundle;
+
+
+/**
+ * Small convenience class to log messages to plugin's log file and also, if
+ * desired, the console. This class should only be used by classes in this
+ * plugin. Other plugins should make their own copy, with appropriate ID.
+ */
+public class Logger {
+	private static final String PLUGIN_ID = "org.eclipse.wst.html.ui"; //$NON-NLS-1$
+	
+	public static final int ERROR = IStatus.ERROR; // 4
+	public static final int ERROR_DEBUG = 200 + ERROR;
+	public static final int INFO = IStatus.INFO; // 1
+	public static final int INFO_DEBUG = 200 + INFO;
+
+	public static final int OK = IStatus.OK; // 0
+
+	public static final int OK_DEBUG = 200 + OK;
+
+	private static final String TRACEFILTER_LOCATION = "/debug/tracefilter"; //$NON-NLS-1$
+	public static final int WARNING = IStatus.WARNING; // 2
+	public static final int WARNING_DEBUG = 200 + WARNING;
+
+	/**
+	 * Adds message to log.
+	 * 
+	 * @param level
+	 *            severity level of the message (OK, INFO, WARNING, ERROR,
+	 *            OK_DEBUG, INFO_DEBUG, WARNING_DEBUG, ERROR_DEBUG)
+	 * @param message
+	 *            text to add to the log
+	 * @param exception
+	 *            exception thrown
+	 */
+	protected static void _log(int level, String message, Throwable exception) {
+		if (level == OK_DEBUG || level == INFO_DEBUG || level == WARNING_DEBUG || level == ERROR_DEBUG) {
+			if (!isDebugging())
+				return;
+		}
+
+		int severity = IStatus.OK;
+		switch (level) {
+			case INFO_DEBUG :
+			case INFO :
+				severity = IStatus.INFO;
+				break;
+			case WARNING_DEBUG :
+			case WARNING :
+				severity = IStatus.WARNING;
+				break;
+			case ERROR_DEBUG :
+			case ERROR :
+				severity = IStatus.ERROR;
+		}
+		message = (message != null) ? message : "null"; //$NON-NLS-1$
+		Status statusObj = new Status(severity, PLUGIN_ID, severity, message, exception);
+		Bundle bundle = Platform.getBundle(PLUGIN_ID);
+		if (bundle != null) 
+			Platform.getLog(bundle).log(statusObj);
+	}
+
+	/**
+	 * Prints message to log if category matches /debug/tracefilter option.
+	 * 
+	 * @param message
+	 *            text to print
+	 * @param category
+	 *            category of the message, to be compared with
+	 *            /debug/tracefilter
+	 */
+	protected static void _trace(String category, String message, Throwable exception) {
+		if (isTracing(category)) {
+			message = (message != null) ? message : "null"; //$NON-NLS-1$
+			Status statusObj = new Status(IStatus.OK, PLUGIN_ID, IStatus.OK, message, exception);
+			Bundle bundle = Platform.getBundle(PLUGIN_ID);
+			if (bundle != null) 
+				Platform.getLog(bundle).log(statusObj);
+		}
+	}
+
+	/**
+	 * @return true if the platform is debugging
+	 */
+	public static boolean isDebugging() {
+		return Platform.inDebugMode();
+	}
+
+	/**
+	 * Determines if currently tracing a category
+	 * 
+	 * @param category
+	 * @return true if tracing category, false otherwise
+	 */
+	public static boolean isTracing(String category) {
+		if (!isDebugging())
+			return false;
+
+		String traceFilter = Platform.getDebugOption(PLUGIN_ID + TRACEFILTER_LOCATION);
+		if (traceFilter != null) {
+			StringTokenizer tokenizer = new StringTokenizer(traceFilter, ","); //$NON-NLS-1$
+			while (tokenizer.hasMoreTokens()) {
+				String cat = tokenizer.nextToken().trim();
+				if (category.equals(cat)) {
+					return true;
+				}
+			}
+		}
+		return false;
+	}
+
+	public static void log(int level, String message) {
+		_log(level, message, null);
+	}
+
+	public static void log(int level, String message, Throwable exception) {
+		_log(level, message, exception);
+	}
+
+	public static void logException(String message, Throwable exception) {
+		_log(ERROR, message, exception);
+	}
+
+	public static void logException(Throwable exception) {
+		_log(ERROR, exception.getMessage(), exception);
+	}
+
+	public static void trace(String category, String message) {
+		_trace(category, message, null);
+	}
+
+	public static void traceException(String category, String message, Throwable exception) {
+		_trace(category, message, exception);
+	}
+
+	public static void traceException(String category, Throwable exception) {
+		_trace(category, exception.getMessage(), exception);
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/autoedit/AutoEditStrategyForTabs.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/autoedit/AutoEditStrategyForTabs.java
new file mode 100644
index 0000000..bc89ee5
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/autoedit/AutoEditStrategyForTabs.java
@@ -0,0 +1,188 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 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 - Initial API and implementation
+ *   Jens Lukowski/Innoopract - initial renaming/restructuring
+ * 
+ *******************************************************************************/
+
+package org.eclipse.wst.html.ui.internal.autoedit;
+
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.ConfigurableLineTracker;
+import org.eclipse.jface.text.DocumentCommand;
+import org.eclipse.jface.text.IAutoEditStrategy;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ILineTracker;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.TextUtilities;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.ui.texteditor.ITextEditorExtension3;
+import org.eclipse.wst.html.core.internal.HTMLCorePlugin;
+import org.eclipse.wst.html.core.internal.preferences.HTMLCorePreferenceNames;
+import org.eclipse.wst.html.ui.internal.Logger;
+
+/**
+ * AutoEditStrategy to handle characters inserted when Tab key is pressed
+ */
+public class AutoEditStrategyForTabs implements IAutoEditStrategy {
+	private final String TAB_CHARACTER = "\t";	//$NON-NLS-1$
+	
+	public void customizeDocumentCommand(IDocument document, DocumentCommand command) {
+		// if not in smart insert mode just ignore
+		if (!isSmartInsertMode())
+			return;
+		
+		// spaces for tab character
+		if (command.length == 0 && command.text != null && command.text.length() > 0 && command.text.indexOf(TAB_CHARACTER) != -1)
+			smartInsertForTab(command, document);
+	}
+
+	/**
+	 * Insert spaces for tabs
+	 * 
+	 * @param command
+	 */
+	private void smartInsertForTab(DocumentCommand command, IDocument document) {
+		// tab key was pressed. now check preferences to see if need to insert
+		// spaces instead of tab
+		int indentationWidth = getIndentationWidth();
+		if (indentationWidth > -1) {
+			String originalText = command.text;
+			StringBuffer newText = new StringBuffer(originalText);
+
+			// determine where in line this command begins
+			int lineOffset = -1;
+			try {
+				IRegion lineInfo = document.getLineInformationOfOffset(command.offset);
+				lineOffset = command.offset - lineInfo.getOffset();
+			} catch (BadLocationException e) {
+				Logger.log(Logger.WARNING_DEBUG, e.getMessage(), e);
+			}
+
+			ILineTracker lineTracker = getLineTracker(document, originalText);
+
+			int startIndex = 0;
+			int index = newText.indexOf(TAB_CHARACTER);
+			while (index != -1) {
+				String indent = getIndentString(indentationWidth, lineOffset, lineTracker, index);
+
+				// replace \t character with spaces
+				newText.replace(index, index + 1, indent);
+				if (lineTracker != null) {
+					try {
+						lineTracker.replace(index, 1, indent);
+					} catch (BadLocationException e) {
+						// if something goes wrong with replacing text, just
+						// reset to current string
+						lineTracker.set(newText.toString());
+						Logger.log(Logger.WARNING_DEBUG, e.getMessage(), e);
+					}
+				}
+
+				startIndex = index + indent.length();
+				index = newText.indexOf(TAB_CHARACTER, startIndex);
+			}
+			command.text = newText.toString();
+		}
+	}
+
+	/**
+	 * Calculate number of spaces for next tab stop
+	 */
+	private String getIndentString(int indentationWidth, int lineOffset, ILineTracker lineTracker, int index) {
+		int indentSize = indentationWidth;
+		int offsetInLine = -1;
+		if (lineTracker != null) {
+			try {
+				IRegion lineInfo = lineTracker.getLineInformationOfOffset(index);
+				if (lineInfo.getOffset() == 0 && lineOffset > -1)
+					offsetInLine = lineOffset + index;
+				else
+					offsetInLine = index - lineInfo.getOffset();
+			} catch (BadLocationException e) {
+				Logger.log(Logger.WARNING_DEBUG, e.getMessage(), e);
+			}
+		} else {
+			if (lineOffset > -1) {
+				offsetInLine = lineOffset + index;
+			}
+		}
+		if (offsetInLine > -1 && indentationWidth > 0) {
+			int remainder = offsetInLine % indentationWidth;
+			indentSize = indentationWidth - remainder;
+		}
+
+		StringBuffer indent = new StringBuffer();
+		for (int i = 0; i < indentSize; i++)
+			indent.append(' ');
+		return indent.toString();
+	}
+
+	/**
+	 * Set up a line tracker for text within command if text is multi-line
+	 */
+	private ILineTracker getLineTracker(IDocument document, String originalText) {
+		ConfigurableLineTracker lineTracker = null;
+		int[] delims = TextUtilities.indexOf(document.getLegalLineDelimiters(), originalText, 0);
+		if (delims[0] != -1 || delims[1] != -1) {
+			lineTracker = new ConfigurableLineTracker(document.getLegalLineDelimiters());
+			lineTracker.set(originalText);
+		}
+		return lineTracker;
+	}
+	
+	/**
+	 * Return true if active editor is in smart insert mode, false otherwise
+	 * 
+	 * @return
+	 */
+	private boolean isSmartInsertMode() {
+		boolean isSmartInsertMode = false;
+		
+		ITextEditor textEditor = null;
+		IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+		if (window != null) {
+			IWorkbenchPage page = window.getActivePage();
+			if (page != null) {
+				IEditorPart editor = page.getActiveEditor();
+				if (editor != null) {
+					if (editor instanceof ITextEditor)
+						textEditor = (ITextEditor)editor;
+					else
+						textEditor = (ITextEditor)editor.getAdapter(ITextEditor.class);
+				}
+			}
+		}
+		
+		// check if smart insert mode
+		if (textEditor instanceof ITextEditorExtension3 && ((ITextEditorExtension3) textEditor).getInsertMode() == ITextEditorExtension3.SMART_INSERT)
+			isSmartInsertMode = true;
+		return isSmartInsertMode;
+	}
+	
+	/**
+	 * Returns indentation width if using spaces for indentation, -1 otherwise
+	 * 
+	 * @return
+	 */
+	private int getIndentationWidth() {
+		int width = -1;
+
+		Preferences preferences = HTMLCorePlugin.getDefault().getPluginPreferences();
+		if (HTMLCorePreferenceNames.SPACE.equals(preferences.getString(HTMLCorePreferenceNames.INDENTATION_CHAR)))
+			width = preferences.getInt(HTMLCorePreferenceNames.INDENTATION_SIZE);
+
+		return width;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/autoedit/StructuredAutoEditStrategyHTML.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/autoedit/StructuredAutoEditStrategyHTML.java
new file mode 100644
index 0000000..57e49df
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/autoedit/StructuredAutoEditStrategyHTML.java
@@ -0,0 +1,349 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.autoedit;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.DocumentCommand;
+import org.eclipse.jface.text.IAutoEditStrategy;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.ui.texteditor.ITextEditorExtension3;
+import org.eclipse.wst.html.core.internal.contentmodel.HTMLElementDeclaration;
+import org.eclipse.wst.html.core.internal.document.HTMLDocumentTypeEntry;
+import org.eclipse.wst.html.core.internal.document.HTMLDocumentTypeRegistry;
+import org.eclipse.wst.html.core.internal.provisional.HTMLCMProperties;
+import org.eclipse.wst.html.ui.internal.HTMLUIPlugin;
+import org.eclipse.wst.html.ui.internal.preferences.HTMLUIPreferenceNames;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.modelquery.ModelQueryUtil;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+import org.eclipse.wst.xml.ui.internal.Logger;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+/**
+ * Automatically inserts closing comment tag or end tag when appropriate.
+ */
+public class StructuredAutoEditStrategyHTML implements IAutoEditStrategy {
+	/*
+	 * NOTE: copies of this class exists in
+	 * org.eclipse.wst.xml.ui.internal.autoedit
+	 * org.eclipse.wst.html.ui.internal.autoedit
+	 */
+	public void customizeDocumentCommand(IDocument document, DocumentCommand command) {
+		Object textEditor = getActiveTextEditor();
+		if (!(textEditor instanceof ITextEditorExtension3 && ((ITextEditorExtension3) textEditor).getInsertMode() == ITextEditorExtension3.SMART_INSERT))
+			return;
+
+		IStructuredModel model = null;
+		try {
+			model = StructuredModelManager.getModelManager().getExistingModelForRead(document);
+			if (model != null) {
+				if (command.text != null) {
+					smartInsertCloseElement(command, document, model);
+					smartInsertForComment(command, document, model);
+					smartInsertForEndTag(command, document, model);
+					smartRemoveEndTag(command, document, model);
+				}
+			}
+		}
+		finally {
+			if (model != null)
+				model.releaseFromRead();
+		}
+	}
+
+	private boolean isPreferenceEnabled(String key) {
+		return (key != null && HTMLUIPlugin.getDefault().getPreferenceStore().getBoolean(key));
+	}
+	
+	private boolean isCommentNode(IDOMNode node) {
+		return (node != null && node instanceof IDOMElement && ((IDOMElement) node).isCommentTag());
+	}
+
+	private boolean isDocumentNode(IDOMNode node) {
+		return (node != null && node.getNodeType() == Node.DOCUMENT_NODE);
+	}
+	
+	/**
+	 * Attempts to clean up an end-tag if a start-tag is converted into an empty-element
+	 * tag (e.g., <node />) and the original element was empty.
+	 * 
+	 * @param command the document command describing the change
+	 * @param document the document that will be changed
+	 * @param model the model based on the document
+	 */
+	private void smartRemoveEndTag(DocumentCommand command, IDocument document, IStructuredModel model) {
+		try {
+			// An opening tag is now a self-terminated end-tag
+			if ("/".equals(command.text) && ">".equals(document.get(command.offset, 1)) && command.length == 0 && isPreferenceEnabled(HTMLUIPreferenceNames.TYPING_REMOVE_END_TAGS)) { //$NON-NLS-1$ //$NON-NLS-2$
+				IDOMNode node = (IDOMNode) model.getIndexedRegion(command.offset);
+				if (node != null && !node.hasChildNodes()) {
+					IStructuredDocumentRegion region = node.getFirstStructuredDocumentRegion();
+					if(region.getFirstRegion().getType() == DOMRegionContext.XML_TAG_OPEN && command.offset <= region.getEnd()) {
+						
+						/* if the region before the command offset is a an attribute value region
+						 * check to see if it has both and opening and closing quote
+						 */
+						ITextRegion prevTextRegion = region.getRegionAtCharacterOffset(command.offset-1);
+						boolean inUnclosedAttValueRegion = false;
+						if(prevTextRegion.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
+							//get the text of the attribute value region
+							String prevText = region.getText(prevTextRegion);
+							inUnclosedAttValueRegion = (prevText.startsWith("'") && ((prevText.length() == 1) || !prevText.endsWith("'"))) ||
+								(prevText.startsWith("\"") && ((prevText.length() == 1) || !prevText.endsWith("\"")));
+						} 
+					
+						//if command offset is in an unclosed attribute value region then done remove the end tag
+						if(!inUnclosedAttValueRegion) {
+							region = node.getEndStructuredDocumentRegion();
+							if (region != null && region.isEnded()) {
+								document.replace(region.getStartOffset(), region.getLength(), ""); //$NON-NLS-1$
+							}
+						}
+					}
+				}
+			}
+		}
+		catch (BadLocationException e) {
+			Logger.logException(e);
+		}
+	}
+
+	private void smartInsertForComment(DocumentCommand command, IDocument document, IStructuredModel model) {
+		try {
+			if (command.text.equals("-") && document.getLength() >= 3 && document.get(command.offset - 3, 3).equals("<!-") && isPreferenceEnabled(HTMLUIPreferenceNames.TYPING_COMPLETE_COMMENTS)) { //$NON-NLS-1$ //$NON-NLS-2$
+				command.text += "  -->"; //$NON-NLS-1$
+				command.shiftsCaret = false;
+				command.caretOffset = command.offset + 2;
+				command.doit = false;
+			}
+		}
+		catch (BadLocationException e) {
+			Logger.logException(e);
+		}
+
+	}
+	
+	/**
+	 * Attempts to insert the end tag when completing a start-tag with the '&gt;' character.
+	 * 
+	 * @param command
+	 * @param document
+	 * @param model
+	 */
+	private void smartInsertCloseElement(DocumentCommand command, IDocument document, IStructuredModel model) {
+		try {
+			// Check terminating start tag, but ignore empty-element tags
+			if (command.text.equals(">") && document.getLength() > 0 && document.getChar(command.offset - 1) != '/' && isPreferenceEnabled(HTMLUIPreferenceNames.TYPING_COMPLETE_ELEMENTS)) { //$NON-NLS-1$
+				IDOMNode node = (IDOMNode) model.getIndexedRegion(command.offset - 1);
+				boolean isClosedByParent = false;
+				// Only insert an end-tag if necessary. Because of the way the document is parsed, it is possible for a child tag with the same
+				// name as an ancestor to be paired with the end-tag of an ancestor, so the ancestors must be checked for an unclosed tag.
+				if (node != null && node.getNodeType() == Node.ELEMENT_NODE && (!node.isClosed() || (isClosedByParent = hasUnclosedAncestor(node)))) {
+					IStructuredDocumentRegion region = node.getEndStructuredDocumentRegion();
+					if (region != null && region.getRegions().size() > 0 && region.getRegions().get(0).getType() == DOMRegionContext.XML_END_TAG_OPEN && !isClosedByParent)
+						return;
+					CMElementDeclaration decl = getCMElementDeclaration(node);
+					// If it's XHTML, always generate the end tag
+					if (isXHTML(node) || shouldGenerateEndTag(decl)) {
+						command.text += "</" + getElementName(node, command.offset) + ">"; //$NON-NLS-1$ //$NON-NLS-2$
+						command.shiftsCaret = false;
+						command.caretOffset = command.offset + 1;
+					}
+				}
+				
+			}
+		} catch (BadLocationException e) {
+			e.printStackTrace();
+		}
+	}
+
+	/**
+	 * Get the element name that will be created by closing the start tag. Defaults
+	 * to the node's nodeName.
+	 * @param node the node that is being edited
+	 * @param offset the offset in the document where the start tag is closed
+	 * @return The element name of the tag
+	 */
+	private String getElementName(IDOMNode node, int offset) {
+		String name = null;
+		
+		IStructuredDocumentRegion region = node.getFirstStructuredDocumentRegion();
+		ITextRegion textRegion = region.getRegionAtCharacterOffset(offset);
+		if (textRegion != null && textRegion.getType() == DOMRegionContext.XML_TAG_NAME) {
+			int nameStart = region.getStartOffset(textRegion);
+			String regionText = region.getText(textRegion);
+			int length = offset - nameStart;
+			if (length <= regionText.length())
+				name = regionText.substring(0, length);
+		}
+		
+		// Default to the node name
+		if (name == null)
+			name = node.getNodeName();
+		return name;
+	}
+
+	private void smartInsertForEndTag(DocumentCommand command, IDocument document, IStructuredModel model) {
+		try {
+			if (command.text.equals("/") && document.getLength() >= 1 && document.get(command.offset - 1, 1).equals("<") && isPreferenceEnabled(HTMLUIPreferenceNames.TYPING_COMPLETE_END_TAGS)) { //$NON-NLS-1$ //$NON-NLS-2$
+				IDOMNode parentNode = (IDOMNode) ((IDOMNode) model.getIndexedRegion(command.offset - 1)).getParentNode();
+				if (isCommentNode(parentNode)) {
+					// loop and find non comment node parent
+					while (parentNode != null && isCommentNode(parentNode)) {
+						parentNode = (IDOMNode) parentNode.getParentNode();
+					}
+				}
+
+				if (!isDocumentNode(parentNode)) {
+					// only add end tag if one does not already exist or if
+					// add '/' does not create one already
+					IStructuredDocumentRegion endTagStructuredDocumentRegion = parentNode.getEndStructuredDocumentRegion();
+					IDOMNode ancestor = parentNode;
+					boolean smartInsertForEnd = false;
+					if(endTagStructuredDocumentRegion != null) {
+						// Look for ancestors by the same name that are missing end tags
+						while((ancestor = (IDOMNode) ancestor.getParentNode()) != null) {
+							if(ancestor.getEndStructuredDocumentRegion() == null && parentNode.getNodeName().equals(ancestor.getNodeName())) {
+								smartInsertForEnd = true;
+								break;
+							}
+						}
+					}
+					if (endTagStructuredDocumentRegion == null || smartInsertForEnd) {
+						StringBuffer toAdd = new StringBuffer(parentNode.getNodeName());
+						if (toAdd.length() > 0) {
+							toAdd.append(">"); //$NON-NLS-1$
+							String suffix = toAdd.toString();
+							if ((document.getLength() < command.offset + suffix.length()) || (!suffix.equals(document.get(command.offset, suffix.length())))) {
+								command.text += suffix;
+							}
+						}
+					}
+				}
+			}
+		}
+		catch (BadLocationException e) {
+			Logger.logException(e);
+		}
+	}
+
+	/**
+	 * Checks if <code>node</code> has an unclosed ancestor by the same name
+	 * 
+	 * @param node the node to check
+	 * @return true if <code>node</code> has an unclosed parent with the same node name
+	 */
+	private boolean hasUnclosedAncestor(IDOMNode node) {
+		IDOMNode parent = (IDOMNode) node.getParentNode();
+		while (parent != null && parent.getNodeType() != Node.DOCUMENT_NODE && parent.getNodeName().equals(node.getNodeName())) {
+			if (!parent.isClosed())
+				return true;
+			parent = (IDOMNode) parent.getParentNode();
+		}
+		return false;
+	}
+
+	/**
+	 * Based on the content model, determine if an end tag should be generated
+	 * @param elementDecl the content model element declaration
+	 * @return true if the end tag should be generated; false otherwise.
+	 */
+	private boolean shouldGenerateEndTag(CMElementDeclaration elementDecl) {
+		if (elementDecl == null)
+			return false;
+		if (elementDecl instanceof HTMLElementDeclaration) {
+			if (((Boolean) elementDecl.getProperty(HTMLCMProperties.IS_JSP)).booleanValue()) {
+				if (elementDecl.getContentType() == CMElementDeclaration.EMPTY)
+					return false;
+			}
+			else {
+				String ommission = (String) elementDecl.getProperty(HTMLCMProperties.OMIT_TYPE);
+				if (ommission.equals(HTMLCMProperties.Values.OMIT_END) || ommission.equals(HTMLCMProperties.Values.OMIT_END_DEFAULT) || ommission.equals(HTMLCMProperties.Values.OMIT_END_MUST)) {
+					return false;
+				}
+			}
+		}
+
+		if (elementDecl.getContentType() == CMElementDeclaration.EMPTY)
+			return false;
+		return true;
+	}
+
+	private CMElementDeclaration getCMElementDeclaration(Node node) {
+		CMElementDeclaration result = null;
+		if (node.getNodeType() == Node.ELEMENT_NODE) {
+			ModelQuery modelQuery = ModelQueryUtil.getModelQuery(node.getOwnerDocument());
+			if (modelQuery != null) {
+				result = modelQuery.getCMElementDeclaration((Element) node);
+			}
+		}
+		return result;
+	}
+
+	/**
+	 * Is the node part of an XHTML document
+	 * @param node
+	 * @return
+	 */
+	private boolean isXHTML(Node node) {
+		Document doc = node.getOwnerDocument();
+		if (!(doc instanceof IDOMDocument))
+			return false;
+		String typeid = ((IDOMDocument) doc).getDocumentTypeId();
+		if (typeid != null) {
+			HTMLDocumentTypeEntry entry = HTMLDocumentTypeRegistry.getInstance().getEntry(typeid);
+			return (entry != null && entry.isXMLType());
+		}
+		return false;
+	}
+	
+	/**
+	 * Return the active text editor if possible, otherwise the active editor
+	 * part.
+	 * 
+	 * @return Object
+	 */
+	private Object getActiveTextEditor() {
+		IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+		if (window != null) {
+			IWorkbenchPage page = window.getActivePage();
+			if (page != null) {
+				IEditorPart editor = page.getActiveEditor();
+				if (editor != null) {
+					if (editor instanceof ITextEditor)
+						return editor;
+					ITextEditor textEditor = (ITextEditor) editor.getAdapter(ITextEditor.class);
+					if (textEditor != null)
+						return textEditor;
+					return editor;
+				}
+			}
+		}
+		return null;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentassist/CustomTemplateProposal.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentassist/CustomTemplateProposal.java
new file mode 100644
index 0000000..6bb0f20
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentassist/CustomTemplateProposal.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.contentassist;
+
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.templates.Template;
+import org.eclipse.jface.text.templates.TemplateContext;
+import org.eclipse.jface.text.templates.TemplateProposal;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.wst.sse.core.utils.StringUtils;
+import org.eclipse.wst.sse.ui.internal.contentassist.IRelevanceCompletionProposal;
+
+/**
+ * Purpose of this class is to make the additional proposal info into content
+ * fit for an HTML viewer (by escaping characters)
+ */
+class CustomTemplateProposal extends TemplateProposal implements IRelevanceCompletionProposal {
+	// copies of this class exist in:
+	// org.eclipse.jst.jsp.ui.internal.contentassist
+	// org.eclipse.wst.html.ui.internal.contentassist
+	// org.eclipse.wst.xml.ui.internal.contentassist
+
+	public CustomTemplateProposal(Template template, TemplateContext context, IRegion region, Image image, int relevance) {
+		super(template, context, region, image, relevance);
+	}
+
+	public String getAdditionalProposalInfo() {
+		String additionalInfo = super.getAdditionalProposalInfo();
+		return StringUtils.convertToHTMLContent(additionalInfo);
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentassist/HTMLContentAssistProcessor.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentassist/HTMLContentAssistProcessor.java
new file mode 100644
index 0000000..63c2ced
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentassist/HTMLContentAssistProcessor.java
@@ -0,0 +1,511 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.contentassist;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.wst.css.ui.internal.contentassist.CSSContentAssistProcessor;
+import org.eclipse.wst.html.core.internal.contentmodel.HTMLCMDocument;
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.html.core.internal.provisional.HTMLCMProperties;
+import org.eclipse.wst.html.core.text.IHTMLPartitions;
+import org.eclipse.wst.html.ui.StructuredTextViewerConfigurationHTML;
+import org.eclipse.wst.html.ui.internal.HTMLUIPlugin;
+import org.eclipse.wst.html.ui.internal.editor.HTMLEditorPluginImageHelper;
+import org.eclipse.wst.html.ui.internal.editor.HTMLEditorPluginImages;
+import org.eclipse.wst.html.ui.internal.preferences.HTMLUIPreferenceNames;
+import org.eclipse.wst.html.ui.internal.templates.TemplateContextTypeIdsHTML;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.IModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapterFactory;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
+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.ITextRegionList;
+import org.eclipse.wst.sse.ui.internal.IReleasable;
+import org.eclipse.wst.sse.ui.internal.contentassist.ContentAssistUtils;
+import org.eclipse.wst.sse.ui.internal.contentassist.CustomCompletionProposal;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.modelquery.ModelQueryUtil;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
+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 org.eclipse.wst.xml.core.internal.ssemodelquery.ModelQueryAdapter;
+import org.eclipse.wst.xml.ui.internal.contentassist.AbstractContentAssistProcessor;
+import org.eclipse.wst.xml.ui.internal.contentassist.ContentAssistRequest;
+import org.eclipse.wst.xml.ui.internal.contentassist.XMLContentModelGenerator;
+import org.eclipse.wst.xml.ui.internal.contentassist.XMLRelevanceConstants;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+/**
+ * @deprecated This class is no longer used locally and will be removed in the future
+ * @see HTMLStructuredContentAssistProcessor
+ */
+public class HTMLContentAssistProcessor extends AbstractContentAssistProcessor implements IPropertyChangeListener {
+	private INodeAdapterFactory factoryForCSS = null;
+	protected IPreferenceStore fPreferenceStore = null;
+	protected boolean isXHTML = false;
+	private HTMLTemplateCompletionProcessor fTemplateProcessor = null;
+	private IContentAssistProcessor fJSContentAssistProcessor = null;
+	private List fTemplateContexts = new ArrayList();
+
+	public HTMLContentAssistProcessor() {
+
+		super();
+	}
+
+	protected void addAttributeNameProposals(ContentAssistRequest contentAssistRequest) {
+		addTemplates(contentAssistRequest, TemplateContextTypeIdsHTML.ATTRIBUTE);
+		super.addAttributeNameProposals(contentAssistRequest);
+	}
+
+	protected void addAttributeValueProposals(ContentAssistRequest contentAssistRequest) {
+		addTemplates(contentAssistRequest, TemplateContextTypeIdsHTML.ATTRIBUTE_VALUE);
+		super.addAttributeValueProposals(contentAssistRequest);
+	}
+
+	/**
+	 * Add the proposals for a completely empty document
+	 */
+	protected void addEmptyDocumentProposals(ContentAssistRequest contentAssistRequest) {
+		addTemplates(contentAssistRequest, TemplateContextTypeIdsHTML.NEW);
+	}
+
+	protected void addPCDATAProposal(String nodeName, ContentAssistRequest contentAssistRequest) {
+		if (isXHTML)
+			super.addPCDATAProposal(nodeName, contentAssistRequest);
+	}
+
+	protected void addStartDocumentProposals(ContentAssistRequest contentAssistRequest) {
+		if (isXHTML)
+			addEmptyDocumentProposals(contentAssistRequest);
+	}
+
+	protected void addTagInsertionProposals(ContentAssistRequest contentAssistRequest, int childPosition) {
+		addTemplates(contentAssistRequest, TemplateContextTypeIdsHTML.TAG);
+		super.addTagInsertionProposals(contentAssistRequest, childPosition);
+	}
+
+	/**
+	 * Adds templates to the list of proposals
+	 * 
+	 * @param contentAssistRequest
+	 * @param context
+	 */
+	private void addTemplates(ContentAssistRequest contentAssistRequest, String context) {
+		addTemplates(contentAssistRequest, context, contentAssistRequest.getReplacementBeginPosition());
+	}
+	
+	/**
+	 * Adds templates to the list of proposals
+	 * 
+	 * @param contentAssistRequest
+	 * @param context
+	 * @param startOffset
+	 */
+	private void addTemplates(ContentAssistRequest contentAssistRequest, String context, int startOffset) {
+		if (contentAssistRequest == null)
+			return;
+		
+		// if already adding template proposals for a certain context type, do
+		// not add again
+		if (!fTemplateContexts.contains(context)) {
+			fTemplateContexts.add(context);
+			boolean useProposalList = !contentAssistRequest.shouldSeparate();
+
+			if (getTemplateCompletionProcessor() != null) {
+				getTemplateCompletionProcessor().setContextType(context);
+				ICompletionProposal[] proposals = getTemplateCompletionProcessor().computeCompletionProposals(fTextViewer, startOffset);
+				for (int i = 0; i < proposals.length; ++i) {
+					if (useProposalList)
+						contentAssistRequest.addProposal(proposals[i]);
+					else
+						contentAssistRequest.addMacro(proposals[i]);
+				}
+			}
+		}
+	}
+
+	protected boolean beginsWith(String aString, String prefix) {
+		if (aString == null || prefix == null || prefix.length() == 0)
+			return true;
+		int minimumLength = Math.min(prefix.length(), aString.length());
+		String beginning = aString.substring(0, minimumLength);
+		return beginning.equalsIgnoreCase(prefix);
+	}
+
+	protected ContentAssistRequest computeCompletionProposals(int documentPosition, String matchString, ITextRegion completionRegion, IDOMNode treeNode, IDOMNode xmlnode) {
+		ContentAssistRequest request = super.computeCompletionProposals(documentPosition, matchString, completionRegion, treeNode, xmlnode);
+		// bug115927 use original document position for all/any region templates
+		addTemplates(request, TemplateContextTypeIdsHTML.ALL, documentPosition);
+		return request;
+	}
+
+	/**
+	 * Return a list of proposed code completions based on the specified
+	 * location within the document that corresponds to the current cursor
+	 * position within the text-editor control.
+	 * 
+	 * @param documentPosition
+	 *            a location within the document
+	 * @return an array of code-assist items
+	 */
+	public ICompletionProposal[] computeCompletionProposals(ITextViewer textViewer, int documentPosition) {
+		fTemplateContexts.clear();
+
+		IndexedRegion treeNode = ContentAssistUtils.getNodeAt(textViewer, documentPosition);
+		IDOMNode node = (IDOMNode) treeNode;
+		setErrorMessage(null);
+
+		// check if it's in a comment node
+		IStructuredDocument structuredDocument = (IStructuredDocument) textViewer.getDocument();
+		IStructuredDocumentRegion fn = structuredDocument.getRegionAtCharacterOffset(documentPosition);
+		if (fn != null && fn.getType() == DOMRegionContext.XML_COMMENT_TEXT && documentPosition != fn.getStartOffset()) {
+			return new ICompletionProposal[0];
+		}
+
+		// CMVC 242695
+		// if it's a </script> tag, bounce back to JS ca processor...
+		if (fn != null && fn.getType() == DOMRegionContext.XML_TAG_NAME && documentPosition == fn.getStartOffset()) {
+			ITextRegionList v = fn.getRegions();
+			if (v.size() > 1) {
+				// determine that it's a close tag
+				if ((v.get(0)).getType() == DOMRegionContext.XML_END_TAG_OPEN) {
+					Iterator it = v.iterator();
+					ITextRegion region = null;
+					// search for script tag name
+					while (it.hasNext()) {
+						region = (ITextRegion) it.next();
+						if (fn.getText(region).equalsIgnoreCase("script")) { //$NON-NLS-1$
+							IContentAssistProcessor jsProcessor = getJSContentAssistProcessor();
+							if (jsProcessor != null) {
+								return jsProcessor.computeCompletionProposals(textViewer, documentPosition);
+							}
+							return new ICompletionProposal[0];
+						}
+					}
+				}
+			}
+		}
+
+		isXHTML = getXHTML(node);
+
+		fGenerator = null; // force reload of content generator
+
+		// handle blank HTML document case
+		if (treeNode == null || isViewerEmpty(textViewer)) {
+			// cursor is at the EOF
+			ICompletionProposal htmlTagProposal = getHTMLTagProposal(textViewer, documentPosition);
+			ICompletionProposal[] superResults = super.computeCompletionProposals(textViewer, documentPosition);
+			if (superResults != null && superResults.length > 0 && htmlTagProposal != null) {
+				ICompletionProposal[] blankHTMLDocResults = new ICompletionProposal[superResults.length + 1];
+				blankHTMLDocResults[0] = htmlTagProposal;
+				System.arraycopy(superResults, 0, blankHTMLDocResults, 1, superResults.length);
+				return blankHTMLDocResults;
+			}
+		}
+
+		if (node != null && node.getNodeType() == Node.ELEMENT_NODE) {
+
+			// check embedded CSS proposals at the beginning of the STYLE end
+			// tag
+			Element element = (Element) node;
+			String tagName = element.getTagName();
+			if (tagName != null && tagName.equalsIgnoreCase(HTML40Namespace.ATTR_NAME_STYLE)) {//$NON-NLS-1$
+				IStructuredDocumentRegion endStructuredDocumentRegion = node.getEndStructuredDocumentRegion();
+				if (endStructuredDocumentRegion != null && endStructuredDocumentRegion.getStartOffset() == documentPosition) {
+					IStructuredDocumentRegion startStructuredDocumentRegion = node.getStartStructuredDocumentRegion();
+					if (startStructuredDocumentRegion != null) {
+						int offset = startStructuredDocumentRegion.getEndOffset();
+						int pos = documentPosition - offset;
+						ICompletionProposal[] proposals = getCSSProposals(textViewer, pos, node, offset, (char) 0);
+						if (proposals != null)
+							return proposals;
+					}
+				}
+			}
+
+			// check inline CSS proposals
+			// need to find attr region from sd region
+			IStructuredDocumentRegion sdRegion = ContentAssistUtils.getStructuredDocumentRegion(textViewer, documentPosition);
+			Iterator regions = sdRegion.getRegions().iterator();
+			ITextRegion styleNameRegion = null;
+			ITextRegion styleValueRegion = null;
+			while (regions.hasNext()) {
+				styleNameRegion = (ITextRegion) regions.next();
+				if (styleNameRegion.getType().equals(DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) && sdRegion.getText(styleNameRegion).equalsIgnoreCase(HTML40Namespace.ATTR_NAME_STYLE)) { //$NON-NLS-1$
+					// the next region should be "="
+					if (regions.hasNext()) {
+						regions.next(); // skip the "="
+						// next region should be attr value region
+						if (regions.hasNext()) {
+							styleValueRegion = (ITextRegion) regions.next();
+							break;
+						}
+					}
+				}
+			}
+
+			if (styleValueRegion != null) {
+				int offset = sdRegion.getStartOffset(styleValueRegion);
+				int end = sdRegion.getTextEndOffset(styleValueRegion);
+				if (documentPosition >= offset && documentPosition <= end) {
+					boolean askCSS = true;
+					char quote = (char) 0;
+					String text = sdRegion.getText(styleValueRegion);
+					int length = (text != null ? text.length() : 0);
+					if (length > 0) {
+						char firstChar = text.charAt(0);
+						if (firstChar == '"' || firstChar == '\'') {
+							if (documentPosition == offset) {
+								// before quote
+								askCSS = false;
+							}
+							else {
+								offset++;
+								quote = firstChar;
+							}
+						}
+						if (documentPosition == end) {
+							if (length > 1 && text.charAt(length - 1) == quote) {
+								// after quote
+								askCSS = false;
+							}
+						}
+					}
+					if (askCSS) {
+						int pos = documentPosition - offset;
+						ICompletionProposal[] proposals = getCSSProposals(textViewer, pos, node, offset, quote);
+						if (proposals != null)
+							return proposals;
+					}
+				}
+			}
+		}
+
+		return super.computeCompletionProposals(textViewer, documentPosition);
+	}
+
+	/**
+	 * Returns true if there is no text or it's all white space, otherwise
+	 * returns false
+	 * 
+	 * @param treeNode
+	 * @param textViewer
+	 * @return boolean
+	 */
+	private boolean isViewerEmpty(ITextViewer textViewer) {
+		boolean isEmpty = false;
+		String text = textViewer.getTextWidget().getText();
+		if (text == null || (text != null && text.trim().equals(""))) //$NON-NLS-1$
+			isEmpty = true;
+		return isEmpty;
+	}
+
+	/**
+	 * @return ICompletionProposal
+	 */
+	private ICompletionProposal getHTMLTagProposal(ITextViewer viewer, int documentPosition) {
+		IModelManager mm = StructuredModelManager.getModelManager();
+		IStructuredModel model = null;
+		ICompletionProposal result = null;
+		try {
+			if (mm != null) {
+				model = mm.getExistingModelForRead(viewer.getDocument());
+
+				if (model != null) {
+					IDOMDocument doc = ((IDOMModel) model).getDocument();
+
+					ModelQuery mq = ModelQueryUtil.getModelQuery(doc);
+					if (mq != null) {
+
+						// XHTML requires lowercase tagname for lookup
+						CMDocument correspondingCMDocument = mq.getCorrespondingCMDocument(doc);
+						if (correspondingCMDocument != null) {
+							CMElementDeclaration htmlDecl = (CMElementDeclaration) correspondingCMDocument.getElements().getNamedItem(HTML40Namespace.ElementName.HTML.toLowerCase());
+							if (htmlDecl != null) {
+								StringBuffer proposedTextBuffer = new StringBuffer();
+								getContentGenerator().generateTag(doc, htmlDecl, proposedTextBuffer);
+
+								String proposedText = proposedTextBuffer.toString();
+								String requiredName = getContentGenerator().getRequiredName(doc, htmlDecl);
+
+								CustomCompletionProposal proposal = new CustomCompletionProposal(proposedText, documentPosition,
+								/* start pos */
+								0, /* replace length */
+								requiredName.length() + 2, /*
+															 * cursor position
+															 * after
+															 * (relavtive to
+															 * start)
+															 */
+								HTMLEditorPluginImageHelper.getInstance().getImage(HTMLEditorPluginImages.IMG_OBJ_TAG_GENERIC), requiredName, null, null, XMLRelevanceConstants.R_TAG_NAME);
+								result = proposal;
+							}
+						}
+					}
+				}
+			}
+		}
+		finally {
+			if (model != null)
+				model.releaseFromRead();
+		}
+		return result;
+	}
+
+	/**
+	 * @see AbstractContentAssistProcessor#getContentGenerator()
+	 */
+	public XMLContentModelGenerator getContentGenerator() {
+		if (fGenerator == null) {
+			if (isXHTML)
+				fGenerator = XHTMLMinimalContentModelGenerator.getInstance();
+			else
+				fGenerator = HTMLMinimalContentModelGenerator.getInstance();
+		}
+		return fGenerator;
+	}
+
+	protected ICompletionProposal[] getCSSProposals(ITextViewer viewer, int pos, IDOMNode element, int offset, char quote) {
+
+		CSSContentAssistProcessor cssProcessor = new CSSContentAssistProcessor();
+		cssProcessor.setDocumentOffset(offset);
+		cssProcessor.setQuoteCharOfStyleAttribute(quote);
+
+		return cssProcessor.computeCompletionProposals(viewer, pos);
+	}
+
+	protected String getEmptyTagCloseString() {
+		if (isXHTML)
+			return " />"; //$NON-NLS-1$
+		return ">"; //$NON-NLS-1$
+	}
+	
+	private IContentAssistProcessor getJSContentAssistProcessor() {
+		if (fJSContentAssistProcessor == null) {
+			fJSContentAssistProcessor = new StructuredTextViewerConfigurationHTML().getContentAssistant(null).getContentAssistProcessor(IHTMLPartitions.SCRIPT);
+		}
+		return fJSContentAssistProcessor;
+	}
+
+	private HTMLTemplateCompletionProcessor getTemplateCompletionProcessor() {
+		if (fTemplateProcessor == null) {
+			fTemplateProcessor = new HTMLTemplateCompletionProcessor();
+		}
+		return fTemplateProcessor;
+	}
+
+	/**
+	 * Determine if this Document is an XHTML Document. Oprates solely off of
+	 * the Document Type declaration
+	 */
+	protected boolean getXHTML(Node node) {
+		if (node == null)
+			return false;
+
+		Document doc = null;
+		if (node.getNodeType() != Node.DOCUMENT_NODE)
+			doc = node.getOwnerDocument();
+		else
+			doc = ((Document) node);
+
+		if (doc instanceof IDOMDocument)
+			return ((IDOMDocument) doc).isXMLType();
+
+
+		if (doc instanceof INodeNotifier) {
+			ModelQueryAdapter adapter = (ModelQueryAdapter) ((INodeNotifier) doc).getAdapterFor(ModelQueryAdapter.class);
+			CMDocument cmdoc = null;
+			if (adapter != null && adapter.getModelQuery() != null)
+				cmdoc = adapter.getModelQuery().getCorrespondingCMDocument(doc);
+			if (cmdoc != null) {
+				// treat as XHTML unless we've got the in-code HTML content
+				// model
+				if (cmdoc instanceof HTMLCMDocument)
+					return false;
+				if (cmdoc.supports(HTMLCMProperties.IS_XHTML))
+					return Boolean.TRUE.equals(cmdoc.getProperty(HTMLCMProperties.IS_XHTML));
+			}
+		}
+		// this should never be reached
+		DocumentType docType = doc.getDoctype();
+		return docType != null && docType.getPublicId() != null && docType.getPublicId().indexOf("-//W3C//DTD XHTML ") == 0; //$NON-NLS-1$
+	}
+
+	protected void init() {
+		getPreferenceStore().addPropertyChangeListener(this);
+		reinit();
+	}
+
+	protected void reinit() {
+		String key = HTMLUIPreferenceNames.AUTO_PROPOSE;
+		boolean doAuto = getPreferenceStore().getBoolean(key);
+		if (doAuto) {
+			key = HTMLUIPreferenceNames.AUTO_PROPOSE_CODE;
+			completionProposalAutoActivationCharacters = getPreferenceStore().getString(key).toCharArray();
+		}
+		else {
+			completionProposalAutoActivationCharacters = null;
+		}
+	}
+
+	public void release() {
+		if (factoryForCSS != null) {
+			factoryForCSS.release();
+		}
+		if (fJSContentAssistProcessor instanceof IReleasable) {
+			((IReleasable)fJSContentAssistProcessor).release();
+		}
+		getPreferenceStore().removePropertyChangeListener(this);
+		super.release();
+	}
+
+	protected boolean stringsEqual(String a, String b) {
+		return a.equalsIgnoreCase(b);
+	}
+
+	public void propertyChange(PropertyChangeEvent event) {
+		String property = event.getProperty();
+
+		if (property.compareTo(HTMLUIPreferenceNames.AUTO_PROPOSE) == 0 || property.compareTo(HTMLUIPreferenceNames.AUTO_PROPOSE_CODE) == 0) {
+			reinit();
+		}
+	}
+
+	protected IPreferenceStore getPreferenceStore() {
+		if (fPreferenceStore == null)
+			fPreferenceStore = HTMLUIPlugin.getDefault().getPreferenceStore();
+
+		return fPreferenceStore;
+	}
+
+	public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int documentPosition, IndexedRegion indexedNode, ITextRegion region) {
+		return computeCompletionProposals(viewer, documentPosition);
+	}
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentassist/HTMLMinimalContentModelGenerator.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentassist/HTMLMinimalContentModelGenerator.java
new file mode 100644
index 0000000..0bdd85f
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentassist/HTMLMinimalContentModelGenerator.java
@@ -0,0 +1,134 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.contentassist;
+
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.wst.html.core.internal.HTMLCorePlugin;
+import org.eclipse.wst.html.core.internal.contentmodel.HTMLElementDeclaration;
+import org.eclipse.wst.html.core.internal.preferences.HTMLCorePreferenceNames;
+import org.eclipse.wst.html.core.internal.provisional.HTMLCMProperties;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.ui.internal.contentassist.XMLContentModelGenerator;
+import org.w3c.dom.Node;
+
+public class HTMLMinimalContentModelGenerator extends XMLContentModelGenerator {
+
+	private static HTMLMinimalContentModelGenerator instance = null;
+	protected int fTagCase;
+	protected int fAttrCase;
+
+	/**
+	 * HTMLMinimalContentModelGenerator constructor comment.
+	 */
+	private HTMLMinimalContentModelGenerator() {
+		super();
+	}
+
+	private void init() {
+		String qualifier = HTMLCorePlugin.getDefault().getBundle().getSymbolicName();
+		fTagCase = Platform.getPreferencesService().getInt(qualifier, HTMLCorePreferenceNames.TAG_NAME_CASE, 0, null);
+		fAttrCase = Platform.getPreferencesService().getInt(qualifier, HTMLCorePreferenceNames.ATTR_NAME_CASE, 0, null);
+	}
+
+	protected void generateEndTag(String tagName, Node parentNode, CMElementDeclaration elementDecl, StringBuffer buffer) {
+		if (elementDecl == null)
+			return;
+		if (elementDecl instanceof HTMLElementDeclaration) {
+			if (((Boolean) elementDecl.getProperty(HTMLCMProperties.IS_JSP)).booleanValue()) {
+				if (elementDecl.getContentType() == CMElementDeclaration.EMPTY)
+					return;
+			}
+			else {
+				String ommission = (String) elementDecl.getProperty(HTMLCMProperties.OMIT_TYPE);
+				if (ommission.equals(HTMLCMProperties.Values.OMIT_END) || ommission.equals(HTMLCMProperties.Values.OMIT_END_DEFAULT) || ommission.equals(HTMLCMProperties.Values.OMIT_END_MUST)) {
+					return;
+				}
+			}
+		}
+
+		if (elementDecl.getContentType() == CMElementDeclaration.EMPTY)
+			return;
+		buffer.append("</" + tagName + ">"); //$NON-NLS-2$//$NON-NLS-1$
+		return;
+	}
+
+	private boolean shouldIgnoreCase(CMNode cmnode) {
+		if (!cmnode.supports(HTMLCMProperties.SHOULD_IGNORE_CASE))
+			return false;
+		return ((Boolean) cmnode.getProperty(HTMLCMProperties.SHOULD_IGNORE_CASE)).booleanValue();
+	}
+
+	public String getRequiredName(Node ownerNode, CMNode cmnode) {
+		String name = super.getRequiredName(ownerNode, cmnode);
+		// don't change the case unless we're certain it is meaningless
+		if (shouldIgnoreCase(cmnode)) {
+			int caseVal = -1;
+			if (cmnode.getNodeType() == CMNode.ELEMENT_DECLARATION)
+				caseVal = fTagCase;
+			else if (cmnode.getNodeType() == CMNode.ATTRIBUTE_DECLARATION)
+				caseVal = fAttrCase;
+			switch (caseVal) {
+				case HTMLCorePreferenceNames.LOWER :
+					{
+						name = name.toLowerCase();
+					}
+					break;
+				case HTMLCorePreferenceNames.UPPER :
+					{
+						name = name.toUpperCase();
+					}
+					break;
+			}
+		}
+		return name;
+	}
+
+	public String getStartTagClose(Node parentNode, CMElementDeclaration elementDecl) {
+		String other = getOtherClose(parentNode);
+		if (other != null)
+			return other;
+		if (elementDecl == null)
+			return ">"; //$NON-NLS-1$
+		if (elementDecl instanceof HTMLElementDeclaration) {
+			if (((Boolean) elementDecl.getProperty(HTMLCMProperties.IS_JSP)).booleanValue()) {
+				if (elementDecl.getContentType() == CMElementDeclaration.EMPTY)
+					return "/>"; //$NON-NLS-1$
+			}
+			else {
+				String ommission = (String) elementDecl.getProperty(HTMLCMProperties.OMIT_TYPE);
+				if (ommission.equals(HTMLCMProperties.Values.OMIT_END) || ommission.equals(HTMLCMProperties.Values.OMIT_END_DEFAULT) || ommission.equals(HTMLCMProperties.Values.OMIT_END_MUST)) {
+					return ">"; //$NON-NLS-1$
+				}
+			}
+		}
+		
+		//if not an html element and empty, assume start tag needs to be closed
+		else if (elementDecl.getContentType() == CMElementDeclaration.EMPTY) {
+			return "/>"; //$NON-NLS-1$
+		}
+
+		return ">"; //$NON-NLS-1$
+	}
+
+	/**
+	 * Gets the instance.
+	 * @return Returns a HTMLMinimalContentModelGenerator
+	 */
+	public synchronized static HTMLMinimalContentModelGenerator getInstance() {
+		if (instance == null)
+			instance = new HTMLMinimalContentModelGenerator();
+		instance.init();
+		return instance;
+	}
+
+
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentassist/HTMLStructuredContentAssistProcessor.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentassist/HTMLStructuredContentAssistProcessor.java
new file mode 100644
index 0000000..994c111
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentassist/HTMLStructuredContentAssistProcessor.java
@@ -0,0 +1,91 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.contentassist;
+
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.contentassist.ContentAssistant;
+import org.eclipse.jface.text.contentassist.IContextInformationValidator;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.wst.html.ui.internal.HTMLUIPlugin;
+import org.eclipse.wst.html.ui.internal.preferences.HTMLUIPreferenceNames;
+import org.eclipse.wst.sse.ui.contentassist.StructuredContentAssistProcessor;
+import org.eclipse.wst.xml.ui.internal.contentassist.AttributeContextInformationPresenter;
+
+/**
+ * <p>Implementation of {@link StructuredContentAssistProcessor} for HTML documents</p>
+ * 
+ * <p>This implementation will react to user preference changes for auto activation
+ * characters for HTML pages</p>
+ */
+public class HTMLStructuredContentAssistProcessor extends StructuredContentAssistProcessor {
+	/** the auto activation characters for this processor, set by user preference */
+	private char[] fCompletionProposalAutoActivationCharacters;
+
+	/** the context information validator for this processor */
+	private IContextInformationValidator fContextInformationValidator;
+	
+	/**
+	 * <p>Constructor</p>
+	 * 
+	 * @param assistant {@link ContentAssistant} to use
+	 * @param partitionTypeID the partition type this processor is for
+	 * @param viewer {@link ITextViewer} this processor is acting in
+	 */
+	public HTMLStructuredContentAssistProcessor(ContentAssistant assistant,
+			String partitionTypeID, ITextViewer viewer) {
+		
+		super(assistant, partitionTypeID, viewer, HTMLUIPlugin.getDefault().getPreferenceStore());
+		getAutoActivationCharacterPreferences();
+	}
+	
+	/**
+	 * @see org.eclipse.wst.sse.ui.contentassist.StructuredContentAssistProcessor#getContextInformationValidator()
+	 */
+	public IContextInformationValidator getContextInformationValidator() {
+		if (this.fContextInformationValidator == null) {
+			this.fContextInformationValidator = new AttributeContextInformationPresenter();
+		}
+		return this.fContextInformationValidator;
+	}
+	
+	/**
+	 * @see org.eclipse.wst.sse.ui.contentassist.StructuredContentAssistProcessor#getCompletionProposalAutoActivationCharacters()
+	 */
+	public char[] getCompletionProposalAutoActivationCharacters() {
+		return super.getCompletionProposalAutoActivationCharacters() != null ? super.getCompletionProposalAutoActivationCharacters() : this.fCompletionProposalAutoActivationCharacters;
+	}
+	
+	/**
+	 * @see org.eclipse.wst.sse.ui.contentassist.StructuredContentAssistProcessor#propertyChange(
+	 * 	org.eclipse.jface.util.PropertyChangeEvent)
+	 */
+	public void propertyChange(PropertyChangeEvent event) {
+		if(event.getProperty().equals(HTMLUIPreferenceNames.AUTO_PROPOSE) ||
+				event.getProperty().equals(HTMLUIPreferenceNames.AUTO_PROPOSE_CODE)) {
+			getAutoActivationCharacterPreferences();
+		}
+	}
+	
+	/**
+	 * <p>Gets the auto activation character user preferences and stores them for later use</p>
+	 */
+	private void getAutoActivationCharacterPreferences() {
+		String key = HTMLUIPreferenceNames.AUTO_PROPOSE;
+		boolean doAuto = getPreferenceStore().getBoolean(key);
+		if (doAuto) {
+			key = HTMLUIPreferenceNames.AUTO_PROPOSE_CODE;
+			this.fCompletionProposalAutoActivationCharacters = getPreferenceStore().getString(key).toCharArray();
+		}
+		else {
+			this.fCompletionProposalAutoActivationCharacters = null;
+		}
+	}
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentassist/HTMLTagsCompletionProposalComputer.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentassist/HTMLTagsCompletionProposalComputer.java
new file mode 100644
index 0000000..3265f58
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentassist/HTMLTagsCompletionProposalComputer.java
@@ -0,0 +1,338 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.contentassist;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.jface.text.contentassist.IContextInformationValidator;
+import org.eclipse.wst.html.core.internal.contentmodel.HTMLAttributeDeclaration;
+import org.eclipse.wst.html.core.internal.contentmodel.HTMLCMDocument;
+import org.eclipse.wst.html.core.internal.contentmodel.HTMLPropertyDeclaration;
+import org.eclipse.wst.html.core.internal.document.HTMLDocumentTypeEntry;
+import org.eclipse.wst.html.core.internal.document.HTMLDocumentTypeRegistry;
+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
+import org.eclipse.wst.html.core.internal.provisional.HTMLCMProperties;
+import org.eclipse.wst.html.ui.internal.HTMLUIMessages;
+import org.eclipse.wst.html.ui.internal.editor.HTMLEditorPluginImageHelper;
+import org.eclipse.wst.html.ui.internal.editor.HTMLEditorPluginImages;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
+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.ui.contentassist.CompletionProposalInvocationContext;
+import org.eclipse.wst.sse.ui.internal.contentassist.ContentAssistUtils;
+import org.eclipse.wst.sse.ui.internal.contentassist.CustomCompletionProposal;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.contentmodel.basic.CMElementDeclarationImpl;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.modelquery.ModelQueryUtil;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
+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 org.eclipse.wst.xml.core.internal.ssemodelquery.ModelQueryAdapter;
+import org.eclipse.wst.xml.ui.internal.contentassist.AbstractXMLModelQueryCompletionProposalComputer;
+import org.eclipse.wst.xml.ui.internal.contentassist.AttributeContextInformationPresenter;
+import org.eclipse.wst.xml.ui.internal.contentassist.AttributeContextInformationProvider;
+import org.eclipse.wst.xml.ui.internal.contentassist.ContentAssistRequest;
+import org.eclipse.wst.xml.ui.internal.contentassist.XMLContentModelGenerator;
+import org.eclipse.wst.xml.ui.internal.contentassist.XMLRelevanceConstants;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImageHelper;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImages;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Node;
+
+/**
+ * <p>{@link AbstractXMLModelQueryCompletionProposalComputer} for HTML tag proposals</p>
+ */
+public class HTMLTagsCompletionProposalComputer extends
+		AbstractXMLModelQueryCompletionProposalComputer {
+	
+	/** <code>true</code> if the document the proposal request is on is XHTML */
+	protected boolean isXHTML = false;
+	
+	/** the context information validator for this computer */
+	private IContextInformationValidator fContextInformationValidator;
+	
+	/**
+	 * <p>Default constructor</p>
+	 */
+	public HTMLTagsCompletionProposalComputer() {
+		this.fContextInformationValidator = null;
+	}
+	
+	/**
+	 * <p>Determine if the document is XHTML or not, then compute the proposals</p>
+	 * 
+	 * @see org.eclipse.wst.xml.ui.internal.contentassist.AbstractXMLCompletionProposalComputer#computeCompletionProposals(org.eclipse.wst.sse.ui.contentassist.CompletionProposalInvocationContext, org.eclipse.core.runtime.IProgressMonitor)
+	 */
+	public List computeCompletionProposals(
+			CompletionProposalInvocationContext context,
+			IProgressMonitor monitor) {
+		
+		//determine if the content is XHTML or not
+		IndexedRegion treeNode = ContentAssistUtils.getNodeAt(context.getViewer(),
+				context.getInvocationOffset());
+		IDOMNode node = (IDOMNode) treeNode;
+		boolean isXHTMLNode = isXHTMLNode(node);
+		if(this.isXHTML != isXHTMLNode) {
+			this.isXHTML = isXHTMLNode;
+		}
+		
+		//compute the completion proposals
+		return super.computeCompletionProposals(context, monitor);
+	}
+	
+	/**
+	 * @see org.eclipse.wst.xml.ui.internal.contentassist.AbstractXMLCompletionProposalComputer#computeContextInformation(org.eclipse.wst.sse.ui.contentassist.CompletionProposalInvocationContext, org.eclipse.core.runtime.IProgressMonitor)
+	 */
+	public List computeContextInformation(
+			CompletionProposalInvocationContext context,
+			IProgressMonitor monitor) {
+		
+		AttributeContextInformationProvider attributeInfoProvider =
+			new AttributeContextInformationProvider((IStructuredDocument)context.getDocument(),
+					(AttributeContextInformationPresenter) getContextInformationValidator());
+		return Arrays.asList(attributeInfoProvider.getAttributeInformation(context.getInvocationOffset()));
+	}
+	
+	/**
+	 * <p>Dependent on if the document is XHTML or not</p>
+	 * 
+	 * @see org.eclipse.wst.xml.ui.internal.contentassist.AbstractXMLModelQueryCompletionProposalComputer#getContentGenerator()
+	 */
+	protected XMLContentModelGenerator getContentGenerator() {
+		if (isXHTML) {
+			return XHTMLMinimalContentModelGenerator.getInstance();
+		} else {
+			return HTMLMinimalContentModelGenerator.getInstance();
+		}
+	}
+	
+	/**
+	 * <p>Filter out all {@link CMNode}s except those specific to HTML documents</p>
+	 * 
+	 * @see org.eclipse.wst.xml.ui.internal.contentassist.AbstractXMLModelQueryCompletionProposalComputer#validModelQueryNode(org.eclipse.wst.xml.core.internal.contentmodel.CMNode)
+	 */
+	protected boolean validModelQueryNode(CMNode node) {
+		boolean isValid = false;
+		Object cmdoc = node.getProperty("CMDocument"); //$NON-NLS-1$
+		if (cmdoc instanceof CMNode) {
+			String name = ((CMNode) cmdoc).getNodeName();
+			isValid = name != null && name.endsWith(".dtd") && name.indexOf("html") != -1; //$NON-NLS-1$ //$NON-NLS-2$
+		} else if (node.supports(HTMLAttributeDeclaration.IS_HTML)) {
+			Boolean isHTML = (Boolean) node.getProperty(HTMLAttributeDeclaration.IS_HTML);
+			isValid = isHTML == null || isHTML.booleanValue();
+		} else if(node instanceof HTMLPropertyDeclaration) {
+			HTMLPropertyDeclaration propDec = (HTMLPropertyDeclaration)node;
+			isValid = !propDec.isJSP();
+		} else if (node instanceof CMAttributeDeclaration || node instanceof CMElementDeclarationImpl) {
+			isValid = true;
+		} else if(node instanceof CMElementDeclaration) {
+			Boolean isXHTML = ((Boolean)node.getProperty(HTMLCMProperties.IS_XHTML));
+			isValid = isXHTML != null && isXHTML.booleanValue();
+		}
+
+		// Do not propose obsolete tags, regardless
+		if (isValid && node.supports(HTMLCMProperties.IS_OBSOLETE)) {
+			Boolean isObsolete = ((Boolean) node.getProperty(HTMLCMProperties.IS_OBSOLETE));
+			isValid = !(isObsolete != null && isObsolete.booleanValue());
+		}
+
+		return isValid;
+	}
+	
+	/**
+	 * @see org.eclipse.wst.xml.ui.internal.contentassist.AbstractXMLModelQueryCompletionProposalComputer#addEmptyDocumentProposals(org.eclipse.wst.xml.ui.internal.contentassist.ContentAssistRequest, org.eclipse.wst.sse.ui.contentassist.CompletionProposalInvocationContext)
+	 */
+	protected void addEmptyDocumentProposals(
+			ContentAssistRequest contentAssistRequest,
+			CompletionProposalInvocationContext context) {
+		
+		addHTMLTagProposal(contentAssistRequest, context);
+	}
+	
+	/**
+	 * @see org.eclipse.wst.xml.ui.internal.contentassist.AbstractXMLModelQueryCompletionProposalComputer#addStartDocumentProposals(org.eclipse.wst.xml.ui.internal.contentassist.ContentAssistRequest, org.eclipse.wst.sse.ui.contentassist.CompletionProposalInvocationContext)
+	 */
+	protected void addStartDocumentProposals(
+			ContentAssistRequest contentAssistRequest,
+			CompletionProposalInvocationContext context) {
+		
+		//determine if XMLPI is first element
+		Node aNode = contentAssistRequest.getNode();
+		Document owningDocument = aNode.getOwnerDocument();
+		Node first = owningDocument.getFirstChild();
+		boolean xmlpiIsFirstElement = ((first != null) && (first.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE));
+		
+		//if there is an XMLPI then XHTML doctype, else HTML doctype
+		if (xmlpiIsFirstElement && (owningDocument.getDoctype() == null) &&
+				isCursorAfterXMLPI(contentAssistRequest)) {
+			
+			addDocTypeProposal(contentAssistRequest, true);
+		} else {
+			addDocTypeProposal(contentAssistRequest,  false);
+		}
+	}
+	
+	/**
+	 * 
+	 * @param contentAssistRequest
+	 * @param isXHTML
+	 */
+	private void addDocTypeProposal(ContentAssistRequest contentAssistRequest, boolean isXHTML) {
+		// if a DocumentElement exists, use that for the root Element name
+		String rootname = "unspecified"; //$NON-NLS-1$
+		if (contentAssistRequest.getNode().getOwnerDocument().getDocumentElement() != null) {
+			rootname = contentAssistRequest.getNode().getOwnerDocument().getDocumentElement().getNodeName();
+		}
+		
+		//decide which entry to use
+		HTMLDocumentTypeEntry entry;
+		if(isXHTML) {
+			entry = HTMLDocumentTypeRegistry.getInstance().getXHTMLDefaultEntry();
+		} else {
+			entry = HTMLDocumentTypeRegistry.getInstance().getDefaultEntry();
+		}
+
+		//create the content assist string and proposal
+		String proposedText = "<!DOCTYPE " + rootname + " PUBLIC \"" + //$NON-NLS-1$ //$NON-NLS-2$
+				entry.getPublicId() + "\" \"" + entry.getSystemId() + "\">"; //$NON-NLS-1$ //$NON-NLS-2$
+		ICompletionProposal proposal = new CustomCompletionProposal(
+				proposedText, contentAssistRequest.getReplacementBeginPosition(),
+				contentAssistRequest.getReplacementLength(), 10,
+				XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_DOCTYPE),
+				entry.getDisplayName() + " " + HTMLUIMessages.Expandable_label_document_type, //$NON-NLS-1$ 
+				null, null, XMLRelevanceConstants.R_DOCTYPE);
+		contentAssistRequest.addProposal(proposal);
+	}
+	
+	/**
+	 * <p>adds HTML tag proposal for empty document</p>
+	 * 
+	 * @param contentAssistRequest request to add proposal too
+	 * @param context context of the completion request
+	 */
+	private void addHTMLTagProposal(ContentAssistRequest contentAssistRequest, CompletionProposalInvocationContext context) {
+		IStructuredModel model = null;
+		try {
+			if(context.getDocument() instanceof IStructuredDocument) {
+				model = StructuredModelManager.getModelManager().getModelForRead((IStructuredDocument)context.getDocument());
+			}
+			if (model != null) {
+				IDOMDocument doc = ((IDOMModel) model).getDocument();
+
+				ModelQuery mq = ModelQueryUtil.getModelQuery(doc);
+				if (mq != null) {
+
+					// XHTML requires lowercase tagname for lookup
+					CMDocument correspondingCMDocument = mq.getCorrespondingCMDocument(doc);
+					if (correspondingCMDocument != null) {
+						CMElementDeclaration htmlDecl = (CMElementDeclaration) correspondingCMDocument.getElements().getNamedItem(HTML40Namespace.ElementName.HTML.toLowerCase());
+						if (htmlDecl != null) {
+							StringBuffer proposedTextBuffer = new StringBuffer();
+							getContentGenerator().generateTag(doc, htmlDecl, proposedTextBuffer);
+
+							String proposedText = proposedTextBuffer.toString();
+							String requiredName = getContentGenerator().getRequiredName(doc, htmlDecl);
+							
+							IStructuredDocumentRegion region = contentAssistRequest.getDocumentRegion();
+							if (region != null) {
+								if (region.getFirstRegion() != null && 
+										region.getFirstRegion().getType().equals(DOMRegionContext.XML_TAG_OPEN)) {
+									//in order to differentiate between content assist on 
+									//completely empty document and the one with xml open tag
+									proposedText = proposedText.substring(1);
+								}
+							}
+							if (!beginsWith(proposedText, contentAssistRequest.getMatchString())) {
+								return;
+							}
+							int cursorAdjustment = getCursorPositionForProposedText(proposedText);
+							CustomCompletionProposal proposal = new CustomCompletionProposal(
+									proposedText, contentAssistRequest.getReplacementBeginPosition(),
+									contentAssistRequest.getReplacementLength(), cursorAdjustment, 
+									HTMLEditorPluginImageHelper.getInstance().getImage(HTMLEditorPluginImages.IMG_OBJ_TAG_GENERIC),
+									requiredName, null, null, XMLRelevanceConstants.R_TAG_NAME);
+							contentAssistRequest.addProposal(proposal);
+						}
+					}
+				}
+			}
+		}
+		finally {
+			if (model != null)
+				model.releaseFromRead();
+		}
+	}
+	
+	/**
+	 * Determine if this Document is an XHTML Document. Operates solely off of
+	 * the Document Type declaration
+	 */
+	private static boolean isXHTMLNode(Node node) {
+		if (node == null) {
+			return false;
+		}
+
+		Document doc = null;
+		if (node.getNodeType() != Node.DOCUMENT_NODE)
+			doc = node.getOwnerDocument();
+		else
+			doc = ((Document) node);
+
+		if (doc instanceof IDOMDocument) {
+			return ((IDOMDocument) doc).isXMLType();
+		}
+
+		if (doc instanceof INodeNotifier) {
+			ModelQueryAdapter adapter = (ModelQueryAdapter) ((INodeNotifier) doc).getAdapterFor(ModelQueryAdapter.class);
+			CMDocument cmdoc = null;
+			if (adapter != null && adapter.getModelQuery() != null)
+				cmdoc = adapter.getModelQuery().getCorrespondingCMDocument(doc);
+			if (cmdoc != null) {
+				// treat as XHTML unless we've got the in-code HTML content
+				// model
+				if (cmdoc instanceof HTMLCMDocument)
+					return false;
+				if (cmdoc.supports(HTMLCMProperties.IS_XHTML))
+					return Boolean.TRUE.equals(cmdoc.getProperty(HTMLCMProperties.IS_XHTML));
+			}
+		}
+		// this should never be reached
+		DocumentType docType = doc.getDoctype();
+		return docType != null && docType.getPublicId() != null && docType.getPublicId().indexOf("-//W3C//DTD XHTML ") == 0; //$NON-NLS-1$
+	}
+	
+	/**
+	 * Returns a validator used to determine when displayed context
+	 * information should be dismissed. May only return <code>null</code> if
+	 * the processor is incapable of computing context information.
+	 * 
+	 * a context information validator, or <code>null</code> if the
+	 * processor is incapable of computing context information
+	 */
+	private IContextInformationValidator getContextInformationValidator() {
+		if (fContextInformationValidator == null) {
+			fContextInformationValidator = new AttributeContextInformationPresenter();
+		}
+		return fContextInformationValidator;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentassist/HTMLTemplateCompletionProcessor.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentassist/HTMLTemplateCompletionProcessor.java
new file mode 100644
index 0000000..25d9a43
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentassist/HTMLTemplateCompletionProcessor.java
@@ -0,0 +1,160 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.contentassist;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.jface.text.templates.ContextTypeRegistry;
+import org.eclipse.jface.text.templates.Template;
+import org.eclipse.jface.text.templates.TemplateCompletionProcessor;
+import org.eclipse.jface.text.templates.TemplateContext;
+import org.eclipse.jface.text.templates.TemplateContextType;
+import org.eclipse.jface.text.templates.TemplateException;
+import org.eclipse.jface.text.templates.TemplateProposal;
+import org.eclipse.jface.text.templates.persistence.TemplateStore;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.wst.html.ui.internal.HTMLUIPlugin;
+import org.eclipse.wst.html.ui.internal.editor.HTMLEditorPluginImageHelper;
+import org.eclipse.wst.html.ui.internal.editor.HTMLEditorPluginImages;
+
+
+/**
+ * <p>Completion computer for HTML templates</p>
+ */
+public class HTMLTemplateCompletionProcessor extends TemplateCompletionProcessor {
+	private static final class ProposalComparator implements Comparator {
+		public int compare(Object o1, Object o2) {
+			return ((TemplateProposal) o2).getRelevance() - ((TemplateProposal) o1).getRelevance();
+		}
+	}
+
+	private static final Comparator fgProposalComparator = new ProposalComparator();
+	private String fContextTypeId = null;
+
+	/*
+	 * Copied from super class except instead of calling createContext(viewer,
+	 * region) call createContext(viewer, region, offset) instead
+	 */
+	public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int offset) {
+
+		ITextSelection selection = (ITextSelection) viewer.getSelectionProvider().getSelection();
+
+		// adjust offset to end of normalized selection
+		if (selection.getOffset() == offset)
+			offset = selection.getOffset() + selection.getLength();
+
+		String prefix = extractPrefix(viewer, offset);
+		Region region = new Region(offset - prefix.length(), prefix.length());
+		TemplateContext context = createContext(viewer, region, offset);
+		if (context == null)
+			return new ICompletionProposal[0];
+		// name of the selection variables {line, word}_selection
+		context.setVariable("selection", selection.getText()); //$NON-NLS-1$
+
+		Template[] templates = getTemplates(context.getContextType().getId());
+
+		List matches = new ArrayList();
+		for (int i = 0; i < templates.length; i++) {
+			Template template = templates[i];
+			try {
+				context.getContextType().validate(template.getPattern());
+			}
+			catch (TemplateException e) {
+				continue;
+			}
+			if (template.matches(prefix, context.getContextType().getId()))
+				matches.add(createProposal(template, context, (IRegion) region, getRelevance(template, prefix)));
+		}
+
+		Collections.sort(matches, fgProposalComparator);
+
+		return (ICompletionProposal[]) matches.toArray(new ICompletionProposal[matches.size()]);
+	}
+
+	/**
+	 * Creates a concrete template context for the given region in the
+	 * document. This involves finding out which context type is valid at the
+	 * given location, and then creating a context of this type. The default
+	 * implementation returns a <code>SmartReplaceTemplateContext</code> for
+	 * the context type at the given location. This takes the offset at which
+	 * content assist was invoked into consideration.
+	 * 
+	 * @param viewer
+	 *            the viewer for which the context is created
+	 * @param region
+	 *            the region into <code>document</code> for which the
+	 *            context is created
+	 * @param offset
+	 *            the original offset where content assist was invoked
+	 * @return a template context that can handle template insertion at the
+	 *         given location, or <code>null</code>
+	 */
+	private TemplateContext createContext(ITextViewer viewer, IRegion region, int offset) {
+		// pretty much same code as super.createContext except create
+		// SmartReplaceTemplateContext
+		TemplateContextType contextType = getContextType(viewer, region);
+		if (contextType != null) {
+			IDocument document = viewer.getDocument();
+			return new ReplaceNameTemplateContext(contextType, document, region.getOffset(), region.getLength(), offset);
+		}
+		return null;
+	}
+
+	protected ICompletionProposal createProposal(Template template, TemplateContext context, IRegion region, int relevance) {
+		return new CustomTemplateProposal(template, context, region, getImage(template), relevance);
+	}
+
+	protected TemplateContextType getContextType(ITextViewer viewer, IRegion region) {
+		TemplateContextType type = null;
+
+		ContextTypeRegistry registry = getTemplateContextRegistry();
+		if (registry != null)
+			type = registry.getContextType(fContextTypeId);
+
+		return type;
+	}
+
+	protected Image getImage(Template template) {
+		// just return the same image for now
+		return HTMLEditorPluginImageHelper.getInstance().getImage(HTMLEditorPluginImages.IMG_OBJ_TAG_TEMPLATE);
+	}
+
+	private ContextTypeRegistry getTemplateContextRegistry() {
+		return HTMLUIPlugin.getDefault().getTemplateContextRegistry();
+	}
+
+	protected Template[] getTemplates(String contextTypeId) {
+		Template templates[] = null;
+
+		TemplateStore store = getTemplateStore();
+		if (store != null)
+			templates = store.getTemplates(contextTypeId);
+
+		return templates;
+	}
+
+	private TemplateStore getTemplateStore() {
+		return HTMLUIPlugin.getDefault().getTemplateStore();
+	}
+
+	public void setContextType(String contextTypeId) {
+		fContextTypeId = contextTypeId;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentassist/HTMLTemplatesCompletionProposalComputer.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentassist/HTMLTemplatesCompletionProposalComputer.java
new file mode 100644
index 0000000..2fe72d1
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentassist/HTMLTemplatesCompletionProposalComputer.java
@@ -0,0 +1,146 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.contentassist;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.wst.html.ui.internal.templates.TemplateContextTypeIdsHTML;
+import org.eclipse.wst.sse.ui.contentassist.CompletionProposalInvocationContext;
+import org.eclipse.wst.xml.ui.internal.contentassist.ContentAssistRequest;
+import org.eclipse.wst.xml.ui.internal.contentassist.DefaultXMLCompletionProposalComputer;
+
+/**
+ * <p>XML type proposal computer to create HTML template proposals</p>
+ */
+public class HTMLTemplatesCompletionProposalComputer extends
+		DefaultXMLCompletionProposalComputer {
+
+	/** template processor used to create template proposals */
+	private HTMLTemplateCompletionProcessor fTemplateProcessor = null;
+
+	/**
+	 * <p>Create the computer</p>
+	 */
+	public HTMLTemplatesCompletionProposalComputer() {
+		fTemplateProcessor = new HTMLTemplateCompletionProcessor();
+	}
+
+	/**
+	 * <p>Calls super to add templates based on context and then
+	 * adds templates not specific to a context</p>
+	 * 
+	 * @see org.eclipse.wst.xml.ui.internal.contentassist.AbstractXMLCompletionProposalComputer#computeCompletionProposals(org.eclipse.wst.sse.ui.contentassist.CompletionProposalInvocationContext, org.eclipse.core.runtime.IProgressMonitor)
+	 */
+	public List computeCompletionProposals(
+			CompletionProposalInvocationContext context,
+			IProgressMonitor monitor) {
+		
+		//get the templates specific to the context
+		List proposals = new ArrayList(super.computeCompletionProposals(context, monitor));
+		
+		//get templates not specific to the context
+		proposals.addAll(this.getTemplateProposals(TemplateContextTypeIdsHTML.ALL, context));
+		
+		return proposals;
+	}
+	
+	/**
+	 * @see org.eclipse.wst.xml.ui.internal.contentassist.DefaultXMLCompletionProposalComputer#addAttributeNameProposals(org.eclipse.wst.xml.ui.internal.contentassist.ContentAssistRequest, org.eclipse.wst.sse.ui.contentassist.CompletionProposalInvocationContext)
+	 */
+	protected void addAttributeNameProposals(
+			ContentAssistRequest contentAssistRequest,
+			CompletionProposalInvocationContext context) {
+		
+		addTemplates(contentAssistRequest, TemplateContextTypeIdsHTML.ATTRIBUTE, context);
+	}
+
+	/**
+	 * @see org.eclipse.wst.xml.ui.internal.contentassist.DefaultXMLCompletionProposalComputer#addAttributeValueProposals(org.eclipse.wst.xml.ui.internal.contentassist.ContentAssistRequest, org.eclipse.wst.sse.ui.contentassist.CompletionProposalInvocationContext)
+	 */
+	protected void addAttributeValueProposals(
+			ContentAssistRequest contentAssistRequest,
+			CompletionProposalInvocationContext context) {
+		
+		addTemplates(contentAssistRequest, TemplateContextTypeIdsHTML.ATTRIBUTE_VALUE, context);
+	}
+	
+	/**
+	 * @see org.eclipse.wst.xml.ui.internal.contentassist.DefaultXMLCompletionProposalComputer#addEmptyDocumentProposals(org.eclipse.wst.xml.ui.internal.contentassist.ContentAssistRequest, org.eclipse.wst.sse.ui.contentassist.CompletionProposalInvocationContext)
+	 */
+	protected void addEmptyDocumentProposals(
+			ContentAssistRequest contentAssistRequest,
+			CompletionProposalInvocationContext context) {
+		
+		addTemplates(contentAssistRequest, TemplateContextTypeIdsHTML.NEW, context);
+	}
+	
+	/**
+	 * @see org.eclipse.wst.xml.ui.internal.contentassist.DefaultXMLCompletionProposalComputer#addTagInsertionProposals(org.eclipse.wst.xml.ui.internal.contentassist.ContentAssistRequest, int, org.eclipse.wst.sse.ui.contentassist.CompletionProposalInvocationContext)
+	 */
+	protected void addTagInsertionProposals(
+			ContentAssistRequest contentAssistRequest, int childPosition,
+			CompletionProposalInvocationContext context) {
+		
+		addTemplates(contentAssistRequest, TemplateContextTypeIdsHTML.TAG, context);
+	}
+	
+	/**
+	 * <p>Get the template proposals from the template processor</p>
+	 * 
+	 * @param templateContext
+	 * @param context
+	 * @return
+	 */
+	private List getTemplateProposals(String templateContext,
+			CompletionProposalInvocationContext context) {
+		
+		List templateProposals = new ArrayList();
+		
+		if (fTemplateProcessor != null) {
+			fTemplateProcessor.setContextType(templateContext);
+			ICompletionProposal[] proposals =
+				fTemplateProcessor.computeCompletionProposals(context.getViewer(), context.getInvocationOffset());
+		
+			templateProposals.addAll(Arrays.asList(proposals));
+		}
+		
+		return templateProposals;
+	}
+	
+	/**
+	 * Adds templates to the list of proposals
+	 * 
+	 * @param contentAssistRequest
+	 * @param templateContext
+	 * @param context
+	 */
+	private void addTemplates(ContentAssistRequest contentAssistRequest, String templateContext,
+			CompletionProposalInvocationContext context) {
+		
+		if (contentAssistRequest != null) {
+			boolean useProposalList = !contentAssistRequest.shouldSeparate();
+			List proposals = this.getTemplateProposals(templateContext, context);
+	
+			for (int i = 0; i < proposals.size(); ++i) {
+				if (useProposalList) {
+					contentAssistRequest.addProposal((ICompletionProposal)proposals.get(i));
+				}
+				else {
+					contentAssistRequest.addMacro((ICompletionProposal)proposals.get(i));
+				}
+			}
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentassist/NoRegionContentAssistProcessorForHTML.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentassist/NoRegionContentAssistProcessorForHTML.java
new file mode 100644
index 0000000..748a54d
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentassist/NoRegionContentAssistProcessorForHTML.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.contentassist;
+
+import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
+import org.eclipse.wst.css.core.text.ICSSPartitions;
+import org.eclipse.wst.css.ui.internal.contentassist.CSSContentAssistProcessor;
+import org.eclipse.wst.html.core.text.IHTMLPartitions;
+import org.eclipse.wst.html.ui.StructuredTextViewerConfigurationHTML;
+import org.eclipse.wst.xml.ui.internal.contentassist.NoRegionContentAssistProcessor;
+
+/**
+ * 
+ * @author pavery
+ */
+public class NoRegionContentAssistProcessorForHTML extends NoRegionContentAssistProcessor {
+	protected void initPartitionToProcessorMap() {
+		
+		super.initPartitionToProcessorMap();
+		IContentAssistProcessor htmlProcessor = new HTMLContentAssistProcessor();
+		addPartitionProcessor(IHTMLPartitions.HTML_DEFAULT, htmlProcessor);
+		addPartitionProcessor(IHTMLPartitions.HTML_COMMENT, htmlProcessor);
+
+		IContentAssistProcessor jsContentAssistProcessor = new StructuredTextViewerConfigurationHTML().getContentAssistant(null).getContentAssistProcessor(IHTMLPartitions.SCRIPT);
+		addPartitionProcessor(IHTMLPartitions.SCRIPT, jsContentAssistProcessor);
+
+		IContentAssistProcessor cssContentAssistProcessor = new CSSContentAssistProcessor();
+		addPartitionProcessor(ICSSPartitions.STYLE, cssContentAssistProcessor);
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentassist/ReplaceNameTemplateContext.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentassist/ReplaceNameTemplateContext.java
new file mode 100644
index 0000000..764a915
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentassist/ReplaceNameTemplateContext.java
@@ -0,0 +1,113 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 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
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.contentassist;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.templates.DocumentTemplateContext;
+import org.eclipse.jface.text.templates.Template;
+import org.eclipse.jface.text.templates.TemplateBuffer;
+import org.eclipse.jface.text.templates.TemplateContextType;
+import org.eclipse.jface.text.templates.TemplateException;
+import org.eclipse.jface.text.templates.TemplateVariable;
+
+/**
+ * Just like DocumentTemplateContext except if an insert offset is passed in,
+ * during evaluation, the "prefix" before the template will be checked to see
+ * if it matches the template name. If so, overwrite the template name.
+ * Otherwise, just insert the template at the insert offset location (by not
+ * overwriting the prefix text)
+ */
+public class ReplaceNameTemplateContext extends DocumentTemplateContext {
+	private int fInsertOffset = -1;
+
+	/**
+	 * Creates a document template context.
+	 * 
+	 * @param type
+	 *            the context type
+	 * @param document
+	 *            the document this context applies to
+	 * @param offset
+	 *            the offset of the document region
+	 * @param length
+	 *            the length of the document region
+	 */
+	public ReplaceNameTemplateContext(TemplateContextType type, IDocument document, int offset, int length) {
+		this(type, document, new Position(offset, length));
+	}
+
+	/**
+	 * Creates a document template context. The supplied <code>Position</code>
+	 * will be queried to compute the <code>getStart</code> and
+	 * <code>getEnd</code> methods, which will therefore answer updated
+	 * position data if it is registered with the document.
+	 * 
+	 * @param type
+	 *            the context type
+	 * @param document
+	 *            the document this context applies to
+	 * @param position
+	 *            the position describing the area of the document which forms
+	 *            the template context
+	 * @since 3.1
+	 */
+	public ReplaceNameTemplateContext(TemplateContextType type, IDocument document, Position position) {
+		super(type, document, position);
+	}
+
+	/**
+	 * Creates a document template context.
+	 * 
+	 * @param type
+	 *            the context type
+	 * @param document
+	 *            the document this context applies to
+	 * @param offset
+	 *            the offset of the document region
+	 * @param length
+	 *            the length of the document region
+	 * @param insertOffset
+	 *            the offset of the document region where insert was
+	 *            originally requested
+	 */
+	public ReplaceNameTemplateContext(TemplateContextType type, IDocument document, int offset, int length, int insertOffset) {
+		this(type, document, new Position(offset, length));
+		fInsertOffset = insertOffset;
+	}
+
+	/*
+	 * @see org.eclipse.jface.text.templates.TemplateContext#evaluate(org.eclipse.jface.text.templates.Template)
+	 */
+	public TemplateBuffer evaluate(Template template) throws BadLocationException, TemplateException {
+		TemplateBuffer buffer = super.evaluate(template);
+		if (buffer != null) {
+			if (fInsertOffset > -1 && fInsertOffset > getStart()) {
+				String prefix = getDocument().get(getStart(), fInsertOffset - getStart());
+				if (!template.getName().startsWith(prefix)) {
+					// generate a new buffer that actually contains the
+					// text that was going to be overwritten
+					int prefixSize = prefix.length();
+					TemplateVariable[] newTemplateVar = buffer.getVariables();
+					for (int i =0; i < newTemplateVar.length; i++ ){
+						int[] offsets = newTemplateVar[i].getOffsets();
+						for (int j=0; j<offsets.length ;j++){
+							offsets[j] += prefixSize;
+						}
+					}
+					buffer = new TemplateBuffer(prefix + buffer.getString(), newTemplateVar);
+				}
+			}
+		}
+		return buffer;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentassist/XHTMLMinimalContentModelGenerator.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentassist/XHTMLMinimalContentModelGenerator.java
new file mode 100644
index 0000000..2a9607e
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentassist/XHTMLMinimalContentModelGenerator.java
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.contentassist;
+
+
+
+import org.eclipse.wst.html.core.internal.contentmodel.HTMLElementDeclaration;
+import org.eclipse.wst.html.core.internal.provisional.HTMLCMProperties;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.ui.internal.contentassist.XMLContentModelGenerator;
+import org.w3c.dom.Node;
+
+public class XHTMLMinimalContentModelGenerator extends XMLContentModelGenerator {
+
+	private static XHTMLMinimalContentModelGenerator instance = null;
+
+	private XHTMLMinimalContentModelGenerator() {
+		super();
+	}
+
+	protected void generateEndTag(String tagName, Node parentNode, CMElementDeclaration elementDecl, StringBuffer buffer) {
+		if (elementDecl == null)
+			return;
+		if (elementDecl instanceof HTMLElementDeclaration) {
+			if (((Boolean) elementDecl.getProperty(HTMLCMProperties.IS_JSP)).booleanValue()) {
+				if (elementDecl.getContentType() == CMElementDeclaration.EMPTY)
+					return;
+			}
+			else {
+				String ommission = (String) elementDecl.getProperty(HTMLCMProperties.OMIT_TYPE);
+				if (ommission.equals(HTMLCMProperties.Values.OMIT_END) || ommission.equals(HTMLCMProperties.Values.OMIT_END_DEFAULT) || ommission.equals(HTMLCMProperties.Values.OMIT_END_MUST)) {
+					return;
+				}
+			}
+		}
+
+		if (elementDecl.getContentType() == CMElementDeclaration.EMPTY)
+			return;
+		buffer.append("</" + tagName + ">"); //$NON-NLS-2$//$NON-NLS-1$
+		return;
+	}
+
+
+	public String getStartTagClose(Node parentNode, CMElementDeclaration elementDecl) {
+		String other = getOtherClose(parentNode);
+		if (other != null)
+			return other;
+		if (elementDecl == null)
+			return ">"; //$NON-NLS-1$
+		// EMPTY tag, do a self-close
+		if (elementDecl.getContentType() == CMElementDeclaration.EMPTY) {
+			// if it's a JSP element, don't add the space since the JSP container doesn't/shouldn't care
+			if (elementDecl instanceof HTMLElementDeclaration && (((Boolean) elementDecl.getProperty(HTMLCMProperties.IS_JSP)).booleanValue()))
+				// if it's not JSP, conform to XHTML guidelines and add the space
+				return "/>"; //$NON-NLS-1$
+			else
+				return " />"; //$NON-NLS-1$
+		}
+		// not defined as EMPTY, but should be treated as such anyway
+		else if (elementDecl instanceof HTMLElementDeclaration) {
+			String ommission = (String) elementDecl.getProperty(HTMLCMProperties.OMIT_TYPE);
+			if (ommission.equals(HTMLCMProperties.Values.OMIT_END) || ommission.equals(HTMLCMProperties.Values.OMIT_END_DEFAULT) || ommission.equals(HTMLCMProperties.Values.OMIT_END_MUST)) {
+				return " />"; //$NON-NLS-1$
+			}
+		}
+
+		return ">"; //$NON-NLS-1$
+	}
+
+	public synchronized static XHTMLMinimalContentModelGenerator getInstance() {
+		if (instance == null)
+			instance = new XHTMLMinimalContentModelGenerator();
+		return instance;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentoutline/HTMLNodeActionManager.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentoutline/HTMLNodeActionManager.java
new file mode 100644
index 0000000..b59c954
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentoutline/HTMLNodeActionManager.java
@@ -0,0 +1,129 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.contentoutline;
+
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.wst.html.core.internal.HTMLContentBuilder;
+import org.eclipse.wst.html.core.internal.HTMLCorePlugin;
+import org.eclipse.wst.html.core.internal.format.HTMLFormatProcessorImpl;
+import org.eclipse.wst.html.core.internal.preferences.HTMLCorePreferenceNames;
+import org.eclipse.wst.html.core.internal.provisional.HTMLCMProperties;
+import org.eclipse.wst.html.core.internal.provisional.contenttype.ContentTypeIdForHTML;
+import org.eclipse.wst.sse.core.internal.format.IStructuredFormatProcessor;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.DOMContentBuilder;
+import org.eclipse.wst.xml.ui.internal.contentoutline.XMLNodeActionManager;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+/**
+ * 
+ */
+public class HTMLNodeActionManager extends XMLNodeActionManager {
+	protected int fTagCase;
+	protected int fAttrCase;
+
+	public HTMLNodeActionManager(IStructuredModel model, Viewer viewer) {
+		super(model, viewer);
+		updateCase();
+	}
+
+	/**
+	 * If neccessary, employ a DOMContentBuilder that understands how to
+	 * change the case of HTML tags (but NOT taglib derived tags).
+	 */
+	public DOMContentBuilder createDOMContentBuilder(Document document) {
+		DOMContentBuilder builder = null;
+		String one = fModel.getModelHandler().getAssociatedContentTypeId();
+		String modelContentTypeId = fModel.getContentTypeIdentifier();
+		if (one != modelContentTypeId) {
+			System.out.println("not equal"); //$NON-NLS-1$
+		}
+		if (modelContentTypeId.equals(ContentTypeIdForHTML.ContentTypeID_HTML))
+			builder = new HTMLContentBuilder(document);
+		else
+			builder = super.createDOMContentBuilder(document);
+
+		return builder;
+	}
+
+	private boolean shouldIgnoreCase(CMNode cmnode) {
+		if (!cmnode.supports(HTMLCMProperties.SHOULD_IGNORE_CASE))
+			return false;
+		return ((Boolean) cmnode.getProperty(HTMLCMProperties.SHOULD_IGNORE_CASE)).booleanValue();
+	}
+
+	/**
+	 * Modify the displayed menuitem label to change the case of HTML children
+	 * but neither XML nor taglib-derived children.
+	 */
+	public String getLabel(Node parent, CMNode cmnode) {
+		String result = null;
+		// CMNode cmnode = action.getCMNode();
+		// don't change the case unless we're certain it is meaningless
+		if (shouldIgnoreCase(cmnode)) {
+			String name = cmnode.getNodeName();
+			if (cmnode.getNodeType() == CMNode.ELEMENT_DECLARATION) {
+				if (fTagCase == HTMLCorePreferenceNames.LOWER)
+					name = name.toLowerCase();
+				else if (fTagCase == HTMLCorePreferenceNames.UPPER)
+					name = name.toUpperCase();
+				// else do nothing
+			}
+			else if (cmnode.getNodeType() == CMNode.ATTRIBUTE_DECLARATION) {
+				if (fAttrCase == HTMLCorePreferenceNames.LOWER)
+					name = name.toLowerCase();
+				else if (fAttrCase == HTMLCorePreferenceNames.UPPER)
+					name = name.toUpperCase();
+				// else do nothing
+			}
+			result = name;
+		}
+		else {
+			result = super.getLabel(parent, cmnode);
+		}
+
+		return result;
+	}
+
+	/**
+	 * Another HTML specific detail.
+	 */
+	protected void updateCase() {
+		if (fModel != null) {
+			String modelContentTypeId = fModel.getContentTypeIdentifier();
+			if (modelContentTypeId != null) {
+				if (modelContentTypeId.equals(ContentTypeIdForHTML.ContentTypeID_HTML)) {
+					Preferences prefs = HTMLCorePlugin.getDefault().getPluginPreferences(); //$NON-NLS-1$
+					fTagCase = prefs.getInt(HTMLCorePreferenceNames.TAG_NAME_CASE);
+					fAttrCase = prefs.getInt(HTMLCorePreferenceNames.ATTR_NAME_CASE);
+				}
+			}
+		}
+	}
+
+	public void reformat(Node newElement, boolean deep) {
+		try {
+			// tell the model that we are about to make a big model change
+			fModel.aboutToChangeModel();
+
+			// format selected node
+			IStructuredFormatProcessor formatProcessor = new HTMLFormatProcessorImpl();
+			formatProcessor.formatNode(newElement);
+		}
+		finally {
+			// tell the model that we are done with the big model change
+			fModel.changedModel();
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentoutline/JFaceNodeAdapterFactoryForHTML.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentoutline/JFaceNodeAdapterFactoryForHTML.java
new file mode 100644
index 0000000..ea1dddd
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentoutline/JFaceNodeAdapterFactoryForHTML.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.contentoutline;
+
+
+
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapter;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapterFactory;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.sse.ui.internal.contentoutline.IJFaceNodeAdapter;
+import org.eclipse.wst.xml.ui.internal.contentoutline.JFaceNodeAdapterFactory;
+
+/**
+ * An adapter factory to create JFaceNodeAdapters.  Use this
+ * adapter factory with a JFaceAdapterContentProvider to display
+ * DOM nodes in a tree.
+ */
+public class JFaceNodeAdapterFactoryForHTML extends JFaceNodeAdapterFactory {
+
+
+	public JFaceNodeAdapterFactoryForHTML() {
+		this(IJFaceNodeAdapter.class, true);
+	}
+
+	public JFaceNodeAdapterFactoryForHTML(Object adapterKey, boolean registerAdapters) {
+		super(adapterKey, registerAdapters);
+	}
+
+	protected INodeAdapter createAdapter(INodeNotifier node) {
+		if (singletonAdapter == null) {
+			// create the JFaceNodeAdapter
+			singletonAdapter = new JFaceNodeAdapterForHTML(this);
+			initAdapter(singletonAdapter, node);
+		}
+		return singletonAdapter;
+	}
+
+	public INodeAdapterFactory copy() {
+		return new JFaceNodeAdapterFactoryForHTML(getAdapterKey(), isShouldRegisterAdapter());
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentoutline/JFaceNodeAdapterForHTML.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentoutline/JFaceNodeAdapterForHTML.java
new file mode 100644
index 0000000..1b494c5
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentoutline/JFaceNodeAdapterForHTML.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.contentoutline;
+
+
+
+import java.util.Locale;
+
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.wst.html.ui.internal.editor.HTMLEditorPluginImageHelper;
+import org.eclipse.wst.html.ui.internal.editor.HTMLEditorPluginImages;
+import org.eclipse.wst.xml.ui.internal.contentoutline.JFaceNodeAdapter;
+import org.eclipse.wst.xml.ui.internal.contentoutline.JFaceNodeAdapterFactory;
+import org.w3c.dom.Node;
+
+/**
+ * Adapts a DOM node to a JFace viewer.
+ */
+public class JFaceNodeAdapterForHTML extends JFaceNodeAdapter {
+
+	private Image createHTMLImage(String imageResourceName) {
+		return HTMLEditorPluginImageHelper.getInstance().getImage(imageResourceName);
+	}
+
+	/**
+	 * Constructor for JFaceNodeAdapterForHTML.
+	 * 
+	 * @param adapterFactory
+	 */
+	public JFaceNodeAdapterForHTML(JFaceNodeAdapterFactory adapterFactory) {
+		super(adapterFactory);
+	}
+
+	protected Image createImage(Object object) {
+		Image image = null;
+
+		Node node = (Node) object;
+		if (node.getNodeType() == Node.ELEMENT_NODE) {
+			String lowerName = node.getNodeName().toLowerCase(Locale.US);
+			if (lowerName.equals("table") || lowerName.endsWith(":table")) //$NON-NLS-1$
+				image = createHTMLImage(HTMLEditorPluginImages.IMG_OBJ_TABLE);
+			else if (lowerName.equals("a") || lowerName.endsWith(":a")) //$NON-NLS-1$
+				image = createHTMLImage(HTMLEditorPluginImages.IMG_OBJ_TAG_ANCHOR);
+			else if (lowerName.equals("body") || lowerName.endsWith(":body")) //$NON-NLS-1$
+				image = createHTMLImage(HTMLEditorPluginImages.IMG_OBJ_TAG_BODY);
+			else if (lowerName.equals("button") || lowerName.endsWith(":button")) //$NON-NLS-1$
+				image = createHTMLImage(HTMLEditorPluginImages.IMG_OBJ_TAG_BUTTON);
+			else if (lowerName.equals("font") || lowerName.endsWith(":font")) //$NON-NLS-1$
+				image = createHTMLImage(HTMLEditorPluginImages.IMG_OBJ_TAG_FONT);
+			else if (lowerName.equals("form") || lowerName.endsWith(":form")) //$NON-NLS-1$
+				image = createHTMLImage(HTMLEditorPluginImages.IMG_OBJ_TAG_FORM);
+			else if (lowerName.equals("html") || lowerName.endsWith(":html")) //$NON-NLS-1$
+				image = createHTMLImage(HTMLEditorPluginImages.IMG_OBJ_TAG_HTML);
+			else if (lowerName.equals("img") || lowerName.endsWith(":img")) //$NON-NLS-1$
+				image = createHTMLImage(HTMLEditorPluginImages.IMG_OBJ_TAG_IMAGE);
+			else if (lowerName.equals("map") || lowerName.endsWith(":map")) //$NON-NLS-1$
+				image = createHTMLImage(HTMLEditorPluginImages.IMG_OBJ_TAG_IMAGE_MAP);
+			else if (lowerName.equals("title") || lowerName.endsWith(":title")) //$NON-NLS-1$
+				image = createHTMLImage(HTMLEditorPluginImages.IMG_OBJ_TAG_TITLE);
+			else
+				image = createHTMLImage(HTMLEditorPluginImages.IMG_OBJ_TAG);
+		}
+		if (image == null) {
+			image = super.createImage(node);
+		}
+		return image;
+	}
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentproperties/ui/AbstractDeviceProfileEntry.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentproperties/ui/AbstractDeviceProfileEntry.java
new file mode 100644
index 0000000..b123df9
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentproperties/ui/AbstractDeviceProfileEntry.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.contentproperties.ui;
+
+/**
+ * @deprecated Not needed. See BUG118359
+ */
+public class AbstractDeviceProfileEntry implements DeviceProfileEntry {
+
+	public AbstractDeviceProfileEntry() {
+		super();
+	}
+
+	public String getEntryId() {
+		return null;
+	}
+
+	public String getEntryName() {
+		return null;
+	}
+
+	public void release() {
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentproperties/ui/AbstractDeviceProfileEntryProvider.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentproperties/ui/AbstractDeviceProfileEntryProvider.java
new file mode 100644
index 0000000..664084c
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentproperties/ui/AbstractDeviceProfileEntryProvider.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.contentproperties.ui;
+
+import java.util.Iterator;
+
+/**
+ * @deprecated Not needed.  See BUG118359
+ */
+public class AbstractDeviceProfileEntryProvider implements
+		DeviceProfileEntryProvider {
+
+	public AbstractDeviceProfileEntryProvider() {
+		super();
+	}
+
+	public Iterator getDeviceProfileEntries() {
+		return null;
+	}
+
+	public void release() {
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentproperties/ui/ContentSettingsRegistry.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentproperties/ui/ContentSettingsRegistry.java
new file mode 100644
index 0000000..75b272d
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentproperties/ui/ContentSettingsRegistry.java
@@ -0,0 +1,173 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.contentproperties.ui;
+
+import java.util.Enumeration;
+import java.util.Iterator;
+
+import org.eclipse.wst.css.core.internal.metamodel.CSSProfile;
+import org.eclipse.wst.css.core.internal.metamodel.CSSProfileRegistry;
+import org.eclipse.wst.html.core.internal.document.HTMLDocumentTypeEntry;
+import org.eclipse.wst.html.core.internal.document.HTMLDocumentTypeRegistry;
+import org.eclipse.wst.html.ui.internal.HTMLUIMessages;
+import org.eclipse.wst.sse.core.internal.encoding.CommonCharsetNames;
+import org.eclipse.wst.sse.ui.internal.contentproperties.ui.ComboList;
+
+/**
+ * @deprecated This class only contains helper methods that you should
+ *             actually implement yourself.
+ */
+public final class ContentSettingsRegistry {
+
+	private static final String NONE = HTMLUIMessages.UI_none;
+
+	public static String maxLengthStringInHTMLDocumentTypeRegistry = ""; //$NON-NLS-1$
+	public static String maxLengthStringInCharacterCodeRegistry = ""; //$NON-NLS-1$
+
+	private ContentSettingsRegistry() {
+	}
+
+	public static void setHTMLDocumentTypeRegistryInto(ComboList combo) {
+		combo.add(NONE, ""); //$NON-NLS-1$
+		HTMLDocumentTypeRegistry reg = HTMLDocumentTypeRegistry.getInstance();
+		Enumeration e = reg.getEntries();
+		while (e.hasMoreElements()) {
+			HTMLDocumentTypeEntry entry = (HTMLDocumentTypeEntry) e.nextElement();
+			String publicId = entry.getPublicId();
+			String displayName = entry.getDisplayName();
+			if (displayName != null) {
+				combo.add(displayName, publicId);
+				if (displayName.length() > maxLengthStringInHTMLDocumentTypeRegistry.length())
+					maxLengthStringInHTMLDocumentTypeRegistry = displayName;
+			}
+			else
+				combo.add(publicId, publicId);
+			if (publicId.length() > maxLengthStringInHTMLDocumentTypeRegistry.length())
+				maxLengthStringInHTMLDocumentTypeRegistry = publicId;
+			if (entry.getSystemId() == null)
+				continue; // if HTML entry
+			if (entry.getSystemId().length() > maxLengthStringInHTMLDocumentTypeRegistry.length())
+				maxLengthStringInHTMLDocumentTypeRegistry = entry.getSystemId();
+		}
+
+		combo.sortByKey(1);
+	}
+
+	public static void setCSSMetaModelRegistryInto(ComboList combo) {
+		combo.add(NONE, ""); //$NON-NLS-1$
+		CSSProfileRegistry reg = CSSProfileRegistry.getInstance();
+		Iterator i = reg.getProfiles();
+		while (i.hasNext()) {
+			CSSProfile profile = (CSSProfile) i.next();
+			String id = profile.getProfileID();
+			String name = profile.getProfileName();
+			combo.add(name, id);
+		}
+		combo.sortByKey(1);
+	}
+
+	public static void setDeviceProfileRegistryInto(ComboList combo) {
+		combo.add(NONE, ""); //$NON-NLS-1$
+		DeviceProfileEntryProvider reg = DeviceProfileEntryProviderBuilder.getEntryProvider();
+		if (reg == null) {
+			return;
+		}
+		Iterator profiles = reg.getDeviceProfileEntries();
+		if (profiles == null) {
+			reg.release();
+			return;
+		}
+		DeviceProfileEntry entry;
+		while (profiles.hasNext()) {
+			entry = (DeviceProfileEntry) profiles.next();
+			combo.add(entry.getEntryName(), entry.getEntryId());
+			entry.release();
+		}
+		reg.release();
+		combo.sortByKey(1);
+	}
+
+	public static String getSystemIdFrom(String publicId) {
+		if (publicId == null || publicId.length() == 0)
+			return null;
+		HTMLDocumentTypeRegistry reg = HTMLDocumentTypeRegistry.getInstance();
+		Enumeration e = reg.getEntries();
+		while (e.hasMoreElements()) {
+			HTMLDocumentTypeEntry entry = (HTMLDocumentTypeEntry) e.nextElement();
+			if (entry.getPublicId().equals(publicId))
+				return entry.getSystemId();
+		}
+		return null;
+	}
+
+	public static void setContentTypeInto(ComboList combo) {
+		String[] type = {"", //$NON-NLS-1$
+					"application/xhtml+xml", //$NON-NLS-1$
+					"application/xml", //$NON-NLS-1$
+					"text/html", //$NON-NLS-1$
+					"text/xml",}; //$NON-NLS-1$
+		String[] displayName = {NONE, "application/xhtml+xml", //$NON-NLS-1$
+					//$NON-NLS-1$
+					"application/xml", //$NON-NLS-1$
+					"text/html", //$NON-NLS-1$
+					"text/xml",}; //$NON-NLS-1$
+		for (int i = 0; i < type.length; i++) {
+			if (displayName[i] != null && displayName[i].length() != 0)
+				combo.add(displayName[i], type[i]);
+			else
+				combo.add(type[i], type[i]);
+		}
+
+	}
+
+	public static void setCharacterCodeInto(ComboList combo) {
+		combo.add(NONE, ""); //$NON-NLS-1$
+		String max = ""; //$NON-NLS-1$
+		// CommonCharsetNames encoding = new CommonCharsetNames();
+		String[] charCode = CommonCharsetNames.getCommonCharsetNames();
+		for (int i = 0; i < charCode.length; i++) {
+			String displayName = CommonCharsetNames.getDisplayString(charCode[i]);
+			if (displayName != null && displayName.length() != 0) {
+				combo.add(displayName, charCode[i]);
+				int n_byte = displayName.getBytes().length;
+				if (max.getBytes().length < n_byte)
+					max = displayName;
+			}
+			else
+				combo.add(charCode[i], charCode[i]);
+		}
+		/*
+		 * charCode = encoding.getSupportedJavaEncodings(); for(int i=0;i<charCode.length;i++){
+		 * String displayName = encoding.getDisplayString(charCode[i]); if
+		 * (displayName!=null && displayName.length()!=0)
+		 * combo.add(displayName,charCode[i]); else
+		 * combo.add(charCode[i],charCode[i]); }
+		 */
+		// combo.sortByKey(1);
+		maxLengthStringInCharacterCodeRegistry = max;
+	}
+
+	public static void setLanguageInto(ComboList combo) {
+		String[] lang = {"", //$NON-NLS-1$
+					"java", //$NON-NLS-1$
+					"javascript",}; //$NON-NLS-1$
+		String[] displayName = {NONE, "java", //$NON-NLS-1$
+					//$NON-NLS-1$
+					"javascript",}; //$NON-NLS-1$
+		for (int i = 0; i < lang.length; i++) {
+			if (displayName[i] != null && displayName[i].length() != 0)
+				combo.add(displayName[i], lang[i]);
+			else
+				combo.add(lang[i], lang[i]);
+		}
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentproperties/ui/DeviceProfileEntry.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentproperties/ui/DeviceProfileEntry.java
new file mode 100644
index 0000000..c42cb15
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentproperties/ui/DeviceProfileEntry.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.contentproperties.ui;
+
+/**
+ * <p>
+ * This interface is not intended to be implemented by clients directly.
+ * Instead, please use abstract class(AbstractDeviceProfileEntry) instead.
+ * </p>
+ * 
+ * @deprecated Not needed. See BUG118359
+ */
+public interface DeviceProfileEntry {
+	public String getEntryId();
+
+	public String getEntryName();
+
+	public void release();
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentproperties/ui/DeviceProfileEntryProvider.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentproperties/ui/DeviceProfileEntryProvider.java
new file mode 100644
index 0000000..fe60779
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentproperties/ui/DeviceProfileEntryProvider.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.contentproperties.ui;
+
+import java.util.Iterator;
+
+/**
+ * <p>
+ * This interface is not intended to be implemented by clients directly.
+ * Instead, please use abstract class(AbstractDeviceProfileEntryProvider)
+ * instead.
+ * </p>
+ * 
+ * @deprecated Not needed. See BUG118359
+ */
+public interface DeviceProfileEntryProvider {
+	public Iterator getDeviceProfileEntries();
+
+	public void release();
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentproperties/ui/DeviceProfileEntryProviderBuilder.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentproperties/ui/DeviceProfileEntryProviderBuilder.java
new file mode 100644
index 0000000..3263eaa
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentproperties/ui/DeviceProfileEntryProviderBuilder.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.contentproperties.ui;
+
+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.Platform;
+
+/**
+ * @deprecated Not needed.  See BUG118359
+ */
+public class DeviceProfileEntryProviderBuilder {
+	private static final String EXTENSION_POINT_PLUGINID = "org.eclipse.wst.html.ui";  //$NON-NLS-1$
+	private static final String EXTENSION_POINT_NAME = "deviceProfileEntryProvider"; //$NON-NLS-1$
+	private static final String ATTR_CLASS = "class"; //$NON-NLS-1$
+
+	public DeviceProfileEntryProviderBuilder() {
+		super();
+	}
+	static public DeviceProfileEntryProvider getEntryProvider() {
+		IExtensionPoint point = Platform.getExtensionRegistry().getExtensionPoint(EXTENSION_POINT_PLUGINID, EXTENSION_POINT_NAME);
+		if (point != null) {
+			IExtension extensions[] = point.getExtensions();
+			if ((extensions != null) && (extensions.length > 0)) {
+				for (int i = 0; i < extensions.length; i++) {
+					IConfigurationElement elements[] = extensions[i].getConfigurationElements();
+					if ((elements != null) && (elements.length > 0)) {
+						for (int j = 0; j < elements.length; j++) {
+							IConfigurationElement config = elements[j];
+							if ((config != null) && (config.getName().equals(EXTENSION_POINT_NAME) == true)) {
+								String className = config.getAttribute(ATTR_CLASS);
+								if (className != null) {
+									try {
+										DeviceProfileEntryProvider provider = (DeviceProfileEntryProvider)config.createExecutableExtension(ATTR_CLASS);
+										if (provider != null) {
+											return provider;
+										}
+									} catch (CoreException ignored) {
+									}
+								}
+							}
+						}
+					}
+				}
+			}
+		}
+		return null;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentproperties/ui/HTMLContentSettingsPropertyPage.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentproperties/ui/HTMLContentSettingsPropertyPage.java
new file mode 100644
index 0000000..395fded
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentproperties/ui/HTMLContentSettingsPropertyPage.java
@@ -0,0 +1,280 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.contentproperties.ui;
+
+import java.util.Map;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.swt.widgets.Widget;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.wst.html.ui.internal.HTMLUIMessages;
+import org.eclipse.wst.html.ui.internal.Logger;
+import org.eclipse.wst.html.ui.internal.editor.IHelpContextIds;
+import org.eclipse.wst.sse.internal.contentproperties.IContentSettings;
+import org.eclipse.wst.sse.ui.internal.contentproperties.ui.ComboListOnPropertyPage;
+import org.eclipse.wst.sse.ui.internal.contentproperties.ui.ContentSettingsPropertyPage;
+
+/**
+ * @deprecated Use WebContentSettingsPropertyPage instead
+ */
+public final class HTMLContentSettingsPropertyPage extends ContentSettingsPropertyPage implements org.eclipse.swt.events.SelectionListener {
+
+
+	private final int N_DOCUMENT_TYPE = 0;
+	private final int N_CSS_PROFILE = 1;
+	private final int N_TARGET_DEVICE = 2;
+
+	private Text publicIdText;
+	private Text systemIdText;
+
+	public HTMLContentSettingsPropertyPage() {
+		super();
+		numberOfCombo = 3;
+		numCols = 2;
+		numRows = 8;
+		combo = new ComboListOnPropertyPage[super.numberOfCombo];
+
+	}
+
+
+
+	protected void createDocumentTypeComboBox() {
+
+		// create description of implecit DOCTYPE	
+		Label label = new Label(propertyPage, SWT.LEFT);
+		label.setText(HTMLUIMessages.UI_Description_of_role_of_following_DOCTYPE);
+		GridData data = new GridData();
+		data.horizontalAlignment = GridData.FILL;
+		data.horizontalSpan = numCols;
+		label.setLayoutData(data);
+
+		// create combobox
+		super.combo[N_DOCUMENT_TYPE] = super.createComboBoxOf(DOCUMENT_LABEL);
+		super.combo[this.N_DOCUMENT_TYPE].addSelectionListener(this);
+		// set entry list into Combo
+		ContentSettingsRegistry.setHTMLDocumentTypeRegistryInto(combo[N_DOCUMENT_TYPE]);
+		//	create TextField
+		createIDTextField();
+		if (combo[N_DOCUMENT_TYPE].getItemCount() <= 0)
+			return;
+
+		String initValue = contentSettings.getProperty((IResource) super.getElement(), IContentSettings.HTML_DOCUMENT_TYPE);
+		// when either .contentsettings or element doesn't exist
+		// when attribute doesn't exists,getProperty returns empty string.
+		if (initValue == null)
+			initValue = ""; //$NON-NLS-1$
+		// set init selectionItem in Combo
+		super.setSelectionItem(combo[N_DOCUMENT_TYPE], initValue);
+		this.publicIdText.setText(initValue);
+		if (!initValue.equals("")) {//$NON-NLS-1$
+			// toro D210260
+			if (ContentSettingsRegistry.getSystemIdFrom(initValue) != null)
+				this.systemIdText.setText(ContentSettingsRegistry.getSystemIdFrom(initValue));
+			else
+				this.systemIdText.setText("");//$NON-NLS-1$
+		}
+		else
+			this.systemIdText.setText("");//$NON-NLS-1$
+
+		// create separator
+		label = new Label(propertyPage, SWT.SEPARATOR | SWT.HORIZONTAL);
+		data = new GridData();
+		data.horizontalAlignment = GridData.FILL;
+		data.horizontalSpan = numCols;
+		data.verticalSpan = 8;
+		label.setLayoutData(data);
+
+	}
+
+
+
+	protected void createCSSComboBox() {
+		super.combo[N_CSS_PROFILE] = super.createComboBoxOf(CSS_LABEL);
+
+		ContentSettingsRegistry.setCSSMetaModelRegistryInto(combo[N_CSS_PROFILE]);
+		if (combo[N_CSS_PROFILE].getItemCount() <= 0)
+			return;
+		String initValue = contentSettings.getProperty((IResource) super.getElement(), IContentSettings.CSS_PROFILE);
+		// when either .contentsettings or element doesn't exist
+		// when attribute doesn't exists,getProperty returns empty string.
+		if (initValue == null)
+			initValue = ""; //$NON-NLS-1$
+		// set init selectionItem in Combo
+		super.setSelectionItem(combo[N_CSS_PROFILE], initValue);
+	}
+
+
+
+	protected void createDeviceComboBox() {
+		super.combo[N_TARGET_DEVICE] = super.createComboBoxOf(DEVICE_LABEL);
+
+		ContentSettingsRegistry.setDeviceProfileRegistryInto(combo[N_TARGET_DEVICE]);
+		if (combo[N_TARGET_DEVICE].getItemCount() <= 0)
+			return;
+		String initValue = contentSettings.getProperty((IResource) super.getElement(), IContentSettings.DEVICE_PROFILE);
+		// when either .contentsettings or element doesn't exist
+		// when attribute doesn't exists,getProperty returns empty string.
+		if (initValue == null)
+			initValue = ""; //$NON-NLS-1$
+		// set init selectionItem in Combo
+		super.setSelectionItem(combo[N_TARGET_DEVICE], initValue);
+	}
+
+
+	protected void createSettingsPageGUI() {
+		int type = ((IResource) getElement()).getType();
+		switch (type) {
+			case IResource.FILE :
+				//	composite = createComposite(propertyPage,numCols,numRows);
+				createDocumentTypeComboBox();
+				createCSSComboBox();
+				createDeviceComboBox();
+				computeMaxWidthHint();
+				PlatformUI.getWorkbench().getHelpSystem().setHelp(propertyPage, IHelpContextIds.WEB_CONTENT_SETTINGS_HELPID);
+				break;
+
+			default :
+				Logger.log(Logger.WARNING, "HTMLContentSettingsPropertyPage is instantiated by resource except FILE");//$NON-NLS-1$
+				break;
+		}
+
+	}
+
+
+
+	protected void putSelectedPropertyInto(Map properties, String valueInCombo, int index) {
+
+		switch (index) {
+			case N_DOCUMENT_TYPE :
+				// doc type
+				properties.put(IContentSettings.HTML_DOCUMENT_TYPE, valueInCombo);
+				break;
+			case N_CSS_PROFILE :
+				// css
+				properties.put(IContentSettings.CSS_PROFILE, valueInCombo);
+				break;
+			case N_TARGET_DEVICE :
+				// device
+				properties.put(IContentSettings.DEVICE_PROFILE, valueInCombo);
+				break;
+			default :
+				Logger.log(Logger.ERROR, "Index is out of range in putSelectedPropertyInto() in class HTMLContentSettingsPropertyPage");//$NON-NLS-1$
+				break;
+		}
+
+	}
+
+	protected void deleteNoneProperty(int index) {
+		switch (index) {
+			case N_DOCUMENT_TYPE :
+				// doc type
+				contentSettings.deleteProperty((IResource) super.getElement(), IContentSettings.HTML_DOCUMENT_TYPE);
+				break;
+			case N_CSS_PROFILE :
+				// css
+				contentSettings.deleteProperty((IResource) super.getElement(), IContentSettings.CSS_PROFILE);
+				break;
+			case N_TARGET_DEVICE :
+				// device
+				contentSettings.deleteProperty((IResource) super.getElement(), IContentSettings.DEVICE_PROFILE);
+				break;
+			default :
+				Logger.log(Logger.ERROR, "Index is out of range in deleteNoneProperty() in class HTMLContentSettingsPropertyPage");//$NON-NLS-1$
+				break;
+		}
+	}
+
+	private void createIDTextField() {
+		// public ID & System ID
+		Label publicLabel = new Label(super.propertyPage, SWT.NONE);
+		GridData data = new GridData(GridData.GRAB_HORIZONTAL | GridData.FILL_HORIZONTAL);
+		data.horizontalIndent = 10;
+		publicLabel.setLayoutData(data);
+		publicLabel.setText(HTMLUIMessages.UI_Public_ID);
+		publicIdText = new Text(super.propertyPage, SWT.BORDER | SWT.READ_ONLY);
+		data = new GridData();
+
+		publicIdText.setLayoutData(data);
+
+		Label systemLabel = new Label(super.propertyPage, SWT.NONE);
+		data = new GridData(GridData.GRAB_HORIZONTAL | GridData.FILL_HORIZONTAL);
+		data.horizontalIndent = 10;
+		systemLabel.setLayoutData(data);
+		systemLabel.setText(HTMLUIMessages.UI_System_ID);
+		systemIdText = new Text(super.propertyPage, SWT.BORDER | SWT.READ_ONLY);
+		data = new GridData();
+
+		systemIdText.setLayoutData(data);
+	}
+
+
+
+	private void computeMaxWidthHint() {
+		// maxLengthString was set when HTMLDocumentTypeEntry was set in class ContentSettingsRegistry.
+		String maxLengthString = ContentSettingsRegistry.maxLengthStringInHTMLDocumentTypeRegistry;
+		String backup = this.systemIdText.getText();
+		this.systemIdText.setText(maxLengthString);
+		int maxWidthHint = this.systemIdText.computeSize(SWT.DEFAULT, SWT.DEFAULT).x;
+		this.systemIdText.setText(backup);
+
+		if (this.combo[this.N_DOCUMENT_TYPE].getLayoutData() != null)
+			((GridData) this.combo[this.N_DOCUMENT_TYPE].getLayoutData()).widthHint = maxWidthHint;
+		if (this.publicIdText.getLayoutData() != null)
+			((GridData) this.publicIdText.getLayoutData()).widthHint = maxWidthHint;
+		if (this.systemIdText.getLayoutData() != null)
+			((GridData) this.systemIdText.getLayoutData()).widthHint = maxWidthHint;
+		if (this.combo[this.N_CSS_PROFILE].getLayoutData() != null)
+			((GridData) this.combo[this.N_CSS_PROFILE].getLayoutData()).widthHint = maxWidthHint;
+		if (this.combo[this.N_TARGET_DEVICE].getLayoutData() != null)
+			((GridData) this.combo[this.N_TARGET_DEVICE].getLayoutData()).widthHint = maxWidthHint;
+
+	}
+
+
+	public void widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent e) {
+	}
+
+	public void widgetSelected(org.eclipse.swt.events.SelectionEvent event) {
+		Widget source = event.widget;
+
+		if (this.combo[this.N_DOCUMENT_TYPE].equals(source)) {
+			ComboListOnPropertyPage combo = this.combo[this.N_DOCUMENT_TYPE];
+			if (combo.getSelectionIndex() < 0)
+				return;
+			if (!combo.getSelectedValue().equals("")) {//$NON-NLS-1$
+				this.publicIdText.setText(combo.getSelectedValue());
+				if (ContentSettingsRegistry.getSystemIdFrom(combo.getSelectedValue()) != null)
+					this.systemIdText.setText(ContentSettingsRegistry.getSystemIdFrom(combo.getSelectedValue()));
+				else
+					this.systemIdText.setText("");//$NON-NLS-1$
+			}
+			else {
+				this.publicIdText.setText("");//$NON-NLS-1$
+				this.systemIdText.setText(""); //$NON-NLS-1$
+			}
+
+		}
+	}
+
+	protected void performDefaults() {
+		super.performDefaults();
+		this.publicIdText.setText("");//$NON-NLS-1$
+		this.systemIdText.setText(""); //$NON-NLS-1$
+
+	}
+
+
+}
+
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentproperties/ui/ProjectContentSettingsPropertyPage.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentproperties/ui/ProjectContentSettingsPropertyPage.java
new file mode 100644
index 0000000..333c615
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentproperties/ui/ProjectContentSettingsPropertyPage.java
@@ -0,0 +1,282 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.contentproperties.ui;
+
+import java.util.Map;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.swt.widgets.Widget;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.wst.html.ui.internal.HTMLUIMessages;
+import org.eclipse.wst.html.ui.internal.Logger;
+import org.eclipse.wst.html.ui.internal.editor.IHelpContextIds;
+import org.eclipse.wst.sse.internal.contentproperties.IContentSettings;
+import org.eclipse.wst.sse.ui.internal.contentproperties.ui.ComboListOnPropertyPage;
+import org.eclipse.wst.sse.ui.internal.contentproperties.ui.ContentSettingsPropertyPage;
+
+/**
+ * @deprecated Use ProjectHTMLContentSettingsPropertyPage instead
+ */
+public final class ProjectContentSettingsPropertyPage extends ContentSettingsPropertyPage implements org.eclipse.swt.events.SelectionListener {
+
+
+	private final int N_DOCUMENT_TYPE = 0;
+	private final int N_CSS_PROFILE = 1;
+	private final int N_TARGET_DEVICE = 2;
+
+	private Text publicIdText;
+	private Text systemIdText;
+
+	public ProjectContentSettingsPropertyPage() {
+		super();
+		numberOfCombo = 3;
+		numCols = 2;
+		numRows = 8;
+		combo = new ComboListOnPropertyPage[super.numberOfCombo];
+
+	}
+
+
+
+	protected void createDocumentTypeComboBox() {
+
+		// create description of implecit DOCTYPE
+		Label label = new Label(propertyPage, SWT.LEFT);
+		label.setText(HTMLUIMessages.UI_Description_of_role_of_following_DOCTYPE);
+		GridData data = new GridData();
+		data.horizontalAlignment = GridData.FILL;
+		data.horizontalSpan = numCols;
+		label.setLayoutData(data);
+
+		// create combobox
+		super.combo[N_DOCUMENT_TYPE] = super.createComboBoxOf(DOCUMENT_LABEL);
+		super.combo[this.N_DOCUMENT_TYPE].addSelectionListener(this);
+		// set entry list into Combo
+		ContentSettingsRegistry.setHTMLDocumentTypeRegistryInto(combo[N_DOCUMENT_TYPE]);
+		// create TextField
+		createIDTextField();
+		if (combo[N_DOCUMENT_TYPE].getItemCount() <= 0)
+			return;
+
+		String initValue = contentSettings.getProperty((IResource) super.getElement(), IContentSettings.HTML_DOCUMENT_TYPE);
+		// when either .contentsettings or element doesn't exist
+		// when attribute doesn't exists,getProperty returns empty string.
+		if (initValue == null)
+			initValue = ""; //$NON-NLS-1$
+		// set init selectionItem in Combo
+		super.setSelectionItem(combo[N_DOCUMENT_TYPE], initValue);
+		this.publicIdText.setText(initValue);
+		if (!initValue.equals("")) {//$NON-NLS-1$
+			// toro D210260
+			if (ContentSettingsRegistry.getSystemIdFrom(initValue) != null)
+				this.systemIdText.setText(ContentSettingsRegistry.getSystemIdFrom(initValue));
+			else
+				this.systemIdText.setText("");//$NON-NLS-1$
+		}
+		else
+			this.systemIdText.setText("");//$NON-NLS-1$
+
+		// create separator
+		label = new Label(propertyPage, SWT.SEPARATOR | SWT.HORIZONTAL);
+		data = new GridData();
+		data.horizontalAlignment = GridData.FILL;
+		data.horizontalSpan = numCols;
+		data.verticalSpan = 8;
+		label.setLayoutData(data);
+
+	}
+
+
+
+	protected void createCSSComboBox() {
+		super.combo[N_CSS_PROFILE] = super.createComboBoxOf(CSS_LABEL);
+
+		ContentSettingsRegistry.setCSSMetaModelRegistryInto(combo[N_CSS_PROFILE]);
+		if (combo[N_CSS_PROFILE].getItemCount() <= 0)
+			return;
+		String initValue = contentSettings.getProperty((IResource) super.getElement(), IContentSettings.CSS_PROFILE);
+		// when either .contentsettings or element doesn't exist
+		// when attribute doesn't exists,getProperty returns empty string.
+		if (initValue == null)
+			initValue = ""; //$NON-NLS-1$
+		// set init selectionItem in Combo
+		super.setSelectionItem(combo[N_CSS_PROFILE], initValue);
+	}
+
+
+
+	protected void createDeviceComboBox() {
+		super.combo[N_TARGET_DEVICE] = super.createComboBoxOf(DEVICE_LABEL);
+
+		ContentSettingsRegistry.setDeviceProfileRegistryInto(combo[N_TARGET_DEVICE]);
+		if (combo[N_TARGET_DEVICE].getItemCount() <= 0)
+			return;
+		String initValue = contentSettings.getProperty((IResource) super.getElement(), IContentSettings.DEVICE_PROFILE);
+		// when either .contentsettings or element doesn't exist
+		// when attribute doesn't exists,getProperty returns empty string.
+		if (initValue == null)
+			initValue = ""; //$NON-NLS-1$
+		// set init selectionItem in Combo
+		super.setSelectionItem(combo[N_TARGET_DEVICE], initValue);
+	}
+
+
+	protected void createSettingsPageGUI() {
+		int type = ((IResource) getElement()).getType();
+		switch (type) {
+			case IResource.PROJECT :
+				// composite = createComposite(propertyPage,numCols,numRows);
+				createDocumentTypeComboBox();
+				createCSSComboBox();
+				createDeviceComboBox();
+				computeMaxWidthHint();
+				PlatformUI.getWorkbench().getHelpSystem().setHelp(propertyPage, IHelpContextIds.WEB_CONTENT_SETTINGS_HELPID);
+				break;
+
+			default :
+				Logger.log(Logger.WARNING, "ProjectContentSettingsPropertyPage is instantiated by resource except PROJECT");//$NON-NLS-1$
+				break;
+		}
+
+	}
+
+
+
+	protected void putSelectedPropertyInto(Map properties, String valueInCombo, int index) {
+
+		switch (index) {
+			case N_DOCUMENT_TYPE :
+				// doc type
+				properties.put(IContentSettings.HTML_DOCUMENT_TYPE, valueInCombo);
+				break;
+			case N_CSS_PROFILE :
+				// css
+				properties.put(IContentSettings.CSS_PROFILE, valueInCombo);
+				break;
+			case N_TARGET_DEVICE :
+				// device
+				properties.put(IContentSettings.DEVICE_PROFILE, valueInCombo);
+				break;
+			default :
+				Logger.log(Logger.ERROR, "Index is out of range in putSelectedPropertyInto() in class ProjectContentSettingsPropertyPage");//$NON-NLS-1$
+				break;
+		}
+
+	}
+
+	protected void deleteNoneProperty(int index) {
+		switch (index) {
+			case N_DOCUMENT_TYPE :
+				// doc type
+				contentSettings.deleteProperty((IResource) super.getElement(), IContentSettings.HTML_DOCUMENT_TYPE);
+				break;
+
+			case N_CSS_PROFILE :
+				// css
+				contentSettings.deleteProperty((IResource) super.getElement(), IContentSettings.CSS_PROFILE);
+				break;
+
+			case N_TARGET_DEVICE :
+				// device
+				contentSettings.deleteProperty((IResource) super.getElement(), IContentSettings.DEVICE_PROFILE);
+				break;
+
+			default :
+				Logger.log(Logger.ERROR, "Index is out of range in deleteNoneProperty() in class ProjectContentSettingsPropertyPage");//$NON-NLS-1$
+				break;
+		}
+	}
+
+	private void createIDTextField() {
+		// public ID & System ID
+		Label publicLabel = new Label(super.propertyPage, SWT.NONE);
+		GridData data = new GridData(GridData.GRAB_HORIZONTAL | GridData.FILL_HORIZONTAL);
+		data.horizontalIndent = 10;
+		publicLabel.setLayoutData(data);
+		publicLabel.setText(HTMLUIMessages.UI_Public_ID);
+		publicIdText = new Text(super.propertyPage, SWT.BORDER | SWT.READ_ONLY);
+		data = new GridData();
+
+		publicIdText.setLayoutData(data);
+
+		Label systemLabel = new Label(super.propertyPage, SWT.NONE);
+		data = new GridData(GridData.GRAB_HORIZONTAL | GridData.FILL_HORIZONTAL);
+		data.horizontalIndent = 10;
+		systemLabel.setLayoutData(data);
+		systemLabel.setText(HTMLUIMessages.UI_System_ID);
+		systemIdText = new Text(super.propertyPage, SWT.BORDER | SWT.READ_ONLY);
+		data = new GridData();
+
+		systemIdText.setLayoutData(data);
+	}
+
+
+
+	private void computeMaxWidthHint() {
+		// maxLengthString was set when HTMLDocumentTypeEntry was set in class
+		// ContentSettingsRegistry.
+		String maxLengthString = ContentSettingsRegistry.maxLengthStringInHTMLDocumentTypeRegistry;
+		String backup = this.systemIdText.getText();
+		this.systemIdText.setText(maxLengthString);
+		int maxWidthHint = this.systemIdText.computeSize(SWT.DEFAULT, SWT.DEFAULT).x;
+		this.systemIdText.setText(backup);
+
+		if (this.combo[this.N_DOCUMENT_TYPE].getLayoutData() != null)
+			((GridData) this.combo[this.N_DOCUMENT_TYPE].getLayoutData()).widthHint = maxWidthHint;
+		if (this.publicIdText.getLayoutData() != null)
+			((GridData) this.publicIdText.getLayoutData()).widthHint = maxWidthHint;
+		if (this.systemIdText.getLayoutData() != null)
+			((GridData) this.systemIdText.getLayoutData()).widthHint = maxWidthHint;
+		if (this.combo[this.N_CSS_PROFILE].getLayoutData() != null)
+			((GridData) this.combo[this.N_CSS_PROFILE].getLayoutData()).widthHint = maxWidthHint;
+		if (this.combo[this.N_TARGET_DEVICE].getLayoutData() != null)
+			((GridData) this.combo[this.N_TARGET_DEVICE].getLayoutData()).widthHint = maxWidthHint;
+
+	}
+
+
+	public void widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent e) {
+	}
+
+	public void widgetSelected(org.eclipse.swt.events.SelectionEvent event) {
+		Widget source = event.widget;
+
+		if (this.combo[this.N_DOCUMENT_TYPE].equals(source)) {
+			ComboListOnPropertyPage combo = this.combo[this.N_DOCUMENT_TYPE];
+			if (combo.getSelectionIndex() < 0)
+				return;
+			if (!combo.getSelectedValue().equals("")) {//$NON-NLS-1$
+				this.publicIdText.setText(combo.getSelectedValue());
+				if (ContentSettingsRegistry.getSystemIdFrom(combo.getSelectedValue()) != null)
+					this.systemIdText.setText(ContentSettingsRegistry.getSystemIdFrom(combo.getSelectedValue()));
+				else
+					this.systemIdText.setText("");//$NON-NLS-1$
+			}
+			else {
+				this.publicIdText.setText("");//$NON-NLS-1$
+				this.systemIdText.setText(""); //$NON-NLS-1$
+			}
+
+		}
+	}
+
+	protected void performDefaults() {
+		super.performDefaults();
+		this.publicIdText.setText("");//$NON-NLS-1$
+		this.systemIdText.setText(""); //$NON-NLS-1$
+
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentproperties/ui/ProjectWebContentSettingsPropertyPage.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentproperties/ui/ProjectWebContentSettingsPropertyPage.java
new file mode 100644
index 0000000..6ccbe4c
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentproperties/ui/ProjectWebContentSettingsPropertyPage.java
@@ -0,0 +1,19 @@
+/*******************************************************************************
+ * Copyright (c) 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.contentproperties.ui;
+
+import org.eclipse.wst.html.ui.internal.HTMLUIMessages;
+
+public class ProjectWebContentSettingsPropertyPage extends WebContentSettingsPropertyPage {
+	public ProjectWebContentSettingsPropertyPage() {
+		setDescription(HTMLUIMessages.ProjectWebContentSettingsPropertyPage_0);
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentproperties/ui/WebContentSettingsPropertyPage.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentproperties/ui/WebContentSettingsPropertyPage.java
new file mode 100644
index 0000000..76c3a7d
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/contentproperties/ui/WebContentSettingsPropertyPage.java
@@ -0,0 +1,384 @@
+/*******************************************************************************
+ * 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
+ *     David Schneider, david.schneider@unisys.com - [142500] WTP properties pages fonts don't follow Eclipse preferences
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.contentproperties.ui;
+
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.dialogs.PropertyPage;
+import org.eclipse.wst.css.core.internal.contentproperties.CSSContentProperties;
+import org.eclipse.wst.css.core.internal.metamodel.CSSProfile;
+import org.eclipse.wst.css.core.internal.metamodel.CSSProfileRegistry;
+import org.eclipse.wst.html.core.internal.contentproperties.HTMLContentProperties;
+import org.eclipse.wst.html.core.internal.document.HTMLDocumentTypeEntry;
+import org.eclipse.wst.html.core.internal.document.HTMLDocumentTypeRegistry;
+import org.eclipse.wst.html.ui.internal.HTMLUIMessages;
+import org.eclipse.wst.html.ui.internal.Logger;
+import org.eclipse.wst.html.ui.internal.editor.IHelpContextIds;
+
+public class WebContentSettingsPropertyPage extends PropertyPage {
+	private static final String SELECT_NONE = HTMLUIMessages.UI_none;
+	private String maxLengthStringInHTMLDocumentTypeRegistry = ""; //$NON-NLS-1$
+
+	private class ComboSelectionListener implements SelectionListener {
+		public void widgetDefaultSelected(SelectionEvent e) {
+			// do nothing
+		}
+
+		public void widgetSelected(SelectionEvent e) {
+			int index = fDocumentTypeCombo.getSelectionIndex();
+			String doctype = (String) fDocumentTypeIds.get(index);
+			updateDoctypeText(index, doctype);
+		}
+	}
+
+	Combo fDocumentTypeCombo;
+	List fDocumentTypeIds;
+	private Text fPublicIdText;
+	private Text fSystemIdText;
+	private Combo fProfileCombo;
+	private List fProfileIds;
+	private SelectionListener fListener;
+
+	public WebContentSettingsPropertyPage() {
+		super();
+		setDescription(HTMLUIMessages.WebContentSettingsPropertyPage_0);
+	}
+
+	private Composite createComposite(Composite parent, int numColumns) {
+		Composite composite = new Composite(parent, SWT.NULL);
+
+		// GridLayout
+		GridLayout layout = new GridLayout();
+		layout.numColumns = numColumns;
+		composite.setLayout(layout);
+
+		// GridData
+		GridData data = new GridData(GridData.FILL, GridData.FILL, true, false);
+		data.horizontalIndent = 0;
+		composite.setLayoutData(data);
+
+		return composite;
+	}
+
+	protected Control createContents(Composite parent) {
+		Composite propertyPage = createComposite(parent, 2);
+
+		createDoctypeContents(propertyPage);
+		createCSSProfileContents(propertyPage);
+
+		populateValues();
+		initializeValues();
+		computeMaxWidthHint();
+
+		fListener = new ComboSelectionListener();
+		fDocumentTypeCombo.addSelectionListener(fListener);
+
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(propertyPage, IHelpContextIds.WEB_CONTENT_SETTINGS_HELPID);
+		Dialog.applyDialogFont(parent);
+		return propertyPage;
+	}
+
+	private void createCSSProfileContents(Composite parent) {
+		// CSS Profile
+		Label languageLabel = new Label(parent, SWT.NONE);
+		languageLabel.setText(HTMLUIMessages.UI_CSS_profile___2);
+		fProfileCombo = new Combo(parent, SWT.READ_ONLY);
+		GridData data = new GridData(GridData.FILL, GridData.FILL, true, false);
+		data.horizontalIndent = 0;
+		fProfileCombo.setLayoutData(data);
+	}
+
+	private void createDoctypeContents(Composite parent) {
+		// create description of implicit DOCTYPE
+		Text doctypeLabel = new Text(parent, SWT.READ_ONLY);
+		doctypeLabel.setText(HTMLUIMessages.UI_Description_of_role_of_following_DOCTYPE);
+		GridData data = new GridData(GridData.FILL, GridData.FILL, true, false);
+		data.horizontalIndent = 0;
+		data.horizontalSpan = 2;
+		doctypeLabel.setLayoutData(data);
+
+		// document type
+		Label languageLabel = new Label(parent, SWT.NONE);
+		languageLabel.setText(HTMLUIMessages.UI_Default_HTML_DOCTYPE_ID___1);
+		fDocumentTypeCombo = new Combo(parent, SWT.READ_ONLY);
+		data = new GridData(GridData.FILL, GridData.FILL, true, false);
+		data.horizontalIndent = 0;
+		fDocumentTypeCombo.setLayoutData(data);
+
+		// public ID
+		Label publicIdLabel = new Label(parent, SWT.NONE);
+		publicIdLabel.setText(HTMLUIMessages.UI_Public_ID);
+		fPublicIdText = new Text(parent, SWT.READ_ONLY | SWT.BORDER);
+		data = new GridData(GridData.FILL, GridData.FILL, true, false);
+		data.horizontalIndent = 0;
+		fPublicIdText.setLayoutData(data);
+
+		// system ID
+		Label systemIdLabel = new Label(parent, SWT.NONE);
+		systemIdLabel.setText(HTMLUIMessages.UI_System_ID);
+		fSystemIdText = new Text(parent, SWT.READ_ONLY | SWT.BORDER);
+		data = new GridData(GridData.FILL, GridData.FILL, true, false);
+		data.horizontalIndent = 0;
+		fSystemIdText.setLayoutData(data);
+
+		// create separator
+		Label label = new Label(parent, SWT.SEPARATOR | SWT.HORIZONTAL);
+		data = new GridData();
+		data.horizontalAlignment = GridData.FILL;
+		data.horizontalSpan = 2;
+		data.verticalSpan = 8;
+		label.setLayoutData(data);
+
+	}
+
+	/**
+	 * Get the resource this properties page is for
+	 * 
+	 * @return IResource for this properties page or null if there is no
+	 *         IResource
+	 */
+	private IResource getResource() {
+		IResource resource = null;
+		IAdaptable adaptable = getElement();
+		if (adaptable instanceof IResource) {
+			resource = (IResource) adaptable;
+		} else if (adaptable != null) {
+			Object o = adaptable.getAdapter(IResource.class);
+			if (o instanceof IResource) {
+				resource = (IResource)o;
+			}
+		}
+		return resource;
+	}
+
+	private String getSystemIdFrom(String publicId) {
+		if (publicId == null || publicId.length() == 0)
+			return null;
+		HTMLDocumentTypeRegistry reg = HTMLDocumentTypeRegistry.getInstance();
+		Enumeration e = reg.getEntries();
+		while (e.hasMoreElements()) {
+			HTMLDocumentTypeEntry entry = (HTMLDocumentTypeEntry) e.nextElement();
+			if (entry.getPublicId().equals(publicId))
+				return entry.getSystemId();
+		}
+		return null;
+	}
+
+	private void initializeValues() {
+		initializeDoctypeValues();
+		initializeCSSProfileValues();
+	}
+
+	private void initializeCSSProfileValues() {
+		int index = 0;
+		String profile = CSSContentProperties.getProperty(CSSContentProperties.CSS_PROFILE, getResource(), false);
+		if (profile != null && profile.length() > 0) {
+			/*
+			 * If item is already part of combo, select it. Otherwise, select
+			 * none.
+			 */
+			index = fProfileIds.indexOf(profile);
+		}
+		index = index >= 0 ? index : 0;
+		fProfileCombo.select(index);
+	}
+
+	private void initializeDoctypeValues() {
+		int index = 0;
+		String doctype = HTMLContentProperties.getProperty(HTMLContentProperties.DOCUMENT_TYPE, getResource(), false);
+		if (doctype != null) {
+			/*
+			 * If item is already part of combo, select it. Otherwise, select
+			 * none.
+			 */
+			index = fDocumentTypeIds.indexOf(doctype);
+		}
+
+		// set combobox
+		index = index >= 0 ? index : 0;
+		fDocumentTypeCombo.select(index);
+
+		updateDoctypeText(index, doctype);
+	}
+
+	void updateDoctypeText(int index, String doctype) {
+		if (index > 0) {
+			// set public/system id text
+			fPublicIdText.setText(doctype);
+			String systemId = getSystemIdFrom(doctype);
+			if (systemId != null)
+				fSystemIdText.setText(systemId);
+			else
+				fSystemIdText.setText(""); //$NON-NLS-1$
+		}
+		else {
+			// set public/system id text
+			fPublicIdText.setText(""); //$NON-NLS-1$
+			fSystemIdText.setText(""); //$NON-NLS-1$
+		}
+	}
+
+	private void populateValues() {
+		populateDoctypeValues();
+		populateCSSProfileValues();
+	}
+
+	private void populateCSSProfileValues() {
+		fProfileIds = new ArrayList();
+		// add none first
+		fProfileCombo.add(SELECT_NONE);
+		fProfileIds.add(null);
+
+		CSSProfileRegistry reg = CSSProfileRegistry.getInstance();
+		Iterator i = reg.getProfiles();
+		while (i.hasNext()) {
+			CSSProfile profile = (CSSProfile) i.next();
+			String id = profile.getProfileID();
+			String name = profile.getProfileName();
+			fProfileCombo.add(name);
+			fProfileIds.add(id);
+		}
+	}
+
+	private void populateDoctypeValues() {
+		fDocumentTypeIds = new ArrayList();
+		// add none first
+		fDocumentTypeCombo.add(SELECT_NONE);
+		fDocumentTypeIds.add(null);
+
+		HTMLDocumentTypeRegistry reg = HTMLDocumentTypeRegistry.getInstance();
+		Enumeration e = reg.getEntries();
+		while (e.hasMoreElements()) {
+			HTMLDocumentTypeEntry entry = (HTMLDocumentTypeEntry) e.nextElement();
+			String publicId = entry.getPublicId();
+			String displayName = entry.getDisplayName();
+			displayName = displayName != null ? displayName : publicId;
+
+			fDocumentTypeCombo.add(displayName);
+			fDocumentTypeIds.add(publicId);
+
+			if (displayName.length() > maxLengthStringInHTMLDocumentTypeRegistry.length()) {
+				maxLengthStringInHTMLDocumentTypeRegistry = displayName;
+			}
+
+			if (entry.getSystemId() == null)
+				continue; // if HTML entry
+
+
+			if (entry.getSystemId().length() > maxLengthStringInHTMLDocumentTypeRegistry.length())
+				maxLengthStringInHTMLDocumentTypeRegistry = entry.getSystemId();
+		}
+	}
+
+	private void computeMaxWidthHint() {
+		// maxLengthString was set populateDoctypeValues was called
+		String maxLengthString = maxLengthStringInHTMLDocumentTypeRegistry;
+		String backup = fSystemIdText.getText();
+		fSystemIdText.setText(maxLengthString);
+		int maxWidthHint = fSystemIdText.computeSize(SWT.DEFAULT, SWT.DEFAULT).x;
+		fSystemIdText.setText(backup);
+
+		if (fDocumentTypeCombo.getLayoutData() != null)
+			((GridData) fDocumentTypeCombo.getLayoutData()).widthHint = maxWidthHint;
+		if (fPublicIdText.getLayoutData() != null)
+			((GridData) fPublicIdText.getLayoutData()).widthHint = maxWidthHint;
+		if (fSystemIdText.getLayoutData() != null)
+			((GridData) fSystemIdText.getLayoutData()).widthHint = maxWidthHint;
+		if (fProfileCombo.getLayoutData() != null)
+			((GridData) fProfileCombo.getLayoutData()).widthHint = maxWidthHint;
+	}
+
+	private void performCSSProfileDefaults() {
+		int index = fProfileCombo.indexOf(SELECT_NONE);
+		if (index > -1)
+			fProfileCombo.select(index);
+
+		super.performDefaults();
+	}
+
+	private boolean performCSSProfileOk() {
+		int index = fProfileCombo.getSelectionIndex();
+		if (index > -1) {
+			String id = (String) fProfileIds.get(index);
+			if (id == null || id.length() == 0 || id.equalsIgnoreCase(SELECT_NONE)) {
+				// if none, use null
+				id = null;
+			}
+			try {
+				CSSContentProperties.setProperty(CSSContentProperties.CSS_PROFILE, getResource(), id);
+			}
+			catch (CoreException e) {
+				// maybe in future, let user know there was a problem saving
+				// file
+				Logger.log(Logger.WARNING_DEBUG, e.getMessage(), e);
+			}
+		}
+		return true;
+	}
+
+	protected void performDefaults() {
+		super.performDefaults();
+
+		performDoctypeDefaults();
+		performCSSProfileDefaults();
+	}
+
+	private void performDoctypeDefaults() {
+		fPublicIdText.setText("");//$NON-NLS-1$
+		fSystemIdText.setText(""); //$NON-NLS-1$
+	}
+
+	private boolean performDoctypeOk() {
+		int index = fDocumentTypeCombo.getSelectionIndex();
+		if (index > -1) {
+			String id = (String) fDocumentTypeIds.get(index);
+			if (id == null || id.equalsIgnoreCase(SELECT_NONE)) {
+				// if none, use null
+				id = null;
+			}
+			try {
+				HTMLContentProperties.setProperty(HTMLContentProperties.DOCUMENT_TYPE, getResource(), id);
+			}
+			catch (CoreException e) {
+				// maybe in future, let user know there was a problem saving
+				// file
+				Logger.log(Logger.WARNING_DEBUG, e.getMessage(), e);
+			}
+		}
+		return true;
+	}
+
+	public boolean performOk() {
+		performDoctypeOk();
+		performCSSProfileOk();
+
+		return super.performOk();
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/correction/CorrectionAssistantProviderHTML.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/correction/CorrectionAssistantProviderHTML.java
new file mode 100644
index 0000000..3ddb028
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/correction/CorrectionAssistantProviderHTML.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *   IBM - Initial API and implementation
+ *   Jens Lukowski/Innoopract - initial renaming/restructuring
+ * 
+ *******************************************************************************/
+
+package org.eclipse.wst.html.ui.internal.correction;
+
+import org.eclipse.jface.text.contentassist.ContentAssistant;
+import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
+import org.eclipse.jface.text.contentassist.IContentAssistant;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.wst.html.core.text.IHTMLPartitions;
+import org.eclipse.wst.sse.ui.internal.correction.CorrectionAssistantProvider;
+import org.eclipse.wst.xml.core.text.IXMLPartitions;
+import org.eclipse.wst.xml.ui.internal.correction.CorrectionProcessorXML;
+
+/**
+ * Correction assistant for HTML
+ * 
+ * @deprecated since 2.0 RC0 Use
+ *             org.eclipse.jface.text.quickassist.IQuickAssistProcessor;
+ */
+public class CorrectionAssistantProviderHTML extends CorrectionAssistantProvider {
+
+	public IContentAssistant getCorrectionAssistant(ISourceViewer sourceViewer) {
+		IContentAssistant ca = null;
+
+		if (sourceViewer != null) {
+			ContentAssistant assistant = new ContentAssistant();
+
+			if (sourceViewer != null) {
+				IContentAssistProcessor correctionProcessor = new CorrectionProcessorXML(sourceViewer);
+				assistant.setContentAssistProcessor(correctionProcessor, IHTMLPartitions.HTML_DEFAULT);
+				assistant.setContentAssistProcessor(correctionProcessor, IXMLPartitions.XML_CDATA);
+				assistant.setContentAssistProcessor(correctionProcessor, IXMLPartitions.XML_COMMENT);
+				assistant.setContentAssistProcessor(correctionProcessor, IXMLPartitions.XML_DECLARATION);
+				assistant.setContentAssistProcessor(correctionProcessor, IXMLPartitions.XML_PI);
+				assistant.setContentAssistProcessor(correctionProcessor, IXMLPartitions.DTD_SUBSET);
+			}
+			ca = assistant;
+		}
+
+		return ca;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/derived/SingleCharReader.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/derived/SingleCharReader.java
new file mode 100644
index 0000000..3860bbc
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/derived/SingleCharReader.java
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 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 - Initial API and implementation
+ *   Jens Lukowski/Innoopract - initial renaming/restructuring
+ * 
+ *******************************************************************************/
+
+package org.eclipse.wst.html.ui.internal.derived;
+
+import java.io.IOException;
+import java.io.Reader;
+
+/*
+ * Copied from org.eclipse.jdt.internal.corext.javadoc.SingleCharReader.
+ * Modification was made to fix statement unnecessarily nested within else
+ * clause warning in read(..).
+ */
+public abstract class SingleCharReader extends Reader {
+
+	/**
+	 * @see Reader#read()
+	 */
+	public abstract int read() throws IOException;
+
+	/**
+	 * @see Reader#read(char[],int,int)
+	 */
+	public int read(char cbuf[], int off, int len) throws IOException {
+		int end = off + len;
+		for (int i = off; i < end; i++) {
+			int ch = read();
+			if (ch == -1) {
+				if (i == off) {
+					return -1;
+				}
+				return i - off;
+			}
+			cbuf[i] = (char) ch;
+		}
+		return len;
+	}
+
+	/**
+	 * @see Reader#ready()
+	 */
+	public boolean ready() throws IOException {
+		return true;
+	}
+
+	/**
+	 * Gets the content as a String
+	 */
+	public String getString() throws IOException {
+		StringBuffer buf = new StringBuffer();
+		int ch;
+		while ((ch = read()) != -1) {
+			buf.append((char) ch);
+		}
+		return buf.toString();
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/edit/ui/ActionContributorHTML.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/edit/ui/ActionContributorHTML.java
new file mode 100644
index 0000000..c471d06
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/edit/ui/ActionContributorHTML.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.edit.ui;
+
+import org.eclipse.wst.xml.ui.internal.actions.ActionContributorXML;
+
+/**
+ *
+ * Instead, use SourcePageActionContributor for source page contributor
+ * of multi page editor.
+ * 
+ * Note that this class is still valid for single page editor.
+ */
+public class ActionContributorHTML extends ActionContributorXML {
+	private static final String[] EDITOR_IDS = {"org.eclipse.wst.html.core.htmlsource.source", "org.eclipse.wst.sse.ui.StructuredTextEditor"}; //$NON-NLS-1$ //$NON-NLS-2$
+
+
+	protected String[] getExtensionIDs() {
+		return EDITOR_IDS;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/edit/ui/CleanupActionHTMLDelegate.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/edit/ui/CleanupActionHTMLDelegate.java
new file mode 100644
index 0000000..6d8fd56
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/edit/ui/CleanupActionHTMLDelegate.java
@@ -0,0 +1,162 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+
+package org.eclipse.wst.html.ui.internal.edit.ui;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.custom.BusyIndicator;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.ui.IActionDelegate2;
+import org.eclipse.ui.IEditorActionDelegate;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IViewActionDelegate;
+import org.eclipse.ui.IViewPart;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.wst.html.core.internal.cleanup.HTMLCleanupProcessorImpl;
+import org.eclipse.wst.html.ui.internal.HTMLUIMessages;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.cleanup.IStructuredCleanupProcessor;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.ui.internal.SSEUIMessages;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
+
+/**
+ * Cleanup action delegate for HTML editor
+ */
+public class CleanupActionHTMLDelegate implements IEditorActionDelegate, IActionDelegate2, IViewActionDelegate {
+	private IEditorPart fEditor;
+	private IStructuredCleanupProcessor fCleanupProcessor;
+
+	public void setActiveEditor(IAction action, IEditorPart targetEditor) {
+		fEditor = targetEditor;
+	}
+
+	public void dispose() {
+		// nulling out just in case
+		fEditor = null;
+		fCleanupProcessor = null;
+	}
+
+	public void init(IAction action) {
+		if (action != null) {
+			action.setText(HTMLUIMessages.CleanupDocument_label);
+			action.setToolTipText(HTMLUIMessages.CleanupDocument_tooltip);
+			action.setDescription(HTMLUIMessages.CleanupDocument_description);
+		}
+	}
+
+	public void runWithEvent(IAction action, Event event) {
+		run(action);
+	}
+
+	public void init(IViewPart view) {
+		// do nothing
+	}
+
+	public void run(IAction action) {
+		if (fEditor instanceof ITextEditor) {
+			final ITextEditor editor = (ITextEditor) fEditor;
+			CleanupDialogHTML cleanupDialog = new CleanupDialogHTML(editor.getSite().getShell());
+			cleanupDialog.setisXHTMLType(isXHTML());
+			if (cleanupDialog.open() == Window.OK) {
+				// setup runnable
+				Runnable runnable = new Runnable() {
+					public void run() {
+						IStructuredCleanupProcessor cleanupProcessor = getCleanupProcessor();
+						if (cleanupProcessor != null) {
+							IStructuredModel model = null;
+							try {
+								model = StructuredModelManager.getModelManager().getExistingModelForEdit(editor.getDocumentProvider().getDocument(editor.getEditorInput()));
+								if (model != null)
+									cleanupProcessor.cleanupModel(model);
+							}
+							finally {
+								if (model != null)
+									model.releaseFromEdit();
+							}
+						}
+					}
+				};
+
+				// TODO: make independent of 'model'.
+				IStructuredModel model = null;
+				try {
+					model = StructuredModelManager.getModelManager().getExistingModelForEdit(editor.getDocumentProvider().getDocument(editor.getEditorInput()));
+					if (model != null) {
+						// begin recording
+						ITextSelection selection = (ITextSelection) editor.getSelectionProvider().getSelection();
+						model.beginRecording(this, SSEUIMessages.Cleanup_Document_UI_, SSEUIMessages.Cleanup_Document_UI_, selection.getOffset(), selection.getLength()); //$NON-NLS-1$ //$NON-NLS-2$
+
+						// tell the model that we are about to make a big
+						// model change
+						model.aboutToChangeModel();
+
+						// run
+						BusyIndicator.showWhile(fEditor.getEditorSite().getWorkbenchWindow().getShell().getDisplay(), runnable);
+					}
+				}
+				finally {
+					if (model != null) {
+						// tell the model that we are done with the big
+						// model
+						// change
+						model.changedModel();
+
+						// end recording
+						ITextSelection selection = (ITextSelection) editor.getSelectionProvider().getSelection();
+						model.endRecording(this, selection.getOffset(), selection.getLength());
+						model.releaseFromEdit();
+					}
+				}
+			}
+		}
+	}
+
+	public void selectionChanged(IAction action, ISelection selection) {
+		// do nothing
+	}
+
+	IStructuredCleanupProcessor getCleanupProcessor() {
+		if (fCleanupProcessor == null)
+			fCleanupProcessor = new HTMLCleanupProcessorImpl();
+
+		return fCleanupProcessor;
+	}
+
+	private boolean isXHTML() {
+		boolean isxhtml = false;
+		if (fEditor instanceof ITextEditor) {
+			ITextEditor textEditor = (ITextEditor) fEditor;
+			IDocument document = textEditor.getDocumentProvider().getDocument(textEditor.getEditorInput());
+			IStructuredModel model = null;
+			try {
+				model = StructuredModelManager.getModelManager().getExistingModelForRead(document);
+				if (model instanceof IDOMModel) {
+					IDOMDocument domDocument = ((IDOMModel) model).getDocument();
+					if (domDocument != null)
+						isxhtml = domDocument.isXMLType();
+				}
+			}
+			finally {
+				if (model != null) {
+					model.releaseFromRead();
+				}
+			}
+		}
+		return isxhtml;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/edit/ui/CleanupDialogHTML.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/edit/ui/CleanupDialogHTML.java
new file mode 100644
index 0000000..9764210
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/edit/ui/CleanupDialogHTML.java
@@ -0,0 +1,333 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.edit.ui;
+
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.wst.html.core.internal.HTMLCorePlugin;
+import org.eclipse.wst.html.core.internal.preferences.HTMLCorePreferenceNames;
+import org.eclipse.wst.html.ui.internal.HTMLUIMessages;
+import org.eclipse.wst.html.ui.internal.editor.IHelpContextIds;
+import org.eclipse.wst.sse.core.internal.encoding.CommonEncodingPreferenceNames;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+
+public class CleanupDialogHTML extends Dialog implements SelectionListener {
+
+	protected Button fRadioButtonTagNameCaseAsis;
+	protected Button fRadioButtonTagNameCaseLower;
+	protected Button fRadioButtonTagNameCaseUpper;
+	protected Button fRadioButtonAttrNameCaseAsis;
+	protected Button fRadioButtonAttrNameCaseLower;
+	protected Button fRadioButtonAttrNameCaseUpper;
+	protected Button fCheckBoxCompressEmptyElementTags;
+	protected Button fCheckBoxInsertRequiredAttrs;
+	protected Button fCheckBoxInsertMissingTags;
+	protected Button fCheckBoxQuoteAttrValues;
+	protected Button fCheckBoxFormatSource;
+	protected Button fCheckBoxConvertEOLCodes;
+	protected Button fRadioButtonConvertEOLWindows;
+	protected Button fRadioButtonConvertEOLUnix;
+	protected Button fRadioButtonConvertEOLMac;
+	protected Preferences fPreferences = null;
+	private boolean fIsXHTML = false;
+	private Group fTagNameCase;
+	private Group fAttrNameCase;
+
+	public CleanupDialogHTML(Shell shell) {
+		super(shell);
+	}
+
+	protected Control createDialogArea(Composite parent) {
+		getShell().setText(HTMLUIMessages.Cleanup_UI_);
+		Composite composite = new Composite(parent, SWT.NULL);
+
+		createDialogAreaInComposite(composite);
+		initializeOptions();
+
+		return composite;
+	}
+
+	protected Control createButtonBar(Composite parent) {
+		Control c = super.createButtonBar(parent);
+		okButtonEnablement();
+		return c;
+	}
+
+	protected void createDialogAreaInCompositeForHTML(Composite composite) {
+		// Convert tag name case
+		// d257064 need to associate group w/ radio buttons so radio buttons
+		// header can be read
+		fTagNameCase = new Group(composite, SWT.NONE);
+		fTagNameCase.setText(HTMLUIMessages.Tag_name_case_for_HTML_UI_);
+		GridLayout hLayout = new GridLayout();
+		hLayout.numColumns = 3;
+		fTagNameCase.setLayout(hLayout);
+		fRadioButtonTagNameCaseAsis = new Button(fTagNameCase, SWT.RADIO);
+		fRadioButtonTagNameCaseAsis.setText(HTMLUIMessages.Tag_name_case_As_is_UI_);
+		fRadioButtonTagNameCaseAsis.addSelectionListener(this);
+		fRadioButtonTagNameCaseLower = new Button(fTagNameCase, SWT.RADIO);
+		fRadioButtonTagNameCaseLower.setText(HTMLUIMessages.Tag_name_case_Lower_UI_);
+		fRadioButtonTagNameCaseLower.addSelectionListener(this);
+		fRadioButtonTagNameCaseUpper = new Button(fTagNameCase, SWT.RADIO);
+		fRadioButtonTagNameCaseUpper.setText(HTMLUIMessages.Tag_name_case_Upper_UI_);
+		fRadioButtonTagNameCaseUpper.addSelectionListener(this);
+
+		// Convert attr name case
+		// d257064 need to associate group w/ radio buttons so radio buttons
+		// header can be read
+		fAttrNameCase = new Group(composite, SWT.NONE);
+		fAttrNameCase.setText(HTMLUIMessages.Attribute_name_case_for_HTML_UI_);
+		fAttrNameCase.setLayout(hLayout);
+		fRadioButtonAttrNameCaseAsis = new Button(fAttrNameCase, SWT.RADIO);
+		fRadioButtonAttrNameCaseAsis.setText(HTMLUIMessages.Attribute_name_case_As_is_UI_);
+		fRadioButtonAttrNameCaseAsis.addSelectionListener(this);
+		fRadioButtonAttrNameCaseLower = new Button(fAttrNameCase, SWT.RADIO);
+		fRadioButtonAttrNameCaseLower.setText(HTMLUIMessages.Attribute_name_case_Lower_UI_);
+		fRadioButtonAttrNameCaseLower.addSelectionListener(this);
+		fRadioButtonAttrNameCaseUpper = new Button(fAttrNameCase, SWT.RADIO);
+		fRadioButtonAttrNameCaseUpper.setText(HTMLUIMessages.Attribute_name_case_Upper_UI_);
+		fRadioButtonAttrNameCaseUpper.addSelectionListener(this);
+	}
+
+	protected void createDialogAreaInComposite(Composite composite) {
+		createDialogAreaInCompositeForHTML(composite);
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, IHelpContextIds.CLEANUP_HTML_HELPID); // use
+		// HTML
+		// specific
+		// help
+
+		GridLayout layout = new GridLayout();
+		layout.numColumns = 1;
+		layout.makeColumnsEqualWidth = true;
+		composite.setLayout(layout);
+
+		// Compress empty element tags
+		fCheckBoxCompressEmptyElementTags = new Button(composite, SWT.CHECK);
+		fCheckBoxCompressEmptyElementTags.setText(XMLUIMessages.Compress_empty_element_tags_UI_);
+		fCheckBoxCompressEmptyElementTags.addSelectionListener(this);
+
+		// Insert missing required attrs
+		fCheckBoxInsertRequiredAttrs = new Button(composite, SWT.CHECK);
+		fCheckBoxInsertRequiredAttrs.setText(HTMLUIMessages.Insert_required_attributes_UI_);
+		fCheckBoxInsertRequiredAttrs.addSelectionListener(this);
+
+		// Insert missing begin/end tags
+		fCheckBoxInsertMissingTags = new Button(composite, SWT.CHECK);
+		fCheckBoxInsertMissingTags.setText(HTMLUIMessages.Insert_missing_tags_UI_);
+		fCheckBoxInsertMissingTags.addSelectionListener(this);
+
+		// Quote attribute values
+		fCheckBoxQuoteAttrValues = new Button(composite, SWT.CHECK);
+		fCheckBoxQuoteAttrValues.setText(HTMLUIMessages.Quote_attribute_values_UI_);
+		fCheckBoxQuoteAttrValues.addSelectionListener(this);
+
+		// Format source
+		fCheckBoxFormatSource = new Button(composite, SWT.CHECK);
+		fCheckBoxFormatSource.setText(HTMLUIMessages.Format_source_UI_);
+		fCheckBoxFormatSource.addSelectionListener(this);
+
+		// Convert EOL code
+		fCheckBoxConvertEOLCodes = new Button(composite, SWT.CHECK);
+		fCheckBoxConvertEOLCodes.setText(HTMLUIMessages.Convert_EOL_codes_UI_);
+		fCheckBoxConvertEOLCodes.addSelectionListener(this);
+		Composite EOLCodes = new Composite(composite, SWT.NULL);
+		GridLayout hLayout = new GridLayout();
+		hLayout.numColumns = 3;
+		EOLCodes.setLayout(hLayout);
+		fRadioButtonConvertEOLWindows = new Button(EOLCodes, SWT.RADIO);
+		fRadioButtonConvertEOLWindows.setText(HTMLUIMessages.EOL_Windows_UI);
+		fRadioButtonConvertEOLWindows.addSelectionListener(this);
+		fRadioButtonConvertEOLUnix = new Button(EOLCodes, SWT.RADIO);
+		fRadioButtonConvertEOLUnix.setText(HTMLUIMessages.EOL_Unix_UI);
+		fRadioButtonConvertEOLUnix.addSelectionListener(this);
+		fRadioButtonConvertEOLMac = new Button(EOLCodes, SWT.RADIO);
+		fRadioButtonConvertEOLMac.setText(HTMLUIMessages.EOL_Mac_UI);
+		fRadioButtonConvertEOLMac.addSelectionListener(this);
+	}
+
+	protected void okPressed() {
+		storeOptions();
+
+		super.okPressed();
+	}
+
+	protected void initializeOptionsForHTML() {
+		boolean caseSensitive = isXHTMLType();
+
+		if (caseSensitive) {
+			fRadioButtonTagNameCaseLower.setSelection(true);
+		} else {
+			int tagNameCase = getModelPreferences().getInt(HTMLCorePreferenceNames.CLEANUP_TAG_NAME_CASE);
+			if (tagNameCase == HTMLCorePreferenceNames.UPPER) {
+				fRadioButtonTagNameCaseUpper.setSelection(true);
+			} else if (tagNameCase == HTMLCorePreferenceNames.LOWER)
+				fRadioButtonTagNameCaseLower.setSelection(true);
+			else
+				fRadioButtonTagNameCaseAsis.setSelection(true);
+		}
+
+		if (caseSensitive) {
+			fRadioButtonAttrNameCaseLower.setSelection(true);
+		} else {
+			int attrNameCase = getModelPreferences().getInt(HTMLCorePreferenceNames.CLEANUP_ATTR_NAME_CASE);
+			if (attrNameCase == HTMLCorePreferenceNames.UPPER) {
+				fRadioButtonAttrNameCaseUpper.setSelection(true);
+			} else if (attrNameCase == HTMLCorePreferenceNames.LOWER)
+				fRadioButtonAttrNameCaseLower.setSelection(true);
+			else
+				fRadioButtonAttrNameCaseAsis.setSelection(true);
+		}
+
+		enableCaseControls(!caseSensitive);
+	}
+
+	protected void initializeOptions() {
+		initializeOptionsForHTML();
+
+		fCheckBoxCompressEmptyElementTags.setSelection(getModelPreferences().getBoolean(HTMLCorePreferenceNames.COMPRESS_EMPTY_ELEMENT_TAGS));
+		fCheckBoxInsertRequiredAttrs.setSelection(getModelPreferences().getBoolean(HTMLCorePreferenceNames.INSERT_REQUIRED_ATTRS));
+		fCheckBoxInsertMissingTags.setSelection(getModelPreferences().getBoolean(HTMLCorePreferenceNames.INSERT_MISSING_TAGS));
+		fCheckBoxQuoteAttrValues.setSelection(getModelPreferences().getBoolean(HTMLCorePreferenceNames.QUOTE_ATTR_VALUES));
+		fCheckBoxFormatSource.setSelection(getModelPreferences().getBoolean(HTMLCorePreferenceNames.FORMAT_SOURCE));
+		fCheckBoxConvertEOLCodes.setSelection(getModelPreferences().getBoolean(HTMLCorePreferenceNames.CONVERT_EOL_CODES));
+		if (fCheckBoxConvertEOLCodes.getSelection()) {
+			String EOLCode = getModelPreferences().getString(HTMLCorePreferenceNames.CLEANUP_EOL_CODE);
+			if (EOLCode == CommonEncodingPreferenceNames.LF)
+				fRadioButtonConvertEOLUnix.setSelection(true);
+			else if (EOLCode == CommonEncodingPreferenceNames.CR)
+				fRadioButtonConvertEOLMac.setSelection(true);
+			else
+				fRadioButtonConvertEOLWindows.setSelection(true);
+		}
+		enableEOLCodeRadios(fCheckBoxConvertEOLCodes.getSelection());
+	}
+
+	protected void storeOptionsForHTML() {
+		if (!isXHTMLType() && fRadioButtonTagNameCaseUpper.getSelection())
+			getModelPreferences().setValue(HTMLCorePreferenceNames.CLEANUP_TAG_NAME_CASE, HTMLCorePreferenceNames.UPPER);
+		else if (fRadioButtonTagNameCaseLower.getSelection())
+			getModelPreferences().setValue(HTMLCorePreferenceNames.CLEANUP_TAG_NAME_CASE, HTMLCorePreferenceNames.LOWER);
+		else
+			getModelPreferences().setValue(HTMLCorePreferenceNames.CLEANUP_TAG_NAME_CASE, HTMLCorePreferenceNames.ASIS);
+
+		if (!isXHTMLType() && fRadioButtonAttrNameCaseUpper.getSelection())
+			getModelPreferences().setValue(HTMLCorePreferenceNames.CLEANUP_ATTR_NAME_CASE, HTMLCorePreferenceNames.UPPER);
+		else if (fRadioButtonAttrNameCaseLower.getSelection())
+			getModelPreferences().setValue(HTMLCorePreferenceNames.CLEANUP_ATTR_NAME_CASE, HTMLCorePreferenceNames.LOWER);
+		else
+			getModelPreferences().setValue(HTMLCorePreferenceNames.CLEANUP_ATTR_NAME_CASE, HTMLCorePreferenceNames.ASIS);
+
+		// explicitly save plugin preferences so values are stored
+		HTMLCorePlugin.getDefault().savePluginPreferences();
+	}
+
+	protected void storeOptions() {
+		storeOptionsForHTML();
+
+		getModelPreferences().setValue(HTMLCorePreferenceNames.COMPRESS_EMPTY_ELEMENT_TAGS, fCheckBoxCompressEmptyElementTags.getSelection());
+		getModelPreferences().setValue(HTMLCorePreferenceNames.INSERT_REQUIRED_ATTRS, fCheckBoxInsertRequiredAttrs.getSelection());
+		getModelPreferences().setValue(HTMLCorePreferenceNames.INSERT_MISSING_TAGS, fCheckBoxInsertMissingTags.getSelection());
+		getModelPreferences().setValue(HTMLCorePreferenceNames.QUOTE_ATTR_VALUES, fCheckBoxQuoteAttrValues.getSelection());
+		getModelPreferences().setValue(HTMLCorePreferenceNames.FORMAT_SOURCE, fCheckBoxFormatSource.getSelection());
+		getModelPreferences().setValue(HTMLCorePreferenceNames.CONVERT_EOL_CODES, fCheckBoxConvertEOLCodes.getSelection());
+
+		if (fCheckBoxConvertEOLCodes.getSelection()) {
+			if (fRadioButtonConvertEOLUnix.getSelection()) {
+				getModelPreferences().setValue(HTMLCorePreferenceNames.CLEANUP_EOL_CODE, CommonEncodingPreferenceNames.LF);
+			} else if (fRadioButtonConvertEOLMac.getSelection()) {
+				getModelPreferences().setValue(HTMLCorePreferenceNames.CLEANUP_EOL_CODE, CommonEncodingPreferenceNames.CR);
+			} else {
+				getModelPreferences().setValue(HTMLCorePreferenceNames.CLEANUP_EOL_CODE, CommonEncodingPreferenceNames.CRLF);
+			}
+		}
+
+		// explicitly save plugin preferences so values are stored
+		HTMLCorePlugin.getDefault().savePluginPreferences();
+	}
+
+	public void widgetDefaultSelected(SelectionEvent e) {
+		widgetSelected(e);
+	}
+
+	public void widgetSelected(SelectionEvent e) {
+		if (e.widget == fCheckBoxConvertEOLCodes)
+			enableEOLCodeRadios(fCheckBoxConvertEOLCodes.getSelection());
+
+		okButtonEnablement();
+	}
+
+	protected Preferences getModelPreferences() {
+		return HTMLCorePlugin.getDefault().getPluginPreferences();
+	}
+
+	private boolean isXHTMLType() {
+		return fIsXHTML;
+	}
+
+	protected void enableEOLCodeRadios(boolean enable) {
+		if ((fRadioButtonConvertEOLWindows != null) && (fRadioButtonConvertEOLUnix != null) && (fRadioButtonConvertEOLMac != null)) {
+			fRadioButtonConvertEOLWindows.setEnabled(enable);
+			fRadioButtonConvertEOLUnix.setEnabled(enable);
+			fRadioButtonConvertEOLMac.setEnabled(enable);
+
+			if (!fRadioButtonConvertEOLWindows.getSelection() && !fRadioButtonConvertEOLUnix.getSelection() && !fRadioButtonConvertEOLMac.getSelection())
+				fRadioButtonConvertEOLWindows.setSelection(true);
+		}
+	}
+
+	/**
+	 * Enables/disables the tag/attr case radio buttons
+	 */
+	private void enableCaseControls(boolean enable) {
+		fTagNameCase.setEnabled(enable);
+		fRadioButtonTagNameCaseAsis.setEnabled(enable);
+		fRadioButtonTagNameCaseLower.setEnabled(enable);
+		fRadioButtonTagNameCaseUpper.setEnabled(enable);
+
+		fAttrNameCase.setEnabled(enable);
+		fRadioButtonAttrNameCaseAsis.setEnabled(enable);
+		fRadioButtonAttrNameCaseLower.setEnabled(enable);
+		fRadioButtonAttrNameCaseUpper.setEnabled(enable);
+	}
+
+	/**
+	 * Enables/disables OK button
+	 * 
+	 */
+	private void okButtonEnablement() {
+		boolean tagNameCaseCheck = ((fRadioButtonTagNameCaseUpper != null && fRadioButtonTagNameCaseUpper.getSelection()) || fRadioButtonTagNameCaseLower.getSelection());
+		boolean attrNameCaseCheck = ((fRadioButtonAttrNameCaseUpper != null && fRadioButtonAttrNameCaseUpper.getSelection()) || fRadioButtonAttrNameCaseLower.getSelection());
+		boolean eolCheck = fCheckBoxConvertEOLCodes.getSelection() && (fRadioButtonConvertEOLUnix.getSelection() || fRadioButtonConvertEOLMac.getSelection() || fRadioButtonConvertEOLWindows.getSelection());
+		boolean buttonEnabled = false;
+		if (isXHTMLType()){
+			buttonEnabled = fCheckBoxInsertRequiredAttrs.getSelection() || fCheckBoxInsertMissingTags.getSelection() || fCheckBoxQuoteAttrValues.getSelection() || fCheckBoxFormatSource.getSelection() || eolCheck;
+		}
+		else {
+			buttonEnabled = tagNameCaseCheck || attrNameCaseCheck || fCheckBoxInsertRequiredAttrs.getSelection() || fCheckBoxInsertMissingTags.getSelection() || fCheckBoxQuoteAttrValues.getSelection() || fCheckBoxFormatSource.getSelection() || eolCheck;
+		}
+		getButton(IDialogConstants.OK_ID).setEnabled(buttonEnabled);
+	}
+
+	void setisXHTMLType(boolean isXHTML) {
+		fIsXHTML = isXHTML;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/edit/ui/CleanupDocumentHandler.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/edit/ui/CleanupDocumentHandler.java
new file mode 100644
index 0000000..75c5267
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/edit/ui/CleanupDocumentHandler.java
@@ -0,0 +1,137 @@
+/*******************************************************************************
+ * Copyright (c) 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.edit.ui;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.commands.IHandler;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.custom.BusyIndicator;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.handlers.HandlerUtil;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.wst.html.core.internal.cleanup.HTMLCleanupProcessorImpl;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.cleanup.IStructuredCleanupProcessor;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.ui.internal.SSEUIMessages;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
+
+public class CleanupDocumentHandler extends AbstractHandler implements IHandler {
+	private IStructuredCleanupProcessor fCleanupProcessor;
+
+	public void dispose() {
+		// nulling out just in case
+		fCleanupProcessor = null;
+	}
+
+	public Object execute(ExecutionEvent event) throws ExecutionException {
+		IEditorPart editorPart = HandlerUtil.getActiveEditor(event);
+		ITextEditor textEditor = null;
+		if (editorPart instanceof ITextEditor)
+			textEditor = (ITextEditor) editorPart;
+		else {
+			Object o = editorPart.getAdapter(ITextEditor.class);
+			if (o != null)
+				textEditor = (ITextEditor) o;
+		}
+		if (textEditor != null) {
+			final ITextEditor editor = textEditor;
+			CleanupDialogHTML cleanupDialog = new CleanupDialogHTML(editor.getSite().getShell());
+			cleanupDialog.setisXHTMLType(isXHTML(editor));
+			if (cleanupDialog.open() == Window.OK) {
+				// setup runnable
+				Runnable runnable = new Runnable() {
+					public void run() {
+						IStructuredCleanupProcessor cleanupProcessor = getCleanupProcessor();
+						if (cleanupProcessor != null) {
+							IStructuredModel model = null;
+							try {
+								model = StructuredModelManager.getModelManager().getExistingModelForEdit(editor.getDocumentProvider().getDocument(editor.getEditorInput()));
+								if (model != null)
+									cleanupProcessor.cleanupModel(model);
+							}
+							finally {
+								if (model != null)
+									model.releaseFromEdit();
+							}
+						}
+					}
+				};
+
+				// TODO: make independent of 'model'.
+				IStructuredModel model = null;
+				try {
+					model = StructuredModelManager.getModelManager().getExistingModelForEdit(editor.getDocumentProvider().getDocument(editor.getEditorInput()));
+					if (model != null) {
+						// begin recording
+						ITextSelection selection = (ITextSelection) editor.getSelectionProvider().getSelection();
+						model.beginRecording(this, SSEUIMessages.Cleanup_Document_UI_, SSEUIMessages.Cleanup_Document_UI_, selection.getOffset(), selection.getLength()); //$NON-NLS-1$ //$NON-NLS-2$
+
+						// tell the model that we are about to make a big
+						// model change
+						model.aboutToChangeModel();
+
+						// run
+						BusyIndicator.showWhile(editor.getEditorSite().getWorkbenchWindow().getShell().getDisplay(), runnable);
+					}
+				}
+				finally {
+					if (model != null) {
+						// tell the model that we are done with the big
+						// model
+						// change
+						model.changedModel();
+
+						// end recording
+						ITextSelection selection = (ITextSelection) editor.getSelectionProvider().getSelection();
+						model.endRecording(this, selection.getOffset(), selection.getLength());
+						model.releaseFromEdit();
+					}
+				}
+			}
+		}
+		return null;
+	}
+
+	IStructuredCleanupProcessor getCleanupProcessor() {
+		if (fCleanupProcessor == null)
+			fCleanupProcessor = new HTMLCleanupProcessorImpl();
+
+		return fCleanupProcessor;
+	}
+	
+	private boolean isXHTML(ITextEditor editor) {
+		boolean isxhtml = false;
+		if (editor != null) {
+			IDocument document = editor.getDocumentProvider().getDocument(editor.getEditorInput());
+			IStructuredModel model = null;
+			try {
+				model = StructuredModelManager.getModelManager().getExistingModelForRead(document);
+				if (model instanceof IDOMModel) {
+					IDOMDocument domDocument = ((IDOMModel) model).getDocument();
+					if (domDocument != null)
+						isxhtml = domDocument.isXMLType();
+				}
+			}
+			finally {
+				if (model != null) {
+					model.releaseFromRead();
+				}
+			}
+		}
+		return isxhtml;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/editor/HTMLEditorPluginImageHelper.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/editor/HTMLEditorPluginImageHelper.java
new file mode 100644
index 0000000..ab6450a
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/editor/HTMLEditorPluginImageHelper.java
@@ -0,0 +1,148 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.editor;
+
+import java.util.HashMap;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.resource.ImageRegistry;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.eclipse.wst.html.ui.internal.HTMLUIPlugin;
+
+
+/**
+ * Helper class to handle images provided by this plug-in.
+ */
+public class HTMLEditorPluginImageHelper {
+	private final String PLUGINID = HTMLUIPlugin.ID;
+	private static HTMLEditorPluginImageHelper instance = null;
+
+	//	 save a descriptor for each image
+	private HashMap fImageDescRegistry = null;
+
+	/**
+	 * Gets the instance.
+	 * 
+	 * @return Returns a HTMLEditorPluginImageHelper
+	 */
+	public synchronized static HTMLEditorPluginImageHelper getInstance() {
+		if (instance == null)
+			instance = new HTMLEditorPluginImageHelper();
+		return instance;
+	}
+
+	/**
+	 * Retrieves the image associated with resource from the image registry.
+	 * If the image cannot be retrieved, attempt to find and load the image at
+	 * the location specified in resource.
+	 * 
+	 * @param resource
+	 *            the image to retrieve
+	 * @return Image the image associated with resource or null if one could
+	 *         not be found
+	 */
+	public Image getImage(String resource) {
+		Image image = getImageRegistry().get(resource);
+		if (image == null) {
+			// create an image
+			image = createImage(resource);
+		}
+		return image;
+	}
+
+	/**
+	 * Retrieves the image descriptor associated with resource from the image
+	 * descriptor registry. If the image descriptor cannot be retrieved,
+	 * attempt to find and load the image descriptor at the location specified
+	 * in resource.
+	 * 
+	 * @param resource
+	 *            the image descriptor to retrieve
+	 * @return ImageDescriptor the image descriptor assocated with resource or
+	 *         the default "missing" image descriptor if one could not be
+	 *         found
+	 */
+	public ImageDescriptor getImageDescriptor(String resource) {
+		ImageDescriptor imageDescriptor = null;
+		Object o = getImageDescriptorRegistry().get(resource);
+		if (o == null) {
+			//create a descriptor
+			imageDescriptor = createImageDescriptor(resource);
+		}
+		else {
+			imageDescriptor = (ImageDescriptor) o;
+		}
+		return imageDescriptor;
+	}
+
+	/**
+	 * Returns the image descriptor registry for this plugin.
+	 * 
+	 * @return HashMap - image descriptor registry for this plugin
+	 */
+	private HashMap getImageDescriptorRegistry() {
+		if (fImageDescRegistry == null)
+			fImageDescRegistry = new HashMap();
+		return fImageDescRegistry;
+	}
+
+	/**
+	 * Returns the image registry for this plugin.
+	 * 
+	 * @return ImageRegistry - image registry for this plugin
+	 */
+	private ImageRegistry getImageRegistry() {
+		return HTMLUIPlugin.getInstance().getImageRegistry();
+	}
+
+	/**
+	 * Creates an image from the given resource and adds the image to the
+	 * image registry.
+	 * 
+	 * @param resource
+	 * @return Image
+	 */
+	private Image createImage(String resource) {
+		ImageDescriptor desc = getImageDescriptor(resource);
+		Image image = null;
+		
+		if (desc != null) {
+			image = desc.createImage();
+			// dont add the missing image descriptor image to the image registry
+			if (!desc.equals(ImageDescriptor.getMissingImageDescriptor()))
+				getImageRegistry().put(resource, image);
+		}
+		return image;
+	}
+
+	/**
+	 * Creates an image descriptor from the given imageFilePath and adds the
+	 * image descriptor to the image descriptor registry. If an image
+	 * descriptor could not be created, the default "missing" image descriptor
+	 * is returned but not added to the image descriptor registry.
+	 * 
+	 * @param imageFilePath
+	 * @return ImageDescriptor image descriptor for imageFilePath or default
+	 *         "missing" image descriptor if resource could not be found
+	 */
+	private ImageDescriptor createImageDescriptor(String imageFilePath) {
+		ImageDescriptor imageDescriptor = AbstractUIPlugin.imageDescriptorFromPlugin(PLUGINID, imageFilePath);
+		if (imageDescriptor != null) {
+			getImageDescriptorRegistry().put(imageFilePath, imageDescriptor);
+		}
+		else {
+			imageDescriptor = ImageDescriptor.getMissingImageDescriptor();
+		}
+
+		return imageDescriptor;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/editor/HTMLEditorPluginImages.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/editor/HTMLEditorPluginImages.java
new file mode 100644
index 0000000..1fa0f24
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/editor/HTMLEditorPluginImages.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.editor;
+
+/**
+ * Bundle of most images used by the HTML Editor plug-in.
+ */
+public class HTMLEditorPluginImages { 	
+	public static final String IMG_OBJ_TABLE = "icons/full/obj16/table.gif";			//$NON-NLS-1$
+	public static final String IMG_OBJ_TAG_ANCHOR = "icons/full/obj16/tag-anchor.gif";			//$NON-NLS-1$
+	public static final String IMG_OBJ_TAG_BODY = "icons/full/obj16/tag-body.gif";			//$NON-NLS-1$
+	public static final String IMG_OBJ_TAG_BUTTON = "icons/full/obj16/tag-button.gif";			//$NON-NLS-1$
+	public static final String IMG_OBJ_TAG_FONT = "icons/full/obj16/tag-font.gif";			//$NON-NLS-1$
+	public static final String IMG_OBJ_TAG_FORM = "icons/full/obj16/tag-form.gif";			//$NON-NLS-1$
+	public static final String IMG_OBJ_TAG_GENERIC = "icons/full/obj16/tag-generic.gif";			//$NON-NLS-1$
+	public static final String IMG_OBJ_TAG_HTML = "icons/full/obj16/tag-html.gif";			//$NON-NLS-1$
+	public static final String IMG_OBJ_TAG_IMAGE_MAP = "icons/full/obj16/tag-image-map.gif";			//$NON-NLS-1$
+	public static final String IMG_OBJ_TAG_IMAGE = "icons/full/obj16/tag-image.gif";			//$NON-NLS-1$
+	public static final String IMG_OBJ_TAG_JSP = "icons/full/obj16/tag-jsp.gif";			//$NON-NLS-1$
+	public static final String IMG_OBJ_TAG_TEMPLATE = "icons/full/obj16/tag-template.gif";			//$NON-NLS-1$
+	public static final String IMG_OBJ_TAG_TITLE = "icons/full/obj16/tag-title.gif";			//$NON-NLS-1$
+	public static final String IMG_OBJ_TAG = "icons/full/obj16/tag.gif";			//$NON-NLS-1$
+	public static final String IMG_WIZBAN_NEWHTMLFILE = "icons/full/wizban/newhfile_wiz.png";			//$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/editor/IHelpContextIds.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/editor/IHelpContextIds.java
new file mode 100644
index 0000000..569b724
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/editor/IHelpContextIds.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.editor;
+
+import org.eclipse.wst.html.ui.internal.HTMLUIPlugin;
+
+/**
+ * Help context ids for the HTML Source Editor.
+ * <p>
+ * This interface contains constants only; it is not intended to be implemented.
+ * </p>
+ * 
+ */
+public interface IHelpContextIds {
+	// org.eclipse.wst.html.ui.
+	public static final String PREFIX = HTMLUIPlugin.ID + "."; //$NON-NLS-1$
+
+	// // figured out on the fly
+	// // HTML Source page editor
+	// public static final String HTML_SOURCEVIEW_HELPID =
+	// ContentTypeIdForHTML.ContentTypeID_HTML +"_source_HelpId";
+	// //$NON-NLS-1$
+	
+	// HTML Files Preference page
+	public static final String HTML_PREFWEBX_FILES_HELPID = PREFIX + "webx0030"; //$NON-NLS-1$
+	// HTML Source Preference page
+	public static final String HTML_PREFWEBX_SOURCE_HELPID = PREFIX + "webx0031"; //$NON-NLS-1$
+	// HTML Styles Preference page
+	public static final String HTML_PREFWEBX_STYLES_HELPID = PREFIX + "webx0032"; //$NON-NLS-1$
+	// HTML Templates Preference page
+	public static final String HTML_PREFWEBX_TEMPLATES_HELPID = PREFIX + "webx0033"; //$NON-NLS-1$
+		
+	// HTML Cleanup dialog
+	public static final String CLEANUP_HTML_HELPID = PREFIX + "xmlm1100"; //$NON-NLS-1$
+	
+	// HTML Content Settings
+	public static final String WEB_CONTENT_SETTINGS_HELPID = PREFIX + "misc0170"; //$NON-NLS-1$
+	
+	// HTML New File Wizard - Template Page
+	public static final String HTML_NEWWIZARD_TEMPLATE_HELPID = PREFIX + "htmlw0010"; //$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/handlers/HTMLFindOccurrencesHandler.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/handlers/HTMLFindOccurrencesHandler.java
new file mode 100644
index 0000000..68cc317
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/handlers/HTMLFindOccurrencesHandler.java
@@ -0,0 +1,154 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 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
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.handlers;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.commands.IHandler;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.text.ITypedRegion;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IFileEditorInput;
+import org.eclipse.ui.handlers.HandlerUtil;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.wst.html.ui.internal.search.HTMLFindOccurrencesProcessor;
+import org.eclipse.wst.sse.ui.StructuredTextEditor;
+import org.eclipse.wst.sse.ui.internal.ExtendedConfigurationBuilder;
+import org.eclipse.wst.sse.ui.internal.SSEUIMessages;
+import org.eclipse.wst.sse.ui.internal.search.FindOccurrencesProcessor;
+import org.eclipse.wst.sse.ui.internal.util.PlatformStatusLineUtil;
+
+public class HTMLFindOccurrencesHandler extends AbstractHandler implements IHandler {
+	private List fProcessors;
+
+	
+	public Object execute(ExecutionEvent event) throws ExecutionException {
+		IEditorPart editor = HandlerUtil.getActiveEditor(event);
+		ITextEditor textEditor = null;
+		boolean okay = false;
+		
+		if (editor instanceof ITextEditor)
+			textEditor = (ITextEditor) editor;
+		else {
+			Object o = editor.getAdapter(ITextEditor.class);
+			if (o != null)
+				textEditor = (ITextEditor) o;
+		}
+		
+		if (textEditor != null) {
+			IDocument document = textEditor.getDocumentProvider().getDocument(textEditor.getEditorInput());
+			if (document != null) {
+				ITextSelection textSelection = getTextSelection(textEditor);
+				FindOccurrencesProcessor findOccurrenceProcessor = getProcessorForCurrentSelection(document, textSelection);
+				if (findOccurrenceProcessor != null) {
+					if (textEditor.getEditorInput() instanceof IFileEditorInput) {
+						IFile file = ((IFileEditorInput) textEditor.getEditorInput()).getFile();
+						okay = findOccurrenceProcessor.findOccurrences(document, textSelection, file);
+					}
+				}
+			}
+		}
+		if (okay) {
+			// clear status message
+			PlatformStatusLineUtil.clearStatusLine();
+		}
+		else {
+			String errorMessage = SSEUIMessages.FindOccurrencesActionProvider_0; //$NON-NLS-1$
+			if (textEditor instanceof StructuredTextEditor) {
+				PlatformStatusLineUtil.displayTemporaryErrorMessage(((StructuredTextEditor) textEditor).getTextViewer(), errorMessage);
+			}
+			else {
+				PlatformStatusLineUtil.displayErrorMessage(errorMessage);
+				PlatformStatusLineUtil.addOneTimeClearListener();
+			}
+		}
+		return null;
+	}
+	
+	/**
+	 * Get the appropriate find occurrences processor
+	 * 
+	 * @param document -
+	 *            assumes not null
+	 * @param textSelection
+	 * @return
+	 */
+	private FindOccurrencesProcessor getProcessorForCurrentSelection(IDocument document, ITextSelection textSelection) {
+		// check if we have an action that's enabled on the current partition
+		ITypedRegion tr = getPartition(document, textSelection);
+		String partition = tr != null ? tr.getType() : ""; //$NON-NLS-1$
+
+		Iterator it = getProcessors().iterator();
+		FindOccurrencesProcessor processor = null;
+		while (it.hasNext()) {
+			processor = (FindOccurrencesProcessor) it.next();
+			// we just choose the first action that can handle the partition
+			if (processor.enabledForParitition(partition))
+				return processor;
+		}
+
+		List extendedFindOccurrencesProcessors = ExtendedConfigurationBuilder.getInstance().getConfigurations(FindOccurrencesProcessor.class.getName(), partition);
+		for (int i = 0; i < extendedFindOccurrencesProcessors.size(); i++) {
+			Object o = extendedFindOccurrencesProcessors.get(i);
+			if (o instanceof FindOccurrencesProcessor) {
+				/*
+				 * We just choose the first registered processor that
+				 * explicitly says it can handle the partition
+				 */
+				processor = (FindOccurrencesProcessor) o;
+				if (processor.enabledForParitition(partition))
+					return processor;
+			}
+		}
+		return null;
+	}
+	
+	private ITypedRegion getPartition(IDocument document, ITextSelection textSelection) {
+		ITypedRegion region = null;
+		if (textSelection != null) {
+			try {
+				region = document.getPartition(textSelection.getOffset());
+			}
+			catch (BadLocationException e) {
+				region = null;
+			}
+		}
+		return region;
+	}
+	
+	private ITextSelection getTextSelection(ITextEditor textEditor) {
+		ITextSelection textSelection = null;
+		ISelection selection = textEditor.getSelectionProvider().getSelection();
+		if (selection instanceof ITextSelection && !selection.isEmpty()) {
+			textSelection = (ITextSelection) selection;
+		}
+		return textSelection;
+	}
+	
+	protected List getProcessors() {
+		if (fProcessors == null) {
+			fProcessors = new ArrayList();
+			HTMLFindOccurrencesProcessor htmlProcessor = new HTMLFindOccurrencesProcessor();
+			fProcessors.add(htmlProcessor);
+		}
+		return fProcessors;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/hyperlink/AnchorHyperlinkDetector.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/hyperlink/AnchorHyperlinkDetector.java
new file mode 100644
index 0000000..4d8ab98
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/hyperlink/AnchorHyperlinkDetector.java
@@ -0,0 +1,511 @@
+/*******************************************************************************

+ * Copyright (c) 2008 IBM Corporation and others.

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ * 

+ * Contributors:

+ *     IBM Corporation - initial API and implementation

+ *******************************************************************************/

+

+package org.eclipse.wst.html.ui.internal.hyperlink;

+

+import java.util.ArrayList;

+import java.util.List;

+import java.util.NoSuchElementException;

+

+import org.eclipse.core.resources.IFile;

+import org.eclipse.core.resources.IMarker;

+import org.eclipse.core.resources.ResourcesPlugin;

+import org.eclipse.core.runtime.CoreException;

+import org.eclipse.core.runtime.IPath;

+import org.eclipse.core.runtime.IProgressMonitor;

+import org.eclipse.core.runtime.IStatus;

+import org.eclipse.core.runtime.Path;

+import org.eclipse.core.runtime.Status;

+import org.eclipse.core.runtime.jobs.Job;

+import org.eclipse.jface.text.BadLocationException;

+import org.eclipse.jface.text.IDocument;

+import org.eclipse.jface.text.IRegion;

+import org.eclipse.jface.text.ITextViewer;

+import org.eclipse.jface.text.ITextViewerExtension5;

+import org.eclipse.jface.text.Region;

+import org.eclipse.jface.text.TextSelection;

+import org.eclipse.jface.text.hyperlink.AbstractHyperlinkDetector;

+import org.eclipse.jface.text.hyperlink.IHyperlink;

+import org.eclipse.osgi.util.NLS;

+import org.eclipse.swt.widgets.Display;

+import org.eclipse.ui.IEditorPart;

+import org.eclipse.ui.IWorkbenchPage;

+import org.eclipse.ui.PartInitException;

+import org.eclipse.ui.PlatformUI;

+import org.eclipse.ui.ide.IDE;

+import org.eclipse.ui.progress.UIJob;

+import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;

+import org.eclipse.wst.html.core.internal.validate.ModuleCoreSupport;

+import org.eclipse.wst.html.ui.internal.HTMLUIMessages;

+import org.eclipse.wst.html.ui.internal.HTMLUIPlugin;

+import org.eclipse.wst.html.ui.internal.Logger;

+import org.eclipse.wst.sse.core.StructuredModelManager;

+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;

+import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;

+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.ITextRegionList;

+import org.eclipse.wst.sse.core.utils.StringUtils;

+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 org.w3c.dom.Element;

+import org.w3c.dom.Node;

+import org.w3c.dom.NodeList;

+

+import com.ibm.icu.util.StringTokenizer;

+

+public class AnchorHyperlinkDetector extends AbstractHyperlinkDetector {

+	static class ExternalElementHyperlink implements IHyperlink {

+		private String fAnchorName = null;

+		private Element fBaseElement = null;

+		private Display fDisplay = null;

+		private IRegion fHyperlinkRegion = null;

+

+		/**

+		 * @param hyperlinkRegion

+		 * @param anchorName

+		 */

+		public ExternalElementHyperlink(Display display, IRegion hyperlinkRegion, String anchorName, Element baseElement) {

+			super();

+			fDisplay = display;

+			fHyperlinkRegion = hyperlinkRegion;

+			fAnchorName = anchorName;

+			fBaseElement = baseElement;

+		}

+

+		/*

+		 * (non-Javadoc)

+		 * 

+		 * @see org.eclipse.jface.text.hyperlink.IHyperlink#open()

+		 */

+		IStatus _open() {

+			if (fBaseElement instanceof IDOMNode) {

+				StringTokenizer tokenizer = new StringTokenizer(fAnchorName, "#"); //$NON-NLS-1$

+				String filename = null;

+				String anchorName = null;

+				if (tokenizer.hasMoreTokens()) {

+					try {

+						filename = tokenizer.nextToken();

+						anchorName = tokenizer.nextToken();

+					}

+					catch (NoSuchElementException e) {

+						// poorly formed value

+					}

+				}

+				if (filename != null && anchorName != null) {

+					// System.out.println(filename + ":" + anchorName + "-" +

+					// fBaseElement);

+

+					IPath basePath = new Path(((IDOMNode) fBaseElement).getModel().getBaseLocation());

+					if (basePath.segmentCount() > 1) {

+						IPath resolved = ModuleCoreSupport.resolve(basePath, filename);

+						IFile targetFile = ResourcesPlugin.getWorkspace().getRoot().getFile(resolved);

+						if (targetFile.isAccessible()) {

+							IStructuredModel model = null;

+							int start = -1;

+							int end = -1;

+							try {

+								model = StructuredModelManager.getModelManager().getModelForRead(targetFile);

+								if (model instanceof IDOMModel) {

+									NodeList anchors = ((IDOMModel) model).getDocument().getElementsByTagNameNS("*", HTML40Namespace.ElementName.A); //$NON-NLS-1$

+									for (int i = 0; i < anchors.getLength() && start < 0; i++) {

+										Node item = anchors.item(i);

+										Node nameNode = item.getAttributes().getNamedItem(HTML40Namespace.ATTR_NAME_NAME);

+										if (nameNode == null)

+											nameNode = item.getAttributes().getNamedItem(HTML40Namespace.ATTR_NAME_ID);

+										if (nameNode != null) {

+											String name = nameNode.getNodeValue();

+											if (anchorName.equals(name) && nameNode instanceof IndexedRegion) {

+												start = ((IndexedRegion) nameNode).getStartOffset();

+												end = ((IndexedRegion) nameNode).getEndOffset();

+											}

+										}

+									}

+									anchors = ((IDOMModel) model).getDocument().getElementsByTagName(HTML40Namespace.ElementName.A);

+									for (int i = 0; i < anchors.getLength() && start < 0; i++) {

+										Node item = anchors.item(i);

+										Node nameNode = item.getAttributes().getNamedItem(HTML40Namespace.ATTR_NAME_NAME);

+										if (nameNode == null)

+											nameNode = item.getAttributes().getNamedItem(HTML40Namespace.ATTR_NAME_ID);

+										if (nameNode != null) {

+											String name = nameNode.getNodeValue();

+											if (anchorName.equals(name) && nameNode instanceof IndexedRegion) {

+												start = ((IndexedRegion) nameNode).getStartOffset();

+												end = ((IndexedRegion) nameNode).getEndOffset();

+											}

+										}

+									}

+

+									anchors = ((IDOMModel) model).getDocument().getElementsByTagName("*"); //$NON-NLS-1$

+									for (int i = 0; i < anchors.getLength() && start < 0; i++) {

+										Node item = anchors.item(i);

+										Node nameNode = item.getAttributes().getNamedItem(HTML40Namespace.ATTR_NAME_NAME);

+										if (nameNode == null)

+											nameNode = item.getAttributes().getNamedItem(HTML40Namespace.ATTR_NAME_ID);

+										if (nameNode != null) {

+											String name = nameNode.getNodeValue();

+											if (anchorName.equals(name) && nameNode instanceof IndexedRegion) {

+												start = ((IndexedRegion) nameNode).getStartOffset();

+												end = ((IndexedRegion) nameNode).getEndOffset();

+											}

+										}

+									}

+

+								}

+								return open(basePath.toString(), targetFile, start, end);

+							}

+							catch (Exception e) {

+								Logger.logException(e);

+								return new Status(IStatus.ERROR, HTMLUIPlugin.ID, e.getMessage());

+

+							}

+							finally {

+								if (model != null)

+									model.releaseFromRead();

+							}

+						}

+					}

+				}

+			}

+			return Status.OK_STATUS;

+		}

+

+		/*

+		 * (non-Javadoc)

+		 * 

+		 * @see

+		 * org.eclipse.jface.text.hyperlink.IHyperlink#getHyperlinkRegion()

+		 */

+		public IRegion getHyperlinkRegion() {

+			return fHyperlinkRegion;

+		}

+

+		/*

+		 * (non-Javadoc)

+		 * 

+		 * @see org.eclipse.jface.text.hyperlink.IHyperlink#getHyperlinkText()

+		 */

+		public String getHyperlinkText() {

+			return NLS.bind(HTMLUIMessages.Open, fAnchorName);

+		}

+

+		/*

+		 * (non-Javadoc)

+		 * 

+		 * @see org.eclipse.jface.text.hyperlink.IHyperlink#getTypeLabel()

+		 */

+		public String getTypeLabel() {

+			return null;

+		}

+

+		public void open() {

+			scheduleOpen();

+		}

+

+		/**

+		 * @param targetFile

+		 * @param start

+		 * @param end

+		 */

+		private IStatus open(String base, IFile targetFile, int start, int end) throws CoreException, PartInitException {

+			IMarker temporaryMarker = null;

+			try {

+				IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();

+

+				IEditorPart editor = IDE.openEditor(page, targetFile);

+

+				if (0 <= start && start <= end) {

+					temporaryMarker = targetFile.createMarker(IMarker.BOOKMARK);

+					temporaryMarker.setAttribute(IMarker.MESSAGE, base);

+					temporaryMarker.setAttribute(IMarker.CHAR_START, start);

+					temporaryMarker.setAttribute(IMarker.CHAR_END, end);

+					IDE.gotoMarker(editor, temporaryMarker);

+				}

+				return Status.OK_STATUS;

+			}

+			finally {

+				if (temporaryMarker != null)

+					try {

+						temporaryMarker.delete();

+					}

+					catch (CoreException e) {

+						Logger.logException(e);

+					}

+			}

+		}

+

+		void scheduleOpen() {

+			Job opener = new UIJob(fDisplay, fAnchorName) {

+				public IStatus runInUIThread(IProgressMonitor monitor) {

+					return _open();

+				}

+

+			};

+			opener.setSystem(true);

+			opener.setUser(false);

+			opener.schedule();

+		}

+	}

+

+	/**

+	 * Links to the given target node within the text viewer. The target node

+	 * is expected to implement IndexedNode and appear in that text viewer

+	 * (i.e. same editor).

+	 * 

+	 */

+	static class InternalElementHyperlink implements IHyperlink {

+		private IRegion fHyperlinkRegion;

+		private Node fTarget = null;

+		private ITextViewer fViewer = null;

+

+		/**

+		 * 

+		 */

+		public InternalElementHyperlink(ITextViewer textViewer, IRegion hyperlinkRegion, Node targetNode) {

+			fHyperlinkRegion = hyperlinkRegion;

+			fTarget = targetNode;

+			fViewer = textViewer;

+		}

+

+		/*

+		 * (non-Javadoc)

+		 * 

+		 * @see

+		 * org.eclipse.jface.text.hyperlink.IHyperlink#getHyperlinkRegion()

+		 */

+		public IRegion getHyperlinkRegion() {

+			return fHyperlinkRegion;

+		}

+

+		/*

+		 * (non-Javadoc)

+		 * 

+		 * @see org.eclipse.jface.text.hyperlink.IHyperlink#getHyperlinkText()

+		 */

+		public String getHyperlinkText() {

+			if (fTarget instanceof IndexedRegion) {

+				try {

+					int line = fViewer.getDocument().getLineOfOffset(((IndexedRegion) fTarget).getStartOffset()) + 1;

+					return NLS.bind(HTMLUIMessages.Hyperlink_line, new String[]{fTarget.getNodeName(), fTarget.getNodeValue(), String.valueOf(line)});

+				}

+				catch (BadLocationException e) {

+					Logger.logException(e);

+				}

+			}

+			return NLS.bind(HTMLUIMessages.Open, fTarget.getNodeName());

+		}

+

+		/*

+		 * (non-Javadoc)

+		 * 

+		 * @see org.eclipse.jface.text.hyperlink.IHyperlink#getTypeLabel()

+		 */

+		public String getTypeLabel() {

+			return null;

+		}

+

+		/*

+		 * (non-Javadoc)

+		 * 

+		 * @see org.eclipse.jface.text.hyperlink.IHyperlink#open()

+		 */

+		public void open() {

+			if (fTarget instanceof IndexedRegion) {

+				int offset = ((IndexedRegion) fTarget).getStartOffset();

+				if (fViewer instanceof ITextViewerExtension5) {

+					offset = ((ITextViewerExtension5) fViewer).modelOffset2WidgetOffset(offset);

+				}

+				fViewer.getSelectionProvider().setSelection(new TextSelection(offset, 0));

+				fViewer.revealRange(offset, 0);

+			}

+		}

+	}

+

+	public AnchorHyperlinkDetector() {

+		super();

+	}

+

+	private void addHyperLinkForHref(ITextViewer textViewer, IRegion linkRegion, Element element, String hrefValue, List links, Node anchor) {

+		Node nameNode = anchor.getAttributes().getNamedItem(HTML40Namespace.ATTR_NAME_HREF);

+		if (nameNode != null) {

+			String name = nameNode.getNodeValue();

+			if (hrefValue.equals(name) && nameNode instanceof IndexedRegion) {

+				links.add(new InternalElementHyperlink(textViewer, linkRegion, nameNode));

+			}

+		}

+	}

+

+	private void addHyperLinkForName(ITextViewer textViewer, IRegion linkRegion, Element element, String anchorName, List links, Node anchor) {

+		Node nameNode = anchor.getAttributes().getNamedItem(HTML40Namespace.ATTR_NAME_NAME);

+		if (nameNode != null) {

+			String name = nameNode.getNodeValue();

+			if (anchorName.equals(name) && nameNode instanceof IndexedRegion) {

+				links.add(new InternalElementHyperlink(textViewer, linkRegion, nameNode));

+			}

+		}

+		nameNode = anchor.getAttributes().getNamedItem(HTML40Namespace.ATTR_NAME_ID);

+		if (nameNode != null) {

+			String name = nameNode.getNodeValue();

+			if (anchorName.equals(name) && nameNode instanceof IndexedRegion) {

+				links.add(new InternalElementHyperlink(textViewer, linkRegion, nameNode));

+			}

+		}

+	}

+

+	/**

+	 * @param documentRegion

+	 * @param valueRegion

+	 * @return

+	 */

+	private IRegion createHyperlinkRegion(IStructuredDocumentRegion documentRegion, ITextRegion valueRegion) {

+		return new Region(documentRegion.getStartOffset(valueRegion), valueRegion.getTextLength());

+	}

+

+	// link to anchors with the given name (value includes the '#')

+	IHyperlink[] createHyperlinksToAnchorNamed(ITextViewer textViewer, IRegion hyperlinkRegion, Element element, String anchorName, boolean canShowMultipleHyperlinks) {

+		List links = new ArrayList(1);

+		// >1 guards the substring-ing

+		if (anchorName.length() > 1 && anchorName.startsWith("#")) { //$NON-NLS-1$

+			// an anchor in this document

+			NodeList anchors = null;//element.getOwnerDocument().getElementsByTagNameNS("*", HTML40Namespace.ElementName.A); //$NON-NLS-1$

+			String internalAnchorName = anchorName.substring(1);

+//			for (int i = 0; i < anchors.getLength(); i++) {

+//				addHyperLinkForName(textViewer, hyperlinkRegion, element, internalAnchorName, links, anchors.item(i));

+//			}

+//			anchors = element.getOwnerDocument().getElementsByTagName(HTML40Namespace.ElementName.A);

+//			for (int i = 0; i < anchors.getLength(); i++) {

+//				addHyperLinkForName(textViewer, hyperlinkRegion, element, internalAnchorName, links, anchors.item(i));

+//			}

+			anchors = element.getOwnerDocument().getElementsByTagName("*"); //$NON-NLS-1$

+			for (int i = 0; i < anchors.getLength(); i++) {

+				addHyperLinkForName(textViewer, hyperlinkRegion, element, internalAnchorName, links, anchors.item(i));

+			}

+		}

+		else {

+			// another file, possibly very slow to compute ahead of time

+			links.add(new ExternalElementHyperlink(textViewer.getTextWidget().getDisplay(), hyperlinkRegion, anchorName, element));

+		}

+		if (!links.isEmpty()) {

+			return (IHyperlink[]) links.toArray(new IHyperlink[links.size()]);

+		}

+		return null;

+	}

+

+	// link to anchors that link to this target

+	IHyperlink[] createReferrerHyperlinks(ITextViewer textViewer, IRegion hyperlinkRegion, Element element, String nameValue, boolean canShowMultipleHyperlinks) {

+		List links = new ArrayList(1);

+		if (nameValue.length() > 0) {

+			String target = "#" + nameValue; //$NON-NLS-1$

+			NodeList anchors = null;//element.getOwnerDocument().getElementsByTagNameNS("*", HTML40Namespace.ElementName.A); //$NON-NLS-1$

+//			for (int i = 0; i < anchors.getLength(); i++) {

+//				addHyperLinkForHref(textViewer, hyperlinkRegion, element, target, links, anchors.item(i));

+//			}

+//			anchors = element.getOwnerDocument().getElementsByTagName(HTML40Namespace.ElementName.A);

+//			for (int i = 0; i < anchors.getLength(); i++) {

+//				addHyperLinkForHref(textViewer, hyperlinkRegion, element, target, links, anchors.item(i));

+//			}

+			anchors = element.getOwnerDocument().getElementsByTagName("*"); //$NON-NLS-1$

+			for (int i = 0; i < anchors.getLength(); i++) {

+				addHyperLinkForHref(textViewer, hyperlinkRegion, element, target, links, anchors.item(i));

+			}

+		}

+		if (!links.isEmpty()) {

+			return (IHyperlink[]) links.toArray(new IHyperlink[links.size()]);

+		}

+		return null;

+	}

+

+	public IHyperlink[] detectHyperlinks(ITextViewer textViewer, IRegion region, boolean canShowMultipleHyperlinks) {

+		if (textViewer != null && region != null) {

+			IDocument document = textViewer.getDocument();

+			if (document != null) {

+				Node currentNode = getCurrentNode(document, region.getOffset());

+				if (currentNode != null && currentNode.getNodeType() == Node.ELEMENT_NODE) {

+					Element element = (Element) currentNode;

+						IStructuredDocumentRegion documentRegion = ((IStructuredDocument) document).getRegionAtCharacterOffset(region.getOffset());

+						ITextRegion textRegion = documentRegion.getRegionAtCharacterOffset(region.getOffset());

+						ITextRegion nameRegion = null;

+						ITextRegion valueRegion = null;

+						String name = null;

+						String value = null;

+						if (DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE.equals(textRegion.getType())) {

+							ITextRegionList regions = documentRegion.getRegions();

+							/*

+							 * Could use 2, but there needs to be the tag open

+							 * and name regions

+							 */

+							int index = regions.indexOf(textRegion);

+							if (index >= 4) {

+								nameRegion = regions.get(index - 2);

+								valueRegion = textRegion;

+								name = documentRegion.getText(nameRegion);

+								value = StringUtils.strip(documentRegion.getText(valueRegion));

+							}

+						}

+						else if (DOMRegionContext.XML_TAG_ATTRIBUTE_NAME.equals(textRegion.getType())) {

+							ITextRegionList regions = documentRegion.getRegions();

+							int index = regions.indexOf(textRegion);

+							// minus 3 to leave equal and value regions

+							if (index <= regions.size() - 3) {

+								nameRegion = textRegion;

+								valueRegion = regions.get(index + 2);

+								name = documentRegion.getText(nameRegion);

+								value = StringUtils.strip(documentRegion.getText(valueRegion));

+							}

+						}

+						if (name != null && value != null) {

+							if (HTML40Namespace.ATTR_NAME_HREF.equalsIgnoreCase(name) && value.indexOf("#") >= 0) { //$NON-NLS-1$

+								return createHyperlinksToAnchorNamed(textViewer, createHyperlinkRegion(documentRegion, valueRegion), element, value, canShowMultipleHyperlinks);

+							}

+							if (HTML40Namespace.ATTR_NAME_NAME.equalsIgnoreCase(name)||HTML40Namespace.ATTR_NAME_ID.equalsIgnoreCase(name)) {

+								return createReferrerHyperlinks(textViewer, createHyperlinkRegion(documentRegion, valueRegion), element, value, canShowMultipleHyperlinks);

+							}

+						}

+				}

+			}

+		}

+		return null;

+	}

+

+	/**

+	 * Returns the node the cursor is currently on in the document. null if no

+	 * node is selected

+	 * 

+	 * @param offset

+	 * @return Node either element, doctype, text, or null

+	 */

+	private Node getCurrentNode(IDocument document, int offset) {

+		// get the current node at the offset (returns either: element,

+		// doctype, text)

+		IndexedRegion inode = null;

+		IStructuredModel sModel = null;

+		try {

+			sModel = StructuredModelManager.getModelManager().getExistingModelForRead(document);

+			if (sModel != null) {

+				inode = sModel.getIndexedRegion(offset);

+				if (inode == null) {

+					inode = sModel.getIndexedRegion(offset - 1);

+				}

+			}

+		}

+		finally {

+			if (sModel != null)

+				sModel.releaseFromRead();

+		}

+

+		if (inode instanceof Node) {

+			return (Node) inode;

+		}

+		return null;

+	}

+}

diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/preferences/HTMLCompletionProposalCategoriesConfiguration.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/preferences/HTMLCompletionProposalCategoriesConfiguration.java
new file mode 100644
index 0000000..11cb1d0
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/preferences/HTMLCompletionProposalCategoriesConfiguration.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (c) 20109 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.preferences;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.wst.html.ui.internal.HTMLUIPlugin;
+import org.eclipse.wst.sse.ui.preferences.AbstractCompletionProposalCategoriesConfiguration;
+
+/**
+ * <p>The readable and writable completion proposal categories configuration
+ * for the HTML content type</p>
+ */
+public class HTMLCompletionProposalCategoriesConfiguration extends AbstractCompletionProposalCategoriesConfiguration {
+
+	/** the ID of the preference page where users can change the preferences */
+	private static final String PREFERENCES_PAGE_ID = "org.eclipse.wst.html.ui.preferences.contentassist"; //$NON-NLS-1$
+	
+	/**
+	 * <p>Creates the configuration</p>
+	 */
+	public HTMLCompletionProposalCategoriesConfiguration() {
+		//nothing to do.
+	}
+
+	/**
+	 * @see org.eclipse.wst.sse.ui.preferences.AbstractCompletionProposalCategoriesConfiguration#getPreferenceStore()
+	 */
+	protected IPreferenceStore getPreferenceStore() {
+		return HTMLUIPlugin.getDefault().getPreferenceStore();
+	}
+	
+	/**
+	 * @see org.eclipse.wst.sse.ui.preferences.ICompletionProposalCategoriesConfigurationWriter#hasAssociatedPropertiesPage()
+	 */
+	public boolean hasAssociatedPropertiesPage() {
+		return true;
+	}
+
+	/**
+	 * @see org.eclipse.wst.sse.ui.preferences.ICompletionProposalCategoriesConfigurationWriter#getPropertiesPageID()
+	 */
+	public String getPropertiesPageID() {
+		return PREFERENCES_PAGE_ID;
+	}
+
+	/**
+	 * @see org.eclipse.wst.sse.ui.preferences.AbstractCompletionProposalCategoriesConfiguration#getShouldNotDisplayOnDefaultPagePrefKey()
+	 */
+	protected String getShouldNotDisplayOnDefaultPagePrefKey() {
+		return HTMLUIPreferenceNames.CONTENT_ASSIST_DO_NOT_DISPLAY_ON_DEFAULT_PAGE;
+	}
+
+	/**
+	 * @see org.eclipse.wst.sse.ui.preferences.AbstractCompletionProposalCategoriesConfiguration#getShouldNotDisplayOnOwnPagePrefKey()
+	 */
+	protected String getShouldNotDisplayOnOwnPagePrefKey() {
+		return HTMLUIPreferenceNames.CONTENT_ASSIST_DO_NOT_DISPLAY_ON_OWN_PAGE;
+	}
+
+	/**
+	 * @see org.eclipse.wst.sse.ui.preferences.AbstractCompletionProposalCategoriesConfiguration#getPageSortOrderPrefKey()
+	 */
+	protected String getPageSortOrderPrefKey() {
+		return HTMLUIPreferenceNames.CONTENT_ASSIST_OWN_PAGE_SORT_ORDER;
+	}
+	
+	/**
+	 * @see org.eclipse.wst.sse.ui.preferences.AbstractCompletionProposalCategoriesConfiguration#getDefaultPageSortOrderPrefKey()
+	 */
+	protected String getDefaultPageSortOrderPrefKey() {
+		return HTMLUIPreferenceNames.CONTENT_ASSIST_DEFAULT_PAGE_SORT_ORDER;
+	}
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/preferences/HTMLUIPreferenceInitializer.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/preferences/HTMLUIPreferenceInitializer.java
new file mode 100644
index 0000000..6ddbb67
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/preferences/HTMLUIPreferenceInitializer.java
@@ -0,0 +1,129 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 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
+ *     Benjamin Muskalla, b.muskalla@gmx.net - [158660] character entities should have their own syntax highlighting preference      
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.preferences;
+
+import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.resource.ColorRegistry;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.wst.html.ui.internal.HTMLUIPlugin;
+import org.eclipse.wst.html.ui.internal.style.IStyleConstantsHTML;
+import org.eclipse.wst.sse.ui.internal.preferences.ui.ColorHelper;
+import org.eclipse.wst.xml.ui.internal.style.IStyleConstantsXML;
+
+/**
+ * Sets default values for HTML UI preferences
+ */
+public class HTMLUIPreferenceInitializer extends AbstractPreferenceInitializer {
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer#initializeDefaultPreferences()
+	 */
+	public void initializeDefaultPreferences() {
+		IPreferenceStore store = HTMLUIPlugin.getDefault().getPreferenceStore();
+		ColorRegistry registry = PlatformUI.getWorkbench().getThemeManager().getCurrentTheme().getColorRegistry();
+		
+		store.setDefault(HTMLUIPreferenceNames.AUTO_PROPOSE, true);
+		store.setDefault(HTMLUIPreferenceNames.AUTO_PROPOSE_CODE, "<=");//$NON-NLS-1$
+
+		// HTML Style Preferences
+		String NOBACKGROUNDBOLD = " | null | false"; //$NON-NLS-1$
+		String JUSTITALIC = " | null | false | true"; //$NON-NLS-1$
+		String styleValue = ColorHelper.findRGBString(registry, IStyleConstantsXML.TAG_ATTRIBUTE_NAME, 127, 0, 127) + NOBACKGROUNDBOLD;
+		store.setDefault(IStyleConstantsXML.TAG_ATTRIBUTE_NAME, styleValue);
+
+		styleValue = ColorHelper.findRGBString(registry, IStyleConstantsXML.TAG_ATTRIBUTE_VALUE, 42, 0, 255) + JUSTITALIC;
+		store.setDefault(IStyleConstantsXML.TAG_ATTRIBUTE_VALUE, styleValue);
+
+		styleValue = "null" + NOBACKGROUNDBOLD; //$NON-NLS-1$
+		store.setDefault(IStyleConstantsXML.TAG_ATTRIBUTE_EQUALS, styleValue); // specified value is black; leaving as widget default
+
+		styleValue = ColorHelper.findRGBString(registry, IStyleConstantsXML.COMMENT_BORDER, 63, 95, 191) + NOBACKGROUNDBOLD;
+		store.setDefault(IStyleConstantsXML.COMMENT_BORDER, styleValue);
+		styleValue = ColorHelper.findRGBString(registry, IStyleConstantsXML.COMMENT_TEXT, 63, 95, 191) + NOBACKGROUNDBOLD;
+		store.setDefault(IStyleConstantsXML.COMMENT_TEXT, styleValue);
+
+		styleValue = ColorHelper.findRGBString(registry, IStyleConstantsXML.DECL_BORDER, 0, 128, 128) + NOBACKGROUNDBOLD;
+		store.setDefault(IStyleConstantsXML.DECL_BORDER, styleValue);
+
+		styleValue = ColorHelper.findRGBString(registry, IStyleConstantsXML.DOCTYPE_NAME, 0, 0, 128) + NOBACKGROUNDBOLD;
+		store.setDefault(IStyleConstantsXML.DOCTYPE_NAME, styleValue);
+		styleValue = ColorHelper.findRGBString(registry, IStyleConstantsXML.DOCTYPE_EXTERNAL_ID_PUBREF, 0, 0, 128) + NOBACKGROUNDBOLD;
+		store.setDefault(IStyleConstantsXML.DOCTYPE_EXTERNAL_ID_PUBREF, styleValue);
+
+		styleValue = ColorHelper.findRGBString(registry, IStyleConstantsXML.DOCTYPE_EXTERNAL_ID, 128, 128, 128) + NOBACKGROUNDBOLD;
+		store.setDefault(IStyleConstantsXML.DOCTYPE_EXTERNAL_ID, styleValue);
+
+		styleValue = ColorHelper.findRGBString(registry, IStyleConstantsXML.DOCTYPE_EXTERNAL_ID_SYSREF, 63, 127, 95) + NOBACKGROUNDBOLD;
+		store.setDefault(IStyleConstantsXML.DOCTYPE_EXTERNAL_ID_SYSREF, styleValue);
+
+		styleValue = "null" + NOBACKGROUNDBOLD; //$NON-NLS-1$
+		store.setDefault(IStyleConstantsXML.XML_CONTENT, styleValue);	// specified value is black; leaving as widget default
+
+		styleValue = ColorHelper.findRGBString(registry, IStyleConstantsXML.TAG_BORDER, 0, 128, 128) + NOBACKGROUNDBOLD;
+		store.setDefault(IStyleConstantsXML.TAG_BORDER, styleValue);
+
+		styleValue = ColorHelper.findRGBString(registry, IStyleConstantsXML.TAG_NAME, 63, 127, 127) + NOBACKGROUNDBOLD;
+		store.setDefault(IStyleConstantsXML.TAG_NAME, styleValue);
+
+		styleValue = ColorHelper.findRGBString(registry, IStyleConstantsXML.PI_BORDER, 0, 128, 128) + NOBACKGROUNDBOLD;
+		store.setDefault(IStyleConstantsXML.PI_BORDER, styleValue);
+
+		styleValue = "null" + NOBACKGROUNDBOLD; //$NON-NLS-1$
+		store.setDefault(IStyleConstantsXML.PI_CONTENT, styleValue);	// specified value is black; leaving as widget default
+
+		styleValue = ColorHelper.findRGBString(registry, IStyleConstantsXML.CDATA_BORDER, 0, 128, 128) + NOBACKGROUNDBOLD;
+		store.setDefault(IStyleConstantsXML.CDATA_BORDER, styleValue);
+
+		styleValue = ColorHelper.findRGBString(registry, IStyleConstantsXML.CDATA_TEXT, 0, 0, 0) + NOBACKGROUNDBOLD;
+		store.setDefault(IStyleConstantsXML.CDATA_TEXT, styleValue);
+
+		styleValue = ColorHelper.findRGBString(registry, IStyleConstantsHTML.SCRIPT_AREA_BORDER, 191, 95, 63) + NOBACKGROUNDBOLD;
+		store.setDefault(IStyleConstantsHTML.SCRIPT_AREA_BORDER, styleValue);
+
+		styleValue = ColorHelper.findRGBString(registry, IStyleConstantsXML.ENTITY_REFERENCE, 42, 0, 255) + NOBACKGROUNDBOLD;
+		store.setDefault(IStyleConstantsXML.ENTITY_REFERENCE, styleValue);
+
+		// set default new html file template to use in new file wizard
+		/*
+		 * Need to find template name that goes with default template id (name
+		 * may change for different language)
+		 */
+		store.setDefault(HTMLUIPreferenceNames.NEW_FILE_TEMPLATE_ID, "org.eclipse.wst.html.ui.templates.html"); //$NON-NLS-1$
+		
+		// Defaults for the Typing preference page
+		store.setDefault(HTMLUIPreferenceNames.TYPING_COMPLETE_COMMENTS, true);
+		store.setDefault(HTMLUIPreferenceNames.TYPING_COMPLETE_END_TAGS, true);
+		store.setDefault(HTMLUIPreferenceNames.TYPING_COMPLETE_ELEMENTS, true);
+		store.setDefault(HTMLUIPreferenceNames.TYPING_REMOVE_END_TAGS, true);
+		store.setDefault(HTMLUIPreferenceNames.TYPING_CLOSE_STRINGS, true);
+		store.setDefault(HTMLUIPreferenceNames.TYPING_CLOSE_BRACKETS, true);
+		
+		// Defaults for Content Assist preference page
+		store.setDefault(HTMLUIPreferenceNames.CONTENT_ASSIST_DO_NOT_DISPLAY_ON_DEFAULT_PAGE, "");
+		store.setDefault(HTMLUIPreferenceNames.CONTENT_ASSIST_DO_NOT_DISPLAY_ON_OWN_PAGE, "");
+		store.setDefault(HTMLUIPreferenceNames.CONTENT_ASSIST_DEFAULT_PAGE_SORT_ORDER,
+				"org.eclipse.wst.html.ui.proposalCategory.htmlTags\0" +
+				"org.eclipse.wst.css.ui.proposalCategory.css\0" +
+				"org.eclipse.wst.html.ui.proposalCategory.htmlTemplates\0" +
+				"org.eclipse.wst.css.ui.proposalCategory.cssTemplates");
+		store.setDefault(HTMLUIPreferenceNames.CONTENT_ASSIST_OWN_PAGE_SORT_ORDER,
+				"org.eclipse.wst.html.ui.proposalCategory.htmlTemplates\0"+
+				"org.eclipse.wst.css.ui.proposalCategory.cssTemplates\0" +
+				"org.eclipse.wst.html.ui.proposalCategory.htmlTags\0" +
+				"org.eclipse.wst.css.ui.proposalCategory.css");
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/preferences/HTMLUIPreferenceNames.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/preferences/HTMLUIPreferenceNames.java
new file mode 100644
index 0000000..4f8b012
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/preferences/HTMLUIPreferenceNames.java
@@ -0,0 +1,161 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 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
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.preferences;
+
+/**
+ * Preference keys for HTML UI
+ */
+public class HTMLUIPreferenceNames {
+	/**
+	 * A named preference that controls if code assist gets auto activated.
+	 * <p>
+	 * Value is of type <code>Boolean</code>.
+	 * </p>
+	 */
+	public static final String AUTO_PROPOSE = getAutoProposeKey();
+
+	private static String getAutoProposeKey() {
+		return "autoPropose";//$NON-NLS-1$
+	}
+
+	/**
+	 * A named preference that holds the characters that auto activate code
+	 * assist.
+	 * <p>
+	 * Value is of type <code>String</code>. All characters that trigger
+	 * auto code assist.
+	 * </p>
+	 */
+	public static final String AUTO_PROPOSE_CODE = getAutoProposeCodeKey();
+
+	private static String getAutoProposeCodeKey() {
+		return "autoProposeCode";//$NON-NLS-1$
+	}
+
+	/**
+	 * The key to store customized templates.
+	 * <p>
+	 * Value is of type <code>String</code>.
+	 * </p>
+	 */
+	public static final String TEMPLATES_KEY = getTemplatesKey();
+
+	private static String getTemplatesKey() {
+		return "org.eclipse.wst.sse.ui.custom_templates"; //$NON-NLS-1$
+	}
+	
+	/**
+	 * The key to store the last template name used in new HTML file wizard.
+	 * Template name is stored instead of template id because user-created
+	 * templates do not have template ids.
+	 * <p>
+	 * Value is of type <code>String</code>.
+	 * </p>
+	 */
+	public static final String NEW_FILE_TEMPLATE_NAME = "newFileTemplateName"; //$NON-NLS-1$
+
+	/**
+	 * The initial template ID to be used in the new HTML file wizard. In the absence
+	 * of {@link NEW_FILE_TEMPLATE_NAME}, this ID is used to find a template name
+	 */
+	public static final String NEW_FILE_TEMPLATE_ID = "newFileTemplateId"; //$NON-NLS-1$
+
+	/**
+	 * The key to store the option for auto-completing comments while
+	 * typing.
+	 * <p>
+	 * Value is of type <code>boolean</code>.
+	 * </p>
+	 */
+	public static final String TYPING_COMPLETE_COMMENTS = "completeComments"; //$NON-NLS-1$
+	
+	/**
+	 * The key to store the option for auto-completing end-tags after entering
+	 * <code>&lt;/</code>
+	 * <p>
+	 * Value is of type <code>boolean</code>.
+	 * </p>
+	 */
+	public static final String TYPING_COMPLETE_END_TAGS = "completeEndTags"; //$NON-NLS-1$
+	
+	/**
+	 * The key to store the option for auto-completing the element after entering
+	 * <code>&gt;</code>
+	 * <p>
+	 * Value is of type <code>boolean</code>.
+	 * </p>
+	 */
+	public static final String TYPING_COMPLETE_ELEMENTS = "completeElements"; //$NON-NLS-1$
+	
+	/**
+	 * The key to store the option for removing an end-tag if the start tag is
+	 * converted to an empty-tag.
+	 * <p>
+	 * Value is of type <code>boolean</code>.
+	 * </p>
+	 */
+	public static final String TYPING_REMOVE_END_TAGS = "removeEndTags"; //$NON-NLS-1$
+
+	/**
+	 * The key to store the option for auto-completing strings (" and ') while
+	 * typing.
+	 * <p>
+	 * Value is of type <code>boolean</code>.
+	 * </p>
+	 */
+	public static final String TYPING_CLOSE_STRINGS = "closeStrings"; //$NON-NLS-1$
+
+	/**
+	 * The key to store the option for auto-completing brackets ([ and () while
+	 * typing.
+	 * <p>
+	 * Value is of type <code>boolean</code>.
+	 * </p>
+	 */
+	public static final String TYPING_CLOSE_BRACKETS = "closeBrackets"; //$NON-NLS-1$
+	
+	/**
+	 * <p>preference key used for saving which categories should not display on the default page</p>
+	 * 
+	 * <p>Value is of type {@link String} consisting of
+	 * <tt>org.eclipse.wst.sse.ui.completionProposal/proposalCategory/@id</tt>s separated by the null
+	 * character (<tt>\0</tt>), ordered is ignored</p>
+	 */
+	public static final String CONTENT_ASSIST_DO_NOT_DISPLAY_ON_DEFAULT_PAGE = "html_content_assist_display_on_default_page"; //$NON-NLS-1$
+	
+	/**
+	 * <p>preference key used for saving which categories should not display on their own page</p>
+	 * 
+	 * <p>Value is of type {@link String} consisting of
+	 * <tt>org.eclipse.wst.sse.ui.completionProposal/proposalCategory/@id</tt>s separated by the null
+	 * character (<tt>\0</tt>), order is ignored</p>
+	 */
+	public static final String CONTENT_ASSIST_DO_NOT_DISPLAY_ON_OWN_PAGE = "html_content_assist_display_on_own_page"; //$NON-NLS-1$
+	
+	/**
+	 * <p>preference key for saving the sort order of the categories when displaying them on their own page</p>
+	 * 
+	 * <p>Value is of type {@link String} consisting of
+	 * <tt>org.eclipse.wst.sse.ui.completionProposal/proposalCategory/@id</tt>s separated by the null
+	 * character (<tt>\0</tt>) in the desired sort order.</p>
+	 */
+	public static final String CONTENT_ASSIST_OWN_PAGE_SORT_ORDER= "html_content_assist_own_page_sort_order"; //$NON-NLS-1$
+	
+	/**
+	 * <p>preference key for saving the sort order of the categories when displaying them on the default page</p>
+	 * 
+	 * <p>Value is of type {@link String} consisting of
+	 * <tt>org.eclipse.wst.sse.ui.completionProposal/proposalCategory/@id</tt>s separated by the null
+	 * character (<tt>\0</tt>) in the desired sort order.</p>
+	 */
+	public static final String CONTENT_ASSIST_DEFAULT_PAGE_SORT_ORDER= "html_content_assist_default_page_sort_order"; //$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/preferences/ui/AbstractValidationSettingsPage.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/preferences/ui/AbstractValidationSettingsPage.java
new file mode 100644
index 0000000..f2ab08d
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/preferences/ui/AbstractValidationSettingsPage.java
@@ -0,0 +1,400 @@
+/*******************************************************************************
+ * Copyright (c) 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.preferences.ui;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.ProjectScope;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.core.runtime.preferences.DefaultScope;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences;
+import org.eclipse.core.runtime.preferences.IPreferencesService;
+import org.eclipse.core.runtime.preferences.IScopeContext;
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.MessageBox;
+import org.eclipse.swt.widgets.Widget;
+import org.eclipse.ui.forms.events.ExpansionAdapter;
+import org.eclipse.ui.forms.events.ExpansionEvent;
+import org.eclipse.ui.forms.widgets.ExpandableComposite;
+import org.eclipse.wst.html.ui.internal.HTMLUIMessages;
+import org.eclipse.wst.sse.core.internal.validate.ValidationMessage;
+import org.eclipse.wst.sse.ui.internal.preferences.ui.ScrolledPageContent;
+import org.eclipse.wst.validation.ValidationFramework;
+import org.osgi.service.prefs.BackingStoreException;
+
+/**
+ * Based on org.eclipse.jdt.internal.ui.preferences.OptionsConfigurationBlock
+ */
+abstract class AbstractValidationSettingsPage extends PropertyPreferencePage {
+
+	private List fCombos;
+	private List fExpandables;
+	
+	private SelectionListener fSelectionListener;
+	
+	private IPreferencesService fPreferencesService = null;
+	
+	private static final String SETTINGS_EXPANDED = "expanded"; //$NON-NLS-1$
+	
+	private ValidationFramework fValidation;
+	
+	private class ComboData {
+		private String fKey;
+		private int[] fSeverities;
+		private int fIndex;
+		int originalSeverity = -2;
+		
+		public ComboData(String key, int[] severities, int index) {
+			fKey = key;
+			fSeverities = severities;
+			fIndex = index;
+		}
+		
+		public String getKey() {
+			return fKey;
+		}
+		
+		public void setIndex(int index) {
+			fIndex = index;
+		}
+		
+		public int getIndex() {
+			return fIndex;
+		}
+		
+		/**
+		 * Sets the severity index based on <code>severity</code>.
+		 * If the severity doesn't exist, the index is set to -1.
+		 * 
+		 * @param severity the severity level
+		 */
+		public void setSeverity(int severity) {
+			for(int i = 0; fSeverities != null && i < fSeverities.length; i++) {
+				if(fSeverities[i] == severity) {
+					fIndex = i;
+					return;
+				}
+			}
+			
+			fIndex = -1;
+		}
+		
+		public int getSeverity() {
+			return (fIndex >= 0 && fSeverities != null && fIndex < fSeverities.length) ? fSeverities[fIndex] : -1;
+		}
+		
+		boolean isChanged() {
+			return fSeverities[fIndex] != originalSeverity;
+		}
+	}
+	
+	public AbstractValidationSettingsPage() {
+		super();
+		fCombos = new ArrayList();
+		fExpandables = new ArrayList();
+		fPreferencesService = Platform.getPreferencesService();
+		fValidation = ValidationFramework.getDefault();
+	}
+	
+	/**
+	 * Creates a Combo widget in the composite <code>parent</code>. The data
+	 * in the Combo is associated with <code>key</code>. The Combo data is
+	 * generated based on the integer <code>values</code> where the index
+	 * of <code>values</code> corresponds to the index of <code>valueLabels</code>
+	 * 
+	 * @param parent the composite to create the combo box in
+	 * @param label the label to give the combo box
+	 * @param key the unique key to identify the combo box
+	 * @param values the values represented by the combo options
+	 * @param valueLabels the calues displayed in the combo box
+	 * @param indent how far to indent the combo box label
+	 * 
+	 * @return the generated combo box
+	 */
+	protected Combo addComboBox(Composite parent, String label, String key, int[] values, String[] valueLabels, int indent) {
+		GridData gd= new GridData(GridData.FILL, GridData.CENTER, true, false, 2, 1);
+		gd.horizontalIndent= indent;
+				
+		Label labelControl= new Label(parent, SWT.LEFT);
+		labelControl.setFont(JFaceResources.getDialogFont());
+		labelControl.setText(label);
+		labelControl.setLayoutData(gd);
+				
+		Combo comboBox= newComboControl(parent, key, values, valueLabels);
+		comboBox.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
+
+		return comboBox;
+	}
+	
+	/**
+	 * Creates a combo box and associates the combo data with the
+	 * combo box.
+	 * 
+	 * @param composite the composite to create the combo box in
+	 * @param key the unique key to identify the combo box
+	 * @param values the values represented by the combo options
+	 * @param valueLabels the values displayed in the combo box
+	 * 
+	 * @return the generated combo box
+	 */
+	protected Combo newComboControl(Composite composite, String key, int[] values, String[] valueLabels) {
+		ComboData data = new ComboData(key, values, -1);
+		
+		Combo comboBox= new Combo(composite, SWT.READ_ONLY);
+		comboBox.setItems(valueLabels);
+		comboBox.setData(data);
+		comboBox.addSelectionListener(getSelectionListener());
+		comboBox.setFont(JFaceResources.getDialogFont());
+			
+		makeScrollableCompositeAware(comboBox);
+		
+		int severity = -1;
+		if(key != null)
+			severity = fPreferencesService.getInt(getPreferenceNodeQualifier(), key, ValidationMessage.WARNING, createPreferenceScopes());
+
+		if (severity == ValidationMessage.ERROR || severity == ValidationMessage.WARNING || severity == ValidationMessage.IGNORE) {
+			data.setSeverity(severity);
+			data.originalSeverity = severity;
+		}
+		
+		if(data.getIndex() >= 0)
+			comboBox.select(data.getIndex());
+		
+		fCombos.add(comboBox);
+		return comboBox;
+	}
+	
+	protected SelectionListener getSelectionListener() {
+		if (fSelectionListener == null) {
+			fSelectionListener= new SelectionListener() {
+				public void widgetDefaultSelected(SelectionEvent e) {}
+	
+				public void widgetSelected(SelectionEvent e) {
+					controlChanged(e.widget);
+				}
+			};
+		}
+		return fSelectionListener;
+	}
+	
+	protected void controlChanged(Widget widget) {
+		ComboData data= (ComboData) widget.getData();
+		if (widget instanceof Combo) {
+			data.setIndex(((Combo)widget).getSelectionIndex());
+		} else {
+			return;
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * @see org.eclipse.wst.sse.ui.internal.preferences.ui.AbstractSettingsPage#storeValues()
+	 */
+	protected void storeValues() {
+		if(fCombos == null || fCombos.size() == 0)
+			return;
+		
+		Iterator it = fCombos.iterator();
+		
+		IScopeContext[] contexts = createPreferenceScopes();
+
+		while(it.hasNext()) {
+			ComboData data = (ComboData) ((Combo)it.next()).getData();
+			if(data.getKey() != null) {
+				contexts[0].getNode(getPreferenceNodeQualifier()).putInt(data.getKey(), data.getSeverity());
+			}
+		}
+		
+		for(int i = 0; i < contexts.length; i++) {
+			try {
+				contexts[i].getNode(getPreferenceNodeQualifier()).flush();
+			}
+			catch (BackingStoreException e) {
+				
+			}
+		}
+	}
+	
+	protected ExpandableComposite getParentExpandableComposite(Control control) {
+		Control parent= control.getParent();
+		while (!(parent instanceof ExpandableComposite) && parent != null) {
+			parent= parent.getParent();
+		}
+		if (parent instanceof ExpandableComposite) {
+			return (ExpandableComposite) parent;
+		}
+		return null;
+	}
+	
+	protected ExpandableComposite createStyleSection(Composite parent, String label, int nColumns) {
+		ExpandableComposite excomposite= new ExpandableComposite(parent, SWT.NONE, ExpandableComposite.TWISTIE | ExpandableComposite.CLIENT_INDENT);
+		excomposite.setText(label);
+		excomposite.setExpanded(false);
+		excomposite.setFont(JFaceResources.getFontRegistry().getBold(JFaceResources.DIALOG_FONT));
+		excomposite.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, false, nColumns, 1));
+		excomposite.addExpansionListener(new ExpansionAdapter() {
+			public void expansionStateChanged(ExpansionEvent e) {
+				expandedStateChanged((ExpandableComposite) e.getSource());
+			}
+		});
+		fExpandables.add(excomposite);
+		makeScrollableCompositeAware(excomposite);
+		return excomposite;
+	}
+	
+	protected final void expandedStateChanged(ExpandableComposite expandable) {
+		ScrolledPageContent parentScrolledComposite= getParentScrolledComposite(expandable);
+		if (parentScrolledComposite != null) {
+			parentScrolledComposite.reflow(true);
+		}
+	}
+	
+	private void makeScrollableCompositeAware(Control control) {
+		ScrolledPageContent parentScrolledComposite= getParentScrolledComposite(control);
+		if (parentScrolledComposite != null) {
+			parentScrolledComposite.adaptChild(control);
+		}
+	}
+	
+	protected ScrolledPageContent getParentScrolledComposite(Control control) {
+		Control parent= control.getParent();
+		while (!(parent instanceof ScrolledPageContent) && parent != null) {
+			parent= parent.getParent();
+		}
+		if (parent instanceof ScrolledPageContent) {
+			return (ScrolledPageContent) parent;
+		}
+		return null;
+	}
+	
+	protected void storeSectionExpansionStates(IDialogSettings section) {
+		for(int i = 0; i < fExpandables.size(); i++) {
+			ExpandableComposite comp = (ExpandableComposite) fExpandables.get(i);
+			section.put(SETTINGS_EXPANDED + String.valueOf(i), comp.isExpanded());
+		}
+	}
+	
+	protected void restoreSectionExpansionStates(IDialogSettings settings) {
+		for (int i= 0; i < fExpandables.size(); i++) {
+			ExpandableComposite excomposite= (ExpandableComposite) fExpandables.get(i);
+			if (settings == null) {
+				excomposite.setExpanded(i == 0); // only expand the first node by default
+			} else {
+				excomposite.setExpanded(settings.getBoolean(SETTINGS_EXPANDED + String.valueOf(i)));
+			}
+		}
+	}
+	
+	protected void resetSeverities() {
+		IEclipsePreferences defaultContext = new DefaultScope().getNode(getPreferenceNodeQualifier());
+		for(int i = 0; i < fCombos.size(); i++) {
+			ComboData data = (ComboData)((Combo)fCombos.get(i)).getData();
+			int severity = defaultContext.getInt(data.getKey(), ValidationMessage.WARNING);
+			data.setSeverity(severity);
+			((Combo)fCombos.get(i)).select(data.getIndex());
+		}
+	}
+	
+	protected boolean shouldRevalidateOnSettingsChange() {
+		Iterator it = fCombos.iterator();
+
+		while (it.hasNext()) {
+			ComboData data = (ComboData) ((Combo) it.next()).getData();
+			if (data.isChanged())
+				return true;
+		}
+		return false;
+	}
+	
+	public boolean performOk() {
+		if(super.performOk() && shouldRevalidateOnSettingsChange()) {
+			MessageBox mb = new MessageBox(this.getShell(), SWT.APPLICATION_MODAL | SWT.YES | SWT.NO | SWT.CANCEL | SWT.ICON_INFORMATION | SWT.RIGHT);
+			mb.setText(HTMLUIMessages.Validation_Title);
+			/* Choose which message to use based on if its project or workspace settings */
+			String msg = (getProject() == null) ? HTMLUIMessages.Validation_Workspace : HTMLUIMessages.Validation_Project;
+			mb.setMessage(msg);
+			switch(mb.open()) {
+				case SWT.CANCEL:
+					return false;
+				case SWT.YES:
+					storeValues();
+					ValidateJob job = new ValidateJob(HTMLUIMessages.Validation_jobName);
+					job.schedule();
+				case SWT.NO:
+					storeValues();
+				default:
+					return true;
+			}
+		}
+		return true;
+	}
+	
+	/**
+	 * Performs validation after validation preferences have been modified.
+	 */
+	private class ValidateJob extends Job {
+		
+		public ValidateJob(String name) {
+			super(name);
+		}
+
+		protected IStatus run(IProgressMonitor monitor) {
+			IStatus status = Status.OK_STATUS;
+			try {
+				IProject[] projects = null;
+				/* Changed preferences for a single project, only validate it */
+				if(getProject() != null)
+					projects = new IProject[] {getProject()};
+				/* Workspace-wide preferences changed */
+				else {
+					/* Get all of the projects in the workspace */
+					projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
+					IEclipsePreferences prefs = null;
+					List projectList = new ArrayList();
+					
+					/* Filter out projects that use project-specific settings or have been closed */
+					for(int i = 0; i < projects.length; i++) {
+						prefs = new ProjectScope(projects[i]).getNode(getPreferenceNodeQualifier());
+						if(projects[i].isAccessible() && !prefs.getBoolean(getProjectSettingsKey(), false))
+							projectList.add(projects[i]);
+					}
+					projects = (IProject[]) projectList.toArray(new IProject[projectList.size()]);
+				}
+				fValidation.validate(projects, true, false, monitor);
+			}
+			catch (CoreException ce) {
+				status = Status.CANCEL_STATUS;
+			}
+			
+			return status;
+		}
+		
+	}
+	
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/preferences/ui/EmptyFilePreferencePage.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/preferences/ui/EmptyFilePreferencePage.java
new file mode 100644
index 0000000..cc3ca1b
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/preferences/ui/EmptyFilePreferencePage.java
@@ -0,0 +1,100 @@
+/*******************************************************************************
+ * Copyright (c) 2008 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.preferences.ui;
+
+import org.eclipse.jface.preference.PreferencePage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.ScrolledComposite;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+import org.eclipse.wst.html.ui.internal.HTMLUIMessages;
+
+public class EmptyFilePreferencePage extends PreferencePage implements IWorkbenchPreferencePage {
+
+	private Composite createComposite(Composite parent, int numColumns) {
+		noDefaultAndApplyButton();
+
+		Composite composite = new Composite(parent, SWT.NULL);
+
+		// GridLayout
+		GridLayout layout = new GridLayout();
+		layout.numColumns = numColumns;
+		composite.setLayout(layout);
+
+		// GridData
+		GridData data = new GridData(GridData.FILL);
+		data.horizontalIndent = 0;
+		data.verticalAlignment = GridData.FILL;
+		data.horizontalAlignment = GridData.FILL;
+		composite.setLayoutData(data);
+
+		return composite;
+	}
+
+	protected Control createContents(Composite parent) {
+		Composite composite = createScrolledComposite(parent);
+
+		String description = HTMLUIMessages.EmptyFilePreferencePage_0; 
+		Text text = new Text(composite, SWT.READ_ONLY);
+		// some themes on GTK have different background colors for Text and Labels
+		text.setBackground(composite.getBackground());
+		text.setText(description);
+
+		setSize(composite);
+		return composite;
+	}
+
+	private Composite createScrolledComposite(Composite parent) {
+		// create scrollbars for this parent when needed
+		final ScrolledComposite sc1 = new ScrolledComposite(parent, SWT.H_SCROLL | SWT.V_SCROLL);
+		sc1.setLayoutData(new GridData(GridData.FILL_BOTH));
+		Composite composite = createComposite(sc1, 1);
+		sc1.setContent(composite);
+
+		// not calling setSize for composite will result in a blank composite,
+		// so calling it here initially
+		// setSize actually needs to be called after all controls are created,
+		// so scrolledComposite
+		// has correct minSize
+		setSize(composite);
+		return composite;
+	}
+
+	public void init(IWorkbench workbench) {
+	}
+
+	private void setSize(Composite composite) {
+		if (composite != null) {
+			// Note: The font is set here in anticipation that the class inheriting
+			//       this base class may add widgets to the dialog.   setSize
+			//       is assumed to be called just before we go live.
+			applyDialogFont(composite);
+			Point minSize = composite.computeSize(SWT.DEFAULT, SWT.DEFAULT);
+			composite.setSize(minSize);
+			// set scrollbar composite's min size so page is expandable but
+			// has scrollbars when needed
+			if (composite.getParent() instanceof ScrolledComposite) {
+				ScrolledComposite sc1 = (ScrolledComposite) composite.getParent();
+				sc1.setMinSize(minSize);
+				sc1.setExpandHorizontal(true);
+				sc1.setExpandVertical(true);
+			}
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/preferences/ui/HTMLColorPage.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/preferences/ui/HTMLColorPage.java
new file mode 100644
index 0000000..c299dac
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/preferences/ui/HTMLColorPage.java
@@ -0,0 +1,127 @@
+/*******************************************************************************
+ * Copyright (c) 2004,2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.preferences.ui;
+
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.Iterator;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.wst.html.core.internal.provisional.contenttype.ContentTypeIdForHTML;
+import org.eclipse.wst.html.ui.internal.HTMLUIMessages;
+import org.eclipse.wst.html.ui.internal.HTMLUIPlugin;
+import org.eclipse.wst.html.ui.internal.editor.IHelpContextIds;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.IModelManager;
+import org.eclipse.wst.sse.ui.internal.preferences.OverlayPreferenceStore;
+import org.eclipse.wst.sse.ui.internal.preferences.OverlayPreferenceStore.OverlayKey;
+import org.eclipse.wst.sse.ui.internal.preferences.ui.StyledTextColorPicker;
+import org.eclipse.wst.xml.ui.internal.preferences.XMLColorPage;
+
+/**
+ * @deprecated
+ */
+public class HTMLColorPage extends XMLColorPage {
+
+	/**
+	 * Set up all the style preference keys in the overlay store
+	 */
+	protected OverlayKey[] createOverlayStoreKeys() {
+		ArrayList overlayKeys = new ArrayList();
+		
+		ArrayList styleList = new ArrayList();
+		initStyleList(styleList);
+		Iterator i = styleList.iterator();
+		while (i.hasNext()) {
+			overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, (String)i.next()));	
+		}
+
+		OverlayPreferenceStore.OverlayKey[] keys = new OverlayPreferenceStore.OverlayKey[overlayKeys.size()];
+		overlayKeys.toArray(keys);
+		return keys;
+	}
+
+	public String getSampleText() {
+		return HTMLUIMessages.Sample_HTML_doc;
+
+	}
+
+	protected void initContextStyleMap(Dictionary contextStyleMap) {
+
+		initCommonContextStyleMap(contextStyleMap);
+		initDocTypeContextStyleMap(contextStyleMap);
+		// FIXME: these were "brute forced" commented out when moving XMLJSPRegionContexts
+		// effect is unknown, but thought just to effect preference page
+		//contextStyleMap.put(XMLJSPRegionContexts.JSP_DIRECTIVE_NAME, IStyleConstantsXML.TAG_NAME);
+		//contextStyleMap.put(XMLJSPRegionContexts.JSP_COMMENT_OPEN, IStyleConstantsXML.COMMENT_BORDER);
+		//contextStyleMap.put(XMLJSPRegionContexts.JSP_COMMENT_TEXT, IStyleConstantsXML.COMMENT_TEXT);
+		//contextStyleMap.put(XMLJSPRegionContexts.JSP_COMMENT_CLOSE, IStyleConstantsXML.COMMENT_BORDER);
+	}
+
+	protected void initDescriptions(Dictionary descriptions) {
+
+		initCommonDescriptions(descriptions);
+		initDocTypeDescriptions(descriptions);
+	}
+
+	protected void initStyleList(ArrayList list) {
+		initCommonStyleList(list);
+		initDocTypeStyleList(list);
+		//	list.add(HTMLColorManager.SCRIPT_AREA_BORDER);
+
+	}
+
+	protected void setupPicker(StyledTextColorPicker picker) {
+		IModelManager mmanager = StructuredModelManager.getModelManager();
+		picker.setParser(mmanager.createStructuredDocumentFor(ContentTypeIdForHTML.ContentTypeID_HTML).getParser());
+
+		// create descriptions for hilighting types
+		Dictionary descriptions = new Hashtable();
+		initDescriptions(descriptions);
+
+		// map region types to hilighting types
+		Dictionary contextStyleMap = new Hashtable();
+		initContextStyleMap(contextStyleMap);
+
+		ArrayList styleList = new ArrayList();
+		initStyleList(styleList);
+
+		picker.setContextStyleMap(contextStyleMap);
+		picker.setDescriptions(descriptions);
+		picker.setStyleList(styleList);
+
+		//	updatePickerFont(picker);
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.preference.PreferencePage#createContents(org.eclipse.swt.widgets.Composite)
+	 */
+	protected Control createContents(Composite parent) {
+		Control c = super.createContents(parent);
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(c, IHelpContextIds.HTML_PREFWEBX_STYLES_HELPID);
+		return c;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.preference.PreferencePage#doGetPreferenceStore()
+	 */
+	protected IPreferenceStore doGetPreferenceStore() {
+		return HTMLUIPlugin.getDefault().getPreferenceStore();
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.sse.ui.preferences.ui.AbstractColorPage#savePreferences()
+	 */
+	protected void savePreferences() {
+		HTMLUIPlugin.getDefault().savePluginPreferences();
+	}
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/preferences/ui/HTMLContentAssistPreferencePage.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/preferences/ui/HTMLContentAssistPreferencePage.java
new file mode 100644
index 0000000..c1fc2b6
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/preferences/ui/HTMLContentAssistPreferencePage.java
@@ -0,0 +1,200 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.preferences.ui;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+import org.eclipse.wst.html.ui.internal.HTMLUIMessages;
+import org.eclipse.wst.html.ui.internal.HTMLUIPlugin;
+import org.eclipse.wst.html.ui.internal.preferences.HTMLUIPreferenceNames;
+import org.eclipse.wst.sse.ui.internal.Logger;
+import org.eclipse.wst.sse.ui.internal.contentassist.CompletionProposoalCatigoriesConfigurationRegistry;
+import org.eclipse.wst.sse.ui.internal.preferences.ui.AbstractPreferencePage;
+import org.eclipse.wst.sse.ui.preferences.CodeAssistCyclingConfigurationBlock;
+import org.eclipse.wst.sse.ui.preferences.ICompletionProposalCategoriesConfigurationWriter;
+
+/**
+ * <p>Defines the preference page for allowing the user to change the content
+ * assist preferences</p>
+ */
+public class HTMLContentAssistPreferencePage extends AbstractPreferencePage implements
+		IWorkbenchPreferencePage {
+
+	private static final String HTML_CONTENT_TYPE_ID = "org.eclipse.wst.html.core.htmlsource"; //$NON-NLS-1$
+	
+	// Auto Activation
+	private Button fAutoPropose;
+	private Label fAutoProposeLabel;
+	private Text fAutoProposeText;
+	
+	/** configuration block for changing preference having to do with the content assist categories */
+	private CodeAssistCyclingConfigurationBlock fConfigurationBlock;
+	
+	/**
+	 * @see org.eclipse.wst.sse.ui.internal.preferences.ui.AbstractPreferencePage#createContents(org.eclipse.swt.widgets.Composite)
+	 */
+	protected Control createContents(Composite parent) {
+		final Composite composite = super.createComposite(parent, 1);
+		
+		createContentsForAutoActivationGroup(composite);
+		createContentsForCyclingGroup(composite);
+		
+		setSize(composite);
+		loadPreferences();
+		
+		return composite;
+	}
+	
+	/**
+	 * @see org.eclipse.wst.sse.ui.internal.preferences.ui.AbstractPreferencePage#performDefaults()
+	 */
+	protected void performDefaults() {
+		performDefaultsForAutoActivationGroup();
+		performDefaultsForCyclingGroup();
+
+		validateValues();
+		enableValues();
+
+		super.performDefaults();
+	}
+	
+	/**
+	 * @see org.eclipse.wst.sse.ui.internal.preferences.ui.AbstractPreferencePage#initializeValues()
+	 */
+	protected void initializeValues() {
+		initializeValuesForAutoActivationGroup();
+		initializeValuesForCyclingGroup();
+	}
+	
+	/**
+	 * @see org.eclipse.wst.sse.ui.internal.preferences.ui.AbstractPreferencePage#storeValues()
+	 */
+	protected void storeValues() {
+		storeValuesForAutoActivationGroup();
+		storeValuesForCyclingGroup();
+	}
+	
+	/**
+	 * @see org.eclipse.wst.sse.ui.internal.preferences.ui.AbstractPreferencePage#enableValues()
+	 */
+	protected void enableValues() {
+		if (fAutoPropose != null) {
+			if (fAutoPropose.getSelection()) {
+				fAutoProposeLabel.setEnabled(true);
+				fAutoProposeText.setEnabled(true);
+			}
+			else {
+				fAutoProposeLabel.setEnabled(false);
+				fAutoProposeText.setEnabled(false);
+			}
+		}
+	}
+	
+	/**
+	 * @see org.eclipse.jface.preference.PreferencePage#doGetPreferenceStore()
+	 */
+	protected IPreferenceStore doGetPreferenceStore() {
+		return HTMLUIPlugin.getDefault().getPreferenceStore();
+	}
+
+	/**
+	 * <p>Create contents for the auto activation preference group</p>
+	 * @param parent {@link Composite} parent of the group
+	 */
+	private void createContentsForAutoActivationGroup(Composite parent) {
+		Group contentAssistGroup = createGroup(parent, 2);
+		contentAssistGroup.setText(HTMLUIMessages.Auto_Activation_UI_);
+
+		fAutoPropose = createCheckBox(contentAssistGroup, HTMLUIMessages.Automatically_make_suggest_UI_);
+		((GridData) fAutoPropose.getLayoutData()).horizontalSpan = 2;
+		fAutoPropose.addSelectionListener(this);
+
+		fAutoProposeLabel = createLabel(contentAssistGroup, HTMLUIMessages.Prompt_when_these_characte_UI_);
+		fAutoProposeText = createTextField(contentAssistGroup);
+	}
+	
+	/**
+	 * <p>Create the contents for the content assist cycling preference group</p>
+	 * @param parent {@link Composite} parent of the group
+	 */
+	private void createContentsForCyclingGroup(Composite parent) {
+		ICompletionProposalCategoriesConfigurationWriter configurationWriter = CompletionProposoalCatigoriesConfigurationRegistry.getDefault().getWritableConfiguration(HTML_CONTENT_TYPE_ID);
+		
+		if(configurationWriter != null) {
+			fConfigurationBlock = new CodeAssistCyclingConfigurationBlock(HTML_CONTENT_TYPE_ID, configurationWriter);
+			fConfigurationBlock.createContents(parent, HTMLUIMessages.Cycling_UI_);
+		} else {
+			Logger.log(Logger.ERROR, "There should be an ICompletionProposalCategoriesConfigurationWriter" + //$NON-NLS-1$
+					" specified for the HTML content type, but can't fine it, thus can't create user" + //$NON-NLS-1$
+					" preference block for editing proposal categories preferences."); //$NON-NLS-1$
+		}
+	}
+	
+	/**
+	 * <p>Store the values for the auto activation group</p>
+	 */
+	private void storeValuesForAutoActivationGroup() {
+		getPreferenceStore().setValue(HTMLUIPreferenceNames.AUTO_PROPOSE, fAutoPropose.getSelection());
+		getPreferenceStore().setValue(HTMLUIPreferenceNames.AUTO_PROPOSE_CODE, fAutoProposeText.getText());
+	}
+	
+	/**
+	 * <p>Store the values for the cycling group</p>
+	 */
+	private void storeValuesForCyclingGroup() {
+		if (fConfigurationBlock != null) {
+			fConfigurationBlock.storeValues();
+		}
+	}
+	
+	/**
+	 * <p>Initialize the values for the auto activation group</p>
+	 */
+	private void initializeValuesForAutoActivationGroup() {
+		// Content Assist
+		fAutoPropose.setSelection(getPreferenceStore().getBoolean(HTMLUIPreferenceNames.AUTO_PROPOSE));
+		fAutoProposeText.setText(getPreferenceStore().getString(HTMLUIPreferenceNames.AUTO_PROPOSE_CODE));
+	}
+	
+	/**
+	 * <p>Initialize the values for the cycling group</p>
+	 */
+	private void initializeValuesForCyclingGroup() {
+		if(fConfigurationBlock != null) {
+			fConfigurationBlock.initializeValues();
+		}
+	}
+	
+	/**
+	 * <p>Load the defaults for the auto activation group</p>
+	 */
+	private void performDefaultsForAutoActivationGroup() {
+		// Content Assist
+		fAutoPropose.setSelection(getPreferenceStore().getDefaultBoolean(HTMLUIPreferenceNames.AUTO_PROPOSE));
+		fAutoProposeText.setText(getPreferenceStore().getDefaultString(HTMLUIPreferenceNames.AUTO_PROPOSE_CODE));
+	}
+	
+	/**
+	 * <p>Load the defaults of the cycling group</p>
+	 */
+	private void performDefaultsForCyclingGroup() {
+		if(fConfigurationBlock != null) {
+			fConfigurationBlock.performDefaults();
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/preferences/ui/HTMLFilesPreferencePage.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/preferences/ui/HTMLFilesPreferencePage.java
new file mode 100644
index 0000000..1aa3304
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/preferences/ui/HTMLFilesPreferencePage.java
@@ -0,0 +1,114 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.preferences.ui;
+
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.core.runtime.content.IContentType;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.wst.html.core.internal.HTMLCorePlugin;
+import org.eclipse.wst.html.core.internal.provisional.contenttype.ContentTypeIdForHTML;
+import org.eclipse.wst.html.ui.internal.HTMLUIMessages;
+import org.eclipse.wst.html.ui.internal.HTMLUIPlugin;
+import org.eclipse.wst.html.ui.internal.editor.IHelpContextIds;
+import org.eclipse.wst.sse.core.internal.encoding.CommonEncodingPreferenceNames;
+import org.eclipse.wst.xml.ui.internal.preferences.WorkbenchDefaultEncodingSettings;
+import org.eclipse.wst.xml.ui.internal.preferences.XMLFilesPreferencePage;
+
+public class HTMLFilesPreferencePage extends XMLFilesPreferencePage {
+	private WorkbenchDefaultEncodingSettings fInputEncodingSettings = null;
+
+	protected Preferences getModelPreferences() {
+		return HTMLCorePlugin.getDefault().getPluginPreferences();
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.preference.PreferencePage#doGetPreferenceStore()
+	 */
+	protected IPreferenceStore doGetPreferenceStore() {
+		return HTMLUIPlugin.getDefault().getPreferenceStore();
+	}
+
+	protected void doSavePreferenceStore() {
+		HTMLCorePlugin.getDefault().savePluginPreferences(); // model
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.preference.PreferencePage#createContents(org.eclipse.swt.widgets.Composite)
+	 */
+	protected Control createContents(Composite parent) {
+		Composite scrolledComposite = createScrolledComposite(parent);
+		createContentsForCreatingGroup(scrolledComposite);
+		createContentsForLoadingGroup(scrolledComposite);
+
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(scrolledComposite, IHelpContextIds.HTML_PREFWEBX_FILES_HELPID);
+
+		setSize(scrolledComposite);
+		loadPreferences();
+
+		return scrolledComposite;
+	}
+
+	protected void createContentsForLoadingGroup(Composite parent) {
+		Group group = createGroup(parent, 1);
+		group.setText(HTMLUIMessages.HTMLFilesPreferencePage_0);
+
+		fInputEncodingSettings = new WorkbenchDefaultEncodingSettings(group);
+	}
+
+	protected IContentType getContentType() {
+		return Platform.getContentTypeManager().getContentType(ContentTypeIdForHTML.ContentTypeID_HTML);
+	}
+
+	protected void initializeValues() {
+		super.initializeValues();
+		initializeValuesForLoadingGroup();
+	}
+
+	protected void initializeValuesForLoadingGroup() {
+		String encoding = getModelPreferences().getString(CommonEncodingPreferenceNames.INPUT_CODESET);
+
+		fInputEncodingSettings.setIANATag(encoding);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.preference.PreferencePage#performDefaults()
+	 */
+	protected void performDefaults() {
+		super.performDefaults();
+		performDefaultsForLoadingGroup();
+	}
+
+	protected void performDefaultsForLoadingGroup() {
+		String encoding = getModelPreferences().getDefaultString(CommonEncodingPreferenceNames.INPUT_CODESET);
+
+		fInputEncodingSettings.setIANATag(encoding);
+	}
+
+	protected void storeValues() {
+		super.storeValues();
+		storeValuesForLoadingGroup();
+	}
+
+	protected void storeValuesForLoadingGroup() {
+		getModelPreferences().setValue(CommonEncodingPreferenceNames.INPUT_CODESET, fInputEncodingSettings.getIANATag());
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/preferences/ui/HTMLSourcePreferencePage.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/preferences/ui/HTMLSourcePreferencePage.java
new file mode 100644
index 0000000..a5e711a
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/preferences/ui/HTMLSourcePreferencePage.java
@@ -0,0 +1,284 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.preferences.ui;
+
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.jface.layout.GridDataFactory;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Spinner;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.dialogs.PreferenceLinkArea;
+import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer;
+import org.eclipse.wst.html.core.internal.HTMLCorePlugin;
+import org.eclipse.wst.html.core.internal.preferences.HTMLCorePreferenceNames;
+import org.eclipse.wst.html.ui.internal.HTMLUIMessages;
+import org.eclipse.wst.html.ui.internal.HTMLUIPlugin;
+import org.eclipse.wst.html.ui.internal.editor.IHelpContextIds;
+import org.eclipse.wst.sse.ui.internal.preferences.ui.AbstractPreferencePage;
+
+public class HTMLSourcePreferencePage extends AbstractPreferencePage {
+	private Button fTagNameUpper = null;
+	private Button fTagNameLower = null;
+	private Button fAttrNameUpper = null;
+	private Button fAttrNameLower = null;
+
+	private final int MIN_INDENTATION_SIZE = 0;
+	private final int MAX_INDENTATION_SIZE = 16;
+
+	private Button fClearAllBlankLines;
+
+	// Formatting
+	private Text fLineWidthText;
+	private Button fSplitMultiAttrs;
+	private Button fAlignEndBracket;
+	private Button fIndentUsingTabs;
+	private Button fIndentUsingSpaces;
+	private Spinner fIndentationSize;
+
+	private Composite createContentsForPreferredCaseGroup(Composite parent, int columnSpan) {
+		Group caseGroup = createGroup(parent, columnSpan);
+		caseGroup.setText(HTMLUIMessages.Preferred_markup_case_UI_);
+
+		// d257064 need to associate group w/ radio buttons so radio buttons
+		// header can be read
+		Group tagNameGroup = createGroup(caseGroup, 1);
+		tagNameGroup.setText(HTMLUIMessages.Tag_names__UI_);
+		fTagNameUpper = createRadioButton(tagNameGroup, HTMLUIMessages.Tag_names_Upper_case_UI_);
+		fTagNameLower = createRadioButton(tagNameGroup, HTMLUIMessages.Tag_names_Lower_case_UI_);
+
+		// d257064 need to associate group w/ radio buttons so radio buttons
+		// header can be read
+		Group attrNameGroup = createGroup(caseGroup, 1);
+		attrNameGroup.setText(HTMLUIMessages.Attribute_names__UI_);
+		fAttrNameUpper = createRadioButton(attrNameGroup, HTMLUIMessages.Attribute_names_Upper_case_UI_);
+		fAttrNameLower = createRadioButton(attrNameGroup, HTMLUIMessages.Attribute_names_Lower_case_UI_);
+
+		return parent;
+
+	}
+
+	private void createContentsForFormattingGroup(Composite parent) {
+		Group formattingGroup = createGroup(parent, 2);
+		formattingGroup.setText(HTMLUIMessages.Formatting_UI_);
+
+		createLabel(formattingGroup, HTMLUIMessages.Line_width__UI_);
+		fLineWidthText = new Text(formattingGroup, SWT.SINGLE | SWT.BORDER);
+		GridData gData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING | GridData.BEGINNING);
+		gData.widthHint = 25;
+		fLineWidthText.setLayoutData(gData);
+		fLineWidthText.addModifyListener(this);
+
+		fSplitMultiAttrs = createCheckBox(formattingGroup, HTMLUIMessages.Split_multiple_attributes);
+		((GridData) fSplitMultiAttrs.getLayoutData()).horizontalSpan = 2;
+		fAlignEndBracket = createCheckBox(formattingGroup, HTMLUIMessages.Align_final_bracket);
+		((GridData) fAlignEndBracket.getLayoutData()).horizontalSpan = 2;
+		fClearAllBlankLines = createCheckBox(formattingGroup, HTMLUIMessages.Clear_all_blank_lines_UI_);
+		((GridData) fClearAllBlankLines.getLayoutData()).horizontalSpan = 2;
+
+		// [269224] - Place the indent controls in their own composite for proper tab ordering
+		Composite indentComposite = createComposite(formattingGroup, 1);
+		((GridData) indentComposite.getLayoutData()).horizontalSpan = 2;
+		((GridLayout) indentComposite.getLayout()).marginWidth = 0;
+		((GridLayout) indentComposite.getLayout()).marginHeight = 0;
+
+		fIndentUsingTabs = createRadioButton(indentComposite, HTMLUIMessages.Indent_using_tabs);
+		((GridData) fIndentUsingTabs.getLayoutData()).horizontalSpan = 1;
+
+		fIndentUsingSpaces = createRadioButton(indentComposite, HTMLUIMessages.Indent_using_spaces);
+		((GridData) fIndentUsingSpaces.getLayoutData()).horizontalSpan = 1;
+
+		createLabel(formattingGroup, HTMLUIMessages.Indentation_size);
+		fIndentationSize = new Spinner(formattingGroup, SWT.READ_ONLY | SWT.BORDER);
+		GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
+		fIndentationSize.setLayoutData(gd);
+		fIndentationSize.setToolTipText(HTMLUIMessages.Indentation_size_tip);
+		fIndentationSize.setMinimum(MIN_INDENTATION_SIZE);
+		fIndentationSize.setMaximum(MAX_INDENTATION_SIZE);
+		fIndentationSize.setIncrement(1);
+		fIndentationSize.setPageIncrement(4);
+		fIndentationSize.addModifyListener(this);
+	}
+
+	protected void performDefaults() {
+		fTagNameUpper.setSelection(getModelPreferences().getDefaultInt(HTMLCorePreferenceNames.TAG_NAME_CASE) == HTMLCorePreferenceNames.UPPER);
+		fTagNameLower.setSelection(getModelPreferences().getDefaultInt(HTMLCorePreferenceNames.TAG_NAME_CASE) == HTMLCorePreferenceNames.LOWER);
+		fAttrNameUpper.setSelection(getModelPreferences().getDefaultInt(HTMLCorePreferenceNames.ATTR_NAME_CASE) == HTMLCorePreferenceNames.UPPER);
+		fAttrNameLower.setSelection(getModelPreferences().getDefaultInt(HTMLCorePreferenceNames.ATTR_NAME_CASE) == HTMLCorePreferenceNames.LOWER);
+
+		performDefaultsForFormattingGroup();
+
+		validateValues();
+		enableValues();
+
+		super.performDefaults();
+	}
+
+	private void performDefaultsForFormattingGroup() {
+		// Formatting
+		fLineWidthText.setText(getModelPreferences().getDefaultString(HTMLCorePreferenceNames.LINE_WIDTH));
+		fSplitMultiAttrs.setSelection(getModelPreferences().getDefaultBoolean(HTMLCorePreferenceNames.SPLIT_MULTI_ATTRS));
+		fAlignEndBracket.setSelection(getModelPreferences().getDefaultBoolean(HTMLCorePreferenceNames.ALIGN_END_BRACKET));
+		fClearAllBlankLines.setSelection(getModelPreferences().getDefaultBoolean(HTMLCorePreferenceNames.CLEAR_ALL_BLANK_LINES));
+
+		if (HTMLCorePreferenceNames.TAB.equals(getModelPreferences().getDefaultString(HTMLCorePreferenceNames.INDENTATION_CHAR))) {
+			fIndentUsingTabs.setSelection(true);
+			fIndentUsingSpaces.setSelection(false);
+		}
+		else {
+			fIndentUsingSpaces.setSelection(true);
+			fIndentUsingTabs.setSelection(false);
+		}
+		fIndentationSize.setSelection(getModelPreferences().getDefaultInt(HTMLCorePreferenceNames.INDENTATION_SIZE));
+	}
+
+	protected void initializeValues() {
+		fTagNameUpper.setSelection(getModelPreferences().getInt(HTMLCorePreferenceNames.TAG_NAME_CASE) == HTMLCorePreferenceNames.UPPER);
+		fTagNameLower.setSelection(getModelPreferences().getInt(HTMLCorePreferenceNames.TAG_NAME_CASE) == HTMLCorePreferenceNames.LOWER);
+		fAttrNameUpper.setSelection(getModelPreferences().getInt(HTMLCorePreferenceNames.ATTR_NAME_CASE) == HTMLCorePreferenceNames.UPPER);
+		fAttrNameLower.setSelection(getModelPreferences().getInt(HTMLCorePreferenceNames.ATTR_NAME_CASE) == HTMLCorePreferenceNames.LOWER);
+
+		initializeValuesForFormattingGroup();
+	}
+
+	private void initializeValuesForFormattingGroup() {
+		// Formatting
+		fLineWidthText.setText(getModelPreferences().getString(HTMLCorePreferenceNames.LINE_WIDTH));
+		fSplitMultiAttrs.setSelection(getModelPreferences().getBoolean(HTMLCorePreferenceNames.SPLIT_MULTI_ATTRS));
+		fAlignEndBracket.setSelection(getModelPreferences().getBoolean(HTMLCorePreferenceNames.ALIGN_END_BRACKET));
+		fClearAllBlankLines.setSelection(getModelPreferences().getBoolean(HTMLCorePreferenceNames.CLEAR_ALL_BLANK_LINES));
+
+		if (HTMLCorePreferenceNames.TAB.equals(getModelPreferences().getString(HTMLCorePreferenceNames.INDENTATION_CHAR))) {
+			fIndentUsingTabs.setSelection(true);
+			fIndentUsingSpaces.setSelection(false);
+		}
+		else {
+			fIndentUsingSpaces.setSelection(true);
+			fIndentUsingTabs.setSelection(false);
+		}
+
+		fIndentationSize.setSelection(getModelPreferences().getInt(HTMLCorePreferenceNames.INDENTATION_SIZE));
+	}
+
+	protected void storeValues() {
+		if (fTagNameUpper.getSelection())
+			getModelPreferences().setValue(HTMLCorePreferenceNames.TAG_NAME_CASE, HTMLCorePreferenceNames.UPPER);
+		else
+			getModelPreferences().setValue(HTMLCorePreferenceNames.TAG_NAME_CASE, HTMLCorePreferenceNames.LOWER);
+		if (fAttrNameUpper.getSelection())
+			getModelPreferences().setValue(HTMLCorePreferenceNames.ATTR_NAME_CASE, HTMLCorePreferenceNames.UPPER);
+		else
+			getModelPreferences().setValue(HTMLCorePreferenceNames.ATTR_NAME_CASE, HTMLCorePreferenceNames.LOWER);
+
+		storeValuesForFormattingGroup();
+	}
+
+	private void storeValuesForFormattingGroup() {
+		// Formatting
+		getModelPreferences().setValue(HTMLCorePreferenceNames.LINE_WIDTH, fLineWidthText.getText());
+		getModelPreferences().setValue(HTMLCorePreferenceNames.SPLIT_MULTI_ATTRS, fSplitMultiAttrs.getSelection());
+		getModelPreferences().setValue(HTMLCorePreferenceNames.ALIGN_END_BRACKET, fAlignEndBracket.getSelection());
+		getModelPreferences().setValue(HTMLCorePreferenceNames.CLEAR_ALL_BLANK_LINES, fClearAllBlankLines.getSelection());
+
+		if (fIndentUsingTabs.getSelection()) {
+			getModelPreferences().setValue(HTMLCorePreferenceNames.INDENTATION_CHAR, HTMLCorePreferenceNames.TAB);
+		}
+		else {
+			getModelPreferences().setValue(HTMLCorePreferenceNames.INDENTATION_CHAR, HTMLCorePreferenceNames.SPACE);
+		}
+		getModelPreferences().setValue(HTMLCorePreferenceNames.INDENTATION_SIZE, fIndentationSize.getSelection());
+	}
+
+	public boolean performOk() {
+		boolean result = super.performOk();
+
+		doSavePreferenceStore();
+
+		return result;
+	}
+
+	protected Preferences getModelPreferences() {
+		return HTMLCorePlugin.getDefault().getPluginPreferences();
+	}
+
+	protected IPreferenceStore doGetPreferenceStore() {
+		return HTMLUIPlugin.getDefault().getPreferenceStore();
+	}
+
+	private void doSavePreferenceStore() {
+		HTMLUIPlugin.getDefault().savePluginPreferences(); // UI
+		HTMLCorePlugin.getDefault().savePluginPreferences(); // model
+	}
+
+	protected Control createContents(Composite parent) {
+		final Composite composite = super.createComposite(parent, 1);
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, IHelpContextIds.HTML_PREFWEBX_SOURCE_HELPID);
+
+		new PreferenceLinkArea(composite, SWT.WRAP | SWT.MULTI, "org.eclipse.wst.sse.ui.preferences.editor", HTMLUIMessages._UI_STRUCTURED_TEXT_EDITOR_PREFS_LINK,//$NON-NLS-1$
+					(IWorkbenchPreferenceContainer) getContainer(), null).getControl().setLayoutData(GridDataFactory.fillDefaults().hint(150, SWT.DEFAULT).create());
+		new Label(composite, SWT.NONE).setLayoutData(GridDataFactory.swtDefaults().create());
+
+		createContentsForFormattingGroup(composite);
+		createContentsForPreferredCaseGroup(composite, 2);
+		setSize(composite);
+		loadPreferences();
+
+		return composite;
+	}
+
+	protected void validateValues() {
+		boolean isError = false;
+		String widthText = null;
+
+		if (fLineWidthText != null) {
+			try {
+				widthText = fLineWidthText.getText();
+				int formattingLineWidth = Integer.parseInt(widthText);
+				if ((formattingLineWidth < WIDTH_VALIDATION_LOWER_LIMIT) || (formattingLineWidth > WIDTH_VALIDATION_UPPER_LIMIT)) {
+					throw new NumberFormatException();
+				}
+			}
+			catch (NumberFormatException nfexc) {
+				setInvalidInputMessage(widthText);
+				setValid(false);
+				isError = true;
+			}
+		}
+
+		int indentSize = 0;
+		if (fIndentationSize != null) {
+			try {
+				indentSize = fIndentationSize.getSelection();
+				if ((indentSize < MIN_INDENTATION_SIZE) || (indentSize > MAX_INDENTATION_SIZE)) {
+					throw new NumberFormatException();
+				}
+			}
+			catch (NumberFormatException nfexc) {
+				setInvalidInputMessage(Integer.toString(indentSize));
+				setValid(false);
+				isError = true;
+			}
+		}
+
+		if (!isError) {
+			setErrorMessage(null);
+			setValid(true);
+		}
+	}
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/preferences/ui/HTMLSyntaxColoringPage.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/preferences/ui/HTMLSyntaxColoringPage.java
new file mode 100644
index 0000000..ef0f01d
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/preferences/ui/HTMLSyntaxColoringPage.java
@@ -0,0 +1,874 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.preferences.ui;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.jface.preference.ColorSelector;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.preference.PreferencePage;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.text.TextAttribute;
+import org.eclipse.jface.text.source.SourceViewer;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.ListViewer;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.StructuredViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerComparator;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.accessibility.ACC;
+import org.eclipse.swt.accessibility.AccessibleAdapter;
+import org.eclipse.swt.accessibility.AccessibleEvent;
+import org.eclipse.swt.custom.SashForm;
+import org.eclipse.swt.custom.StyleRange;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.KeyListener;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.events.TraverseEvent;
+import org.eclipse.swt.events.TraverseListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Link;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.dialogs.PreferencesUtil;
+import org.eclipse.wst.html.core.internal.provisional.contenttype.ContentTypeIdForHTML;
+import org.eclipse.wst.html.ui.internal.HTMLUIMessages;
+import org.eclipse.wst.html.ui.internal.HTMLUIPlugin;
+import org.eclipse.wst.html.ui.internal.editor.IHelpContextIds;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+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.ITextRegionList;
+import org.eclipse.wst.sse.ui.internal.SSEUIMessages;
+import org.eclipse.wst.sse.ui.internal.SSEUIPlugin;
+import org.eclipse.wst.sse.ui.internal.preferences.OverlayPreferenceStore;
+import org.eclipse.wst.sse.ui.internal.preferences.OverlayPreferenceStore.OverlayKey;
+import org.eclipse.wst.sse.ui.internal.preferences.ui.ColorHelper;
+import org.eclipse.wst.sse.ui.internal.util.EditorUtility;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+import org.eclipse.wst.xml.ui.internal.style.IStyleConstantsXML;
+
+import com.ibm.icu.text.Collator;
+
+/**
+ * A preference page to configure our XML syntax color. It resembles the JDT
+ * and CDT pages far more than our original color page while retaining the
+ * extra "click-to-find" functionality.
+ */
+public final class HTMLSyntaxColoringPage extends PreferencePage implements IWorkbenchPreferencePage {
+
+	private Button fBold;
+	private Label fForegroundLabel;
+	private Label fBackgroundLabel;
+	private Button fClearStyle;
+	private Map fContextToStyleMap;
+	private Color fDefaultForeground = null;
+	private Color fDefaultBackground = null;
+	private IStructuredDocument fDocument;
+	private ColorSelector fForegroundColorEditor;
+	private ColorSelector fBackgroundColorEditor;
+	private Button fItalic;
+	private OverlayPreferenceStore fOverlayStore;
+	private Button fStrike;
+	private Collection fStylePreferenceKeys;
+	private StructuredViewer fStylesViewer = null;
+	private Map fStyleToDescriptionMap;
+	private StyledText fText;
+	private Button fUnderline;
+
+	// activate controls based on the given local color type
+	private void activate(String namedStyle) {
+		Color foreground = fDefaultForeground;
+		Color background = fDefaultBackground;
+		if (namedStyle == null) {
+			fClearStyle.setEnabled(false);
+			fBold.setEnabled(false);
+			fItalic.setEnabled(false);
+			fStrike.setEnabled(false);
+			fUnderline.setEnabled(false);
+			fForegroundLabel.setEnabled(false);
+			fBackgroundLabel.setEnabled(false);
+			fForegroundColorEditor.setEnabled(false);
+			fBackgroundColorEditor.setEnabled(false);
+			fBold.setSelection(false);
+			fItalic.setSelection(false);
+			fStrike.setSelection(false);
+			fUnderline.setSelection(false);
+		}
+		else {
+			TextAttribute attribute = getAttributeFor(namedStyle);
+			fClearStyle.setEnabled(true);
+			fBold.setEnabled(true);
+			fItalic.setEnabled(true);
+			fStrike.setEnabled(true);
+			fUnderline.setEnabled(true);
+			fForegroundLabel.setEnabled(true);
+			fBackgroundLabel.setEnabled(true);
+			fForegroundColorEditor.setEnabled(true);
+			fBackgroundColorEditor.setEnabled(true);
+			fBold.setSelection((attribute.getStyle() & SWT.BOLD) != 0);
+			fItalic.setSelection((attribute.getStyle() & SWT.ITALIC) != 0);
+			fStrike.setSelection((attribute.getStyle() & TextAttribute.STRIKETHROUGH) != 0);
+			fUnderline.setSelection((attribute.getStyle() & TextAttribute.UNDERLINE) != 0);
+			if (attribute.getForeground() != null) {
+				foreground = attribute.getForeground();
+			}
+			if (attribute.getBackground() != null) {
+				background = attribute.getBackground();
+			}
+		}
+
+		fForegroundColorEditor.setColorValue(foreground.getRGB());
+		fBackgroundColorEditor.setColorValue(background.getRGB());
+	}
+
+	/**
+	 * Color the text in the sample area according to the current preferences
+	 */
+	void applyStyles() {
+		if (fText == null || fText.isDisposed())
+			return;
+		IStructuredDocumentRegion documentRegion = fDocument.getFirstStructuredDocumentRegion();
+		while (documentRegion != null) {
+			ITextRegionList regions = documentRegion.getRegions();
+			for (int i = 0; i < regions.size(); i++) {
+				ITextRegion currentRegion = regions.get(i);
+				// lookup the local coloring type and apply it
+				String namedStyle = (String) fContextToStyleMap.get(currentRegion.getType());
+				if (namedStyle == null)
+					continue;
+				TextAttribute attribute = getAttributeFor(namedStyle);
+				if (attribute == null)
+					continue;
+				StyleRange style = new StyleRange(documentRegion.getStartOffset(currentRegion), currentRegion.getTextLength(), attribute.getForeground(), attribute.getBackground(), attribute.getStyle());
+				style.strikeout = (attribute.getStyle() & TextAttribute.STRIKETHROUGH) != 0;
+				style.underline = (attribute.getStyle() & TextAttribute.UNDERLINE) != 0;
+				fText.setStyleRange(style);
+			}
+			documentRegion = documentRegion.getNext();
+		}
+	}
+
+	Button createCheckbox(Composite parent, String label) {
+		Button button = new Button(parent, SWT.CHECK);
+		button.setText(label);
+		button.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+		return button;
+	}
+
+	/**
+	 * Creates composite control and sets the default layout data.
+	 */
+	private Composite createComposite(Composite parent, int numColumns) {
+		Composite composite = new Composite(parent, SWT.NULL);
+
+		// GridLayout
+		GridLayout layout = new GridLayout();
+		layout.numColumns = numColumns;
+		layout.makeColumnsEqualWidth = false;
+		layout.marginHeight = 0;
+		layout.marginWidth = 0;
+		composite.setLayout(layout);
+
+		// GridData
+		GridData data = new GridData(SWT.FILL, SWT.FILL, true, false);
+		composite.setLayoutData(data);
+		return composite;
+	}
+
+	protected Control createContents(final Composite parent) {
+		initializeDialogUnits(parent);
+
+		fDefaultForeground = parent.getDisplay().getSystemColor(SWT.COLOR_LIST_FOREGROUND);
+		fDefaultBackground = parent.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND);
+		Composite pageComponent = createComposite(parent, 2);
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(pageComponent, IHelpContextIds.HTML_PREFWEBX_STYLES_HELPID);
+
+		Link link = new Link(pageComponent, SWT.WRAP);
+		link.setText(SSEUIMessages.SyntaxColoring_Link);
+		link.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				PreferencesUtil.createPreferenceDialogOn(parent.getShell(), e.text, null, null);
+			}
+		});
+
+		GridData linkData= new GridData(SWT.FILL, SWT.BEGINNING, true, false, 2, 1);
+		linkData.widthHint= 150; // only expand further if anyone else requires it
+		link.setLayoutData(linkData);
+
+		new Label(pageComponent, SWT.NONE).setLayoutData(new GridData());
+		new Label(pageComponent, SWT.NONE).setLayoutData(new GridData());
+
+		SashForm editor = new SashForm(pageComponent, SWT.VERTICAL);
+		GridData gridData2 = new GridData(SWT.FILL, SWT.FILL, true, true);
+		gridData2.horizontalSpan = 2;
+		editor.setLayoutData(gridData2);
+		SashForm top = new SashForm(editor, SWT.HORIZONTAL);
+		Composite styleEditor = createComposite(top, 1);
+		((GridLayout) styleEditor.getLayout()).marginRight = 5;
+		((GridLayout) styleEditor.getLayout()).marginLeft = 0;
+		createLabel(styleEditor, HTMLUIMessages.SyntaxColoringPage_0);
+		fStylesViewer = createStylesViewer(styleEditor);
+		GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
+		gridData.horizontalIndent = 0;
+		Iterator iterator = fStyleToDescriptionMap.values().iterator();
+		while (iterator.hasNext()) {
+			gridData.widthHint = Math.max(gridData.widthHint, convertWidthInCharsToPixels(iterator.next().toString().length()));
+		}
+		gridData.heightHint = convertHeightInCharsToPixels(5);
+		fStylesViewer.getControl().setLayoutData(gridData);
+
+		Composite editingComposite = createComposite(top, 1);
+		((GridLayout) styleEditor.getLayout()).marginLeft = 5;
+		createLabel(editingComposite, ""); //$NON-NLS-1$
+		Button enabler = createCheckbox(editingComposite, HTMLUIMessages.SyntaxColoringPage_2);
+		enabler.setEnabled(false);
+		enabler.setSelection(true);
+		Composite editControls = createComposite(editingComposite, 2);
+		((GridLayout) editControls.getLayout()).marginLeft = 20;
+
+		fForegroundLabel = createLabel(editControls, SSEUIMessages.Foreground_UI_);
+		((GridData) fForegroundLabel.getLayoutData()).verticalAlignment = SWT.CENTER;
+		fForegroundLabel.setEnabled(false);
+
+		fForegroundColorEditor = new ColorSelector(editControls);
+		Button fForegroundColor = fForegroundColorEditor.getButton();
+		GridData gd = new GridData(SWT.BEGINNING, SWT.FILL, false, false);
+		fForegroundColor.setLayoutData(gd);
+		fForegroundColorEditor.setEnabled(false);
+
+		fBackgroundLabel = createLabel(editControls, SSEUIMessages.Background_UI_);
+		((GridData) fBackgroundLabel.getLayoutData()).verticalAlignment = SWT.CENTER;
+		fBackgroundLabel.setEnabled(false);
+
+		fBackgroundColorEditor = new ColorSelector(editControls);
+		Button fBackgroundColor = fBackgroundColorEditor.getButton();
+		gd = new GridData(SWT.BEGINNING, SWT.FILL, false, false);
+		fBackgroundColor.setLayoutData(gd);
+		fBackgroundColorEditor.setEnabled(false);
+
+		fBold = createCheckbox(editControls, HTMLUIMessages.SyntaxColoringPage_3);
+		fBold.setEnabled(false);
+		((GridData) fBold.getLayoutData()).horizontalSpan = 2;
+		fItalic = createCheckbox(editControls, HTMLUIMessages.SyntaxColoringPage_4);
+		fItalic.setEnabled(false);
+		((GridData) fItalic.getLayoutData()).horizontalSpan = 2;
+		fStrike = createCheckbox(editControls, HTMLUIMessages.SyntaxColoringPage_5);
+		fStrike.setEnabled(false);
+		((GridData) fStrike.getLayoutData()).horizontalSpan = 2;
+		fUnderline = createCheckbox(editControls, HTMLUIMessages.SyntaxColoringPage_6);
+		fUnderline.setEnabled(false);
+		((GridData) fUnderline.getLayoutData()).horizontalSpan = 2;
+		fClearStyle = new Button(editingComposite, SWT.PUSH);
+		fClearStyle.setText(SSEUIMessages.Restore_Default_UI_); //$NON-NLS-1$ = "Restore Default"
+		fClearStyle.setLayoutData(new GridData(SWT.BEGINNING));
+		((GridData)fClearStyle.getLayoutData()).horizontalIndent = 20;
+		fClearStyle.setEnabled(false);
+
+		Composite sampleArea = createComposite(editor, 1);
+
+		((GridLayout) sampleArea.getLayout()).marginLeft = 5;
+		((GridLayout) sampleArea.getLayout()).marginTop = 5;
+		createLabel(sampleArea, SSEUIMessages.Sample_text__UI_); //$NON-NLS-1$ = "&Sample text:"
+		SourceViewer viewer = new SourceViewer(sampleArea, null, SWT.BORDER | SWT.LEFT_TO_RIGHT | SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL | SWT.READ_ONLY);
+		fText = viewer.getTextWidget();
+		GridData gridData3 = new GridData(SWT.FILL, SWT.FILL, true, true);
+		gridData3.widthHint = convertWidthInCharsToPixels(20);
+		gridData3.heightHint = convertHeightInCharsToPixels(5);
+		gridData3.horizontalSpan = 2;
+		fText.setLayoutData(gridData3);
+		fText.setEditable(false);
+		fText.setFont(JFaceResources.getFont("org.eclipse.wst.sse.ui.textfont")); //$NON-NLS-1$
+		fText.addKeyListener(getTextKeyListener());
+		fText.addSelectionListener(getTextSelectionListener());
+		fText.addMouseListener(getTextMouseListener());
+		fText.addTraverseListener(getTraverseListener());
+		setAccessible(fText, SSEUIMessages.Sample_text__UI_);
+		fDocument = StructuredModelManager.getModelManager().createStructuredDocumentFor(ContentTypeIdForHTML.ContentTypeID_HTML);
+		fDocument.set(getExampleText());
+		viewer.setDocument(fDocument);
+
+		top.setWeights(new int[]{1, 1});
+		editor.setWeights(new int[]{1, 1});
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(pageComponent, IHelpContextIds.HTML_PREFWEBX_STYLES_HELPID);
+
+		fStylesViewer.setInput(getStylePreferenceKeys());
+
+		applyStyles();
+
+		fStylesViewer.addSelectionChangedListener(new ISelectionChangedListener() {
+			public void selectionChanged(SelectionChangedEvent event) {
+				if (!event.getSelection().isEmpty()) {
+					Object o = ((IStructuredSelection) event.getSelection()).getFirstElement();
+					String namedStyle = o.toString();
+					activate(namedStyle);
+					if (namedStyle == null)
+						return;
+				}
+			}
+		});
+
+		fForegroundColorEditor.addListener(new IPropertyChangeListener() {
+			public void propertyChange(PropertyChangeEvent event) {
+				if (event.getProperty().equals(ColorSelector.PROP_COLORCHANGE)) {
+					Object o = ((IStructuredSelection) fStylesViewer.getSelection()).getFirstElement();
+					String namedStyle = o.toString();
+					String prefString = getOverlayStore().getString(namedStyle);
+					String[] stylePrefs = ColorHelper.unpackStylePreferences(prefString);
+					if (stylePrefs != null) {
+						String oldValue = stylePrefs[0];
+						// open color dialog to get new color
+						String newValue = ColorHelper.toRGBString(fForegroundColorEditor.getColorValue());
+
+						if (!newValue.equals(oldValue)) {
+							stylePrefs[0] = newValue;
+							String newPrefString = ColorHelper.packStylePreferences(stylePrefs);
+							getOverlayStore().setValue(namedStyle, newPrefString);
+							applyStyles();
+							fText.redraw();
+						}
+					}
+				}
+			}
+		});
+
+		fBackgroundColorEditor.addListener(new IPropertyChangeListener() {
+			public void propertyChange(PropertyChangeEvent event) {
+				if (event.getProperty().equals(ColorSelector.PROP_COLORCHANGE)) {
+					Object o = ((IStructuredSelection) fStylesViewer.getSelection()).getFirstElement();
+					String namedStyle = o.toString();
+					String prefString = getOverlayStore().getString(namedStyle);
+					String[] stylePrefs = ColorHelper.unpackStylePreferences(prefString);
+					if (stylePrefs != null) {
+						String oldValue = stylePrefs[1];
+						// open color dialog to get new color
+						String newValue = ColorHelper.toRGBString(fBackgroundColorEditor.getColorValue());
+
+						if (!newValue.equals(oldValue)) {
+							stylePrefs[1] = newValue;
+							String newPrefString = ColorHelper.packStylePreferences(stylePrefs);
+							getOverlayStore().setValue(namedStyle, newPrefString);
+							applyStyles();
+							fText.redraw();
+							activate(namedStyle);
+						}
+					}
+				}
+			}
+		});
+
+		fBold.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				super.widgetSelected(e);
+				// get current (newly old) style
+				Object o = ((IStructuredSelection) fStylesViewer.getSelection()).getFirstElement();
+				String namedStyle = o.toString();
+				String prefString = getOverlayStore().getString(namedStyle);
+				String[] stylePrefs = ColorHelper.unpackStylePreferences(prefString);
+				if (stylePrefs != null) {
+					String oldValue = stylePrefs[2];
+					String newValue = String.valueOf(fBold.getSelection());
+					if (!newValue.equals(oldValue)) {
+						stylePrefs[2] = newValue;
+						String newPrefString = ColorHelper.packStylePreferences(stylePrefs);
+						getOverlayStore().setValue(namedStyle, newPrefString);
+						applyStyles();
+						fText.redraw();
+					}
+				}
+			}
+		});
+
+		fItalic.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				super.widgetSelected(e);
+				// get current (newly old) style
+				Object o = ((IStructuredSelection) fStylesViewer.getSelection()).getFirstElement();
+				String namedStyle = o.toString();
+				String prefString = getOverlayStore().getString(namedStyle);
+				String[] stylePrefs = ColorHelper.unpackStylePreferences(prefString);
+				if (stylePrefs != null) {
+					String oldValue = stylePrefs[3];
+					String newValue = String.valueOf(fItalic.getSelection());
+					if (!newValue.equals(oldValue)) {
+						stylePrefs[3] = newValue;
+						String newPrefString = ColorHelper.packStylePreferences(stylePrefs);
+						getOverlayStore().setValue(namedStyle, newPrefString);
+						applyStyles();
+						fText.redraw();
+					}
+				}
+			}
+		});
+
+		fStrike.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				super.widgetSelected(e);
+				// get current (newly old) style
+				Object o = ((IStructuredSelection) fStylesViewer.getSelection()).getFirstElement();
+				String namedStyle = o.toString();
+				String prefString = getOverlayStore().getString(namedStyle);
+				String[] stylePrefs = ColorHelper.unpackStylePreferences(prefString);
+				if (stylePrefs != null) {
+					String oldValue = stylePrefs[4];
+					String newValue = String.valueOf(fStrike.getSelection());
+					if (!newValue.equals(oldValue)) {
+						stylePrefs[4] = newValue;
+						String newPrefString = ColorHelper.packStylePreferences(stylePrefs);
+						getOverlayStore().setValue(namedStyle, newPrefString);
+						applyStyles();
+						fText.redraw();
+					}
+				}
+			}
+		});
+
+		fUnderline.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				super.widgetSelected(e);
+				// get current (newly old) style
+				Object o = ((IStructuredSelection) fStylesViewer.getSelection()).getFirstElement();
+				String namedStyle = o.toString();
+				String prefString = getOverlayStore().getString(namedStyle);
+				String[] stylePrefs = ColorHelper.unpackStylePreferences(prefString);
+				if (stylePrefs != null) {
+					String oldValue = stylePrefs[5];
+					String newValue = String.valueOf(fUnderline.getSelection());
+					if (!newValue.equals(oldValue)) {
+						stylePrefs[5] = newValue;
+						String newPrefString = ColorHelper.packStylePreferences(stylePrefs);
+						getOverlayStore().setValue(namedStyle, newPrefString);
+						applyStyles();
+						fText.redraw();
+					}
+				}
+			}
+		});
+		
+		fClearStyle.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				if (fStylesViewer.getSelection().isEmpty())
+					return;
+				String namedStyle = ((IStructuredSelection) fStylesViewer.getSelection()).getFirstElement().toString();
+				getOverlayStore().setToDefault(namedStyle);
+				applyStyles();
+				fText.redraw();
+				activate(namedStyle);
+			}
+		});
+
+		return pageComponent;
+	}
+
+	private Label createLabel(Composite parent, String text) {
+		Label label = new Label(parent, SWT.WRAP);
+		label.setText(text);
+		GridData data = new GridData(SWT.FILL, SWT.FILL, false, false);
+		label.setLayoutData(data);
+		label.setBackground(parent.getBackground());
+		return label;
+	}
+
+	// protected Label createDescriptionLabel(Composite parent) {
+	// return null;
+	// }
+
+	/**
+	 * Set up all the style preference keys in the overlay store
+	 */
+	private OverlayKey[] createOverlayStoreKeys() {
+		List overlayKeys = new ArrayList();
+
+		Iterator i = getStylePreferenceKeys().iterator();
+		while (i.hasNext()) {
+			overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, (String) i.next()));
+		}
+
+		OverlayPreferenceStore.OverlayKey[] keys = new OverlayPreferenceStore.OverlayKey[overlayKeys.size()];
+		overlayKeys.toArray(keys);
+		return keys;
+	}
+
+	/**
+	 * Creates the List viewer where we see the various syntax element display
+	 * names--would it ever be a Tree like JDT's?
+	 * 
+	 * @param parent
+	 * @return
+	 */
+	private StructuredViewer createStylesViewer(Composite parent) {
+		StructuredViewer stylesViewer = new ListViewer(parent, SWT.SINGLE | SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER);
+		stylesViewer.setComparator(new ViewerComparator(Collator.getInstance()));
+		stylesViewer.setLabelProvider(new LabelProvider() {
+			public String getText(Object element) {
+				Object description = fStyleToDescriptionMap.get(element);
+				if (description != null)
+					return description.toString();
+				return super.getText(element);
+			}
+		});
+		stylesViewer.setContentProvider(new ITreeContentProvider() {
+			public void dispose() {
+			}
+
+			public Object[] getChildren(Object parentElement) {
+				return getStylePreferenceKeys().toArray();
+			}
+
+			public Object[] getElements(Object inputElement) {
+				return getChildren(inputElement);
+			}
+
+			public Object getParent(Object element) {
+				return getStylePreferenceKeys();
+			}
+
+			public boolean hasChildren(Object element) {
+				return false;
+			}
+
+			public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+			}
+		});
+		return stylesViewer;
+	}
+
+	public void dispose() {
+		if (fOverlayStore != null) {
+			fOverlayStore.stop();
+		}
+		super.dispose();
+	}
+
+	protected IPreferenceStore doGetPreferenceStore() {
+		return HTMLUIPlugin.getDefault().getPreferenceStore();
+	}
+
+	private TextAttribute getAttributeFor(String namedStyle) {
+		TextAttribute ta = new TextAttribute(fDefaultForeground, fDefaultBackground, SWT.NORMAL);
+
+		if (namedStyle != null && fOverlayStore != null) {
+			// note: "namedStyle" *is* the preference key
+			String prefString = getOverlayStore().getString(namedStyle);
+			String[] stylePrefs = ColorHelper.unpackStylePreferences(prefString);
+			if (stylePrefs != null) {
+				RGB foreground = ColorHelper.toRGB(stylePrefs[0]);
+				RGB background = ColorHelper.toRGB(stylePrefs[1]);
+
+				int fontModifier = SWT.NORMAL;
+
+				if (stylePrefs.length > 2) {
+					boolean on = Boolean.valueOf(stylePrefs[2]).booleanValue();
+					if (on)
+						fontModifier = fontModifier | SWT.BOLD;
+				}
+				if (stylePrefs.length > 3) {
+					boolean on = Boolean.valueOf(stylePrefs[3]).booleanValue();
+					if (on)
+						fontModifier = fontModifier | SWT.ITALIC;
+				}
+				if (stylePrefs.length > 4) {
+					boolean on = Boolean.valueOf(stylePrefs[4]).booleanValue();
+					if (on)
+						fontModifier = fontModifier | TextAttribute.STRIKETHROUGH;
+				}
+				if (stylePrefs.length > 5) {
+					boolean on = Boolean.valueOf(stylePrefs[5]).booleanValue();
+					if (on)
+						fontModifier = fontModifier | TextAttribute.UNDERLINE;
+				}
+
+				ta = new TextAttribute((foreground != null) ? EditorUtility.getColor(foreground) : null, (background != null) ? EditorUtility.getColor(background) : null, fontModifier);
+			}
+		}
+		return ta;
+	}
+
+	private String getExampleText() {
+		return HTMLUIMessages.Sample_HTML_doc;
+	}
+
+	private String getNamedStyleAtOffset(int offset) {
+		// ensure the offset is clean
+		if (offset >= fDocument.getLength())
+			return getNamedStyleAtOffset(fDocument.getLength() - 1);
+		else if (offset < 0)
+			return getNamedStyleAtOffset(0);
+		IStructuredDocumentRegion documentRegion = fDocument.getFirstStructuredDocumentRegion();
+		while (documentRegion != null && !documentRegion.containsOffset(offset)) {
+			documentRegion = documentRegion.getNext();
+		}
+		if (documentRegion != null) {
+			// find the ITextRegion's Context at this offset
+			ITextRegion interest = documentRegion.getRegionAtCharacterOffset(offset);
+			if (interest == null)
+				return null;
+			if (offset > documentRegion.getTextEndOffset(interest))
+				return null;
+			String regionContext = interest.getType();
+			if (regionContext == null)
+				return null;
+			// find the named style (internal/selectable name) for that
+			// context
+			String namedStyle = (String) fContextToStyleMap.get(regionContext);
+			if (namedStyle != null) {
+				return namedStyle;
+			}
+		}
+		return null;
+	}
+
+	private OverlayPreferenceStore getOverlayStore() {
+		return fOverlayStore;
+	}
+
+	private Collection getStylePreferenceKeys() {
+		if (fStylePreferenceKeys == null) {
+			List styles = new ArrayList();
+			styles.add(IStyleConstantsXML.ENTITY_REFERENCE);
+			styles.add(IStyleConstantsXML.TAG_BORDER);
+			styles.add(IStyleConstantsXML.TAG_NAME);
+			styles.add(IStyleConstantsXML.TAG_ATTRIBUTE_NAME);
+			styles.add(IStyleConstantsXML.TAG_ATTRIBUTE_EQUALS);
+			styles.add(IStyleConstantsXML.TAG_ATTRIBUTE_VALUE);
+			styles.add(IStyleConstantsXML.COMMENT_BORDER);
+			styles.add(IStyleConstantsXML.COMMENT_TEXT);
+			styles.add(IStyleConstantsXML.DECL_BORDER);
+			styles.add(IStyleConstantsXML.XML_CONTENT);
+			styles.add(IStyleConstantsXML.DOCTYPE_NAME);
+			styles.add(IStyleConstantsXML.DOCTYPE_EXTERNAL_ID);
+			styles.add(IStyleConstantsXML.DOCTYPE_EXTERNAL_ID_PUBREF);
+			styles.add(IStyleConstantsXML.DOCTYPE_EXTERNAL_ID_SYSREF);
+//			styles.add(IStyleConstantsXML.CDATA_BORDER);
+//			styles.add(IStyleConstantsXML.CDATA_TEXT);
+//			styles.add(IStyleConstantsXML.PI_BORDER);
+//			styles.add(IStyleConstantsXML.PI_CONTENT);
+			fStylePreferenceKeys = styles;
+		}
+		return fStylePreferenceKeys;
+	}
+
+	private KeyListener getTextKeyListener() {
+		return new KeyListener() {
+			public void keyPressed(KeyEvent e) {
+				if (e.widget instanceof StyledText) {
+					int x = ((StyledText) e.widget).getCaretOffset();
+					selectColorAtOffset(x);
+				}
+			}
+
+			public void keyReleased(KeyEvent e) {
+				if (e.widget instanceof StyledText) {
+					int x = ((StyledText) e.widget).getCaretOffset();
+					selectColorAtOffset(x);
+				}
+			}
+		};
+	}
+
+	private MouseListener getTextMouseListener() {
+		return new MouseListener() {
+			public void mouseDoubleClick(MouseEvent e) {
+			}
+
+			public void mouseDown(MouseEvent e) {
+			}
+
+			public void mouseUp(MouseEvent e) {
+				if (e.widget instanceof StyledText) {
+					int x = ((StyledText) e.widget).getCaretOffset();
+					selectColorAtOffset(x);
+				}
+			}
+		};
+	}
+
+	private SelectionListener getTextSelectionListener() {
+		return new SelectionListener() {
+			public void widgetDefaultSelected(SelectionEvent e) {
+				selectColorAtOffset(e.x);
+				if (e.widget instanceof StyledText) {
+					((StyledText) e.widget).setSelection(e.x);
+				}
+			}
+
+			public void widgetSelected(SelectionEvent e) {
+				selectColorAtOffset(e.x);
+				if (e.widget instanceof StyledText) {
+					((StyledText) e.widget).setSelection(e.x);
+				}
+			}
+		};
+	}
+
+	private TraverseListener getTraverseListener() {
+		return new TraverseListener() {
+			/**
+			 * @see org.eclipse.swt.events.TraverseListener#keyTraversed(TraverseEvent)
+			 */
+			public void keyTraversed(TraverseEvent e) {
+				if (e.widget instanceof StyledText) {
+					if ((e.detail == SWT.TRAVERSE_TAB_NEXT) || (e.detail == SWT.TRAVERSE_TAB_PREVIOUS))
+						e.doit = true;
+				}
+			}
+		};
+	}
+
+	public void init(IWorkbench workbench) {
+		setDescription(SSEUIMessages.SyntaxColoring_Description);
+
+		fStyleToDescriptionMap = new HashMap();
+		fContextToStyleMap = new HashMap();
+
+		initStyleToDescriptionMap();
+		initRegionContextToStyleMap();
+
+		fOverlayStore = new OverlayPreferenceStore(getPreferenceStore(), createOverlayStoreKeys());
+		fOverlayStore.load();
+		fOverlayStore.start();
+	}
+
+	private void initRegionContextToStyleMap() {
+		fContextToStyleMap.put(DOMRegionContext.XML_COMMENT_OPEN, IStyleConstantsXML.COMMENT_BORDER);
+		fContextToStyleMap.put(DOMRegionContext.XML_COMMENT_TEXT, IStyleConstantsXML.COMMENT_TEXT);
+		fContextToStyleMap.put(DOMRegionContext.XML_COMMENT_CLOSE, IStyleConstantsXML.COMMENT_BORDER);
+
+		fContextToStyleMap.put(DOMRegionContext.XML_TAG_OPEN, IStyleConstantsXML.TAG_BORDER);
+		fContextToStyleMap.put(DOMRegionContext.XML_END_TAG_OPEN, IStyleConstantsXML.TAG_BORDER);
+		fContextToStyleMap.put(DOMRegionContext.XML_TAG_NAME, IStyleConstantsXML.TAG_NAME);
+		fContextToStyleMap.put(DOMRegionContext.XML_TAG_ATTRIBUTE_NAME, IStyleConstantsXML.TAG_ATTRIBUTE_NAME);
+		fContextToStyleMap.put(DOMRegionContext.XML_TAG_ATTRIBUTE_EQUALS, IStyleConstantsXML.TAG_ATTRIBUTE_EQUALS);
+		fContextToStyleMap.put(DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE, IStyleConstantsXML.TAG_ATTRIBUTE_VALUE);
+		fContextToStyleMap.put(DOMRegionContext.XML_TAG_CLOSE, IStyleConstantsXML.TAG_BORDER);
+		fContextToStyleMap.put(DOMRegionContext.XML_EMPTY_TAG_CLOSE, IStyleConstantsXML.TAG_BORDER);
+
+		fContextToStyleMap.put(DOMRegionContext.XML_DECLARATION_OPEN, IStyleConstantsXML.DECL_BORDER);
+		fContextToStyleMap.put(DOMRegionContext.XML_DECLARATION_CLOSE, IStyleConstantsXML.DECL_BORDER);
+		fContextToStyleMap.put(DOMRegionContext.XML_ELEMENT_DECLARATION, IStyleConstantsXML.DECL_BORDER);
+		fContextToStyleMap.put(DOMRegionContext.XML_ELEMENT_DECL_CLOSE, IStyleConstantsXML.DECL_BORDER);
+
+		fContextToStyleMap.put(DOMRegionContext.XML_CHAR_REFERENCE, IStyleConstantsXML.ENTITY_REFERENCE);
+		fContextToStyleMap.put(DOMRegionContext.XML_ENTITY_REFERENCE, IStyleConstantsXML.ENTITY_REFERENCE);
+		fContextToStyleMap.put(DOMRegionContext.XML_PE_REFERENCE, IStyleConstantsXML.ENTITY_REFERENCE);
+
+		fContextToStyleMap.put(DOMRegionContext.XML_CONTENT, IStyleConstantsXML.XML_CONTENT);
+
+		fContextToStyleMap.put(DOMRegionContext.XML_ELEMENT_DECL_NAME, IStyleConstantsXML.DOCTYPE_NAME);
+		fContextToStyleMap.put(DOMRegionContext.XML_DOCTYPE_DECLARATION, IStyleConstantsXML.TAG_NAME);
+		fContextToStyleMap.put(DOMRegionContext.XML_DOCTYPE_DECLARATION_CLOSE, IStyleConstantsXML.DECL_BORDER);
+
+		fContextToStyleMap.put(DOMRegionContext.XML_DOCTYPE_NAME, IStyleConstantsXML.DOCTYPE_NAME);
+		fContextToStyleMap.put(DOMRegionContext.XML_DOCTYPE_EXTERNAL_ID_PUBLIC, IStyleConstantsXML.DOCTYPE_EXTERNAL_ID);
+		fContextToStyleMap.put(DOMRegionContext.XML_DOCTYPE_EXTERNAL_ID_PUBREF, IStyleConstantsXML.DOCTYPE_EXTERNAL_ID_PUBREF);
+		fContextToStyleMap.put(DOMRegionContext.XML_DOCTYPE_EXTERNAL_ID_SYSTEM, IStyleConstantsXML.DOCTYPE_EXTERNAL_ID);
+		fContextToStyleMap.put(DOMRegionContext.XML_DOCTYPE_EXTERNAL_ID_SYSREF, IStyleConstantsXML.DOCTYPE_EXTERNAL_ID_SYSREF);
+
+//		fContextToStyleMap.put(DOMRegionContext.XML_PI_OPEN, IStyleConstantsXML.PI_BORDER);
+//		fContextToStyleMap.put(DOMRegionContext.XML_PI_CONTENT, IStyleConstantsXML.PI_CONTENT);
+//		fContextToStyleMap.put(DOMRegionContext.XML_CDATA_OPEN, IStyleConstantsXML.CDATA_BORDER);
+//		fContextToStyleMap.put(DOMRegionContext.XML_CDATA_TEXT, IStyleConstantsXML.CDATA_TEXT);
+//		fContextToStyleMap.put(DOMRegionContext.XML_CDATA_CLOSE, IStyleConstantsXML.CDATA_BORDER);
+	}
+
+	private void initStyleToDescriptionMap() {
+		fStyleToDescriptionMap.put(IStyleConstantsXML.COMMENT_BORDER, XMLUIMessages.Comment_Delimiters_UI_); // =
+		fStyleToDescriptionMap.put(IStyleConstantsXML.COMMENT_TEXT, XMLUIMessages.Comment_Content_UI_); // =
+		fStyleToDescriptionMap.put(IStyleConstantsXML.TAG_BORDER, XMLUIMessages.Tag_Delimiters_UI_); // =
+		fStyleToDescriptionMap.put(IStyleConstantsXML.TAG_NAME, XMLUIMessages.Tag_Names_UI_); // =
+		fStyleToDescriptionMap.put(IStyleConstantsXML.TAG_ATTRIBUTE_NAME, XMLUIMessages.Attribute_Names_UI_); // =
+		fStyleToDescriptionMap.put(IStyleConstantsXML.TAG_ATTRIBUTE_EQUALS, XMLUIMessages.Attribute_Equals_UI_);
+		fStyleToDescriptionMap.put(IStyleConstantsXML.TAG_ATTRIBUTE_VALUE, XMLUIMessages.Attribute_Values_UI_); // =
+		fStyleToDescriptionMap.put(IStyleConstantsXML.DECL_BORDER, XMLUIMessages.Declaration_Delimiters_UI_); // =
+		fStyleToDescriptionMap.put(IStyleConstantsXML.XML_CONTENT, XMLUIMessages.Content_UI_); // =
+		fStyleToDescriptionMap.put(IStyleConstantsXML.ENTITY_REFERENCE, XMLUIMessages.Entity_Reference_UI_); //$NON-NLS-1$ = "Entity References"
+		fStyleToDescriptionMap.put(IStyleConstantsXML.DOCTYPE_NAME, XMLUIMessages.DOCTYPE_Name_UI_); // =
+		fStyleToDescriptionMap.put(IStyleConstantsXML.DOCTYPE_EXTERNAL_ID, XMLUIMessages.DOCTYPE_SYSTEM_PUBLIC_Keyw_UI_); // =
+		fStyleToDescriptionMap.put(IStyleConstantsXML.DOCTYPE_EXTERNAL_ID_PUBREF, XMLUIMessages.DOCTYPE_Public_Reference_UI_); // =
+		fStyleToDescriptionMap.put(IStyleConstantsXML.DOCTYPE_EXTERNAL_ID_SYSREF, XMLUIMessages.DOCTYPE_System_Reference_UI_); // =
+//		fStyleToDescriptionMap.put(IStyleConstantsXML.PI_BORDER, XMLUIMessages.Processing_Instruction_Del_UI_);
+//		fStyleToDescriptionMap.put(IStyleConstantsXML.PI_CONTENT, XMLUIMessages.Processing_Instruction_Con_UI__UI_);
+//		fStyleToDescriptionMap.put(IStyleConstantsXML.CDATA_BORDER, XMLUIMessages.CDATA_Delimiters_UI_);
+//		fStyleToDescriptionMap.put(IStyleConstantsXML.CDATA_TEXT, XMLUIMessages.CDATA_Content_UI_);
+}
+
+	protected void performDefaults() {
+		super.performDefaults();
+		getOverlayStore().loadDefaults();
+		applyStyles();
+		fStylesViewer.setSelection(StructuredSelection.EMPTY);
+		activate(null);
+		fText.redraw();
+	}
+
+	public boolean performOk() {
+		getOverlayStore().propagate();
+
+		HTMLUIPlugin.getDefault().savePluginPreferences();
+		SSEUIPlugin.getDefault().savePluginPreferences();
+		return true;
+	}
+
+	private void selectColorAtOffset(int offset) {
+		String namedStyle = getNamedStyleAtOffset(offset);
+		if (namedStyle != null) {
+			fStylesViewer.setSelection(new StructuredSelection(namedStyle));
+			fStylesViewer.reveal(namedStyle);
+		}
+		else {
+			fStylesViewer.setSelection(StructuredSelection.EMPTY);
+		}
+		activate(namedStyle);
+	}
+
+	/**
+	 * Specifically set the reporting name of a control for accessibility
+	 */
+	private void setAccessible(Control control, String name) {
+		if (control == null)
+			return;
+		final String n = name;
+		control.getAccessible().addAccessibleListener(new AccessibleAdapter() {
+			public void getName(AccessibleEvent e) {
+				if (e.childID == ACC.CHILDID_SELF)
+					e.result = n;
+			}
+		});
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/preferences/ui/HTMLTemplatePreferencePage.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/preferences/ui/HTMLTemplatePreferencePage.java
new file mode 100644
index 0000000..0700d82
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/preferences/ui/HTMLTemplatePreferencePage.java
@@ -0,0 +1,157 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.preferences.ui;
+
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.contentassist.ContentAssistant;
+import org.eclipse.jface.text.contentassist.IContentAssistant;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.text.source.SourceViewer;
+import org.eclipse.jface.text.source.SourceViewerConfiguration;
+import org.eclipse.jface.text.templates.ContextTypeRegistry;
+import org.eclipse.jface.text.templates.Template;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.texteditor.templates.TemplatePreferencePage;
+import org.eclipse.wst.html.core.internal.provisional.contenttype.ContentTypeIdForHTML;
+import org.eclipse.wst.html.ui.StructuredTextViewerConfigurationHTML;
+import org.eclipse.wst.html.ui.internal.HTMLUIPlugin;
+import org.eclipse.wst.html.ui.internal.editor.IHelpContextIds;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.ui.StructuredTextViewerConfiguration;
+import org.eclipse.wst.sse.ui.internal.StructuredTextViewer;
+import org.eclipse.wst.sse.ui.internal.provisional.style.LineStyleProvider;
+
+
+/**
+ * Preference page for HTML templates
+ */
+public class HTMLTemplatePreferencePage extends TemplatePreferencePage {
+		class HTMLEditTemplateDialog extends EditTemplateDialog {
+		public HTMLEditTemplateDialog(Shell parent, Template template, boolean edit, boolean isNameModifiable, ContextTypeRegistry registry) {
+			super(parent, template, edit, isNameModifiable, registry);
+		}
+
+		protected SourceViewer createViewer(Composite parent) {
+			SourceViewerConfiguration sourceViewerConfiguration = new StructuredTextViewerConfiguration() {
+				StructuredTextViewerConfiguration baseConfiguration = new StructuredTextViewerConfigurationHTML();
+
+				public String[] getConfiguredContentTypes(ISourceViewer sourceViewer) {
+					return baseConfiguration.getConfiguredContentTypes(sourceViewer);
+				}
+
+				public LineStyleProvider[] getLineStyleProviders(ISourceViewer sourceViewer, String partitionType) {
+					return baseConfiguration.getLineStyleProviders(sourceViewer, partitionType);
+				}
+
+				public IContentAssistant getContentAssistant(ISourceViewer sourceViewer) {
+					ContentAssistant assistant = new ContentAssistant();
+					assistant.enableAutoActivation(true);
+					assistant.enableAutoInsert(true);
+					assistant.setContentAssistProcessor(getTemplateProcessor(), IDocument.DEFAULT_CONTENT_TYPE);
+					return assistant;
+				}
+			};
+			return doCreateViewer(parent, sourceViewerConfiguration);
+		}
+	}
+
+	public HTMLTemplatePreferencePage() {
+		HTMLUIPlugin htmlEditorPlugin = HTMLUIPlugin.getDefault();
+		
+		setPreferenceStore(htmlEditorPlugin.getPreferenceStore());
+		setTemplateStore(htmlEditorPlugin.getTemplateStore());
+		setContextTypeRegistry(htmlEditorPlugin.getTemplateContextRegistry());
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.preference.IPreferencePage#performOk()
+	 */
+	public boolean performOk() {
+  	  boolean ok = super.performOk();
+  	  HTMLUIPlugin.getDefault().savePluginPreferences();
+	  return ok;
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.ui.texteditor.templates.TemplatePreferencePage#isShowFormatterSetting()
+	 */
+	protected boolean isShowFormatterSetting() {
+		// template formatting has not been implemented
+		return false;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.preference.PreferencePage#createContents(org.eclipse.swt.widgets.Composite)
+	 */
+	protected Control createContents(Composite ancestor) {
+		Control c = super.createContents(ancestor);
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(c, IHelpContextIds.HTML_PREFWEBX_TEMPLATES_HELPID);
+		return c;
+	}
+	/*
+	 * (non-Javadoc)
+	 * @see org.eclipse.ui.texteditor.templates.TemplatePreferencePage#createViewer(org.eclipse.swt.widgets.Composite)
+	 */
+	protected SourceViewer createViewer(Composite parent) {
+		SourceViewerConfiguration sourceViewerConfiguration = new StructuredTextViewerConfiguration() {
+			StructuredTextViewerConfiguration baseConfiguration = new StructuredTextViewerConfigurationHTML();
+
+			public String[] getConfiguredContentTypes(ISourceViewer sourceViewer) {
+				return baseConfiguration.getConfiguredContentTypes(sourceViewer);
+			}
+
+			public LineStyleProvider[] getLineStyleProviders(ISourceViewer sourceViewer, String partitionType) {
+				return baseConfiguration.getLineStyleProviders(sourceViewer, partitionType);
+			}
+		};
+		return doCreateViewer(parent, sourceViewerConfiguration);
+	}
+
+	SourceViewer doCreateViewer(Composite parent, SourceViewerConfiguration viewerConfiguration) {
+		SourceViewer viewer = null;
+		String contentTypeID = ContentTypeIdForHTML.ContentTypeID_HTML;
+		viewer = new StructuredTextViewer(parent, null, null, false, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
+		viewer.getTextWidget().setFont(JFaceResources.getFont("org.eclipse.wst.sse.ui.textfont")); //$NON-NLS-1$
+		IStructuredModel scratchModel = StructuredModelManager.getModelManager().createUnManagedStructuredModelFor(contentTypeID);
+		IDocument document = scratchModel.getStructuredDocument();
+		viewer.configure(viewerConfiguration);
+		viewer.setDocument(document);
+		return viewer;
+	}
+
+	/**
+	 * Creates the edit dialog. Subclasses may override this method to provide
+	 * a custom dialog.
+	 * 
+	 * @param template
+	 *            the template being edited
+	 * @param edit
+	 *            whether the dialog should be editable
+	 * @param isNameModifiable
+	 *            whether the template name may be modified
+	 * @return the created or modified template, or <code>null</code> if the
+	 *         edition failed
+	 * @since 3.1
+	 */
+	protected Template editTemplate(Template template, boolean edit, boolean isNameModifiable) {
+		EditTemplateDialog dialog = new HTMLEditTemplateDialog(getShell(), template, edit, isNameModifiable, getContextTypeRegistry());
+		if (dialog.open() == Window.OK) {
+			return dialog.getTemplate();
+		}
+		return null;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/preferences/ui/HTMLTypingPreferencePage.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/preferences/ui/HTMLTypingPreferencePage.java
new file mode 100644
index 0000000..8942dfe
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/preferences/ui/HTMLTypingPreferencePage.java
@@ -0,0 +1,130 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.preferences.ui;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.wst.html.ui.internal.HTMLUIMessages;
+import org.eclipse.wst.html.ui.internal.HTMLUIPlugin;
+import org.eclipse.wst.html.ui.internal.preferences.HTMLUIPreferenceNames;
+import org.eclipse.wst.sse.ui.internal.preferences.ui.AbstractPreferencePage;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+
+public class HTMLTypingPreferencePage extends AbstractPreferencePage {
+
+	private Button fCloseComment;
+	private Button fCloseEndTag;
+	private Button fRemoveEndTag;
+	private Button fCloseElement;
+	private Button fCloseStrings;
+	private Button fCloseBrackets;
+	
+	protected Control createContents(Composite parent) {
+		Composite composite = super.createComposite(parent, 1);
+		
+		createStartTagGroup(composite);
+		createEndTagGroup(composite);
+		createAutoComplete(composite);
+		createAutoRemove(composite);
+		
+		setSize(composite);
+		loadPreferences();
+		
+		return composite;
+	}
+	
+	private void createStartTagGroup(Composite parent) {
+		Group group = createGroup(parent, 2);
+
+		group.setText(XMLUIMessages.XMLTyping_Start_Tag);
+
+		fCloseElement = createCheckBox(group, XMLUIMessages.XMLTyping_Complete_Elements);
+		((GridData) fCloseElement.getLayoutData()).horizontalSpan = 2;
+	}
+	
+	private void createEndTagGroup(Composite parent) {
+		Group group = createGroup(parent, 2);
+
+		group.setText(XMLUIMessages.XMLTyping_End_Tag);
+
+		fCloseEndTag = createCheckBox(group, XMLUIMessages.XMLTyping_Complete_End_Tags);
+		((GridData) fCloseEndTag.getLayoutData()).horizontalSpan = 2;
+	}
+	
+	private void createAutoComplete(Composite parent) {
+		Group group = createGroup(parent, 2);
+
+		group.setText(HTMLUIMessages.HTMLTyping_Auto_Complete);
+
+		fCloseComment = createCheckBox(group, HTMLUIMessages.HTMLTyping_Complete_Comments);
+		((GridData) fCloseComment.getLayoutData()).horizontalSpan = 2;
+
+		fCloseStrings = createCheckBox(group, HTMLUIMessages.HTMLTyping_Close_Strings);
+		((GridData) fCloseStrings.getLayoutData()).horizontalSpan = 2;
+
+		fCloseBrackets = createCheckBox(group, HTMLUIMessages.HTMLTyping_Close_Brackets);
+		((GridData) fCloseBrackets.getLayoutData()).horizontalSpan = 2;
+	}
+	
+	private void createAutoRemove(Composite parent) {
+		Group group = createGroup(parent, 2);
+		
+		group.setText(HTMLUIMessages.HTMLTyping_Auto_Remove);
+		
+		fRemoveEndTag = createCheckBox(group, HTMLUIMessages.HTMLTyping_Remove_End_Tags);
+		((GridData) fRemoveEndTag.getLayoutData()).horizontalSpan = 2;
+	}
+	
+	public boolean performOk() {
+		boolean result = super.performOk();
+		
+		HTMLUIPlugin.getDefault().savePluginPreferences();
+		
+		return result;
+	}
+	
+	protected void initializeValues() {
+		initCheckbox(fCloseComment, HTMLUIPreferenceNames.TYPING_COMPLETE_COMMENTS);
+		initCheckbox(fCloseEndTag, HTMLUIPreferenceNames.TYPING_COMPLETE_END_TAGS);
+		initCheckbox(fCloseElement, HTMLUIPreferenceNames.TYPING_COMPLETE_ELEMENTS);
+		initCheckbox(fRemoveEndTag, HTMLUIPreferenceNames.TYPING_REMOVE_END_TAGS);
+		initCheckbox(fCloseStrings, HTMLUIPreferenceNames.TYPING_CLOSE_STRINGS);
+		initCheckbox(fCloseBrackets, HTMLUIPreferenceNames.TYPING_CLOSE_BRACKETS);
+	}
+	
+	protected void performDefaults() {
+		defaultCheckbox(fCloseComment, HTMLUIPreferenceNames.TYPING_COMPLETE_COMMENTS);
+		defaultCheckbox(fCloseEndTag, HTMLUIPreferenceNames.TYPING_COMPLETE_END_TAGS);
+		defaultCheckbox(fCloseElement, HTMLUIPreferenceNames.TYPING_COMPLETE_ELEMENTS);
+		defaultCheckbox(fRemoveEndTag, HTMLUIPreferenceNames.TYPING_REMOVE_END_TAGS);
+		defaultCheckbox(fCloseStrings, HTMLUIPreferenceNames.TYPING_CLOSE_STRINGS);
+		defaultCheckbox(fCloseBrackets, HTMLUIPreferenceNames.TYPING_CLOSE_BRACKETS);
+	}
+	
+	protected void storeValues() {
+		getPreferenceStore().setValue(HTMLUIPreferenceNames.TYPING_COMPLETE_COMMENTS, (fCloseComment != null) ? fCloseComment.getSelection() : false);
+		getPreferenceStore().setValue(HTMLUIPreferenceNames.TYPING_COMPLETE_END_TAGS, (fCloseEndTag != null) ? fCloseEndTag.getSelection() : false);
+		getPreferenceStore().setValue(HTMLUIPreferenceNames.TYPING_COMPLETE_ELEMENTS, (fCloseElement != null) ? fCloseElement.getSelection() : false);
+		getPreferenceStore().setValue(HTMLUIPreferenceNames.TYPING_REMOVE_END_TAGS, (fRemoveEndTag != null) ? fRemoveEndTag.getSelection() : false);
+		getPreferenceStore().setValue(HTMLUIPreferenceNames.TYPING_CLOSE_STRINGS, (fCloseStrings != null) ? fCloseStrings.getSelection() : false);
+		getPreferenceStore().setValue(HTMLUIPreferenceNames.TYPING_CLOSE_BRACKETS, (fCloseBrackets != null) ? fCloseBrackets.getSelection() : false);
+	}
+	
+	protected IPreferenceStore doGetPreferenceStore() {
+		return HTMLUIPlugin.getDefault().getPreferenceStore();
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/preferences/ui/HTMLValidationPreferencePage.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/preferences/ui/HTMLValidationPreferencePage.java
new file mode 100644
index 0000000..1a1f612
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/preferences/ui/HTMLValidationPreferencePage.java
@@ -0,0 +1,326 @@
+/*******************************************************************************
+ * Copyright (c) 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.preferences.ui;
+
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.layout.PixelConverter;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.forms.widgets.ExpandableComposite;
+import org.eclipse.wst.html.core.internal.HTMLCorePlugin;
+import org.eclipse.wst.html.core.internal.preferences.HTMLCorePreferenceNames;
+import org.eclipse.wst.html.ui.internal.HTMLUIMessages;
+import org.eclipse.wst.html.ui.internal.HTMLUIPlugin;
+import org.eclipse.wst.sse.core.internal.validate.ValidationMessage;
+import org.eclipse.wst.sse.ui.internal.preferences.ui.ScrolledPageContent;
+
+public class HTMLValidationPreferencePage extends AbstractValidationSettingsPage {
+	
+	private static final int[] SEVERITIES = {ValidationMessage.ERROR, ValidationMessage.WARNING, ValidationMessage.IGNORE};
+	
+	private static final String SETTINGS_SECTION_NAME = "HTMLValidationSeverities";//$NON-NLS-1$
+	
+	public HTMLValidationPreferencePage() {
+		super();
+	}
+	
+	private PixelConverter fPixelConverter;
+	
+	protected Control createCommonContents(Composite parent) {
+		final Composite page = new Composite(parent, SWT.NULL);
+		
+		//GridLayout
+		GridLayout layout = new GridLayout();
+		layout.numColumns = 1;
+		page.setLayout(layout);
+		
+		fPixelConverter = new PixelConverter(parent);
+		
+		final Composite content = createValidationSection(page);
+
+		GridData gridData= new GridData(GridData.FILL, GridData.FILL, true, true);
+		gridData.heightHint = fPixelConverter.convertHeightInCharsToPixels(20);
+		content.setLayoutData(gridData);
+		
+		return page;
+	}
+	
+	private Composite createValidationSection(Composite page) {
+		int nColumns = 3;
+		
+		final ScrolledPageContent spContent = new ScrolledPageContent(page);
+		
+		Composite composite = spContent.getBody();
+		
+		GridLayout layout= new GridLayout(nColumns, false);
+		layout.marginHeight= 0;
+		layout.marginWidth= 0;
+		composite.setLayout(layout);
+		
+		Label description = new Label(composite, SWT.NONE);
+		description.setText(HTMLUIMessages.Validation_description);
+		description.setFont(page.getFont());
+
+		
+		ExpandableComposite ec;
+		Composite inner;
+		String label;
+		
+		String[] errorWarningIgnoreLabel = new String[] { HTMLUIMessages.Validation_Error, HTMLUIMessages.Validation_Warning, HTMLUIMessages.Validation_Ignore };
+		
+		// Element section
+		
+		ec = createStyleSection(composite, HTMLUIMessages.Expandable_label_elements, nColumns);
+		
+		inner = new Composite(ec, SWT.NONE);
+		inner.setFont(composite.getFont());
+		inner.setLayout(new GridLayout(nColumns, false));
+		ec.setClient(inner);
+		
+		label = HTMLUIMessages.HTMLValidationPreferencePage_8;
+		addComboBox(inner, label, HTMLCorePreferenceNames.ELEM_UNKNOWN_NAME, SEVERITIES, errorWarningIgnoreLabel, 0);
+		
+		label = HTMLUIMessages.HTMLValidationPreferencePage_9;
+		addComboBox(inner, label, HTMLCorePreferenceNames.ELEM_INVALID_NAME, SEVERITIES, errorWarningIgnoreLabel, 0);
+		
+		label = HTMLUIMessages.HTMLValidationPreferencePage_10;
+		addComboBox(inner, label, HTMLCorePreferenceNames.ELEM_START_INVALID_CASE, SEVERITIES, errorWarningIgnoreLabel, 0);
+		
+		label = HTMLUIMessages.HTMLValidationPreferencePage_11;
+		addComboBox(inner, label, HTMLCorePreferenceNames.ELEM_END_INVALID_CASE, SEVERITIES, errorWarningIgnoreLabel, 0);
+		
+		label = HTMLUIMessages.HTMLValidationPreferencePage_12;
+		addComboBox(inner, label, HTMLCorePreferenceNames.ELEM_MISSING_START, SEVERITIES, errorWarningIgnoreLabel, 0);
+		
+		label = HTMLUIMessages.HTMLValidationPreferencePage_13;
+		addComboBox(inner, label, HTMLCorePreferenceNames.ELEM_MISSING_END, SEVERITIES, errorWarningIgnoreLabel, 0);
+		
+		label = HTMLUIMessages.HTMLValidationPreferencePage_14;
+		addComboBox(inner, label, HTMLCorePreferenceNames.ELEM_UNNECESSARY_END, SEVERITIES, errorWarningIgnoreLabel, 0);
+		
+		label = HTMLUIMessages.HTMLValidationPreferencePage_15;
+		addComboBox(inner, label, HTMLCorePreferenceNames.ELEM_INVALID_DIRECTIVE, SEVERITIES, errorWarningIgnoreLabel, 0);
+		
+		label = HTMLUIMessages.HTMLValidationPreferencePage_16;
+		addComboBox(inner, label, HTMLCorePreferenceNames.ELEM_INVALID_CONTENT, SEVERITIES, errorWarningIgnoreLabel, 0);
+		
+		label = HTMLUIMessages.HTMLValidationPreferencePage_17;
+		addComboBox(inner, label, HTMLCorePreferenceNames.ELEM_DUPLICATE, SEVERITIES, errorWarningIgnoreLabel, 0);
+		
+		label = HTMLUIMessages.HTMLValidationPreferencePage_18;
+		addComboBox(inner, label, HTMLCorePreferenceNames.ELEM_COEXISTENCE, SEVERITIES, errorWarningIgnoreLabel, 0);
+		
+		label = HTMLUIMessages.HTMLValidationPreferencePage_19;
+		addComboBox(inner, label, HTMLCorePreferenceNames.ELEM_UNCLOSED_START_TAG, SEVERITIES, errorWarningIgnoreLabel, 0);
+		
+		label = HTMLUIMessages.HTMLValidationPreferencePage_20;
+		addComboBox(inner, label, HTMLCorePreferenceNames.ELEM_UNCLOSED_END_TAG, SEVERITIES, errorWarningIgnoreLabel, 0);
+		
+		label = HTMLUIMessages.HTMLValidationPreferencePage_21;
+		addComboBox(inner, label, HTMLCorePreferenceNames.ELEM_INVALID_EMPTY_TAG, SEVERITIES, errorWarningIgnoreLabel, 0);
+		// End Element Section
+		
+		// The Attribute validation section
+		
+		ec = createStyleSection(composite, HTMLUIMessages.Expandable_label_attributes, nColumns);
+		inner = new Composite(ec, SWT.NONE);
+		inner.setFont(composite.getFont());
+		inner.setLayout(new GridLayout(nColumns, false));
+		ec.setClient(inner);
+		
+		label = HTMLUIMessages.HTMLValidationPreferencePage_0;
+		addComboBox(inner, label, HTMLCorePreferenceNames.ATTRIBUTE_UNDEFINED_NAME, SEVERITIES, errorWarningIgnoreLabel, 0);
+		
+		label = HTMLUIMessages.HTMLValidationPreferencePage_1;
+		addComboBox(inner, label, HTMLCorePreferenceNames.ATTRIBUTE_UNDEFINED_VALUE, SEVERITIES, errorWarningIgnoreLabel, 0);
+		
+		label = HTMLUIMessages.HTMLValidationPreferencePage_2;
+		addComboBox(inner, label, HTMLCorePreferenceNames.ATTRIBUTE_NAME_MISMATCH, SEVERITIES, errorWarningIgnoreLabel, 0);
+		
+		label = HTMLUIMessages.HTMLValidationPreferencePage_3;
+		addComboBox(inner, label, HTMLCorePreferenceNames.ATTRIBUTE_INVALID_NAME, SEVERITIES, errorWarningIgnoreLabel, 0);
+		
+		label = HTMLUIMessages.HTMLValidationPreferencePage_4;
+		addComboBox(inner, label, HTMLCorePreferenceNames.ATTRIBUTE_INVALID_VALUE, SEVERITIES, errorWarningIgnoreLabel, 0);
+		
+		label = HTMLUIMessages.HTMLValidationPreferencePage_5;
+		addComboBox(inner, label, HTMLCorePreferenceNames.ATTRIBUTE_DUPLICATE, SEVERITIES, errorWarningIgnoreLabel, 0);
+		
+		label = HTMLUIMessages.HTMLValidationPreferencePage_6;
+		addComboBox(inner, label, HTMLCorePreferenceNames.ATTRIBUTE_VALUE_MISMATCH, SEVERITIES, errorWarningIgnoreLabel, 0);
+		
+		label = HTMLUIMessages.HTMLValidationPreferencePage_7;
+		addComboBox(inner, label, HTMLCorePreferenceNames.ATTRIBUTE_VALUE_UNCLOSED, SEVERITIES, errorWarningIgnoreLabel, 0);
+		
+		label = HTMLUIMessages.HTMLValidationPreferencePage_35;
+		// TODO: validate resources?
+		// addComboBox(inner, label, HTMLCorePreferenceNames.ATTRIBUTE_VALUE_RESOURCE_NOT_FOUND, SEVERITIES, errorWarningIgnoreLabel, 0);
+
+		// End Attribute section
+		
+		
+		// Document Type
+		ec = createStyleSection(composite, HTMLUIMessages.Expandable_label_document_type, nColumns);
+		
+		inner = new Composite(ec, SWT.NONE);
+		inner.setFont(composite.getFont());
+		inner.setLayout(new GridLayout(nColumns, false));
+		ec.setClient(inner);
+		
+		label = HTMLUIMessages.HTMLValidationPreferencePage_22;
+		addComboBox(inner, label, HTMLCorePreferenceNames.DOC_DUPLICATE, SEVERITIES, errorWarningIgnoreLabel, 0);
+		
+		label = HTMLUIMessages.HTMLValidationPreferencePage_23;
+		addComboBox(inner, label, HTMLCorePreferenceNames.DOC_INVALID_CONTENT, SEVERITIES, errorWarningIgnoreLabel, 0);
+		
+		label = HTMLUIMessages.HTMLValidationPreferencePage_24;
+		addComboBox(inner, label, HTMLCorePreferenceNames.DOC_DOCTYPE_UNCLOSED, SEVERITIES, errorWarningIgnoreLabel, 0);
+		
+		// End Document Type
+		
+		// Comments
+		ec = createStyleSection(composite, HTMLUIMessages.Expandable_label_comment, nColumns);
+		
+		inner = new Composite(ec, SWT.NONE);
+		inner.setFont(composite.getFont());
+		inner.setLayout(new GridLayout(nColumns, false));
+		ec.setClient(inner);
+		
+		label = HTMLUIMessages.HTMLValidationPreferencePage_27;
+		addComboBox(inner, label, HTMLCorePreferenceNames.COMMENT_INVALID_CONTENT, SEVERITIES, errorWarningIgnoreLabel, 0);
+		
+		label = HTMLUIMessages.HTMLValidationPreferencePage_28;
+		addComboBox(inner, label, HTMLCorePreferenceNames.COMMENT_UNCLOSED, SEVERITIES, errorWarningIgnoreLabel, 0);
+		
+		// End Comments
+		
+		
+		// CDATA Sections
+		ec = createStyleSection(composite, HTMLUIMessages.Expandable_label_cdata, nColumns);
+		
+		inner = new Composite(ec, SWT.NONE);
+		inner.setFont(composite.getFont());
+		inner.setLayout(new GridLayout(nColumns, false));
+		ec.setClient(inner);
+		
+		label = HTMLUIMessages.HTMLValidationPreferencePage_29;
+		addComboBox(inner, label, HTMLCorePreferenceNames.CDATA_INVALID_CONTENT, SEVERITIES, errorWarningIgnoreLabel, 0);
+		
+		label = HTMLUIMessages.HTMLValidationPreferencePage_30;
+		addComboBox(inner, label, HTMLCorePreferenceNames.CDATA_UNCLOSED, SEVERITIES, errorWarningIgnoreLabel, 0);
+		
+		// End CDATA Sections
+		
+		// Processing Instructions
+		ec = createStyleSection(composite, HTMLUIMessages.Expandable_label_pi, nColumns);
+		
+		inner = new Composite(ec, SWT.NONE);
+		inner.setFont(composite.getFont());
+		inner.setLayout(new GridLayout(nColumns, false));
+		ec.setClient(inner);
+		
+		label = HTMLUIMessages.HTMLValidationPreferencePage_31;
+		addComboBox(inner, label, HTMLCorePreferenceNames.PI_INVALID_CONTENT, SEVERITIES, errorWarningIgnoreLabel, 0);
+		
+		label = HTMLUIMessages.HTMLValidationPreferencePage_32;
+		addComboBox(inner, label, HTMLCorePreferenceNames.PI_UNCLOSED, SEVERITIES, errorWarningIgnoreLabel, 0);
+		
+		// End Processing Instructions
+		
+		// Entity References
+		ec = createStyleSection(composite, HTMLUIMessages.Expandable_label_entity_ref, nColumns);
+		
+		inner = new Composite(ec, SWT.NONE);
+		inner.setFont(composite.getFont());
+		inner.setLayout(new GridLayout(nColumns, false));
+		ec.setClient(inner);
+		
+		label = HTMLUIMessages.HTMLValidationPreferencePage_33;
+		addComboBox(inner, label, HTMLCorePreferenceNames.REF_INVALID_CONTENT, SEVERITIES, errorWarningIgnoreLabel, 0);
+		
+		label = HTMLUIMessages.HTMLValidationPreferencePage_34;
+		addComboBox(inner, label, HTMLCorePreferenceNames.REF_UNDEFINED, SEVERITIES, errorWarningIgnoreLabel, 0);
+		
+		
+		// End Entity References
+		
+		
+		// Text Content
+		ec = createStyleSection(composite, HTMLUIMessages.Expandable_label_text, nColumns);
+		
+		inner = new Composite(ec, SWT.NONE);
+		inner.setFont(composite.getFont());
+		inner.setLayout(new GridLayout(nColumns, false));
+		ec.setClient(inner);
+		
+		label = HTMLUIMessages.HTMLValidationPreferencePage_25;
+		addComboBox(inner, label, HTMLCorePreferenceNames.TEXT_INVALID_CONTENT, SEVERITIES, errorWarningIgnoreLabel, 0);
+		
+		label = HTMLUIMessages.HTMLValidationPreferencePage_26;
+		addComboBox(inner, label, HTMLCorePreferenceNames.TEXT_INVALID_CHAR, SEVERITIES, errorWarningIgnoreLabel, 0);
+		
+		// End Text Content
+		
+		restoreSectionExpansionStates(getDialogSettings().getSection(SETTINGS_SECTION_NAME));
+		
+		return spContent;
+	}
+	
+	/*
+	 * (non-Javadoc)
+	 * @see org.eclipse.jface.preference.PreferencePage#performDefaults()
+	 */
+	protected void performDefaults() {
+		resetSeverities();
+		super.performDefaults();
+	}
+	
+	protected IDialogSettings getDialogSettings() {
+		return HTMLUIPlugin.getDefault().getDialogSettings();
+	}
+	
+	/*
+	 * (non-Javadoc)
+	 * @see org.eclipse.jface.dialogs.DialogPage#dispose()
+	 */
+	public void dispose() {
+		storeSectionExpansionStates(getDialogSettings().addNewSection(SETTINGS_SECTION_NAME));
+		super.dispose();
+	}
+	
+	protected String getQualifier() {
+		return HTMLCorePlugin.getDefault().getBundle().getSymbolicName();
+	}
+	
+	protected String getPreferenceNodeQualifier() {
+		return HTMLCorePlugin.getDefault().getBundle().getSymbolicName();
+	}
+
+	protected String getPreferencePageID() {
+		return "org.eclipse.wst.html.ui.preferences.validation";//$NON-NLS-1$
+	}
+
+	protected String getProjectSettingsKey() {
+		return HTMLCorePreferenceNames.USE_PROJECT_SETTINGS;
+	}
+
+	protected String getPropertyPageID() {
+		return "org.eclipse.wst.html.ui.propertyPage.project.validation";//$NON-NLS-1$
+	}
+
+	public void init(IWorkbench workbench) {
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/preferences/ui/PropertyPreferencePage.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/preferences/ui/PropertyPreferencePage.java
new file mode 100644
index 0000000..ae95c84
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/preferences/ui/PropertyPreferencePage.java
@@ -0,0 +1,300 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2008 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.preferences.ui;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.ProjectScope;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.preferences.DefaultScope;
+import org.eclipse.core.runtime.preferences.IScopeContext;
+import org.eclipse.core.runtime.preferences.InstanceScope;
+import org.eclipse.jface.dialogs.ControlEnableState;
+import org.eclipse.jface.viewers.DecoratingLabelProvider;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Link;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+import org.eclipse.ui.dialogs.ListDialog;
+import org.eclipse.ui.dialogs.PreferencesUtil;
+import org.eclipse.ui.dialogs.PropertyPage;
+import org.eclipse.ui.model.WorkbenchLabelProvider;
+import org.eclipse.ui.views.navigator.ResourceSorter;
+import org.eclipse.wst.sse.core.internal.tasks.TaskTagPreferenceKeys;
+import org.eclipse.wst.sse.ui.internal.SSEUIMessages;
+import org.eclipse.wst.sse.ui.internal.SSEUIPlugin;
+
+/**
+ * Based loosely on org.eclipse.jdt.internal.ui.preferences.PropertyAndPreferencePage
+ */
+abstract class PropertyPreferencePage extends PropertyPage implements IWorkbenchPreferencePage {
+	private static final boolean _debugPreferences = "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.wst.sse.ui/preferences-properties")); //$NON-NLS-1$ //$NON-NLS-2$
+	/*
+	 * Disable link data, prevents the display of a "workspace" or "project"
+	 * settings link to prevent recursive dialog launching
+	 */
+	private static final Object DISABLE_LINK = "DISABLE_LINK"; //$NON-NLS-1$
+
+	private Map fData = null;
+
+	private Button fEnableProjectSettings;
+
+	private Link fProjectSettingsLink;
+	
+	private Control fCommon;
+	
+	private ControlEnableState fEnablements;
+
+	public PropertyPreferencePage() {
+		super();
+	}
+
+	public final void applyData(Object data) {
+		super.applyData(data);
+		if (data instanceof Map) {
+			fData = (Map) data;
+			updateLinkEnablement();
+		}
+	}
+
+	protected abstract Control createCommonContents(Composite composite);
+
+	public final Control createContents(Composite parent) {
+		Composite composite = new Composite(parent, SWT.NULL);
+
+		GridLayout layout = new GridLayout();
+		composite.setLayout(layout);
+		GridData data = new GridData(GridData.FILL_BOTH);
+		composite.setLayoutData(data);
+
+		Composite checkLinkComposite = new Composite(composite, SWT.NONE);
+		checkLinkComposite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
+		checkLinkComposite.setLayout(new GridLayout(2, false));
+
+		if (getProject() != null) {
+			fEnableProjectSettings = new Button(checkLinkComposite, SWT.CHECK);
+			fEnableProjectSettings.setText(SSEUIMessages.EnableProjectSettings); //$NON-NLS-1$//$NON-NLS-2$
+			fEnableProjectSettings.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, false, false));
+			boolean enabledForProject = createPreferenceScopes()[0].getNode(getPreferenceNodeQualifier()).getBoolean(getProjectSettingsKey(), false);
+			fEnableProjectSettings.setSelection(enabledForProject);
+		}
+		else {
+			Label spacer = new Label(checkLinkComposite, SWT.CHECK);
+			spacer.setLayoutData(new GridData());
+		}
+
+		fProjectSettingsLink = new Link(checkLinkComposite, SWT.NONE);
+		fProjectSettingsLink.setLayoutData(new GridData(SWT.END, SWT.BEGINNING, true, false));
+
+		/*
+		 * "element" should be a project, if null, link to per-project
+		 * properties
+		 */
+		if (getProject() != null) {
+			fProjectSettingsLink.setText("<a>" + SSEUIMessages.ConfigureWorkspaceSettings + "</a>"); //$NON-NLS-1$//$NON-NLS-2$
+		}
+		else {
+			fProjectSettingsLink.setText("<a>" + SSEUIMessages.ConfigureProjectSettings + "</a>"); //$NON-NLS-1$//$NON-NLS-2$
+		}
+
+		updateLinkEnablement();
+
+		fProjectSettingsLink.addSelectionListener(new SelectionListener() {
+			public void widgetDefaultSelected(SelectionEvent e) {
+				widgetSelected(e);
+			}
+
+			public void widgetSelected(SelectionEvent e) {
+				if (getProject() == null) {
+					openProjectSettings();
+				}
+				else {
+					openWorkspaceSettings();
+				}
+			}
+
+		});
+
+		if (getProject() != null) {
+			Label line = new Label(composite, SWT.SEPARATOR | SWT.HORIZONTAL);
+			line.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
+		}
+
+//		final Control common = createCommonContents(composite);
+		fCommon = createCommonContents(composite);
+		
+		fCommon.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+		if (fEnableProjectSettings != null) {
+			SelectionAdapter selectionAdapter = new SelectionAdapter() {
+				public void widgetSelected(SelectionEvent e) {
+					super.widgetSelected(e);
+					enablePreferenceContent(fEnableProjectSettings.getSelection());
+				}
+			};
+			selectionAdapter.widgetSelected(null);
+			fEnableProjectSettings.addSelectionListener(selectionAdapter);
+		}
+		
+		applyDialogFont(composite);
+		return composite;
+	}
+
+	protected IScopeContext[] createPreferenceScopes() {
+		IProject project = getProject();
+		if (project != null) {
+			return new IScopeContext[]{new ProjectScope(project), new InstanceScope(), new DefaultScope()};
+		}
+		return new IScopeContext[]{new InstanceScope(), new DefaultScope()};
+	}
+
+	protected abstract String getPreferenceNodeQualifier();
+
+	protected abstract String getPreferencePageID();
+
+	protected IProject getProject() {
+		if (getElement() != null) {
+			if (getElement() instanceof IProject) {
+				return (IProject) getElement();
+			}
+			Object adapter = getElement().getAdapter(IProject.class);
+			if (adapter instanceof IProject) {
+				return (IProject) adapter;
+			}
+			adapter = getElement().getAdapter(IResource.class);
+			if (adapter instanceof IProject) {
+				return (IProject) adapter;
+			}
+		}
+		return null;
+	}
+
+	protected abstract String getProjectSettingsKey();
+
+	protected abstract String getPropertyPageID();
+
+	protected boolean isElementSettingsEnabled() {
+		return fEnableProjectSettings != null && fEnableProjectSettings.getSelection();
+	}
+
+	void openProjectSettings() {
+		ListDialog dialog = new ListDialog(getShell()) {
+
+			protected Control createDialogArea(Composite container) {
+				Control area = super.createDialogArea(container);
+				getTableViewer().setSorter(new ResourceSorter(ResourceSorter.NAME));
+				return area;
+			}
+		};
+		dialog.setMessage(SSEUIMessages.PropertyPreferencePage_02);
+		dialog.setContentProvider(new IStructuredContentProvider() {
+			public void dispose() {
+			}
+
+			public Object[] getElements(Object inputElement) {
+				return ((IWorkspace) inputElement).getRoot().getProjects();
+			}
+
+			public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+			}
+		});
+		dialog.setLabelProvider(new DecoratingLabelProvider(new WorkbenchLabelProvider(), SSEUIPlugin.getDefault().getWorkbench().getDecoratorManager().getLabelDecorator()));
+		dialog.setInput(ResourcesPlugin.getWorkspace());
+		dialog.setTitle(SSEUIMessages.PropertyPreferencePage_01);
+		if (dialog.open() == Window.OK) {
+			Object[] result = dialog.getResult();
+			if (result.length > 0) {
+				IProject project = (IProject) dialog.getResult()[0];
+				Map data = new HashMap();
+				data.put(DISABLE_LINK, Boolean.TRUE);
+				PreferencesUtil.createPropertyDialogOn(getShell(), project, getPropertyPageID(), new String[]{getPropertyPageID()}, data).open();
+			}
+		}
+	}
+
+	void openWorkspaceSettings() {
+		Map data = new HashMap();
+		data.put(DISABLE_LINK, Boolean.TRUE);
+		PreferencesUtil.createPreferenceDialogOn(getShell(), getPreferencePageID(), new String[]{getPreferencePageID()}, data).open();
+	}
+
+	public boolean performOk() {
+		boolean ok = super.performOk();
+		IScopeContext[] preferenceScopes = createPreferenceScopes();
+		if (getProject() != null) {
+			if (isElementSettingsEnabled()) {
+				if (_debugPreferences) {
+					System.out.println(getClass().getName() + " setting " + TaskTagPreferenceKeys.TASK_TAG_PER_PROJECT + " (" + true + ") in scope " + preferenceScopes[0].getName() + ":" + preferenceScopes[0].getLocation()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$  
+				}
+				preferenceScopes[0].getNode(getPreferenceNodeQualifier()).putBoolean(getProjectSettingsKey(), fEnableProjectSettings.getSelection());
+			}
+			else {
+				if (_debugPreferences) {
+					System.out.println(getClass().getName() + " removing " + TaskTagPreferenceKeys.TASK_TAG_PER_PROJECT + " from scope " + preferenceScopes[0].getName() + ":" + preferenceScopes[0].getLocation()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+				}
+				preferenceScopes[0].getNode(getPreferenceNodeQualifier()).remove(getProjectSettingsKey());
+			}
+		}
+		return ok;
+	}
+	
+	protected void performDefaults() {
+		if(getProject() != null && fEnableProjectSettings != null) {
+			fEnableProjectSettings.setSelection(false);
+			enablePreferenceContent(false);
+		}
+		super.performDefaults();
+	}
+
+	private void updateLinkEnablement() {
+		if (fData != null && fProjectSettingsLink != null) {
+			fProjectSettingsLink.setEnabled(!Boolean.TRUE.equals(fData.get(DISABLE_LINK)));
+		}
+	}
+	
+	/**
+	 * Controls the enablement of the common content region
+	 * of a property or preference page
+	 * 
+	 * @param enable the enabled state of the common content
+	 * area
+	 */
+	protected void enablePreferenceContent(boolean enable) {
+		if(enable) {
+			if(fEnablements != null) {
+				fEnablements.restore();
+				fEnablements = null;
+			}
+		}
+		else {
+			if(fEnablements == null)
+				fEnablements = ControlEnableState.disable(fCommon);
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/registry/AdapterFactoryProviderForHTML.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/registry/AdapterFactoryProviderForHTML.java
new file mode 100644
index 0000000..145ab9a
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/registry/AdapterFactoryProviderForHTML.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.registry;
+
+import org.eclipse.wst.html.core.internal.modelhandler.ModelHandlerForHTML;
+import org.eclipse.wst.html.ui.internal.contentoutline.JFaceNodeAdapterFactoryForHTML;
+import org.eclipse.wst.sse.core.internal.ltk.modelhandler.IDocumentTypeHandler;
+import org.eclipse.wst.sse.core.internal.model.FactoryRegistry;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapterFactory;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.ui.internal.contentoutline.IJFaceNodeAdapter;
+import org.eclipse.wst.sse.ui.internal.provisional.registry.AdapterFactoryProvider;
+import org.eclipse.wst.sse.ui.internal.util.Assert;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
+
+
+public class AdapterFactoryProviderForHTML implements AdapterFactoryProvider {
+
+
+	public void addAdapterFactories(IStructuredModel structuredModel) {
+
+		// these are the normal edit side content based factories
+		addContentBasedFactories(structuredModel);
+		// Must update/add to propagating adapter here too
+		if (structuredModel instanceof IDOMModel) {
+			addPropagatingAdapters(structuredModel);
+		}
+	}
+
+	protected void addContentBasedFactories(IStructuredModel structuredModel) {
+
+		FactoryRegistry factoryRegistry = structuredModel.getFactoryRegistry();
+		Assert.isNotNull(factoryRegistry, "Program Error: client caller must ensure model has factory registry"); //$NON-NLS-1$
+		INodeAdapterFactory factory = null;
+
+		factory = factoryRegistry.getFactoryFor(IJFaceNodeAdapter.class);
+		if (factory == null) {
+			factory = new JFaceNodeAdapterFactoryForHTML();
+			factoryRegistry.addFactory(factory);
+		}
+	}
+
+	protected void addPropagatingAdapters(IStructuredModel structuredModel) {
+		// no propagating to add
+	}
+
+	/*
+	 * @see AdapterFactoryProvider#isFor(ContentTypeDescription)
+	 */
+	public boolean isFor(IDocumentTypeHandler contentTypeDescription) {
+		return (contentTypeDescription instanceof ModelHandlerForHTML);
+	}
+
+	public void reinitializeFactories(IStructuredModel structuredModel) {
+		// nothing to do, since no embedded type
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/search/HTMLFindOccurrencesActionDelegate.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/search/HTMLFindOccurrencesActionDelegate.java
new file mode 100644
index 0000000..23c2c49
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/search/HTMLFindOccurrencesActionDelegate.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+
+package org.eclipse.wst.html.ui.internal.search;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.wst.sse.ui.internal.search.FindOccurrencesActionDelegate;
+
+/**
+ * Sets up FindOccurrencesActionDelegate for html find occurrences processors
+ */
+public class HTMLFindOccurrencesActionDelegate extends FindOccurrencesActionDelegate {
+	private List fProcessors;
+
+	protected List getProcessors() {
+		if (fProcessors == null) {
+			fProcessors = new ArrayList();
+			HTMLFindOccurrencesProcessor htmlProcessor = new HTMLFindOccurrencesProcessor();
+			fProcessors.add(htmlProcessor);
+		}
+		return fProcessors;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/search/HTMLFindOccurrencesProcessor.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/search/HTMLFindOccurrencesProcessor.java
new file mode 100644
index 0000000..c20efa1
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/search/HTMLFindOccurrencesProcessor.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+
+package org.eclipse.wst.html.ui.internal.search;
+
+import org.eclipse.wst.html.core.text.IHTMLPartitions;
+import org.eclipse.wst.sse.ui.internal.search.FindOccurrencesProcessor;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+import org.eclipse.wst.xml.core.text.IXMLPartitions;
+
+/**
+ * Configures a FindOccurrencesProcessor with HTML partitions and regions
+ */
+public class HTMLFindOccurrencesProcessor extends FindOccurrencesProcessor {
+
+	protected String[] getPartitionTypes() {
+		return new String[]{IHTMLPartitions.HTML_DEFAULT, IXMLPartitions.XML_DEFAULT};
+	}
+
+	protected String[] getRegionTypes() {
+		return new String[]{DOMRegionContext.XML_TAG_NAME, DOMRegionContext.XML_TAG_ATTRIBUTE_NAME, DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE};
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/style/IStyleConstantsHTML.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/style/IStyleConstantsHTML.java
new file mode 100644
index 0000000..81f765c
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/style/IStyleConstantsHTML.java
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.style;
+
+import org.eclipse.wst.xml.ui.internal.style.IStyleConstantsXML;
+
+/**
+ * Contains the symbolic name of styles used by LineStyleProvider, ColorManager, and
+ * any others who may be interested
+ */
+public interface IStyleConstantsHTML extends IStyleConstantsXML {
+	public static final String SCRIPT_AREA_BORDER = "SCRIPT_AREA_BORDER";//$NON-NLS-1$
+	public static final String SCRIPT_AREA = "SCRIPT_AREA";//$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/style/LineStyleProviderForHTML.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/style/LineStyleProviderForHTML.java
new file mode 100644
index 0000000..4db6f64
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/style/LineStyleProviderForHTML.java
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.style;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.TextAttribute;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.wst.html.ui.internal.HTMLUIPlugin;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+import org.eclipse.wst.sse.ui.internal.provisional.style.LineStyleProvider;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+import org.eclipse.wst.xml.ui.internal.style.IStyleConstantsXML;
+import org.eclipse.wst.xml.ui.internal.style.LineStyleProviderForXML;
+
+public class LineStyleProviderForHTML extends LineStyleProviderForXML implements LineStyleProvider {
+
+	public LineStyleProviderForHTML() {
+		super();
+	}
+
+	/**
+	 * a method to centralize all the "format rules" for regions 
+	 * specifically associated for how to "open" the region.
+	 */
+	// NOTE: this method was just copied down form LineStyleProviderForXML
+	public TextAttribute getAttributeFor(ITextRegion region) {
+		// not sure why this is coming through null, but just to catch it
+		if (region == null) {
+			return (TextAttribute)getTextAttributes().get(IStyleConstantsXML.XML_CONTENT);
+		}
+		String type = region.getType();
+		if (type == DOMRegionContext.BLOCK_TEXT) {
+			return (TextAttribute)getTextAttributes().get(IStyleConstantsXML.XML_CONTENT);
+		}
+		// workaround: make PI edges the same color as tag edges
+		else if ((type == DOMRegionContext.XML_PI_OPEN) || (type == DOMRegionContext.XML_PI_CLOSE)) {
+			return (TextAttribute) getTextAttributes().get(IStyleConstantsXML.TAG_BORDER);
+		}
+		// first try "standard" tag attributes from super class
+		return super.getAttributeFor(region);
+	}
+
+	protected void loadColors() {
+		super.loadColors();
+
+		addTextAttribute(IStyleConstantsHTML.SCRIPT_AREA_BORDER);
+	}
+	
+	
+	protected void handlePropertyChange(PropertyChangeEvent event) {
+		if (event != null) {
+			String prefKey = event.getProperty();
+			// check if preference changed is a style preference
+			if (IStyleConstantsHTML.SCRIPT_AREA_BORDER.equals(prefKey)) {
+				addTextAttribute(IStyleConstantsHTML.SCRIPT_AREA_BORDER);
+
+				// this is what AbstractLineStyleProvider.propertyChange() does
+				getHighlighter().refreshDisplay();
+			} else {
+				super.handlePropertyChange(event);
+			}
+		} else {
+			super.handlePropertyChange(event);
+		}
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.sse.ui.style.AbstractLineStyleProvider#getColorPreferences()
+	 */
+	protected IPreferenceStore getColorPreferences() {
+		return HTMLUIPlugin.getDefault().getPreferenceStore();
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/taginfo/HTMLInformationProvider.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/taginfo/HTMLInformationProvider.java
new file mode 100644
index 0000000..5f859c7
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/taginfo/HTMLInformationProvider.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.taginfo;
+
+
+
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextHover;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.information.IInformationProvider;
+import org.eclipse.jface.text.information.IInformationProviderExtension;
+import org.eclipse.wst.sse.ui.internal.SSEUIPlugin;
+
+/**
+ * Provides context information for HTML tags (Shows tooltip description)
+ * 
+ * @deprecated StructuredTextViewerConfiguration creates the appropriate
+ *             information provider
+ */
+public class HTMLInformationProvider implements IInformationProvider, IInformationProviderExtension {
+
+	private ITextHover fTextHover = null;
+
+	public HTMLInformationProvider() {
+		fTextHover = SSEUIPlugin.getDefault().getTextHoverManager().createBestMatchHover(new HTMLTagInfoHoverProcessor());
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.information.IInformationProvider#getSubject(org.eclipse.jface.text.ITextViewer,
+	 *      int)
+	 */
+	public IRegion getSubject(ITextViewer textViewer, int offset) {
+		return fTextHover.getHoverRegion(textViewer, offset);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.information.IInformationProvider#getInformation(org.eclipse.jface.text.ITextViewer,
+	 *      org.eclipse.jface.text.IRegion)
+	 */
+	public String getInformation(ITextViewer textViewer, IRegion subject) {
+		return (String) getInformation2(textViewer, subject);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.information.IInformationProviderExtension#getInformation2(org.eclipse.jface.text.ITextViewer,
+	 *      org.eclipse.jface.text.IRegion)
+	 */
+	public Object getInformation2(ITextViewer textViewer, IRegion subject) {
+		return fTextHover.getHoverInfo(textViewer, subject);
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/taginfo/HTMLTagInfoHoverProcessor.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/taginfo/HTMLTagInfoHoverProcessor.java
new file mode 100644
index 0000000..a99186a
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/taginfo/HTMLTagInfoHoverProcessor.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.taginfo;
+
+
+
+import org.eclipse.wst.xml.ui.internal.taginfo.XMLTagInfoHoverProcessor;
+
+/**
+ * Provides hover help documentation for HTML tags
+ * 
+ * @author amywu
+ */
+public class HTMLTagInfoHoverProcessor extends XMLTagInfoHoverProcessor {
+	//	currently empty because XMLTagInfoHoverProcessor handles all cases relevant to HTML
+	public HTMLTagInfoHoverProcessor() {
+		super();
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/templates/EncodingTemplateVariableResolverHTML.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/templates/EncodingTemplateVariableResolverHTML.java
new file mode 100644
index 0000000..aca7d17
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/templates/EncodingTemplateVariableResolverHTML.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.templates;
+
+import org.eclipse.jface.text.templates.SimpleTemplateVariableResolver;
+import org.eclipse.jface.text.templates.TemplateContext;
+import org.eclipse.wst.html.core.internal.HTMLCorePlugin;
+import org.eclipse.wst.html.ui.internal.HTMLUIMessages;
+import org.eclipse.wst.sse.core.internal.encoding.CommonEncodingPreferenceNames;
+
+
+public class EncodingTemplateVariableResolverHTML extends SimpleTemplateVariableResolver {
+	private static final String ENCODING_TYPE = getEncodingType();
+
+	private static String getEncodingType() {
+		return "encoding"; //$NON-NLS-1$
+	}
+
+	/**
+	 * Creates a new encoding variable
+	 */
+	public EncodingTemplateVariableResolverHTML() {
+		super(ENCODING_TYPE, HTMLUIMessages.Creating_files_encoding);
+	}
+
+	protected String resolve(TemplateContext context) {
+		return HTMLCorePlugin.getDefault().getPluginPreferences().getString(CommonEncodingPreferenceNames.OUTPUT_CODESET);
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/templates/TemplateContextTypeHTML.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/templates/TemplateContextTypeHTML.java
new file mode 100644
index 0000000..2a18055
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/templates/TemplateContextTypeHTML.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.templates;
+
+import org.eclipse.jface.text.templates.GlobalTemplateVariables;
+import org.eclipse.jface.text.templates.TemplateContextType;
+
+/**
+ * Base class for HTML template context types. Templates of this context type
+ * apply to any place within HTML content type.
+ */
+public class TemplateContextTypeHTML extends TemplateContextType {
+
+	public TemplateContextTypeHTML() {
+		super();
+		addResolver(new GlobalTemplateVariables.Cursor());
+		addResolver(new GlobalTemplateVariables.Date());
+		addResolver(new GlobalTemplateVariables.Dollar());
+		addResolver(new GlobalTemplateVariables.LineSelection());
+		addResolver(new GlobalTemplateVariables.Time());
+		addResolver(new GlobalTemplateVariables.User());
+		addResolver(new GlobalTemplateVariables.WordSelection());
+		addResolver(new GlobalTemplateVariables.Year());
+		addResolver(new EncodingTemplateVariableResolverHTML());
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/templates/TemplateContextTypeIdsHTML.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/templates/TemplateContextTypeIdsHTML.java
new file mode 100644
index 0000000..794b13d
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/templates/TemplateContextTypeIdsHTML.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.templates;
+
+
+public class TemplateContextTypeIdsHTML {
+
+	public static final String ALL = getAll();
+
+	public static final String ATTRIBUTE = getAttribute();
+
+	public static final String ATTRIBUTE_VALUE = getAttributeValue();
+
+	public static final String NEW = getNew();
+
+	public static final String TAG = getTag();
+
+	private static String getAll() {
+		return getPrefix() + "_all"; //$NON-NLS-1$
+	}
+
+	private static String getAttribute() {
+		return getPrefix() + "_attribute"; //$NON-NLS-1$
+	}
+
+	private static String getAttributeValue() {
+		return getPrefix() + "_attribute_value"; //$NON-NLS-1$
+	}
+
+	private static String getNew() {
+		return getPrefix() + "_new"; //$NON-NLS-1$
+	}
+
+	private static String getTag() {
+		return getPrefix() + "_tag"; //$NON-NLS-1$
+	}
+
+	private static String getPrefix() {
+		return "html"; //$NON-NLS-1$
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/text/CharacterPairInserter.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/text/CharacterPairInserter.java
new file mode 100644
index 0000000..b418adc
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/text/CharacterPairInserter.java
@@ -0,0 +1,106 @@
+/*******************************************************************************

+ * Copyright (c) 2009, 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

+ *******************************************************************************/

+package org.eclipse.wst.html.ui.internal.text;

+

+import org.eclipse.jface.preference.IPreferenceStore;

+import org.eclipse.jface.text.IDocument;

+import org.eclipse.jface.text.source.ISourceViewer;

+import org.eclipse.jface.util.IPropertyChangeListener;

+import org.eclipse.jface.util.PropertyChangeEvent;

+import org.eclipse.swt.graphics.Point;

+import org.eclipse.wst.html.ui.internal.HTMLUIPlugin;

+import org.eclipse.wst.html.ui.internal.preferences.HTMLUIPreferenceNames;

+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.ui.typing.AbstractCharacterPairInserter;

+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;

+

+public class CharacterPairInserter extends AbstractCharacterPairInserter implements IPropertyChangeListener {

+

+	// preferences

+	private boolean fCloseStrings = true;

+	private boolean fCloseBrackets = true;

+

+	protected boolean shouldPair(ISourceViewer viewer, char c) {

+		switch (c) {

+			case '\'':

+			case '"':

+				return fCloseStrings ? checkRegion(viewer) : false;

+			default:

+				return fCloseBrackets;

+		}

+	}

+

+	/**

+	 * Checks if the region should support paired quotes

+	 * @param viewer the viewer

+	 * @return true if the region is not in an XML attribute value

+	 */

+	private boolean checkRegion(ISourceViewer viewer) {

+		final IDocument doc = viewer.getDocument();

+		final Point selection = viewer.getSelectedRange();

+		final int offset = selection.x;

+

+		if (doc instanceof IStructuredDocument) {

+			IStructuredDocumentRegion[] regions = ((IStructuredDocument) doc).getStructuredDocumentRegions(offset, 0);

+			if (regions != null && regions.length > 0) {

+				ITextRegion region = regions[0].getRegionAtCharacterOffset(offset);

+				return region != null && region.getType() != DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE;

+			}

+		}

+		return true;

+	}

+

+	public boolean hasPair(char c) {

+		switch (c) {

+			case '"':

+			case '\'':

+			case '[':

+			case '(':

+				return true;

+			default:

+				return false;

+		}

+	}

+

+	protected char getPair(char c) {

+		switch (c) {

+			case '\'':

+			case '"':

+				return c;

+			case '(':

+				return ')';

+			case '[':

+				return ']';

+			default:

+				throw new IllegalArgumentException();

+		}

+	}

+

+	public void initialize() {

+		IPreferenceStore store = HTMLUIPlugin.getInstance().getPreferenceStore();

+		fCloseStrings = store.getBoolean(HTMLUIPreferenceNames.TYPING_CLOSE_STRINGS);

+		fCloseBrackets = store.getBoolean(HTMLUIPreferenceNames.TYPING_CLOSE_BRACKETS);

+		store.addPropertyChangeListener(this);

+	}

+

+	public void dispose() {

+		HTMLUIPlugin.getInstance().getPreferenceStore().removePropertyChangeListener(this);

+	}

+

+	public void propertyChange(PropertyChangeEvent event) {

+		if (HTMLUIPreferenceNames.TYPING_CLOSE_BRACKETS.equals(event.getProperty()))

+			fCloseBrackets = ((Boolean) event.getNewValue()).booleanValue();

+		else if (HTMLUIPreferenceNames.TYPING_CLOSE_STRINGS.equals(event.getProperty()))

+			fCloseStrings = ((Boolean) event.getNewValue()).booleanValue();

+	}

+}

diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/text/HTMLDocumentRegionEdgeMatcher.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/text/HTMLDocumentRegionEdgeMatcher.java
new file mode 100644
index 0000000..aa75cdb
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/text/HTMLDocumentRegionEdgeMatcher.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.text;
+
+import org.eclipse.wst.sse.ui.internal.text.DocumentRegionEdgeMatcher;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+
+public class HTMLDocumentRegionEdgeMatcher extends DocumentRegionEdgeMatcher {
+
+	protected final static char[] BRACKETS = {'{', '}', '(', ')', '[', ']','"','"','\'','\''};
+	/**
+	 * @param validContexts
+	 * @param nextMatcher
+	 */
+	public HTMLDocumentRegionEdgeMatcher() {
+		super(new String[]{DOMRegionContext.XML_TAG_NAME, DOMRegionContext.XML_COMMENT_TEXT, DOMRegionContext.XML_CDATA_TEXT, DOMRegionContext.XML_PI_OPEN, DOMRegionContext.XML_PI_CONTENT}, new JavaPairMatcher(BRACKETS));
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/text/IJavaPartitions.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/text/IJavaPartitions.java
new file mode 100644
index 0000000..b9d8561
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/text/IJavaPartitions.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.text;
+
+// taken from package org.eclipse.jdt.ui.text;
+
+/**
+ * Definition of Java partitioning and its partitions.
+ * 
+ * @see Eclipse 3.1
+ */
+interface IJavaPartitions {
+
+	/**
+	 * The identifier of the Java partitioning.
+	 */
+	String JAVA_PARTITIONING = "___java_partitioning"; //$NON-NLS-1$
+
+	/**
+	 * The identifier of the single-line (JLS2: EndOfLineComment) end comment
+	 * partition content type.
+	 */
+	String JAVA_SINGLE_LINE_COMMENT = "__java_singleline_comment"; //$NON-NLS-1$
+
+	/**
+	 * The identifier multi-line (JLS2: TraditionalComment) comment partition
+	 * content type.
+	 */
+	String JAVA_MULTI_LINE_COMMENT = "__java_multiline_comment"; //$NON-NLS-1$
+
+	/**
+	 * The identifier of the Javadoc (JLS2: DocumentationComment) partition
+	 * content type.
+	 */
+	String JAVA_DOC = "__java_javadoc"; //$NON-NLS-1$
+
+	/**
+	 * The identifier of the Java string partition content type.
+	 */
+	String JAVA_STRING = "__java_string"; //$NON-NLS-1$
+
+	/**
+	 * The identifier of the Java character partition content type.
+	 */
+	String JAVA_CHARACTER = "__java_character"; //$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/text/JavaCodeReader.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/text/JavaCodeReader.java
new file mode 100644
index 0000000..e3cace3
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/text/JavaCodeReader.java
@@ -0,0 +1,244 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.text;
+
+// taken from package org.eclipse.jdt.ui.text;
+
+import java.io.IOException;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.wst.html.ui.internal.derived.SingleCharReader;
+
+/**
+ * Reads from a document either forwards or backwards. May be configured to
+ * skip comments and strings.
+ */
+class JavaCodeReader extends SingleCharReader {
+
+	/** The EOF character */
+	public static final int EOF = -1;
+
+	private boolean fSkipComments = false;
+	private boolean fSkipStrings = false;
+	private boolean fForward = false;
+
+	private IDocument fDocument;
+	private int fOffset;
+
+	private int fEnd = -1;
+	private int fCachedLineNumber = -1;
+	private int fCachedLineOffset = -1;
+
+
+	public JavaCodeReader() {
+	}
+
+	/**
+	 * Returns the offset of the last read character. Should only be called
+	 * after read has been called.
+	 */
+	public int getOffset() {
+		return fForward ? fOffset - 1 : fOffset;
+	}
+
+	public void configureForwardReader(IDocument document, int offset, int length, boolean skipComments, boolean skipStrings) throws IOException {
+		fDocument = document;
+		fOffset = offset;
+		fSkipComments = skipComments;
+		fSkipStrings = skipStrings;
+
+		fForward = true;
+		fEnd = Math.min(fDocument.getLength(), fOffset + length);
+	}
+
+	public void configureBackwardReader(IDocument document, int offset, boolean skipComments, boolean skipStrings) throws IOException {
+		fDocument = document;
+		fOffset = offset;
+		fSkipComments = skipComments;
+		fSkipStrings = skipStrings;
+
+		fForward = false;
+		try {
+			fCachedLineNumber = fDocument.getLineOfOffset(fOffset);
+		}
+		catch (BadLocationException x) {
+			throw new IOException(x.getMessage());
+		}
+	}
+
+	/*
+	 * @see Reader#close()
+	 */
+	public void close() throws IOException {
+		fDocument = null;
+	}
+
+	/*
+	 * @see SingleCharReader#read()
+	 */
+	public int read() throws IOException {
+		try {
+			return fForward ? readForwards() : readBackwards();
+		}
+		catch (BadLocationException x) {
+			throw new IOException(x.getMessage());
+		}
+	}
+
+	private void gotoCommentEnd() throws BadLocationException {
+		while (fOffset < fEnd) {
+			char current = fDocument.getChar(fOffset++);
+			if (current == '*') {
+				if (fOffset < fEnd && fDocument.getChar(fOffset) == '/') {
+					++fOffset;
+					return;
+				}
+			}
+		}
+	}
+
+	private void gotoStringEnd(char delimiter) throws BadLocationException {
+		while (fOffset < fEnd) {
+			char current = fDocument.getChar(fOffset++);
+			if (current == '\\') {
+				// ignore escaped characters
+				++fOffset;
+			}
+			else if (current == delimiter) {
+				return;
+			}
+		}
+	}
+
+	private void gotoLineEnd() throws BadLocationException {
+		int line = fDocument.getLineOfOffset(fOffset);
+		fOffset = fDocument.getLineOffset(line + 1);
+	}
+
+	private int readForwards() throws BadLocationException {
+		while (fOffset < fEnd) {
+			char current = fDocument.getChar(fOffset++);
+
+			switch (current) {
+				case '/' :
+
+					if (fSkipComments && fOffset < fEnd) {
+						char next = fDocument.getChar(fOffset);
+						if (next == '*') {
+							// a comment starts, advance to the comment end
+							++fOffset;
+							gotoCommentEnd();
+							continue;
+						}
+						else if (next == '/') {
+							// '//'-comment starts, advance to the line end
+							gotoLineEnd();
+							continue;
+						}
+					}
+
+					return current;
+
+				case '"' :
+				case '\'' :
+
+					if (fSkipStrings) {
+						gotoStringEnd(current);
+						continue;
+					}
+
+					return current;
+			}
+
+			return current;
+		}
+
+		return EOF;
+	}
+
+	private void handleSingleLineComment() throws BadLocationException {
+		int line = fDocument.getLineOfOffset(fOffset);
+		if (line < fCachedLineNumber) {
+			fCachedLineNumber = line;
+			fCachedLineOffset = fDocument.getLineOffset(line);
+			int offset = fOffset;
+			while (fCachedLineOffset < offset) {
+				char current = fDocument.getChar(offset--);
+				if (current == '/' && fCachedLineOffset <= offset && fDocument.getChar(offset) == '/') {
+					fOffset = offset;
+					return;
+				}
+			}
+		}
+	}
+
+	private void gotoCommentStart() throws BadLocationException {
+		while (0 < fOffset) {
+			char current = fDocument.getChar(fOffset--);
+			if (current == '*' && 0 <= fOffset && fDocument.getChar(fOffset) == '/')
+				return;
+		}
+	}
+
+	private void gotoStringStart(char delimiter) throws BadLocationException {
+		while (0 < fOffset) {
+			char current = fDocument.getChar(fOffset);
+			if (current == delimiter) {
+				if (!(0 <= fOffset && fDocument.getChar(fOffset - 1) == '\\'))
+					return;
+			}
+			--fOffset;
+		}
+	}
+
+	private int readBackwards() throws BadLocationException {
+
+		while (0 < fOffset) {
+			--fOffset;
+
+			handleSingleLineComment();
+
+			char current = fDocument.getChar(fOffset);
+			switch (current) {
+				case '/' :
+
+					if (fSkipComments && fOffset > 1) {
+						char next = fDocument.getChar(fOffset - 1);
+						if (next == '*') {
+							// a comment ends, advance to the comment start
+							fOffset -= 2;
+							gotoCommentStart();
+							continue;
+						}
+					}
+
+					return current;
+
+				case '"' :
+				case '\'' :
+
+					if (fSkipStrings) {
+						--fOffset;
+						gotoStringStart(current);
+						continue;
+					}
+
+					return current;
+			}
+
+			return current;
+		}
+
+		return EOF;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/text/JavaHeuristicScanner.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/text/JavaHeuristicScanner.java
new file mode 100644
index 0000000..01602a2
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/text/JavaHeuristicScanner.java
@@ -0,0 +1,986 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.text;
+
+// taken from package org.eclipse.jdt.internal.ui.text;
+
+import java.util.Arrays;
+
+import org.eclipse.jface.text.Assert;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITypedRegion;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jface.text.TextUtilities;
+import org.eclipse.jface.text.TypedRegion;
+
+/**
+ * Utility methods for heuristic based Java manipulations in an incomplete
+ * Java source file.
+ * 
+ * <p>
+ * An instance holds some internal position in the document and is therefore
+ * not threadsafe.
+ * </p>
+ * 
+ * @see Eclipse 3.0
+ */
+final class JavaHeuristicScanner implements Symbols {
+	/**
+	 * Returned by all methods when the requested position could not be found,
+	 * or if a {@link BadLocationException} was thrown while scanning.
+	 */
+	public static final int NOT_FOUND = -1;
+
+	/**
+	 * Special bound parameter that means either -1 (backward scanning) or
+	 * <code>fDocument.getLength()</code> (forward scanning).
+	 */
+	public static final int UNBOUND = -2;
+
+
+	/* character constants */
+	private static final char LBRACE = '{';
+	private static final char RBRACE = '}';
+	private static final char LPAREN = '(';
+	private static final char RPAREN = ')';
+	private static final char SEMICOLON = ';';
+	private static final char COLON = ':';
+	private static final char COMMA = ',';
+	private static final char LBRACKET = '[';
+	private static final char RBRACKET = ']';
+	private static final char QUESTIONMARK = '?';
+	private static final char EQUAL = '=';
+	private static final char LANGLE = '<';
+	private static final char RANGLE = '>';
+
+	/**
+	 * Specifies the stop condition, upon which the <code>scanXXX</code>
+	 * methods will decide whether to keep scanning or not. This interface may
+	 * implemented by clients.
+	 */
+	private static abstract class StopCondition {
+		/**
+		 * Instructs the scanner to return the current position.
+		 * 
+		 * @param ch
+		 *            the char at the current position
+		 * @param position
+		 *            the current position
+		 * @param forward
+		 *            the iteration direction
+		 * @return <code>true</code> if the stop condition is met.
+		 */
+		public abstract boolean stop(char ch, int position, boolean forward);
+
+		/**
+		 * Asks the condition to return the next position to query. The
+		 * default is to return the next/previous position.
+		 * 
+		 * @return the next position to scan
+		 */
+		public int nextPosition(int position, boolean forward) {
+			return forward ? position + 1 : position - 1;
+		}
+	}
+
+	/**
+	 * Stops upon a non-whitespace (as defined by
+	 * {@link Character#isWhitespace(char)}) character.
+	 */
+	private static class NonWhitespace extends StopCondition {
+		/*
+		 * @see org.eclipse.jdt.internal.ui.text.JavaHeuristicScanner.StopCondition#stop(char)
+		 */
+		public boolean stop(char ch, int position, boolean forward) {
+			return !Character.isWhitespace(ch);
+		}
+	}
+
+	/**
+	 * Stops upon a non-whitespace character in the default partition.
+	 * 
+	 * @see NonWhitespace
+	 */
+	private final class NonWhitespaceDefaultPartition extends NonWhitespace {
+		/*
+		 * @see org.eclipse.jdt.internal.ui.text.JavaHeuristicScanner.StopCondition#stop(char)
+		 */
+		public boolean stop(char ch, int position, boolean forward) {
+			return super.stop(ch, position, true) && isDefaultPartition(position);
+		}
+
+		/*
+		 * @see org.eclipse.jdt.internal.ui.text.JavaHeuristicScanner.StopCondition#nextPosition(int,
+		 *      boolean)
+		 */
+		public int nextPosition(int position, boolean forward) {
+			ITypedRegion partition = getPartition(position);
+			if (fPartition.equals(partition.getType()))
+				return super.nextPosition(position, forward);
+
+			if (forward) {
+				int end = partition.getOffset() + partition.getLength();
+				if (position < end)
+					return end;
+			}
+			else {
+				int offset = partition.getOffset();
+				if (position > offset)
+					return offset - 1;
+			}
+			return super.nextPosition(position, forward);
+		}
+	}
+
+	/**
+	 * Stops upon a non-java identifier (as defined by
+	 * {@link Character#isJavaIdentifierPart(char)}) character.
+	 */
+	private static class NonJavaIdentifierPart extends StopCondition {
+		/*
+		 * @see org.eclipse.jdt.internal.ui.text.JavaHeuristicScanner.StopCondition#stop(char)
+		 */
+		public boolean stop(char ch, int position, boolean forward) {
+			return !Character.isJavaIdentifierPart(ch);
+		}
+	}
+
+	/**
+	 * Stops upon a non-java identifier character in the default partition.
+	 * 
+	 * @see NonJavaIdentifierPart
+	 */
+	private final class NonJavaIdentifierPartDefaultPartition extends NonJavaIdentifierPart {
+		/*
+		 * @see org.eclipse.jdt.internal.ui.text.JavaHeuristicScanner.StopCondition#stop(char)
+		 */
+		public boolean stop(char ch, int position, boolean forward) {
+			return super.stop(ch, position, true) || !isDefaultPartition(position);
+		}
+
+		/*
+		 * @see org.eclipse.jdt.internal.ui.text.JavaHeuristicScanner.StopCondition#nextPosition(int,
+		 *      boolean)
+		 */
+		public int nextPosition(int position, boolean forward) {
+			ITypedRegion partition = getPartition(position);
+			if (fPartition.equals(partition.getType()))
+				return super.nextPosition(position, forward);
+
+			if (forward) {
+				int end = partition.getOffset() + partition.getLength();
+				if (position < end)
+					return end;
+			}
+			else {
+				int offset = partition.getOffset();
+				if (position > offset)
+					return offset - 1;
+			}
+			return super.nextPosition(position, forward);
+		}
+	}
+
+	/**
+	 * Stops upon a character in the default partition that matches the given
+	 * character list.
+	 */
+	private final class CharacterMatch extends StopCondition {
+		private final char[] fChars;
+
+		/**
+		 * Creates a new instance.
+		 * 
+		 * @param ch
+		 *            the single character to match
+		 */
+		public CharacterMatch(char ch) {
+			this(new char[]{ch});
+		}
+
+		/**
+		 * Creates a new instance.
+		 * 
+		 * @param chars
+		 *            the chars to match.
+		 */
+		public CharacterMatch(char[] chars) {
+			Assert.isNotNull(chars);
+			Assert.isTrue(chars.length > 0);
+			fChars = chars;
+			Arrays.sort(chars);
+		}
+
+		/*
+		 * @see org.eclipse.jdt.internal.ui.text.JavaHeuristicScanner.StopCondition#stop(char,
+		 *      int)
+		 */
+		public boolean stop(char ch, int position, boolean forward) {
+			return Arrays.binarySearch(fChars, ch) >= 0 && isDefaultPartition(position);
+		}
+
+		/*
+		 * @see org.eclipse.jdt.internal.ui.text.JavaHeuristicScanner.StopCondition#nextPosition(int,
+		 *      boolean)
+		 */
+		public int nextPosition(int position, boolean forward) {
+			ITypedRegion partition = getPartition(position);
+			if (fPartition.equals(partition.getType()))
+				return super.nextPosition(position, forward);
+
+			if (forward) {
+				int end = partition.getOffset() + partition.getLength();
+				if (position < end)
+					return end;
+			}
+			else {
+				int offset = partition.getOffset();
+				if (position > offset)
+					return offset - 1;
+			}
+			return super.nextPosition(position, forward);
+		}
+	}
+
+	/** The document being scanned. */
+	private IDocument fDocument;
+	/** The partitioning being used for scanning. */
+	private String fPartitioning;
+	/** The partition to scan in. */
+	private String fPartition;
+
+	/* internal scan state */
+
+	/** the most recently read character. */
+	private char fChar;
+	/** the most recently read position. */
+	private int fPos;
+
+	/* preset stop conditions */
+	private final StopCondition fNonWSDefaultPart = new NonWhitespaceDefaultPartition();
+	private final static StopCondition fNonWS = new NonWhitespace();
+	private final StopCondition fNonIdent = new NonJavaIdentifierPartDefaultPartition();
+
+	/**
+	 * Creates a new instance.
+	 * 
+	 * @param document
+	 *            the document to scan
+	 * @param partitioning
+	 *            the partitioning to use for scanning
+	 * @param partition
+	 *            the partition to scan in
+	 */
+	public JavaHeuristicScanner(IDocument document, String partitioning, String partition) {
+		Assert.isNotNull(document);
+		Assert.isNotNull(partitioning);
+		Assert.isNotNull(partition);
+		fDocument = document;
+		fPartitioning = partitioning;
+		fPartition = partition;
+	}
+
+	/**
+	 * Calls
+	 * <code>this(document, IJavaPartitions.JAVA_PARTITIONING, IDocument.DEFAULT_CONTENT_TYPE)</code>.
+	 * 
+	 * @param document
+	 *            the document to scan.
+	 */
+	public JavaHeuristicScanner(IDocument document) {
+		this(document, IJavaPartitions.JAVA_PARTITIONING, IDocument.DEFAULT_CONTENT_TYPE);
+	}
+
+	/**
+	 * Returns the most recent internal scan position.
+	 * 
+	 * @return the most recent internal scan position.
+	 */
+	public int getPosition() {
+		return fPos;
+	}
+
+	/**
+	 * Returns the next token in forward direction, starting at
+	 * <code>start</code>, and not extending further than
+	 * <code>bound</code>. The return value is one of the constants defined
+	 * in {@link Symbols}. After a call, {@link #getPosition()} will return
+	 * the position just after the scanned token (i.e. the next position that
+	 * will be scanned).
+	 * 
+	 * @param start
+	 *            the first character position in the document to consider
+	 * @param bound
+	 *            the first position not to consider any more
+	 * @return a constant from {@link Symbols} describing the next token
+	 */
+	public int nextToken(int start, int bound) {
+		int pos = scanForward(start, bound, fNonWSDefaultPart);
+		if (pos == NOT_FOUND)
+			return TokenEOF;
+
+		fPos++;
+
+		switch (fChar) {
+			case LBRACE :
+				return TokenLBRACE;
+			case RBRACE :
+				return TokenRBRACE;
+			case LBRACKET :
+				return TokenLBRACKET;
+			case RBRACKET :
+				return TokenRBRACKET;
+			case LPAREN :
+				return TokenLPAREN;
+			case RPAREN :
+				return TokenRPAREN;
+			case SEMICOLON :
+				return TokenSEMICOLON;
+			case COMMA :
+				return TokenCOMMA;
+			case QUESTIONMARK :
+				return TokenQUESTIONMARK;
+			case EQUAL :
+				return TokenEQUAL;
+			case LANGLE :
+				return TokenLESSTHAN;
+			case RANGLE :
+				return TokenGREATERTHAN;
+		}
+
+		// else
+		if (Character.isJavaIdentifierPart(fChar)) {
+			// assume an ident or keyword
+			int from = pos, to;
+			pos = scanForward(pos + 1, bound, fNonIdent);
+			if (pos == NOT_FOUND)
+				to = bound == UNBOUND ? fDocument.getLength() : bound;
+			else
+				to = pos;
+
+			String identOrKeyword;
+			try {
+				identOrKeyword = fDocument.get(from, to - from);
+			}
+			catch (BadLocationException e) {
+				return TokenEOF;
+			}
+
+			return getToken(identOrKeyword);
+
+
+		}
+		else {
+			// operators, number literals etc
+			return TokenOTHER;
+		}
+	}
+
+	/**
+	 * Returns the next token in backward direction, starting at
+	 * <code>start</code>, and not extending further than
+	 * <code>bound</code>. The return value is one of the constants defined
+	 * in {@link Symbols}. After a call, {@link #getPosition()} will return
+	 * the position just before the scanned token starts (i.e. the next
+	 * position that will be scanned).
+	 * 
+	 * @param start
+	 *            the first character position in the document to consider
+	 * @param bound
+	 *            the first position not to consider any more
+	 * @return a constant from {@link Symbols} describing the previous token
+	 */
+	public int previousToken(int start, int bound) {
+		int pos = scanBackward(start, bound, fNonWSDefaultPart);
+		if (pos == NOT_FOUND)
+			return TokenEOF;
+
+		fPos--;
+
+		switch (fChar) {
+			case LBRACE :
+				return TokenLBRACE;
+			case RBRACE :
+				return TokenRBRACE;
+			case LBRACKET :
+				return TokenLBRACKET;
+			case RBRACKET :
+				return TokenRBRACKET;
+			case LPAREN :
+				return TokenLPAREN;
+			case RPAREN :
+				return TokenRPAREN;
+			case SEMICOLON :
+				return TokenSEMICOLON;
+			case COLON :
+				return TokenCOLON;
+			case COMMA :
+				return TokenCOMMA;
+			case QUESTIONMARK :
+				return TokenQUESTIONMARK;
+			case EQUAL :
+				return TokenEQUAL;
+			case LANGLE :
+				return TokenLESSTHAN;
+			case RANGLE :
+				return TokenGREATERTHAN;
+		}
+
+		// else
+		if (Character.isJavaIdentifierPart(fChar)) {
+			// assume an ident or keyword
+			int from, to = pos + 1;
+			pos = scanBackward(pos - 1, bound, fNonIdent);
+			if (pos == NOT_FOUND)
+				from = bound == UNBOUND ? 0 : bound + 1;
+			else
+				from = pos + 1;
+
+			String identOrKeyword;
+			try {
+				identOrKeyword = fDocument.get(from, to - from);
+			}
+			catch (BadLocationException e) {
+				return TokenEOF;
+			}
+
+			return getToken(identOrKeyword);
+
+
+		}
+		else {
+			// operators, number literals etc
+			return TokenOTHER;
+		}
+
+	}
+
+	/**
+	 * Returns one of the keyword constants or <code>TokenIDENT</code> for a
+	 * scanned identifier.
+	 * 
+	 * @param s
+	 *            a scanned identifier
+	 * @return one of the constants defined in {@link Symbols}
+	 */
+	private int getToken(String s) {
+		Assert.isNotNull(s);
+
+		switch (s.length()) {
+			case 2 :
+				if ("if".equals(s)) //$NON-NLS-1$
+					return TokenIF;
+				if ("do".equals(s)) //$NON-NLS-1$
+					return TokenDO;
+				break;
+			case 3 :
+				if ("for".equals(s)) //$NON-NLS-1$
+					return TokenFOR;
+				if ("try".equals(s)) //$NON-NLS-1$
+					return TokenTRY;
+				if ("new".equals(s)) //$NON-NLS-1$
+					return TokenNEW;
+				break;
+			case 4 :
+				if ("case".equals(s)) //$NON-NLS-1$
+					return TokenCASE;
+				if ("else".equals(s)) //$NON-NLS-1$
+					return TokenELSE;
+				if ("enum".equals(s)) //$NON-NLS-1$
+					return TokenENUM;
+				if ("goto".equals(s)) //$NON-NLS-1$
+					return TokenGOTO;
+				break;
+			case 5 :
+				if ("break".equals(s)) //$NON-NLS-1$
+					return TokenBREAK;
+				if ("catch".equals(s)) //$NON-NLS-1$
+					return TokenCATCH;
+				if ("class".equals(s)) //$NON-NLS-1$
+					return TokenCLASS;
+				if ("while".equals(s)) //$NON-NLS-1$
+					return TokenWHILE;
+				break;
+			case 6 :
+				if ("return".equals(s)) //$NON-NLS-1$
+					return TokenRETURN;
+				if ("static".equals(s)) //$NON-NLS-1$
+					return TokenSTATIC;
+				if ("switch".equals(s)) //$NON-NLS-1$
+					return TokenSWITCH;
+				break;
+			case 7 :
+				if ("default".equals(s)) //$NON-NLS-1$
+					return TokenDEFAULT;
+				if ("finally".equals(s)) //$NON-NLS-1$
+					return TokenFINALLY;
+				break;
+			case 9 :
+				if ("interface".equals(s)) //$NON-NLS-1$
+					return TokenINTERFACE;
+				break;
+			case 12 :
+				if ("synchronized".equals(s)) //$NON-NLS-1$
+					return TokenSYNCHRONIZED;
+				break;
+		}
+		return TokenIDENT;
+	}
+
+	/**
+	 * Returns the position of the closing peer character (forward search).
+	 * Any scopes introduced by opening peers are skipped. All peers accounted
+	 * for must reside in the default partition.
+	 * 
+	 * <p>
+	 * Note that <code>start</code> must not point to the opening peer, but
+	 * to the first character being searched.
+	 * </p>
+	 * 
+	 * @param start
+	 *            the start position
+	 * @param openingPeer
+	 *            the opening peer character (e.g. '{')
+	 * @param closingPeer
+	 *            the closing peer character (e.g. '}')
+	 * @return the matching peer character position, or <code>NOT_FOUND</code>
+	 */
+	public int findClosingPeer(int start, final char openingPeer, final char closingPeer) {
+		Assert.isNotNull(fDocument);
+		Assert.isTrue(start >= 0);
+
+		try {
+			int depth = 1;
+			start -= 1;
+			while (true) {
+				start = scanForward(start + 1, UNBOUND, new CharacterMatch(new char[]{openingPeer, closingPeer}));
+				if (start == NOT_FOUND)
+					return NOT_FOUND;
+
+				if (fDocument.getChar(start) == openingPeer)
+					depth++;
+				else
+					depth--;
+
+				if (depth == 0)
+					return start;
+			}
+
+		}
+		catch (BadLocationException e) {
+			return NOT_FOUND;
+		}
+	}
+
+	/**
+	 * Returns the position of the opening peer character (backward search).
+	 * Any scopes introduced by closing peers are skipped. All peers accounted
+	 * for must reside in the default partition.
+	 * 
+	 * <p>
+	 * Note that <code>start</code> must not point to the closing peer, but
+	 * to the first character being searched.
+	 * </p>
+	 * 
+	 * @param start
+	 *            the start position
+	 * @param openingPeer
+	 *            the opening peer character (e.g. '{')
+	 * @param closingPeer
+	 *            the closing peer character (e.g. '}')
+	 * @return the matching peer character position, or <code>NOT_FOUND</code>
+	 */
+	public int findOpeningPeer(int start, char openingPeer, char closingPeer) {
+		Assert.isTrue(start < fDocument.getLength());
+
+		try {
+			int depth = 1;
+			start += 1;
+			while (true) {
+				start = scanBackward(start - 1, UNBOUND, new CharacterMatch(new char[]{openingPeer, closingPeer}));
+				if (start == NOT_FOUND)
+					return NOT_FOUND;
+
+				if (fDocument.getChar(start) == closingPeer)
+					depth++;
+				else
+					depth--;
+
+				if (depth == 0)
+					return start;
+			}
+
+		}
+		catch (BadLocationException e) {
+			return NOT_FOUND;
+		}
+	}
+
+	/**
+	 * Computes the surrounding block around <code>offset</code>. The
+	 * search is started at the beginning of <code>offset</code>, i.e. an
+	 * opening brace at <code>offset</code> will not be part of the
+	 * surrounding block, but a closing brace will.
+	 * 
+	 * @param offset
+	 *            the offset for which the surrounding block is computed
+	 * @return a region describing the surrounding block, or <code>null</code>
+	 *         if none can be found
+	 */
+	public IRegion findSurroundingBlock(int offset) {
+		if (offset < 1 || offset >= fDocument.getLength())
+			return null;
+
+		int begin = findOpeningPeer(offset - 1, LBRACE, RBRACE);
+		int end = findClosingPeer(offset, LBRACE, RBRACE);
+		if (begin == NOT_FOUND || end == NOT_FOUND)
+			return null;
+		return new Region(begin, end + 1 - begin);
+	}
+
+	/**
+	 * Finds the smallest position in <code>fDocument</code> such that the
+	 * position is &gt;= <code>position</code> and &lt; <code>bound</code>
+	 * and <code>Character.isWhitespace(fDocument.getChar(pos))</code>
+	 * evaluates to <code>false</code> and the position is in the default
+	 * partition.
+	 * 
+	 * @param position
+	 *            the first character position in <code>fDocument</code> to
+	 *            be considered
+	 * @param bound
+	 *            the first position in <code>fDocument</code> to not
+	 *            consider any more, with <code>bound</code> &gt;
+	 *            <code>position</code>, or <code>UNBOUND</code>
+	 * @return the smallest position of a non-whitespace character in [<code>position</code>,
+	 *         <code>bound</code>) that resides in a Java partition, or
+	 *         <code>NOT_FOUND</code> if none can be found
+	 */
+	public int findNonWhitespaceForward(int position, int bound) {
+		return scanForward(position, bound, fNonWSDefaultPart);
+	}
+
+	/**
+	 * Finds the smallest position in <code>fDocument</code> such that the
+	 * position is &gt;= <code>position</code> and &lt; <code>bound</code>
+	 * and <code>Character.isWhitespace(fDocument.getChar(pos))</code>
+	 * evaluates to <code>false</code>.
+	 * 
+	 * @param position
+	 *            the first character position in <code>fDocument</code> to
+	 *            be considered
+	 * @param bound
+	 *            the first position in <code>fDocument</code> to not
+	 *            consider any more, with <code>bound</code> &gt;
+	 *            <code>position</code>, or <code>UNBOUND</code>
+	 * @return the smallest position of a non-whitespace character in [<code>position</code>,
+	 *         <code>bound</code>), or <code>NOT_FOUND</code> if none can
+	 *         be found
+	 */
+	public int findNonWhitespaceForwardInAnyPartition(int position, int bound) {
+		return scanForward(position, bound, fNonWS);
+	}
+
+	/**
+	 * Finds the highest position in <code>fDocument</code> such that the
+	 * position is &lt;= <code>position</code> and &gt; <code>bound</code>
+	 * and <code>Character.isWhitespace(fDocument.getChar(pos))</code>
+	 * evaluates to <code>false</code> and the position is in the default
+	 * partition.
+	 * 
+	 * @param position
+	 *            the first character position in <code>fDocument</code> to
+	 *            be considered
+	 * @param bound
+	 *            the first position in <code>fDocument</code> to not
+	 *            consider any more, with <code>bound</code> &lt;
+	 *            <code>position</code>, or <code>UNBOUND</code>
+	 * @return the highest position of a non-whitespace character in (<code>bound</code>,
+	 *         <code>position</code>] that resides in a Java partition, or
+	 *         <code>NOT_FOUND</code> if none can be found
+	 */
+	public int findNonWhitespaceBackward(int position, int bound) {
+		return scanBackward(position, bound, fNonWSDefaultPart);
+	}
+
+	/**
+	 * Finds the lowest position <code>p</code> in <code>fDocument</code>
+	 * such that <code>start</code> &lt;= p &lt; <code>bound</code> and
+	 * <code>condition.stop(fDocument.getChar(p), p)</code> evaluates to
+	 * <code>true</code>.
+	 * 
+	 * @param start
+	 *            the first character position in <code>fDocument</code> to
+	 *            be considered
+	 * @param bound
+	 *            the first position in <code>fDocument</code> to not
+	 *            consider any more, with <code>bound</code> &gt;
+	 *            <code>start</code>, or <code>UNBOUND</code>
+	 * @param condition
+	 *            the <code>StopCondition</code> to check
+	 * @return the lowest position in [<code>start</code>,
+	 *         <code>bound</code>) for which <code>condition</code>
+	 *         holds, or <code>NOT_FOUND</code> if none can be found
+	 */
+	public int scanForward(int start, int bound, StopCondition condition) {
+		Assert.isTrue(start >= 0);
+
+		if (bound == UNBOUND)
+			bound = fDocument.getLength();
+
+		Assert.isTrue(bound <= fDocument.getLength());
+
+		try {
+			fPos = start;
+			while (fPos < bound) {
+
+				fChar = fDocument.getChar(fPos);
+				if (condition.stop(fChar, fPos, true))
+					return fPos;
+
+				fPos = condition.nextPosition(fPos, true);
+			}
+		}
+		catch (BadLocationException e) {
+		}
+		return NOT_FOUND;
+	}
+
+
+	/**
+	 * Finds the lowest position in <code>fDocument</code> such that the
+	 * position is &gt;= <code>position</code> and &lt; <code>bound</code>
+	 * and <code>fDocument.getChar(position) == ch</code> evaluates to
+	 * <code>true</code> and the position is in the default partition.
+	 * 
+	 * @param position
+	 *            the first character position in <code>fDocument</code> to
+	 *            be considered
+	 * @param bound
+	 *            the first position in <code>fDocument</code> to not
+	 *            consider any more, with <code>bound</code> &gt;
+	 *            <code>position</code>, or <code>UNBOUND</code>
+	 * @param ch
+	 *            the <code>char</code> to search for
+	 * @return the lowest position of <code>ch</code> in (<code>bound</code>,
+	 *         <code>position</code>] that resides in a Java partition, or
+	 *         <code>NOT_FOUND</code> if none can be found
+	 */
+	public int scanForward(int position, int bound, char ch) {
+		return scanForward(position, bound, new CharacterMatch(ch));
+	}
+
+	/**
+	 * Finds the lowest position in <code>fDocument</code> such that the
+	 * position is &gt;= <code>position</code> and &lt; <code>bound</code>
+	 * and <code>fDocument.getChar(position) == ch</code> evaluates to
+	 * <code>true</code> for at least one ch in <code>chars</code> and the
+	 * position is in the default partition.
+	 * 
+	 * @param position
+	 *            the first character position in <code>fDocument</code> to
+	 *            be considered
+	 * @param bound
+	 *            the first position in <code>fDocument</code> to not
+	 *            consider any more, with <code>bound</code> &gt;
+	 *            <code>position</code>, or <code>UNBOUND</code>
+	 * @param chars
+	 *            an array of <code>char</code> to search for
+	 * @return the lowest position of a non-whitespace character in [<code>position</code>,
+	 *         <code>bound</code>) that resides in a Java partition, or
+	 *         <code>NOT_FOUND</code> if none can be found
+	 */
+	public int scanForward(int position, int bound, char[] chars) {
+		return scanForward(position, bound, new CharacterMatch(chars));
+	}
+
+	/**
+	 * Finds the highest position <code>p</code> in <code>fDocument</code>
+	 * such that <code>bound</code> &lt; <code>p</code> &lt;=
+	 * <code>start</code> and
+	 * <code>condition.stop(fDocument.getChar(p), p)</code> evaluates to
+	 * <code>true</code>.
+	 * 
+	 * @param start
+	 *            the first character position in <code>fDocument</code> to
+	 *            be considered
+	 * @param bound
+	 *            the first position in <code>fDocument</code> to not
+	 *            consider any more, with <code>bound</code> &lt;
+	 *            <code>start</code>, or <code>UNBOUND</code>
+	 * @param condition
+	 *            the <code>StopCondition</code> to check
+	 * @return the highest position in (<code>bound</code>,
+	 *         <code>start</code> for which <code>condition</code> holds,
+	 *         or <code>NOT_FOUND</code> if none can be found
+	 */
+	public int scanBackward(int start, int bound, StopCondition condition) {
+		if (bound == UNBOUND)
+			bound = -1;
+
+		Assert.isTrue(bound >= -1);
+		Assert.isTrue(start < fDocument.getLength());
+
+		try {
+			fPos = start;
+			while (fPos > bound) {
+
+				fChar = fDocument.getChar(fPos);
+				if (condition.stop(fChar, fPos, false))
+					return fPos;
+
+				fPos = condition.nextPosition(fPos, false);
+			}
+		}
+		catch (BadLocationException e) {
+		}
+		return NOT_FOUND;
+	}
+
+	/**
+	 * Finds the highest position in <code>fDocument</code> such that the
+	 * position is &lt;= <code>position</code> and &gt; <code>bound</code>
+	 * and <code>fDocument.getChar(position) == ch</code> evaluates to
+	 * <code>true</code> for at least one ch in <code>chars</code> and the
+	 * position is in the default partition.
+	 * 
+	 * @param position
+	 *            the first character position in <code>fDocument</code> to
+	 *            be considered
+	 * @param bound
+	 *            the first position in <code>fDocument</code> to not
+	 *            consider any more, with <code>bound</code> &lt;
+	 *            <code>position</code>, or <code>UNBOUND</code>
+	 * @param ch
+	 *            the <code>char</code> to search for
+	 * @return the highest position of one element in <code>chars</code> in (<code>bound</code>,
+	 *         <code>position</code>] that resides in a Java partition, or
+	 *         <code>NOT_FOUND</code> if none can be found
+	 */
+	public int scanBackward(int position, int bound, char ch) {
+		return scanBackward(position, bound, new CharacterMatch(ch));
+	}
+
+	/**
+	 * Finds the highest position in <code>fDocument</code> such that the
+	 * position is &lt;= <code>position</code> and &gt; <code>bound</code>
+	 * and <code>fDocument.getChar(position) == ch</code> evaluates to
+	 * <code>true</code> for at least one ch in <code>chars</code> and the
+	 * position is in the default partition.
+	 * 
+	 * @param position
+	 *            the first character position in <code>fDocument</code> to
+	 *            be considered
+	 * @param bound
+	 *            the first position in <code>fDocument</code> to not
+	 *            consider any more, with <code>bound</code> &lt;
+	 *            <code>position</code>, or <code>UNBOUND</code>
+	 * @param chars
+	 *            an array of <code>char</code> to search for
+	 * @return the highest position of one element in <code>chars</code> in (<code>bound</code>,
+	 *         <code>position</code>] that resides in a Java partition, or
+	 *         <code>NOT_FOUND</code> if none can be found
+	 */
+	public int scanBackward(int position, int bound, char[] chars) {
+		return scanBackward(position, bound, new CharacterMatch(chars));
+	}
+
+	/**
+	 * Checks whether <code>position</code> resides in a default (Java)
+	 * partition of <code>fDocument</code>.
+	 * 
+	 * @param position
+	 *            the position to be checked
+	 * @return <code>true</code> if <code>position</code> is in the
+	 *         default partition of <code>fDocument</code>,
+	 *         <code>false</code> otherwise
+	 */
+	public boolean isDefaultPartition(int position) {
+		Assert.isTrue(position >= 0);
+		Assert.isTrue(position <= fDocument.getLength());
+
+		try {
+			return fPartition.equals(TextUtilities.getContentType(fDocument, fPartitioning, position, false));
+		}
+		catch (BadLocationException e) {
+			return false;
+		}
+	}
+
+	/**
+	 * Returns the partition at <code>position</code>.
+	 * 
+	 * @param position
+	 *            the position to get the partition for
+	 * @return the partition at <code>position</code> or a dummy zero-length
+	 *         partition if accessing the document fails
+	 */
+	private ITypedRegion getPartition(int position) {
+		Assert.isTrue(position >= 0);
+		Assert.isTrue(position <= fDocument.getLength());
+
+		try {
+			return TextUtilities.getPartition(fDocument, fPartitioning, position, false);
+		}
+		catch (BadLocationException e) {
+			return new TypedRegion(position, 0, "__no_partition_at_all"); //$NON-NLS-1$
+		}
+
+	}
+
+	/**
+	 * Checks if the line seems to be an open condition not followed by a
+	 * block (i.e. an if, while, or for statement with just one following
+	 * statement, see example below).
+	 * 
+	 * <pre>
+	 * if (condition)
+	 * 	doStuff();
+	 * </pre>
+	 * 
+	 * <p>
+	 * Algorithm: if the last non-WS, non-Comment code on the line is an if
+	 * (condition), while (condition), for( expression), do, else, and there
+	 * is no statement after that
+	 * </p>
+	 * 
+	 * @param position
+	 *            the insert position of the new character
+	 * @param bound
+	 *            the lowest position to consider
+	 * @return <code>true</code> if the code is a conditional statement or
+	 *         loop without a block, <code>false</code> otherwise
+	 */
+	public boolean isBracelessBlockStart(int position, int bound) {
+		if (position < 1)
+			return false;
+
+		switch (previousToken(position, bound)) {
+			case TokenDO :
+			case TokenELSE :
+				return true;
+			case TokenRPAREN :
+				position = findOpeningPeer(fPos, LPAREN, RPAREN);
+				if (position > 0) {
+					switch (previousToken(position - 1, bound)) {
+						case TokenIF :
+						case TokenFOR :
+						case TokenWHILE :
+							return true;
+					}
+				}
+		}
+
+		return false;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/text/JavaPairMatcher.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/text/JavaPairMatcher.java
new file mode 100644
index 0000000..020769f
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/text/JavaPairMatcher.java
@@ -0,0 +1,277 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.text;
+
+// taken from package org.eclipse.jdt.ui.text;
+
+import java.io.IOException;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jface.text.source.ICharacterPairMatcher;
+
+class JavaPairMatcher implements ICharacterPairMatcher {
+
+	protected char[] fPairs;
+	protected IDocument fDocument;
+	protected int fOffset;
+
+	protected int fStartPos;
+	protected int fEndPos;
+	protected int fAnchor;
+
+	protected JavaCodeReader fReader = new JavaCodeReader();
+	/**
+	 * Stores the source version state.
+	 * 
+	 * @see Eclipse  3.1
+	 */
+	private boolean fHighlightAngularBrackets = false;
+
+
+	public JavaPairMatcher(char[] pairs) {
+		fPairs = pairs;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.source.ICharacterPairMatcher#match(org.eclipse.jface.text.IDocument,
+	 *      int)
+	 */
+	public IRegion match(IDocument document, int offset) {
+		fOffset = offset;
+
+		if(offset < 0 || offset >= document.getLength())
+			return null;
+
+		fDocument = document;
+
+		if (fDocument != null && matchPairsAt() && fStartPos != fEndPos)
+			return new Region(fStartPos, fEndPos - fStartPos + 1);
+
+		return null;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.source.ICharacterPairMatcher#getAnchor()
+	 */
+	public int getAnchor() {
+		return fAnchor;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.source.ICharacterPairMatcher#dispose()
+	 */
+	public void dispose() {
+		clear();
+		fDocument = null;
+		fReader = null;
+	}
+
+	/*
+	 * @see org.eclipse.jface.text.source.ICharacterPairMatcher#clear()
+	 */
+	public void clear() {
+		if (fReader != null) {
+			try {
+				fReader.close();
+			}
+			catch (IOException x) {
+				// ignore
+			}
+		}
+	}
+
+	protected boolean matchPairsAt() {
+
+		int i;
+		int pairIndex1 = fPairs.length;
+		int pairIndex2 = fPairs.length;
+
+		fStartPos = -1;
+		fEndPos = -1;
+
+		// get the chars preceding and following the start position
+		try {
+
+			char prevChar = fDocument.getChar(Math.max(fOffset - 1, 0));
+			// modified behavior for
+			// http://dev.eclipse.org/bugs/show_bug.cgi?id=16879
+			// char nextChar= fDocument.getChar(fOffset);
+
+			// search for opening peer character next to the activation point
+			for (i = 0; i < fPairs.length; i = i + 2) {
+				// if (nextChar == fPairs[i]) {
+				// fStartPos= fOffset;
+				// pairIndex1= i;
+				// } else
+				if (prevChar == fPairs[i]) {
+					fStartPos = fOffset - 1;
+					pairIndex1 = i;
+				}
+			}
+
+			// search for closing peer character next to the activation point
+			for (i = 1; i < fPairs.length; i = i + 2) {
+				if (prevChar == fPairs[i]) {
+					fEndPos = fOffset - 1;
+					pairIndex2 = i;
+				}
+				// else if (nextChar == fPairs[i]) {
+				// fEndPos= fOffset;
+				// pairIndex2= i;
+				// }
+			}
+
+			if (fEndPos > -1) {
+				fAnchor = RIGHT;
+				fStartPos = searchForOpeningPeer(fEndPos, fPairs[pairIndex2 - 1], fPairs[pairIndex2], fDocument);
+				if (fStartPos > -1)
+					return true;
+				else
+					fEndPos = -1;
+			}
+			else if (fStartPos > -1) {
+				fAnchor = LEFT;
+				fEndPos = searchForClosingPeer(fStartPos, fPairs[pairIndex1], fPairs[pairIndex1 + 1], fDocument);
+				if (fEndPos > -1)
+					return true;
+				else
+					fStartPos = -1;
+			}
+
+		}
+		catch (BadLocationException x) {
+		}
+		catch (IOException x) {
+		}
+
+		return false;
+	}
+
+	protected int searchForClosingPeer(int offset, int openingPeer, int closingPeer, IDocument document) throws IOException {
+		if (openingPeer == '<' && !(fHighlightAngularBrackets && isTypeParameterBracket(offset, document)))
+			return -1;
+
+		fReader.configureForwardReader(document, offset + 1, document.getLength(), true, true);
+
+		int stack = 1;
+		int c = fReader.read();
+		while (c != JavaCodeReader.EOF) {
+			if (c == openingPeer && c != closingPeer)
+				stack++;
+			else if (c == closingPeer)
+				stack--;
+
+			if (stack == 0)
+				return fReader.getOffset();
+
+			c = fReader.read();
+		}
+
+		return -1;
+	}
+
+
+	protected int searchForOpeningPeer(int offset, int openingPeer, int closingPeer, IDocument document) throws IOException {
+		if (openingPeer == '<' && !fHighlightAngularBrackets)
+			return -1;
+
+		fReader.configureBackwardReader(document, offset, true, true);
+
+		int stack = 1;
+		int c = fReader.read();
+		while (c != JavaCodeReader.EOF) {
+			if (c == closingPeer && c != openingPeer)
+				stack++;
+			else if (c == openingPeer)
+				stack--;
+
+			if (stack == 0) {
+				if (closingPeer == '>' && !isTypeParameterBracket(fReader.getOffset(), document))
+					return -1;
+				return fReader.getOffset();
+			}
+
+			c = fReader.read();
+		}
+
+		return -1;
+	}
+
+	/**
+	 * Checks if the angular bracket at <code>offset</code> is a type
+	 * parameter bracket.
+	 * 
+	 * @param offset
+	 *            the offset of the opening bracket
+	 * @param document
+	 *            the document
+	 * @return <code>true</code> if the bracket is part of a type parameter,
+	 *         <code>false</code> otherwise
+	 * @see Eclipse  3.1
+	 */
+	private boolean isTypeParameterBracket(int offset, IDocument document) {
+		/*
+		 * type parameter come after braces (closing or opening), semicolons,
+		 * or after a Type name (heuristic: starts with capital character, or
+		 * after a modifier keyword in a method declaration (visibility,
+		 * static, synchronized, final)
+		 */
+
+		try {
+			IRegion line = document.getLineInformationOfOffset(offset);
+
+			JavaHeuristicScanner scanner = new JavaHeuristicScanner(document);
+			int prevToken = scanner.previousToken(offset - 1, line.getOffset());
+			int prevTokenOffset = scanner.getPosition() + 1;
+			String previous = prevToken == Symbols.TokenEOF ? null : document.get(prevTokenOffset, offset - prevTokenOffset).trim();
+
+			if (prevToken == Symbols.TokenLBRACE || prevToken == Symbols.TokenRBRACE || prevToken == Symbols.TokenSEMICOLON || prevToken == Symbols.TokenSYNCHRONIZED || prevToken == Symbols.TokenSTATIC || (prevToken == Symbols.TokenIDENT && isTypeParameterIntroducer(previous)) || prevToken == Symbols.TokenEOF)
+				return true;
+		}
+		catch (BadLocationException e) {
+			return false;
+		}
+
+		return false;
+	}
+
+	/**
+	 * Returns <code>true</code> if <code>identifier</code> is an
+	 * identifier that could come right before a type parameter list. It uses
+	 * a heuristic: if the identifier starts with an upper case, it is assumed
+	 * a type name. Also, if <code>identifier</code> is a method modifier,
+	 * it is assumed that the angular bracket is part of the generic type
+	 * parameter of a method.
+	 * 
+	 * @param identifier
+	 *            the identifier to check
+	 * @return <code>true</code> if the identifier could introduce a type
+	 *         parameter list
+	 * @see Eclipse  3.1
+	 */
+	private boolean isTypeParameterIntroducer(String identifier) {
+		return identifier.length() > 0 && (Character.isUpperCase(identifier.charAt(0)) || identifier.startsWith("final") //$NON-NLS-1$
+					|| identifier.startsWith("public") //$NON-NLS-1$
+					|| identifier.startsWith("public") //$NON-NLS-1$
+					|| identifier.startsWith("protected") //$NON-NLS-1$
+		|| identifier.startsWith("private")); //$NON-NLS-1$
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/text/Symbols.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/text/Symbols.java
new file mode 100644
index 0000000..1b203e3
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/text/Symbols.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.text;
+
+// taken from package org.eclipse.jdt.ui.text;
+
+/**
+ * Symbols for the heuristic java scanner.
+ * 
+ * @see Eclipse 3.0
+ */
+interface Symbols {
+	int TokenEOF = -1;
+	int TokenLBRACE = 1;
+	int TokenRBRACE = 2;
+	int TokenLBRACKET = 3;
+	int TokenRBRACKET = 4;
+	int TokenLPAREN = 5;
+	int TokenRPAREN = 6;
+	int TokenSEMICOLON = 7;
+	int TokenOTHER = 8;
+	int TokenCOLON = 9;
+	int TokenQUESTIONMARK = 10;
+	int TokenCOMMA = 11;
+	int TokenEQUAL = 12;
+	int TokenLESSTHAN = 13;
+	int TokenGREATERTHAN = 14;
+	int TokenIF = 109;
+	int TokenDO = 1010;
+	int TokenFOR = 1011;
+	int TokenTRY = 1012;
+	int TokenCASE = 1013;
+	int TokenELSE = 1014;
+	int TokenBREAK = 1015;
+	int TokenCATCH = 1016;
+	int TokenWHILE = 1017;
+	int TokenRETURN = 1018;
+	int TokenSTATIC = 1019;
+	int TokenSWITCH = 1020;
+	int TokenFINALLY = 1021;
+	int TokenSYNCHRONIZED = 1022;
+	int TokenGOTO = 1023;
+	int TokenDEFAULT = 1024;
+	int TokenNEW = 1025;
+	int TokenCLASS = 1026;
+	int TokenINTERFACE = 1027;
+	int TokenENUM = 1028;
+	int TokenIDENT = 2000;
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/wizard/FacetModuleCoreSupport.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/wizard/FacetModuleCoreSupport.java
new file mode 100644
index 0000000..fa1ab95
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/wizard/FacetModuleCoreSupport.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.wizard;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.IPath;
+
+/**
+ * This class encapsulates any used Module Core and Facets APIs along with
+ * fallbacks for use on non-compliant projects and when those services are not
+ * available at runtime.
+ * 
+ * Because ModuleCore API calls can result in locks needing to be acquired,
+ * none of these methods should be called while other thread locks have
+ * already been acquired.
+ */
+final class FacetModuleCoreSupport {
+	static final boolean _dump_NCDFE = false;
+
+	/**
+	 * @param project
+	 * @return the IPath to the "root" of the web contents
+	 */
+	public static IPath getWebContentRootPath(IProject project) {
+		if (project == null)
+			return null;
+		IPath path = null;
+		try {
+			path = FacetModuleCoreSupportDelegate.getWebContentRootPath(project);
+		}
+		catch (NoClassDefFoundError e) {
+			if (_dump_NCDFE)
+				e.printStackTrace();
+		}
+		return path;
+	}
+
+	/**
+	 * @param project
+	 * @return
+	 * @throws org.eclipse.core.runtime.CoreException
+	 */
+	public static boolean isWebProject(IProject project) {
+		if (project == null)
+			return false;
+		try {
+			return FacetModuleCoreSupportDelegate.isWebProject(project);
+		}
+		catch (NoClassDefFoundError e) {
+			if (_dump_NCDFE)
+				e.printStackTrace();
+		}
+		return true;
+	}
+
+
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/wizard/FacetModuleCoreSupportDelegate.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/wizard/FacetModuleCoreSupportDelegate.java
new file mode 100644
index 0000000..ab5484e
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/wizard/FacetModuleCoreSupportDelegate.java
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.wizard;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.wst.common.componentcore.ComponentCore;
+import org.eclipse.wst.common.componentcore.ModuleCoreNature;
+import org.eclipse.wst.common.componentcore.resources.IVirtualComponent;
+import org.eclipse.wst.common.project.facet.core.IFacetedProject;
+import org.eclipse.wst.common.project.facet.core.IProjectFacet;
+import org.eclipse.wst.common.project.facet.core.ProjectFacetsManager;
+import org.eclipse.wst.html.ui.internal.Logger;
+
+/**
+ * Wrapper class for all Facet-related calls. If the Facet or ModuleCore
+ * bundles are not available, this class will not load, or if it does, its
+ * methods will cause NoClassDefFoundErrors. This allows us to
+ * compartmentalize the dependencies.
+ * 
+ */
+final class FacetModuleCoreSupportDelegate {
+	/**
+	 * Copied to avoid unneeded extra dependency (plus it's unclear why the
+	 * value is in that plug-in).
+	 * 
+	 * @see org.eclipse.wst.common.componentcore.internal.util.IModuleConstants.JST_WEB_MODULE
+	 */
+	private final static String JST_WEB_MODULE = "jst.web"; //$NON-NLS-1$
+
+	private final static String WST_WEB_MODULE = "wst.web"; //$NON-NLS-1$
+
+	/**
+	 * @param project
+	 * @return the IPath to the "root" of the web contents
+	 */
+	static IPath getWebContentRootPath(IProject project) {
+		if (!ModuleCoreNature.isFlexibleProject(project))
+			return project.getFullPath();
+
+		IPath path = null;
+		IVirtualComponent component = ComponentCore.createComponent(project);
+		if (component != null && component.exists()) {
+			path = component.getRootFolder().getWorkspaceRelativePath();
+		}
+		else {
+			path = project.getFullPath();
+		}
+		return path;
+	}
+
+	/**
+	 * @param project
+	 * @return
+	 * @throws CoreException
+	 */
+	static boolean isWebProject(IProject project) {
+		boolean is = false;
+		try {
+			IFacetedProject faceted = ProjectFacetsManager.create(project);
+			if (ProjectFacetsManager.isProjectFacetDefined(JST_WEB_MODULE)) {
+				IProjectFacet facet = ProjectFacetsManager.getProjectFacet(JST_WEB_MODULE);
+				is = is || (faceted != null && faceted.hasProjectFacet(facet));
+			}
+			if (ProjectFacetsManager.isProjectFacetDefined(WST_WEB_MODULE)) {
+				IProjectFacet facet = ProjectFacetsManager.getProjectFacet(WST_WEB_MODULE);
+				is = is || (faceted != null && faceted.hasProjectFacet(facet));
+			}
+		}
+		catch (CoreException e) {
+			Logger.logException(e);
+		}
+		return is;
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/wizard/NewHTMLFileWizardPage.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/wizard/NewHTMLFileWizardPage.java
new file mode 100644
index 0000000..110d800
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/wizard/NewHTMLFileWizardPage.java
@@ -0,0 +1,224 @@
+/*******************************************************************************
+ * Copyright (c) 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.wizard;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.core.runtime.content.IContentType;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.ui.dialogs.WizardNewFileCreationPage;
+import org.eclipse.wst.html.core.internal.HTMLCorePlugin;
+import org.eclipse.wst.html.core.internal.preferences.HTMLCorePreferenceNames;
+import org.eclipse.wst.html.core.internal.provisional.contenttype.ContentTypeIdForHTML;
+import org.eclipse.wst.html.ui.internal.HTMLUIMessages;
+
+class NewHTMLFileWizardPage extends WizardNewFileCreationPage {
+
+	private IContentType fContentType;
+	private List fValidExtensions = null;
+	
+	public NewHTMLFileWizardPage(String pageName, IStructuredSelection selection) {
+        super(pageName, selection);
+    }
+	
+	/**
+	 * This method is overriden to set the selected folder to web contents 
+	 * folder if the current selection is outside the web contents folder. 
+	 */
+	protected void initialPopulateContainerNameField() {
+		super.initialPopulateContainerNameField();
+		
+		IPath fullPath = getContainerFullPath();
+		IProject project = getProjectFromPath(fullPath);
+		IPath webContentPath = getWebContentPath(project);
+		
+		if (webContentPath != null && !webContentPath.isPrefixOf(fullPath)) {
+			setContainerFullPath(webContentPath);
+		}
+	}
+	
+	/**
+	 * This method is overriden to set additional validation specific to 
+	 * html files. 
+	 */
+	protected boolean validatePage() {
+		setMessage(null);
+		setErrorMessage(null);
+		
+		if (!super.validatePage()) {
+			return false;
+		}
+		
+		String fileName = getFileName();
+		IPath fullPath = getContainerFullPath();
+		if ((fullPath != null) && (fullPath.isEmpty() == false) && (fileName != null)) {
+			// check that filename does not contain invalid extension
+			if (!extensionValidForContentType(fileName)) {
+				setErrorMessage(NLS.bind(HTMLUIMessages._ERROR_FILENAME_MUST_END_HTML, getValidExtensions().toString()));
+				return false;
+			}
+			// no file extension specified so check adding default
+			// extension doesn't equal a file that already exists
+			if (fileName.lastIndexOf('.') == -1) {
+				String newFileName = addDefaultExtension(fileName);
+				IPath resourcePath = fullPath.append(newFileName);
+
+				IWorkspace workspace = ResourcesPlugin.getWorkspace();
+				IStatus result = workspace.validatePath(resourcePath.toString(), IResource.FOLDER);
+				if (!result.isOK()) {
+					// path invalid
+					setErrorMessage(result.getMessage());
+					return false;
+				}
+
+				if ((workspace.getRoot().getFolder(resourcePath).exists() || workspace.getRoot().getFile(resourcePath).exists())) {
+					setErrorMessage(HTMLUIMessages.ResourceGroup_nameExists);
+					return false;
+				}
+			}
+			
+			// get the IProject for the selection path
+			IProject project = getProjectFromPath(fullPath);
+			// if inside web project, check if inside webContent folder
+			if (project != null && isWebProject(project)) {
+				// check that the path is inside the webContent folder
+				IPath webContentPath = getWebContentPath(project);
+				if (!webContentPath.isPrefixOf(fullPath)) {
+					setMessage(HTMLUIMessages._WARNING_FOLDER_MUST_BE_INSIDE_WEB_CONTENT, WARNING);
+				}
+			}
+		}
+
+		return true;
+	}
+	
+	/**
+	 * Get content type associated with this new file wizard
+	 * 
+	 * @return IContentType
+	 */
+	private IContentType getContentType() {
+		if (fContentType == null)
+			fContentType = Platform.getContentTypeManager().getContentType(ContentTypeIdForHTML.ContentTypeID_HTML);
+		return fContentType;
+	}
+
+	/**
+	 * Get list of valid extensions for HTML Content type
+	 * 
+	 * @return
+	 */
+	private List getValidExtensions() {
+		if (fValidExtensions == null) {
+			IContentType type = getContentType();
+			fValidExtensions = new ArrayList(Arrays.asList(type.getFileSpecs(IContentType.FILE_EXTENSION_SPEC)));
+		}
+		return fValidExtensions;
+	}
+	
+	/**
+	 * Verifies if fileName is valid name for content type. Takes base content
+	 * type into consideration.
+	 * 
+	 * @param fileName
+	 * @return true if extension is valid for this content type
+	 */
+	private boolean extensionValidForContentType(String fileName) {
+		boolean valid = false;
+
+		IContentType type = getContentType();
+		// there is currently an extension
+		if (fileName.lastIndexOf('.') != -1) {
+			// check what content types are associated with current extension
+			IContentType[] types = Platform.getContentTypeManager().findContentTypesFor(fileName);
+			int i = 0;
+			while (i < types.length && !valid) {
+				valid = types[i].isKindOf(type);
+				++i;
+			}
+		}
+		else
+			valid = true; // no extension so valid
+		return valid;
+	}
+
+	/**
+	 * Adds default extension to the filename
+	 * 
+	 * @param filename
+	 * @return
+	 */
+	String addDefaultExtension(String filename) {
+		StringBuffer newFileName = new StringBuffer(filename);
+
+		Preferences preference = HTMLCorePlugin.getDefault().getPluginPreferences();
+		String ext = preference.getString(HTMLCorePreferenceNames.DEFAULT_EXTENSION);
+
+		newFileName.append("."); //$NON-NLS-1$
+		newFileName.append(ext);
+
+		return newFileName.toString();
+	}
+	
+	/**
+	 * Returns the project that contains the specified path
+	 * 
+	 * @param path the path which project is needed
+	 * @return IProject object. If path is <code>null</code> the return value 
+	 * 		   is also <code>null</code>. 
+	 */
+	private IProject getProjectFromPath(IPath path) {
+		IWorkspace workspace = ResourcesPlugin.getWorkspace();
+		IProject project = null;
+		
+		if (path != null) {
+			if (workspace.validatePath(path.toString(), IResource.PROJECT).isOK()) {
+				project = workspace.getRoot().getProject(path.toString());
+			} else {
+				project = workspace.getRoot().getFile(path).getProject();
+			}
+		}
+		
+		return project;
+	}
+	
+	/**
+	 * Checks if the specified project is a web project. 
+	 * 
+	 * @param project project to be checked
+	 * @return true if the project is web project, otherwise false
+	 */
+	private boolean isWebProject(IProject project) {
+		return FacetModuleCoreSupport.isWebProject(project);
+	}
+	
+	/**
+	 * Returns the web contents folder of the specified project
+	 * 
+	 * @param project the project which web contents path is needed
+	 * @return IPath of the web contents folder
+	 */
+	private IPath getWebContentPath(IProject project) {
+		return FacetModuleCoreSupport.getWebContentRootPath(project);
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/wizard/NewHTMLTemplatesWizardPage.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/wizard/NewHTMLTemplatesWizardPage.java
new file mode 100644
index 0000000..115042e
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/wizard/NewHTMLTemplatesWizardPage.java
@@ -0,0 +1,521 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 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
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.wizard;
+
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.preference.PreferenceDialog;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.text.Document;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.text.source.SourceViewer;
+import org.eclipse.jface.text.source.SourceViewerConfiguration;
+import org.eclipse.jface.text.templates.DocumentTemplateContext;
+import org.eclipse.jface.text.templates.Template;
+import org.eclipse.jface.text.templates.TemplateBuffer;
+import org.eclipse.jface.text.templates.TemplateContext;
+import org.eclipse.jface.text.templates.TemplateContextType;
+import org.eclipse.jface.text.templates.persistence.TemplateStore;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.TableLayout;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerSorter;
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ControlAdapter;
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Link;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.dialogs.PreferencesUtil;
+import org.eclipse.wst.html.core.internal.provisional.contenttype.ContentTypeIdForHTML;
+import org.eclipse.wst.html.ui.StructuredTextViewerConfigurationHTML;
+import org.eclipse.wst.html.ui.internal.HTMLUIMessages;
+import org.eclipse.wst.html.ui.internal.HTMLUIPlugin;
+import org.eclipse.wst.html.ui.internal.Logger;
+import org.eclipse.wst.html.ui.internal.editor.IHelpContextIds;
+import org.eclipse.wst.html.ui.internal.preferences.HTMLUIPreferenceNames;
+import org.eclipse.wst.html.ui.internal.templates.TemplateContextTypeIdsHTML;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.ui.StructuredTextViewerConfiguration;
+import org.eclipse.wst.sse.ui.internal.StructuredTextViewer;
+import org.eclipse.wst.sse.ui.internal.provisional.style.LineStyleProvider;
+
+/**
+ * Templates page in new file wizard. Allows users to select a new file
+ * template to be applied in new file.
+ * 
+ */
+public class NewHTMLTemplatesWizardPage extends WizardPage {
+
+	/**
+	 * Content provider for templates
+	 */
+	private class TemplateContentProvider implements IStructuredContentProvider {
+		/** The template store. */
+		private TemplateStore fStore;
+
+		/*
+		 * @see IContentProvider#dispose()
+		 */
+		public void dispose() {
+			fStore = null;
+		}
+
+		/*
+		 * @see IStructuredContentProvider#getElements(Object)
+		 */
+		public Object[] getElements(Object input) {
+			return fStore.getTemplates(TemplateContextTypeIdsHTML.NEW);
+		}
+
+		/*
+		 * @see IContentProvider#inputChanged(Viewer, Object, Object)
+		 */
+		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+			fStore = (TemplateStore) newInput;
+		}
+	}
+
+	/**
+	 * Label provider for templates.
+	 */
+	private class TemplateLabelProvider extends LabelProvider implements ITableLabelProvider {
+
+		/*
+		 * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java.lang.Object,
+		 *      int)
+		 */
+		public Image getColumnImage(Object element, int columnIndex) {
+			return null;
+		}
+
+		/*
+		 * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java.lang.Object,
+		 *      int)
+		 */
+		public String getColumnText(Object element, int columnIndex) {
+			Template template = (Template) element;
+
+			switch (columnIndex) {
+				case 0 :
+					return template.getName();
+				case 1 :
+					return template.getDescription();
+				default :
+					return ""; //$NON-NLS-1$
+			}
+		}
+	}
+
+	/** Last selected template name */
+	private String fLastSelectedTemplateName;
+	/** The viewer displays the pattern of selected template. */
+	private SourceViewer fPatternViewer;
+	/** The table presenting the templates. */
+	private TableViewer fTableViewer;
+	/** Template store used by this wizard page */
+	private TemplateStore fTemplateStore;
+	/** Checkbox for using templates. */
+	private Button fUseTemplateButton;
+
+	public NewHTMLTemplatesWizardPage() {
+		super("NewHTMLTemplatesWizardPage", HTMLUIMessages.NewHTMLTemplatesWizardPage_0, null); //$NON-NLS-1$
+		setDescription(HTMLUIMessages.NewHTMLTemplatesWizardPage_1);
+	}
+
+	/**
+	 * Correctly resizes the table so no phantom columns appear
+	 * 
+	 * @param parent
+	 *            the parent control
+	 * @param buttons
+	 *            the buttons
+	 * @param table
+	 *            the table
+	 * @param column1
+	 *            the first column
+	 * @param column2
+	 *            the second column
+	 * @param column3
+	 *            the third column
+	 */
+	private void configureTableResizing(final Composite parent, final Table table, final TableColumn column1, final TableColumn column2) {
+		parent.addControlListener(new ControlAdapter() {
+			public void controlResized(ControlEvent e) {
+				Rectangle area = parent.getClientArea();
+				Point preferredSize = table.computeSize(SWT.DEFAULT, SWT.DEFAULT);
+				int width = area.width - 2 * table.getBorderWidth();
+				if (preferredSize.y > area.height) {
+					// Subtract the scrollbar width from the total column
+					// width
+					// if a vertical scrollbar will be required
+					Point vBarSize = table.getVerticalBar().getSize();
+					width -= vBarSize.x;
+				}
+
+				Point oldSize = table.getSize();
+				if (oldSize.x > width) {
+					// table is getting smaller so make the columns
+					// smaller first and then resize the table to
+					// match the client area width
+					column1.setWidth(width / 2);
+					column2.setWidth(width / 2);
+					table.setSize(width, area.height);
+				}
+				else {
+					// table is getting bigger so make the table
+					// bigger first and then make the columns wider
+					// to match the client area width
+					table.setSize(width, area.height);
+					column1.setWidth(width / 2);
+					column2.setWidth(width / 2);
+				}
+			}
+		});
+	}
+
+	public void createControl(Composite ancestor) {
+		Composite parent = new Composite(ancestor, SWT.NONE);
+		GridLayout layout = new GridLayout();
+		layout.numColumns = 2;
+		parent.setLayout(layout);
+
+		// create checkbox for user to use HTML Template
+		fUseTemplateButton = new Button(parent, SWT.CHECK);
+		fUseTemplateButton.setText(HTMLUIMessages.NewHTMLTemplatesWizardPage_4);
+		GridData data = new GridData(SWT.FILL, SWT.FILL, true, false, 2, 1);
+		fUseTemplateButton.setLayoutData(data);
+		fUseTemplateButton.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				enableTemplates();
+			}
+		});
+
+		// create composite for Templates table
+		Composite innerParent = new Composite(parent, SWT.NONE);
+		GridLayout innerLayout = new GridLayout();
+		innerLayout.numColumns = 2;
+		innerLayout.marginHeight = 0;
+		innerLayout.marginWidth = 0;
+		innerParent.setLayout(innerLayout);
+		GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1);
+		innerParent.setLayoutData(gd);
+
+		Label label = new Label(innerParent, SWT.NONE);
+		label.setText(HTMLUIMessages.NewHTMLTemplatesWizardPage_7);
+		data = new GridData(SWT.FILL, SWT.FILL, true, false, 2, 1);
+		label.setLayoutData(data);
+
+		// create table that displays templates
+		Table table = new Table(innerParent, SWT.BORDER | SWT.FULL_SELECTION);
+
+		data = new GridData(GridData.FILL_BOTH);
+		data.widthHint = convertWidthInCharsToPixels(2);
+		data.heightHint = convertHeightInCharsToPixels(10);
+		data.horizontalSpan = 2;
+		table.setLayoutData(data);
+		table.setHeaderVisible(true);
+		table.setLinesVisible(true);
+		TableLayout tableLayout = new TableLayout();
+		table.setLayout(tableLayout);
+
+		TableColumn column1 = new TableColumn(table, SWT.NONE);
+		column1.setText(HTMLUIMessages.NewHTMLTemplatesWizardPage_2);
+
+		TableColumn column2 = new TableColumn(table, SWT.NONE);
+		column2.setText(HTMLUIMessages.NewHTMLTemplatesWizardPage_3);
+
+		fTableViewer = new TableViewer(table);
+		fTableViewer.setLabelProvider(new TemplateLabelProvider());
+		fTableViewer.setContentProvider(new TemplateContentProvider());
+
+		fTableViewer.setSorter(new ViewerSorter() {
+			public int compare(Viewer viewer, Object object1, Object object2) {
+				if ((object1 instanceof Template) && (object2 instanceof Template)) {
+					Template left = (Template) object1;
+					Template right = (Template) object2;
+					int result = left.getName().compareToIgnoreCase(right.getName());
+					if (result != 0)
+						return result;
+					return left.getDescription().compareToIgnoreCase(right.getDescription());
+				}
+				return super.compare(viewer, object1, object2);
+			}
+
+			public boolean isSorterProperty(Object element, String property) {
+				return true;
+			}
+		});
+
+		fTableViewer.addSelectionChangedListener(new ISelectionChangedListener() {
+			public void selectionChanged(SelectionChangedEvent e) {
+				updateViewerInput();
+			}
+		});
+
+		// create viewer that displays currently selected template's contents
+		fPatternViewer = doCreateViewer(parent);
+
+		fTemplateStore = HTMLUIPlugin.getDefault().getTemplateStore();
+		fTableViewer.setInput(fTemplateStore);
+
+		// Create linked text to just to templates preference page
+		Link link = new Link(parent, SWT.NONE);
+		link.setText(HTMLUIMessages.NewHTMLTemplatesWizardPage_6);
+		data = new GridData(SWT.END, SWT.FILL, true, false, 2, 1);
+		link.setLayoutData(data);
+		link.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				linkClicked();
+			}
+		});
+
+		configureTableResizing(innerParent, table, column1, column2);
+		loadLastSavedPreferences();
+
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(parent, IHelpContextIds.HTML_NEWWIZARD_TEMPLATE_HELPID);
+		Dialog.applyDialogFont(parent);
+		setControl(parent);
+	}
+
+	/**
+	 * Creates, configures and returns a source viewer to present the template
+	 * pattern on the preference page. Clients may override to provide a
+	 * custom source viewer featuring e.g. syntax coloring.
+	 * 
+	 * @param parent
+	 *            the parent control
+	 * @return a configured source viewer
+	 */
+	private SourceViewer createViewer(Composite parent) {
+		SourceViewerConfiguration sourceViewerConfiguration = new StructuredTextViewerConfiguration() {
+			StructuredTextViewerConfiguration baseConfiguration = new StructuredTextViewerConfigurationHTML();
+
+			public String[] getConfiguredContentTypes(ISourceViewer sourceViewer) {
+				return baseConfiguration.getConfiguredContentTypes(sourceViewer);
+			}
+
+			public LineStyleProvider[] getLineStyleProviders(ISourceViewer sourceViewer, String partitionType) {
+				return baseConfiguration.getLineStyleProviders(sourceViewer, partitionType);
+			}
+		};
+		SourceViewer viewer = new StructuredTextViewer(parent, null, null, false, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
+		viewer.getTextWidget().setFont(JFaceResources.getFont("org.eclipse.wst.sse.ui.textfont")); //$NON-NLS-1$
+		IStructuredModel scratchModel = StructuredModelManager.getModelManager().createUnManagedStructuredModelFor(ContentTypeIdForHTML.ContentTypeID_HTML);
+		IDocument document = scratchModel.getStructuredDocument();
+		viewer.configure(sourceViewerConfiguration);
+		viewer.setDocument(document);
+		return viewer;
+	}
+
+	private SourceViewer doCreateViewer(Composite parent) {
+		Label label = new Label(parent, SWT.NONE);
+		label.setText(HTMLUIMessages.NewHTMLTemplatesWizardPage_5);
+		GridData data = new GridData();
+		data.horizontalSpan = 2;
+		label.setLayoutData(data);
+
+		SourceViewer viewer = createViewer(parent);
+		viewer.setEditable(false);
+
+		Control control = viewer.getControl();
+		data = new GridData(GridData.FILL_BOTH);
+		data.horizontalSpan = 2;
+		data.heightHint = convertHeightInCharsToPixels(5);
+		// [261274] - source viewer was growing to fit the max line width of the template
+		data.widthHint = convertWidthInCharsToPixels(2);
+		control.setLayoutData(data);
+
+		return viewer;
+	}
+
+	/**
+	 * Enable/disable controls in page based on fUseTemplateButton's current
+	 * state.
+	 */
+	void enableTemplates() {
+		boolean enabled = fUseTemplateButton.getSelection();
+
+		if (!enabled) {
+			// save last selected template
+			Template template = getSelectedTemplate();
+			if (template != null)
+				fLastSelectedTemplateName = template.getName();
+			else
+				fLastSelectedTemplateName = ""; //$NON-NLS-1$
+
+			fTableViewer.setSelection(null);
+		}
+		else {
+			setSelectedTemplate(fLastSelectedTemplateName);
+		}
+
+		fTableViewer.getControl().setEnabled(enabled);
+		fPatternViewer.getControl().setEnabled(enabled);
+	}
+
+	/**
+	 * Return the template preference page id
+	 * 
+	 * @return
+	 */
+	private String getPreferencePageId() {
+		return "org.eclipse.wst.html.ui.preferences.templates"; //$NON-NLS-1$
+	}
+
+	/**
+	 * Get the currently selected template.
+	 * 
+	 * @return
+	 */
+	private Template getSelectedTemplate() {
+		Template template = null;
+		IStructuredSelection selection = (IStructuredSelection) fTableViewer.getSelection();
+
+		if (selection.size() == 1) {
+			template = (Template) selection.getFirstElement();
+		}
+		return template;
+	}
+
+	/**
+	 * Returns template string to insert.
+	 * 
+	 * @return String to insert or null if none is to be inserted
+	 */
+	String getTemplateString() {
+		String templateString = null;
+
+		Template template = getSelectedTemplate();
+		if (template != null) {
+			TemplateContextType contextType = HTMLUIPlugin.getDefault().getTemplateContextRegistry().getContextType(TemplateContextTypeIdsHTML.NEW);
+			IDocument document = new Document();
+			TemplateContext context = new DocumentTemplateContext(contextType, document, 0, 0);
+			try {
+				TemplateBuffer buffer = context.evaluate(template);
+				templateString = buffer.getString();
+			}
+			catch (Exception e) {
+				Logger.log(Logger.WARNING_DEBUG, "Could not create template for new html", e); //$NON-NLS-1$
+			}
+		}
+
+		return templateString;
+	}
+
+	void linkClicked() {
+		String pageId = getPreferencePageId();
+		PreferenceDialog dialog = PreferencesUtil.createPreferenceDialogOn(getShell(), pageId, new String[]{pageId}, null);
+		dialog.open();
+		fTableViewer.refresh();
+	}
+
+	/**
+	 * Load the last template name used in New HTML File wizard.
+	 */
+	private void loadLastSavedPreferences() {
+		fLastSelectedTemplateName = ""; //$NON-NLS-1$
+		boolean setSelection = false;
+		String templateName = HTMLUIPlugin.getDefault().getPreferenceStore().getString(HTMLUIPreferenceNames.NEW_FILE_TEMPLATE_NAME);
+		if (templateName == null || templateName.length() == 0) {
+			templateName = HTMLUIPlugin.getDefault().getPreferenceStore().getString(HTMLUIPreferenceNames.NEW_FILE_TEMPLATE_ID);
+			if (templateName != null && templateName.length() > 0) {
+				Template template = fTemplateStore.findTemplateById(templateName);
+				if (template != null) {
+					fLastSelectedTemplateName = template.getName();
+					setSelection = true;
+				}
+			}
+		}
+		else {
+			fLastSelectedTemplateName = templateName;
+			setSelection = true;
+		}
+		fUseTemplateButton.setSelection(setSelection);
+		enableTemplates();
+	}
+
+	/**
+	 * Save template name used for next call to New HTML File wizard.
+	 */
+	void saveLastSavedPreferences() {
+		String templateName = ""; //$NON-NLS-1$
+
+		Template template = getSelectedTemplate();
+		if (template != null) {
+			templateName = template.getName();
+		}
+
+		HTMLUIPlugin.getDefault().getPreferenceStore().setValue(HTMLUIPreferenceNames.NEW_FILE_TEMPLATE_NAME, templateName);
+		HTMLUIPlugin.getDefault().savePluginPreferences();
+	}
+
+	/**
+	 * Select a template in the table viewer given the template name. If
+	 * template name cannot be found or templateName is null, just select
+	 * first item in table. If no items in table select nothing.
+	 * 
+	 * @param templateName
+	 */
+	private void setSelectedTemplate(String templateName) {
+		Object template = null;
+
+		if (templateName != null && templateName.length() > 0) {
+			// pick the last used template
+			template = fTemplateStore.findTemplate(templateName, TemplateContextTypeIdsHTML.NEW);
+		}
+
+		// no record of last used template so just pick first element
+		if (template == null) {
+			// just pick first element
+			template = fTableViewer.getElementAt(0);
+		}
+
+		if (template != null) {
+			IStructuredSelection selection = new StructuredSelection(template);
+			fTableViewer.setSelection(selection, true);
+		}
+	}
+
+	/**
+	 * Updates the pattern viewer.
+	 */
+	void updateViewerInput() {
+		Template template = getSelectedTemplate();
+		if (template != null) {
+			fPatternViewer.getDocument().set(template.getPattern());
+		}
+		else {
+			fPatternViewer.getDocument().set(""); //$NON-NLS-1$
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/wizard/NewHTMLWizard.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/wizard/NewHTMLWizard.java
new file mode 100644
index 0000000..77c52f1
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/internal/wizard/NewHTMLWizard.java
@@ -0,0 +1,145 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.internal.wizard;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.OutputStreamWriter;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.ProjectScope;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.core.runtime.preferences.IScopeContext;
+import org.eclipse.core.runtime.preferences.InstanceScope;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.wizard.Wizard;
+import org.eclipse.ui.INewWizard;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.ide.IDE;
+import org.eclipse.wst.html.core.internal.HTMLCorePlugin;
+import org.eclipse.wst.html.ui.internal.HTMLUIMessages;
+import org.eclipse.wst.html.ui.internal.Logger;
+import org.eclipse.wst.html.ui.internal.editor.HTMLEditorPluginImageHelper;
+import org.eclipse.wst.html.ui.internal.editor.HTMLEditorPluginImages;
+import org.eclipse.wst.sse.core.internal.encoding.CommonEncodingPreferenceNames;
+import org.eclipse.wst.sse.core.utils.StringUtils;
+
+public class NewHTMLWizard extends Wizard implements INewWizard {
+	
+	private NewHTMLFileWizardPage fNewFilePage;
+	private NewHTMLTemplatesWizardPage fNewFileTemplatesPage;
+	private IStructuredSelection fSelection;
+
+	public void addPages() {
+		fNewFilePage = new NewHTMLFileWizardPage("HTMLWizardNewFileCreationPage", new StructuredSelection(IDE.computeSelectedResources(fSelection))); //$NON-NLS-1$
+		fNewFilePage.setTitle(HTMLUIMessages._UI_WIZARD_NEW_HEADING);
+		fNewFilePage.setDescription(HTMLUIMessages._UI_WIZARD_NEW_DESCRIPTION);
+		addPage(fNewFilePage);
+
+		fNewFileTemplatesPage = new NewHTMLTemplatesWizardPage();
+		addPage(fNewFileTemplatesPage);
+	}
+	
+	private String applyLineDelimiter(IFile file, String text) {
+		String lineDelimiter = Platform.getPreferencesService().getString(Platform.PI_RUNTIME, Platform.PREF_LINE_SEPARATOR, System.getProperty("line.separator"), new IScopeContext[] {new ProjectScope(file.getProject()), new InstanceScope() });//$NON-NLS-1$
+		String convertedText = StringUtils.replace(text, "\r\n", "\n");
+		convertedText = StringUtils.replace(convertedText, "\r", "\n");
+		convertedText = StringUtils.replace(convertedText, "\n", lineDelimiter);
+		return convertedText;
+	}
+
+	public void init(IWorkbench aWorkbench, IStructuredSelection aSelection) {
+		fSelection = aSelection;
+		setWindowTitle(HTMLUIMessages._UI_WIZARD_NEW_TITLE);
+
+		ImageDescriptor descriptor = HTMLEditorPluginImageHelper.getInstance().getImageDescriptor(HTMLEditorPluginImages.IMG_WIZBAN_NEWHTMLFILE);
+		setDefaultPageImageDescriptor(descriptor);
+	}
+
+	private void openEditor(final IFile file) {
+		if (file != null) {
+			getShell().getDisplay().asyncExec(new Runnable() {
+				public void run() {
+					try {
+						IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
+						IDE.openEditor(page, file, true);
+					}
+					catch (PartInitException e) {
+						Logger.log(Logger.WARNING_DEBUG, e.getMessage(), e);
+					}
+				}
+			});
+		}
+	}
+
+	public boolean performFinish() {
+		boolean performedOK = false;
+		// save user options for next use
+		fNewFileTemplatesPage.saveLastSavedPreferences();
+
+		// no file extension specified so add default extension
+		String fileName = fNewFilePage.getFileName();
+		if (fileName.lastIndexOf('.') == -1) {
+			String newFileName = fNewFilePage.addDefaultExtension(fileName);
+			fNewFilePage.setFileName(newFileName);
+		}
+
+		// create a new empty file
+		IFile file = fNewFilePage.createNewFile();
+
+		// if there was problem with creating file, it will be null, so make
+		// sure to check
+		if (file != null) {
+			// put template contents into file
+			String templateString = fNewFileTemplatesPage.getTemplateString();
+			if (templateString != null) {
+				templateString = applyLineDelimiter(file, templateString);
+				// determine the encoding for the new file
+				Preferences preference = HTMLCorePlugin.getDefault().getPluginPreferences();
+				String charSet = preference.getString(CommonEncodingPreferenceNames.OUTPUT_CODESET);
+
+				try {
+					ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+					OutputStreamWriter outputStreamWriter = null;
+					if (charSet == null || charSet.trim().equals("")) { //$NON-NLS-1$
+						// just use default encoding
+						outputStreamWriter = new OutputStreamWriter(outputStream);
+					}
+					else {
+						outputStreamWriter = new OutputStreamWriter(outputStream, charSet);
+					}
+					outputStreamWriter.write(templateString);
+					outputStreamWriter.flush();
+					outputStreamWriter.close();
+					ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
+					file.setContents(inputStream, true, false, null);
+					inputStream.close();
+				}
+				catch (Exception e) {
+					Logger.log(Logger.WARNING_DEBUG, "Could not create contents for new HTML file", e); //$NON-NLS-1$
+				}
+			}
+
+			// open the file in editor
+			openEditor(file);
+
+			// everything's fine
+			performedOK = true;
+		}
+		return performedOK;
+	}
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/views/contentoutline/HTMLContentOutlineConfiguration.java b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/views/contentoutline/HTMLContentOutlineConfiguration.java
new file mode 100644
index 0000000..4214204
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/src/org/eclipse/wst/html/ui/views/contentoutline/HTMLContentOutlineConfiguration.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.html.ui.views.contentoutline;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.wst.html.ui.internal.HTMLUIPlugin;
+import org.eclipse.wst.html.ui.internal.contentoutline.HTMLNodeActionManager;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.xml.ui.internal.contentoutline.XMLNodeActionManager;
+import org.eclipse.wst.xml.ui.views.contentoutline.XMLContentOutlineConfiguration;
+
+/**
+ * Configuration for outline view page which shows HTML content.
+ * 
+ * @see org.eclipse.wst.sse.ui.views.contentoutline.ContentOutlineConfiguration
+ * @since 1.0
+ */
+public class HTMLContentOutlineConfiguration extends XMLContentOutlineConfiguration {
+
+	/**
+	 * Create new instance of HTMLContentOutlineConfiguration
+	 */
+	public HTMLContentOutlineConfiguration() {
+		// Must have empty constructor to createExecutableExtension
+		super();
+	}
+
+	protected XMLNodeActionManager createNodeActionManager(TreeViewer treeViewer) {
+		return new HTMLNodeActionManager((IStructuredModel) treeViewer.getInput(), treeViewer);
+	}
+
+	protected IPreferenceStore getPreferenceStore() {
+		return HTMLUIPlugin.getDefault().getPreferenceStore();
+	}
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.html.ui/templates/htmldefault-templates.properties b/bundles/org.eclipse.wst.html.ui/templates/htmldefault-templates.properties
new file mode 100644
index 0000000..cfa1c62
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/templates/htmldefault-templates.properties
@@ -0,0 +1,54 @@
+###############################################################################
+# 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
+#     Benjamin Muskalla, b.muskalla@gmx.net - [156040] no new html template for xhtml 1.0 strict
+###############################################################################
+Templates.comment.name=comment
+Templates.comment.desc=comment
+Templates.ul.name=ul
+Templates.ul.desc=unordered list
+Templates.ul.content=<ul>\n  <li> Item one </li>\n  <li> Item two </li>\n</ul>\n
+Templates.dl.name=dl
+Templates.dl.desc=definition list
+Templates.dl.content=<dl>\n  <dt> First definition</dt>  <dd>  First explanation</dd>\n  <dt> Second definition</dt> <dd> Second explanation</dd>\n</dl>\n
+Templates.table.name=table
+Templates.table.desc=table
+Templates.table.content=<table>\n  <tr>\n    <th>Column 1 Heading</th>\n    <th>Column 2 Heading</th>\n  </tr>\n  <tr>\n    <td>Row 1: Col 1</td>\n    <td>Row 1: Col 2</td>\n  </tr>\n</table>\n
+Templates.ol.name=ol
+Templates.ol.desc=ordered list
+Templates.ol.content=<ol>\n  <li> Item one </li>\n  <li> Item two </li>\n</ol>\n
+Templates.html.name=New HTML File (4.01 transitional)
+Templates.html.desc=html 4.01 transitional
+Templates.html.content=<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">\n<html>\n<head>\n<meta http-equiv="Content-Type" content="text/html; charset=${encoding}">\n<title>Insert title here</title>\n</head>\n<body>\n${cursor}\n</body>\n</html>
+Templates.htmlframeset.name=New HTML File (4.01 frameset)
+Templates.htmlframeset.desc=html 4.01 frameset
+Templates.htmlframeset.content=<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">\n<html>\n<head>\n<meta http-equiv="Content-Type" content="text/html; charset=${encoding}">\n<title>Insert title here</title>\n</head>\n<frameset>\n    <frame>\n    <frame>\n    <noframes>\n    <body>\n    <p>This page uses frames. The current browser you are using does not support frames.</p>\n    </body>\n    </noframes>\n</frameset>\n</html>
+Templates.htmlstrict.name=New HTML File (4.01 strict)
+Templates.htmlstrict.desc=html 4.01 strict
+Templates.htmlstrict.content=<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Strict//EN" "http://www.w3.org/TR/html4/strict.dtd">\n<html>\n<head>\n<meta http-equiv="Content-Type" content="text/html; charset=${encoding}">\n<title>Insert title here</title>\n</head>\n<body>\n${cursor}\n</body>\n</html>
+Templates.xhtml.name=New XHTML File (1.0 transitional)
+Templates.xhtml.desc=xhtml 1.0 transitional
+Templates.xhtml.content=<?xml version="1.0" encoding="${encoding}" ?>\n<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\n<html xmlns="http://www.w3.org/1999/xhtml">\n<head>\n<meta http-equiv="Content-Type" content="text/html; charset=${encoding}" />\n<title>Insert title here</title>\n</head>\n<body>\n${cursor}\n</body>\n</html>
+Templates.xhtmlframeset.name=New XHTML File (1.0 frameset)
+Templates.xhtmlframeset.desc=xhtml 1.0 frameset
+Templates.xhtmlframeset.content=<?xml version="1.0" encoding="${encoding}" ?>\n<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">\n<html xmlns="http://www.w3.org/1999/xhtml">\n<head>\n<meta http-equiv="Content-Type" content="text/html; charset=${encoding}" />\n<title>Insert title here</title>\n</head>\n<frameset>\n    <frame />\n    <frame />\n    <noframes>\n    <body>\n    <p>This page uses frames. The current browser you are using does not support frames.</p>\n    </body>\n    </noframes>\n</frameset>\n</html>
+Templates.xhtmlstrict.name=New XHTML File (1.0 strict)
+Templates.xhtmlstrict.desc=xhtml 1.0 strict
+Templates.xhtmlstrict.content=<?xml version="1.0" encoding="${encoding}" ?>\n<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\n<html xmlns="http://www.w3.org/1999/xhtml">\n<head>\n<meta http-equiv="Content-Type" content="text/html; charset=${encoding}" />\n<title>Insert title here</title>\n</head>\n<body>\n${cursor}\n</body>\n</html>
+Templates.script.name=script
+Templates.script.desc=script     (commented)
+Templates.script.content=<script type=\"${cursor}text/javascript\">\n<!--\n\n//-->\n</script>
+Templates.style.name=style
+Templates.style.desc=style     (commented)
+Templates.style.content=<style>\n<!--\n${cursor}\n-->\n</style>
+Templates.imgmap.name=img
+Templates.imgmap.desc=img     (map)
+Templates.html5.name=New HTML File (5)
+Templates.html5.desc=html 5
+Templates.html5.content=<!DOCTYPE html>\n<html>\n<head>\n<meta charset="${encoding}">\n<title>Insert title here</title>\n</head>\n<body>\n${cursor}\n</body>\n</html>
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.html.ui/templates/htmldefault-templates.xml b/bundles/org.eclipse.wst.html.ui/templates/htmldefault-templates.xml
new file mode 100644
index 0000000..c600c08
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.ui/templates/htmldefault-templates.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*******************************************************************************
+ * 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
+ *     Benjamin Muskalla, b.muskalla@gmx.net - [156040] no new html template for xhtml 1.0 strict
+ *     
+ *******************************************************************************/
+ -->
+<templates>
+
+<template name="%Templates.comment.name" description="%Templates.comment.desc" id="org.eclipse.wst.html.ui.templates.comment" context="html_tag" enabled="true">&lt;!-- ${cursor} --&gt;</template>
+
+<template name="%Templates.imgmap.name" description="%Templates.imgmap.desc" id="org.eclipse.wst.html.ui.templates.imgmap" context="html_tag" enabled="true">&lt;img ismap&gt;</template>
+
+<template name="%Templates.ul.name" description="%Templates.ul.desc" id="org.eclipse.wst.html.ui.templates.ul" context="html_tag" enabled="true">%Templates.ul.content</template>
+
+<template name="%Templates.dl.name" description="%Templates.dl.desc" id="org.eclipse.wst.html.ui.templates.dl" context="html_tag" enabled="true">%Templates.dl.content</template>
+
+<template name="%Templates.table.name" description="%Templates.table.desc" id="org.eclipse.wst.html.ui.templates.table" context="html_tag" enabled="true">%Templates.table.content</template>
+
+<template name="%Templates.ol.name" description="%Templates.ol.desc" id="org.eclipse.wst.html.ui.templates.ol" context="html_tag" enabled="true">%Templates.ol.content</template>
+
+<template name="%Templates.html.name" description="%Templates.html.desc" id="org.eclipse.wst.html.ui.templates.html" context="html_new" enabled="true">%Templates.html.content</template>
+
+<template name="%Templates.htmlframeset.name" description="%Templates.htmlframeset.desc" id="org.eclipse.wst.html.ui.templates.htmlframeset" context="html_new" enabled="true">%Templates.htmlframeset.content</template>
+
+<template name="%Templates.htmlstrict.name" description="%Templates.htmlstrict.desc" id="org.eclipse.wst.html.ui.templates.htmlstrict" context="html_new" enabled="true">%Templates.htmlstrict.content</template>
+
+<template name="%Templates.xhtml.name" description="%Templates.xhtml.desc" id="org.eclipse.wst.html.ui.templates.xhtml" context="html_new" enabled="true">%Templates.xhtml.content</template>
+
+<template name="%Templates.xhtmlframeset.name" description="%Templates.xhtmlframeset.desc" id="org.eclipse.wst.html.ui.templates.xhtmlframeset" context="html_new" enabled="true">%Templates.xhtmlframeset.content</template>
+
+<template name="%Templates.xhtmlstrict.name" description="%Templates.xhtmlstrict.desc" id="org.eclipse.wst.html.ui.templates.xhtmlstrict" context="html_new" enabled="true">%Templates.xhtmlstrict.content</template>
+
+<template name="%Templates.script.name" description="%Templates.script.desc" id="org.eclipse.wst.html.ui.templates.script" context="html_tag" enabled="true">%Templates.script.content</template>
+
+<template name="%Templates.style.name" description="%Templates.style.desc" id="org.eclipse.wst.html.ui.templates.style" context="html_tag" enabled="true">%Templates.style.content</template>
+
+<template name="%Templates.html5.name" description="%Templates.html5.desc" id="org.eclipse.wst.html.ui.templates.html5" context="html_new" enabled="true">%Templates.html5.content</template>
+
+</templates>
diff --git a/bundles/org.eclipse.wst.sse.ui/META-INF/MANIFEST.MF b/bundles/org.eclipse.wst.sse.ui/META-INF/MANIFEST.MF
index 4b8c248..45500ee 100644
--- a/bundles/org.eclipse.wst.sse.ui/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.wst.sse.ui/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %pluginName
 Bundle-SymbolicName: org.eclipse.wst.sse.ui; singleton:=true
-Bundle-Version: 1.2.2.qualifier
+Bundle-Version: 1.2.5.qualifier
 Bundle-Activator: org.eclipse.wst.sse.ui.internal.SSEUIPlugin
 Bundle-Vendor: %providerName
 Bundle-Localization: plugin
diff --git a/bundles/org.eclipse.wst.sse.ui/plugin.properties b/bundles/org.eclipse.wst.sse.ui/plugin.properties
index 7044196..5ab4691 100644
--- a/bundles/org.eclipse.wst.sse.ui/plugin.properties
+++ b/bundles/org.eclipse.wst.sse.ui/plugin.properties
@@ -30,17 +30,23 @@
 Character_Pairing.name=Character Pairing Extension
 Completion_Proposal.name=Completion Proposal
 Completion_Proposal_Categories_Configuration.name=Completion Proposal Categories Configuration
+Commenting_Strategy_Extension.name=Commenting Strategy Extension
 ##########################################################################
 # These strings are used in Workbench Keys Preferences
 ##########################################################################
 scope.structuredTextEditor.name=Editing in Structured Text Editors
 scope.structuredTextEditor.description=Editing in Structured Text Editors
+scope.structuredTextEditor.comments.description=Source Comments in Structured Text Editors
+scope.structuredTextEditor.comments.name=Source Comments in Structured Text Editors
 command.toggle.comment.name=Toggle Comment
 command.toggle.comment.description=Toggle Comment
+command.toggle.comment.mnemonic=T
 command.add.block.comment.name=Add Block Comment
 command.add.block.comment.description=Add Block Comment
+command.add.block.comment.mnemonic=A
 command.remove.block.comment.name=Remove Block Comment
 command.remove.block.comment.description=Remove Block Comment
+command.remove.block.comment.mnemonic=R
 command.cleanup.document.name=Cleanup Document...
 command.cleanup.document.description=Cleanup document
 command.cleanup.document.mnemonic=C
diff --git a/bundles/org.eclipse.wst.sse.ui/plugin.xml b/bundles/org.eclipse.wst.sse.ui/plugin.xml
index 2bf3ff0..35e7717 100644
--- a/bundles/org.eclipse.wst.sse.ui/plugin.xml
+++ b/bundles/org.eclipse.wst.sse.ui/plugin.xml
@@ -210,6 +210,12 @@
 			description="%scope.structuredTextEditor.description"
 			id="org.eclipse.wst.sse.ui.structuredTextEditorScope">
 		</context>
+		<context
+			name="%scope.structuredTextEditor.comments.name"
+			parentId="org.eclipse.wst.sse.ui.structuredTextEditorScope"
+			description="%scope.structuredTextEditor.comments.description"
+			id="org.eclipse.wst.sse.comments">
+		</context>
 	</extension>
 	<!-- Keybindings for source editor -->
 	<extension point="org.eclipse.ui.bindings">
@@ -531,6 +537,7 @@
 		id="quickFixProcessor" 
 		name="%quickFixProcessor" 
 		schema="schema/quickFixProcessor.exsd"/>
+ <extension-point id="commentingStrategy" name="%Commenting_Strategy_Extension.name" schema="schema/commentingStrategy.exsd"/>
  <extension-point id="completionProposal" name="%Completion_Proposal.name" schema="schema/completionProposal.exsd"/>
  <extension-point id="completionProposalCategoriesConfiguration" name="%Completion_Proposal_Categories_Configuration.name" schema="schema/completionProposalCategoriesConfiguration.exsd"/>
  
@@ -661,8 +668,33 @@
 			</command>
 		</menuContribution>
 
-	     <menuContribution
+		<menuContribution
 	           locationURI="popup:sourcePopupMenuId?after=sourceBegin">
+			<command
+					commandId="org.eclipse.wst.sse.ui.toggle.comment"
+					id="ToggleComment"
+					style="push">
+				<visibleWhen checkEnabled="false">
+					<reference definitionId="org.eclipse.wst.sse.ui.commentingActiveContext.definition"></reference>
+				</visibleWhen>
+			</command>
+			<command
+					commandId="org.eclipse.wst.sse.ui.add.block.comment"
+					id="AddBlockComment"
+					style="push">
+				<visibleWhen checkEnabled="false">
+					<reference definitionId="org.eclipse.wst.sse.ui.commentingActiveContext.definition"></reference>
+				</visibleWhen>
+			</command>
+			<command
+					commandId="org.eclipse.wst.sse.ui.remove.block.comment"
+					id="RemoveBlockComment"
+					style="push">
+				<visibleWhen checkEnabled="false">
+					<reference definitionId="org.eclipse.wst.sse.ui.commentingActiveContext.definition"></reference>
+				</visibleWhen>
+			</command>
+			<separator name="format" visible="true"></separator>
 				<command
 			           commandId="org.eclipse.wst.sse.ui.cleanup.document"
 			           id="CleanupDocument"
@@ -691,6 +723,32 @@
 				</command>
 				
 	     </menuContribution>
+			<menuContribution locationURI="menu:sourceMenuId?after=sourceBegin">
+				<command commandId="org.eclipse.wst.sse.ui.toggle.comment"
+						id="ToggleComment"
+				    mnemonic="%command.toggle.comment.mnemonic"
+				    style="push">
+					<visibleWhen checkEnabled="false">
+						<reference definitionId="org.eclipse.wst.sse.ui.commentingActiveContext.definition"/>
+					</visibleWhen>
+				</command>
+				<command commandId="org.eclipse.wst.sse.ui.add.block.comment"
+						id="AddBlockComment"
+				    mnemonic="%command.add.block.comment.mnemonic"
+				    style="push">
+					<visibleWhen checkEnabled="false">
+						<reference definitionId="org.eclipse.wst.sse.ui.commentingActiveContext.definition"/>
+					</visibleWhen>
+				</command>
+				<command commandId="org.eclipse.wst.sse.ui.remove.block.comment"
+						id="RemoveBlockComment"
+						mnemonic="%command.remove.block.comment.mnemonic"
+						style="push">
+					<visibleWhen checkEnabled="false">
+						<reference definitionId="org.eclipse.wst.sse.ui.commentingActiveContext.definition"/>
+					</visibleWhen>
+				</command>
+			</menuContribution>
 	</extension>
 	<extension
        point="org.eclipse.ui.commands">
@@ -730,6 +788,14 @@
 	           </iterate>
             </with>
 		</definition>
+	  <definition 
+	  		id="org.eclipse.wst.sse.ui.commentingActiveContext.definition">
+	  	<with variable="activeContexts">
+				<iterate operator="or">
+					<equals value="org.eclipse.wst.sse.comments"/>
+				</iterate>
+			</with>
+	  </definition>
 	</extension>
 	
 	<!-- Define theme -->
diff --git a/bundles/org.eclipse.wst.sse.ui/schema/commentingStrategy.exsd b/bundles/org.eclipse.wst.sse.ui/schema/commentingStrategy.exsd
new file mode 100644
index 0000000..57b4d68
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.ui/schema/commentingStrategy.exsd
@@ -0,0 +1,260 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.wst.sse.ui" xmlns="http://www.w3.org/2001/XMLSchema">
+<annotation>
+      <appInfo>
+         <meta.schema plugin="org.eclipse.wst.sse.ui" id="commentingStrategy" name="Commenting Strategy"/>
+      </appInfo>
+      <documentation>
+         This extension point allows the contribution of commenting strategy&apos;s to participate in the commenting actions, such as adding and removing commenting blocks and toggling line comments.
+      </documentation>
+   </annotation>
+
+   <element name="extension">
+      <annotation>
+         <appInfo>
+            <meta.element />
+         </appInfo>
+      </annotation>
+      <complexType>
+         <sequence>
+            <choice minOccurs="1" maxOccurs="unbounded">
+               <element ref="blockCommentingStrategy" minOccurs="0" maxOccurs="unbounded"/>
+               <element ref="lineCommentingStrategy" minOccurs="0" maxOccurs="unbounded"/>
+            </choice>
+         </sequence>
+         <attribute name="point" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="id" type="string">
+            <annotation>
+               <documentation>
+                  an optional identifier of the extension instance
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="name" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+               <appInfo>
+                  <meta.attribute translatable="true"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <element name="blockCommentingStrategy">
+      <annotation>
+         <documentation>
+            Defines a block commenting strategy
+         </documentation>
+      </annotation>
+      <complexType>
+         <sequence minOccurs="1" maxOccurs="unbounded">
+            <element ref="contentType"/>
+         </sequence>
+         <attribute name="prefix" type="string" use="required">
+            <annotation>
+               <documentation>
+                  The prefix of the block comment this strategy impliments
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="suffix" type="string" use="required">
+            <annotation>
+               <documentation>
+                  The suffix of the block comment this strategy impliments
+               </documentation>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <element name="lineCommentingStrategy">
+      <annotation>
+         <documentation>
+            Deefines a line commenting strategy
+         </documentation>
+      </annotation>
+      <complexType>
+         <sequence minOccurs="1" maxOccurs="unbounded">
+            <element ref="contentType"/>
+         </sequence>
+         <attribute name="prefix" type="string" use="required">
+            <annotation>
+               <documentation>
+                  The prefix of the block comment this strategy impliments
+               </documentation>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <element name="contentType">
+      <annotation>
+         <documentation>
+            A content type that the strategy is applicable for
+         </documentation>
+      </annotation>
+      <complexType>
+         <sequence>
+            <choice>
+               <element ref="requiredPartitionTypes"/>
+               <element ref="allowablePartitionTypes"/>
+               <sequence>
+                  <element ref="requiredPartitionTypes"/>
+                  <element ref="allowablePartitionTypes"/>
+               </sequence>
+            </choice>
+         </sequence>
+         <attribute name="id" type="string" use="required">
+            <annotation>
+               <documentation>
+                  The ID of the content type
+               </documentation>
+               <appInfo>
+                  <meta.attribute kind="identifier" basedOn="org.eclipse.core.contenttype.contentTypes/content-type/@id"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+         <attribute name="associatedCommentPartitionTypeID" type="string">
+            <annotation>
+               <documentation>
+                  The partition type ID of the comment partition that is associated with the strategy in this content type
+               </documentation>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <element name="requiredPartitionTypes">
+      <annotation>
+         <documentation>
+            List of partition types in the associated content type that are requried for the strategy to be applicable.  Only one of these partition types must be present in a selection for the strategy to be applicable.
+         </documentation>
+      </annotation>
+      <complexType>
+         <sequence minOccurs="1" maxOccurs="unbounded">
+            <element ref="partitionType"/>
+         </sequence>
+      </complexType>
+   </element>
+
+   <element name="allowablePartitionTypes">
+      <annotation>
+         <documentation>
+            The partition types that are allowed in a user selection for the strategy to be valid.  It is assumed that any partition types listed in the &lt;code&gt;requiredPartitionTypes&lt;/code&gt; are also allowable.  This list is ignored if the value of &lt;code&gt;anyPartitionType&lt;/code&gt; is &lt;code&gt;true&lt;/code&gt;.  If this list is not provided then it is assumed the value of &lt;code&gt;anyPartitionType&lt;/code&gt; is false.
+         </documentation>
+      </annotation>
+      <complexType>
+         <sequence minOccurs="0" maxOccurs="unbounded">
+            <element ref="partitionType"/>
+         </sequence>
+         <attribute name="anyPartitionType" type="boolean" use="default" value="false">
+            <annotation>
+               <documentation>
+                  If &lt;code&gt;true&lt;/code&gt; then the strategy is valid for any partition type in the associated &lt;code&gt;contentType&lt;/code&gt;, this means that any &lt;code&gt;partionType&lt;/code&gt;s listed here would be ignored.  If &lt;code&gt;false&lt;/code&gt; then only the &lt;code&gt;partitionType&lt;/code&gt;s listed here are allowed in a user selection (allong with any specified requried partition types) for the strategy to be valid.
+               </documentation>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <element name="partitionType">
+      <annotation>
+         <documentation>
+            A partition type associated with the parenting content type
+         </documentation>
+      </annotation>
+      <complexType>
+         <attribute name="id" type="string" use="required">
+            <annotation>
+               <documentation>
+                  The ID of the partition type.
+               </documentation>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+
+   <annotation>
+      <appInfo>
+         <meta.section type="examples"/>
+      </appInfo>
+      <documentation>
+         &lt;p&gt;&lt;b&gt;Example 1:&lt;/b&gt; A simple example for block comments on XML documents&lt;/p&gt;&lt;pre&gt;&lt;extension point=&quot;org.eclipse.wst.sse.ui.commentingStrategy&quot;&gt;
+  &lt;blockCommentingStrategy
+      prefix=&quot;&amp;lt;!--&quot;
+      suffix=&quot;--&amp;gt;&quot;&gt;
+    &lt;contentType
+        id=&quot;org.eclipse.core.runtime.xml&quot;
+        associatedCommentPartitionTypeID=&quot;org.eclipse.wst.xml.XML_COMMENT&quot;&gt;
+      &lt;allowablePartitionTypes
+          anyPartitionType=&quot;true&quot;&gt;
+      &lt;/allowablePartitionTypes&gt;
+    &lt;/contentType&gt;
+  &lt;/blockCommentingStrategy&gt;
+&lt;/extension&gt;&lt;/pre&gt;
+
+&lt;p&gt;&lt;b&gt;Example 2:&lt;/b&gt; A more complex example for adding CSS comenting to both CSS and HTML documents&lt;/p&gt;&lt;pre&gt;&lt;extension point=&quot;org.eclipse.wst.sse.ui.commentingStrategy&quot;&gt;
+  &lt;blockCommentingStrategy
+      prefix=&quot;/*&quot;
+      suffix=&quot;*/&quot;&gt;
+    &lt;contentType
+        associatedCommentPartitionTypeID=&quot;org.eclipse.wst.css.COMMENT&quot;
+        id=&quot;org.eclipse.wst.css.core.csssource&quot;&gt;
+      &lt;allowablePartitionTypes
+          anyPartitionType=&quot;true&quot;&gt;
+      &lt;/allowablePartitionTypes&gt;
+    &lt;/contentType&gt;
+    &lt;contentType
+        id=&quot;org.eclipse.wst.html.core.htmlsource&quot;&gt;
+      &lt;allowablePartitionTypes
+          anyPartitionType=&quot;false&quot;&gt;
+      &lt;/allowablePartitionTypes&gt;
+      &lt;requiredPartitionTypes
+          requireAll=&quot;true&quot;&gt;
+        &lt;partitionType
+            id=&quot;org.eclipse.wst.css.STYLE&quot;&gt;
+        &lt;/partitionType&gt;
+      &lt;/requiredPartitionTypes&gt;
+    &lt;/contentType&gt;
+  &lt;/blockCommentingStrategy&gt;
+&lt;/extension&gt;&lt;/pre&gt;
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="apiinfo"/>
+      </appInfo>
+      <documentation>
+         The user of this extension point does not need to impliment any classes themselves but for their contributions to work in any given content type then the following handlers must be registered for the content type in question by using the &lt;code&gt;org.eclipse.ui.handlers&lt;/code&gt; extension point.
+&lt;ul&gt;
+&lt;li&gt;&lt;code&gt;org.eclipse.wst.sse.ui.handlers.AddBlockCommentHandler&lt;/code&gt;&lt;/li&gt;
+&lt;li&gt;&lt;code&gt;org.eclipse.wst.sse.ui.handlers.RemoveBlockCommentHandler&lt;/code&gt;&lt;/li&gt;
+&lt;li&gt;&lt;code&gt;org.eclipse.wst.sse.ui.handlers.ToggleLineCommentHandler&lt;/code&gt;&lt;/li&gt;
+&lt;/ul&gt;
+      </documentation>
+   </annotation>
+
+
+   <annotation>
+      <appInfo>
+         <meta.section type="copyright"/>
+      </appInfo>
+      <documentation>
+         Copyright (c) 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 &lt;a href=&quot;http://www.eclipse.org/legal/epl-v10.html&quot;&gt;http://www.eclipse.org/legal/epl-v10.html&lt;/a&gt;
+      </documentation>
+   </annotation>
+
+</schema>
diff --git a/bundles/org.eclipse.wst.sse.ui/schema/completionProposal.exsd b/bundles/org.eclipse.wst.sse.ui/schema/completionProposal.exsd
index c0a8a1f..e361555 100644
--- a/bundles/org.eclipse.wst.sse.ui/schema/completionProposal.exsd
+++ b/bundles/org.eclipse.wst.sse.ui/schema/completionProposal.exsd
@@ -195,6 +195,16 @@
                </documentation>
             </annotation>
          </attribute>
+         <attribute name="autoActivationDelegate" type="string">
+            <annotation>
+               <documentation>
+                  Identifies a class that is responsible for identifying auto-activation characters for the associated content and partition type.
+               </documentation>
+               <appInfo>
+                  <meta.attribute kind="java" basedOn="org.eclipse.wst.sse.ui.contentassist.AutoActivationDelegate:"/>
+               </appInfo>
+            </annotation>
+         </attribute>
       </complexType>
    </element>
 
diff --git a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/StructuredTextEditor.java b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/StructuredTextEditor.java
index 2ac7253..67b939f 100644
--- a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/StructuredTextEditor.java
+++ b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/StructuredTextEditor.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2001, 2010 IBM Corporation and others.
+ * Copyright (c) 2001, 2011 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
@@ -69,13 +69,17 @@
 import org.eclipse.jface.text.ITypedRegion;
 import org.eclipse.jface.text.Region;
 import org.eclipse.jface.text.TextSelection;
+import org.eclipse.jface.text.contentassist.ContentAssistEvent;
 import org.eclipse.jface.text.contentassist.ContentAssistant;
+import org.eclipse.jface.text.contentassist.ICompletionListener;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
 import org.eclipse.jface.text.contentassist.IContentAssistant;
 import org.eclipse.jface.text.information.IInformationPresenter;
 import org.eclipse.jface.text.information.IInformationProvider;
 import org.eclipse.jface.text.information.InformationPresenter;
 import org.eclipse.jface.text.reconciler.IReconciler;
 import org.eclipse.jface.text.source.Annotation;
+import org.eclipse.jface.text.source.ContentAssistantFacade;
 import org.eclipse.jface.text.source.DefaultCharacterPairMatcher;
 import org.eclipse.jface.text.source.ICharacterPairMatcher;
 import org.eclipse.jface.text.source.ISourceViewer;
@@ -189,6 +193,9 @@
 import org.eclipse.wst.sse.ui.internal.editor.SelectionConvertor;
 import org.eclipse.wst.sse.ui.internal.editor.StructuredModelDocumentProvider;
 import org.eclipse.wst.sse.ui.internal.extension.BreakpointProviderBuilder;
+import org.eclipse.wst.sse.ui.internal.handlers.AddBlockCommentHandler;
+import org.eclipse.wst.sse.ui.internal.handlers.RemoveBlockCommentHandler;
+import org.eclipse.wst.sse.ui.internal.handlers.ToggleLineCommentHandler;
 import org.eclipse.wst.sse.ui.internal.hyperlink.OpenHyperlinkAction;
 import org.eclipse.wst.sse.ui.internal.preferences.EditorPreferenceNames;
 import org.eclipse.wst.sse.ui.internal.projection.AbstractStructuredFoldingStrategy;
@@ -800,12 +807,16 @@
 
 	class TimeOutExpired extends TimerTask {
 		public void run() {
+			final byte[] result = new byte[1]; // Did the busy state end successfully?
 			getDisplay().syncExec(new Runnable() {
 				public void run() {
 					if (getDisplay() != null && !getDisplay().isDisposed())
-						endBusyStateInternal();
+						endBusyStateInternal(result);
 				}
 			});
+			if (result[0] == 1) {
+				fBusyTimer.cancel();
+			}
 		}
 
 	}
@@ -830,6 +841,31 @@
 
 	private class CharacterPairListener implements VerifyKeyListener {
 		private CharacterPairing[] fInserters = new CharacterPairing[0];
+		private ICompletionListener fCompletionListener;
+		private boolean fIsCompleting = false;
+
+		public void installCompletionListener() {
+			ISourceViewer viewer = getSourceViewer();
+			if (viewer instanceof StructuredTextViewer) {
+				fCompletionListener = new ICompletionListener() {
+
+					public void assistSessionStarted(ContentAssistEvent event) {
+						fIsCompleting = true;
+					}
+
+					public void assistSessionEnded(ContentAssistEvent event) {
+						fIsCompleting = false;
+					}
+
+					public void selectionChanged(ICompletionProposal proposal, boolean smartToggle) {
+					}
+					
+				};
+				ContentAssistantFacade facade = ((StructuredTextViewer) viewer).getContentAssistFacade();
+				if (facade != null)
+					facade.addCompletionListener(fCompletionListener);
+			}
+		}
 
 		/**
 		 * Add the pairing to the list of inserters
@@ -849,6 +885,13 @@
 		 * Perform cleanup on the character pair inserters
 		 */
 		void dispose() {
+			ISourceViewer viewer = getSourceViewer();
+			if (viewer instanceof StructuredTextViewer) {
+				ContentAssistantFacade facade = ((StructuredTextViewer) viewer).getContentAssistFacade();
+				if (facade != null)
+					facade.removeCompletionListener(fCompletionListener);
+			}
+
 			for (int i = 0; i < fInserters.length; i++) {
 				final AbstractCharacterPairInserter inserter = fInserters[i].inserter;
 				SafeRunner.run(new ISafeRunnable() {
@@ -864,7 +907,7 @@
 		}
 
 		public void verifyKey(final VerifyEvent event) {
-			if (!event.doit || getInsertMode() != SMART_INSERT || isBlockSelectionModeEnabled() && isMultilineSelection())
+			if (!event.doit || getInsertMode() != SMART_INSERT || fIsCompleting || isBlockSelectionModeEnabled() && isMultilineSelection())
 				return;
 			final boolean[] paired = { false };
 			for (int i = 0; i < fInserters.length; i++) {
@@ -1291,7 +1334,7 @@
 		// override the cut/paste/delete action to make
 		// them run on read-only
 		// files
-		Action action = new TextOperationAction(resourceBundle, "Editor_Cut_", this, ITextOperationTarget.CUT, true); //$NON-NLS-1$
+		Action action = new TextOperationAction(resourceBundle, "Editor_Cut_", this, ITextOperationTarget.CUT); //$NON-NLS-1$
 		action.setActionDefinitionId(IWorkbenchActionDefinitionIds.CUT);
 		setAction(ITextEditorActionConstants.CUT, action);
 		helpSystem.setHelp(action, IAbstractTextEditorHelpContextIds.CUT_ACTION);
@@ -1301,7 +1344,7 @@
 		// override the cut/paste/delete action to make
 		// them run on read-only
 		// files
-		action = new TextOperationAction(resourceBundle, "Editor_Paste_", this, ITextOperationTarget.PASTE, true); //$NON-NLS-1$
+		action = new TextOperationAction(resourceBundle, "Editor_Paste_", this, ITextOperationTarget.PASTE); //$NON-NLS-1$
 		action.setActionDefinitionId(IWorkbenchActionDefinitionIds.PASTE);
 		setAction(ITextEditorActionConstants.PASTE, action);
 		helpSystem.setHelp(action, IAbstractTextEditorHelpContextIds.PASTE_ACTION);
@@ -1312,14 +1355,14 @@
 		// override the cut/paste/delete action to make
 		// them run on read-only
 		// files
-		action = new TextOperationAction(resourceBundle, "Editor_Delete_", this, ITextOperationTarget.DELETE, true); //$NON-NLS-1$
+		action = new TextOperationAction(resourceBundle, "Editor_Delete_", this, ITextOperationTarget.DELETE); //$NON-NLS-1$
 		action.setActionDefinitionId(IWorkbenchActionDefinitionIds.DELETE);
 		setAction(ITextEditorActionConstants.DELETE, action);
 		helpSystem.setHelp(action, IAbstractTextEditorHelpContextIds.DELETE_ACTION);
 		// SourceView Action - requesting content assist to
 		// show completetion
 		// proposals for the current insert position
-		action = new TextOperationAction(resourceBundle, StructuredTextEditorActionConstants.ACTION_NAME_CONTENTASSIST_PROPOSALS + UNDERSCORE, this, ISourceViewer.CONTENTASSIST_PROPOSALS, true);
+		action = new TextOperationAction(resourceBundle, StructuredTextEditorActionConstants.ACTION_NAME_CONTENTASSIST_PROPOSALS + UNDERSCORE, this, ISourceViewer.CONTENTASSIST_PROPOSALS);
 		helpSystem.setHelp(action, IHelpContextIds.CONTMNU_CONTENTASSIST_HELPID);
 		action.setActionDefinitionId(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS);
 		setAction(StructuredTextEditorActionConstants.ACTION_NAME_CONTENTASSIST_PROPOSALS, action);
@@ -1367,14 +1410,25 @@
 
 		computeAndSetDoubleClickAction();
 		
-		IHandler handler = new GotoMatchingBracketHandler();
-	    IHandlerService handlerService = (IHandlerService) getSite().getService(IHandlerService.class);
-	    if (handlerService != null)
-	      handlerService.activateHandler(ActionDefinitionIds.GOTO_MATCHING_BRACKET, handler);
-	    if (handlerService != null) {
-	    	fOutlineHandler = new QuickOutlineHandler();
+		//add handlers to handler service
+		IHandlerService handlerService = (IHandlerService) getSite().getService(IHandlerService.class);
+		if (handlerService != null) {
+			
+			IHandler gotoHandler = new GotoMatchingBracketHandler();
+			handlerService.activateHandler(ActionDefinitionIds.GOTO_MATCHING_BRACKET, gotoHandler);
+			
+			fOutlineHandler = new QuickOutlineHandler();
 	    	handlerService.activateHandler(ActionDefinitionIds.SHOW_OUTLINE, fOutlineHandler);
-	    }
+			
+			IHandler toggleCommentHandler = new ToggleLineCommentHandler();
+			handlerService.activateHandler(ActionDefinitionIds.TOGGLE_COMMENT, toggleCommentHandler);
+			
+			IHandler addCommentBlockHandler = new AddBlockCommentHandler();
+			handlerService.activateHandler(ActionDefinitionIds.ADD_BLOCK_COMMENT, addCommentBlockHandler);
+			
+			IHandler removeCommentBlockHandler = new RemoveBlockCommentHandler();
+			handlerService.activateHandler(ActionDefinitionIds.REMOVE_BLOCK_COMMENT, removeCommentBlockHandler);
+		}
 
 		fShowPropertiesAction = new ShowPropertiesAction(getEditorPart(), getSelectionProvider());
 		fFoldingGroup = new FoldingActionGroup(this, getSourceViewer());
@@ -1489,8 +1543,10 @@
 		}
 		installCharacterPairing();
 		ISourceViewer viewer = getSourceViewer();
-		if (viewer instanceof ITextViewerExtension)
+		if (viewer instanceof ITextViewerExtension) {
 			((ITextViewerExtension) viewer).appendVerifyKeyListener(fPairInserter);
+			fPairInserter.installCompletionListener();
+		}
 		
 	}
 
@@ -1960,10 +2016,12 @@
 	 * ... but expected to be gaurded there with ILock, plus, can be called
 	 * directly from timer thread, so the timer's run method guards with ILock
 	 * too.
+	 * 
+	 * Set result[0] to 1 if the busy state was ended successfully
 	 */
-	private void endBusyStateInternal() {
+	private void endBusyStateInternal(byte[] result) {
 		if (fBackgroundJobEnded) {
-			fBusyTimer.cancel();
+			result[0] = 1;
 			showBusy(false);
 
 			ISourceViewer viewer = getSourceViewer();
@@ -2682,8 +2740,7 @@
 		else {
 			implClass = "document was null"; //$NON-NLS-1$
 		}
-		Logger.log(Logger.WARNING, "        Unexpected IDocumentProvider implementation: " + getDocumentProvider().getClass().getName()); //$NON-NLS-1$
-		Logger.log(Logger.WARNING, "        Unexpected IDocument implementation: " + implClass); //$NON-NLS-1$
+		Logger.log(Logger.WARNING, "Unexpected IDocument implementation: " + implClass + "\n\tIDocumentProvider implementation: " + getDocumentProvider().getClass().getName()); //$NON-NLS-1$  //$NON-NLS-2$
 	}
 
 	/*
@@ -2979,8 +3036,15 @@
 			fStatusLineLabelProvider.dispose();
 		}
 
+		String configurationId = fViewerConfigurationTargetId;
 		updateSourceViewerConfiguration();
 
+		/* Only reinstall if the configuration id has changed */
+		if (configurationId != null && !configurationId.equals(fViewerConfigurationTargetId)) {
+			uninstallSemanticHighlighting();
+			installSemanticHighlighting();
+		}
+
 		if (getSourceViewerConfiguration() instanceof StructuredTextViewerConfiguration) {
 			fStatusLineLabelProvider = ((StructuredTextViewerConfiguration) getSourceViewerConfiguration()).getStatusLineLabelProvider(getSourceViewer());
 			updateStatusLine(null);
diff --git a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/StructuredTextViewerConfiguration.java b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/StructuredTextViewerConfiguration.java
index 1bcf291..5008211 100644
--- a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/StructuredTextViewerConfiguration.java
+++ b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/StructuredTextViewerConfiguration.java
@@ -48,6 +48,8 @@
 import org.eclipse.swt.graphics.Color;
 import org.eclipse.swt.graphics.RGB;
 import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IWorkbenchPreferenceConstants;
+import org.eclipse.ui.PlatformUI;
 import org.eclipse.ui.editors.text.EditorsUI;
 import org.eclipse.ui.editors.text.TextSourceViewerConfiguration;
 import org.eclipse.ui.texteditor.ChainedPreferenceStore;
@@ -258,6 +260,7 @@
 			fContentAssistant.setProposalPopupOrientation(IContentAssistant.PROPOSAL_OVERLAY);
 			fContentAssistant.setContextInformationPopupOrientation(IContentAssistant.CONTEXT_INFO_ABOVE);
 			fContentAssistant.setInformationControlCreator(getInformationControlCreator(sourceViewer));
+			fContentAssistant.enableColoredLabels(PlatformUI.getPreferenceStore().getBoolean(IWorkbenchPreferenceConstants.USE_COLORED_LABELS));
 
 			// set content assist preferences
 			if (fPreferenceStore != null) {
diff --git a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/contentassist/AutoActivationDelegate.java b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/contentassist/AutoActivationDelegate.java
new file mode 100644
index 0000000..932db61
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/contentassist/AutoActivationDelegate.java
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *******************************************************************************/
+package org.eclipse.wst.sse.ui.contentassist;
+
+public abstract class AutoActivationDelegate {
+
+	public char[] getCompletionProposalAutoActivationCharacters() {
+		return null;
+	}
+
+	public char[] getContextInformationAutoActivationCharacters() {
+		return null;
+	}
+
+	public abstract void dispose();
+}
diff --git a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/contentassist/StructuredContentAssistProcessor.java b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/contentassist/StructuredContentAssistProcessor.java
index 3799a35..80c7417 100644
--- a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/contentassist/StructuredContentAssistProcessor.java
+++ b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/contentassist/StructuredContentAssistProcessor.java
@@ -150,7 +150,7 @@
 	private final String fPartitionTypeID;
 	
 	/** Content assistant used for giving the user status messages and listening to completion results*/
-	private final ContentAssistant fAssistant;
+	private ContentAssistant fAssistant;
 
 	/* cycling stuff */
 	private int fRepetition= -1;
@@ -170,10 +170,14 @@
 	 * a document is set for this processors associated viewer.
 	 */
 	private ITextInputListener fTextInputListener;
+
+	private CompletionListener fCompletionListener;
 	
 	/** the context information validator for this processor */
 	private IContextInformationValidator fContextInformationValidator;
 	
+	private AutoActivationDelegate fAutoActivation;
+
 	/**
 	 * <p>Create a new content assist processor for a specific partition type. 
 	 * The content type will be determined when a document is set on the viewer</p>
@@ -225,7 +229,8 @@
 		
 		//add completion listener
 		fAssistant = assistant;
-		fAssistant.addCompletionListener(new CompletionListener());
+		fCompletionListener = new CompletionListener();
+		fAssistant.addCompletionListener(fCompletionListener);
 		
 		//lazy load these to speed up initial editor opening
 		fLegacyExtendedContentAssistProcessors = null;
@@ -288,7 +293,7 @@
 	 * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getCompletionProposalAutoActivationCharacters()
 	 */
 	public char[] getCompletionProposalAutoActivationCharacters() {
-		return null;
+		return (fAutoActivation != null) ? fAutoActivation.getCompletionProposalAutoActivationCharacters() : null;
 	}
 
 	/**
@@ -298,7 +303,7 @@
 	 * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getContextInformationAutoActivationCharacters()
 	 */
 	public char[] getContextInformationAutoActivationCharacters() {
-		return null;
+		return (fAutoActivation != null) ? fAutoActivation.getContextInformationAutoActivationCharacters() : null;
 	}
 
 	/**
@@ -324,21 +329,43 @@
 		return this.fContextInformationValidator;
 	}
 	
+	public void install(ITextViewer viewer) {
+		if (fPreferenceStore != null) {
+			fPreferenceStore.addPropertyChangeListener(this);
+		}
+		if (fViewer != null) {
+			fViewer.removeTextInputListener(fTextInputListener);
+		}
+		fViewer = viewer;
+		if (fViewer != null) {
+			fViewer.addTextInputListener(fTextInputListener);
+		}
+		if (fAssistant != null) {
+			fAssistant.addCompletionListener(fCompletionListener);
+		}
+	}
+
 	/**
 	 * <p>Extenders may override, but should always be sure to call the super implementation</p>
 	 * 
 	 * @see org.eclipse.wst.sse.ui.internal.IReleasable#release()
 	 */
 	public void release() {
+		if (fAutoActivation != null) {
+			fAutoActivation.dispose();
+			fAutoActivation = null;
+		}
 		if(this.fPreferenceStore != null) {
 			this.fPreferenceStore.removePropertyChangeListener(this);
-			this.fPreferenceStore = null;
 		}
 		
 		if(this.fViewer != null) {
 			this.fViewer.removeTextInputListener(this.fTextInputListener);
 			this.fViewer = null;
 		}
+		if (this.fAssistant != null) {
+			this.fAssistant.removeCompletionListener(fCompletionListener);
+		}
 	}
 	
 	/**
@@ -461,7 +488,9 @@
 			while (iter.hasNext()) {
 				IContentAssistProcessor legacyProcessor = (IContentAssistProcessor) iter.next();
 				ICompletionProposal[] legacyComputed = legacyProcessor.computeCompletionProposals(viewer, offset);
-				proposals.addAll(Arrays.asList(legacyComputed));
+				if (legacyComputed != null) {
+					proposals.addAll(Arrays.asList(legacyComputed));
+				}
 			}
 		}
 		
@@ -713,7 +742,7 @@
 	 * @return the label of the category
 	 */
 	private String getCategoryLabel(int repetition) {
-		int iteration= repetition % fCategoryIteration.size();
+		int iteration= (fCategoryIteration != null ? repetition % fCategoryIteration.size() : 0);
 		if (iteration == 0)
 			return SSEUIMessages.ContentAssist_defaultProposalCategory_title;
 		return ((CompletionProposalCategory) ((List) fCategoryIteration.get(iteration)).get(0)).getDisplayName();
@@ -744,7 +773,7 @@
 	 * @return <code>true</code> if displaying first page, <code>false</code> otherwise
 	 */
 	private boolean isFirstPage() {
-		return fCategoryIteration.size() == 1 || fRepetition % fCategoryIteration.size() == 1;
+		return fCategoryIteration == null || fCategoryIteration.size() == 1 || fRepetition % fCategoryIteration.size() == 1;
 	}
 	
 	/**
@@ -882,6 +911,10 @@
 						model = StructuredModelManager.getModelManager().getModelForRead((IStructuredDocument)newInput);
 						if(model != null) {
 							fContentTypeID = model.getContentTypeIdentifier();
+							if (fAutoActivation != null) {
+								fAutoActivation.dispose();
+							}
+							fAutoActivation = CompletionProposalComputerRegistry.getDefault().getActivator(fContentTypeID, fPartitionTypeID);
 						}
 					} finally {
 						if(model != null) {
diff --git a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/SSEUIMessages.java b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/SSEUIMessages.java
index 7450860..8a7c7b0 100644
--- a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/SSEUIMessages.java
+++ b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/SSEUIMessages.java
@@ -90,6 +90,7 @@
 	public static String ToggleComment_tooltip;
 	public static String ToggleComment_image;
 	public static String ToggleComment_description;
+	public static String ToggleComment_progress;
 	public static String AddBlockComment_label;
 	public static String AddBlockComment_tooltip;
 	public static String AddBlockComment_image;
diff --git a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/SSEUIPluginResources.properties b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/SSEUIPluginResources.properties
index aa04685..f45338f 100644
--- a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/SSEUIPluginResources.properties
+++ b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/SSEUIPluginResources.properties
@@ -62,6 +62,7 @@
 ToggleComment_tooltip=Toggle Comment
 ToggleComment_image=
 ToggleComment_description=Toggle Comment
+ToggleComment_progress=Toggling line comments...
 AddBlockComment_label=Add &Block Comment
 AddBlockComment_tooltip=Add Block Comment
 AddBlockComment_image=
diff --git a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/StructuredMarkerAnnotation.java b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/StructuredMarkerAnnotation.java
index ed26973..2a725b5 100644
--- a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/StructuredMarkerAnnotation.java
+++ b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/StructuredMarkerAnnotation.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2001, 2006 IBM Corporation and others.
+ * Copyright (c) 2001, 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
@@ -106,7 +106,7 @@
 		IMarker marker = getMarker();
 		fAnnotationType = TemporaryAnnotation.ANNOT_UNKNOWN;
 		try {
-			if (marker.isSubtypeOf(IMarker.PROBLEM)) {
+			if (marker.exists() && marker.isSubtypeOf(IMarker.PROBLEM)) {
 				int severity = marker.getAttribute(IMarker.SEVERITY, -1);
 				switch (severity) {
 					case IMarker.SEVERITY_ERROR :
diff --git a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/StructuredTextViewer.java b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/StructuredTextViewer.java
index d9ba006..58f483d 100644
--- a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/StructuredTextViewer.java
+++ b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/StructuredTextViewer.java
@@ -28,6 +28,8 @@
 import org.eclipse.jface.text.Region;
 import org.eclipse.jface.text.TextSelection;
 import org.eclipse.jface.text.contentassist.IContentAssistant;
+import org.eclipse.jface.text.contentassist.IContentAssistantExtension2;
+import org.eclipse.jface.text.contentassist.IContentAssistantExtension4;
 import org.eclipse.jface.text.formatter.FormattingContext;
 import org.eclipse.jface.text.formatter.FormattingContextProperties;
 import org.eclipse.jface.text.formatter.IContentFormatterExtension;
@@ -37,6 +39,7 @@
 import org.eclipse.jface.text.projection.ProjectionDocument;
 import org.eclipse.jface.text.quickassist.IQuickAssistAssistant;
 import org.eclipse.jface.text.reconciler.IReconciler;
+import org.eclipse.jface.text.source.ContentAssistantFacade;
 import org.eclipse.jface.text.source.IAnnotationModel;
 import org.eclipse.jface.text.source.IOverviewRuler;
 import org.eclipse.jface.text.source.IVerticalRuler;
@@ -101,6 +104,8 @@
 	 */
 	private boolean fFormatterSet = false;
 
+	private ContentAssistantFacade fContentAssistantFacade;
+
 	/**
 	 * @see org.eclipse.jface.text.source.SourceViewer#SourceViewer(Composite,
 	 *      IVerticalRuler, IOverviewRuler, boolean, int)
@@ -121,6 +126,13 @@
 		setRedraw(false);
 	}
 
+	protected void createControl(Composite parent, int styles) {
+		// Forces LEFT_TO_RIGHT orientation unless otherwise suggested
+		if ((styles & SWT.LEFT_TO_RIGHT) == 0 && (styles & SWT.RIGHT_TO_LEFT) == 0)
+			styles |= SWT.LEFT_TO_RIGHT;
+		super.createControl(parent, styles);
+	}
+
 	/*
 	 * (non-Javadoc)
 	 * 
@@ -209,6 +221,8 @@
 
 			if (fContentAssistant != null) {
 				fContentAssistant.install(this);
+				if (fContentAssistant instanceof IContentAssistantExtension2 && fContentAssistant instanceof IContentAssistantExtension4)
+					fContentAssistantFacade= new ContentAssistantFacade(fContentAssistant);
 				fContentAssistantInstalled = true;
 			}
 			else {
@@ -812,6 +826,10 @@
 		}
 	}
 
+	public ContentAssistantFacade getContentAssistFacade() {
+		return fContentAssistantFacade;
+	}
+
 	/**
 	 * Uninstalls anything that was installed by configure
 	 */
diff --git a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/comment/BlockCommentingStrategy.java b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/comment/BlockCommentingStrategy.java
new file mode 100644
index 0000000..5dade3e
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/comment/BlockCommentingStrategy.java
@@ -0,0 +1,138 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *******************************************************************************/
+package org.eclipse.wst.sse.ui.internal.comment;
+
+import java.util.List;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITypedRegion;
+import org.eclipse.jface.text.Region;
+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.ui.internal.Logger;
+
+/**
+ * <p>Represents a Block Comment commenting strategy</p>
+ */
+public class BlockCommentingStrategy extends CommentingStrategy {
+	/** the prefix of the block comment associated with this strategy */
+	private String fPrefix;
+	
+	/** the suffix of the block comment associated with this strategy */
+	private String fSuffix;
+	
+	/**
+	 * @param prefix the prefix of the block comment associated with this strategy
+	 * @param suffix the suffix of the block comment associated with this strategy
+	 */
+	public BlockCommentingStrategy(String prefix, String suffix) {
+		super();
+		this.fPrefix = prefix;
+		this.fSuffix = suffix;
+	}
+
+	/**
+	 * <p>When applying a block comment it also removes any block comments associated
+	 * with this strategy that would now be enclosed by the new block comment</p>
+	 * 
+	 * @see org.eclipse.wst.sse.ui.internal.comment.CommentingStrategy#apply(
+	 * 	org.eclipse.wst.sse.core.internal.provisional.IStructuredModel, int, int)
+	 */
+	public void apply(IStructuredDocument document, int offset, int length) throws BadLocationException {
+		int commentPrefixOffset = offset;
+		int commentSuffixOffset = commentPrefixOffset + length;
+		
+		try {
+			document.replace(commentSuffixOffset, 0, " " + this.fSuffix); //$NON-NLS-1$
+			this.remove(document, commentPrefixOffset + this.fPrefix.length(), length, false);
+			document.replace(commentPrefixOffset, 0, this.fPrefix + " "); //$NON-NLS-1$
+		}
+		catch (BadLocationException e) {
+			Logger.log(Logger.WARNING_DEBUG, e.getMessage(), e);
+		}
+	}
+
+	/**
+	 * @see org.eclipse.wst.sse.ui.internal.comment.CommentingStrategy#remove(
+	 * 	org.eclipse.jface.text.IDocument, int, int)
+	 */
+	public void remove(IStructuredDocument document, int offset, int length, boolean removeEnclosing) throws BadLocationException {
+		IRegion region = new Region(offset, length);
+		ITypedRegion[] typedRegions = document.computePartitioning(region.getOffset(), region.getLength());
+		List commentRegions = this.getAssociatedCommentedRegions(typedRegions);
+		
+		//remove in reverse order as to not effect offset of other regions
+		for(int i = commentRegions.size()-1; i >= 0; --i) {
+			try {
+				//get the comment region
+				ITypedRegion typedRegion = (ITypedRegion)commentRegions.get(i);
+				IRegion commentRegion = new Region(typedRegion.getOffset(), typedRegion.getLength());
+
+				/* because of the nature of structured regions the comment region could actually be a
+				 * sub region that needs to be drilled down too
+				 */
+				if(!this.alreadyCommenting(document, commentRegion)) {
+					IStructuredDocumentRegion structuredRegion =
+						document.getRegionAtCharacterOffset(commentRegion.getOffset());
+					
+					commentRegion = new Region(structuredRegion.getStartOffset(), structuredRegion.getLength());
+					
+					if(!this.alreadyCommenting(document, commentRegion)) {
+						ITextRegion enclosedRegion = structuredRegion.getRegionAtCharacterOffset(typedRegion.getOffset());
+						int enclosedOffset = structuredRegion.getStartOffset(enclosedRegion);
+						commentRegion = new Region(enclosedOffset, structuredRegion.getTextEndOffset(enclosedRegion)-enclosedOffset);
+					}
+				}
+				
+				//at this point should have found the comment region, if not there is an issue
+				if(this.alreadyCommenting(document, commentRegion)) {
+					String regionContent = document.get(commentRegion.getOffset(), commentRegion.getLength());
+					
+					//if found the comment prefix and suffix then uncomment, otherwise log error
+					int commentPrefixOffset = commentRegion.getOffset() + regionContent.indexOf(this.fPrefix);
+					int commentSuffixOffset = commentRegion.getOffset();
+					commentSuffixOffset += regionContent.lastIndexOf(this.fSuffix);
+					
+					//remove comment block depending on if its an enclosing comment block and weather that is allowed
+					if(removeEnclosing || (commentPrefixOffset >= offset && commentSuffixOffset <= offset+length)) {
+						uncomment(document, commentPrefixOffset, this.fPrefix, commentSuffixOffset, this.fSuffix);
+					}
+				} else {
+					Logger.log(Logger.ERROR,
+							"BlockCommentingStrategy#remove could not find the commenting region to remove"); //$NON-NLS-1$
+				}
+			} catch(BadLocationException e) {
+				Logger.logException("This should only ever happen if something has gone wrong with the partitioning", e); //$NON-NLS-1$
+			}
+		}
+	}
+	
+	/**
+	 * <p>A region is already commented by this strategy if it starts with the strategy's associated
+	 * prefix and ends with its associated suffix, ignoring any trailing or leading whitespace</p>
+	 * 
+	 * @see org.eclipse.wst.sse.ui.internal.comment.CommentingStrategy#alreadyCommenting(
+	 * 	org.eclipse.jface.text.IDocument, org.eclipse.jface.text.IRegion)
+	 */
+	public boolean alreadyCommenting(IStructuredDocument document, IRegion region) throws BadLocationException {
+		String regionContent = document.get(region.getOffset(), region.getLength()).trim();
+		return regionContent.startsWith(this.fPrefix) && regionContent.endsWith(this.fSuffix);
+	}
+	
+	/**
+	 * @see org.eclipse.wst.sse.ui.internal.comment.CommentingStrategy#clone()
+	 */
+	public Object clone() {
+		return new BlockCommentingStrategy(this.fPrefix, this.fSuffix);
+	}
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/comment/CommentingStrategy.java b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/comment/CommentingStrategy.java
new file mode 100644
index 0000000..c46248c
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/comment/CommentingStrategy.java
@@ -0,0 +1,355 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *******************************************************************************/
+package org.eclipse.wst.sse.ui.internal.comment;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITypedRegion;
+import org.eclipse.jface.text.Region;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+import org.eclipse.wst.sse.ui.internal.Logger;
+
+/**
+ * <p>Defines a commenting strategy defined by the <code>org.eclipse.wst.sse.ui.commentinStrategy</code>
+ * extension point and tracked by the {@link CommentingStrategyRegistry}.  Though it is important to
+ * note it is not a one to one relationship of {@link CommentingStrategy}s to extensions, there is actually
+ * one {@link CommentingStrategy} for each content type defined for each 
+ * <code>org.eclipse.wst.sse.ui.commentinStrategy</code> extension.<p>
+ * 
+ * <p>The expected use case is that a {@link CommentingStrategy} is created off the basic configuration
+ * of the extension point and then cloned for each associated content type and then each clone has
+ * its partition information set using {@link #setPartitionInformation}.
+ * Then the {@link CommentingStrategyRegistry} can be used to retrieve applicable {@link CommentingStrategy}s
+ * and apply them to documents.</p>
+ * 
+ * <p>It is important to note that any instance of a {@link CommentingStrategy} is only valid for a specific
+ * content type ID but this relationship is tracked by the {@link CommentingStrategyRegistry} and not by
+ * the strategy itself.  Thus any reference to the strategy being valid for specific or general partition
+ * types is implying it is already only valid for a specific content type</p>
+ */
+public abstract class CommentingStrategy {
+	/** <code>true</code> if this strategy has any required partition types, <code>false</code> otherwise */
+	private boolean fHasRequiredPartitionTypes;
+	
+	/**
+	 * <p>required partition type IDs that must be seen for this strategy to be valid, the number of them
+	 * that must be seen for the strategy to be valid is determined by {@link #fRequireAllRequiredPartitionTypes}
+	 * this requirement is waved if the optional {@link #fAssociatedCommentPartitionTypeID} is specified and
+	 * present because this strategy must be valid if its {@link #fAssociatedCommentPartitionTypeID} is present</p>
+	 * 
+	 * @see #fRequireAllRequiredPartitionTypes
+	 * @see #fAssociatedCommentPartitionTypeID
+	 */
+	private List fRequriedPartitionTypeIDs;
+	
+	/**
+	 * <p>if <code>true</code> then {@link #fAllowablePartitionTypeIDs} is ignored because
+	 * this strategy is valid for any partition type, if <code>false</code> then this
+	 * strategy is only valid for those partition types listed in {@link #fAllowablePartitionTypeIDs}</p>
+	 * 
+	 * @see #fAllowablePartitionTypeIDs
+	 */
+	private boolean fAllPartitionTypesAllowable;
+	
+	/**
+	 * <p>the partition types that this strategy is valid for, it is also automatically valid for
+	 * any partition types listed in {@link #fRequriedPartitionTypeIDs} and the optionally
+	 * specified {@link #fAssociatedCommentPartitionTypeID}</p>
+	 * 
+	 * @see #fAllPartitionTypesAllowable
+	 * @see #fRequriedPartitionTypeIDs
+	 * @see #fAssociatedCommentPartitionTypeID
+	 */
+	private List fAllowablePartitionTypeIDs;
+	
+	/**
+	 * an optional associated comment partition type ID, if this partition type is seen then the
+	 * the {@link #fRequriedPartitionTypeIDs} requirement is waved as to weather this strategy is
+	 * valid or not
+	 * 
+	 * @see #fRequriedPartitionTypeIDs
+	 */
+	private String fAssociatedCommentPartitionTypeID;
+	
+	/**
+	 * <p>Default constructor, the specific initialization is done by
+	 * {@link #setPartitionInformation}</p>
+	 */
+	public CommentingStrategy() {
+		this.fAssociatedCommentPartitionTypeID = null;
+		this.fRequriedPartitionTypeIDs = Collections.EMPTY_LIST;
+		this.fAllowablePartitionTypeIDs = Collections.EMPTY_LIST;
+		this.fHasRequiredPartitionTypes = false;
+		this.fAllPartitionTypesAllowable = false;
+	}
+	
+	/**
+	 * <p>Used to set up the partition information for this strategy</p>
+	 * <p>This information is used to determine if a strategy is valid for a set of
+	 * {@link ITypedRegion}s.</p>
+	 * 
+	 * @param allowablePartitionTypeIDs the partition types this strategy is valid for, the strategy will also
+	 * be considered valid for any of the required partition types
+	 * @param allPartitionTypesAllowable if <code>true</code> then this strategy is valid for any partition types
+	 * thus ignoring the <code>allowablePartitionTypeIDs</code>, <code>false</code> otherwise
+	 * @param requiredPartitionTypeIDs partition type IDs that must be seen for this strategy to be valid, there
+	 * are exceptions to this rule, see {@link #isApplicableFor(ITypedRegion[])}
+	 * @param requireAllRequiredPartitionTypes <code>true</code> if all of the <code>requiredPartitionTypeIDs must
+	 * be seen for this strategy to be valid, <code>false</code> otherwise, there are exceptions to these rules, see
+	 * {@link #isApplicableFor(ITypedRegion[])}
+	 * @param associatedCommentPartitionTypeID optional comment partition type associated with this strategy,
+	 * maybe <code>null</code>
+	 * 
+	 * @see #isApplicableFor(ITypedRegion[])
+	 */
+	protected final void setPartitionInformation(List allowablePartitionTypeIDs, boolean allPartitionTypesAllowable,
+			List requiredPartitionTypeIDs, String associatedCommentPartitionTypeID) {
+		
+		this.fAllPartitionTypesAllowable = allPartitionTypesAllowable;
+		
+		this.fRequriedPartitionTypeIDs = requiredPartitionTypeIDs;
+		if(this.fRequriedPartitionTypeIDs == null) {
+			this.fRequriedPartitionTypeIDs = Collections.EMPTY_LIST;
+		}
+		
+		this.fHasRequiredPartitionTypes = this.fRequriedPartitionTypeIDs.size() != 0;
+		
+		this.fAllowablePartitionTypeIDs = allowablePartitionTypeIDs;
+		if(this.fAllowablePartitionTypeIDs == null) {
+			this.fAllowablePartitionTypeIDs = Collections.EMPTY_LIST;
+		}
+		
+		this.fAssociatedCommentPartitionTypeID = associatedCommentPartitionTypeID;
+	}
+	
+	/**
+	 * <p>Applies this strategy to the given model starting at the given offset for the given length</p>
+	 * 
+	 * @param document {@link IStructuredDocument} to apply this strategy too
+	 * @param offset the offset to start this comment at
+	 * @param length the length of the region to apply this comment too
+	 * 
+	 * @throws BadLocationException it is not the fault of the strategy if callers passes a bad
+	 * <code>offset</code> and/or <code>length</code> for the given <code>model</code>
+	 */
+	public abstract void apply(IStructuredDocument document, int offset, int length) throws BadLocationException;
+	
+	/**
+	 * <p>Remove any comments associated with this strategy from the given model for the given offset to
+	 * the given length.  Weather a comment surrounding the given range should be removed can also be
+	 * specified</p>
+	 * 
+	 * @param document {@link IStructuredDocument} to remove comments associated with this strategy from
+	 * @param offset the location to start removing comments associated with this strategy from
+	 * @param length the length of the region to remove associated comments from
+	 * @param removeEnclosing weather a comment should be removed if it incloses the region specified
+	 * by the given <code>offset</code> and <code>length</code>
+	 * 
+	 * @throws BadLocationException it is not the fault of the strategy if callers passes a bad
+	 * <code>offset</code> and/or <code>length</code> for the given <code>model</code>
+	 */
+	public abstract void remove(IStructuredDocument document, int offset, int length, boolean removeEnclosing) throws BadLocationException;
+	
+	/**
+	 * <p>Determines if the given region is a comment region commented by this strategy.</p>
+	 * 
+	 * @param document {@link IStructuredDocument} containing the given <code>region</code>
+	 * @param region determine if this region is a comment region commented by this strategy
+	 * @return <code>true</code> if the given <code>region</code> has already been
+	 * commented by this strategy, <code>false</code> otherwise
+	 * 
+	 * @throws BadLocationException it is not the fault of the strategy if callers passes a bad
+	 * <code>offset</code> and/or <code>length</code> for the given <code>model</code>
+	 */
+	public abstract boolean alreadyCommenting(IStructuredDocument document, IRegion region) throws BadLocationException;
+	
+	/** 
+	 * <p>Implementers should return a copy of themselves</p>
+	 * <p>Allows the {@link CommentingStrategyRegistry} to create a {@link CommentingStrategy} for
+	 * each of its associated content types.</p>
+	 * 
+	 * @return implementers should return an object of type {@link CommentingStrategy}
+	 * 
+	 * @see java.lang.Object#clone()
+	 */
+	public abstract Object clone();
+	
+	/**
+	 * <p>Determines if this strategy is applicable for the given regions for either commenting or un-commenting. 
+	 * For this strategy to be applicable the given regions must contain at least one or all of the
+	 * {@link #fRequriedPartitionTypeIDs} (depending on the value of {@link #fRequireAllRequiredPartitionTypes})
+	 * or contain at least one region of type {@link #fAssociatedCommentPartitionTypeID}.  Also if the value of
+	 * {@link #fAllPartitionTypesAllowable} is <code>false</code> the given regions must all be of type
+	 * {@link #fAllowablePartitionTypeIDs} and/or {@link #fRequriedPartitionTypeIDs} and/or
+	 * {@link #fAssociatedCommentPartitionTypeID} otherwise the regions can be of any type except for they still
+	 * must beet the required partition type requirements</p>
+	 * 
+	 * @param regions determine if this strategy is applicable for these regions
+	 * @return <code>true</code> if this strategy is applicable for the given <code>regions</code>
+	 * <code>false</code> otherwise.
+	 */
+	public final boolean isApplicableFor(ITypedRegion[] regions) {
+		List partitionTypeIDs = getPartitionTypeIDs(regions);
+		
+		boolean foundAssociatedCommentPartitions = false;
+		if(this.fAssociatedCommentPartitionTypeID != null) {
+			foundAssociatedCommentPartitions = partitionTypeIDs.contains(this.fAssociatedCommentPartitionTypeID);
+			if(foundAssociatedCommentPartitions) {
+				//remove all instances of the comment partition type
+				boolean removed;
+				do {
+					removed = partitionTypeIDs.remove(this.fAssociatedCommentPartitionTypeID);
+				} while(removed);
+			}
+		}
+		
+		//determine if required partitions requirements are met
+		boolean requiredPartitionsRequirementsMet = !this.fHasRequiredPartitionTypes ||
+			partitionTypeIDs.removeAll(this.fRequriedPartitionTypeIDs);
+		
+		//determine if allowable partitions requirements are met
+		boolean allowablePartitionsRequirementsMet = false;
+		if(this.fAllPartitionTypesAllowable) {
+			allowablePartitionsRequirementsMet = true;
+		} else {
+			partitionTypeIDs.removeAll(this.fAllowablePartitionTypeIDs);
+			
+			//at this point all required partitions and allowable partitions have been removed
+			allowablePartitionsRequirementsMet = partitionTypeIDs.size() == 0;
+		}
+		
+		return (requiredPartitionsRequirementsMet || foundAssociatedCommentPartitions) && allowablePartitionsRequirementsMet;
+	}
+	
+	/**
+	 * <p>Convenience method to take a list of regions and create one encompassing region to pass to
+	 * {@link #alreadyCommenting(IDocument, IRegion)}</p>
+	 * 
+	 * @param document {@link IDocument} that contains the given <code>regions</code>
+	 * @param regions {@link IRegion}s to combine into one region and pass onto
+	 * {@link #alreadyCommenting(IDocument, IRegion)}
+	 * 
+	 * @return the result of a call to {@link #alreadyCommenting(IDocument, IRegion)} combining
+	 * all of the given <code>regions</code> into one region
+	 * 
+	 * @throws BadLocationException it is not the fault of the strategy if callers passes a bad
+	 * <code>offset</code> and/or <code>length</code> for the given <code>model</code>
+	 */
+	public final boolean alreadyCommenting(IStructuredDocument document, IRegion[] regions) throws BadLocationException {
+		boolean alreadyCommenting = false;
+		if(regions != null && regions.length > 0) {
+			//create one region spanning all the given regions
+			int offset = regions[0].getOffset();
+			int length = regions[regions.length-1].getOffset() +
+					regions[regions.length-1].getLength() - offset;
+		
+			IRegion region = new Region(offset, length);
+			alreadyCommenting = this.alreadyCommenting(document, region);
+		}
+		
+		return alreadyCommenting;
+	}
+	/**
+	 * <p>Given a list of {@link ITypedRegion}s returns the sub set of that list that
+	 * are of the comment region type associated with this strategy</p>
+	 * 
+	 * @param typedRegions {@link ITypedRegion}s to filter down to only the comment regions
+	 * associated with this strategy
+	 * 
+	 * @return {@link List} of {@link ITypedRegion}s from the given <code>typedRegions</code>
+	 * that are of the comment partition type associated with this strategy
+	 */
+	protected List getAssociatedCommentedRegions(ITypedRegion[] typedRegions) {
+		List commentedRegions = new ArrayList();
+		
+		for(int i = 0; i < typedRegions.length; ++i) {
+			if(typedRegions[i].getType().equals(this.fAssociatedCommentPartitionTypeID)) {
+				commentedRegions.add(typedRegions[i]);
+			}
+		}
+		
+		return commentedRegions;
+	}
+	
+	/**
+	 * <p>Given a list of {@link ITypedRegion}s returns a list of the partition
+	 * type IDs taken from the given regions.</p>
+	 * 
+	 * @param regions {@link ITypedRegion}s to get the partition type IDs from
+	 * @return {@link List} of the partition type IDs taken from the given <code>regions</code>
+	 */
+	private static List getPartitionTypeIDs(ITypedRegion[] regions) {
+		List partitionTypes = new ArrayList(regions.length);
+		for(int i = 0; i < regions.length; ++i) {
+			partitionTypes.add(regions[i].getType());
+		}
+		
+		return partitionTypes;
+	}
+	
+	/**
+	 * <p>This method modifies the given document to remove the given comment
+	 * prefix at the given comment prefix offset and the given comment
+	 * suffix at the given comment suffix offset.  In the case of removing
+	 * a line comment that does not have a suffix, pass <code>null</code>
+	 * for the comment suffix and it and its associated offset will
+	 * be ignored.</p>
+	 * 
+	 * <p><b>NOTE:</b> it is a good idea if a model is at hand when calling this to
+	 * warn the model of an impending update</p>
+	 * 
+	 * @param document the document to remove the comment from
+	 * @param commentPrefixOffset the offset of the comment prefix
+	 * @param commentSuffixOffset the offset of the comment suffix
+	 * (ignored if <code>commentSuffix</code> is <code>null</code>)
+	 * @param commentPrefix the prefix of the comment to remove from its associated given offset
+	 * @param commentSuffix the suffix of the comment to remove from its associated given offset,
+	 * or null if there is not suffix to remove for this comment
+	 */
+	protected static void uncomment(IDocument document, int commentPrefixOffset, String commentPrefix,
+			int commentSuffixOffset,  String commentSuffix) {
+		
+		try {
+			//determine if there is a space after the comment prefix that should also be removed
+			int commentPrefixLength = commentPrefix.length();
+			String postCommentPrefixChar = document.get(commentPrefixOffset + commentPrefix.length(), 1);
+			if(postCommentPrefixChar.equals(" ")) {
+				commentPrefixLength++;
+			}
+			
+			//remove the comment prefix
+			document.replace(commentPrefixOffset, commentPrefixLength, ""); //$NON-NLS-1$
+			
+			if(commentSuffix != null) {
+				commentSuffixOffset -= commentPrefixLength;
+				
+				//determine if there is a space before the comment suffix that should also be removed
+				int commentSuffixLength = commentSuffix.length();
+				String preCommentSuffixChar = document.get(commentSuffixOffset-1, 1);
+				if(preCommentSuffixChar.equals(" ")) {
+					commentSuffixLength++;
+					commentSuffixOffset--;
+				}
+				
+				//remove the comment suffix
+				document.replace(commentSuffixOffset, commentSuffixLength, ""); //$NON-NLS-1$
+			}
+		}
+		catch (BadLocationException e) {
+			Logger.log(Logger.WARNING_DEBUG, e.getMessage(), e);
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/comment/CommentingStrategyRegistry.java b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/comment/CommentingStrategyRegistry.java
new file mode 100644
index 0000000..dbc9582
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/comment/CommentingStrategyRegistry.java
@@ -0,0 +1,351 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *******************************************************************************/
+package org.eclipse.wst.sse.ui.internal.comment;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.InvalidRegistryObjectException;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.content.IContentType;
+import org.eclipse.jface.text.ITypedRegion;
+import org.eclipse.wst.sse.ui.internal.Logger;
+import org.eclipse.wst.sse.ui.internal.SSEUIPlugin;
+
+/**
+ * <p>The registry of {@link CommentingStrategy}s defined by the <code>org.eclipse.wst.sse.ui.commentinStrategy</code>
+ * extension point.</p>
+ */
+public class CommentingStrategyRegistry {
+	/** The extension schema name of the extension point */
+	private static final String EXTENSION_POINT = "commentingStrategy"; //$NON-NLS-1$
+	
+	/** The extension schema name of proposal block comment child elements. */
+	private static final String ELEM_PROPOSAL_BLOCK_COMMENTING_STRATEGY = "blockCommentingStrategy"; //$NON-NLS-1$
+	
+	/** The extension schema name of proposal line comment child elements. */
+	private static final String ELEM_PROPOSAL_LINE_COMMENTING_STRATEGY = "lineCommentingStrategy"; //$NON-NLS-1$
+	
+	/** The extension schema name of the content type child elements. */
+	private static final String ELEM_CONTENT_TYPE = "contentType"; //$NON-NLS-1$
+	
+	/** The extension schema name of the required partition types child elements */
+	private static final String ELEM_REQUIRED_PARTITION_TYPES= "requiredPartitionTypes"; //$NON-NLS-1$
+	
+	/** The extension schema name of the allowable partition types child elements */
+	private static final String ELEM_ALLOWABLE_PARTITION_TYPES= "allowablePartitionTypes"; //$NON-NLS-1$
+	
+	/** The extension schema name of partition type child elements */
+	private static final String ELEM_PARTITION_TYPE= "partitionType"; //$NON-NLS-1$
+	
+	/** The extension schema name of the prefix attribute */
+	private static final String ATTR_PREFIX = "prefix"; //$NON-NLS-1$
+	
+	/** The extension schema name of the suffix attribute */
+	private static final String ATTR_SUFFIX = "suffix"; //$NON-NLS-1$
+	
+	/** The extension schema name of the associatedCommentPartitionTypeID attribute */
+	private static final String ATTR_ASSOCIATED_COMMENT_PARTITION_TPYPE_ID = "associatedCommentPartitionTypeID"; //$NON-NLS-1$
+	
+	/** The extension schema name of the anyPartitionType attribute */
+	private static final String ATTR_ANY_PARTITION_TYPE = "anyPartitionType";  //$NON-NLS-1$
+	
+	/** The extension schema name for ID attribute */
+	private static final String ATTR_ID= "id"; //$NON-NLS-1$
+	
+	/** the singleton instance of the registry */
+	private static CommentingStrategyRegistry fSingleton = null;
+	
+	/** <code>true</code> if this registry has been loaded. */
+	private boolean fLoaded;
+	
+	/**
+	 * <p>Registry of content type IDs to {@link BlockCommentingStrategy}s</p>
+	 * 
+	 * <code>{@link Map}&lt{@link String}, {@link List}&lt{@link BlockContentType}&gt&gt</code>
+	 * <ul>
+	 * <li><b>key:</b> content type ID</li>
+	 * <li><b>value:</b> {@link List} of associated {@link BlockContentType}s</li>
+	 * <ul>
+	 */
+	private Map fBlockCommentTypes;
+	
+	/**
+	 * <p>Registry of content type IDs to {@link LineCommentingStrategy}s</p>
+	 *
+	 * <code>{@link Map}&lt{@link String}, {@link List}&lt{@link LineContentType}&gt&gt</code>
+	 * <ul>
+	 * <li><b>key:</b> content type ID</li>
+	 * <li><b>value:</b> {@link List} of associated {@link LineContentType}s</li>
+	 * <ul>
+	 */
+	private Map fLineCommentTypes;
+	
+	/**
+	 * @return the single instance of the {@link CommentingStrategyRegistry}
+	 */
+	public static synchronized CommentingStrategyRegistry getDefault() {
+		if(fSingleton == null) {
+			fSingleton = new CommentingStrategyRegistry();
+		}
+		
+		return fSingleton;
+	}
+	
+	/**
+	 * Singleton constructor for the registry
+	 */
+	private CommentingStrategyRegistry() {
+		this.fLoaded = false;
+		this.fBlockCommentTypes = new HashMap();
+		this.fLineCommentTypes = new HashMap();
+	}
+	
+	/**
+	 * @param contentTypeID get only {@link BlockCommentingStrategy}s associated with this content type
+	 * @param regions get only {@link BlockCommentingStrategy}s associated with these types of regions
+	 * @return all the {@link BlockCommentingStrategy}s associated with the given content type and regions
+	 */
+	public CommentingStrategy getBlockCommentingStrategy(String contentTypeID, ITypedRegion[] regions) {
+		return getCommentingStrategy(contentTypeID, regions, this.fBlockCommentTypes);
+	}
+	
+	/**
+	 * @param contentTypeID get only {@link LineCommentingStrategy}s associated with this content type
+	 * @param regions get only {@link LineCommentingStrategy}s associated with these types of regions
+	 * @return all the {@link LineCommentingStrategy}s associated with the given content type and regions
+	 */
+	public CommentingStrategy getLineCommentingStrategy(String contentTypeID, ITypedRegion[] regions) {
+		return getCommentingStrategy(contentTypeID, regions, this.fLineCommentTypes);
+	}
+	
+	/**
+	 * <p>get all the {@link CommentingStrategy}s associated with the given content type and regions
+	 * from the given registry</p>
+	 * 
+	 * @param contentTypeID  get only {@link CommentingStrategy}s associated with this content type
+	 * @param regions get only {@link CommentingStrategy}s associated with these types of regions
+	 * @param registry get the {@link CommentingStrategy}s from this registry
+	 * @return all the {@link CommentingStrategy}s associated with the given content type and regions
+	 * from the given registry
+	 */
+	private CommentingStrategy getCommentingStrategy(String contentTypeID, ITypedRegion[] regions, Map registry) {
+		ensureExtensionPointRead();
+		
+		CommentingStrategy match = null;
+		IContentType contentType = Platform.getContentTypeManager().getContentType(contentTypeID);
+		
+		/* get all the commenting strategies for the given content type id,
+		 * including those registered for parent content types
+		 */
+		List possibleCommentingStrategies = new ArrayList();
+		while(contentType != null) {
+			List contentTypeCommentingStrategies = (List)registry.get(contentType.getId());
+			if(contentTypeCommentingStrategies != null && contentTypeCommentingStrategies.size() > 0) {
+				possibleCommentingStrategies.addAll(contentTypeCommentingStrategies);
+			}
+			contentType = contentType.getBaseType();
+		}
+		
+		/* find the commenting strategy applicable for the given regions,
+		 * because strategies were added starting from the most specific
+		 * content type first, the most specific strategy will always be chosen
+		 */
+		for(int i = 0; i < possibleCommentingStrategies.size() && match == null; ++i) {
+			CommentingStrategy commentType = (CommentingStrategy)possibleCommentingStrategies.get(i);
+			if(commentType.isApplicableFor(regions)) {
+				match = commentType;
+			}
+		}
+		
+		return match;
+	}
+	
+	/**
+	 * <p>Ensures that the extensions are read and this registry is built</p>
+	 */
+	private void ensureExtensionPointRead() {
+		if(!fLoaded) {
+			load();
+			fLoaded = true;
+		}
+	}
+	
+	/**
+	 * <p>Load the extension points into the registry</p>
+	 */
+	private void load() {
+		IExtensionRegistry extensionRegistry = Platform.getExtensionRegistry();
+		List extensionElements = new ArrayList(Arrays.asList(extensionRegistry.getConfigurationElementsFor(SSEUIPlugin.ID, EXTENSION_POINT)));
+	
+		//for each extension
+		for (Iterator iter= extensionElements.iterator(); iter.hasNext();) {
+			IConfigurationElement element = (IConfigurationElement) iter.next();
+			try {
+				CommentingStrategy newCommentingStrategy = null;
+				Map commentingStrategyRegistry = null;
+				//either a block or line commenting strategy
+				if(element.getName().equals(ELEM_PROPOSAL_BLOCK_COMMENTING_STRATEGY)) {
+					String prefix = element.getAttribute(ATTR_PREFIX);
+					checkExtensionAttributeNotNull(prefix, ATTR_PREFIX, element);
+					
+					String suffix = element.getAttribute(ATTR_SUFFIX);
+					checkExtensionAttributeNotNull(suffix, ATTR_SUFFIX, element);
+					
+					if(prefix != null && suffix != null) {
+						newCommentingStrategy = new BlockCommentingStrategy(prefix, suffix);
+						commentingStrategyRegistry = this.fBlockCommentTypes;
+					}
+				} else if(element.getName().equals(ELEM_PROPOSAL_LINE_COMMENTING_STRATEGY)) {
+					String prefix = element.getAttribute(ATTR_PREFIX);
+					checkExtensionAttributeNotNull(prefix, ATTR_PREFIX, element);
+					
+					if(prefix != null) {
+						newCommentingStrategy = new LineCommentingStrategy(prefix);
+						commentingStrategyRegistry = this.fLineCommentTypes;
+					}
+				}
+				
+				//add the new strategy to the registry
+				if(commentingStrategyRegistry != null && newCommentingStrategy != null) {
+					addCommentingStrategyToRegistry(element, commentingStrategyRegistry, newCommentingStrategy);
+				} else {
+					Logger.log(Logger.WARNING, "Invalid CommentingStrategy extension: " + element); //$NON-NLS-1$
+				}
+			} catch (CoreException e) {
+				Logger.logException(e);
+			} catch (InvalidRegistryObjectException x) {
+				/* Element is not valid any longer as the contributing plug-in was unloaded or for
+				 * some other reason. Do not include the extension in the list and log it
+				 */
+				String message = "The extension ''" + element.toString() + "'' is invalid."; //$NON-NLS-1$ //$NON-NLS-2$
+				IStatus status= new Status(IStatus.WARNING, SSEUIPlugin.ID, IStatus.WARNING, message, x);
+				Logger.log(status);
+			}
+		}
+	}
+	
+	/**
+	 * <p>Checks that the given attribute value is not <code>null</code>.</p>
+	 *
+	 * @param value the object to check if not null
+	 * @param attribute the attribute
+	 * 
+	 * @throws InvalidRegistryObjectException if the registry element is no longer valid
+	 * @throws CoreException if <code>value</code> is <code>null</code>
+	 */
+	private static void checkExtensionAttributeNotNull(Object value, String attribute,
+			IConfigurationElement element) throws InvalidRegistryObjectException, CoreException {
+		
+		if (value == null) {
+			String message = "The extension \"" + element.getDeclaringExtension().getUniqueIdentifier() + //$NON-NLS-1$
+				"\" from plug-in \"" + element.getContributor().getName() + //$NON-NLS-1$
+				"\" did not specify a value for the required \"" + attribute + //$NON-NLS-1$
+				"\" attribute for the element \"" + element.getName() + "\". Disabling the extension."; //$NON-NLS-1$ //$NON-NLS-2$
+			IStatus status= new Status(IStatus.WARNING, SSEUIPlugin.ID, IStatus.OK, message, null);
+			throw new CoreException(status);
+		}
+	}
+	
+	/**
+	 * <p>Using the content type element children of the given element add a copy of the given
+	 * base commenting strategy to the given registry</p>
+	 * 
+	 * @param element a {@link IConfigurationElement} with contentType element children
+	 * @param commentingStrategyRegistry {@link Map} of content type ids to {@link CommentingStrategy}s to register
+	 * the given {@link CommentingStrategy} with based on the <code>element</code>
+	 * @param baseCommentingStrategy {@link CommentingStrategy} that will be cloned and configured for each
+	 * content type in the given <code>element</code>
+	 */
+	private static void addCommentingStrategyToRegistry(IConfigurationElement element,
+			Map commentingStrategyRegistry, CommentingStrategy baseCommentingStrategy) {
+		
+		//get all the content type elements
+		IConfigurationElement[] contentTypeElements = element.getChildren(ELEM_CONTENT_TYPE);
+		if(contentTypeElements.length > 0) {
+			for(int contentTypeIndex = 0; contentTypeIndex < contentTypeElements.length; ++contentTypeIndex) {
+				try {
+					String contentTypeID = contentTypeElements[contentTypeIndex].getAttribute(ATTR_ID);
+					checkExtensionAttributeNotNull(contentTypeID, ATTR_ID, contentTypeElements[contentTypeIndex]);
+					
+					List commentTypes = (List)commentingStrategyRegistry.get(contentTypeID);
+					if(commentTypes == null) {
+						commentTypes = new ArrayList();
+						commentingStrategyRegistry.put(contentTypeID, commentTypes);
+					}
+					
+					//this element is required
+					List allowablePartitionTypeIDs = new ArrayList();
+					IConfigurationElement[] allowablePartitionTypes =
+						contentTypeElements[contentTypeIndex].getChildren(ELEM_ALLOWABLE_PARTITION_TYPES);
+					boolean anyPartitionType = false;
+					//determine anyPartitionType attribute value
+					String anyPartitionTypeValue = allowablePartitionTypes[0].getAttribute(ATTR_ANY_PARTITION_TYPE);
+					if(anyPartitionTypeValue != null) {
+						anyPartitionType = Boolean.valueOf(anyPartitionTypeValue).booleanValue();
+					}
+					
+					//get the optional partition types
+					allowablePartitionTypes = allowablePartitionTypes[0].getChildren(ELEM_PARTITION_TYPE);
+					if(allowablePartitionTypes.length > 0) {
+						for (int partitionTypeIndex = 0; partitionTypeIndex < allowablePartitionTypes.length; ++partitionTypeIndex) {
+							String partitionTypeID = allowablePartitionTypes[partitionTypeIndex].getAttribute(ATTR_ID);
+							checkExtensionAttributeNotNull(partitionTypeID, ATTR_ID, allowablePartitionTypes[partitionTypeIndex]);
+							
+							allowablePartitionTypeIDs.add(partitionTypeID);
+						}
+					}
+					
+					//this element is optional
+					List requiredPartitionTypeIDs = new ArrayList();
+					IConfigurationElement[] requiredPartitionTypes =
+						contentTypeElements[contentTypeIndex].getChildren(ELEM_REQUIRED_PARTITION_TYPES);
+					if(requiredPartitionTypes.length > 0) {
+						//get the required partition types
+						requiredPartitionTypes = requiredPartitionTypes[0].getChildren(ELEM_PARTITION_TYPE);
+						if(requiredPartitionTypes.length > 0) {
+							for (int partitionTypeIndex = 0; partitionTypeIndex < requiredPartitionTypes.length; ++partitionTypeIndex) {
+								String partitionTypeID = requiredPartitionTypes[partitionTypeIndex].getAttribute(ATTR_ID);
+								checkExtensionAttributeNotNull(partitionTypeID, ATTR_ID, requiredPartitionTypes[partitionTypeIndex]);
+								
+								requiredPartitionTypeIDs.add(partitionTypeID);
+							}
+						}
+					}
+					
+					//get the optional associated comment partition type ID
+					String associatedCommentPartitionTypeID =
+						contentTypeElements[contentTypeIndex].getAttribute(ATTR_ASSOCIATED_COMMENT_PARTITION_TPYPE_ID);
+					
+					//register the strategy
+					CommentingStrategy newCommentingStrategy = (CommentingStrategy)baseCommentingStrategy.clone();
+					newCommentingStrategy.setPartitionInformation(allowablePartitionTypeIDs, anyPartitionType,
+							requiredPartitionTypeIDs, associatedCommentPartitionTypeID);
+					commentTypes.add(newCommentingStrategy);
+				} catch(CoreException e) {
+					Logger.logException(e);
+				}
+			}
+		} else {
+			Logger.log(Logger.WARNING, "The commmenting strategy element: " + element +//$NON-NLS-1$
+					" does not contain any required " + ELEM_CONTENT_TYPE + "s"); //$NON-NLS-1$ //$NON-NLS-2$
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/comment/LineCommentingStrategy.java b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/comment/LineCommentingStrategy.java
new file mode 100644
index 0000000..b8d8697
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/comment/LineCommentingStrategy.java
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *******************************************************************************/
+package org.eclipse.wst.sse.ui.internal.comment;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+
+/**
+ * <p>Represents a Line Comment commenting strategy</p>
+ */
+public class LineCommentingStrategy extends CommentingStrategy {
+	/** the prefix of the line comment associated with this strategy */
+	private String fPrefix;
+	
+	/**
+	 * @param prefix the prefix of the line comment associated with this strategy
+	 */
+	public LineCommentingStrategy(String prefix) {
+		super();
+		this.fPrefix = prefix;
+	}
+	
+	/**
+	 * <p>Assumes that the given offset is at the begining of a line and adds the line
+	 * comment prefix there</p>
+	 * 
+	 * @see org.eclipse.wst.sse.ui.internal.comment.CommentingStrategy#apply(
+	 * 	org.eclipse.wst.sse.core.internal.provisional.IStructuredModel, int, int)
+	 */
+	public void apply(IStructuredDocument document, int offset, int length)
+			throws BadLocationException {
+		
+		document.replace(offset, 0, this.fPrefix + " ");
+	}
+
+	/**
+	 * <p>Assumes that the given offset is at the beginning of a line that is commented and removes
+	 * the comment prefix from the beginning of the line, leading whitespace on the line will not
+	 * prevent this method from finishing correctly</p>
+	 * 
+	 * @see org.eclipse.wst.sse.ui.internal.comment.CommentingStrategy#remove(
+	 * 	org.eclipse.wst.sse.core.internal.provisional.IStructuredModel, int, int, boolean)
+	 */
+	public void remove(IStructuredDocument document, int offset, int length, boolean removeEnclosing) throws BadLocationException{
+		String content = document.get(offset, length);
+		int innerOffset = content.indexOf(this.fPrefix);
+		if(innerOffset > 0) {
+			offset += innerOffset;
+		}
+		
+		uncomment(document, offset, this.fPrefix, -1,  null);
+	}
+	
+	/**
+	 * <p>A region is already commented if it begins with the the associated prefix ignoring any
+	 * leading whitespace</p>
+	 * 
+	 * @see org.eclipse.wst.sse.ui.internal.comment.CommentingStrategy#alreadyCommenting(
+	 * 	org.eclipse.jface.text.IDocument, org.eclipse.jface.text.IRegion)
+	 */
+	public boolean alreadyCommenting(IStructuredDocument document, IRegion region)
+			throws BadLocationException {
+		
+		String regionContent = document.get(region.getOffset(), region.getLength()).trim();
+		return regionContent.startsWith(this.fPrefix);
+	}
+	
+	/**
+	 * @see org.eclipse.wst.sse.ui.internal.comment.CommentingStrategy#clone()
+	 */
+	public Object clone() {
+		return new LineCommentingStrategy(this.fPrefix);
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/contentassist/CompletionProposalComputerDescriptor.java b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/contentassist/CompletionProposalComputerDescriptor.java
index 3825dc5..d36cca0 100644
--- a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/contentassist/CompletionProposalComputerDescriptor.java
+++ b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/contentassist/CompletionProposalComputerDescriptor.java
@@ -470,6 +470,7 @@
 						ContentAssistUtils.checkExtensionAttributeNotNull(partitionTypeID, ATTR_ID, partitionTypes[partitionTypeIndex]);
 						
 						CompletionProposalComputerRegistry.getDefault().putDescription(contentTypeID, partitionTypeID, desc);
+						CompletionProposalComputerRegistry.getDefault().putAutoActivator(contentTypeID, partitionTypeID, partitionTypes[partitionTypeIndex]);
 					}
 				} else {
 					CompletionProposalComputerRegistry.getDefault().putDescription(contentTypeID, null, desc);
diff --git a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/contentassist/CompletionProposalComputerRegistry.java b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/contentassist/CompletionProposalComputerRegistry.java
index 21b5b83..f3189a5 100644
--- a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/contentassist/CompletionProposalComputerRegistry.java
+++ b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/contentassist/CompletionProposalComputerRegistry.java
@@ -30,6 +30,7 @@
 import org.eclipse.core.runtime.Status;
 import org.eclipse.core.runtime.content.IContentType;
 import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.wst.sse.ui.contentassist.AutoActivationDelegate;
 import org.eclipse.wst.sse.ui.internal.Logger;
 import org.eclipse.wst.sse.ui.internal.SSEUIPlugin;
 
@@ -55,6 +56,9 @@
 	
 	/** The extension schema name for element ID attributes */
 	private static final String ATTR_ID= "id"; //$NON-NLS-1$
+
+	/** The extension schema name for the partition's auto-activation class */
+	private static final String ATTR_AUTO_ACTIVATION_CLASS = "autoActivationDelegate"; //$NON-NLS-1$
 	
 	/** preference key to keep track of the last known number of content assist computers */
 	private static final String NUM_COMPUTERS_PREF_KEY = "content_assist_number_of_computers"; //$NON-NLS-1$
@@ -109,6 +113,9 @@
 	 */
 	private final Map fDescriptors = new HashMap();
 
+	/** A map maintaining the relationship between content types, partition types and their associated {@link AutoActivationDelegate}s*/
+	private Map fAutoActivators = new HashMap();
+
 	/** The {@link CompletionProposalCategory}s tracked by this registry */
 	private final List fCategories = new ArrayList();
 	
@@ -235,6 +242,30 @@
 		context.putDescriptor(partitionTypeID, descriptor);
 	}
 
+	void putAutoActivator(String contentTypeID, String partitionTypeID, IConfigurationElement element) {
+		String autoActivationClass = element.getAttribute(ATTR_AUTO_ACTIVATION_CLASS);
+		if (autoActivationClass == null)
+			return;
+
+		Map partitionMap = (Map) fAutoActivators.get(contentTypeID);
+		if (partitionMap == null) {
+			partitionMap = new HashMap();
+			fAutoActivators.put(contentTypeID, partitionMap);
+		}
+		partitionMap.put(partitionTypeID, new Activator(element));
+	}
+
+	public AutoActivationDelegate getActivator(String contentTypeID, String partitionTypeID) {
+		Map partitionMap = (Map) fAutoActivators.get(contentTypeID);
+		if (partitionMap != null) {
+			Activator activator = (Activator) partitionMap.get(partitionTypeID);
+			if (activator != null) {
+				return activator.createAutoActivation();
+			}
+		}
+		return null;
+	}
+
 	/**
 	 * @param contentTypeID get only descriptors associated with this content type
 	 * @param partitionTypeID get only descriptors associated with this partition type as well
@@ -505,4 +536,24 @@
 		
 		return contexts;
 	}
+
+	private static class Activator {
+		IConfigurationElement fElement;
+
+		public Activator(IConfigurationElement element) {
+			fElement = element;
+		}
+
+		AutoActivationDelegate createAutoActivation() {
+			AutoActivationDelegate activation = null;
+			if (fElement != null) {
+				try {
+					activation = (AutoActivationDelegate) fElement.createExecutableExtension(ATTR_AUTO_ACTIVATION_CLASS);
+				} catch (CoreException e) {
+				}
+			}
+			return activation;
+		}
+
+	}
 }
diff --git a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/contentassist/CompoundContentAssistProcessor.java b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/contentassist/CompoundContentAssistProcessor.java
index 49c0ae7..7e89b43 100644
--- a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/contentassist/CompoundContentAssistProcessor.java
+++ b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/contentassist/CompoundContentAssistProcessor.java
@@ -35,6 +35,7 @@
 import org.eclipse.jface.text.contentassist.IContextInformationPresenter;
 import org.eclipse.jface.text.contentassist.IContextInformationValidator;
 import org.eclipse.swt.graphics.Image;
+import org.eclipse.wst.sse.ui.contentassist.StructuredContentAssistProcessor;
 import org.eclipse.wst.sse.ui.internal.IReleasable;
 import org.eclipse.wst.sse.ui.internal.Logger;
 
@@ -354,6 +355,15 @@
 		this.release();
 	}
 	
+	public void install(ITextViewer viewer) {
+		for (Iterator it = fProcessors.iterator(); it.hasNext();) {
+			IContentAssistProcessor p = (IContentAssistProcessor) it.next();
+			if (p instanceof StructuredContentAssistProcessor) {
+				((StructuredContentAssistProcessor) p).install(viewer);
+			}
+		}
+	}
+
 	/**
 	 * @see org.eclipse.wst.sse.ui.internal.IReleasable#release()
 	 */
@@ -365,7 +375,6 @@
 				((IReleasable) p).release();
 			}
 		}
-		fProcessors.clear();
 	}
 	
 	private static class WrappedContextInformation implements IContextInformation, IContextInformationExtension {
diff --git a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/contentassist/CustomCompletionProposal.java b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/contentassist/CustomCompletionProposal.java
index 61d9b5f..f39ba52 100644
--- a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/contentassist/CustomCompletionProposal.java
+++ b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/contentassist/CustomCompletionProposal.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2001, 2009 IBM Corporation and others.
+ * Copyright (c) 2001, 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
@@ -40,9 +40,9 @@
 
 	private String fDisplayString;
 
-	private Image fImage;
+	private String fAlternateMatch;
 
-	private int fOriginalReplacementLength;
+	private Image fImage;
 
 	private int fRelevance = IRelevanceConstants.R_NONE;
 
@@ -73,21 +73,25 @@
 	 * 
 	 */
 	public CustomCompletionProposal(String replacementString, int replacementOffset, int replacementLength, int cursorPosition, Image image, String displayString, IContextInformation contextInformation, String additionalProposalInfo, int relevance, boolean updateReplacementLengthOnValidate) {
+		this(replacementString, replacementOffset, replacementLength, cursorPosition, image, displayString, null, contextInformation, additionalProposalInfo, relevance, updateReplacementLengthOnValidate);
+	}
+
+	public CustomCompletionProposal(String replacementString, int replacementOffset, int replacementLength, int cursorPosition, Image image, String displayString, IContextInformation contextInformation, String additionalProposalInfo, int relevance) {
+		this(replacementString, replacementOffset, replacementLength, cursorPosition, image, displayString, contextInformation, additionalProposalInfo, relevance, true);
+	}
+
+	public CustomCompletionProposal(String replacementString, int replacementOffset, int replacementLength, int cursorPosition, Image image, String displayString, String alternateMatch, IContextInformation contextInformation, String additionalProposalInfo, int relevance, boolean updateReplacementLengthOnValidate) {
 		fReplacementString = replacementString;
 		fReplacementOffset = replacementOffset;
 		fReplacementLength = replacementLength;
 		fCursorPosition = cursorPosition;
 		fImage = image;
 		fDisplayString = displayString;
+		fAlternateMatch = alternateMatch;
 		fContextInformation = contextInformation;
 		fAdditionalProposalInfo = additionalProposalInfo;
 		fRelevance = relevance;
 		fUpdateLengthOnValidate = updateReplacementLengthOnValidate;
-		fOriginalReplacementLength = fReplacementLength;
-	}
-
-	public CustomCompletionProposal(String replacementString, int replacementOffset, int replacementLength, int cursorPosition, Image image, String displayString, IContextInformation contextInformation, String additionalProposalInfo, int relevance) {
-		this(replacementString, replacementOffset, replacementLength, cursorPosition, image, displayString, contextInformation, additionalProposalInfo, relevance, true);
 	}
 
 	public void apply(IDocument document) {
@@ -281,9 +285,7 @@
 			int length = offset - fReplacementOffset;
 			String start = document.get(fReplacementOffset, length);
 
-			if(word != null) {
-				return word.substring(0, length).equalsIgnoreCase(start);
-			}
+			return (word != null && word.substring(0, length).equalsIgnoreCase(start)) || (fAlternateMatch != null && length <= fAlternateMatch.length() && fAlternateMatch.substring(0, length).equalsIgnoreCase(start));
 		}
 		catch (BadLocationException x) {
 		}
@@ -308,12 +310,8 @@
 			return false;
 		boolean validated = startsWith(document, offset, fDisplayString);
 
-		if (fUpdateLengthOnValidate) {
-			// it would be better to use "originalCursorPosition" instead of
-			// getReplacementOffset(), but we don't have that info.
-			int newLength = offset - getReplacementOffset();
-			int delta = newLength - fOriginalReplacementLength;
-			fReplacementLength = delta + fOriginalReplacementLength;
+		if (fUpdateLengthOnValidate && event != null) {
+			fReplacementLength += event.fText.length() - event.fLength; //adjust the replacement length by the event's text replacement
 		}
 		return validated;
 	}
diff --git a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/contentassist/StructuredContentAssistant.java b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/contentassist/StructuredContentAssistant.java
index b10942c..8d124ce 100644
--- a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/contentassist/StructuredContentAssistant.java
+++ b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/contentassist/StructuredContentAssistant.java
@@ -15,6 +15,7 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import org.eclipse.jface.text.ITextViewer;
 import org.eclipse.jface.text.contentassist.ContentAssistant;
 import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
 import org.eclipse.wst.sse.ui.internal.IReleasable;
@@ -33,6 +34,8 @@
 	 */
 	private boolean fIsInitalized;
 	
+	private boolean fProcessorsReleased = false;
+
 	/**
 	 * <p>Construct the assistant</p>
 	 */
@@ -92,7 +95,19 @@
 		}
 		return compoundContentAssistProcessor;
 	}
-	
+
+	public void install(ITextViewer textViewer) {
+		if (fProcessorsReleased) {
+			if (this.fReleasableProcessors != null && !this.fReleasableProcessors.isEmpty()) {
+				for(int i = 0; i < this.fReleasableProcessors.size(); ++i) {
+					((CompoundContentAssistProcessor)this.fReleasableProcessors.get(i)).install(textViewer);
+				}
+			}
+			fProcessorsReleased = false;
+		}
+		super.install(textViewer);
+	}
+
 	/**
 	 * @see org.eclipse.jface.text.contentassist.ContentAssistant#uninstall()
 	 */
@@ -102,11 +117,8 @@
 			for(int i = 0; i < this.fReleasableProcessors.size(); ++i) {
 				((IReleasable)this.fReleasableProcessors.get(i)).release();
 			}
-			
-			this.fReleasableProcessors.clear();
 		}
-		this.fReleasableProcessors = null;
-		
+		fProcessorsReleased = true;
 		super.uninstall();
 	}
 }
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/debug/ToggleBreakpointAction.java b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/debug/ToggleBreakpointAction.java
index e211930..8cdb84f 100644
--- a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/debug/ToggleBreakpointAction.java
+++ b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/debug/ToggleBreakpointAction.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2001, 2009 IBM Corporation and others.
+ * Copyright (c) 2001, 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
@@ -185,7 +185,6 @@
 		IBreakpoint[] breakpoints = getBreakpoints(getMarkers());
 		for (int i = 0; i < breakpoints.length; i++) {
 			try {
-				breakpoints[i].getMarker().delete();
 				breakpointManager.removeBreakpoint(breakpoints[i], true);
 			}
 			catch (CoreException e) {
diff --git a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/derived/HTMLTextPresenter.java b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/derived/HTMLTextPresenter.java
index 86fa284..d56b2d5 100644
--- a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/derived/HTMLTextPresenter.java
+++ b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/derived/HTMLTextPresenter.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2005, 2006 IBM Corporation and others.
+ * Copyright (c) 2005, 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
@@ -21,6 +21,7 @@
 import org.eclipse.jface.text.Region;
 import org.eclipse.jface.text.TextPresentation;
 import org.eclipse.swt.custom.StyleRange;
+import org.eclipse.swt.graphics.Drawable;
 import org.eclipse.swt.graphics.GC;
 import org.eclipse.swt.widgets.Display;
 import org.eclipse.wst.sse.ui.internal.Logger;
@@ -30,7 +31,7 @@
  * Modifications were made to use own Logger to log exception, and the
  * ellipses constant
  */
-public class HTMLTextPresenter implements DefaultInformationControl.IInformationPresenter {
+public class HTMLTextPresenter implements DefaultInformationControl.IInformationPresenter, DefaultInformationControl.IInformationPresenterExtension {
 	private static final String ELLIPSES = "..."; //$NON-NLS-1$
 	private static final String LINE_DELIM = System.getProperty("line.separator", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
 
@@ -96,16 +97,26 @@
 		return (i == length ? line : line.substring(0, i)) + " "; //$NON-NLS-1$
 	}
 
-	/*
+	/**
 	 * @see IHoverInformationPresenter#updatePresentation(Display display,
 	 *      String, TextPresentation, int, int)
+	 * @deprecated Use {@link #updatePresentation(Drawable, String, TextPresentation, int, int)}
+	 *             instead
 	 */
 	public String updatePresentation(Display display, String hoverInfo, TextPresentation presentation, int maxWidth, int maxHeight) {
+		return updatePresentation((Drawable)display, hoverInfo, presentation, maxWidth, maxHeight);
+	}
+
+	/*
+	 * @see IHoverInformationPresenterExtension#updatePresentation(Drawable drawable, String, TextPresentation, int, int)
+	 * @since 3.2
+	 */
+	public String updatePresentation(Drawable drawable, String hoverInfo, TextPresentation presentation, int maxWidth, int maxHeight) {
 
 		if (hoverInfo == null)
 			return null;
 
-		GC gc = new GC(display);
+		GC gc = new GC(drawable);
 		try {
 
 			StringBuffer buffer = new StringBuffer();
diff --git a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/handlers/AbstractCommentHandler.java b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/handlers/AbstractCommentHandler.java
new file mode 100644
index 0000000..eab9187
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/handlers/AbstractCommentHandler.java
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.ui.internal.handlers;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.text.TextSelection;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.handlers.HandlerUtil;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+
+/**
+ * This class contains all of the shared functionality for comment handlers
+ */
+public abstract class AbstractCommentHandler extends AbstractHandler {
+
+	/**
+	 * <p>Default constructor must exist because sub classes are created by java reflection</p>
+	 */
+	public AbstractCommentHandler() {
+		super();
+	}
+
+	/**
+	 * <p>Gets the important information out of the event and passes it onto 
+	 * the internal method {@link #processAction}</p>
+	 * 
+	 * @see org.eclipse.wst.xml.ui.internal.handlers.CommentHandler#execute(org.eclipse.core.commands.ExecutionEvent)
+	 */
+	public final Object execute(ExecutionEvent event) throws ExecutionException {
+		IEditorPart editor = HandlerUtil.getActiveEditor(event);
+		ITextEditor textEditor = null;
+		if (editor instanceof ITextEditor)
+			textEditor = (ITextEditor) editor;
+		else {
+			Object o = editor.getAdapter(ITextEditor.class);
+			if (o != null)
+				textEditor = (ITextEditor) o;
+		}
+		if (textEditor != null) {
+			IDocument document = textEditor.getDocumentProvider().getDocument(textEditor.getEditorInput());
+			if (document != null && document instanceof IStructuredDocument) {
+				// get current text selection
+				ITextSelection textSelection = getCurrentSelection(textEditor);
+				if (!textSelection.isEmpty()) {
+					//call the implementers code to deal with the event
+					processAction(textEditor, (IStructuredDocument)document, textSelection);
+				}
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * <p>This method is called by the public {@link #execute} method whenever
+	 * the comment handler is invoked.  This method should be used for the
+	 * logic of handling the structured comment event.</p>
+	 * 
+	 * @param textEditor the text editor the initiating event was caused in
+	 * @param document the document the text editor is editing
+	 * @param textSelection the user selection when the event was caused
+	 */
+	protected abstract void processAction(ITextEditor textEditor, IStructuredDocument document, ITextSelection textSelection);
+	
+	/**
+	 * <p>Gets the current user selection in the given {@link ITextEditor}</p>
+	 * 
+	 * @param textEditor get the user selection from here
+	 * @return the current user selection in <code>textEdtior</code>
+	 */
+	private static ITextSelection getCurrentSelection(ITextEditor textEditor) {
+		ISelectionProvider provider = textEditor.getSelectionProvider();
+		if (provider != null) {
+			ISelection selection = provider.getSelection();
+			if (selection instanceof ITextSelection) {
+				return (ITextSelection) selection;
+			}
+		}
+		return TextSelection.emptySelection();
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/handlers/AddBlockCommentHandler.java b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/handlers/AddBlockCommentHandler.java
new file mode 100644
index 0000000..97f999e
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/handlers/AddBlockCommentHandler.java
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *******************************************************************************/
+package org.eclipse.wst.sse.ui.internal.handlers;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.DocumentRewriteSession;
+import org.eclipse.jface.text.DocumentRewriteSessionType;
+import org.eclipse.jface.text.IDocumentExtension4;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.text.ITypedRegion;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.Logger;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+import org.eclipse.wst.sse.ui.internal.SSEUIMessages;
+import org.eclipse.wst.sse.ui.internal.comment.CommentingStrategy;
+import org.eclipse.wst.sse.ui.internal.comment.CommentingStrategyRegistry;
+
+/**
+ * <p>A comment handler to add block comments</p>
+ */
+public final class AddBlockCommentHandler extends
+		AbstractCommentHandler {
+
+	/**
+	 * @see org.eclipse.wst.sse.ui.internal.handlers.AbstractCommentHandler#processAction(
+	 * 	org.eclipse.ui.texteditor.ITextEditor, org.eclipse.jface.text.IDocument, org.eclipse.jface.text.ITextSelection)
+	 */
+	protected void processAction(ITextEditor textEditor, IStructuredDocument document, ITextSelection textSelection) {
+		IStructuredModel model = null;
+		boolean changed = false;
+		DocumentRewriteSession session = null;
+		
+		try {
+			model = StructuredModelManager.getModelManager().getModelForEdit(document);
+			if(model != null) {
+				//makes it so one undo will undo all the edits to the document
+				model.beginRecording(this, SSEUIMessages.AddBlockComment_label, SSEUIMessages.AddBlockComment_description);
+				
+				//keeps listeners from doing anything until updates are all done
+				model.aboutToChangeModel();
+				if(document instanceof IDocumentExtension4) {
+					session = ((IDocumentExtension4)document).startRewriteSession(DocumentRewriteSessionType.UNRESTRICTED);
+				}
+				changed = true;
+				
+				ITypedRegion[] typedRegions = document.computePartitioning(textSelection.getOffset(), textSelection.getLength());
+				CommentingStrategy commentType = CommentingStrategyRegistry.getDefault().getBlockCommentingStrategy(model.getContentTypeIdentifier(), typedRegions);
+				
+				if(commentType != null) {
+					commentType.apply(document, textSelection.getOffset(), textSelection.getLength());
+				}
+			}
+		} catch (BadLocationException e) {
+			Logger.logException("The given selection " + textSelection + " must be invalid", e); //$NON-NLS-1$ //$NON-NLS-2$
+		} finally {
+			//clean everything up
+			if(session != null && document instanceof IDocumentExtension4) {
+				((IDocumentExtension4)document).stopRewriteSession(session);
+			}
+			
+			if(model != null) {
+				model.endRecording(this);
+				if(changed) {
+					model.changedModel();
+				}
+				model.releaseFromEdit();
+			}
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/handlers/RemoveBlockCommentHandler.java b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/handlers/RemoveBlockCommentHandler.java
new file mode 100644
index 0000000..5cf0beb
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/handlers/RemoveBlockCommentHandler.java
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *******************************************************************************/
+package org.eclipse.wst.sse.ui.internal.handlers;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.DocumentRewriteSession;
+import org.eclipse.jface.text.DocumentRewriteSessionType;
+import org.eclipse.jface.text.IDocumentExtension4;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.text.ITypedRegion;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+import org.eclipse.wst.sse.ui.internal.Logger;
+import org.eclipse.wst.sse.ui.internal.SSEUIMessages;
+import org.eclipse.wst.sse.ui.internal.comment.CommentingStrategy;
+import org.eclipse.wst.sse.ui.internal.comment.CommentingStrategyRegistry;
+
+/**
+ * <p>A comment handler to remove block comments</p>
+ */
+public final class RemoveBlockCommentHandler extends
+		AbstractCommentHandler {
+
+	/**
+	 * @see org.eclipse.wst.sse.ui.internal.handlers.AbstractCommentHandler#processAction(org.eclipse.ui.texteditor.ITextEditor, org.eclipse.jface.text.IDocument, org.eclipse.jface.text.ITextSelection)
+	 */
+	protected void processAction(ITextEditor textEditor, IStructuredDocument document, ITextSelection textSelection) {
+		
+		IStructuredModel model = null;
+		boolean changed = false;
+		DocumentRewriteSession session = null;
+		try {
+			model = StructuredModelManager.getModelManager().getModelForEdit(document);
+			
+			if(model != null) {
+				//makes it so one undo will undo all the edits to the document
+				model.beginRecording(this, SSEUIMessages.RemoveBlockComment_label,
+						SSEUIMessages.RemoveBlockComment_label);
+				
+				//keeps listeners from doing anything until updates are all done
+				model.aboutToChangeModel();
+				if(document instanceof IDocumentExtension4) {
+					session = ((IDocumentExtension4)document).startRewriteSession(
+							DocumentRewriteSessionType.UNRESTRICTED);
+				}
+				changed = true;
+				
+				ITypedRegion[] typedRegions = document.computePartitioning(
+						textSelection.getOffset(), textSelection.getLength());
+				CommentingStrategy commentType = CommentingStrategyRegistry.getDefault().getBlockCommentingStrategy(
+						model.getContentTypeIdentifier(), typedRegions);
+				
+				if(commentType != null) {
+					commentType.remove(document, textSelection.getOffset(), textSelection.getLength(), true);
+				}
+			}
+		} catch (BadLocationException e) {
+			Logger.logException("The given selection " + textSelection + " must be invalid", e); //$NON-NLS-1$ //$NON-NLS-2$
+		} finally {
+			//clean everything up
+			if(session != null && document instanceof IDocumentExtension4) {
+				((IDocumentExtension4)document).stopRewriteSession(session);
+			}
+			
+			if(model != null) {
+				model.endRecording(this);
+				if(changed) {
+					model.changedModel();
+				}
+				model.releaseFromEdit();
+			}
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/handlers/ToggleLineCommentHandler.java b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/handlers/ToggleLineCommentHandler.java
new file mode 100644
index 0000000..d19d404
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/handlers/ToggleLineCommentHandler.java
@@ -0,0 +1,273 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *******************************************************************************/
+package org.eclipse.wst.sse.ui.internal.handlers;
+
+import java.lang.reflect.InvocationTargetException;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.jface.dialogs.ProgressMonitorDialog;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.DocumentRewriteSession;
+import org.eclipse.jface.text.DocumentRewriteSessionType;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentExtension4;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.text.ITypedRegion;
+import org.eclipse.jface.text.Position;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+import org.eclipse.wst.sse.ui.StructuredTextEditor;
+import org.eclipse.wst.sse.ui.internal.Logger;
+import org.eclipse.wst.sse.ui.internal.SSEUIMessages;
+import org.eclipse.wst.sse.ui.internal.StructuredTextViewer;
+import org.eclipse.wst.sse.ui.internal.comment.BlockCommentingStrategy;
+import org.eclipse.wst.sse.ui.internal.comment.CommentingStrategy;
+import org.eclipse.wst.sse.ui.internal.comment.CommentingStrategyRegistry;
+import org.eclipse.wst.sse.ui.internal.comment.LineCommentingStrategy;
+
+/**
+ * <p>A comment handler to toggle line comments, this means that if a
+ * comment already exists on a line then toggling it will remove the comment,
+ * if the line in question is not already commented then it will not be commented.
+ * If multiple lines are selected each will be commented separately.  The handler
+ * first attempts to find a {@link LineCommentingStrategy} for a line, if it can
+ * not find one then it will try and find a {@link BlockCommentingStrategy} to
+ * wrap just that line in.</p>
+ * 
+ * <p>If a great number of lines are being toggled then a progress dialog will be
+ * displayed because this can be a timely process</p>
+ */
+public final class ToggleLineCommentHandler extends AbstractCommentHandler {
+	/** if toggling more then this many lines then use a busy indicator */
+	private static final int TOGGLE_LINES_MAX_NO_BUSY_INDICATOR = 10;
+	
+	/**
+	 * @see org.eclipse.wst.sse.ui.internal.handlers.AbstractCommentHandler#processAction(
+	 * 	org.eclipse.ui.texteditor.ITextEditor, org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument,
+	 * 	org.eclipse.jface.text.ITextSelection)
+	 */
+	protected void processAction(ITextEditor textEditor,
+			final IStructuredDocument document, ITextSelection textSelection) {
+		
+		IStructuredModel model = null;
+		DocumentRewriteSession session = null;
+		boolean changed = false;
+		
+		try {
+			// get text selection lines info
+			int selectionStartLine = textSelection.getStartLine();
+			int selectionEndLine = textSelection.getEndLine();
+			
+			int selectionEndLineOffset = document.getLineOffset(selectionEndLine);
+			int selectionEndOffset = textSelection.getOffset() + textSelection.getLength();
+
+			// adjust selection end line
+			if ((selectionEndLine > selectionStartLine) && (selectionEndLineOffset == selectionEndOffset)) {
+				selectionEndLine--;
+			}
+
+			// save the selection position since it will be changing
+			Position selectionPosition = null;
+			selectionPosition = new Position(textSelection.getOffset(), textSelection.getLength());
+			document.addPosition(selectionPosition);
+
+			
+			model = StructuredModelManager.getModelManager().getModelForEdit(document);
+			if (model != null) {
+				//makes it so one undo will undo all the edits to the document
+				model.beginRecording(this, SSEUIMessages.ToggleComment_label, SSEUIMessages.ToggleComment_description);
+				
+				//keeps listeners from doing anything until updates are all done
+				model.aboutToChangeModel();
+				if(document instanceof IDocumentExtension4) {
+					session = ((IDocumentExtension4)document).startRewriteSession(DocumentRewriteSessionType.UNRESTRICTED);
+				}
+				changed = true;
+				
+				//get the display for the editor if we can
+				Display display = null;
+				if(textEditor instanceof StructuredTextEditor) {
+					StructuredTextViewer viewer = ((StructuredTextEditor)textEditor).getTextViewer();
+					if(viewer != null) {
+						display = viewer.getControl().getDisplay();
+					}
+				}
+				
+				//create the toggling operation
+				IRunnableWithProgress toggleCommentsRunnable = new ToggleLinesRunnable(
+						model.getContentTypeIdentifier(), document, selectionStartLine, selectionEndLine, display);
+				
+				//if toggling lots of lines then use progress monitor else just run the operation
+				if((selectionEndLine - selectionStartLine) > TOGGLE_LINES_MAX_NO_BUSY_INDICATOR && display != null) {
+					ProgressMonitorDialog dialog = new ProgressMonitorDialog(display.getActiveShell());
+					dialog.run(false, true, toggleCommentsRunnable);
+				} else {
+					toggleCommentsRunnable.run(new NullProgressMonitor());
+				}
+			}
+		} catch (InvocationTargetException e) {
+			Logger.logException("Problem running toggle comment progess dialog.", e);  //$NON-NLS-1$
+		} catch (InterruptedException e) {
+			Logger.logException("Problem running toggle comment progess dialog.", e);  //$NON-NLS-1$
+		} catch (BadLocationException e) {
+			Logger.logException("The given selection " + textSelection + " must be invalid", e); //$NON-NLS-1$ //$NON-NLS-2$
+		} finally {
+			//clean everything up
+			if(session != null && document instanceof IDocumentExtension4) {
+				((IDocumentExtension4)document).stopRewriteSession(session);
+			}
+			
+			if(model != null) {
+				model.endRecording(this);
+				if(changed) {
+					model.changedModel();
+				}
+				model.releaseFromEdit();
+			}
+		}
+	}
+	
+	/**
+	 * <p>The actual line toggling takes place in a runnable so it can be
+	 * run as part of a progress dialog if there are many lines to toggle
+	 * and thus the operation will take a noticeable amount of time the user
+	 * should be aware of, this also allows for the operation to be canceled 
+	 * by the user</p>
+	 * 
+	 */
+	private static class ToggleLinesRunnable implements IRunnableWithProgress {
+		/** the content type for the document being commented */
+		private String fContentType;
+		
+		/** the document that the lines will be toggled on */
+		private IStructuredDocument fDocument;
+		
+		/** the first line in the document to toggle */
+		private int fSelectionStartLine;
+		
+		/** the last line in the document to toggle */
+		private int fSelectionEndLine;
+		
+		/** the display, so that it can be updated during a long operation */
+		private Display fDisplay;
+		
+		/**
+		 * @param model {@link IStructuredModel} that the lines will be toggled on
+		 * @param document {@link IDocument} that the lines will be toggled on
+		 * @param selectionStartLine first line in the document to toggle
+		 * @param selectionEndLine last line in the document to toggle
+		 * @param display {@link Display}, so that it can be updated during a long operation
+		 */
+		protected ToggleLinesRunnable(String contentTypeIdentifier, IStructuredDocument document,
+				int selectionStartLine, int selectionEndLine, Display display) {
+			
+			this.fContentType = contentTypeIdentifier;
+			this.fDocument = document;
+			this.fSelectionStartLine = selectionStartLine;
+			this.fSelectionEndLine = selectionEndLine;
+			this.fDisplay = display;
+		}
+		
+		/**
+		 * @see org.eclipse.jface.operation.IRunnableWithProgress#run(org.eclipse.core.runtime.IProgressMonitor)
+		 */
+		public void run(IProgressMonitor monitor) {
+			//start work
+			monitor.beginTask(SSEUIMessages.ToggleComment_progress,
+					this.fSelectionEndLine-this.fSelectionStartLine);
+			try {
+				//toggle each line so long as task not canceled
+				for (int line = this.fSelectionStartLine;
+						line <= this.fSelectionEndLine && !monitor.isCanceled(); ++line) {
+					
+					//allows the user to be able to click the cancel button
+					readAndDispatch(this.fDisplay);
+					
+					//get the line region
+					IRegion lineRegion = this.fDocument.getLineInformation(line);
+					
+					//don't toggle empty lines
+					String content = this.fDocument.get(lineRegion.getOffset(), lineRegion.getLength());
+					if (content.trim().length() > 0) {
+						//try to get a line comment type
+						ITypedRegion[] lineTypedRegions =
+							this.fDocument.computePartitioning(lineRegion.getOffset(), lineRegion.getLength());
+						CommentingStrategy commentType = CommentingStrategyRegistry.getDefault().getLineCommentingStrategy(
+								this.fContentType, lineTypedRegions);
+						
+						//could not find line comment type so find block comment type to use on line
+						if(commentType == null) {
+							commentType = CommentingStrategyRegistry.getDefault().getBlockCommentingStrategy(
+									this.fContentType, lineTypedRegions);
+						}
+						
+						//toggle the comment on the line
+						if(commentType != null) {
+							if(commentType.alreadyCommenting(this.fDocument, lineTypedRegions)) {
+								commentType.remove(this.fDocument, lineRegion.getOffset(), lineRegion.getLength(), true);
+							} else {
+								commentType.apply(this.fDocument, lineRegion.getOffset(), lineRegion.getLength());
+							}
+						}
+					}
+					monitor.worked(1);
+				}
+			} catch(BadLocationException e) {
+				Logger.logException("Bad location while toggling comments.", e);  //$NON-NLS-1$
+			}
+			//done work
+			monitor.done();
+		}
+		
+		/**
+		 * <p>When calling {@link Display#readAndDispatch()} the game is off as to whose code you maybe
+		 * calling into because of event handling/listeners/etc.  The only important thing is that
+		 * the UI has been given a chance to react to user clicks.  Thus the logging of most {@link Exception}s
+		 * and {@link Error}s as caused by {@link Display#readAndDispatch()} because they are not caused
+		 * by this code and do not effect it.</p>
+		 * 
+		 * @param display the {@link Display} to call <code>readAndDispatch</code>
+		 * on with exception/error handling.
+		 */
+		private void readAndDispatch(Display display) {
+			try {
+				display.readAndDispatch();
+			}
+			catch (Exception e) {
+				Logger.log(Logger.WARNING,
+						"Exception caused by readAndDispatch, not caused by or fatal to caller", e);
+			}
+			catch (LinkageError e) {
+				Logger.log(Logger.WARNING,
+						"LinkageError caused by readAndDispatch, not caused by or fatal to caller", e);
+			}
+			catch (VirtualMachineError e) {
+				// re-throw these
+				throw e;
+			}
+			catch (ThreadDeath e) {
+				// re-throw these
+				throw e;
+			}
+			catch (Error e) {
+				// catch every error, except for a few that we don't want to handle
+				Logger.log(Logger.WARNING,
+						"Error caused by readAndDispatch, not caused by or fatal to caller", e);
+			}
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/projection/AbstractStructuredFoldingStrategy.java b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/projection/AbstractStructuredFoldingStrategy.java
index c686845..271fb1d 100644
--- a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/projection/AbstractStructuredFoldingStrategy.java
+++ b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/projection/AbstractStructuredFoldingStrategy.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2010 IBM Corporation and others.
+ * Copyright (c) 2009, 2011 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
@@ -485,23 +485,33 @@
 	}
 
 	/**
-	 * <p>Gets all of the {@link IndexedRegion}s from the given {@link IStructuredModel} spand by the given
+	 * <p>Gets all of the {@link IndexedRegion}s from the given {@link IStructuredModel} spanned by the given
 	 * {@link IStructuredDocumentRegion}s.</p>
 	 * 
 	 * @param model the {@link IStructuredModel} used to get the {@link IndexedRegion}s
 	 * @param structRegions get the {@link IndexedRegion}s spanned by these {@link IStructuredDocumentRegion}s
-	 * @return the {@link Set} of {@link IndexedRegion}s from the given {@link IStructuredModel} spaned by the
+	 * @return the {@link Set} of {@link IndexedRegion}s from the given {@link IStructuredModel} spanned by the
 	 * given {@link IStructuredDocumentRegion}s.
 	 */
 	private Set getIndexedRegions(IStructuredModel model, IStructuredDocumentRegion[] structRegions) {
 		Set indexedRegions = new HashSet();
 
-		//for each text region in each struct doc region find the indexed region it spans/is in
-		for(int structRegionIndex = 0; structRegionIndex < structRegions.length && fProjectionAnnotationModel != null; ++structRegionIndex) {
-			ITextRegionList textRegions = structRegions[structRegionIndex].getRegions();
-			for(int textRegionIndex = 0; textRegionIndex < textRegions.size() && fProjectionAnnotationModel != null; ++textRegionIndex) {
-				int offset = structRegions[structRegionIndex].getStartOffset(textRegions.get(textRegionIndex));
-				indexedRegions.add(model.getIndexedRegion(offset));
+		//for each text region in each structured document region find the indexed region it spans/is in
+		for (int structRegionIndex = 0; structRegionIndex < structRegions.length && fProjectionAnnotationModel != null; ++structRegionIndex) {
+			IStructuredDocumentRegion structuredDocumentRegion = structRegions[structRegionIndex];
+			ITextRegionList textRegions = structuredDocumentRegion.getRegions();
+			
+			int offset = structuredDocumentRegion.getStartOffset(textRegions.get(0));
+			IndexedRegion indexedRegion = model.getIndexedRegion(offset);
+			indexedRegions.add(indexedRegion);
+			if (structuredDocumentRegion.getEndOffset() <= indexedRegion.getEndOffset())
+				continue;
+
+			int textRegionCount = textRegions.size();
+			for (int textRegionIndex = 1; textRegionIndex < textRegionCount; ++textRegionIndex) {
+				offset = structuredDocumentRegion.getStartOffset(textRegions.get(textRegionIndex));
+				indexedRegion = model.getIndexedRegion(offset);
+				indexedRegions.add(indexedRegion);
 			}
 		}
 
diff --git a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/reconcile/DocumentRegionProcessor.java b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/reconcile/DocumentRegionProcessor.java
index 1567622..032bc28 100644
--- a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/reconcile/DocumentRegionProcessor.java
+++ b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/reconcile/DocumentRegionProcessor.java
@@ -327,6 +327,9 @@
 		if (validatorStrategy != null) {
 			validatorStrategy.setDocument(doc);
 		}
+		if (fSemanticHighlightingStrategy != null) {
+			fSemanticHighlightingStrategy.setDocument(doc);
+		}
 		
 		fSpellcheckStrategy = null;
 		if(fFoldingStrategy != null) {
diff --git a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/reconcile/validator/ValidatorStrategy.java b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/reconcile/validator/ValidatorStrategy.java
index 129e4b3..e0f20a9 100644
--- a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/reconcile/validator/ValidatorStrategy.java
+++ b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/reconcile/validator/ValidatorStrategy.java
@@ -219,8 +219,11 @@
 					if (v1 != null)
 						disabledValsByClass.add(v1.getId());
 					// not a V1 validator
-					else if (v.getSourceId() != null)
-						disabledValsBySourceId.add(v.getSourceId());
+					else if (v.getSourceId() != null) {
+						//could be more then one sourceid per batch validator
+						String[] sourceIDs = StringUtils.unpack(v.getSourceId());
+						disabledValsBySourceId.addAll(Arrays.asList(sourceIDs));
+					}
 				}
 			}
 		}
diff --git a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/search/BasicSearchQuery.java b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/search/BasicSearchQuery.java
index d54823a..008eb33 100644
--- a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/search/BasicSearchQuery.java
+++ b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/search/BasicSearchQuery.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2001, 2009 IBM Corporation and others.
+ * Copyright (c) 2001, 2011 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
@@ -43,6 +43,11 @@
 	private AbstractTextSearchResult fResult = null;
 
 	/**
+	 * The progress monitor for the query
+	 */
+	private IProgressMonitor fProgressMonitor = null;
+
+	/**
 	 * <p>Construct a new basic query.</p>
 	 * 
 	 * <p><b>IMPORTANT: </b>It is very important that after
@@ -64,6 +69,7 @@
 	 * @see org.eclipse.search.ui.ISearchQuery#run(org.eclipse.core.runtime.IProgressMonitor)
 	 */
 	public IStatus run(IProgressMonitor monitor) {
+		fProgressMonitor = monitor;
 		return doQuery();
 	}
 	
@@ -153,8 +159,23 @@
 	 * will actually do something</p>
 	 * 
 	 * @return the status of the query when it has finished
+	 * 
+	 * @deprecated use {@link #doQuery(IProgressMonitor)} so that the operation is cancelable
 	 */
 	protected IStatus doQuery() {
+		return doQuery(fProgressMonitor);
+	}
+	
+	/**
+	 * <p>The actual work of the query, called by {@link #run(IProgressMonitor)}</p>
+	 * <p><i>Note: </i>This method should be overridden by implementers so that their query
+	 * will actually do something</p>
+	 * 
+	 * @param monitor {@link IProgressMonitor} used to track progress and cancel the operation
+	 * 
+	 * @return the status of the query when it has finished
+	 */
+	protected IStatus doQuery(IProgressMonitor monitor) {
 		return Status.OK_STATUS;
 	}
 	
diff --git a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/search/OccurrencesContentProvider.java b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/search/OccurrencesContentProvider.java
index 274c9b6..7a8f26a 100644
--- a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/search/OccurrencesContentProvider.java
+++ b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/search/OccurrencesContentProvider.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2001, 2009 IBM Corporation and others.
+ * Copyright (c) 2001, 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
@@ -42,18 +42,14 @@
 	public void elementsChanged(Object[] updatedElements) {
 
 		//TODO: copied from JavaSearchTableContentProvider
-		int addCount = 0;
-		int removeCount = 0;
 		for (int i = 0; i < updatedElements.length; i++) {
 			if (this.fResult.getMatchCount(updatedElements[i]) > 0) {
 				if (this.fTableViewer.testFindItem(updatedElements[i]) != null)
 					this.fTableViewer.refresh(updatedElements[i]);
 				else
 					this.fTableViewer.add(updatedElements[i]);
-				addCount++;
 			} else {
 				this.fTableViewer.remove(updatedElements[i]);
-				removeCount++;
 			}
 		}
 	}
diff --git a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/search/OccurrencesSearchQuery.java b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/search/OccurrencesSearchQuery.java
index b37babf..d5c8e0f 100644
--- a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/search/OccurrencesSearchQuery.java
+++ b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/search/OccurrencesSearchQuery.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2001, 2009 IBM Corporation and others.
+ * Copyright (c) 2001, 2011 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
@@ -145,14 +145,14 @@
 	 * 
 	 * @see org.eclipse.wst.sse.ui.internal.search.BasicSearchQuery#doQuery()
 	 */
-	protected IStatus doQuery() {
+	protected IStatus doQuery(IProgressMonitor monitor) {
 		IStatus status = Status.OK_STATUS;
 		FindRegions findRegions = new FindRegions(this.fDocument, this.fRegionText, this.fRegionType);
 		try {
 			// BUG158846 - deadlock if lock up entire workspace, so only lock
 			// up the file we are searching on
 			ISchedulingRule markerRule = ResourcesPlugin.getWorkspace().getRuleFactory().markerRule(getFile());
-			ResourcesPlugin.getWorkspace().run(findRegions, markerRule, IWorkspace.AVOID_UPDATE, null);
+			ResourcesPlugin.getWorkspace().run(findRegions, markerRule, IWorkspace.AVOID_UPDATE, monitor);
 		} catch (CoreException e) {
 			status = new Status(IStatus.ERROR, SSEUIPlugin.ID, IStatus.OK, "", null); //$NON-NLS-1$
 		}
diff --git a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/style/SemanticHighlightingPresenter.java b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/style/SemanticHighlightingPresenter.java
index ad973d3..093ec05 100644
--- a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/style/SemanticHighlightingPresenter.java
+++ b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/style/SemanticHighlightingPresenter.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2010 IBM Corporation and others.
+ * Copyright (c) 2009, 2011 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
@@ -104,8 +104,13 @@
 						// do nothing
 						// updateWithSucceedingEvent(position, event);
 					}
-					else if (offset <= eventOffset && end >= eventEnd)
-						updateWithIncludedEvent(position, event);
+					else if (offset <= eventOffset && end >= eventEnd) {
+						 // Previous region updated to overlap the beginning of this one; just bump the start.
+						if (i > 0 && positions[i - 1].offset + positions[i - 1].length > offset)
+							updateWithPrecedingEvent(position, event);
+						else
+							updateWithIncludedEvent(position, event);
+					}
 					else if (offset <= eventOffset)
 						updateWithOverEndEvent(position, event);
 					else if (end >= eventEnd)
diff --git a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/style/SemanticHighlightingReconciler.java b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/style/SemanticHighlightingReconciler.java
index ee86fcd..8318c97 100644
--- a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/style/SemanticHighlightingReconciler.java
+++ b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/style/SemanticHighlightingReconciler.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2010 IBM Corporation and others.
+ * Copyright (c) 2009, 2011 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
@@ -104,7 +104,7 @@
 		fJobHighlightings = fHighlightings;
 		IStructuredModel model = null;
 		try {
-			if (fJobPresenter == null || fJobSemanticHighlightings == null || fJobHighlightings == null)
+			if (fJobPresenter == null || fJobSemanticHighlightings == null || fJobHighlightings == null || fDocument == null)
 				return;
 
 			fJobPresenter.setCanceled(false);
@@ -240,7 +240,7 @@
 
 	public void setDocument(IDocument document) {
 		fDocument = document;
-		refresh();
+//		refresh();
 	}
 
 	public void initialReconcile() {
diff --git a/bundles/org.eclipse.wst.xml.core/.classpath b/bundles/org.eclipse.wst.xml.core/.classpath
new file mode 100644
index 0000000..0f97d08
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/.classpath
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src-contentmodel"/>
+	<classpathentry kind="src" path="src-search"/>
+	<classpathentry kind="src" path="src-validation"/>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="src" path="src-catalog"/>
+	<classpathentry kind="src" path="src-emfModelSynch"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins">
+		<accessrules>
+			<accessrule kind="accessible" pattern="org/eclipse/wst/validation/**"/>
+			<accessrule kind="accessible" pattern="org/eclipse/wst/common/internal/emf/resource/**"/>
+			<accessrule kind="accessible" pattern="org/eclipse/wst/common/internal/emf/utilities/**"/>
+			<accessrule kind="accessible" pattern="org/eclipse/wst/common/internal/emfworkbench/**"/>
+		</accessrules>
+	</classpathentry>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.4">
+		<accessrules>
+			<accessrule kind="accessible" pattern="org/apache/xerces/dom/TreeWalkerImpl"/>
+			<accessrule kind="accessible" pattern="org/w3c/dom/ranges/DocumentRange"/>
+			<accessrule kind="accessible" pattern="org/w3c/dom/ranges/Range"/>
+			<accessrule kind="accessible" pattern="org/w3c/dom/traversal/DocumentTraversal"/>
+			<accessrule kind="accessible" pattern="org/w3c/dom/traversal/NodeFilter"/>
+			<accessrule kind="accessible" pattern="org/w3c/dom/traversal/NodeIterator"/>
+			<accessrule kind="accessible" pattern="org/w3c/dom/traversal/TreeWalker"/>
+			<accessrule kind="accessible" pattern="org/w3c/dom/ranges/RangeException"/>
+			<accessrule kind="accessible" pattern="org/apache/xerces/impl/XMLErrorReporter"/>
+			<accessrule kind="accessible" pattern="org/apache/xerces/parsers/StandardParserConfiguration"/>
+			<accessrule kind="accessible" pattern="org/apache/xerces/xni/Augmentations"/>
+			<accessrule kind="accessible" pattern="org/apache/xerces/xni/NamespaceContext"/>
+			<accessrule kind="accessible" pattern="org/apache/xerces/xni/QName"/>
+			<accessrule kind="accessible" pattern="org/apache/xerces/xni/XMLAttributes"/>
+			<accessrule kind="accessible" pattern="org/apache/xerces/xni/XMLLocator"/>
+			<accessrule kind="accessible" pattern="org/apache/xerces/xni/XMLResourceIdentifier"/>
+			<accessrule kind="accessible" pattern="org/apache/xerces/xni/XNIException"/>
+			<accessrule kind="accessible" pattern="org/apache/xerces/xni/parser/XMLEntityResolver"/>
+			<accessrule kind="accessible" pattern="org/apache/xerces/xni/parser/XMLInputSource"/>
+			<accessrule kind="accessible" pattern="org/apache/xerces/parsers/SAXParser"/>
+			<accessrule kind="accessible" pattern="org/apache/xerces/parsers/AbstractSAXParser"/>
+		</accessrules>
+	</classpathentry>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/bundles/org.eclipse.wst.xml.core/.cvsignore b/bundles/org.eclipse.wst.xml.core/.cvsignore
new file mode 100644
index 0000000..273f8bc
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/.cvsignore
@@ -0,0 +1,8 @@
+bin
+temp.folder
+build.xml
+xmlmodel.jar
+org.eclipse.wst.xml.core_1.0.0.jar
+@dot
+src.zip
+javaCompiler...args
diff --git a/bundles/org.eclipse.wst.xml.core/.options b/bundles/org.eclipse.wst.xml.core/.options
new file mode 100644
index 0000000..31db1ad
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/.options
@@ -0,0 +1,5 @@
+org.eclipse.wst.xml.core/debug=true
+org.eclipse.wst.xml.core/debug/tracefilter=
+org.eclipse.wst.xml.core/debug/cmdocumentmanager=false
+org.eclipse.wst.xml.core/debug/cmdocumentcache=false
+org.eclipse.wst.xml.core/externalSchemaLocation=false
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.xml.core/.project b/bundles/org.eclipse.wst.xml.core/.project
new file mode 100644
index 0000000..c417514
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/.project
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.wst.xml.core</name>
+	<comment></comment>
+	<projects></projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.ManifestBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.SchemaBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.PluginNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
diff --git a/bundles/org.eclipse.wst.xml.core/.settings/org.eclipse.core.resources.prefs b/bundles/org.eclipse.wst.xml.core/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..afa5c91
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+#Tue Apr 04 03:36:32 EDT 2006
+eclipse.preferences.version=1
+encoding/<project>=ISO-8859-1
diff --git a/bundles/org.eclipse.wst.xml.core/.settings/org.eclipse.core.runtime.prefs b/bundles/org.eclipse.wst.xml.core/.settings/org.eclipse.core.runtime.prefs
new file mode 100644
index 0000000..7ec5750
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/.settings/org.eclipse.core.runtime.prefs
@@ -0,0 +1,3 @@
+#Mon Apr 17 01:48:39 EDT 2006
+eclipse.preferences.version=1
+line.separator=\r\n
diff --git a/bundles/org.eclipse.wst.xml.core/.settings/org.eclipse.jdt.core.prefs b/bundles/org.eclipse.wst.xml.core/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..3405307
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,79 @@
+#Sat Mar 24 02:18:23 EDT 2007

+eclipse.preferences.version=1

+org.eclipse.jdt.core.builder.cleanOutputFolder=clean

+org.eclipse.jdt.core.builder.duplicateResourceTask=warning

+org.eclipse.jdt.core.builder.invalidClasspath=ignore

+org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch

+org.eclipse.jdt.core.circularClasspath=error

+org.eclipse.jdt.core.classpath.exclusionPatterns=enabled

+org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled

+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=disabled

+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.2

+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve

+org.eclipse.jdt.core.compiler.compliance=1.4

+org.eclipse.jdt.core.compiler.debug.lineNumber=generate

+org.eclipse.jdt.core.compiler.debug.localVariable=generate

+org.eclipse.jdt.core.compiler.debug.sourceFile=generate

+org.eclipse.jdt.core.compiler.doc.comment.support=enabled

+org.eclipse.jdt.core.compiler.maxProblemPerUnit=100

+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning

+org.eclipse.jdt.core.compiler.problem.assertIdentifier=warning

+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore

+org.eclipse.jdt.core.compiler.problem.deprecation=ignore

+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled

+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=enabled

+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning

+org.eclipse.jdt.core.compiler.problem.emptyStatement=warning

+org.eclipse.jdt.core.compiler.problem.enumIdentifier=warning

+org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore

+org.eclipse.jdt.core.compiler.problem.finalParameterBound=ignore

+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=error

+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error

+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning

+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning

+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore

+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=error

+org.eclipse.jdt.core.compiler.problem.invalidJavadoc=ignore

+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled

+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled

+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=private

+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore

+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=error

+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore

+org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore

+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=enabled

+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public

+org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore

+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=enabled

+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=private

+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore

+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=error

+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=error

+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning

+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore

+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning

+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=error

+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=enabled

+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=error

+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled

+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore

+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=ignore

+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning

+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore

+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning

+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore

+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=error

+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore

+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore

+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled

+org.eclipse.jdt.core.compiler.problem.unusedImport=error

+org.eclipse.jdt.core.compiler.problem.unusedLabel=error

+org.eclipse.jdt.core.compiler.problem.unusedLocal=error

+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore

+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled

+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled

+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=error

+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning

+org.eclipse.jdt.core.compiler.source=1.3

+org.eclipse.jdt.core.incompatibleJDKLevel=ignore

+org.eclipse.jdt.core.incompleteClasspath=error

diff --git a/bundles/org.eclipse.wst.xml.core/.settings/org.eclipse.jdt.ui.prefs b/bundles/org.eclipse.wst.xml.core/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000..1ca5c5e
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,3 @@
+#Wed Nov 15 02:26:10 EST 2006
+eclipse.preferences.version=1
+org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8"?>\r\n<templates/>
diff --git a/bundles/org.eclipse.wst.xml.core/.settings/org.eclipse.ltk.core.refactoring.prefs b/bundles/org.eclipse.wst.xml.core/.settings/org.eclipse.ltk.core.refactoring.prefs
new file mode 100644
index 0000000..c59368c
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/.settings/org.eclipse.ltk.core.refactoring.prefs
@@ -0,0 +1,3 @@
+#Tue Apr 04 03:36:32 EDT 2006
+eclipse.preferences.version=1
+org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false
diff --git a/bundles/org.eclipse.wst.xml.core/.settings/org.eclipse.pde.prefs b/bundles/org.eclipse.wst.xml.core/.settings/org.eclipse.pde.prefs
new file mode 100644
index 0000000..86ca5a7
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/.settings/org.eclipse.pde.prefs
@@ -0,0 +1,16 @@
+#Wed Nov 15 02:13:31 EST 2006
+compilers.incompatible-environment=0
+compilers.p.build=0
+compilers.p.deprecated=1
+compilers.p.illegal-att-value=0
+compilers.p.no-required-att=0
+compilers.p.not-externalized-att=0
+compilers.p.unknown-attribute=0
+compilers.p.unknown-class=0
+compilers.p.unknown-element=1
+compilers.p.unknown-resource=0
+compilers.p.unresolved-ex-points=0
+compilers.p.unresolved-import=0
+compilers.p.unused-element-or-attribute=0
+compilers.use-project=true
+eclipse.preferences.version=1
diff --git a/bundles/org.eclipse.wst.xml.core/DevTimeSupport/HeadParsers/XML10Names.jFlex b/bundles/org.eclipse.wst.xml.core/DevTimeSupport/HeadParsers/XML10Names.jFlex
new file mode 100644
index 0000000..c33e65b
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/DevTimeSupport/HeadParsers/XML10Names.jFlex
@@ -0,0 +1,100 @@
+/*******************************************************************************
+ * Copyright (c) 2004 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
+ *******************************************************************************/
+/*nlsXXX*/
+package org.eclipse.wst.xml.core.internal.parser;
+
+
+
+%%
+
+%table
+%public
+%final
+%class XML10Names
+%function isValidXML10Name
+%type boolean
+%unicode
+%ignorecase
+%buffer 2048
+%apiprivate
+
+S = (\x20 | \x09 | \x0D | \x0A)
+
+BaseChar = [\u0041-\u005A\u0061-\u007A\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF\u0100-\u0131\u0134-\u013E\u0141-\u0148\u014A-\u017E\u0180-\u01C3\u01CD-\u01F0\u01F4-\u01F5\u01FA-\u0217\u0250-\u02A8\u02BB-\u02C1\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03CE\u03D0-\u03D6\u03DA\u03DC\u03DE\u03E0\u03E2-\u03F3\u0401-\u040C\u040E-\u044F\u0451-\u045C\u045E-\u0481\u0490-\u04C4\u04C7-\u04C8\u04CB-\u04CC\u04D0-\u04EB\u04EE-\u04F5\u04F8-\u04F9\u0531-\u0556\u0559\u0561-\u0586\u05D0-\u05EA\u05F0-\u05F2\u0621-\u063A\u0641-\u064A\u0671-\u06B7\u06BA-\u06BE\u06C0-\u06CE\u06D0-\u06D3\u06D5\u06E5-\u06E6\u0905-\u0939\u093D\u0958-\u0961\u0985-\u098C\u098F-\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09DC-\u09DD\u09DF-\u09E1\u09F0-\u09F1\u0A05-\u0A0A\u0A0F-\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32-\u0A33\u0A35-\u0A36\u0A38-\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8B\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2-\u0AB3\u0AB5-\u0AB9\u0ABD\u0AE0\u0B05-\u0B0C\u0B0F-\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32-\u0B33\u0B36-\u0B39\u0B3D\u0B5C-\u0B5D\u0B5F-\u0B61\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99-\u0B9A\u0B9C\u0B9E-\u0B9F\u0BA3-\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB5\u0BB7-\u0BB9\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C60-\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CDE\u0CE0-\u0CE1\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D28\u0D2A-\u0D39\u0D60-\u0D61\u0E01-\u0E2E\u0E30\u0E32-\u0E33\u0E40-\u0E45\u0E81-\u0E82\u0E84\u0E87-\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA-\u0EAB\u0EAD-\u0EAE\u0EB0\u0EB2-\u0EB3\u0EBD\u0EC0-\u0EC4\u0F40-\u0F47\u0F49-\u0F69\u10A0-\u10C5\u10D0-\u10F6\u1100\u1102-\u1103\u1105-\u1107\u1109\u110B-\u110C\u110E-\u1112\u113C\u113E\u1140\u114C\u114E\u1150\u1154-\u1155\u1159\u115F-\u1161\u1163\u1165\u1167\u1169\u116D-\u116E\u1172-\u1173\u1175\u119E\u11A8\u11AB\u11AE-\u11AF\u11B7-\u11B8\u11BA\u11BC-\u11C2\u11EB\u11F0\u11F9\u1E00-\u1E9B\u1EA0-\u1EF9\u1F00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2126\u212A-\u212B\u212E\u2180-\u2182\u3041-\u3094\u30A1-\u30FA\u3105-\u312C\uAC00-\uD7A3]
+
+Ideographic = [\u4E00-\u9FA5\u3007\u3021-\u3029]
+
+CombiningChar = [\u0300-\u0345\u0360-\u0361\u0483-\u0486\u0591-\u05A1\u05A3-\u05B9\u05BB-\u05BD\u05BF\u05C1-\u05C2\u05C4\u064B-\u0652\u0670\u06D6-\u06DC\u06DD-\u06DF\u06E0-\u06E4\u06E7-\u06E8\u06EA-\u06ED\u0901-\u0903\u093C\u093E-\u094C\u094D\u0951-\u0954\u0962-\u0963\u0981-\u0983\u09BC\u09BE\u09BF\u09C0-\u09C4\u09C7-\u09C8\u09CB-\u09CD\u09D7\u09E2-\u09E3\u0A02\u0A3C\u0A3E\u0A3F\u0A40-\u0A42\u0A47-\u0A48\u0A4B-\u0A4D\u0A70-\u0A71\u0A81-\u0A83\u0ABC\u0ABE-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0B01-\u0B03\u0B3C\u0B3E-\u0B43\u0B47-\u0B48\u0B4B-\u0B4D\u0B56-\u0B57\u0B82-\u0B83\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD7\u0C01-\u0C03\u0C3E-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55-\u0C56\u0C82-\u0C83\u0CBE-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5-\u0CD6\u0D02-\u0D03\u0D3E-\u0D43\u0D46-\u0D48\u0D4A-\u0D4D\u0D57\u0E31\u0E34-\u0E3A\u0E47-\u0E4E\u0EB1\u0EB4-\u0EB9\u0EBB-\u0EBC\u0EC8-\u0ECD\u0F18-\u0F19\u0F35\u0F37\u0F39\u0F3E\u0F3F\u0F71-\u0F84\u0F86-\u0F8B\u0F90-\u0F95\u0F97\u0F99-\u0FAD\u0FB1-\u0FB7\u0FB9\u20D0-\u20DC\u20E1\u302A-\u302F\u3099\u309A]
+
+Digit =  [\u0030-\u0039\u0660-\u0669\u06F0-\u06F9\u0966-\u096F\u09E6-\u09EF\u0A66-\u0A6F\u0AE6-\u0AEF\u0B66-\u0B6F\u0BE7-\u0BEF\u0C66-\u0C6F\u0CE6-\u0CEF\u0D66-\u0D6F\u0E50-\u0E59\u0ED0-\u0ED9\u0F20-\u0F29]
+
+Extender = [\u00B7\u02D0\u02D1\u0387\u0640\u0E46\u0EC6\u3005\u3031-\u3035\u309D-\u309E\u30FC-\u30FE]
+
+Letter = ({BaseChar} | {Ideographic})
+
+NameChar = ({Letter} | {Digit} | . | - | _ | : | {CombiningChar} | {Extender})
+
+Name = ({Letter} | _ | : ) ({NameChar})*
+
+
+
+%{
+
+	/**
+	 * Creates a new scanner
+	 */
+	public XML10Names() {
+		this.zzReader = null;
+	}
+
+	public boolean isValidXML10Name(String stringToCheck) {
+		boolean result = false;
+		yyreset(new java.io.StringReader(stringToCheck));
+		try {
+			result = isValidXML10Name();
+		}
+		catch (java.io.IOException e) {
+			// should be impossible with strings, but if occurs, just means
+			// "not"
+			result = false;
+		}
+		return result;
+	}
+
+%}
+
+
+
+
+%%
+
+<YYINITIAL>
+{
+
+	// don't match if contains trailing or embedded space
+	{Name} {S}+         {return false;}
+	{Name} {S}+ {Name}  {return false;}
+
+	{Name}              {return true;}
+
+	// match anything should come last
+	.                   {return false;}
+
+}
+
+
+// this rule always in effect
+<<EOF>>
+{
+	{return false;}
+}
+
+
diff --git a/bundles/org.eclipse.wst.xml.core/DevTimeSupport/HeadParsers/XMLHeadTokenizer.jFlex b/bundles/org.eclipse.wst.xml.core/DevTimeSupport/HeadParsers/XMLHeadTokenizer.jFlex
new file mode 100644
index 0000000..15d5b0a
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/DevTimeSupport/HeadParsers/XMLHeadTokenizer.jFlex
@@ -0,0 +1,254 @@
+/*******************************************************************************

+ * Copyright (c) 2005, 2008 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

+ *******************************************************************************/

+/*nlsXXX*/

+package org.eclipse.wst.xml.core.internal.contenttype;

+import java.io.IOException;

+import java.io.Reader;

+

+import org.eclipse.wst.xml.core.internal.contenttype.EncodingParserConstants;

+import org.eclipse.wst.xml.core.internal.contenttype.XMLHeadTokenizerConstants;

+

+

+%%

+

+%{

+

+

+	private boolean hasMore = true;

+	private final static int MAX_TO_SCAN = 8000;

+	StringBuffer string = new StringBuffer();

+	// state stack for easier state handling

+	private IntStack fStateStack = new IntStack();

+	private String valueText = null;

+

+

+	public XMLHeadTokenizer() {

+		super();

+	}

+

+	  public void reset (Reader in) {

+                /* the input device */

+                zzReader = in;

+

+                /* the current state of the DFA */

+                zzState = 0;

+

+                /* the current lexical state */

+                zzLexicalState = YYINITIAL;

+

+                /* this buffer contains the current text to be matched and is

+                 the source of the yytext() string */

+                java.util.Arrays.fill(zzBuffer, (char)0);

+

+                /* the textposition at the last accepting state */

+                zzMarkedPos = 0;

+

+                /* the textposition at the last state to be included in yytext */

+                zzPushbackPos = 0;

+

+                /* the current text position in the buffer */

+                zzCurrentPos = 0;

+

+                /* startRead marks the beginning of the yytext() string in the buffer */

+                zzStartRead = 0;

+

+                /**

+                 * endRead marks the last character in the buffer, that has been read

+                 * from input

+                 */

+                zzEndRead = 0;

+

+                /* number of newlines encountered up to the start of the matched text */

+                yyline = 0;

+

+                /* the number of characters up to the start of the matched text */

+                yychar = 0;

+

+                /**

+                 * the number of characters from the last newline up to the start

+                 * of the matched text

+                 */

+                yycolumn = 0;

+

+                /**

+                 * yy_atBOL == true <=> the scanner is currently at the beginning

+                 * of a line

+                 */

+                zzAtBOL = true;

+

+                /* yy_atEOF == true <=> the scanner has returned a value for EOF */

+                zzAtEOF = false;

+

+                /* denotes if the user-EOF-code has already been executed */

+                zzEOFDone = false;

+

+

+                fStateStack.clear();

+

+                hasMore = true;

+  		

+  	}

+

+

+	public final HeadParserToken getNextToken() throws IOException {

+		String context = null;

+		context = primGetNextToken();

+		HeadParserToken result = null;

+		if (valueText != null) {

+			result = createToken(context, yychar, valueText);

+			valueText = null;

+		} else {

+			result = createToken(context, yychar, yytext());

+		}

+		return result;

+	}

+

+	public final boolean hasMoreTokens() {

+		return hasMore && yychar < MAX_TO_SCAN;

+	}

+	private void pushCurrentState() {

+		fStateStack.push(yystate());

+

+	}

+

+	private void popState() {

+		yybegin(fStateStack.pop());

+	}

+	

+	private HeadParserToken createToken(String context, int start, String text) {

+		return new HeadParserToken(context, start, text);

+	}	

+

+%}

+

+%eof{

+	hasMore=false;

+%eof}

+

+%public

+%class XMLHeadTokenizer

+%function primGetNextToken

+%type String

+%char

+%unicode

+%ignorecase 

+//%debug

+%switch

+%buffer 8192

+

+UTF16BE = \xFE\xFF

+UTF16LE = \xFF\xFE

+UTF83ByteBOM = \xEF\xBB\xBF

+

+//SpaceChar = [\x20\x09]

+

+// [3] S ::= (0x20 | 0x9 | 0xD | 0xA)+

+S = [\x20\x09\x0D\x0A]

+

+//BeginAttribeValue = {S}* \= {S}*

+

+LineTerminator = \r|\n

+

+// Z is the single-byte zero character to be used in parsing double-byte files

+Z = (\x00)?

+S_UTF = {Z}{S}{Z}

+BeginAttributeValueUTF = {S_UTF}* \= {S_UTF}*

+

+%state ST_XMLDecl

+%state QuotedAttributeValue

+%state DQ_STRING

+%state SQ_STRING

+%state UnDelimitedString

+

+%%

+

+

+<YYINITIAL>  

+{

+	// force to start at beginning of line (^) and at beginning of file (yychar == 0)

+	^{UTF16BE}   		{if (yychar == 0 ) {hasMore = false; return EncodingParserConstants.UTF16BE;}}

+	^{UTF16LE}   		{if (yychar == 0 ) {hasMore = false; return EncodingParserConstants.UTF16LE;}}

+	^{UTF83ByteBOM}   	{if (yychar == 0 ) {hasMore = false; return EncodingParserConstants.UTF83ByteBOM;}}

+	

+	// force to be started on first line, but we do allow preceeding spaces

+	^ {S_UTF}* ({Z}<{Z}\?{Z}x{Z}m{Z}l{Z}){S_UTF}+ {if (yychar == 0 ) {yybegin(ST_XMLDecl); return XMLHeadTokenizerConstants.XMLDeclStart;}}

+	

+}	

+	

+<ST_XMLDecl> 

+{

+	({Z}v{Z}e{Z}r{Z}s{Z}i{Z}o{Z}n{Z}) {BeginAttributeValueUTF} {pushCurrentState(); yybegin(QuotedAttributeValue); return XMLHeadTokenizerConstants.XMLDeclVersion;}

+	({Z}e{Z}n{Z}c{Z}o{Z}d{Z}i{Z}n{Z}g{Z}) {BeginAttributeValueUTF} {pushCurrentState(); yybegin(QuotedAttributeValue); return XMLHeadTokenizerConstants.XMLDelEncoding;}

+	// note the "forced end" (via 'hasMore=false') once the end of XML Declaration found

+	// This is since non-ascii chars may follow and may cause IOExceptions which would not occur once stream is 

+	// read with incorrect encoding (such as if platform encoding is in effect until true encoding detected). 

+	({Z}\?{Z}>{Z})    {yybegin(YYINITIAL); hasMore = false; return XMLHeadTokenizerConstants.XMLDeclEnd;}

+}	

+

+	

+

+<QuotedAttributeValue>

+{

+	{Z}\"{Z}        { yybegin(DQ_STRING); string.setLength(0); }

+	{Z}\'{Z}			{ yybegin(SQ_STRING); string.setLength(0); }

+	// in this state, anything other than a space character can start an undelimited string

+	{S_UTF}*.           { yypushback(1); yybegin(UnDelimitedString); string.setLength(0);}

+

+}	

+

+

+<DQ_STRING>

+{

+

+	{Z}\"{Z}                      { popState(); valueText = string.toString(); return EncodingParserConstants.StringValue; }

+  	{Z}{LineTerminator}{Z}        { yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}

+	{Z}\?{Z}>{Z}			{ yypushback(yylength()); popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}

+	{Z}<{Z}			{ yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}

+	[^\x00]			{ string.append( yytext() ); }

+

+}

+

+<SQ_STRING>

+{

+

+	{Z}\'{Z}                      { popState(); valueText = string.toString(); return EncodingParserConstants.StringValue;}

+  	{Z}{LineTerminator}{Z}        { yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}

+	{Z}%{Z}>{Z}			{ yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}

+	{Z}<{Z}			{ yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}

+	[^\x00]			{ string.append( yytext() ); }

+

+}

+

+<UnDelimitedString>

+{

+

+	{S_UTF}                     { yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.UnDelimitedStringValue; }

+  	{Z}{LineTerminator}{Z}        { yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}

+	{Z}\?{Z}>{Z}			{ yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}

+	{Z}<{Z}	

+	{ yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}

+	// these are a bit special, since we started an undelimit string, but found a quote ... probably indicates a missing beginning quote

+	{Z}\'{Z}			{ yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTermintatedUnDelimitedStringValue;}

+	

+	{Z}\"{Z}			{ yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTermintatedUnDelimitedStringValue;}

+	

+	[^\x00]			{ string.append( yytext() ); }

+

+}

+

+// The "match anything" rule should always be in effect except for when looking for end of string

+// (That is, remember to update state list if/when new states added)

+.|\n	{if(yychar > MAX_TO_SCAN) {hasMore=false; return EncodingParserConstants.MAX_CHARS_REACHED;}}

+

+// this rule always in effect

+<<EOF>>         {hasMore = false; return EncodingParserConstants.EOF;}

+

+	
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.xml.core/DevTimeSupport/buildNames.xml b/bundles/org.eclipse.wst.xml.core/DevTimeSupport/buildNames.xml
new file mode 100644
index 0000000..6d97563
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/DevTimeSupport/buildNames.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="tokenizer" default="XML10Names">
+	
+	<!-- Note: for Eclipse env., the JFlex 1.4 jar should be added 
+	to the ant global entries  -->
+	<taskdef classname="JFlex.anttask.JFlexTask" name="jflex" />
+		
+	<target name="init">
+		<property name="src.file" value="XML10Names.jFlex"/>			
+		<property name="src.dir" value="HeadParsers"/>
+		<property name="dest.dir" value="../src"/>
+		<!-- touch causes to always build, remove for real 'make' behavior -->
+		<touch file="${src.dir}/${src.file}"/>
+					
+	</target>
+
+	<target name="XML10Names" depends="init">
+		<antcall target="run-jflex"/>
+	</target>
+
+	<target name="run-jflex" depends="init">
+		<jflex
+	    	file="${src.dir}/${src.file}"
+	    	destdir="${dest.dir}"
+			verbose="true"
+			nobak="true"
+			time="on"
+	    />
+	</target>
+	
+
+</project>
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.xml.core/DevTimeSupport/buildParser.xml b/bundles/org.eclipse.wst.xml.core/DevTimeSupport/buildParser.xml
new file mode 100644
index 0000000..49619df
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/DevTimeSupport/buildParser.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="tokenizer" default="HeadTokenizer">
+	
+	<!-- Note: for Eclipse env., the JFlex 1.4 jar should be added 
+	to the ant global entries  -->
+	<taskdef classname="JFlex.anttask.JFlexTask" name="jflex" />
+		
+	<target name="init">
+		<property name="src.file" value="XMLHeadTokenizer.jFlex"/>			
+		<property name="src.dir" value="HeadParsers"/>
+		<property name="dest.dir" value="../src"/>
+		<!-- touch causes to always build, remove for real 'make' behavior -->
+		<touch file="${src.dir}/${src.file}"/>
+					
+	</target>
+
+	<target name="HeadTokenizer" depends="init">
+		<antcall target="run-jflex"/>
+	</target>
+
+	<target name="run-jflex" depends="init">
+		<jflex
+	    	file="${src.dir}/${src.file}"
+	    	destdir="${dest.dir}"
+			verbose="true"
+			nobak="true"
+			time="on"
+	    />
+	</target>
+	
+
+</project>
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.xml.core/META-INF/MANIFEST.MF b/bundles/org.eclipse.wst.xml.core/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..84a387d
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/META-INF/MANIFEST.MF
@@ -0,0 +1,76 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %pluginName
+Bundle-SymbolicName: org.eclipse.wst.xml.core; singleton:=true
+Bundle-Version: 1.1.505.qualifier
+Bundle-Activator: org.eclipse.wst.xml.core.internal.XMLCorePlugin
+Bundle-Vendor: %providerName
+Bundle-Localization: plugin
+Export-Package: org.eclipse.wst.xml.core.internal;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.xml.core.internal.catalog;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.xml.core.internal.catalog.provisional;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.xml.core.internal.cleanup;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.xml.core.internal.commentelement;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.xml.core.internal.commentelement.impl;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.xml.core.internal.commentelement.util;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.xml.core.internal.contentmodel;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.xml.core.internal.contentmodel.annotation;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.xml.core.internal.contentmodel.basic;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.xml.core.internal.contentmodel.factory;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.xml.core.internal.contentmodel.internal.annotation;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.xml.core.internal.contentmodel.internal.modelqueryimpl;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.xml.core.internal.contentmodel.internal.util;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.xml.core.internal.contentmodel.modelquery;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.xml.core.internal.contentmodel.modelquery.extension;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.xml.core.internal.contentmodel.modelqueryimpl;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.xml.core.internal.contentmodel.util;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.xml.core.internal.contenttype;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.xml.core.internal.document;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.xml.core.internal.emf2xml;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.xml.core.internal.encoding;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.xml.core.internal.formatter;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.xml.core.internal.modelhandler;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.xml.core.internal.modelquery;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.xml.core.internal.parser;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.xml.core.internal.parser.regions;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.xml.core.internal.preferences;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.xml.core.internal.propagate;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.xml.core.internal.provisional;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.xml.core.internal.provisional.contentmodel;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.xml.core.internal.provisional.contenttype;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.xml.core.internal.provisional.document;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.xml.core.internal.provisional.format;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.xml.core.internal.provisional.text;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.xml.core.internal.regions;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.xml.core.internal.search;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.xml.core.internal.search.impl;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.xml.core.internal.search.matching;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.xml.core.internal.search.quickscan;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.xml.core.internal.ssemodelquery;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.xml.core.internal.tasks;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.xml.core.internal.text;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.xml.core.internal.text.rules;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.xml.core.internal.validate;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.xml.core.internal.validation;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.xml.core.internal.validation.core;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.xml.core.internal.validation.core.logging;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.xml.core.internal.validation.eclipse;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.xml.core.internal.validation.errorcustomization;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.xml.core.text
+Import-Package: com.ibm.icu.util; version="3.8",
+ com.ibm.icu.text; version="3.8"
+Require-Bundle: org.apache.xerces;bundle-version="[2.9.0,3.0.0)";visibility:=reexport,
+ org.eclipse.core.runtime;bundle-version="[3.5.0,4.0.0)",
+ org.eclipse.core.resources;bundle-version="[3.5.0,4.0.0)",
+ org.eclipse.core.filebuffers;bundle-version="[3.5.0,4.0.0)";resolution:=optional,
+ org.eclipse.wst.common.uriresolver;bundle-version="[1.1.301,1.2.0)",
+ org.eclipse.wst.sse.core;bundle-version="[1.1.500,1.2.0)",
+ org.eclipse.jem.util;bundle-version="[2.0.200,3.0.0)";resolution:=optional,
+ org.eclipse.wst.validation;bundle-version="[1.2.100,1.3.0)";resolution:=optional,
+ org.eclipse.wst.common.emf;bundle-version="[1.1.300,1.3.0)";resolution:=optional,
+ org.eclipse.emf.ecore.xmi;bundle-version="[2.4.0,3.0.0)";resolution:=optional,
+ org.eclipse.wst.common.emfworkbench.integration;bundle-version="[1.1.300,1.3.0)";resolution:=optional,
+ org.eclipse.wst.common.core;bundle-version="[1.1.201,1.3.0)",
+ org.eclipse.osgi.services;bundle-version="[3.2.0,4.0.0)"
+Bundle-ActivationPolicy: lazy; exclude:="org.eclipse.wst.xml.core.internal.contenttype"
+Bundle-RequiredExecutionEnvironment: J2SE-1.4
diff --git a/bundles/org.eclipse.wst.xml.core/README.txt b/bundles/org.eclipse.wst.xml.core/README.txt
new file mode 100644
index 0000000..ffa6466
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/README.txt
@@ -0,0 +1 @@
+THe XML specific model implementation.
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.xml.core/about.html b/bundles/org.eclipse.wst.xml.core/about.html
new file mode 100644
index 0000000..2199df3
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/about.html
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
+<HTML>
+
+<head>
+<title>About</title>
+<meta http-equiv=Content-Type content="text/html; charset=ISO-8859-1">
+</head>
+
+<BODY lang="EN-US">
+
+<H3>About This Content</H3>
+
+<P>June, 2008</P>
+
+<H3>License</H3>
+
+<P>The Eclipse Foundation makes available all content in this plug-in 
+("Content"). Unless otherwise indicated below, the Content is provided to you 
+under the terms and conditions of the Eclipse Public License Version 1.0 
+("EPL"). A copy of the EPL is available at
+<A href="http://www.eclipse.org/org/documents/epl-v10.php">http://www.eclipse.org/org/documents/epl-v10.php</A>. 
+For purposes of the EPL, "Program" will mean the Content.</P>
+
+<P>If you did not receive this Content directly from the Eclipse Foundation, the 
+Content is being redistributed by another party ("Redistributor") and different 
+terms and conditions may apply to your use of any object code in the Content. 
+Check the RedistributorÂ’s license that was provided with the Content. If no such 
+license exists, contact the Redistributor. Unless otherwise indicated below, the 
+terms and conditions of the EPL still apply to any source code in the Content 
+and such source code may be obtained at
+<A href="http://www.eclipse.org/">http://www.eclipse.org/</A>.</P>
+
+</BODY>
+</HTML>
diff --git a/bundles/org.eclipse.wst.xml.core/build.properties b/bundles/org.eclipse.wst.xml.core/build.properties
new file mode 100644
index 0000000..8d49b33
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/build.properties
@@ -0,0 +1,33 @@
+###############################################################################
+# Copyright (c) 2001, 2006 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
+#     Jens Lukowski/Innoopract - initial renaming/restructuring
+#     
+###############################################################################
+bin.includes = plugin.xml,\
+               .options,\
+               plugin.properties,\
+               META-INF/,\
+               .,\
+               about.html,\
+               schema/
+bin.excludes = bin/**,\
+               @dot/**,\
+               temp.folder/**
+src.includes = component.xml,\
+               schema/,\
+               DevTimeSupport/
+source.. = src-catalog/,\
+           src-contentmodel/,\
+           src-validation/,\
+           src/,\
+           src-emfModelSynch/,\
+           src-search/
+
+output.. = bin/
diff --git a/bundles/org.eclipse.wst.xml.core/component.xml b/bundles/org.eclipse.wst.xml.core/component.xml
new file mode 100644
index 0000000..e061eb3
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/component.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<component xmlns="http://eclipse.org/wtp/releng/tools/component-model" name="org.eclipse.wst.xml">
+	<component-depends unrestricted="true"></component-depends>
+	<plugin id="org.eclipse.wst.xmleditor.doc.user" fragment="false" />
+	<plugin id="org.eclipse.wst.xml.core" fragment="false" />
+	<plugin id="org.eclipse.wst.xml.ui" fragment="false" />
+	<description url="http://eclipse.org/webtools/wst/components/xml/overview.html" />
+	<package name="org.eclipse.wst.xml.ui" api="false">
+		<type name="StructuredTextViewerConfigurationXML" subclass="true" instantiate="true" />
+	</package>
+	<package name="org.eclipse.wst.xml.ui.views.contentoutline" api="false">
+		<type name="XMLContentOutlineConfiguration" subclass="true" instantiate="true" />
+	</package>
+	<package name="org.eclipse.wst.xml.ui.views.properties" api="false">
+		<type name="XMLPropertySheetConfiguration" subclass="true" instantiate="true" />
+	</package>
+	<plugin id="org.eclipse.wst.xml.ui.infopop" fragment="false" />
+	<plugin id="org.eclipse.wst.xml_core.feature.source" fragment="false" />
+	<plugin id="org.eclipse.wst.xml_ui.feature.source" fragment="false" />
+	<plugin id="org.apache.xerces" fragment="false" />
+</component>
diff --git a/bundles/org.eclipse.wst.xml.core/plugin.properties b/bundles/org.eclipse.wst.xml.core/plugin.properties
new file mode 100644
index 0000000..0e9ea2b
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/plugin.properties
@@ -0,0 +1,28 @@
+###############################################################################
+# Copyright (c) 2001, 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
+#     Jens Lukowski/Innoopract - initial renaming/restructuring
+#     
+###############################################################################
+providerName=Eclipse Web Tools Platform
+pluginName=Structured Source XML Model
+Structured_XML_Document_Factory_Extension.name=Structured XML Document Factory Extension
+XML_Content_Type_Extension_Element.name=XML (Illformed)
+# contentmodel strings
+Content_Model_Document_Factories_Extension.name=Content Model Document Factories
+Content_Model_Annotation_Files_Extension.name=Content Model Annotation Files
+Model_Query_Extension.name=Model Query Extension
+XML_Catalog_Contributions_Extension_Point.name=XML Catalog Contributions Extension Point
+XSL_Content_Type_Extension_Element.name=XSL
+XMI_Content_Type=XMI
+XML_Validator.name=XML Validator
+XML_Validation_Error_Customizer.name=XML Validator Error Customizer Extension Point
+External_Schema_Location.name=XML External Schema Location Extension Point
+_validationMarker.name=XML Problem
+_taskMarker.name=XML Task
diff --git a/bundles/org.eclipse.wst.xml.core/plugin.xml b/bundles/org.eclipse.wst.xml.core/plugin.xml
new file mode 100644
index 0000000..cf6ec4e
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/plugin.xml
@@ -0,0 +1,209 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+<plugin>
+
+   <!-- An extension for contributing a XML validation error customizer. -->
+   <extension-point id="errorCustomizer" name="%XML_Validation_Error_Customizer.name" schema="schema/errorCustomizer.exsd"/>
+	<extension-point id="externalSchemaLocations" name="%External_Schema_Location.name" schema="schema/externalSchemaLocations.exsd"/>
+
+	<extension point="org.eclipse.wst.sse.core.modelHandler">
+		<modelHandler
+			default="true"
+			class="org.eclipse.wst.xml.core.internal.modelhandler.ModelHandlerForXML"
+			associatedContentTypeId="org.eclipse.core.runtime.xml"
+			id="org.eclipse.wst.xml.core.internal.modelhandler">
+		</modelHandler>
+	</extension>
+	<extension point="org.eclipse.wst.sse.core.modelHandler">
+		<modelHandler
+			default="true"
+			class="org.eclipse.wst.xml.core.internal.modelhandler.ModelHandlerForXML"
+			associatedContentTypeId="org.eclipse.wst.xml.core.xmlsource"
+			id="org.eclipse.wst.xml.core.internal.modelhandler2">
+		</modelHandler>
+	</extension>
+	
+	<extension point="org.eclipse.wst.sse.core.embeddedTypeHandler">
+		<embeddedTypeHandler
+			class="org.eclipse.wst.xml.core.internal.modelhandler.EmbeddedXML">
+		</embeddedTypeHandler>
+	</extension>
+
+	<extension point="org.eclipse.wst.sse.core.taskscanner">
+		<scanner
+			id="org.eclipse.wst.xml.core.internal.tasks.XMLFileTaskScanner"
+			class="org.eclipse.wst.xml.core.internal.tasks.XMLFileTaskScanner:org.eclipse.wst.xml.core.taskMarker"
+			contentTypeIds="org.eclipse.core.runtime.xml" />
+	</extension>
+	<extension
+		id="taskMarker"
+		name="%_taskMarker.name"
+		point="org.eclipse.core.resources.markers">
+		<super type="org.eclipse.core.resources.taskmarker"/>
+		<persistent value="true"/>
+	</extension>
+	 
+   <!-- Here we define a new extension point.  This extension point is used
+        to programmatically contribute catalog entries to the XML Catalog. -->
+   <extension-point id="catalogContributions" name="%XML_Catalog_Contributions_Extension_Point.name" schema="schema/catalogContributions.exsd"/>
+
+   <!-- This extension point extends the Common Extensbile URI Resolver so that
+        the XML Catalog can participare in resolving processes. -->
+   <extension point="org.eclipse.wst.common.uriresolver.resolverExtensions">
+      <resolverExtension
+            stage="postnormalization"
+            class="org.eclipse.wst.xml.core.internal.catalog.XMLCatalogURIResolverExtension">
+      </resolverExtension>
+   </extension>
+
+	<extension
+		point="org.eclipse.core.filebuffers.documentCreation"
+		id="org.eclipse.wst.xml.core.documentfactories"
+		name="%Structured_XML_Document_Factory_Extension.name">
+		<factory
+			contentTypeId="org.eclipse.core.runtime.xml"
+			class="org.eclipse.wst.sse.core.internal.filebuffers.BasicStructuredDocumentFactory" />
+	</extension>
+	<extension
+		point="org.eclipse.core.filebuffers.documentCreation"
+		id="org.eclipse.wst.xml.core.documentfactories2"
+		name="%Structured_XML_Document_Factory_Extension.name">
+		<factory
+			contentTypeId="org.eclipse.wst.xml.core.xmlsource"
+			class="org.eclipse.wst.sse.core.internal.filebuffers.BasicStructuredDocumentFactory" />
+	</extension>
+	<extension point="org.eclipse.team.core.fileTypes">
+		<fileTypes
+			type="text"
+			extension="xsl">
+		</fileTypes>
+		<fileTypes
+			type="text"
+			extension="xslt">
+		</fileTypes>
+		<fileTypes
+			type="text"
+			extension="dadx">
+		</fileTypes>
+		<fileTypes
+			type="text"
+			extension="wsdl">
+		</fileTypes>
+		<fileTypes
+			type="text"
+			extension="nst">
+		</fileTypes>
+		<fileTypes
+			type="text"
+			extension="xmi">
+		</fileTypes>
+		<fileTypes
+			type="text"
+			extension="xsd">
+		</fileTypes>
+	</extension>
+	
+	<extension point="org.eclipse.wst.sse.core.formatProcessors">
+		<processor
+			class="org.eclipse.wst.xml.core.internal.formatter.XMLFormatterFormatProcessor"
+			contentTypeId="org.eclipse.core.runtime.xml">
+		</processor>
+	</extension>
+
+	<!--  https://bugs.eclipse.org/bugs/show_bug.cgi?id=103083 -->\
+	<!--  FYI: this xmi type *should* be defined in EMF, but, since isn't
+			we will here. In future versions is could be removed -->
+	<extension point="org.eclipse.core.contenttype.contentTypes">
+		<content-type
+			file-extensions="xmi"
+			priority="low"
+			name="%XMI_Content_Type"
+			id="xmisource"
+			base-type="org.eclipse.core.runtime.xml">
+		</content-type>
+
+		<content-type
+			file-extensions="xml,xsl,xslt,wsdl,xsd,exsd,xmi"
+			priority="low"
+			name="%XML_Content_Type_Extension_Element.name"
+			id="xmlsource"
+			base-type="org.eclipse.core.runtime.text"
+			default-charset="UTF-8">
+			<describer class="org.eclipse.wst.xml.core.internal.contenttype.ContentDescriberForXML" />
+		</content-type>
+
+		<content-type
+			file-extensions="xsl,xslt"
+			priority="high"
+			name="%XSL_Content_Type_Extension_Element.name"
+			id="xslsource"
+			base-type="org.eclipse.core.runtime.xml"
+			default-charset="UTF-8">
+		</content-type>
+	</extension>
+
+
+	<!-- initialize xml core preferences -->
+	<extension point="org.eclipse.core.runtime.preferences">
+		<initializer class="org.eclipse.wst.xml.core.internal.preferences.XMLCorePreferenceInitializer" />
+	</extension>
+
+	<extension-point id="documentFactories" name="%Content_Model_Document_Factories_Extension.name" schema="schema/documentFactories.exsd"/>
+
+	<extension-point id="modelQueryExtensions" name="%Model_Query_Extension.name" schema="schema/modelQueryExtensions.exsd"/>
+
+	<extension-point id="annotationFiles" name="%Content_Model_Annotation_Files_Extension.name" schema="schema/annotationFiles.exsd"/>	
+		
+	<extension 
+       point="org.eclipse.jem.util.uiContextSensitiveClass">
+       <uiContextSensitiveClass
+            context="UI"
+            key="rendererFactory"
+            className="org.eclipse.wst.xml.core.internal.emf2xml.EMF2DOMSSERendererFactory">
+       </uiContextSensitiveClass>
+  </extension>
+  <!-- ====================================================== -->
+	<!-- Register the XML validator with the validation 		-->
+	<!-- framework. 										    -->
+	<!-- ====================================================== -->
+
+ <extension
+         id="validationMarker"
+         name="%_validationMarker.name"
+         point="org.eclipse.core.resources.markers">
+      <super type="org.eclipse.wst.validation.problemmarker"/>
+      <persistent value="true"/>
+ </extension>
+
+   <extension id="xml" name="%XML_Validator.name" point="org.eclipse.wst.validation.validatorV2">
+      <validator
+            build="true"
+            class="org.eclipse.wst.xml.core.internal.validation.eclipse.Validator"
+            manual="true"
+            sourceid="org.eclipse.wst.xml.ui.internal.validation.DelegatingSourceValidatorForXML"
+            version="3"
+            markerId="org.eclipse.wst.xml.core.validationMarker">
+         <include>
+            <rules>
+               <contentType id="org.eclipse.core.runtime.xml"></contentType>
+               <contentType id="org.eclipse.wst.xml.core.xmlsource"></contentType>
+               <contentType id="org.eclipse.wst.xml.core.xslsource"></contentType>
+               <contentType id="org.eclipse.jst.jsp.core.tldsource"></contentType>
+               <fileext
+                     caseSensitive="false"
+                     ext="xml">
+               </fileext>
+            </rules>
+         </include>
+         <exclude>
+            <rules>
+				<projectNature id="org.eclipse.jst.j2ee.ejb.EJBNature"/>
+				<projectNature id="org.eclipse.jst.j2ee.EARNature"/>
+    			<file caseSensitive="true" name=".project" type="file"/>
+    			<file caseSensitive="true" name=".classpath" type="file"/>
+    			<file caseSensitive="true" name=".settings"  type="folder"/>
+            </rules>
+         </exclude>
+      </validator>
+   </extension>
+</plugin>
diff --git a/bundles/org.eclipse.wst.xml.core/schema/annotationFiles.exsd b/bundles/org.eclipse.wst.xml.core/schema/annotationFiles.exsd
new file mode 100644
index 0000000..d417f55
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/schema/annotationFiles.exsd
@@ -0,0 +1,113 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.wst.xml.core">
+<annotation>
+      <appInfo>
+         <meta.schema plugin="org.eclipse.wst.xml.core" id="annotationFiles" name="Content Model Annotation Files"/>
+      </appInfo>
+      <documentation>
+         &lt;b&gt;This extension point is internal and should not be used by any other plugins.&lt;/b&gt;
+      </documentation>
+   </annotation>
+
+   <element name="extension">
+      <complexType>
+         <sequence>
+            <element ref="annotationFile" minOccurs="1" maxOccurs="unbounded"/>
+         </sequence>
+         <attribute name="point" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="id" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="name" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+               <appInfo>
+                  <meta.attribute translatable="true"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <element name="annotationFile">
+      <complexType>
+         <attribute name="location" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="publicId" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="since"/>
+      </appInfo>
+      <documentation>
+         &lt;b&gt;This extension point is internal and should not be used by any other plugins.&lt;/b&gt;
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="examples"/>
+      </appInfo>
+      <documentation>
+         
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="apiInfo"/>
+      </appInfo>
+      <documentation>
+         
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="implementation"/>
+      </appInfo>
+      <documentation>
+         
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="copyright"/>
+      </appInfo>
+      <documentation>
+         Copyright (c) 2000, 2005 IBM Corporation and others.&lt;br&gt;
+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 &lt;a
+href=&quot;http://www.eclipse.org/legal/epl-v10.html&quot;&gt;http://www.eclipse.org/legal/epl-v10.html&lt;/a&gt;
+      </documentation>
+   </annotation>
+
+</schema>
diff --git a/bundles/org.eclipse.wst.xml.core/schema/catalogContributions.exsd b/bundles/org.eclipse.wst.xml.core/schema/catalogContributions.exsd
new file mode 100644
index 0000000..b7bad1b
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/schema/catalogContributions.exsd
@@ -0,0 +1,283 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.wst.xml.core">
+<annotation>
+      <appInfo>
+         <meta.schema plugin="org.eclipse.wst.xml.core" id="catalogContributions" name="XML Catalog Contributions Extension Point"/>
+      </appInfo>
+      <documentation>
+         This extension point allows to specify entries for XML Catalog.  Catalog entries have format specified in &lt;a href=&quot;http://www.oasis-open.org/committees/download.php/14041/xml-catalogs.html&quot;&gt;http://www.oasis-open.org/committees/entity/spec.html&lt;/a&gt;.  
+Each catalog extension consists of a single catalogContribution element.
+      </documentation>
+   </annotation>
+
+   <element name="extension">
+      <complexType>
+         <choice>
+            <element ref="catalogContribution"/>
+         </choice>
+         <attribute name="point" type="string" use="required">
+            <annotation>
+               <documentation>
+                  a fully qualified identifier of the target extension point
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="id" type="string">
+            <annotation>
+               <documentation>
+                  an optional identifier of the extension instance
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="name" type="string">
+            <annotation>
+               <documentation>
+                  an optional name of the extension instance
+               </documentation>
+               <appInfo>
+                  <meta.attribute translatable="true"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <element name="catalogContribution">
+      <annotation>
+         <documentation>
+            The catalogContribution element may have id, and it is just a container for the contributed catalog entries.
+         </documentation>
+      </annotation>
+      <complexType>
+         <sequence>
+            <element ref="public" minOccurs="0" maxOccurs="unbounded"/>
+            <element ref="system" minOccurs="0" maxOccurs="unbounded"/>
+            <element ref="uri" minOccurs="0" maxOccurs="unbounded"/>
+            <element ref="nextCatalog" minOccurs="0" maxOccurs="unbounded"/>
+         </sequence>
+         <attribute name="id" type="string">
+            <annotation>
+               <documentation>
+                  Id of the catalog to which entries will be added. Could be &quot;default&quot;, and if ommited, entries are added to the default workspace catalog.
+               </documentation>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <element name="public">
+      <annotation>
+         <documentation>
+            The public element associates a URI reference with the public identitier portion of an external identifier.
+         </documentation>
+      </annotation>
+      <complexType>
+         <sequence>
+         </sequence>
+         <attribute name="id" type="string">
+            <annotation>
+               <documentation>
+                  Id of the element, optional.
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="publicId" type="string" use="required">
+            <annotation>
+               <documentation>
+                  The public identifier portion of an external identifier.
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="uri" type="string" use="required">
+            <annotation>
+               <documentation>
+                  The value of the uri attribute could be relative to the plugin.xml file, use platform:/ or file:/ protocols.
+               </documentation>
+               <appInfo>
+                  <meta.attribute kind="resource"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+         <attribute name="webURL" type="string">
+            <annotation>
+               <documentation>
+                  Alternative Web address for the public ID
+               </documentation>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <element name="system">
+      <annotation>
+         <documentation>
+            The system elements associates a URI reference with the system identifier of an external identifier
+         </documentation>
+      </annotation>
+      <complexType>
+         <sequence>
+         </sequence>
+         <attribute name="id" type="string">
+            <annotation>
+               <documentation>
+                  Id of the element, optional.
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="systemId" type="string" use="required">
+            <annotation>
+               <documentation>
+                  The system identifier portion of an external identifier.
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="uri" type="string" use="required">
+            <annotation>
+               <documentation>
+                  The value of the uri attribute could be relative to the plugin.xml file, use platform:/ or file:/ protocols.
+               </documentation>
+               <appInfo>
+                  <meta.attribute kind="resource"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <element name="uri">
+      <annotation>
+         <documentation>
+            The uri element associates a URI reference with the a URI reference that is not part of an external identifier.
+         </documentation>
+      </annotation>
+      <complexType>
+         <sequence>
+         </sequence>
+         <attribute name="id" type="string">
+            <annotation>
+               <documentation>
+                  Id of the element, optional.
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="uri" type="string" use="required">
+            <annotation>
+               <documentation>
+                  The value of the uri attribute could be relative to the plugin.xml file, use platform:/ or file:/ protocols.
+               </documentation>
+               <appInfo>
+                  <meta.attribute kind="resource"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+         <attribute name="name" type="string" use="required">
+            <annotation>
+               <documentation>
+                  A URI reference that is not part of an external identitier.
+               </documentation>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <element name="nextCatalog">
+      <annotation>
+         <documentation>
+            The nextCatalog elements indicate additional catalog entry file(s) to be considered during the process of resolution.
+         </documentation>
+      </annotation>
+      <complexType>
+         <attribute name="id" type="string">
+            <annotation>
+               <documentation>
+                  Id of the element, optional.
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="catalog" type="string" use="required">
+            <annotation>
+               <documentation>
+                  The value of the uri attribute could be relative to the plugin.xml file, use platform:/ or file:/ protocols.
+               </documentation>
+               <appInfo>
+                  <meta.attribute kind="resource"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="since"/>
+      </appInfo>
+      <documentation>
+         1.0
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="examples"/>
+      </appInfo>
+      <documentation>
+         &lt;pre&gt;
+   &lt;extension 
+         point=&quot;org.eclipse.wst.xml.core.catalogContributions&quot;&gt;
+      &lt;catalogContribution&gt; 
+         &lt;system 
+               systemId=&quot;http://schemas.xmlsoap.org/wsdl/&quot;
+               uri=&quot;data/xsd/wsdl.xml&quot; &gt; 
+            &lt;property 
+                  name=&quot;webURL&quot;
+                  value=&quot;http://schemas.xmlsoap.org/wsdl/&quot;/&gt;
+         &lt;/system&gt;
+         &lt;uri
+               name=&quot;http://schemas.xmlsoap.org/wsdl/soap/&quot; 
+               uri=&quot;data/xsd/soap.xsd&quot;/&gt; 
+         &lt;public
+               publicId=&quot;http://www.w3.org/1999/XSL/Transform&quot;
+               uri=&quot;data/xsd/XSLSchema.xsd&quot;&gt;
+         &lt;/public&gt;
+         &lt;nextCatalog
+               id=&quot;nestedCatalog&quot; 
+               catalog=&quot;data/catalog1.xml&quot;/&gt; 
+      &lt;/catalogContribution&gt; 
+   &lt;/extension&gt;
+&lt;/pre&gt;
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="apiInfo"/>
+      </appInfo>
+      <documentation>
+         
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="implementation"/>
+      </appInfo>
+      <documentation>
+         
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="copyright"/>
+      </appInfo>
+      <documentation>
+         Copyright (c) 2005 IBM Corporation and others.&lt;br&gt;
+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 &lt;a
+href=&quot;http://www.eclipse.org/legal/epl-v10.html&quot;&gt;http://www.eclipse.org/legal/epl-v10.html&lt;/a&gt;
+      </documentation>
+   </annotation>
+
+</schema>
diff --git a/bundles/org.eclipse.wst.xml.core/schema/documentFactories.exsd b/bundles/org.eclipse.wst.xml.core/schema/documentFactories.exsd
new file mode 100644
index 0000000..dd0d906
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/schema/documentFactories.exsd
@@ -0,0 +1,116 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.wst.xml.core">
+<annotation>
+      <appInfo>
+         <meta.schema plugin="org.eclipse.wst.xml.core" id="documentFactories" name="Content Model Document Factories"/>
+      </appInfo>
+      <documentation>
+         &lt;b&gt;This extension point is internal and should not be used by any other plugins.&lt;/b&gt;
+      </documentation>
+   </annotation>
+
+   <element name="extension">
+      <complexType>
+         <sequence>
+            <element ref="factory"/>
+         </sequence>
+         <attribute name="point" type="string" use="required">
+            <annotation>
+               <documentation>
+                  a fully qualified identifier of the target extension point
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="id" type="string">
+            <annotation>
+               <documentation>
+                  an optional identifier of the extension instance
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="name" type="string">
+            <annotation>
+               <documentation>
+                  an optional name of the extension instance
+               </documentation>
+               <appInfo>
+                  <meta.attribute translatable="true"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <element name="factory">
+      <complexType>
+         <attribute name="type" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="class" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+               <appInfo>
+                  <meta.attribute kind="java"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="since"/>
+      </appInfo>
+      <documentation>
+         &lt;b&gt;This extension point is internal and should not be used by any other plugins.&lt;/b&gt;
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="examples"/>
+      </appInfo>
+      <documentation>
+         
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="apiInfo"/>
+      </appInfo>
+      <documentation>
+         
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="implementation"/>
+      </appInfo>
+      <documentation>
+         
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="copyright"/>
+      </appInfo>
+      <documentation>
+         Copyright (c) 2000, 2005 IBM Corporation and others.&lt;br&gt;
+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 &lt;a
+href=&quot;http://www.eclipse.org/legal/epl-v10.html&quot;&gt;http://www.eclipse.org/legal/epl-v10.html&lt;/a&gt;
+      </documentation>
+   </annotation>
+
+</schema>
diff --git a/bundles/org.eclipse.wst.xml.core/schema/errorCustomizer.exsd b/bundles/org.eclipse.wst.xml.core/schema/errorCustomizer.exsd
new file mode 100644
index 0000000..608f190
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/schema/errorCustomizer.exsd
@@ -0,0 +1,123 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.wst.xml.core">
+<annotation>
+      <appInfo>
+         <meta.schema plugin="org.eclipse.wst.xml.core" id="errorCustomizer" name="XML Validation Error Customizer"/>
+      </appInfo>
+      <documentation>
+         The error customizer extension point allows a client to contribute an error customizer for a specific namespace. The error customizer can provide error messages that are more domain specific than the generic error messages provided by the underlying generic XML validator.
+      </documentation>
+   </annotation>
+
+   <element name="extension">
+      <complexType>
+         <sequence>
+            <element ref="errorCustomizer" minOccurs="1" maxOccurs="unbounded"/>
+         </sequence>
+         <attribute name="point" type="string" use="required">
+            <annotation>
+               <documentation>
+                  a fully qualified identifier of the target extension point
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="id" type="string">
+            <annotation>
+               <documentation>
+                  an optional identifier of the extension instance
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="name" type="string">
+            <annotation>
+               <documentation>
+                  an optional name of the extension instance
+               </documentation>
+               <appInfo>
+                  <meta.attribute translatable="true"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <element name="errorCustomizer">
+      <complexType>
+         <attribute name="namespace" type="string" use="required">
+            <annotation>
+               <documentation>
+                  The namespace for which this error customizer will consider error customizations.
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="class" type="string" use="required">
+            <annotation>
+               <documentation>
+                  The class that implements &lt;code&gt;org.eclipse.wst.xml.core.internal.validation.errorcustomization.IErrorMessageCustomizer&lt;/code&gt;.
+               </documentation>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="since"/>
+      </appInfo>
+      <documentation>
+         &lt;b&gt;This extension point is part of an interim API that is still under development and expected to change significantly before reaching stability. It is being made available at this early stage to solicit feedback from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken (repeatedly) as the API evolves.&lt;/b&gt;
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="examples"/>
+      </appInfo>
+      <documentation>
+         The following is an example of an Error Customizer contribution:
+&lt;pre&gt;
+   &lt;extension
+         id=&quot;sampleErrorCustomizer&quot;
+         name=&quot;Sample Error Customizer&quot;
+         point=&quot;org.eclipse.wst.xml.core.errorCustomizer&quot;&gt;
+      &lt;errorCustomizer
+            namespace=&quot;http://sample.namespace&quot;
+            class=&quot;org.eclipse.wst.xml.core.SampleErrorCustomizer&quot;/&gt;
+   &lt;/extension&gt;
+&lt;/pre&gt;
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="apiInfo"/>
+      </appInfo>
+      <documentation>
+         The supplied class must implement &lt;code&gt;org.eclipse.wst.xml.core.internal.validation.errorcustomization.IErrorMessageCustomizer&lt;/code&gt;.
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="implementation"/>
+      </appInfo>
+      <documentation>
+         
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="copyright"/>
+      </appInfo>
+      <documentation>
+         Copyright (c) 2006 IBM Corporation and others.&lt;br&gt;
+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 &lt;a
+href=&quot;http://www.eclipse.org/legal/epl-v10.html&quot;&gt;http://www.eclipse.org/legal/epl-v10.html&lt;/a&gt;
+      </documentation>
+   </annotation>
+
+</schema>
diff --git a/bundles/org.eclipse.wst.xml.core/schema/externalSchemaLocations.exsd b/bundles/org.eclipse.wst.xml.core/schema/externalSchemaLocations.exsd
new file mode 100644
index 0000000..2031c77
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/schema/externalSchemaLocations.exsd
@@ -0,0 +1,102 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.wst.xml.core" xmlns="http://www.w3.org/2001/XMLSchema">
+<annotation>
+      <appInfo>
+         <meta.schema plugin="org.eclipse.wst.xml.core" id="externalSchemaLocations" name="External Schema Locations"/>
+      </appInfo>
+      <documentation>
+         [Enter description of this extension point.]
+      </documentation>
+   </annotation>
+
+   <element name="extension">
+      <annotation>
+         <appInfo>
+            <meta.element />
+         </appInfo>
+      </annotation>
+      <complexType>
+         <sequence minOccurs="1" maxOccurs="unbounded">
+            <element ref="provider"/>
+         </sequence>
+         <attribute name="point" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="id" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="name" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+               <appInfo>
+                  <meta.attribute translatable="true"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <element name="provider">
+      <complexType>
+         <attribute name="class" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+               <appInfo>
+                  <meta.attribute kind="java" basedOn=":org.eclipse.wst.xml.core.internal.contentmodel.modelquery.IExternalSchemaLocationProvider"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="since"/>
+      </appInfo>
+      <documentation>
+         [Enter the first release in which this extension point appears.]
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="examples"/>
+      </appInfo>
+      <documentation>
+         [Enter extension point usage example here.]
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="apiinfo"/>
+      </appInfo>
+      <documentation>
+         [Enter API information here.]
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="implementation"/>
+      </appInfo>
+      <documentation>
+         [Enter information about supplied implementation of this extension point.]
+      </documentation>
+   </annotation>
+
+
+</schema>
diff --git a/bundles/org.eclipse.wst.xml.core/schema/modelQueryExtensions.exsd b/bundles/org.eclipse.wst.xml.core/schema/modelQueryExtensions.exsd
new file mode 100644
index 0000000..6b2f977
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/schema/modelQueryExtensions.exsd
@@ -0,0 +1,102 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.wst.xml.core" xmlns="http://www.w3.org/2001/XMLSchema">
+<annotation>
+      <appinfo>
+         <meta.schema plugin="org.eclipse.wst.xml.core" id="modelQueryExtensions" name="Model Query Extension"/>
+      </appinfo>
+      <documentation>
+         &lt;b&gt;This extension point is internal and should not be used by any other plugins.&lt;/b&gt;
+      </documentation>
+   </annotation>
+
+   <element name="extension">
+      <annotation>
+         <appinfo>
+            <meta.element internal="true" />
+         </appinfo>
+      </annotation>
+      <complexType>
+         <sequence>
+            <element ref="modelQueryExtension"/>
+         </sequence>
+         <attribute name="point" type="string" use="required">
+            <annotation>
+               <documentation>
+                  a fully qualified identifier of the target extension point
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="id" type="string">
+            <annotation>
+               <documentation>
+                  an optional identifier of the extension instance
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="name" type="string">
+            <annotation>
+               <documentation>
+                  an optional name of the extension instance
+               </documentation>
+               <appinfo>
+                  <meta.attribute translatable="true"/>
+               </appinfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <element name="modelQueryExtension">
+      <annotation>
+         <documentation>
+            Allows for the customization of returned vaues from a ModelQuery object.
+         </documentation>
+      </annotation>
+      <complexType>
+         <attribute name="class" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+               <appinfo>
+                  <meta.attribute kind="java" basedOn="org.eclipse.wst.xml.core.internal.contentmodel.modelquery.extension.ModelQueryExtension:"/>
+               </appinfo>
+            </annotation>
+         </attribute>
+         <attribute name="contentType" type="string" use="required">
+            <annotation>
+               <documentation>
+                  Content Types for which to use this extension
+               </documentation>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <annotation>
+      <appinfo>
+         <meta.section type="since"/>
+      </appinfo>
+      <documentation>
+         &lt;b&gt;This extension point is internal and should not be used by any other plugins.&lt;/b&gt;
+      </documentation>
+   </annotation>
+
+
+
+
+   <annotation>
+      <appinfo>
+         <meta.section type="copyright"/>
+      </appinfo>
+      <documentation>
+         Copyright (c) 2000, 2005 IBM Corporation and others.&lt;br&gt;
+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 &lt;a
+href=&quot;http://www.eclipse.org/legal/epl-v10.html&quot;&gt;http://www.eclipse.org/legal/epl-v10.html&lt;/a&gt;
+      </documentation>
+   </annotation>
+
+</schema>
diff --git a/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/Catalog.java b/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/Catalog.java
new file mode 100644
index 0000000..6586c01
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/Catalog.java
@@ -0,0 +1,787 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2009 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     Jesper Steen Moeller - Added XML Catalogs 1.1 support
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.catalog;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.wst.xml.core.internal.Logger;
+import org.eclipse.wst.xml.core.internal.XMLCorePlugin;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalog;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalogElement;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalogEntry;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalogEvent;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalogListener;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.IDelegateCatalog;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.INextCatalog;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.IRewriteEntry;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ISuffixEntry;
+public class Catalog implements ICatalog
+{
+
+	class CatalogLS
+	{
+		public void load()
+		{
+		}
+
+		public synchronized void save()
+		{
+			try
+			{
+				new CatalogWriter().write(Catalog.this, location);
+			} catch (Exception e)
+			{
+				Logger.logException(e);
+			}
+		}
+	}
+
+	class DefaultCatalogLS extends CatalogLS
+	{
+		public void load()
+		{
+			NextCatalog userCatalogReference = new NextCatalog();
+			userCatalogReference.setId(XMLCorePlugin.USER_CATALOG_ID);
+			userCatalogReference.setCatalogLocation(USER_CATALOG_FILE);
+			addCatalogElement(userCatalogReference);
+
+			NextCatalog systemCatalogReference = new NextCatalog();
+			systemCatalogReference.setId(XMLCorePlugin.SYSTEM_CATALOG_ID);
+			systemCatalogReference.setCatalogLocation(SYSTEM_CATALOG_FILE);
+			addCatalogElement(systemCatalogReference);
+
+			/*
+			 * Here we save the file in order to 'reflect' the catalog that
+			 * we've created from plug-in extensions to disk. The 'default'
+			 * catalog is only ever written to disk and never read from disk.
+			 */
+			save();
+		}
+	}
+
+	private static Comparator LONGEST_REWRITE_FIRST = new Comparator() 
+	{
+		public int compare(Object entry1, Object entry2) 
+		{
+			String start1 = ((IRewriteEntry)entry1).getStartString();
+			String start2 = ((IRewriteEntry)entry2).getStartString();
+			
+			// Bigger is earlier
+			return start2.length() - start1.length();
+		}
+	};
+
+	private static Comparator LONGEST_SUFFIX_FIRST = new Comparator() 
+	{
+		public int compare(Object entry1, Object entry2) 
+		{
+			String suffix1 = ((ISuffixEntry)entry1).getSuffix();
+			String suffix2 = ((ISuffixEntry)entry2).getSuffix();
+			
+			// Bigger is earlier
+			return suffix2.length() - suffix1.length();
+		}
+	};
+
+	private static Comparator LONGEST_DELEGATE_PREFIX_FIRST = new Comparator() 
+	{
+		public int compare(Object entry1, Object entry2) 
+		{
+			String prefix1 = ((IDelegateCatalog)entry1).getStartString();
+			String prefix2 = ((IDelegateCatalog)entry2).getStartString();
+			
+			// Bigger is earlier
+			return prefix2.length() - prefix1.length();
+		}
+	};
+
+	class InternalResolver
+	{
+		protected Map publicMap = new HashMap();
+
+		protected Map systemMap = new HashMap();
+
+		protected Map uriMap = new HashMap();
+
+		// These are sorted by longest "key" first.
+		protected List rewriteSystemList = new LinkedList();
+		protected List rewriteUriList = new LinkedList();
+		protected List suffixSystemList = new LinkedList();
+		protected List suffixUriList = new LinkedList();
+		protected List delegatePublicList = new LinkedList();
+		protected List delegateSystemList = new LinkedList();
+		protected List delegateUriList = new LinkedList();
+		
+		InternalResolver()
+		{
+			for (Iterator i = catalogElements.iterator(); i.hasNext();)
+			{
+				ICatalogElement catalogElement = (ICatalogElement) i.next();
+				if (catalogElement.getType() == ICatalogElement.TYPE_ENTRY)
+				{
+					ICatalogEntry entry = (ICatalogEntry) catalogElement;
+					Map map = getEntryMap(entry.getEntryType());
+					map.put(entry.getKey(), entry);
+				} 
+				else if (catalogElement.getType() == ICatalogElement.TYPE_REWRITE) 
+				{
+					IRewriteEntry entry = (IRewriteEntry) catalogElement;
+					if (entry.getEntryType() == IRewriteEntry.REWRITE_TYPE_SYSTEM) 
+					{
+						rewriteSystemList.add(entry);
+					} 
+					else 
+					{
+						rewriteUriList.add(entry);
+					}
+				} 
+				else if (catalogElement.getType() == ICatalogElement.TYPE_SUFFIX) 
+				{
+					ISuffixEntry entry = (ISuffixEntry) catalogElement;
+					if (entry.getEntryType() == ISuffixEntry.SUFFIX_TYPE_SYSTEM) 
+					{
+						suffixSystemList.add(entry);
+					} 
+					else 
+					{
+						suffixUriList.add(entry);
+					}
+				} 
+				else if (catalogElement.getType() == ICatalogElement.TYPE_DELEGATE) 
+				{
+					IDelegateCatalog delegate = (IDelegateCatalog) catalogElement;
+					if (delegate.getEntryType() == IDelegateCatalog.DELEGATE_TYPE_PUBLIC) 
+					{
+						delegatePublicList.add(delegate);
+					}
+					else if (delegate.getEntryType() == IDelegateCatalog.DELEGATE_TYPE_SYSTEM) 
+					{
+						delegateSystemList.add(delegate);
+					}
+					else 
+					{
+						delegateUriList.add(delegate);
+					}
+				}
+			}
+			
+			Collections.sort(rewriteSystemList, LONGEST_REWRITE_FIRST);
+			Collections.sort(rewriteUriList, LONGEST_REWRITE_FIRST);
+
+			Collections.sort(suffixSystemList, LONGEST_SUFFIX_FIRST);
+			Collections.sort(suffixUriList, LONGEST_SUFFIX_FIRST);
+		
+			Collections.sort(delegatePublicList, LONGEST_DELEGATE_PREFIX_FIRST);
+			Collections.sort(delegateSystemList, LONGEST_DELEGATE_PREFIX_FIRST);
+			Collections.sort(delegateUriList, LONGEST_DELEGATE_PREFIX_FIRST);
+		}
+
+		private Map getEntryMap(int entryType)
+		{
+			Map map = systemMap;
+			switch (entryType)
+			{
+			case ICatalogEntry.ENTRY_TYPE_PUBLIC:
+				map = publicMap;
+				break;
+			case ICatalogEntry.ENTRY_TYPE_URI:
+				map = uriMap;
+				break;
+			default:
+				break;
+			}
+			return map;
+		}
+
+		protected String getMappedURI(Map map, String key)
+		{
+			CatalogEntry entry = (CatalogEntry) map.get(key);
+			if(entry == null) return null;
+			String uri = entry.getURI();
+			try
+			{
+                // TODO CS : do we really want to resolve these here?
+                // I'm guessing we should return the 'platform:' form of the URI
+                // to the caller.
+                if (uri.startsWith("platform:")) //$NON-NLS-1$
+                {  
+				  URL entryURL = new URL(entry.getAbsolutePath(uri));                
+				  uri = Platform.resolve(entryURL).toString();
+                  
+                  // we need to ensure URI's are of form "file:///D:/XXX" and NOT  
+                  // "file:D:/XXX".  Otherwise the EMF URI class gets confused
+                  // (see bug 103607) 
+                  String FILE_SCHEME = "file:"; //$NON-NLS-1$
+                  if (uri.startsWith(FILE_SCHEME) && !uri.startsWith(FILE_SCHEME + "/")) //$NON-NLS-1$
+                  {
+                    uri = FILE_SCHEME + "///" + uri.substring(FILE_SCHEME.length()); //$NON-NLS-1$
+                  }  
+                }  
+                return uri; 
+			} catch (IOException e)
+			{
+				return null;
+			}
+		}
+
+		public String resolvePublic(String publicId, String systemId)
+				throws MalformedURLException, IOException
+		{
+			String result = getMappedURI(publicMap, publicId);
+			if (result == null)
+			{
+				result = getMappedURI(systemMap, systemId);
+			}
+			// our clients used to pass namespace in place of public id, so we need to check uri map for those
+			if (result == null)
+			{
+				result = getMappedURI(uriMap, publicId);
+			}
+			if (result == null)
+			{
+				result = resolveDelegateCatalogs(delegatePublicList, publicId, systemId);
+			}
+			if (result == null)
+			{
+				result = resolveSubordinateCatalogs(
+						ICatalogEntry.ENTRY_TYPE_PUBLIC, publicId, systemId);
+			}
+			return result;
+		}
+
+		public String resolveSystem(String systemId)
+				throws MalformedURLException, IOException
+		{
+			String result = getMappedURI(systemMap, systemId);
+			if (result == null)
+			{
+				result = resolveRewrite(rewriteSystemList, systemId);
+			}
+			if (result == null)
+			{
+				result = resolveSuffix(suffixSystemList, systemId);
+			}
+			if (result == null)
+			{
+				result = resolveDelegateCatalogs(delegateSystemList, systemId, systemId); // systemId is the key for "startString"
+			}
+			if (result == null)
+			{
+				result = resolveSubordinateCatalogs(
+						ICatalogEntry.ENTRY_TYPE_SYSTEM, null, systemId);
+			}
+			return result;
+		}
+
+		private String resolveRewrite(List rewriteList, String searchString) 
+		{
+			for (Iterator it = rewriteList.iterator(); it.hasNext();) 
+			{
+				IRewriteEntry entry = (IRewriteEntry) it.next();
+				String startString = entry.getStartString();
+				if (searchString.startsWith(startString)) 
+				{
+					return entry.getRewritePrefix() + searchString.substring(startString.length());
+				}
+			}
+			return null;
+		}
+
+		private String resolveSuffix(List suffixList, String searchString) {
+			for (Iterator it = suffixList.iterator(); it.hasNext();) {
+				ISuffixEntry entry = (ISuffixEntry) it.next();
+				if (searchString.endsWith(entry.getSuffix())) {
+					return entry.getURI();
+				}
+			}
+			return null;
+		}
+
+		protected String resolveDelegateCatalogs(List delegateCatalogs, String key,
+				String systemId) throws MalformedURLException, IOException
+		{
+			String result = null;
+			for (Iterator iterator = delegateCatalogs.iterator(); iterator
+					.hasNext();) {
+				IDelegateCatalog delegate = (IDelegateCatalog) iterator.next();
+				
+				if (key.startsWith(delegate.getStartString())) {
+	
+					ICatalog catalog = delegate.getReferencedCatalog();
+					if (catalog != null)
+					{
+						switch (delegate.getEntryType())
+						{
+						case IDelegateCatalog.DELEGATE_TYPE_PUBLIC:
+							result = catalog.resolvePublic(key, systemId);
+							break;
+						case IDelegateCatalog.DELEGATE_TYPE_SYSTEM:
+							result = catalog.resolveSystem(systemId);
+							break;
+						case IDelegateCatalog.DELEGATE_TYPE_URI:
+							result = catalog.resolveURI(systemId);
+							break;
+						default:
+							break;
+						}
+						if (result != null)
+						{
+							return result;
+						}
+					}
+				}
+			}
+			return null;
+		}
+		
+		public String resolveURI(String uri) throws MalformedURLException,
+				IOException
+		{
+			String result = getMappedURI(uriMap, uri);
+			if (result == null)
+			{
+				result = resolveRewrite(rewriteUriList, uri);
+			}
+			if (result == null)
+			{
+				result = resolveSuffix(suffixUriList, uri);
+			}
+			if (result == null)
+			{
+				result = resolveDelegateCatalogs(delegateUriList, uri, uri); // uri is treated as the systemId
+			}
+			if (result == null)
+			{
+				result = resolveSubordinateCatalogs(
+						ICatalogEntry.ENTRY_TYPE_URI, null, uri);
+			}
+			return result;
+		}
+	}
+
+	class SystemCatalogLS extends CatalogLS
+	{
+		public void load()
+		{
+			new CatalogContributorRegistryReader(Catalog.this).readRegistry();
+
+			/*
+			 * Here we save the file in order to 'reflect' the catalog that
+			 * we've created from plugin extensions to disk. 
+			 * The 'system' catalog is only ever written to disk and never read from disk.
+			 */
+			save();
+		}
+	}
+
+	class UserCatalogLS extends CatalogLS
+	{
+		public void load()
+		{
+			InputStream inputStream = null;
+			try
+			{
+				if (location != null && location.length() > 0) 
+				{
+					URL url = new URL(location);
+					inputStream = url.openStream();
+					boolean oldNotificationEnabled = isNotificationEnabled();
+					setNotificationEnabled(false);
+					clear();
+					try
+					{
+						CatalogReader.read(Catalog.this, inputStream);
+					} finally
+					{
+						setNotificationEnabled(oldNotificationEnabled);
+					}
+				}
+				else
+				{
+					clear();
+				}
+				notifyChanged();
+			} catch (Exception e)
+			{
+				// This is OK since the catalog may not exist before we create it
+			} finally
+			{
+				if (inputStream != null)
+				{
+					try
+					{
+						inputStream.close();
+					} catch (Exception e)
+					{
+					}
+				}
+			}
+		}
+	}
+
+	public static final String DEFAULT_CATALOG_FILE = "default_catalog.xml"; //$NON-NLS-1$
+
+	public static final String SYSTEM_CATALOG_FILE = "system_catalog.xml"; //$NON-NLS-1$
+
+	public static final String USER_CATALOG_FILE = "user_catalog.xml"; //$NON-NLS-1$
+
+	protected String base;
+
+	protected List catalogElements = new ArrayList();
+
+	protected CatalogLS catalogLS;
+
+	protected String id;
+
+	protected InternalResolver internalResolver;
+
+	protected boolean isNotificationEnabled;
+
+	protected List listenerList = new ArrayList();
+
+	protected String location;
+
+	protected CatalogSet resourceSet;
+
+	public Catalog(CatalogSet catalogResourceSet, String id, String location)
+	{
+		this.resourceSet = catalogResourceSet;
+		this.id = id;
+		this.location = location;
+
+		if (XMLCorePlugin.DEFAULT_CATALOG_ID.equals(id))
+		{
+			catalogLS = new DefaultCatalogLS();
+		} else if (XMLCorePlugin.SYSTEM_CATALOG_ID.equals(id))
+		{
+			catalogLS = new SystemCatalogLS();
+		} else
+		{
+			catalogLS = new UserCatalogLS();
+		}
+	}
+
+	public void addCatalogElement(ICatalogElement element)
+	{
+		catalogElements.add(element);
+		element.setOwnerCatalog(this);
+		internalResolver = null;
+		notifyAddElement(element);
+	}
+
+	public void addEntriesFromCatalog(ICatalog catalog)
+	{
+		try
+		{
+			setNotificationEnabled(false);
+			if (catalog != null)
+			{
+				ICatalogElement[] entries = ((Catalog)catalog).getCatalogElements();
+				for (int i = 0; i < entries.length; i++)
+				{
+					CatalogElement clone = (CatalogElement)((CatalogElement)entries[i]).clone();
+					addCatalogElement(clone);
+				}
+			} else
+			{
+				Logger.log(Logger.ERROR, "argument was null in Catalog.addEntriesFromCatalog"); //$NON-NLS-1$
+			}
+		} finally
+		{
+			setNotificationEnabled(true);
+		}
+		internalResolver = null;
+		notifyChanged();
+	}
+
+	public void addListener(ICatalogListener listener)
+	{
+		listenerList.add(listener);
+	}
+
+	public void clear()
+	{
+		catalogElements.clear();
+		internalResolver = null;
+		notifyChanged();
+	}
+
+	public ICatalogElement createCatalogElement(int type)
+	{
+		switch (type)
+		{
+		case ICatalogElement.TYPE_ENTRY:
+			return new CatalogEntry(); // TODO: Should be kind of deprecated
+		case ICatalogElement.TYPE_NEXT_CATALOG:
+			return new NextCatalog();
+		case ICatalogEntry.ENTRY_TYPE_PUBLIC:
+		case ICatalogEntry.ENTRY_TYPE_SYSTEM:
+		case ICatalogEntry.ENTRY_TYPE_URI:
+			return new CatalogEntry(type);
+		case ICatalogElement.TYPE_REWRITE:	
+		case IRewriteEntry.REWRITE_TYPE_SYSTEM:
+		case IRewriteEntry.REWRITE_TYPE_URI:
+			return new RewriteEntry(type);
+		case ICatalogElement.TYPE_SUFFIX:	
+		case ISuffixEntry.SUFFIX_TYPE_SYSTEM:
+		case ISuffixEntry.SUFFIX_TYPE_URI:
+			return new SuffixEntry(type);
+		case ICatalogElement.TYPE_DELEGATE:	
+		case IDelegateCatalog.DELEGATE_TYPE_PUBLIC:
+		case IDelegateCatalog.DELEGATE_TYPE_SYSTEM:
+		case IDelegateCatalog.DELEGATE_TYPE_URI:
+			return new DelegateCatalog(type);
+		default:
+			throw new IllegalArgumentException("Unknown element type " + type);//$NON-NLS-1 // Makes no sense at all!
+		}
+	}
+
+	public String getBase()
+	{
+		return base;
+	}
+
+	private List getCatalogElements(int type)
+	{
+		List result = new ArrayList();
+		ICatalogElement[] elements = (ICatalogElement[]) catalogElements
+				.toArray(new ICatalogElement[catalogElements.size()]);
+		for (int i = 0; i < elements.length; i++)
+		{
+			ICatalogElement element = elements[i];
+			if (element.getType() == type)
+			{
+				result.add(element);
+			}
+		}
+		return result;
+	}
+
+	public ICatalogEntry[] getCatalogEntries()
+	{
+		List result = getCatalogElements(ICatalogElement.TYPE_ENTRY);
+		return (ICatalogEntry[]) result
+				.toArray(new ICatalogEntry[result.size()]);
+	}
+
+	public IDelegateCatalog[] getDelegateCatalogs() 
+	{
+		List result = getCatalogElements(ICatalogElement.TYPE_DELEGATE);
+		return (IDelegateCatalog[]) result
+				.toArray(new IDelegateCatalog[result.size()]);
+	}
+	
+	public IRewriteEntry[] getRewriteEntries() 
+	{
+		List result = getCatalogElements(ICatalogElement.TYPE_REWRITE);
+		return (IRewriteEntry[]) result
+				.toArray(new IRewriteEntry[result.size()]);
+	}
+	
+	public ISuffixEntry[] getSuffixEntries() 
+	{
+		List result = getCatalogElements(ICatalogElement.TYPE_SUFFIX);
+		return (ISuffixEntry[]) result
+				.toArray(new ISuffixEntry[result.size()]);
+	}
+	
+	protected CatalogSet getCatalogSet()
+	{
+		return resourceSet;
+	}
+
+	public String getId()
+	{
+		return id;
+	}
+
+	public String getLocation()
+	{
+		return location;
+	}
+
+	public INextCatalog[] getNextCatalogs()
+	{
+		List result = getCatalogElements(ICatalogElement.TYPE_NEXT_CATALOG);
+		return (INextCatalog[]) result.toArray(new INextCatalog[result.size()]);
+	}
+
+	protected InternalResolver getOrCreateInternalResolver()
+	{
+		if (internalResolver == null)
+		{
+			internalResolver = new InternalResolver();
+		}
+		return internalResolver;
+	}
+
+	protected boolean isNotificationEnabled()
+	{
+		return isNotificationEnabled;
+	}
+
+	public void load() throws IOException
+	{
+		catalogLS.load();
+	}
+
+	protected void notifyAddElement(ICatalogElement entry)
+	{
+		if (isNotificationEnabled)
+		{
+			ICatalogEvent event = new CatalogEvent(this, entry,
+					ICatalogEvent.ELEMENT_ADDED);
+			notifyListeners(event);
+		}
+	}
+
+	protected void notifyChanged()
+	{
+		ICatalogEvent event = new CatalogEvent(this, null,
+				ICatalogEvent.CHANGED);
+		notifyListeners(event);
+	}
+
+	protected void notifyListeners(ICatalogEvent event)
+	{
+		List list = new ArrayList();
+		list.addAll(listenerList);
+		for (Iterator i = list.iterator(); i.hasNext();)
+		{
+			ICatalogListener listener = (ICatalogListener) i.next();
+			listener.catalogChanged(event);
+		}
+	}
+
+	protected void notifyRemoveElement(ICatalogElement element)
+	{
+		if (isNotificationEnabled)
+		{
+			ICatalogEvent event = new CatalogEvent(this, element,
+					ICatalogEvent.ELEMENT_REMOVED);
+			notifyListeners(event);
+		}
+	}
+
+	public void removeCatalogElement(ICatalogElement element)
+	{
+		catalogElements.remove(element);
+		internalResolver = null;
+		notifyRemoveElement(element);
+		
+	}
+
+	public void removeListener(ICatalogListener listener)
+	{
+		listenerList.remove(listener);
+	}
+
+	public String resolvePublic(String publicId, String systemId)
+			throws MalformedURLException, IOException
+	{
+		return getOrCreateInternalResolver().resolvePublic(publicId, systemId);
+	}
+
+	protected String resolveSubordinateCatalogs(int entryType, String publicId,
+			String systemId) throws MalformedURLException, IOException
+	{
+		String result = null;
+		INextCatalog[] nextCatalogs = getNextCatalogs();
+		for (int i = 0; i < nextCatalogs.length; i++)
+		{
+			INextCatalog nextCatalog = nextCatalogs[i];
+			ICatalog catalog = nextCatalog.getReferencedCatalog();
+			if (catalog != null)
+			{
+				switch (entryType)
+				{
+				case ICatalogEntry.ENTRY_TYPE_PUBLIC:
+					result = catalog.resolvePublic(publicId, systemId);
+					break;
+				case ICatalogEntry.ENTRY_TYPE_SYSTEM:
+					result = catalog.resolveSystem(systemId);
+					break;
+				case ICatalogEntry.ENTRY_TYPE_URI:
+					result = catalog.resolveURI(systemId);
+					break;
+				default:
+					break;
+				}
+				if (result != null)
+				{
+					return result;
+				}
+			}
+		}
+		return null;
+	}
+
+	public String resolveSystem(String systemId) throws MalformedURLException,
+			IOException
+	{
+		return getOrCreateInternalResolver().resolveSystem(systemId);
+	}
+
+	public String resolveURI(String uri) throws MalformedURLException,
+			IOException
+	{
+		return getOrCreateInternalResolver().resolveURI(uri);
+	}
+
+	public void save() throws IOException
+	{
+		catalogLS.save();
+	}
+
+	public void setBase(String base)
+	{
+		this.base = base;
+	}
+
+	public void setId(String id)
+	{
+		this.id = id;
+	}
+
+	public void setLocation(String location)
+	{
+		this.location = location;
+	}
+
+	protected void setNotificationEnabled(boolean b)
+	{
+		isNotificationEnabled = b;
+	}
+
+	public ICatalogElement[] getCatalogElements()
+	{
+		return (ICatalogElement[]) catalogElements.toArray(new ICatalogElement[catalogElements.size()]);
+	}
+	
+
+	
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/CatalogContributorRegistryReader.java b/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/CatalogContributorRegistryReader.java
new file mode 100644
index 0000000..2f01c5f
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/CatalogContributorRegistryReader.java
@@ -0,0 +1,269 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.catalog;
+
+import java.io.IOException;
+import java.net.URL;
+
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtensionPoint;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.InvalidRegistryObjectException;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.wst.xml.core.internal.Logger;
+import org.eclipse.wst.xml.core.internal.XMLCoreMessages;
+import org.eclipse.wst.xml.core.internal.XMLCorePlugin;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalog;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalogElement;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalogEntry;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.INextCatalog;
+import org.osgi.framework.Bundle;
+
+public class CatalogContributorRegistryReader
+{
+  protected static final String EXTENSION_POINT_ID = "catalogContributions"; //$NON-NLS-1$
+  protected static final String TAG_CONTRIBUTION = "catalogContribution"; //$NON-NLS-1$
+  /*
+   * this is a sample exptension 
+   * <extension point="org.eclipse.wst.xml.core.catalogContributions"> 
+   * <catalogContribution>
+   *    <uri
+   *             name="http://schemas.xmlsoap.org/wsdl/soap/" 
+   *             uri="xsd/soap.xsd"/> 
+   *   	<public
+   *          publicId="-//W3C//DTD XHTML 1.1//EN"
+   *          uri="dtds/xhtml11-flat.dtd"/> 
+   *  	<nextCatalog id="nestedCatalog" catalog="data/catalog1.xml"/> 
+   *  </catalogContribution> 
+   *  </extension>
+   *  
+   */
+  protected ICatalog catalog;
+
+  protected String declaringExtensionId;
+  
+  protected CatalogContributorRegistryReader(ICatalog aCatalog)
+  {
+    catalog = aCatalog;
+  }
+
+  /**
+   * read from plugin registry and parse it.
+   */
+  protected void readRegistry()
+  {
+    IExtensionRegistry pluginRegistry = Platform.getExtensionRegistry();
+    IExtensionPoint point = pluginRegistry.getExtensionPoint(XMLCorePlugin.getDefault().getBundle().getSymbolicName(), EXTENSION_POINT_ID);
+    if (point != null)
+    {
+      IConfigurationElement[] elements = point.getConfigurationElements();
+      for (int i = 0; i < elements.length; i++)
+      {
+        readElement(elements[i]);
+      }
+    }
+    
+  }
+  
+  public static String resolvePath(URL platformURL, String path) 
+  {      
+	String fileLocation = path;
+	int jarPathStart = path.indexOf("jar:"); //$NON-NLS-1$
+	jarPathStart = jarPathStart < 0 ? 0 : jarPathStart + "jar:".length(); //$NON-NLS-1$
+	int jarPathEnd = path.indexOf("!"); //$NON-NLS-1$
+	jarPathEnd = jarPathEnd < 0 ? path.length() : jarPathEnd;
+	fileLocation = path.substring(jarPathStart, jarPathEnd);
+	
+	String result = path;
+	String resolvedLocation = fileLocation;
+	URL resolvedURL = null;
+    if (fileLocation.startsWith("platform:/plugin")) //$NON-NLS-1$
+    {
+      // this is the speclial case, where the resource is located relative 
+      // to another plugin (not the one that declares the extension point)
+      //
+		try
+		{
+			resolvedURL = Platform.resolve(new URL(fileLocation));
+		} catch (IOException e)
+		{
+			// do nothing
+		} 
+    }
+    else{
+    	 // this is the typical case, where the resource is located relative
+        // to the plugin that declares the extension point
+    	 try {
+    	     	resolvedURL = new URL(Platform.resolve(platformURL), fileLocation);
+    	 } catch (IOException e) {
+    	    	// do nothing
+    	 }
+    }
+   
+   if(resolvedURL != null){
+    	resolvedLocation = resolvedURL.toExternalForm().replace('\\', '/');
+    	result = result.replaceFirst(fileLocation, resolvedLocation);
+    }
+    return result;
+  }
+  
+  public static URL getPlatformURL(String pluginId){
+	  Bundle bundle = Platform.getBundle(pluginId);
+		if (bundle != null)
+		{
+			URL bundleEntry = bundle.getEntry("/"); //$NON-NLS-1$
+			
+			if(bundleEntry != null){
+				try
+				{
+					return Platform.resolve(bundleEntry);
+				} catch (IOException e)
+				{
+					Logger.logException(e);
+				}
+			}
+		}
+		return null;
+  }
+
+  private String resolvePath(String path)
+  {
+	  return resolvePath(getPlatformURL(declaringExtensionId), path);
+  }
+
+  protected void readElement(IConfigurationElement element)
+  {
+    try
+    {
+	  declaringExtensionId = element.getDeclaringExtension().getNamespace();
+    }
+    catch (InvalidRegistryObjectException e)
+    {
+      Logger.logException(e);
+    }
+    
+    if (TAG_CONTRIBUTION.equals(element.getName())){
+    	IConfigurationElement[] mappingInfoElementList = element.getChildren(OASISCatalogConstants.TAG_PUBLIC);
+    	processMappingInfoElements(mappingInfoElementList);
+    	mappingInfoElementList = element.getChildren(OASISCatalogConstants.TAG_SYSTEM);
+    	processMappingInfoElements(mappingInfoElementList);
+    	mappingInfoElementList = element.getChildren(OASISCatalogConstants.TAG_URI);
+    	processMappingInfoElements(mappingInfoElementList);
+    	IConfigurationElement[] nextCatalogElementList = element.getChildren(OASISCatalogConstants.TAG_NEXT_CATALOG);
+    	processNextCatalogElements(nextCatalogElementList);
+    	
+    }
+    
+  }
+
+  private void processMappingInfoElements(IConfigurationElement[] childElementList)
+  {
+    if (catalog == null)
+      return;
+    for (int i = 0; i < childElementList.length; i++)
+    {
+      IConfigurationElement childElement = childElementList[i];
+      String name = childElement.getName();
+      String key = null;
+	
+      int type = ICatalogEntry.ENTRY_TYPE_PUBLIC;
+      if (OASISCatalogConstants.TAG_PUBLIC.equals(name))
+      {
+        key = childElement.getAttribute(OASISCatalogConstants.ATTR_PUBLIC_ID);
+      }
+      else if (OASISCatalogConstants.TAG_SYSTEM.equals(name))
+      {
+        key = childElement.getAttribute(OASISCatalogConstants.ATTR_SYSTEM_ID);
+        type = ICatalogEntry.ENTRY_TYPE_SYSTEM;
+      }
+      else if (OASISCatalogConstants.TAG_URI.equals(name))
+      {
+        key = childElement.getAttribute(OASISCatalogConstants.ATTR_NAME);
+        type = ICatalogEntry.ENTRY_TYPE_URI;
+      }
+      else if (OASISCatalogConstants.TAG_NEXT_CATALOG.equals(name))
+      {
+        processNextCatalogElements(new IConfigurationElement[]{childElement});
+        continue;
+      }
+      if (key == null || key.equals("")) //$NON-NLS-1$
+      {
+         Logger.log(Logger.ERROR, XMLCoreMessages.Catalog_entry_key_not_set);
+        continue;
+      }
+      String entryURI = childElement.getAttribute(OASISCatalogConstants.ATTR_URI); // mandatory
+      if (entryURI == null || entryURI.equals("")) //$NON-NLS-1$
+      {
+       Logger.log(Logger.ERROR, XMLCoreMessages.Catalog_entry_uri_not_set);
+        continue;
+      }
+      ICatalogElement catalogElement = catalog.createCatalogElement(type);
+      if (catalogElement instanceof ICatalogEntry)
+      {
+        ICatalogEntry entry = (ICatalogEntry) catalogElement;
+        entry.setKey(key);
+		String resolvedPath = resolvePath(entryURI);
+		entry.setURI(resolvedPath);
+        String id = childElement.getAttribute(OASISCatalogConstants.ATTR_ID); // optional
+        if (id != null && !id.equals("")) //$NON-NLS-1$
+        {
+          entry.setId(id);
+        }
+      }
+      // process any other attributes
+      for (int j = 0; j < childElement.getAttributeNames().length; j++)
+      {
+        String attrName = childElement.getAttributeNames()[j];
+        if (!attrName.equals(OASISCatalogConstants.ATTR_URI) && !attrName.equals(OASISCatalogConstants.ATTR_NAME) && !attrName.equals(OASISCatalogConstants.ATTR_PUBLIC_ID)
+            && !attrName.equals(OASISCatalogConstants.ATTR_SYSTEM_ID) && !attrName.equals(OASISCatalogConstants.ATTR_CATALOG) && !attrName.equals(OASISCatalogConstants.ATTR_ID)
+            && !attrName.equals(OASISCatalogConstants.ATTR_BASE))
+        {
+          String attrValue = childElement.getAttribute(attrName);
+          if (attrValue != null && !attrValue.equals("")) //$NON-NLS-1$
+          {
+            catalogElement.setAttributeValue(attrName, attrValue);
+          }
+        }
+      }
+      catalog.addCatalogElement(catalogElement);
+    }
+  }
+
+  private void processNextCatalogElements(IConfigurationElement[] childElementList)
+  {
+    if (catalog == null)
+      return;
+    for (int i = 0; i < childElementList.length; i++)
+    {
+      IConfigurationElement childElement = childElementList[i];
+      String location = childElement.getAttribute(OASISCatalogConstants.ATTR_CATALOG); // mandatory
+      if (location == null || location.equals("")) //$NON-NLS-1$
+      {
+        Logger.log(Logger.ERROR, XMLCoreMessages.Catalog_next_catalog_location_uri_not_set);
+        continue;
+      }
+      INextCatalog nextCatalog = new NextCatalog();
+	  String resolvedPath = resolvePath(location);
+      nextCatalog.setCatalogLocation(resolvedPath);
+	  String id = childElement.getAttribute(OASISCatalogConstants.ATTR_ID);
+	  if (id != null && !id.equals("")) //$NON-NLS-1$
+      { 
+		  nextCatalog.setId(id);
+      }
+      catalog.addCatalogElement(nextCatalog);
+    }
+  }
+  
+ 
+ 
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/CatalogElement.java b/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/CatalogElement.java
new file mode 100644
index 0000000..ef86e22
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/CatalogElement.java
@@ -0,0 +1,174 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2009 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     Jesper Steen Moller - jesper@selskabet.org - bug 112284
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.catalog;
+
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalog;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalogElement;
+
+
+public class CatalogElement implements ICatalogElement
+{
+	int type;
+
+	String id;
+
+	String base;
+
+	Map attributes = new HashMap();
+
+	ICatalog ownerCatalog;
+
+	public CatalogElement(int aType)
+	{
+		super();
+		type = aType;
+	}
+
+	public int getType()
+	{
+		return type;
+	}
+
+	public String getBase()
+	{
+		return base;
+	}
+
+	public void setBase(String base)
+	{
+		this.base = base;
+	}
+
+	public String getAttributeValue(String name)
+	{
+		return (String) attributes.get(name);
+	}
+
+	public void setAttributeValue(String name, String value)
+	{
+		attributes.put(name, value);
+	}
+
+	public String[] getAttributes()
+	{
+		Collection c = attributes.values();
+		String[] result = new String[c.size()];
+		attributes.keySet().toArray(result);
+		return result;
+	}
+
+	public String getId()
+	{
+		return id;
+	}
+
+	public void setId(String id)
+	{
+		this.id = id;
+	}
+
+	public ICatalog getOwnerCatalog()
+	{
+		return ownerCatalog;
+	}
+
+	public void setOwnerCatalog(ICatalog catalog)
+	{
+		this.ownerCatalog = catalog;
+	}
+
+	protected static String makeAbsolute(String baseLocation, String location)
+	{
+		URL local = null;
+		location = location.replace('\\', '/');
+		try
+		{
+			URL baseURL = new URL(baseLocation);
+			local = new URL(baseURL, location);
+		} catch (MalformedURLException e)
+		{
+		}
+
+		if (local != null)
+		{
+			return local.toString();
+		} else
+		{
+			return location;
+		}
+	}
+
+	public String getAbsolutePath(String path)
+	{
+		try
+		{
+			URI uri = new URI(path);
+			if (uri.isAbsolute())
+			{
+				return path;
+			}
+		} catch (URISyntaxException e)
+		{
+		}
+
+		if (this.base != null && !this.base.equals("")) //$NON-NLS-1$
+		{
+			return makeAbsolute(base, path);		
+		}
+		
+		String result = path;
+		Catalog catalog = (Catalog) getOwnerCatalog();
+		if (catalog != null)
+		{
+			String base = catalog.getBase();
+			if (base == null || base.equals("")) //$NON-NLS-1$
+			{
+				base = catalog.getLocation();
+			}
+			result = makeAbsolute(base, path);
+		}
+		return result;
+	}
+	
+	  /*
+	   * Since we don't have events notifications for entry properties, clone()
+	   * could allow to copy and edit entry and then replace it in catalog. Entry
+	   * replacement will signal ICatalogEvent @return
+	   */
+	  public Object clone()
+	  {
+		ICatalogElement element = ownerCatalog.createCatalogElement(type);
+	    String[] attributes = getAttributes();   
+	    for (int i = 0; i < attributes.length; i++)
+	    {
+	      String attrName = attributes[i];
+	      String attrValue = getAttributeValue(attrName);
+	      element.setAttributeValue(attrName, attrValue);
+	    }
+		element.setOwnerCatalog(ownerCatalog);
+		element.setId(id);
+		element.setBase(base);
+	    return element;
+	  }
+
+	
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/CatalogEntry.java b/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/CatalogEntry.java
new file mode 100644
index 0000000..550a8e4
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/CatalogEntry.java
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.catalog;
+
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalogElement;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalogEntry;
+
+public class CatalogEntry extends CatalogElement implements ICatalogEntry, Cloneable
+{
+  int entryType = ICatalogEntry.ENTRY_TYPE_PUBLIC;
+  String key;
+  String uri;
+
+  protected CatalogEntry(int anEntryType)
+  {
+    super(ICatalogElement.TYPE_ENTRY);
+    entryType = anEntryType;
+  }
+
+  protected CatalogEntry()
+  {
+    super(ICatalogElement.TYPE_ENTRY);
+  }
+
+  public void setEntryType(int value)
+  {
+    entryType = value;
+  }
+
+  public int getEntryType()
+  {
+    return entryType;
+  }
+
+  public void setKey(String value)
+  {
+    key = value;
+  }
+
+  public String getKey()
+  {
+    return key;
+  }
+
+  public String getURI()
+  {
+    return uri;
+  }
+  
+  public void setURI(String value)
+  {
+    uri = value;
+  }
+
+  public Object clone()
+  {
+    CatalogEntry entry = (CatalogEntry)super.clone();
+	entry.setEntryType(entryType);
+    entry.setKey(key);
+    entry.setURI(uri);
+    return entry;
+  }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/CatalogEvent.java b/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/CatalogEvent.java
new file mode 100644
index 0000000..8fba64d
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/CatalogEvent.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.catalog;
+
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalog;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalogElement;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalogEvent;
+
+
+public class CatalogEvent implements ICatalogEvent
+{
+  protected ICatalog catalog;
+  protected ICatalogElement catalogElement;
+  protected int eventType;
+
+  public CatalogEvent(Catalog catalog, ICatalogElement element, int eventType)
+  {
+    this.catalog = catalog;
+    this.catalogElement = element;
+    this.eventType = eventType;
+  }
+
+  public ICatalog getCatalog()
+  {
+    return catalog;
+  }
+
+  public ICatalogElement getCatalogElement()
+  {
+    return catalogElement;
+  }
+
+  public int getEventType()
+  {
+    return eventType;
+  }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/CatalogReader.java b/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/CatalogReader.java
new file mode 100644
index 0000000..d53a15b
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/CatalogReader.java
@@ -0,0 +1,321 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     Jesper Steen Moeller - Added XML Catalogs 1.1 support
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.catalog;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Stack;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.eclipse.wst.common.uriresolver.internal.URI;
+import org.eclipse.wst.common.uriresolver.internal.util.URIHelper;
+import org.eclipse.wst.xml.core.internal.Logger;
+import org.eclipse.wst.xml.core.internal.XMLCoreMessages;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalogElement;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalogEntry;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.IDelegateCatalog;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.IRewriteEntry;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ISuffixEntry;
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * 
+ * 
+ */
+public final class CatalogReader
+{
+  public static void read(Catalog xmlCatalog, InputStream input) throws IOException
+  {
+    try
+    {
+      SAXParserFactory factory = SAXParserFactory.newInstance();
+      factory.setNamespaceAware(true);
+      factory.setValidating(false);
+      factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);//$NON-NLS-1$
+      SAXParser parser = factory.newSAXParser();
+      parser.parse(new InputSource(input), new CatalogContentHandler(xmlCatalog));
+    }
+    catch (ParserConfigurationException e)
+    {
+      Logger.logException(e);
+    }
+    catch (SAXException e)
+    {
+      Logger.logException(e);
+    }
+  }
+  protected static class CatalogContentHandler extends DefaultHandler
+  {
+    protected Catalog catalog;
+    protected Stack baseURIStack = new Stack();
+
+    public CatalogContentHandler(Catalog xmlCatalog)
+    {
+      this.catalog = xmlCatalog;
+      String base = xmlCatalog.getBase();
+      if(base == null || base == "") {  //$NON-NLS-1$
+    	  base = xmlCatalog.getLocation();
+      }
+      baseURIStack.push(base);
+    }
+
+    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException
+    {
+      // set base attribute xml:base
+      String base = attributes.getValue(OASISCatalogConstants.ATTR_BASE); //$NON-NLS-1$
+      if (base != null && !base.equals("")) //$NON-NLS-1$
+      {
+          // since the xml:base attribute can be relative to the enclosing element's effective base, we're maintaining a
+          // stack of absolute URIs
+		  if (URI.createURI(base).isRelative())
+          {
+            base = URI.resolveRelativeURI(base, baseURIStack.peek().toString());
+          }
+
+          baseURIStack.push(URIHelper.ensureURIProtocolFormat(base));
+      } else {
+    	  baseURIStack.push(baseURIStack.peek());
+      }
+
+	  // processing for backward compatibility start
+	  if (localName.equals(CompatabilityConstants.TAG_USER_ENTRY))
+      {
+        String typeName = attributes.getValue("", CompatabilityConstants.ATT_TYPE); //$NON-NLS-1$
+        boolean isSystem = false;
+        if (typeName != null)
+        {
+        	isSystem = (typeName.compareToIgnoreCase("SYSTEM") == 0); //$NON-NLS-1$
+        }
+        ICatalogEntry catalogEntry = new CatalogEntry(isSystem ? ICatalogEntry.ENTRY_TYPE_SYSTEM : ICatalogEntry.ENTRY_TYPE_PUBLIC);
+        catalogEntry.setKey(attributes.getValue("", CompatabilityConstants.ATT_ID)); //$NON-NLS-1$
+        String entryUri = attributes.getValue("", CompatabilityConstants.ATT_URI); //$NON-NLS-1$
+        
+        // For relative URIs, try to resolve them using the corresponding base URI.
+        catalogEntry.setURI(resolveRelative(entryUri));
+
+        String webURL = attributes.getValue("", CompatabilityConstants.ATT_WEB_URL); //$NON-NLS-1$
+        if (webURL != null)
+        {
+        	catalogEntry.setAttributeValue(
+        			ICatalogEntry.ATTR_WEB_URL, webURL);
+        }
+		catalog.addCatalogElement(catalogEntry);
+		return;
+      }
+	  //  processing for backward compatibility end
+	  ICatalogElement catalogElement = null;
+
+      if (OASISCatalogConstants.TAG_PUBLIC.equals(localName))
+      {
+    	  // 6.5.3. The public Entry
+    	  catalogElement = createEntry(attributes, ICatalogEntry.ENTRY_TYPE_PUBLIC, OASISCatalogConstants.ATTR_PUBLIC_ID);
+      }
+      else if (OASISCatalogConstants.TAG_SYSTEM.equals(localName))
+      {
+    	  // 6.5.4. The system Element
+    	  catalogElement = createEntry(attributes, ICatalogEntry.ENTRY_TYPE_SYSTEM, OASISCatalogConstants.ATTR_SYSTEM_ID);
+      }
+      else if (OASISCatalogConstants.TAG_URI.equals(localName))
+      {
+    	  // 6.5.9. The uri Element
+    	  catalogElement = createEntry(attributes, ICatalogEntry.ENTRY_TYPE_URI, OASISCatalogConstants.ATTR_NAME);
+      }
+      else if (OASISCatalogConstants.TAG_REWRITE_SYSTEM.equals(localName))
+      {
+    	  // 6.5.5. The rewriteSystem Element
+    	  catalogElement = createRewrite(attributes, IRewriteEntry.REWRITE_TYPE_SYSTEM, OASISCatalogConstants.ATTR_SYSTEM_ID_START_STRING);
+      }
+      else if (OASISCatalogConstants.TAG_REWRITE_URI.equals(localName))
+      {
+    	  // 6.5.9. The uri Element
+    	  catalogElement = createRewrite(attributes, IRewriteEntry.REWRITE_TYPE_URI, OASISCatalogConstants.ATTR_URI_START_STRING);
+      }
+      else if (OASISCatalogConstants.TAG_DELEGATE_PUBLIC.equals(localName))
+      {
+    	  // 6.5.7. The delegatePublic Element
+    	  catalogElement = createDelegate(attributes, IDelegateCatalog.DELEGATE_TYPE_PUBLIC, OASISCatalogConstants.ATTR_PUBLIC_ID_START_STRING);
+      }
+      else if (OASISCatalogConstants.TAG_DELEGATE_SYSTEM.equals(localName))
+      {
+    	  // 6.5.8. The delegateSystem Element
+    	  catalogElement = createDelegate(attributes, IDelegateCatalog.DELEGATE_TYPE_SYSTEM, OASISCatalogConstants.ATTR_SYSTEM_ID_START_STRING);
+      }
+      else if (OASISCatalogConstants.TAG_DELEGATE_URI.equals(localName))
+      {
+    	  // 6.5.12. The delegateURI Element
+    	  catalogElement = createDelegate(attributes, IDelegateCatalog.DELEGATE_TYPE_URI, OASISCatalogConstants.ATTR_URI_START_STRING);
+      }
+      else if (OASISCatalogConstants.TAG_SYSTEM_SUFFIX.equals(localName))
+      {
+    	  // 6.5.6. The systemSuffix Element
+    	  catalogElement = createSuffix(attributes, ISuffixEntry.SUFFIX_TYPE_SYSTEM, OASISCatalogConstants.ATTR_SYSTEM_ID_SUFFFIX);
+      }
+      else if (OASISCatalogConstants.TAG_URI_SUFFIX.equals(localName))
+      {
+    	  // 6.5.11. The uriSuffix Element
+    	  catalogElement = createSuffix(attributes, ISuffixEntry.SUFFIX_TYPE_URI, OASISCatalogConstants.ATTR_URI_SUFFIX);
+      }
+      else if (OASISCatalogConstants.TAG_NEXT_CATALOG.equals(localName))
+      {
+        catalogElement = createNextCatalog(attributes);
+      }
+      
+      if (catalogElement == null)
+      {
+    	// do not set the extra information
+        return;
+      }
+
+	  String attrId = attributes.getValue("", OASISCatalogConstants.ATTR_ID);//$NON-NLS-1$
+	  if (attrId != null && ! "".equals(attrId)) catalogElement.setId(attrId);//$NON-NLS-1$
+      // process any other attributes
+      for (int j = 0; j < attributes.getLength(); j++)
+      {
+        String attrName = attributes.getLocalName(j);
+        if (!attrName.equals(OASISCatalogConstants.ATTR_URI) && !attrName.equals(OASISCatalogConstants.ATTR_NAME) && !attrName.equals(OASISCatalogConstants.ATTR_PUBLIC_ID)
+            && !attrName.equals(OASISCatalogConstants.ATTR_SYSTEM_ID) && !attrName.equals(OASISCatalogConstants.ATTR_CATALOG) && !attrName.equals(OASISCatalogConstants.ATTR_ID)
+            && !attrName.equals(OASISCatalogConstants.ATTR_BASE))
+        {
+          String attrValue = attributes.getValue(attrName);
+          if (attrValue != null && !attrValue.equals("")) //$NON-NLS-1$
+          {
+            catalogElement.setAttributeValue(attrName, attrValue);
+          }
+        }
+      }
+      catalog.addCatalogElement(catalogElement);
+
+    }
+
+	private ICatalogElement createNextCatalog(Attributes attributes) {
+		String location = attributes.getValue("", OASISCatalogConstants.ATTR_CATALOG);    //$NON-NLS-1$
+        NextCatalog delegate = new NextCatalog();
+        delegate.setBase((String)baseURIStack.peek());
+        delegate.setCatalogLocation(location);  
+		return delegate;
+	}
+
+    private ICatalogEntry createEntry(Attributes attributes, int entryType, String keyAttributeName) {
+    	String key = attributes.getValue("", keyAttributeName); //$NON-NLS-1$
+    	if (key == null || key.equals("")) //$NON-NLS-1$
+    	{
+    		Logger.log(Logger.ERROR, XMLCoreMessages.Catalog_entry_key_not_set);
+    		return null;
+    	}
+    	String entryURI = attributes.getValue("", OASISCatalogConstants.ATTR_URI); //$NON-NLS-1$
+    	if (entryURI == null || entryURI.equals("")) //$NON-NLS-1$
+    	{
+    		Logger.log(Logger.ERROR, XMLCoreMessages.Catalog_entry_uri_not_set);
+    		return null;
+    	}
+    	CatalogEntry entry = new CatalogEntry(entryType);
+    	entry.setKey(key);
+    	entry.setURI(resolveRelative(entryURI));
+    	return entry;
+    }
+
+    private IRewriteEntry createRewrite(Attributes attributes, int entryType, String prefixStringName) {
+    	String startString = attributes.getValue("", prefixStringName); //$NON-NLS-1$
+    	if (startString == null || startString.equals("")) //$NON-NLS-1$
+    	{
+    		Logger.log(Logger.ERROR, XMLCoreMessages.Catalog_rewrite_startString_not_set);
+    		return null;
+    	}
+    	String prefix = attributes.getValue("", OASISCatalogConstants.ATTR_REWRITE_PREFIX); //$NON-NLS-1$
+    	if (prefix == null || prefix.equals("")) //$NON-NLS-1$
+    	{
+    		Logger.log(Logger.ERROR, XMLCoreMessages.Catalog_rewrite_prefix_not_set);
+    		return null;
+    	}
+    	RewriteEntry entry = new RewriteEntry(entryType);
+    	entry.setStartString(startString);
+    	entry.setRewritePrefix(resolveRelative(prefix));
+    	return entry;
+    }
+
+    private IDelegateCatalog createDelegate(Attributes attributes, int entryType, String startStringAttrName) {
+    	String startString = attributes.getValue("", startStringAttrName); //$NON-NLS-1$
+    	if (startString == null || startString.equals("")) //$NON-NLS-1$
+    	{
+    		Logger.log(Logger.ERROR, XMLCoreMessages.Catalog_delegate_prefix_not_set);
+    		return null;
+    	}
+    	String catalogUri = attributes.getValue("", OASISCatalogConstants.ATTR_CATALOG); //$NON-NLS-1$
+    	if (catalogUri == null || catalogUri.equals("")) //$NON-NLS-1$
+    	{
+    		Logger.log(Logger.ERROR, XMLCoreMessages.Catalog_delegate_prefix_not_set);
+    		return null;
+    	}
+    	DelegateCatalog entry = new DelegateCatalog(entryType);
+    	entry.setStartString(startString);
+    	entry.setCatalogLocation(catalogUri);
+    	return entry;
+    }
+
+    private ISuffixEntry createSuffix(Attributes attributes, int entryType, String suffixAttrName) {
+    	String suffix = attributes.getValue("", suffixAttrName); //$NON-NLS-1$
+    	if (suffix == null || suffix.equals("")) //$NON-NLS-1$
+    	{
+    		Logger.log(Logger.ERROR, XMLCoreMessages.Catalog_suffix_string_not_set);
+    		return null;
+    	}
+    	String uri = attributes.getValue("", OASISCatalogConstants.ATTR_URI); //$NON-NLS-1$
+    	if (uri == null || uri.equals("")) //$NON-NLS-1$
+    	{
+    		Logger.log(Logger.ERROR, XMLCoreMessages.Catalog_suffix_uri_not_set);
+    		return null;
+    	}
+    	SuffixEntry entry = new SuffixEntry(entryType);
+    	entry.setSuffix(suffix);
+    	entry.setURI(resolveRelative(uri));
+    	return entry;
+    }
+
+	private String resolveRelative(String entryURI) 
+	{
+		if(URI.createURI(entryURI).isRelative()) 
+		{
+        	entryURI = URI.resolveRelativeURI(entryURI, baseURIStack.peek().toString());
+        }
+		return URIHelper.ensureURIProtocolFormat(entryURI);
+	}
+
+    public void endElement(String uri, String localName, String qName) throws SAXException
+    {
+      if (baseURIStack.size() > 0)
+      {
+        baseURIStack.pop();
+      }
+    }
+    
+  }  
+  
+  // for backward compatability
+  interface CompatabilityConstants{
+	  
+	  public static final String TAG_ID_XML_CATALOG_SETTINGS = "XMLCatalogSettings"; //$NON-NLS-1$
+	  public static final String TAG_ID_USER_ENTRIES = "UserEntries"; //$NON-NLS-1$
+	  public static final String TAG_USER_ENTRY = "UserEntry"; //$NON-NLS-1$
+	  public static final String ATT_TYPE = "TYPE"; //$NON-NLS-1$
+	  public static final String ATT_ID = "ID"; //$NON-NLS-1$
+	  public static final String ATT_URI = "URI"; //$NON-NLS-1$
+	  public static final String ATT_WEB_URL = "WEB_URL"; //$NON-NLS-1$
+  }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/CatalogSet.java b/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/CatalogSet.java
new file mode 100644
index 0000000..acfbd16
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/CatalogSet.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.catalog;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.wst.xml.core.internal.Logger;
+
+
+
+public class CatalogSet {
+	protected Map uriResourceMap = new HashMap();
+	protected Map catalogPersistenceLocations = new HashMap();
+	public CatalogSet() {
+		super();
+	}
+
+	/**
+	 * Find a Catalog with the given ID.  If one is not found, create one at the given URI.
+	 * 
+	 * @param id
+	 * @param uri - the URI, the parent of this file path must already exist
+	 * @return
+	 */
+	public Catalog lookupOrCreateCatalog(String id, String uri) {
+		Catalog catalog = getCatalog(id, uri);
+		if (catalog == null) {
+			catalog = new Catalog(this, id, uri);
+			try {
+				catalog.load();
+				uriResourceMap.put(uri, catalog);
+			}
+			catch (Exception e) {
+				// we catch and log all exceptions, to disallow
+				// one bad extension interfering with others
+				Logger.logException("error loading catalog: " + id + " " + uri, e); //$NON-NLS-1$ //$NON-NLS-2$
+			}
+		}
+		return catalog;
+	}
+
+	private Catalog getCatalog(String id, String uri) {
+		return (Catalog) uriResourceMap.get(uri);
+	}
+
+	public void putCatalogPersistenceLocation(String logicalURI, String actualURI) {
+		catalogPersistenceLocations.put(logicalURI, actualURI);
+	}
+
+	// Never used?
+	public String getCatalogPersistenceLocation(String id) {
+		return (String) catalogPersistenceLocations.get(id);
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/CatalogWriter.java b/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/CatalogWriter.java
new file mode 100644
index 0000000..30d5169
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/CatalogWriter.java
@@ -0,0 +1,367 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.catalog;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import org.eclipse.wst.xml.core.internal.Logger;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalog;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalogElement;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalogEntry;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.IDelegateCatalog;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.INextCatalog;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.IRewriteEntry;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ISuffixEntry;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/**
+ * Write OASIS XML Catalog format
+ * 
+ */
+public final class CatalogWriter
+{
+  private Document doc;
+
+  public void write(ICatalog xmlCatalog, String uri) throws FileNotFoundException, IOException
+  {
+	OutputStream outputStream = null;
+	try {
+      visitCatalog(xmlCatalog);
+      outputStream = getOutputStream(uri);
+      serialize(outputStream);
+	}
+	finally {
+	  if(outputStream != null) {
+		outputStream.close();
+	  }
+	}
+  }
+
+  public void write(ICatalog catalog, OutputStream os) throws FileNotFoundException, IOException
+  {
+    if (catalog != null)
+    {
+      visitCatalog(catalog);
+      serialize(os);
+    }
+  }
+
+  private void visitCatalog(ICatalog xmlCatalog)
+  {
+    try
+    {
+      doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
+    }
+    catch (ParserConfigurationException e)
+    {
+      Logger.logException(e);
+    }
+    if (doc == null)
+      return;
+    Element catalogElement = doc.createElementNS(OASISCatalogConstants.namespaceName, OASISCatalogConstants.TAG_CATALOG);
+    doc.appendChild(catalogElement);
+    processCatalogEntries(xmlCatalog, catalogElement);
+    processNextCatalogs(xmlCatalog, catalogElement);
+    processDelegateCatalogs(xmlCatalog, catalogElement);
+    processSuffixEntries(xmlCatalog, catalogElement);
+    processRewriteEntries(xmlCatalog, catalogElement);
+  }
+
+  private void processRewriteEntries(ICatalog catalog, Element parent)
+  {
+    IRewriteEntry[] catalogEntries = catalog.getRewriteEntries();
+    
+    for (int i = 0; i < catalogEntries.length; i++)
+    {
+      IRewriteEntry entry = catalogEntries[i];
+      String startString = entry.getStartString();
+      String prefix = entry.getRewritePrefix();
+	  Element childElement = null;
+	 
+     switch (entry.getEntryType())
+      {
+        case IRewriteEntry.REWRITE_TYPE_SYSTEM :
+          childElement = parent.getOwnerDocument().createElement(OASISCatalogConstants.TAG_REWRITE_SYSTEM);
+          if (childElement != null)
+          {
+            childElement.setAttribute(OASISCatalogConstants.ATTR_SYSTEM_ID_START_STRING, startString);
+            childElement.setAttribute(OASISCatalogConstants.ATTR_REWRITE_PREFIX, prefix);
+          }
+          break;
+        case IRewriteEntry.REWRITE_TYPE_URI:
+          childElement = parent.getOwnerDocument().createElement(OASISCatalogConstants.TAG_REWRITE_URI);
+          if (childElement != null)
+          {
+	            childElement.setAttribute(OASISCatalogConstants.ATTR_URI_START_STRING, startString);
+	            childElement.setAttribute(OASISCatalogConstants.ATTR_REWRITE_PREFIX, prefix);
+          }
+          break;
+        default :
+          break;
+      }
+      if (childElement != null)
+      {
+        setAttributes(entry, childElement);
+        parent.appendChild(childElement);
+      }
+    }
+  }
+
+  private void processSuffixEntries(ICatalog catalog, Element parent)
+  {
+    ISuffixEntry[] suffixEntries = catalog.getSuffixEntries();
+    
+    for (int i = 0; i < suffixEntries.length; i++)
+    {
+      ISuffixEntry entry = suffixEntries[i];
+      String suffixString = entry.getSuffix();
+      String uri = entry.getURI();
+	  Element childElement = null;
+	 
+     switch (entry.getEntryType())
+      {
+        case ISuffixEntry.SUFFIX_TYPE_SYSTEM :
+          childElement = parent.getOwnerDocument().createElement(OASISCatalogConstants.TAG_SYSTEM_SUFFIX);
+          if (childElement != null)
+          {
+            childElement.setAttribute(OASISCatalogConstants.ATTR_SYSTEM_ID_SUFFFIX, suffixString);
+            childElement.setAttribute(OASISCatalogConstants.ATTR_URI, uri);
+          }
+          break;
+        case ISuffixEntry.SUFFIX_TYPE_URI:
+          childElement = parent.getOwnerDocument().createElement(OASISCatalogConstants.TAG_URI_SUFFIX);
+          if (childElement != null)
+          {
+	            childElement.setAttribute(OASISCatalogConstants.ATTR_URI_SUFFIX, suffixString);
+	            childElement.setAttribute(OASISCatalogConstants.ATTR_URI, uri);
+          }
+          break;
+        default :
+          break;
+      }
+      if (childElement != null)
+      {
+        setAttributes(entry, childElement);
+        parent.appendChild(childElement);
+      }
+    }
+  }
+
+  private void processDelegateCatalogs(ICatalog catalog, Element parent)
+  {
+    IDelegateCatalog[] delegateCatalogs = catalog.getDelegateCatalogs();
+
+    for (int i = 0; i < delegateCatalogs.length; i++)
+    {
+      IDelegateCatalog entry = delegateCatalogs[i];
+      String prefixString = entry.getStartString();
+      String catalogLocation = entry.getCatalogLocation();
+      Element childElement = null;
+
+      switch (entry.getEntryType())
+      {
+      case IDelegateCatalog.DELEGATE_TYPE_PUBLIC:
+        childElement = parent.getOwnerDocument().createElement(OASISCatalogConstants.TAG_DELEGATE_PUBLIC);
+        if (childElement != null)
+        {
+          childElement.setAttribute(OASISCatalogConstants.ATTR_PUBLIC_ID_START_STRING, prefixString);
+          childElement.setAttribute(OASISCatalogConstants.ATTR_CATALOG, catalogLocation);
+        }
+        break;
+      case IDelegateCatalog.DELEGATE_TYPE_SYSTEM:
+        childElement = parent.getOwnerDocument().createElement(OASISCatalogConstants.TAG_DELEGATE_SYSTEM);
+        if (childElement != null)
+        {
+          childElement.setAttribute(OASISCatalogConstants.ATTR_SYSTEM_ID_START_STRING, prefixString);
+          childElement.setAttribute(OASISCatalogConstants.ATTR_CATALOG, catalogLocation);
+        }
+        break;
+      case IDelegateCatalog.DELEGATE_TYPE_URI:
+        childElement = parent.getOwnerDocument().createElement(OASISCatalogConstants.TAG_DELEGATE_URI);
+        if (childElement != null)
+        {
+          childElement.setAttribute(OASISCatalogConstants.ATTR_URI_START_STRING, prefixString);
+          childElement.setAttribute(OASISCatalogConstants.ATTR_CATALOG, catalogLocation);
+        }
+        break;
+      default :
+        break;
+      }
+      if (childElement != null)
+      {
+        setAttributes(entry, childElement);
+        parent.appendChild(childElement);
+      }
+    }
+  }
+
+  private void processCatalogEntries(ICatalog catalog, Element parent)
+  {
+    ICatalogEntry[] catalogEntries = catalog.getCatalogEntries();
+  
+    for (int i = 0; i < catalogEntries.length; i++)
+    {
+      ICatalogEntry entry = catalogEntries[i];
+      String key = entry.getKey();
+      String uri = entry.getURI();
+      Element childElement = null;
+	 
+      switch (entry.getEntryType())
+      {
+        case ICatalogEntry.ENTRY_TYPE_PUBLIC :
+          childElement = parent.getOwnerDocument().createElement(OASISCatalogConstants.TAG_PUBLIC);
+          if (childElement != null)
+          {
+            childElement.setAttribute(OASISCatalogConstants.ATTR_PUBLIC_ID, key);
+            childElement.setAttribute(OASISCatalogConstants.ATTR_URI, uri);
+          }
+          break;
+        case ICatalogEntry.ENTRY_TYPE_SYSTEM :
+          childElement = parent.getOwnerDocument().createElement(OASISCatalogConstants.TAG_SYSTEM);
+          if (childElement != null)
+          {
+            childElement.setAttribute(OASISCatalogConstants.ATTR_SYSTEM_ID, key);
+            childElement.setAttribute(OASISCatalogConstants.ATTR_URI, uri);
+          }
+          break;
+        case ICatalogEntry.ENTRY_TYPE_URI :
+          childElement = parent.getOwnerDocument().createElement(OASISCatalogConstants.TAG_URI);
+          if (childElement != null)
+          {
+            childElement.setAttribute(OASISCatalogConstants.ATTR_NAME, key);
+            childElement.setAttribute(OASISCatalogConstants.ATTR_URI, uri);
+          }
+          break;
+        default :
+          break;
+      }
+      if (childElement != null)
+      {
+    	  setAttributes(entry, childElement);
+        parent.appendChild(childElement);
+      }
+    }
+  }
+
+  private void setAttributes(ICatalogElement entry, Element childElement)
+  {
+    String[] attributes = entry.getAttributes();   
+    for (int j = 0; j < attributes.length; j++)
+    {
+      String attrName = attributes[j];
+      if (attrName != null && !attrName.equals("")) //$NON-NLS-1$
+      {
+        String attrValue = entry.getAttributeValue(attrName);
+        if (childElement != null && attrValue != null)
+        {
+          childElement.setAttribute(attrName, attrValue);
+        }
+      }
+    }
+    String id = entry.getId();
+    if (id != null)
+    {
+      childElement.setAttribute(OASISCatalogConstants.ATTR_ID, id);
+    }
+  }
+
+  private void processNextCatalogs(ICatalog catalog, Element parent)
+  {
+    // handle catalog entries
+    INextCatalog[] nextCatalogs = catalog.getNextCatalogs();
+    Element childElement = null;
+   //dw String attrValue = null;
+    for (int i = 0; i < nextCatalogs.length; i++)
+    {
+      INextCatalog delegate = nextCatalogs[i];
+      childElement = parent.getOwnerDocument().createElement(OASISCatalogConstants.TAG_NEXT_CATALOG);
+      if (childElement != null)
+      {
+        parent.appendChild(childElement);
+        String location = delegate.getCatalogLocation();
+        if (location != null)
+        {
+          childElement.setAttribute(OASISCatalogConstants.ATTR_CATALOG, location);
+        }
+        setAttributes(delegate, childElement);
+      }
+    }
+  }
+
+  private void serialize(OutputStream outputStream) throws FileNotFoundException, IOException
+  {
+    if (doc == null)
+      return;
+    try
+    {
+      TransformerFactory transformerFactory = TransformerFactory.newInstance();
+      Transformer transformer = transformerFactory.newTransformer();
+      transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
+      transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$
+      // Unless a width is set, there will be only line breaks but no
+      // indentation.
+      // The IBM JDK and the Sun JDK don't agree on the property name,
+      // so we set them both.
+      //
+      transformer.setOutputProperty("{http://xml.apache.org/xalan}indent-amount", "2"); //$NON-NLS-1$ //$NON-NLS-2$
+      transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); //$NON-NLS-1$ //$NON-NLS-2$
+      String encoding = "UTF-8"; // TBD //$NON-NLS-1$
+      if (encoding != null)
+      {
+        transformer.setOutputProperty(OutputKeys.ENCODING, encoding);
+      }
+      transformer.transform(new DOMSource(doc), new StreamResult(outputStream));
+    }
+    catch (TransformerException e)
+    {
+      Logger.logException(e);
+    }
+  }
+
+  private OutputStream getOutputStream(String uri) throws FileNotFoundException, IOException
+  {
+    String filePath = removeProtocol(uri);
+    File file = new File(filePath);
+    OutputStream stream = new FileOutputStream(file);
+    return stream;
+  }
+  
+  protected static String removeProtocol(String uri)
+  {
+    String result = uri;  
+    String protocol_pattern = ":"; //$NON-NLS-1$
+    if (uri != null)
+    {
+      int index = uri.indexOf(protocol_pattern);
+      if (index > 2)
+      {
+        result = result.substring(index + protocol_pattern.length());                 
+      }
+    }
+    return result;
+  }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/DelegateCatalog.java b/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/DelegateCatalog.java
new file mode 100644
index 0000000..57e729b
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/DelegateCatalog.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Jesper Steen Moeller
+ * 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:
+ *     Jesper Steen Moeller - Added XML Catalogs 1.1 support
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.catalog;
+
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalog;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalogElement;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.IDelegateCatalog;
+
+
+
+public class DelegateCatalog extends TypedCatalogElement implements IDelegateCatalog
+{
+  private String location;
+  private ICatalog referencedCatalog;
+  private String startString; 
+
+  public String getStartString() 
+  {
+    return startString;
+  }
+
+  public void setStartString(String startString) 
+  {
+    this.startString = startString;
+  }
+
+  public DelegateCatalog(int type)
+  {
+    super(ICatalogElement.TYPE_DELEGATE, type);
+  }
+
+  public String getCatalogLocation()
+  {
+    return location;
+  }
+
+  public ICatalog getReferencedCatalog()
+  {
+    if (referencedCatalog == null)
+    {
+      referencedCatalog = ((Catalog)ownerCatalog).getCatalogSet().lookupOrCreateCatalog(getId(), getAbsolutePath(location));
+    }
+    return referencedCatalog;
+  }
+
+  public void setCatalogLocation(String uri)
+  {
+    location = uri;
+    referencedCatalog = null;
+  }
+
+  public Object clone()
+  {
+    DelegateCatalog nextCatalog = (DelegateCatalog)super.clone();
+    nextCatalog.setCatalogLocation(location);
+    nextCatalog.setStartString(startString);
+    return nextCatalog;
+  }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/NextCatalog.java b/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/NextCatalog.java
new file mode 100644
index 0000000..16f755a
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/NextCatalog.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     Raj Mandayam, IBM
+ *           136400 NextCatalog.getReferencedCatalog() takes a lot of time computing constant information
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.catalog;
+
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalog;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalogElement;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.INextCatalog;
+
+
+
+public class NextCatalog extends CatalogElement implements INextCatalog
+{
+  private String location;
+  private ICatalog referencedCatalog;
+
+  public NextCatalog()
+  {
+    super(ICatalogElement.TYPE_NEXT_CATALOG);
+  }
+    
+  public String getCatalogLocation()
+  {
+    return location;
+  }
+
+  public ICatalog getReferencedCatalog()
+  {
+    if (referencedCatalog == null)
+    {
+      referencedCatalog = ((Catalog)ownerCatalog).getCatalogSet().lookupOrCreateCatalog(getId(), getAbsolutePath(location));
+    }
+    return referencedCatalog;
+  }
+
+  public void setCatalogLocation(String uri)
+  {
+    location = uri;
+    referencedCatalog = null;
+  }
+  
+  public Object clone()
+  {
+	NextCatalog nextCatalog = (NextCatalog)super.clone();
+	nextCatalog.setCatalogLocation(location);
+    return nextCatalog;
+  }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/OASISCatalogConstants.java b/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/OASISCatalogConstants.java
new file mode 100644
index 0000000..d716a62
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/OASISCatalogConstants.java
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2009 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     Jesper Steen Moeller - Added XML Catalogs 1.1 support
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.catalog;
+
+public interface OASISCatalogConstants
+{
+  String namespaceName = "urn:oasis:names:tc:entity:xmlns:xml:catalog"; //$NON-NLS-1$
+  /** Types of the catalog entries */
+  /** The CATALOG element name. */
+  String TAG_CATALOG = "catalog"; //$NON-NLS-1$
+  /** The GROUP catalog entry. */
+  String TAG_GROUP = "group"; //$NON-NLS-1$
+  /** The PUBLIC catalog entry. */
+  String TAG_PUBLIC = "public"; //$NON-NLS-1$
+  /** The SYSTEM catalog etnry. */
+  String TAG_SYSTEM = "system"; //$NON-NLS-1$
+  /** The URI catalog entry. */
+  String TAG_URI = "uri"; //$NON-NLS-1$
+  /** The REWRITE_SYSTEM catalog entry. */
+  String TAG_REWRITE_SYSTEM = "rewriteSystem"; //$NON-NLS-1$
+  /** The REWRITE_URI catalog entry. */
+  String TAG_REWRITE_URI = "rewriteURI"; //$NON-NLS-1$
+  /** The systemSuffix catalog entry. */
+  String TAG_SYSTEM_SUFFIX = "systemSuffix"; //$NON-NLS-1$
+  /** The uriSuffix catalog entry. */
+  String TAG_URI_SUFFIX = "uriSuffix"; //$NON-NLS-1$
+  /** The DELEGATE_PUBLIC catalog entry. */
+  String TAG_DELEGATE_PUBLIC = "delegatePublic"; //$NON-NLS-1$
+  /** The DELEGATE_SYSTEM catalog entry. */
+  String TAG_DELEGATE_SYSTEM = "delegateSystem"; //$NON-NLS-1$
+  /** The DELEGATE_URI catalog entry. */
+  String TAG_DELEGATE_URI = "delegateURI"; //$NON-NLS-1$
+  /** The NEXT_CATALOG catalog entry. */
+  String TAG_NEXT_CATALOG = "nextCatalog"; //$NON-NLS-1$
+  /** Attributes */
+  /** Attribute id used in all catalog entries */
+  String ATTR_ID = "id"; //$NON-NLS-1$
+  /** Attribute id base in all catalog entries */
+  String ATTR_BASE = "xml:base"; //$NON-NLS-1$
+  /** Attribute id prefer in catalog entries: CATALOG, GROUP */
+  String ATTR_PREFERE = "prefer"; //$NON-NLS-1$
+  /** Attribute used in catalog entries of type: PUBLIC */
+  String ATTR_PUBLIC_ID = "publicId"; //$NON-NLS-1$
+  /**
+   * Attribute used in catalog entries of type: SYSTEM
+   */
+  String ATTR_SYSTEM_ID = "systemId"; //$NON-NLS-1$
+  /**
+   * Attribute used in catalog entries of type: SYSTEM_SUFFIX
+   */
+  String ATTR_SYSTEM_ID_SUFFFIX = "systemIdSuffix"; //$NON-NLS-1$
+  /**
+   * Attribute used in catalog entries of type: URI
+   */
+  String ATTR_NAME = "name"; //$NON-NLS-1$
+  /**
+   * Attribute used in catalog entries of type: PUBLIC, URI
+   */
+  String ATTR_URI = "uri"; //$NON-NLS-1$
+  /**
+   * Attribute used in catalog entries of type: URI_SUFFIX
+   */
+  String ATTR_URI_SUFFIX = "uriSuffix"; //$NON-NLS-1$
+  /**
+   * Attribute used in catalog entries of type: REWRITE_SYSTEM, DELEGATE_SYSTEM
+   */
+  String ATTR_SYSTEM_ID_START_STRING = "systemIdStartString"; //$NON-NLS-1$
+  /**
+   * Attribute used in catalog entries of type: REWRITE_SYSTEM, REWRITE_URI
+   */
+  String ATTR_REWRITE_PREFIX = "rewritePrefix"; //$NON-NLS-1$
+  /**
+   * Attribute used in catalog entries of type: DELEGATE_PUBLIC
+   */
+  String ATTR_PUBLIC_ID_START_STRING = "publicIdStartString"; //$NON-NLS-1$
+  /**
+   * Attribute used in catalog entries of type: DELEGATE_PUBLIC,
+   * DELEGATE_SYSTEM, DELEGATE_URI, NEXT_CATALOG
+   */
+  String ATTR_CATALOG = "catalog"; //$NON-NLS-1$
+  /**
+   * Attribute used in catalog entries of type: REWRITE_URI, DELEGATE_URI
+   */
+  String ATTR_URI_START_STRING = "uriStartString"; //$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/RewriteEntry.java b/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/RewriteEntry.java
new file mode 100644
index 0000000..5d9590e
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/RewriteEntry.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Jesper Steen Moeller
+ * 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:
+ *     Jesper Steen Moeller - Added XML Catalogs 1.1 support
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.catalog;
+
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalogElement;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.IRewriteEntry;
+
+public class RewriteEntry extends TypedCatalogElement implements IRewriteEntry, Cloneable 
+{
+	String startString;
+	String rewritePrefix;
+
+	protected RewriteEntry(int anEntryType) 
+	{
+		super(ICatalogElement.TYPE_REWRITE, anEntryType);
+	}
+
+	public String getStartString() 
+	{
+		return startString;
+	}
+
+	public void setStartString(String startString) 
+	{
+		this.startString = startString;
+	}
+
+	public String getRewritePrefix() 
+	{
+		return rewritePrefix;
+	}
+
+	public void setRewritePrefix(String rewritePrefix) 
+	{
+		this.rewritePrefix = rewritePrefix;
+	}
+
+	public Object clone() 
+	{
+		RewriteEntry entry = (RewriteEntry) super.clone();
+		entry.setRewritePrefix(rewritePrefix);
+		entry.setStartString(startString);
+		return entry;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/SuffixEntry.java b/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/SuffixEntry.java
new file mode 100644
index 0000000..f9daaa5
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/SuffixEntry.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Jesper Steen Moeller
+ * 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:
+ *     Jesper Steen Moeller - Added XML Catalogs 1.1 support
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.catalog;
+
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalogElement;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ISuffixEntry;
+
+public class SuffixEntry extends TypedCatalogElement implements ISuffixEntry, Cloneable
+{
+  String suffix;
+  String uri;
+
+  protected SuffixEntry(int anEntryType)
+  {
+    super(ICatalogElement.TYPE_SUFFIX, anEntryType);
+  }
+
+  public void setSuffix(String value)
+  {
+    suffix = value;
+  }
+
+  public String getSuffix()
+  {
+    return suffix;
+  }
+
+  public String getURI()
+  {
+    return uri;
+  }
+  
+  public void setURI(String value)
+  {
+    uri = value;
+  }
+
+  public Object clone()
+  {
+    SuffixEntry entry = (SuffixEntry)super.clone();
+    entry.setSuffix(suffix);
+    entry.setURI(uri);
+    return entry;
+  }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/TypedCatalogElement.java b/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/TypedCatalogElement.java
new file mode 100644
index 0000000..8592d6b
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/TypedCatalogElement.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Jesper Steen Moeller
+ * 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:
+ *     Jesper Steen Moeller - Added XML Catalogs 1.1 support
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.catalog;
+
+
+public class TypedCatalogElement extends CatalogElement 
+{
+	protected int entryType;
+
+	public TypedCatalogElement(int type, int entryType) 
+	{
+		super(type);
+		this.entryType = entryType;
+	}
+
+	final public void setEntryType(int value) 
+	{
+	    entryType = value;
+	}
+
+	final public int getEntryType() 
+	{
+	    return entryType;
+	}
+	
+	public Object clone() 
+	{
+		TypedCatalogElement temp = (TypedCatalogElement)super.clone();
+		temp.setEntryType(this.getEntryType());
+		return temp;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/XMLCatalogURIResolverExtension.java b/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/XMLCatalogURIResolverExtension.java
new file mode 100644
index 0000000..0b4af07
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/XMLCatalogURIResolverExtension.java
@@ -0,0 +1,102 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.catalog;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.wst.common.uriresolver.internal.provisional.URIResolverExtension;
+import org.eclipse.wst.xml.core.internal.Logger;
+import org.eclipse.wst.xml.core.internal.XMLCoreMessages;
+import org.eclipse.wst.xml.core.internal.XMLCorePlugin;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalog;
+
+/**
+ * This class is used to inject the XMLCatalog resolution behaviour into the
+ * Common Extensible URI Resolver. This class is referenced in the XML Catalog
+ * plugin's plugin.xml file.
+ */
+public class XMLCatalogURIResolverExtension implements URIResolverExtension
+{
+  public String resolve(IFile file, String baseLocation, String publicId, String systemId)
+  {
+    // if we have catalog in a project we may add it
+    // to the catalog manager first
+    ICatalog catalog = XMLCorePlugin.getDefault().getDefaultXMLCatalog();
+    if (catalog == null)
+    {
+      Logger.log(Logger.ERROR_DEBUG, XMLCoreMessages.Catalog_resolution_null_catalog);
+      return null;
+    }
+    String resolved = null;
+    if (systemId != null)
+    {
+      try
+      {
+        resolved = catalog.resolveSystem(systemId);
+        if (resolved == null)
+        {
+          resolved = catalog.resolveURI(systemId);
+        }
+      }
+      catch (MalformedURLException me)
+      {
+        Logger.log(Logger.ERROR_DEBUG, XMLCoreMessages.Catalog_resolution_malformed_url);
+        resolved = null;
+      }
+      catch (IOException ie)
+      {
+        Logger.log(Logger.ERROR_DEBUG, XMLCoreMessages.Catalog_resolution_io_exception);
+        resolved = null;
+      }
+    }
+    if (resolved == null)
+    {
+      if (publicId != null)
+      {
+        // CS : this is a temporary workaround for bug 96772
+        //
+        // For schemas we always use locations where available and only use
+        // namespace when no location is specified.  For XML entities (such as DOCTYPE) 
+        // default always utilize the public catalog entry.
+        //
+        // This lame test below roughly discriminate between schema and XML entities.
+        // TODO (bug 103243) remove this lame test once we move to the new URIResolver API
+        // since the new API is explicit about namespace and publicId
+        // 
+        if (!(systemId != null && systemId.endsWith(".xsd"))) //$NON-NLS-1$
+        {
+          try
+          {
+            resolved = catalog.resolvePublic(publicId, systemId);
+            if (resolved == null)
+            {
+              resolved = catalog.resolveURI(publicId);
+            }
+          }
+          catch (MalformedURLException me)
+          {
+            Logger.log(Logger.ERROR_DEBUG, XMLCoreMessages.Catalog_resolution_malformed_url);
+            resolved = null;
+          }
+          catch (IOException ie)
+          {
+            Logger.log(Logger.ERROR_DEBUG, XMLCoreMessages.Catalog_resolution_io_exception);
+            resolved = null;
+          }
+        }
+      }
+    }
+    return resolved;
+  }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/provisional/ICatalog.java b/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/provisional/ICatalog.java
new file mode 100644
index 0000000..6796b74
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/provisional/ICatalog.java
@@ -0,0 +1,255 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2009 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     Jesper Steen Moeller - Added XML Catalogs 1.1 support
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.catalog.provisional;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+
+
+
+/**
+ * A representation of the model object '<em><b>Catalog</b></em>'.
+ * 
+ * <p>
+ * This interface is not intended to be implemented by clients.
+ * </p>
+ * 
+ */
+public interface ICatalog
+{
+    /**
+     * Returns catalog id string
+     * 
+     * @return catalog id string
+     */
+    String getId();
+    
+    /**
+     * Sets catalog id string
+     * 
+     */
+    void setId(String id);
+    
+    
+    void setLocation(String location);
+    String getLocation();
+    
+    /**
+     * Return the applicable or SYSTEM identifier.
+     * 
+     * <p>
+     * This method searches the Catalog and returns the system identifier
+     * specified for the given system or identifiers. If no appropriate
+     * or SYSTEM entry is found in the Catalog, null is returned.
+     * </p>
+     * 
+     * @param publicId
+     *            The identifier to locate in the catalog. Public
+     *            identifiers are normalized before comparison.
+     * @param systemId
+     *            The nominal system identifier for the entity in question (as
+     *            provided in the source document).
+     * 
+     * @throws MalformedURLException
+     *             The formal system identifier of a subordinate catalog cannot
+     *             be turned into a valid URL.
+     * @throws IOException
+     *             Error reading subordinate catalog file.
+     * 
+     * @return The system identifier to use. Note that the nominal system
+     *         identifier is not returned if a match is not found in the
+     *         catalog, instead null is returned to indicate that no match was
+     *         found.
+     */
+    String resolvePublic(String publicId, String systemId)
+            throws MalformedURLException, IOException;
+
+    /**
+     * Return the applicable SYSTEM system identifier.
+     * 
+     * <p>
+     * If a SYSTEM entry exists in the Catalog for the system ID specified,
+     * return the mapped value.
+     * </p>
+     * 
+     * <p>
+     * On Windows-based operating systems, the comparison between the system
+     * identifier provided and the SYSTEM entries in the Catalog is
+     * case-insensitive.
+     * </p>
+     * 
+     * @param systemId
+     *            The system ID to locate in the catalog.
+     * 
+     * @return The resolved system identifier.
+     * 
+     * @throws MalformedURLException
+     *             The formal system identifier of a subordinate catalog cannot
+     *             be turned into a valid URL.
+     * @throws IOException
+     *             Error reading subordinate catalog file.
+     */
+    String resolveSystem(String systemId) throws MalformedURLException,
+            IOException;
+
+    /**
+     * Return the applicable URI.
+     * 
+     * <p>
+     * If a URI entry exists in the Catalog for the URI specified, return the
+     * mapped value.
+     * </p>
+     * 
+     * <p>
+     * URI comparison is case sensitive.
+     * </p>
+     * 
+     * @param uri
+     *            The URI to locate in the catalog.
+     * 
+     * @return The resolved URI.
+     * 
+     * @throws MalformedURLException
+     *             The system identifier of a subordinate catalog cannot be
+     *             turned into a valid URL.
+     * @throws IOException
+     *             Error reading subordinate catalog file.
+     */
+    String resolveURI(String uri) throws MalformedURLException,
+            IOException;
+
+    /**
+     * Adds catalog element to the collection of the catalog elements.
+     * 
+     * @param element -
+     *            catalog element
+     */
+    void addCatalogElement(ICatalogElement element);
+
+    /**
+     * Removes catalog element from the collection of the catalog elements.
+     * 
+     * @param element -
+     *            catalog element
+     */
+    void removeCatalogElement(ICatalogElement element);
+
+    /**
+     * Returns an array of catalog elements of type ICatalogElement.TYPE_ENTRY
+     * 
+     * @return an array of catalog elements
+     */
+    ICatalogEntry[] getCatalogEntries();
+
+    /**
+     * Returns an array of catalog elements of type ICatalogElement.TYPE_REWRITE
+     * 
+     * @return an array of rewrite catalog elements
+     */
+    IRewriteEntry[] getRewriteEntries();
+
+    /**
+     * Returns an array of catalog elements of type ICatalogElement.TYPE_SUFFIX
+     * 
+     * @return an array of suffix entry elements
+     */
+    ISuffixEntry[] getSuffixEntries();
+
+    /**
+     * Returns an array of catalog elements of type ICatalogElement.TYPE_DELEGATE
+     * 
+     * @return an array of delegate catalog elements
+     */
+    IDelegateCatalog[] getDelegateCatalogs();
+
+    /**
+     * Returns an array of catalog elements of type
+     * ICatalogElement.TYPE_DELEGATE
+     * 
+     * @return an array of catalog elements
+     */
+    INextCatalog[] getNextCatalogs();
+
+    /**
+     * Returns new catalog element with the specified type. If the type is one
+     * of ELEMENT_TYPE, the result entry will have corresponding interface.
+     * 
+     * @return
+     */
+    ICatalogElement createCatalogElement(int type);
+
+    /**
+     * Removes all the elements from this catalog.
+     * 
+     */
+    void clear();
+    
+    //void load() throws IOException;
+    
+    void save() throws IOException;
+
+    /*
+     * Loads catalog from the specified location. Expecting OASIS XML Catalog
+     * format
+     * 
+     * @param location -
+     *            uri of the file where catalog will be saved
+
+     * @throws IOException -
+     *             problem loading file
+     * 
+     */
+    //void load(InputStream inputStream) throws IOException;
+
+    /*
+     * Saves catalog to the specified location in OASIS XML Catalog format
+     * 
+     * @param location -
+     *            uri of the file where catalog will be saved
+
+     * @throws IOException -
+     *             problem saving file
+     * 
+     */
+    //void save(OutputStream outputStream) throws IOException;
+
+    /**
+     * This method copies all catalog entries from source catalog to this one.
+     * 
+     * @param catalog -
+     *            source catalog
+     * @param includeNested -
+     *            a boolean flag indicating wether to include entries of the
+     *            same type from the nested catalogs
+     */
+    void addEntriesFromCatalog(ICatalog catalog);
+
+    /**
+     * Adds a listener of the catalog events
+     * 
+     * @param listener -
+     *            listener of the catalog events
+     * @see ICatalogEvent
+     */
+    void addListener(ICatalogListener listener);
+
+    /**
+     * Removes a listener of the catalog events
+     * 
+     * @param listener -
+     *            listener of the catalog events
+     * @see ICatalogEvent
+     */
+    void removeListener(ICatalogListener listener);      
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/provisional/ICatalogElement.java b/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/provisional/ICatalogElement.java
new file mode 100644
index 0000000..e011c9b
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/provisional/ICatalogElement.java
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2009 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     Jesper Steen Moeller - Added XML Catalogs 1.1 support
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.catalog.provisional;
+
+
+/**
+ * 
+ * <p>
+ * This interface is not intended to be implemented by clients.
+ * </p>
+ * 
+ */
+public interface ICatalogElement
+{
+    /** Types of the catalog entries */
+    /** The PUBLIC, URI or SYSTEM Catalog Entry. */
+    int TYPE_ENTRY = 1;
+
+    /** The NEXT_CATALOG Catalog Entry type. */
+    int TYPE_NEXT_CATALOG = 10;
+
+    /** Rewrite types (since XML Catalogs 1.1) */
+    int TYPE_REWRITE = 20;
+
+    /** Delegate types (sinceXML Catalogs 1.1) */
+    int TYPE_DELEGATE = 30;
+    
+    /** Suffix types (since XML Catalogs 1.1)  */
+    int TYPE_SUFFIX = 40;
+
+    /**
+     * Returns the value of the '<em><b>Type</b></em>' attribute.
+     * 
+     * @return the value of the '<em>Type</em>' attribute.
+     */
+    int getType();
+
+    /**
+     * Returns the value of the attribute with specified name.
+     * 
+     * @return the value of the attribute with specified name.
+     * @see #setAttributeValue(String)
+     */
+    String getAttributeValue(String name);
+
+    /**
+     * Sets the value of the named attribute.
+     * 
+     * @param name
+     *            the name of the attribute that will be set
+     * @param value
+     *            the new value of the named attribute.
+     * @see #getAttributeValue()
+     */
+    void setAttributeValue(String name, String value);
+
+    /**
+     * Returns an array of attribute names for any dynamic attributes that may exist
+     * 
+     * @return array of attribute names
+     * @see #getAttributeValue()
+     * @see #setAttributeValue(String)
+     */
+    String[] getAttributes();
+    
+    /**
+     * Returns element's id string
+     * 
+     * @return element's id string
+     */
+    public String getId();
+    
+    /**
+     * Sets element's id string
+     * 
+     */
+    public void setId(String id);
+    
+    public void setOwnerCatalog(ICatalog catalog);
+    
+    public ICatalog getOwnerCatalog();
+
+	void setBase(String base);
+
+	String getBase();
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/provisional/ICatalogEntry.java b/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/provisional/ICatalogEntry.java
new file mode 100644
index 0000000..372dbfe
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/provisional/ICatalogEntry.java
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.catalog.provisional;
+
+/**
+ * 
+ * <p>
+ * This interface is not intended to be implemented by clients.
+ * </p>
+ * 
+ */
+public interface ICatalogEntry extends ICatalogElement
+{
+    /** The PUBLIC Catalog Entry type. */
+    public static final int ENTRY_TYPE_PUBLIC = 2;
+
+    /** The SYSTEM Catalog Entry type. */
+    public static final int ENTRY_TYPE_SYSTEM = 3;
+
+    /** The URI Catalog Entry type. */
+    public static final int ENTRY_TYPE_URI = 4;
+
+    /** Attribute name for Web address of catalog entry */
+    public static final String ATTR_WEB_URL = "webURL"; //$NON-NLS-1$
+
+    /**
+     * 
+     * @param entryType
+     */
+    public void setEntryType(int entryType);
+
+    /**
+     * 
+     * @return
+     */
+    public int getEntryType();
+
+    /**
+     * 
+     * @param key
+     */
+    public void setKey(String key);
+
+    /**
+     * 
+     * @return
+     */
+    public String getKey();
+
+    /**
+     * 
+     * @return
+     */
+    public String getURI();
+
+    /**
+     * 
+     * @param uri
+     */
+    public void setURI(String uri);
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/provisional/ICatalogEvent.java b/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/provisional/ICatalogEvent.java
new file mode 100644
index 0000000..7825768
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/provisional/ICatalogEvent.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.catalog.provisional;
+
+
+
+/**
+ * 
+ * <p>
+ * This interface is not intended to be implemented by clients.
+ * </p>
+ * 
+ */
+public interface ICatalogEvent
+{
+    /** */
+    public static final int CHANGED = 0;
+
+    public static final int ELEMENT_ADDED = 1;
+
+    /** */
+    public static final int ELEMENT_REMOVED = 2;
+
+    /** */
+    public static final int ELEMENT_CHANGED = 3;
+
+    /**
+     * 
+     * @return
+     */
+    public int getEventType();
+
+    /**
+     * 
+     * @return
+     */
+    public ICatalog getCatalog();
+
+    /**
+     * 
+     * @return
+     */
+    public ICatalogElement getCatalogElement();
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/provisional/ICatalogListener.java b/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/provisional/ICatalogListener.java
new file mode 100644
index 0000000..7c3dc0d
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/provisional/ICatalogListener.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.catalog.provisional;
+
+import java.util.EventListener;
+
+
+/**
+ * The clients of the catalog that want to listen to catalog changes should
+ * implement this interface.
+ * 
+ * @see ICatalog, ICatalogEvent,
+ * 
+ */
+public interface ICatalogListener extends EventListener
+{
+    /**
+     * This method allows to react to catalog events
+     * 
+     * @param event -
+     *            an event that client should react to
+     */
+    public void catalogChanged(ICatalogEvent event);
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/provisional/IDelegateCatalog.java b/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/provisional/IDelegateCatalog.java
new file mode 100644
index 0000000..82040b0
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/provisional/IDelegateCatalog.java
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Jesper Steen Moeller
+ * 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:
+ *     Jesper Steen Moeller - Added XML Catalogs 1.1 support
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.catalog.provisional;
+
+/**
+ * 
+ * <p>
+ * This interface is not intended to be implemented by clients.
+ * </p>
+ * 
+ */
+public interface IDelegateCatalog extends ICatalogElement
+{
+    /** The SYSTEM Catalog Entry type. */
+    int DELEGATE_TYPE_PUBLIC = 31;
+
+    /** The SYSTEM Catalog Entry type. */
+    int DELEGATE_TYPE_SYSTEM = 32;
+
+    /** The URI Catalog Entry type. */
+    int DELEGATE_TYPE_URI = 33;
+
+    /**
+     * 
+     * @param entryType
+     */
+    void setEntryType(int entryType);
+
+    /**
+     * 
+     * @return
+     */
+    int getEntryType();
+
+    /**
+     * 
+     * @param key
+     */
+    void setStartString(String key);
+
+    /**
+     * 
+     * @return
+     */
+    String getStartString();
+    
+    /**
+     * Set location of the referenced catalog.
+     * 
+     * @param uri -
+     *            location uri of the referenced catalog
+     */
+    void setCatalogLocation(String uri);
+
+    /**
+     * Get location uri of the referenced catalog.
+     * 
+     * @return location uri of the referenced catalog
+     */
+    String getCatalogLocation();
+    
+    ICatalog getReferencedCatalog();
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/provisional/INextCatalog.java b/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/provisional/INextCatalog.java
new file mode 100644
index 0000000..47c939c
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/provisional/INextCatalog.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.catalog.provisional;
+
+
+
+/**
+ * 
+ * A representation of the nextCatalog OASIS XML catalog element. Object of the
+ * class that implements this interface would serve as a reference to the
+ * catalog object.
+ * 
+ * @see ICatalog, ICatalogElement
+ * 
+ * This interface currently is used only by the catalog itself. Need to find if
+ * there are any clients that need it.
+ * 
+ * <p>
+ * This interface is not intended to be implemented by clients.
+ * </p>
+ * 
+ */
+public interface INextCatalog extends ICatalogElement
+{
+    /**
+     * Set location of the referenced catalog.
+     * 
+     * @param uri -
+     *            location uri of the referenced catalog
+     */
+    public void setCatalogLocation(String uri);
+
+    /**
+     * Get location uri of the referenced catalog.
+     * 
+     * @return location uri of the referenced catalog
+     */
+    public String getCatalogLocation();
+    
+    public ICatalog getReferencedCatalog();
+
+   
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/provisional/IRewriteEntry.java b/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/provisional/IRewriteEntry.java
new file mode 100644
index 0000000..9d95592
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/provisional/IRewriteEntry.java
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Jesper Steen Moeller
+ * 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:
+ *     Jesper Steen Moeller - Added XML Catalogs 1.1 support
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.catalog.provisional;
+
+/**
+ * 
+ * <p>
+ * This interface is not intended to be implemented by clients.
+ * </p>
+ * 
+ */
+public interface IRewriteEntry extends ICatalogElement
+{
+    /** The rewriteSystem Catalog type. */
+    int REWRITE_TYPE_SYSTEM = 21;
+
+    /** The URI Catalog Entry type. */
+    int REWRITE_TYPE_URI = 22;
+
+    /**
+     * 
+     * @param entryType
+     */
+    void setEntryType(int entryType);
+
+    /**
+     * 
+     * @return
+     */
+    int getEntryType();
+
+    /**
+     * 
+     * @param key
+     */
+    void setStartString(String startString);
+
+    /**
+     * 
+     * @return
+     */
+    String getStartString();
+
+    /**
+     * 
+     * @return
+     */
+    String getRewritePrefix();
+
+    /**
+     * 
+     * @param uri
+     */
+    void setRewritePrefix(String uri);
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/provisional/ISuffixEntry.java b/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/provisional/ISuffixEntry.java
new file mode 100644
index 0000000..0004014
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-catalog/org/eclipse/wst/xml/core/internal/catalog/provisional/ISuffixEntry.java
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Jesper Steen Moeller
+ * 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:
+ *     Jesper Steen Moeller - Added XML Catalogs 1.1 support
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.catalog.provisional;
+
+/**
+ * 
+ * <p>
+ * This interface is not intended to be implemented by clients.
+ * </p>
+ * 
+ */
+public interface ISuffixEntry extends ICatalogElement
+{
+    /** The rewriteSystem Catalog type. */
+    int SUFFIX_TYPE_SYSTEM = 41;
+
+    /** The URI Catalog Entry type. */
+    int SUFFIX_TYPE_URI = 42;
+
+    /**
+     * 
+     * @param entryType
+     */
+    void setEntryType(int entryType);
+
+    /**
+     * 
+     * @return
+     */
+    int getEntryType();
+
+    /**
+     * 
+     * @param key
+     */
+    void setSuffix(String suffixString);
+
+    /**
+     * 
+     * @return
+     */
+    String getSuffix();
+
+    /**
+     * 
+     * @return
+     */
+    String getURI();
+
+    /**
+     * 
+     * @param uri
+     */
+    void setURI(String uri);
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/CMAnyElement.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/CMAnyElement.java
new file mode 100644
index 0000000..72a4702
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/CMAnyElement.java
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel;
+
+/**
+ * CMAnyElement interface
+ */
+public interface CMAnyElement extends CMContent {
+/**
+ * getNamespaceURI method
+ * @return java.lang.String
+ */
+String getNamespaceURI();
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/CMAttributeDeclaration.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/CMAttributeDeclaration.java
new file mode 100644
index 0000000..c5f718f
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/CMAttributeDeclaration.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel;
+
+import java.util.Enumeration;
+
+/**
+ * AttributeDeclaration interface
+ */
+public interface CMAttributeDeclaration extends CMNode {
+  public static final int OPTIONAL   = 1;
+  public static final int REQUIRED   = 2;
+  public static final int FIXED      = 3;
+  public static final int PROHIBITED = 4;
+/**
+ * getAttrName method
+ * @return java.lang.String
+ */
+String getAttrName();
+/**
+ * getAttrType method
+ * @return CMDataType
+ */
+CMDataType getAttrType();
+/**
+ * getDefaultValue method
+ * @return java.lang.String
+ * @deprecated -- to be replaced in future with additional CMDataType methods (currently found on CMDataTypeHelper)
+ */
+String getDefaultValue();
+/**
+ * getEnumAttr method
+ * @return java.util.Enumeration
+ * @deprecated -- to be replaced in future with additional CMDataType methods (currently found on CMDataTypeHelper)
+ */
+Enumeration getEnumAttr();
+/**
+ * getUsage method
+ * @return int
+ */
+int getUsage();
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/CMContent.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/CMContent.java
new file mode 100644
index 0000000..218b297
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/CMContent.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel;
+
+public interface CMContent extends CMNode
+{
+/**
+ * getMaxOccur method
+ * @return int
+ *
+ * If -1, it's UNBOUNDED.
+ */
+int getMaxOccur();
+/**
+ * getMinOccur method
+ * @return int
+ *
+ * If 0, it's OPTIONAL.
+ * If 1, it's REQUIRED.
+ */
+int getMinOccur();
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/CMDataType.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/CMDataType.java
new file mode 100644
index 0000000..b647228
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/CMDataType.java
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2009 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel;
+
+/**
+ * CMDataType
+ */
+public interface CMDataType extends CMNode {
+    
+  // todo... at some point we should remove these names to
+  // avoid exposing implementation details via the interfaces
+  //
+	static final String CDATA = "CDATA"; //$NON-NLS-1$
+	static final String ID = "ID"; //$NON-NLS-1$
+	static final String IDREF = "IDREF"; //$NON-NLS-1$
+	static final String IDREFS = "IDREFS"; //$NON-NLS-1$
+	static final String ENTITY = "ENTITY"; //$NON-NLS-1$
+	static final String ENTITIES = "ENTITIES"; //$NON-NLS-1$
+	static final String NOTATION = "NOTATION"; //$NON-NLS-1$
+	static final String NMTOKEN = "NMTOKEN"; //$NON-NLS-1$
+	static final String NMTOKENS = "NMTOKENS"; //$NON-NLS-1$
+	static final String NUMBER = "NUMBER"; //$NON-NLS-1$
+	static final String URI = "URI"; //$NON-NLS-1$
+	static final String ENUM = "ENUM"; //$NON-NLS-1$
+
+  static final int IMPLIED_VALUE_NONE             = 1;
+  static final int IMPLIED_VALUE_FIXED            = 2;
+  static final int IMPLIED_VALUE_DEFAULT          = 3;
+
+/**
+ * getTypeName method
+ * @return java.lang.String
+ */
+String getDataTypeName();    
+
+/**
+ * getImpliedValueKind method
+ * @return int
+ *
+ * Returns one of :
+ * IMPLIED_VALUE_NONE, IMPLIED_VALUE_FIXED, IMPLIED_VALUE_DEFAULT.
+ */      
+
+int getImpliedValueKind();  
+
+/**
+ * getTypeName method
+ * @return java.lang.String  
+ *
+ * Returns the implied value or null if none exists.
+ */
+String getImpliedValue();
+
+/**
+ * getTypeName method
+ * @return java.lang.String[]
+ *
+ */
+String[] getEnumeratedValues();
+
+/**
+ * getTypeName method
+ * @return java.lang.String
+ *
+ * This method returns a suitable default value that can be used when an instance of the data type is created.
+ * This returns null of a suitable default is not available.
+ */
+String generateInstanceValue();
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/CMDocument.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/CMDocument.java
new file mode 100644
index 0000000..58d7a43
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/CMDocument.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel;
+
+/**
+ * CMDocument interface
+ */
+public interface CMDocument extends CMNode {
+/**
+ * getElements method
+ * @return CMNamedNodeMap
+ *
+ * Returns CMNamedNodeMap of ElementDeclaration
+ */
+CMNamedNodeMap getElements();
+/**
+ * getEntities method
+ * @return CMNamedNodeMap
+ *
+ * Returns CMNamedNodeMap of EntityDeclaration
+ */
+CMNamedNodeMap getEntities();
+/**
+ * getNamespace method
+ * @return CMNamespace
+ */
+CMNamespace getNamespace();
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/CMDocumentation.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/CMDocumentation.java
new file mode 100644
index 0000000..88e4d8d
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/CMDocumentation.java
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel;
+
+/**
+ * CMDocumentation interface
+ */
+public interface CMDocumentation extends CMNode {        
+  public String getValue();
+  public String getLanguage();
+  public String getSource();
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/CMElementDeclaration.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/CMElementDeclaration.java
new file mode 100644
index 0000000..2c48077
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/CMElementDeclaration.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel;
+
+/**
+ * CMElementDeclaration interface
+ */
+public interface CMElementDeclaration extends CMContent {
+  
+	public static final int ANY = 0;
+	public static final int EMPTY = 1;
+	public static final int ELEMENT = 2;
+	public static final int MIXED = 3;
+	public static final int PCDATA = 4;
+	public static final int CDATA = 5; // todo... clarify this one
+/**
+ * getAttributes method
+ * @return CMNamedNodeMap
+ *
+ * Returns CMNamedNodeMap of AttributeDeclaration
+ */
+CMNamedNodeMap getAttributes();
+/**
+ * getCMContent method
+ * @return CMContent
+ *
+ * Returns the root node of this element's content model.
+ * This can be an CMElementDeclaration or a CMGroup
+ */
+CMContent getContent();
+/**
+ * getContentType method
+ * @return int
+ *
+ * Returns one of :
+ * ANY, EMPTY, ELEMENT, MIXED, PCDATA, CDATA.
+ */
+public int getContentType();
+/**
+ * getElementName method
+ * @return java.lang.String
+ */
+String getElementName();
+
+/**
+ * getDataType method
+ * @return java.lang.String
+ */
+CMDataType getDataType();
+
+/**
+ * getLocalElements method
+ * @return CMNamedNodeMap
+ *
+ * Returns a list of locally defined elements.
+ */
+CMNamedNodeMap getLocalElements();
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/CMEntityDeclaration.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/CMEntityDeclaration.java
new file mode 100644
index 0000000..99b5434
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/CMEntityDeclaration.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel;
+
+/**
+ * CMEntityDeclaration interface
+ */
+public interface CMEntityDeclaration extends CMNode {
+  
+/**
+ * getName method
+ * @return java.lang.String
+ */
+String getName();
+/**
+ * getValue method
+ * @return java.lang.String
+ */
+String getValue();
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/CMGroup.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/CMGroup.java
new file mode 100644
index 0000000..ce01ca7
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/CMGroup.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel;
+
+/**
+ * CMGroup interface
+ */
+public interface CMGroup extends CMContent {
+  
+	static final int ALL = 3;
+	static final int CHOICE = 2;
+	static final int SEQUENCE = 1;
+/**
+ * getChildNodes method
+ * @return CMNodeList
+ *
+ * Returns child CMNodeList, which includes ElementDefinition or CMElement.
+ */
+CMNodeList getChildNodes();
+
+/**
+ * getOperation method
+ * @return int
+ *
+ * Returns one of :
+ * ALONE (a), SEQUENCE (a,b), CHOICE (a|b), ALL (a&b).
+ */
+int getOperator();
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/CMNamedNodeMap.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/CMNamedNodeMap.java
new file mode 100644
index 0000000..2c79b81
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/CMNamedNodeMap.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel;
+import java.util.Iterator;
+/**
+ * NamedCMNodeMap
+ */
+public interface CMNamedNodeMap {
+/**
+ * getLength method
+ * @return int
+ */
+int getLength();
+/**
+ * getNamedItem method
+ * @return CMNode
+ * @param name java.lang.String
+ */
+CMNode getNamedItem(String name);
+/**
+ * item method
+ * @return CMNode
+ * @param index int
+ */
+CMNode item(int index);
+
+/**
+ *
+ */
+Iterator iterator();
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/CMNamespace.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/CMNamespace.java
new file mode 100644
index 0000000..100bcbc
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/CMNamespace.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel;
+
+/**
+ * CMNamespace interface
+ */
+public interface CMNamespace extends CMNode {
+  
+/**
+ * getPrefix method
+ * @return java.lang.String
+ */
+String getPrefix();
+/**
+ * getURI method
+ * @return java.lang.String
+ */
+String getURI();
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/CMNode.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/CMNode.java
new file mode 100644
index 0000000..8bd95e8
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/CMNode.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel;
+
+/**
+ * CMNode interface
+ */
+public interface CMNode {        
+  
+  static final int ANY_ELEMENT           = 1;
+	static final int ATTRIBUTE_DECLARATION = 2;
+	static final int DATA_TYPE             = 3;
+	static final int DOCUMENT              = 4;
+	static final int ELEMENT_DECLARATION   = 5;
+	static final int ENTITY_DECLARATION    = 6;
+	static final int GROUP                 = 7;
+  static final int NAME_SPACE            = 8;
+  static final int DOCUMENTATION         = 9;
+/**
+ * getNodeName method
+ * @return java.lang.String
+ */
+String getNodeName();
+/**
+ * getNodeType method
+ * @return int
+ *
+ * Returns one of :
+ *
+ */
+int getNodeType();
+
+/**
+ * supports method
+ * @return boolean
+ *
+ * Returns true if the CMNode supports a specified property
+ *
+ */
+boolean supports(String propertyName);
+
+/**
+ * getProperty method
+ * @return java.lang.Object
+ *
+ * Returns the object property desciped by the propertyName
+ *
+ */
+Object getProperty(String propertyName); //todo throw unsupported property exception
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/CMNodeList.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/CMNodeList.java
new file mode 100644
index 0000000..94adbf8
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/CMNodeList.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel;
+
+/**
+ * CMNodeList interface
+ */
+public interface CMNodeList {
+  
+/**
+ * getLength method
+ * @return int
+ */
+int getLength();
+/**
+ * item method
+ * @return CMNode
+ * @param index int
+ */
+CMNode item(int index);
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/ContentModelManager.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/ContentModelManager.java
new file mode 100644
index 0000000..602b160
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/ContentModelManager.java
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel;
+
+import java.util.List;
+
+import org.eclipse.core.runtime.Plugin;
+import org.eclipse.wst.xml.core.internal.contentmodel.factory.CMDocumentFactory;
+import org.eclipse.wst.xml.core.internal.contentmodel.factory.CMDocumentFactoryRegistry;
+import org.eclipse.wst.xml.core.internal.contentmodel.factory.CMDocumentFactoryRegistryReader;
+import org.eclipse.wst.xml.core.internal.contentmodel.internal.annotation.AnnotationFileRegistry;
+import org.eclipse.wst.xml.core.internal.contentmodel.internal.annotation.AnnotationFileRegistryReader;
+
+
+/**
+ * ContentModelManager class
+ */
+public class ContentModelManager extends Plugin {
+	// private static InferredGrammarFactory inferredGrammarFactory;
+	private CMDocumentFactoryRegistry cmDocumentFactoryRegistry;
+	private AnnotationFileRegistry annotationFileRegistry;
+
+	private static ContentModelManager instance;
+
+	public ContentModelManager() {
+		super();
+	}
+
+	public static ContentModelManager getInstance() {
+		if (instance == null) {
+			instance = new ContentModelManager();
+		}
+		return instance;
+	}
+
+	public CMDocument createCMDocument(String uri, String resourceType) {
+		if (resourceType == null && uri != null) {
+			int index = uri.lastIndexOf("."); //$NON-NLS-1$
+			resourceType = uri.substring(index + 1);
+		}
+
+		if (resourceType != null) {
+			resourceType = resourceType.toLowerCase();
+		}
+		CMDocumentFactory factory = getCMDocumentFactoryRegistry().getFactory(resourceType);
+		return factory != null ? factory.createCMDocument(uri) : null;
+	}
+
+
+	private CMDocumentFactoryRegistry getCMDocumentFactoryRegistry() {
+		if (cmDocumentFactoryRegistry == null) {
+			cmDocumentFactoryRegistry = new CMDocumentFactoryRegistry();
+			new CMDocumentFactoryRegistryReader(cmDocumentFactoryRegistry).readRegistry();
+		}
+		return cmDocumentFactoryRegistry;
+	}
+
+
+	public List getAnnotationFilesInfos(String publicId) {
+		return getAnnotationFileRegistry().getAnnotationFilesInfos(publicId);
+	}
+
+	private AnnotationFileRegistry getAnnotationFileRegistry() {
+		if (annotationFileRegistry == null) {
+			annotationFileRegistry = new AnnotationFileRegistry();
+			new AnnotationFileRegistryReader(annotationFileRegistry).readRegistry();
+		}
+		return annotationFileRegistry;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/annotation/Annotation.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/annotation/Annotation.java
new file mode 100644
index 0000000..e0a3b39
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/annotation/Annotation.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.annotation;
+
+import java.util.Hashtable;
+import java.util.List;
+         
+/**
+ * 
+ */
+public class Annotation
+{       
+  protected Hashtable hashtable = new Hashtable();                     
+
+  public Annotation()
+  {
+  }
+
+  public void setSpec(String spec)
+  {
+    hashtable.put("spec", spec); //$NON-NLS-1$
+  }     
+
+  public String getSpec()
+  {
+    return (String)hashtable.get("spec"); //$NON-NLS-1$
+  }
+      
+  public void setProperty(String name, String value)
+  {                             
+    hashtable.put(name, value);
+  }
+
+  public String getProperty(String propertyName)
+  {     
+    return (String)hashtable.get(propertyName);
+  }    
+
+  public List getAttributeList()
+  {
+    return null; // todo
+  }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/annotation/AnnotationMap.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/annotation/AnnotationMap.java
new file mode 100644
index 0000000..4b93035
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/annotation/AnnotationMap.java
@@ -0,0 +1,101 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.annotation;
+
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import com.ibm.icu.util.StringTokenizer;
+import java.util.Vector;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.contentmodel.internal.annotation.AnnotationFileInfo;
+import org.eclipse.wst.xml.core.internal.contentmodel.internal.annotation.AnnotationFileParser;
+
+
+/**
+ * AnnotationMap
+ */
+public class AnnotationMap {
+	protected List list = new Vector();
+	protected Hashtable hashtable = new Hashtable();
+	protected boolean isCaseSensitive = true;
+
+	public AnnotationMap() {
+	}
+
+	public void setCaseSensitive(boolean isCaseSensitive) {
+		this.isCaseSensitive = isCaseSensitive;
+	}
+
+	public void addAnnotation(Annotation annotation) {
+		String spec = annotation.getSpec();
+		if (spec != null) {
+			list.add(annotation);
+			StringTokenizer st = new StringTokenizer(spec, "[]|\t\n\r\f "); //$NON-NLS-1$
+			while (st.hasMoreTokens()) {
+				String cmNodeSpec = st.nextToken();
+				addAnnotationForCMNodeSpec(cmNodeSpec, annotation);
+			}
+		}
+	}
+
+	protected void addAnnotationForCMNodeSpec(String cmNodeSpec, Annotation annotation) {
+		String key = isCaseSensitive ? cmNodeSpec : cmNodeSpec.toLowerCase();
+		List list = (List) hashtable.get(key);
+		if (list == null) {
+			list = new Vector();
+
+			hashtable.put(key, list);
+		}
+		list.add(annotation);
+	}
+
+	public String getProperty(String cmNodeSpec, String propertyName) {
+		String result = null;
+		String key = isCaseSensitive ? cmNodeSpec : cmNodeSpec.toLowerCase();
+		List annotationList = (List) hashtable.get(key);
+		if (annotationList != null) {
+			for (Iterator i = annotationList.iterator(); i.hasNext();) {
+				Annotation annotation = (Annotation) i.next();
+				result = annotation.getProperty(propertyName);
+				if (result != null) {
+					break;
+				}
+			}
+		}
+		return result;
+	}
+
+	public String getProperty(CMNode cmNode, String propertyName) {
+		String result = null;
+		String cmNodeSpec = (String) cmNode.getProperty("spec"); //$NON-NLS-1$
+		if (cmNodeSpec == null) {
+			cmNodeSpec = cmNode.getNodeName();
+		}
+		if (cmNodeSpec != null) {
+			result = getProperty(cmNodeSpec, propertyName);
+		}
+		return result;
+	}
+
+	public List getAnnotations() {
+		return list;
+	}
+
+	public void load(String uri, String bundleId) throws Exception {
+		AnnotationFileParser parser = new AnnotationFileParser();
+		AnnotationFileInfo fileInfo = new AnnotationFileInfo(uri, bundleId);
+		parser.parse(this, fileInfo);
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/basic/CMAnyElementImpl.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/basic/CMAnyElementImpl.java
new file mode 100644
index 0000000..8300a90
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/basic/CMAnyElementImpl.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.basic;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAnyElement;
+
+
+public class CMAnyElementImpl extends CMContentImpl implements CMAnyElement
+{
+  protected String namespaceURI;  
+
+  public CMAnyElementImpl(String namespaceURI)
+  {
+    this.namespaceURI = namespaceURI;
+    minOccur = -1;
+  }             
+
+  public static String computeNodeName(String uri)
+  {
+    return uri != null ? ("any#" + uri) : "any"; //$NON-NLS-1$ //$NON-NLS-2$
+  }
+
+  // implements CMNode
+  //
+  public String getNodeName()
+  {
+    return computeNodeName(namespaceURI);
+  }
+ 
+  public int getNodeType()
+  {
+    return ANY_ELEMENT;
+  } 
+
+  // implements CMAnyElement
+  //
+  public String getNamespaceURI()
+  {
+    return namespaceURI;
+  }                     
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/basic/CMAttributeDeclarationImpl.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/basic/CMAttributeDeclarationImpl.java
new file mode 100644
index 0000000..4b554b6
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/basic/CMAttributeDeclarationImpl.java
@@ -0,0 +1,123 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.basic;
+
+import java.util.Enumeration;
+import java.util.List;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+
+public class CMAttributeDeclarationImpl extends CMNodeImpl implements CMAttributeDeclaration
+{
+  protected CMDataType dataType;
+  protected String nodeName;    
+  protected int usage;  
+  protected CMDocument cmDocument;
+  protected boolean prefixQualification;
+  protected List xsiTypes;
+                
+  public CMAttributeDeclarationImpl(String nodeName, int usage)
+  {
+    this(nodeName, usage, new CMDataTypeImpl(CMDataType.CDATA, ""));
+  }     
+
+  public CMAttributeDeclarationImpl(String nodeName, int usage, CMDataType dataType)
+  {        
+    this.nodeName = nodeName;
+    this.usage = usage;
+    this.dataType = dataType; 
+  }    
+
+  public int getNodeType()
+  {
+    return CMNode.ATTRIBUTE_DECLARATION;
+  }
+
+  public Object getProperty(String propertyName)
+  {
+    Object result = null;   
+    if (propertyName.equals("CMDocument")) //$NON-NLS-1$
+    {
+      result = cmDocument;
+    } 
+    else if (propertyName.equals("XSITypes")) //$NON-NLS-1$
+    {                                      
+      result = xsiTypes;
+    }
+    else if (propertyName.equals("http://org.eclipse.wst/cm/properties/nsPrefixQualification")) //$NON-NLS-1$
+    {
+      result = prefixQualification ? "qualified" : "unqualified"; //$NON-NLS-1$ //$NON-NLS-2$
+    }  
+    else
+    {
+      result = super.getProperty(propertyName);
+    }
+    return result;
+  }
+
+  public void setPrefixQualification(boolean qualified)
+  {
+    prefixQualification = qualified;
+  }              
+
+  public void setXSITypes(List list)
+  {
+    xsiTypes = list;
+  }
+     
+  public void setCMDocument(CMDocument cmDocument)
+  {
+    this.cmDocument = cmDocument;
+  }
+
+  public String getNodeName()
+  {
+    return nodeName;
+  }
+
+  public String getAttrName()
+  {
+    return nodeName;
+  }
+
+  public void setAttrType(CMDataType dataType)
+  {
+    this.dataType = dataType;
+  }
+
+  public CMDataType getAttrType()
+  {
+    return dataType;
+  }
+
+  public int getUsage()
+  {
+    return usage;
+  }
+           
+  /** @deprecated */
+  public String getDefaultValue()
+  {
+    return ""; //$NON-NLS-1$
+  }                 
+
+  /** @deprecated */
+  public Enumeration getEnumAttr()
+  {
+    return null;
+  }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/basic/CMContentImpl.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/basic/CMContentImpl.java
new file mode 100644
index 0000000..2357eec
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/basic/CMContentImpl.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.basic;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMContent;
+
+
+public abstract class CMContentImpl extends CMNodeImpl implements CMContent
+{
+  protected int minOccur = 0;
+  protected int maxOccur = -1;       
+                
+  // implements CMContent
+  //
+  public int getMaxOccur()
+  {
+    return maxOccur;
+  }          
+ 
+  public int getMinOccur()
+  {
+    return minOccur;
+  }  
+     
+  // implementation specific
+  //
+  public void setMaxOccur(int n)
+  {
+    maxOccur = n;
+  }          
+ 
+  public void setMinOccur(int n)
+  {
+    minOccur = n;
+  }                      
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/basic/CMDataTypeImpl.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/basic/CMDataTypeImpl.java
new file mode 100644
index 0000000..a004626
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/basic/CMDataTypeImpl.java
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.basic;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+public class CMDataTypeImpl extends CMNodeImpl implements CMDataType
+{
+  protected String dataTypeName;
+  protected String[] enumeratedValues;     
+  protected String instanceValue;
+
+  public CMDataTypeImpl(String dataTypeName, String instanceValue)
+  {
+    this.dataTypeName = dataTypeName;
+    this.instanceValue = instanceValue;
+    this.enumeratedValues = new String[0];
+  }
+
+  public CMDataTypeImpl(String dataTypeName, String[] enumeratedValues)
+  {
+    this.dataTypeName = dataTypeName;
+    this.enumeratedValues = enumeratedValues;   
+    this.instanceValue = enumeratedValues[0];
+  }
+
+
+  public int getNodeType()
+  {
+    return CMNode.DATA_TYPE;
+  }
+
+  public String getNodeName()
+  {
+    return getDataTypeName();
+  }
+
+  public String getDataTypeName()
+  {
+    return dataTypeName;
+  }
+
+  public int getImpliedValueKind()
+  {
+    return IMPLIED_VALUE_NONE;
+  }
+
+  public String getImpliedValue()
+  {
+    return null;
+  }
+
+  public String[] getEnumeratedValues()
+  {
+    return enumeratedValues;
+  }
+
+  public String generateInstanceValue()
+  {
+    return instanceValue;
+  }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/basic/CMDocumentImpl.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/basic/CMDocumentImpl.java
new file mode 100644
index 0000000..7c76a8e
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/basic/CMDocumentImpl.java
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.basic;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamespace;
+
+
+public class CMDocumentImpl extends CMNodeImpl implements CMDocument
+{
+  protected String targetNamespace;
+  protected CMNamedNodeMapImpl elements = new CMNamedNodeMapImpl();
+  protected CMNamedNodeMapImpl localElementPool;
+  protected CMNamedNodeMapImpl anyElements;
+
+  public CMDocumentImpl(String targetNamespace)
+  {
+    this.targetNamespace = targetNamespace;
+  }
+
+  public int getNodeType()
+  {
+    return DOCUMENT;
+  }
+
+  public String getNodeName()
+  {
+    return ""; //$NON-NLS-1$
+  }
+ 
+  public Object getProperty(String propertyName)
+  {
+    Object result = null;
+    if (propertyName.equals("http://org.eclipse.wst/cm/properties/targetNamespaceURI")) //$NON-NLS-1$
+    {
+      result = targetNamespace;
+    }                
+    else
+    {
+      result = super.getProperty(propertyName);
+    }
+    return result;
+  }    
+
+  public CMNamedNodeMap getElements()
+  {
+    return elements;
+  }
+
+  public CMNamedNodeMapImpl getAnyElements()
+  { 
+    if (anyElements == null)
+    {
+      anyElements = new CMNamedNodeMapImpl();
+    }
+    return anyElements;
+  }
+  
+  public CMNamedNodeMapImpl getLocalElementPool()
+  { 
+    if (localElementPool == null)
+    {
+      localElementPool = new CMNamedNodeMapImpl();
+    }                 
+    return localElementPool;
+  }
+
+  public CMNamedNodeMap getEntities()
+  {
+    return new CMNamedNodeMapImpl();
+  }
+
+  public CMNamespace getNamespace()
+  {
+    return null;
+  }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/basic/CMElementDeclarationImpl.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/basic/CMElementDeclarationImpl.java
new file mode 100644
index 0000000..1879b9f
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/basic/CMElementDeclarationImpl.java
@@ -0,0 +1,121 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.basic;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMContent;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+
+
+public class CMElementDeclarationImpl extends CMContentImpl implements CMElementDeclaration
+{
+  protected String name;          
+  protected CMDocument cmDocument;
+  protected CMNamedNodeMapImpl attributeMap = new CMNamedNodeMapImpl();
+  protected CMNamedNodeMapImpl localElementMap = new CMNamedNodeMapImpl();
+  protected CMContent content;
+  protected CMDataType dataType;
+  protected boolean isLocal;
+
+  public CMElementDeclarationImpl(CMDocument cmDocument, String name)
+  {                              
+    this.cmDocument = cmDocument;
+    this.name = name;
+  }     
+
+  // implements CMNode
+  //
+  public String getNodeName()
+  {
+    return name;
+  }
+ 
+  public int getNodeType()
+  {
+    return ELEMENT_DECLARATION;
+  }
+
+  public Object getProperty(String propertyName)
+  { 
+    Object result = null;               
+    if (propertyName.equals("http://org.eclipse.wst/cm/properties/nsPrefixQualification")) //$NON-NLS-1$
+    {
+      result = isLocal ? "unqualified" : "qualified"; //$NON-NLS-1$ //$NON-NLS-2$
+    }    
+    else if (propertyName.equals("CMDocument")) //$NON-NLS-1$
+    {
+      result = cmDocument;       
+    }    
+    else
+    {
+      result = super.getProperty(propertyName);
+    }
+    return result;
+  }
+                
+  // implements CMElementDeclaration
+  //
+  public CMNamedNodeMap getAttributes()
+  {
+    return attributeMap;
+  }                     
+
+  public CMContent getContent()
+  {
+    return content;
+  }
+
+  public int getContentType()
+  {
+    return MIXED;
+  }            
+
+  public String getElementName()
+  {
+    return name;
+  }
+
+  public CMDataType getDataType()
+  { 
+    return dataType;
+  }
+
+  public CMNamedNodeMap getLocalElements()
+  { 
+    return localElementMap;
+  } 
+    
+  //
+  //
+  public void setContent(CMContent cmContent)
+  {
+    content = cmContent;
+  }                 
+
+  public void setDataType(CMDataType cmDataType)
+  {
+    dataType = cmDataType;
+  }
+
+  public CMNamedNodeMapImpl getAttributeMap()
+  {
+    return attributeMap;
+  }
+
+  public void setLocal(boolean isLocal)
+  {
+    this.isLocal = isLocal;
+  }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/basic/CMEntityDeclarationImpl.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/basic/CMEntityDeclarationImpl.java
new file mode 100644
index 0000000..a5d97fa
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/basic/CMEntityDeclarationImpl.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.basic;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMEntityDeclaration;
+
+public class CMEntityDeclarationImpl extends CMNodeImpl implements CMEntityDeclaration
+{
+  protected String name;                         
+  protected String value;
+
+  public CMEntityDeclarationImpl(String name, String value)
+  {
+    this.name = name;
+    this.value = value;
+  }
+
+  public int getNodeType()
+  {
+    return ENTITY_DECLARATION;
+  }
+
+  public String getNodeName()
+  {
+    return name;
+  }
+ 
+  public String getName()
+  {
+    return name;
+  }
+
+  public String getValue()
+  {
+    return value;
+  }
+}   
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/basic/CMGroupImpl.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/basic/CMGroupImpl.java
new file mode 100644
index 0000000..59c4ece
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/basic/CMGroupImpl.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.basic;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNodeList;
+
+public class CMGroupImpl extends CMContentImpl implements CMGroup
+{
+  protected CMNodeList nodeList;                         
+  protected int operator;  
+
+  public CMGroupImpl(CMNodeList nodeList, int operator)
+  {
+    this.nodeList = nodeList;
+    this.operator = operator;
+  }
+
+  public int getNodeType()
+  {
+    return GROUP;
+  }
+ 
+  public CMNodeList getChildNodes()
+  {
+    return nodeList;
+  }
+
+  public int getOperator()
+  {
+    return operator;
+  } 
+}   
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/basic/CMNamedNodeMapImpl.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/basic/CMNamedNodeMapImpl.java
new file mode 100644
index 0000000..fee63d2
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/basic/CMNamedNodeMapImpl.java
@@ -0,0 +1,100 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.basic;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Iterator;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+
+
+public class CMNamedNodeMapImpl implements CMNamedNodeMap 
+{
+  public static CMNamedNodeMapImpl EMPTY_NAMED_NODE_MAP = new CMNamedNodeMapImpl();
+  protected Hashtable table = new Hashtable();
+
+  /**
+   * CMNamedNodeMapImpl constructor comment.
+   */
+  public CMNamedNodeMapImpl()
+  {
+  	super();
+  }
+
+  public CMNamedNodeMapImpl(CMNamedNodeMap initialContentsMap) {
+		super();
+		if (initialContentsMap != null) {
+			int length = initialContentsMap.getLength();
+			for (int j = 0; j < length; j++) {
+				put(initialContentsMap.item(j));
+			}
+		}
+	}
+  /**
+   * getLength method
+   * @return int
+   */
+  public int getLength()
+  {
+  	return table.size();
+  }
+
+  /**
+   * getNamedItem method
+   * @return CMNode
+   * @param name java.lang.String
+   */
+  public CMNode getNamedItem(String name)
+  {
+  	return (CMNode)table.get(name);
+  }
+
+  /**
+   * item method
+   * @return CMNode
+   * @param index int
+   */
+  public CMNode item(int index)
+  {
+    CMNode result = null;
+    int size = table.size();
+    if (index < size)
+    {
+      Enumeration values = table.elements();
+      for(int i = 0; i <= index; i++)
+      {
+        result = (CMNode)values.nextElement();
+      }
+    }
+    return result;
+  }
+  
+  public Hashtable getHashtable()
+  {
+          return table;
+  }
+  
+  public Iterator iterator()
+  {
+          return table.values().iterator();
+  }        
+  
+  public void put(CMNode cmNode)
+  {
+    table.put(cmNode.getNodeName(), cmNode);
+  }
+}
+  
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/basic/CMNodeImpl.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/basic/CMNodeImpl.java
new file mode 100644
index 0000000..a12e2ac
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/basic/CMNodeImpl.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.basic;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+
+public abstract class CMNodeImpl implements CMNode
+{            
+  protected boolean isInferred = false;
+   
+  public String getNodeName()
+  {
+    return ""; //$NON-NLS-1$
+  }
+ 
+  public boolean supports(String propertyName)
+  {
+    return false;
+  } 
+
+  public Object getProperty(String propertyName)
+  {              
+    Object result = null;
+    if ("isInferred".equals(propertyName)) //$NON-NLS-1$
+    {
+      result = isInferred ? Boolean.TRUE : Boolean.FALSE;
+    }
+    return result;
+  }    
+
+  public void setInferred(boolean isInferred)
+  {
+    this.isInferred = isInferred;
+  }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/basic/CMNodeListImpl.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/basic/CMNodeListImpl.java
new file mode 100644
index 0000000..6bcba38
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/basic/CMNodeListImpl.java
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.basic;
+
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNodeList;
+
+
+public class CMNodeListImpl implements CMNodeList 
+{
+  public static CMNodeListImpl EMPTY_NODE_LIST = new CMNodeListImpl(Collections.EMPTY_LIST);
+  protected List list;
+
+  public CMNodeListImpl()
+  {
+    this(new Vector());
+  }
+
+  public CMNodeListImpl(List list)
+  {
+    this.list = list;
+  }
+
+  /**
+   * getLength method
+   * @return int
+   */
+  public int getLength()
+  {
+    return list.size();
+  }
+  /**
+   * item method
+   * @return CMNode
+   * @param index int
+   */
+  public CMNode item(int index)
+  {
+    return (CMNode)list.get(index);
+  }
+  
+  public List getList()
+  {
+    return list;
+  }
+  
+  public Iterator iterator()
+  {
+    return list.iterator();
+  }
+  
+  public boolean contains(CMNode cmNode)
+  {
+    return list.contains(cmNode);
+  } 
+  
+  public void add(CMNode cmNode)
+  {
+    list.add(cmNode);
+  }  
+}
+
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/factory/CMDocumentFactory.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/factory/CMDocumentFactory.java
new file mode 100644
index 0000000..a84be95
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/factory/CMDocumentFactory.java
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.factory;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+
+// this interface is used to build a grammar document given a local file name
+//
+public interface CMDocumentFactory
+{   
+  public CMDocument createCMDocument(String uri);
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/factory/CMDocumentFactoryDescriptor.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/factory/CMDocumentFactoryDescriptor.java
new file mode 100644
index 0000000..c737b92
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/factory/CMDocumentFactoryDescriptor.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.factory;
+
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.wst.xml.core.internal.Logger;
+
+
+public class CMDocumentFactoryDescriptor
+{
+  private IConfigurationElement fElement;
+  private CMDocumentFactory factory;
+
+  public CMDocumentFactoryDescriptor(IConfigurationElement element)
+  {
+    this.fElement = element;
+  }
+
+  public CMDocumentFactory getFactory()
+  {
+    if (factory == null)
+    {
+      try
+      {
+        factory = (CMDocumentFactory) fElement.createExecutableExtension("class"); //$NON-NLS-1$
+      }
+      catch (Exception e)
+      {
+        Logger.logException("Exception loading CMDocumentFactory",e); //$NON-NLS-1$
+      }
+    }
+    return factory;
+  }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/factory/CMDocumentFactoryRegistry.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/factory/CMDocumentFactoryRegistry.java
new file mode 100644
index 0000000..9f403b9
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/factory/CMDocumentFactoryRegistry.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.factory;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Vector;
+
+/**
+ * 
+ * 
+ */
+public class CMDocumentFactoryRegistry 
+{
+	protected static CMDocumentFactoryRegistry instance;
+
+  private static String DEFAULT_RESOURCE_TYPE = "*"; //$NON-NLS-1$
+
+	protected Map resourceTypeMap = new HashMap();
+
+	protected Vector documentBuilderList = new Vector();
+
+	public CMDocumentFactoryRegistry() {
+	}
+
+	public void putFactory(String resourceType, CMDocumentFactoryDescriptor factoryDescriptor) {
+		resourceTypeMap.put(resourceType, factoryDescriptor);
+	}
+
+	public CMDocumentFactory getFactory(String resourceType) {
+		CMDocumentFactoryDescriptor factoryDescriptor = null;
+		if (resourceType != null) {
+			factoryDescriptor = (CMDocumentFactoryDescriptor) resourceTypeMap.get(resourceType);
+		}
+		if (factoryDescriptor == null) {
+			// (dmw) issue: a default type of '*' means what? registered as
+			// '*' is the way this works now. is that the intent? Or should it
+			// mean registered as any other type?
+			factoryDescriptor = (CMDocumentFactoryDescriptor) resourceTypeMap.get(DEFAULT_RESOURCE_TYPE);
+		}
+		return factoryDescriptor != null ? factoryDescriptor.getFactory() : null;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/factory/CMDocumentFactoryRegistryReader.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/factory/CMDocumentFactoryRegistryReader.java
new file mode 100644
index 0000000..6c8b193
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/factory/CMDocumentFactoryRegistryReader.java
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.factory;
+
+import com.ibm.icu.util.StringTokenizer;
+
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtensionPoint;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.wst.xml.core.internal.Logger;
+
+
+
+
+public class CMDocumentFactoryRegistryReader
+{
+  protected static final String EXTENSION_POINT_ID = "documentFactories"; //$NON-NLS-1$
+  protected static final String TAG_NAME = "factory"; //$NON-NLS-1$
+  protected static final String ATT_CLASS = "class"; //$NON-NLS-1$
+  protected static final String ATT_TYPE = "type";   //$NON-NLS-1$
+  protected String pluginId, extensionPointId;
+  
+  protected CMDocumentFactoryRegistry registry;
+  
+  public CMDocumentFactoryRegistryReader(CMDocumentFactoryRegistry registry)
+  {
+  	this.registry = registry;
+  }
+
+  public void readRegistry()
+  {
+    String bundleid = "org.eclipse.wst.xml.core"; //$NON-NLS-1$
+    IExtensionPoint point = Platform.getExtensionRegistry().getExtensionPoint(bundleid, EXTENSION_POINT_ID);
+    if (point != null)
+    {
+      IConfigurationElement[] elements = point.getConfigurationElements();
+      for (int i = 0; i < elements.length; i++)
+      {
+        readElement(elements[i]);
+      }
+    }
+  }
+
+  protected void readElement(IConfigurationElement element)
+  {
+    if (element.getName().equals(TAG_NAME))
+    {
+      String factoryClass = element.getAttribute(ATT_CLASS);
+      String filenameExtensions = element.getAttribute(ATT_TYPE);
+      if (factoryClass != null && filenameExtensions != null)
+      {
+        try
+        {
+          CMDocumentFactoryDescriptor descriptor = new CMDocumentFactoryDescriptor(element);
+          for (StringTokenizer st = new StringTokenizer(filenameExtensions, ","); st.hasMoreTokens(); ) //$NON-NLS-1$
+          {
+          	String token = st.nextToken().trim();
+			registry.putFactory(token, descriptor);	
+          }         
+        }
+        catch (Exception e)
+        {
+			Logger.logException(e);
+        }
+      }
+    }
+  }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/internal/annotation/AnnotationFileInfo.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/internal/annotation/AnnotationFileInfo.java
new file mode 100644
index 0000000..a9a372f
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/internal/annotation/AnnotationFileInfo.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.internal.annotation;
+
+/**
+ * Contains information about annotation files
+ */
+public class AnnotationFileInfo {
+	private String fAnnotationFileLocation;
+	private String fBundleId;
+
+	public AnnotationFileInfo(String annotationFileLocation, String bundleId) {
+		fAnnotationFileLocation = annotationFileLocation;
+		fBundleId = bundleId;
+	}
+
+	/**
+	 * Get the location of the annotation file as originally specified.
+	 * 
+	 * @return String
+	 */
+	public String getAnnotationFileLocation() {
+		return fAnnotationFileLocation;
+	}
+
+	/**
+	 * Get the bundle id where the annotation file is located.
+	 * 
+	 * @return String
+	 */
+	public String getBundleId() {
+		return fBundleId;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/internal/annotation/AnnotationFileParser.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/internal/annotation/AnnotationFileParser.java
new file mode 100644
index 0000000..641915d
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/internal/annotation/AnnotationFileParser.java
@@ -0,0 +1,207 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.internal.annotation;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.PropertyResourceBundle;
+import java.util.ResourceBundle;
+
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.wst.xml.core.internal.Logger;
+import org.eclipse.wst.xml.core.internal.contentmodel.annotation.Annotation;
+import org.eclipse.wst.xml.core.internal.contentmodel.annotation.AnnotationMap;
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+
+/**
+ * 
+ */
+public class AnnotationFileParser {
+	public static final String TAG_ID_ANNOTATIONS = "abstractGrammarAnnotations"; //$NON-NLS-1$
+	public static final String TAG_ID_ANNOTATION = "annotation"; //$NON-NLS-1$
+	public static final String TAG_ID_PROPERTY = "property"; //$NON-NLS-1$
+
+	/**
+	 * This method is called to parse an annotation file and store the
+	 * contents into an annotationMap
+	 */
+	private void parse(AnnotationMap annotationMap, InputStream input, AnnotationFileInfo fileInfo) throws Exception {
+		// move to Xerces-2.... add 'contextClassLoader' stuff
+		ClassLoader prevClassLoader = Thread.currentThread().getContextClassLoader();
+		try {
+			SAXParserFactory factory = SAXParserFactory.newInstance();
+			factory.setNamespaceAware(true);
+			SAXParser parser = factory.newSAXParser();
+			parser.parse(new InputSource(input), new AnnotationMapContentHandler(annotationMap, fileInfo));
+		}
+		finally {
+			Thread.currentThread().setContextClassLoader(prevClassLoader);
+		}
+	}
+
+	/**
+	 * This method is called to parse an annotation file and store the
+	 * contents into an annotationMap
+	 */
+	public void parse(AnnotationMap map, AnnotationFileInfo fileInfo) throws Exception {
+		InputStream inputStream = null;
+		try {
+			URL url = Platform.find(Platform.getBundle(fileInfo.getBundleId()), Path.fromOSString(fileInfo.getAnnotationFileLocation()));
+			if (url != null) {
+				inputStream = url.openStream();
+				parse(map, inputStream, fileInfo);
+			}
+		}
+		catch (Exception e) {
+			Logger.log(Logger.WARNING_DEBUG, e.getMessage(), e);
+			throw (e);
+		}
+		finally {
+			try {
+				if (inputStream != null) {
+					inputStream.close();
+				}
+			}
+			catch (IOException e) {
+			}
+		}
+	}
+
+	protected class AnnotationMapContentHandler extends DefaultHandler {
+		private AnnotationMap annotationMap;
+		private Annotation currentAnnotation;
+		private String currentPropertyName;
+		private StringBuffer propertyValueBuffer;
+		private ResourceBundle resourceBundle;
+		private AnnotationFileInfo fFileInfo;
+
+		public AnnotationMapContentHandler(AnnotationMap annotationMap, AnnotationFileInfo fileInfo) {
+			this.annotationMap = annotationMap;
+			this.fFileInfo = fileInfo;
+		}
+
+		private URL generatePropertiesFileURL(AnnotationFileInfo fileInfo, String propertiesLocation) {
+			URL propertiesURL = null;
+
+			// prepend $nl$ variable to location
+			IPath annotationPath = Path.fromOSString("$nl$/" + fileInfo.getAnnotationFileLocation()); //$NON-NLS-1$
+			// remove the annotation.xml file
+			IPath annotationFolder = annotationPath.removeLastSegments(1);
+			// append location of propertiles file
+			IPath propertiesFile = annotationFolder.append(propertiesLocation);
+			// append .properties extension if needed
+			if (propertiesFile.getFileExtension() == null)
+				propertiesFile = propertiesFile.addFileExtension("properties"); //$NON-NLS-1$
+			// create a URL out of the properties file location
+			propertiesURL = Platform.find(Platform.getBundle(fileInfo.getBundleId()), propertiesFile);
+			return propertiesURL;
+		}
+
+		public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
+			propertyValueBuffer = new StringBuffer();
+			if (localName.equals(TAG_ID_ANNOTATIONS)) {
+				int attributesLength = attributes.getLength();
+				for (int i = 0; i < attributesLength; i++) {
+					String attributeName = attributes.getLocalName(i);
+					String attributeValue = attributes.getValue(i);
+					if (attributeName.equals("propertiesLocation")) //$NON-NLS-1$
+					{
+						URL bundleURL = generatePropertiesFileURL(fFileInfo, attributeValue);
+						if (bundleURL != null) {
+							InputStream bundleStream = null;
+							try {
+								bundleStream = bundleURL.openStream();
+								resourceBundle = new PropertyResourceBundle(bundleStream);
+							}
+							catch (IOException e) {
+								Logger.log(Logger.WARNING_DEBUG, e.getMessage(), e);
+							}
+							finally {
+								try {
+									if (bundleStream != null)
+										bundleStream.close();
+								}
+								catch (IOException x) {
+									Logger.log(Logger.WARNING_DEBUG, x.getMessage(), x);
+								}
+							}
+						}
+					}
+					else if (attributeName.equals("caseSensitive")) //$NON-NLS-1$
+					{
+						if (attributeValue.trim().equals("false")) //$NON-NLS-1$
+						{
+							annotationMap.setCaseSensitive(false);
+						}
+					}
+				}
+			}
+			else if (localName.equals(TAG_ID_ANNOTATION)) {
+				currentAnnotation = null;
+				String specValue = attributes.getValue("spec"); //$NON-NLS-1$
+				if (specValue != null) {
+					currentAnnotation = new Annotation();
+					currentAnnotation.setSpec(specValue);
+				}
+				annotationMap.addAnnotation(currentAnnotation);
+			}
+			else if (localName.equals(TAG_ID_PROPERTY)) {
+				if (currentAnnotation != null) {
+					currentPropertyName = attributes.getValue("name"); //$NON-NLS-1$
+				}
+			}
+		}
+
+		public void endElement(String uri, String localName, String qName) throws SAXException {
+			if (currentPropertyName != null && currentAnnotation != null) {
+				String propertyValue = propertyValueBuffer.toString();
+				if (propertyValue != null) {
+					if (propertyValue.startsWith("%") && resourceBundle != null) //$NON-NLS-1$
+					{
+						try {
+							propertyValue = resourceBundle.getString(propertyValue.substring(1));
+						}
+						catch (Exception e) {
+							// ignore any exception that occurs while trying
+							// to fetch a resource
+						}
+					}
+					currentAnnotation.setProperty(currentPropertyName, propertyValue);
+				}
+			}
+
+			if (localName.equals(TAG_ID_ANNOTATION)) {
+				currentAnnotation = null;
+			}
+			else if (localName.equals(TAG_ID_PROPERTY)) {
+				currentPropertyName = null;
+			}
+		}
+
+		public void characters(char[] ch, int start, int length) {
+			if (currentPropertyName != null && currentAnnotation != null) {
+				propertyValueBuffer.append(ch, start, length);
+			}
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/internal/annotation/AnnotationFileRegistry.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/internal/annotation/AnnotationFileRegistry.java
new file mode 100644
index 0000000..c8991fb
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/internal/annotation/AnnotationFileRegistry.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.internal.annotation;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * This class is used to associate one or more annotation files with a grammar
+ * file.
+ * 
+ */
+public class AnnotationFileRegistry {
+	private Map map = new HashMap();
+
+	public AnnotationFileRegistry() {
+		new AnnotationFileRegistryReader(this).readRegistry();
+	}
+	
+	public synchronized List getAnnotationFilesInfos(String publicId) {
+		List theList = (List) map.get(publicId);
+		return theList != null ? theList : new ArrayList();
+	}
+		
+	public synchronized void addAnnotationFile(String publicId, AnnotationFileInfo fileInfo) {
+		List fileInfos = (List) map.get(publicId);
+		if (fileInfos == null) {
+			fileInfos = new ArrayList();
+			map.put(publicId, fileInfos);
+		}
+		fileInfos.add(fileInfo);
+	}
+
+	public synchronized void removeAnnotationFile(String publicId, AnnotationFileInfo fileInfo) {
+		List fileInfos = (List) map.get(publicId);
+		if (fileInfos != null) {
+			fileInfos.remove(fileInfo);
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/internal/annotation/AnnotationFileRegistryReader.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/internal/annotation/AnnotationFileRegistryReader.java
new file mode 100644
index 0000000..3c7c423
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/internal/annotation/AnnotationFileRegistryReader.java
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.internal.annotation;
+
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtensionPoint;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.wst.xml.core.internal.Logger;
+
+
+/**
+ * This class reads the plugin manifests and adds each specified gramamr
+ * annotation file with the AnnotationProvider
+ */
+public class AnnotationFileRegistryReader {
+	protected static final String EXTENSION_POINT_ID = "annotationFiles"; //$NON-NLS-1$
+	protected static final String TAG_NAME = "annotationFile"; //$NON-NLS-1$
+	protected static final String ATT_PUBLIC_ID = "publicId"; //$NON-NLS-1$
+	protected static final String ATT_LOCATION = "location"; //$NON-NLS-1$
+
+	private AnnotationFileRegistry annotationFileRegistry;
+
+	public AnnotationFileRegistryReader(AnnotationFileRegistry annotationFileRegistry) {
+		this.annotationFileRegistry = annotationFileRegistry;
+	}
+
+	/**
+	 * read from plugin registry and parse it.
+	 */
+	public void readRegistry() {
+		IExtensionRegistry extensionRegistry = Platform.getExtensionRegistry();
+		String pluginId = "org.eclipse.wst.xml.core"; //$NON-NLS-1$
+		IExtensionPoint point = extensionRegistry.getExtensionPoint(pluginId, EXTENSION_POINT_ID);
+		if (point != null) {
+			IConfigurationElement[] elements = point.getConfigurationElements();
+			for (int i = 0; i < elements.length; i++) {
+				readElement(elements[i]);
+			}
+		}
+	}
+
+	/**
+	 * readElement() - parse and deal with an extension like:
+	 * 
+	 * <extension
+	 * point="org.eclipse.wst.xml.core.internal.contentmodel.util_implementation">
+	 * <util_implementation class =
+	 * corg.eclipse.wst.baseutil.CMUtilImplementationImpl /> </extension>
+	 */
+	protected void readElement(IConfigurationElement element) {
+		if (element.getName().equals(TAG_NAME)) {
+			String publicId = element.getAttribute(ATT_PUBLIC_ID);
+			String location = element.getAttribute(ATT_LOCATION);
+			if (publicId != null && location != null) {
+				try {
+					String bundleId = element.getNamespace();
+					AnnotationFileInfo fileInfo = new AnnotationFileInfo(location, bundleId);
+					annotationFileRegistry.addAnnotationFile(publicId, fileInfo);
+				}
+				catch (Exception e) {
+					Logger.logException("problem adding annotation file " + location, e); //$NON-NLS-1$
+				}
+			}
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/internal/annotation/AnnotationUtility.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/internal/annotation/AnnotationUtility.java
new file mode 100644
index 0000000..061088a
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/internal/annotation/AnnotationUtility.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.internal.annotation;
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.wst.xml.core.internal.Logger;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.contentmodel.ContentModelManager;
+import org.eclipse.wst.xml.core.internal.contentmodel.annotation.AnnotationMap;
+
+
+/**
+ * 
+ */
+public class AnnotationUtility {
+	public static void loadAnnotationsForGrammar(String publicId, CMDocument cmDocument) {
+		List annotationFiles = ContentModelManager.getInstance().getAnnotationFilesInfos(publicId);
+		AnnotationMap map = (AnnotationMap) cmDocument.getProperty("annotationMap"); //$NON-NLS-1$
+		if (map != null) {
+			for (Iterator i = annotationFiles.iterator(); i.hasNext();) {
+				try {
+					AnnotationFileInfo annotationFileInfo = (AnnotationFileInfo) i.next();
+					AnnotationFileParser parser = new AnnotationFileParser();
+					parser.parse(map, annotationFileInfo);
+				}
+				catch (Exception e) {
+					Logger.logException(e);
+				}
+			}
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/internal/annotation/ResourceBundleHelper.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/internal/annotation/ResourceBundleHelper.java
new file mode 100644
index 0000000..98eeba4
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/internal/annotation/ResourceBundleHelper.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.internal.annotation;
+                     
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.Locale;
+import java.util.ResourceBundle;
+
+import org.eclipse.core.runtime.Platform;
+
+
+public class ResourceBundleHelper
+{
+  public static ResourceBundle getResourceBundle(String resourceURI, Locale targetLocale) throws Exception
+  {
+	  // try to load bundle from the location specified in the resourceURI
+    // we make the assumption that the resourceURI points to the local file system
+         
+    int index = resourceURI.lastIndexOf("/"); //$NON-NLS-1$
+    if (index == -1)
+    {
+      throw new Exception("Invalid resourceURI"); //$NON-NLS-1$
+    }                               
+
+    // Below we set 'resourceDirectory' so that it ends with a '/'.
+    // Here's an excerpt from the ClassLoader Javadoc ...
+    // Any URL that ends with a '/' is assumed to refer to a directory. Otherwise, the URL is assumed
+    // to refer to a JAR file which will be opened as needed. 
+    //
+    String resourceDirectory = resourceURI.substring(0, index + 1);
+    String resourceBundleName = resourceURI.substring(index + 1);
+    
+    // create a class loader with a class path that points to the resource bundle's location
+    //         
+    URL[] classpath = new URL[1];
+    classpath[0] = Platform.resolve(new URL(resourceDirectory));
+	  ClassLoader resourceLoader = new URLClassLoader(classpath, null); 
+       
+  	return ResourceBundle.getBundle(resourceBundleName, targetLocale, resourceLoader);
+	}  
+
+  public static ResourceBundle getResourceBundle(String resourceURI) throws Exception 
+  {
+	  return getResourceBundle(resourceURI, Locale.getDefault());
+  }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/internal/modelqueryimpl/InferredGrammarFactory.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/internal/modelqueryimpl/InferredGrammarFactory.java
new file mode 100644
index 0000000..19d8131
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/internal/modelqueryimpl/InferredGrammarFactory.java
@@ -0,0 +1,156 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.internal.modelqueryimpl;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAnyElement;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.basic.CMAnyElementImpl;
+import org.eclipse.wst.xml.core.internal.contentmodel.basic.CMAttributeDeclarationImpl;
+import org.eclipse.wst.xml.core.internal.contentmodel.basic.CMDocumentImpl;
+import org.eclipse.wst.xml.core.internal.contentmodel.basic.CMElementDeclarationImpl;
+import org.eclipse.wst.xml.core.internal.contentmodel.basic.CMGroupImpl;
+import org.eclipse.wst.xml.core.internal.contentmodel.basic.CMNamedNodeMapImpl;
+import org.eclipse.wst.xml.core.internal.contentmodel.basic.CMNodeListImpl;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.CMDescriptionBuilder;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+
+ 
+
+public class InferredGrammarFactory
+{                                      
+  public InferredGrammarFactory()
+  {
+  }
+
+  public CMDocument createCMDocument(String uri)
+  {                      
+    CMDocumentImpl cmdocument =new CMDocumentImpl(uri);
+    cmdocument.setInferred(true);
+    return cmdocument;
+  }    
+ 
+  public CMElementDeclaration createCMElementDeclaration(CMDocument cmDocument, Element element, boolean isLocal)
+  {
+    String localName = element.getLocalName();                                   
+    CMDocumentImpl cmDocumentImpl = (CMDocumentImpl)cmDocument;
+
+    CMNamedNodeMapImpl elementMap = isLocal ?
+                                    (CMNamedNodeMapImpl)cmDocumentImpl.getLocalElementPool() :
+                                    (CMNamedNodeMapImpl)cmDocumentImpl.getElements();
+
+    CMElementDeclarationImpl ed = (CMElementDeclarationImpl)elementMap.getNamedItem(localName);
+    if (ed == null)
+    {                                                                                          
+      //System.out.println("create ed " + localName);
+      ed = new CMElementDeclarationImpl(cmDocument, localName);
+      ed.setInferred(true);
+      ed.setLocal(isLocal);
+      ed.setMaxOccur(1);
+      CMGroupImpl group = new CMGroupImpl(new CMNodeListImpl(), CMGroup.CHOICE);
+      group.setInferred(true);
+      group.setMinOccur(0);
+      group.setMaxOccur(-1);
+      ed.setContent(group);            
+      elementMap.put(ed);
+    } 
+
+    // lookup or create the attributes
+    //
+    NamedNodeMap attributeMap = element.getAttributes();
+    int attributeMapLength = attributeMap.getLength();
+    for (int i = 0; i < attributeMapLength; i++)
+    {
+      Attr attr = (Attr)attributeMap.item(i);
+      CMAttributeDeclarationImpl ad = (CMAttributeDeclarationImpl)ed.getAttributeMap().getNamedItem(attr.getNodeName());
+      if (ad == null)
+      {     
+        // todo... use an attribute pool to be more efficient?
+        ad = new CMAttributeDeclarationImpl(attr.getNodeName(), CMAttributeDeclaration.OPTIONAL);
+        ad.setInferred(true);
+        ed.getAttributeMap().put(ad);
+      }
+    }
+    return ed;
+  }         
+
+  public void createCMContent(CMDocument parentCMDocument, CMElementDeclaration parentEd, CMDocument childCMDocument, CMElementDeclaration childEd, boolean isLocal, String uri)
+  {
+    // add element to the parent's content
+    // consider all content to be of the form (A | B | C)*    
+    //
+    CMGroupImpl group = (CMGroupImpl)parentEd.getContent();
+    CMNodeListImpl groupChildNodeList = (CMNodeListImpl)group.getChildNodes();
+
+    if (parentCMDocument == childCMDocument)
+    {
+      if (!groupChildNodeList.contains(childEd))
+      {
+        groupChildNodeList.add(childEd);
+      }
+      if (isLocal)
+      {
+        CMNamedNodeMapImpl localElementMap = (CMNamedNodeMapImpl)parentEd.getLocalElements();
+        localElementMap.put(childEd);
+      }
+    }     
+    else
+    {                                                    
+      CMAnyElement cmAnyElement = lookupOrCreateCMAnyElement((CMDocumentImpl)parentCMDocument, uri);
+      if (!groupChildNodeList.contains(cmAnyElement))
+      {
+        groupChildNodeList.add(cmAnyElement);
+      }
+    }      
+  }   
+
+  protected CMAnyElement lookupOrCreateCMAnyElement(CMDocumentImpl parentCMDocument, String uri)
+  {
+    CMNamedNodeMapImpl anyElementMap = parentCMDocument.getAnyElements();
+    CMAnyElementImpl anyElement = (CMAnyElementImpl)anyElementMap.getNamedItem(CMAnyElementImpl.computeNodeName(uri));
+    if (anyElement == null)
+    {                                                                                     
+      //System.out.println("create anyElement " + uri);
+      anyElement = new CMAnyElementImpl(uri);
+      anyElement.setInferred(true);
+      anyElementMap.put(anyElement);
+    }
+    return anyElement;
+  } 
+      
+
+  public void debugPrint(Collection collection)
+  {                
+    for (Iterator iter = collection.iterator(); iter.hasNext(); )
+    {
+      CMDocument cmDocument = (CMDocument)iter.next(); 
+      System.out.println("-----------------------------------------------"); //$NON-NLS-1$
+      System.out.println("cmDocument (" + cmDocument.getProperty("http://org.eclipse.wst/cm/properties/targetNamespaceURI") +")");  //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+      CMNamedNodeMapImpl elementMap = (CMNamedNodeMapImpl)cmDocument.getElements();
+      int size = elementMap.getLength();
+      for (int i = 0; i < size; i++)
+      {
+        CMElementDeclaration ed = (CMElementDeclaration)elementMap.item(i);
+        CMDescriptionBuilder builder = new CMDescriptionBuilder();
+        System.out.println("  ELEMENT " + ed.getNodeName() + " = " + builder.buildDescription(ed)); //$NON-NLS-1$ //$NON-NLS-2$
+      }
+    }
+  }        
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/internal/modelqueryimpl/ModelQueryExtensionDescriptor.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/internal/modelqueryimpl/ModelQueryExtensionDescriptor.java
new file mode 100644
index 0000000..c6d9490
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/internal/modelqueryimpl/ModelQueryExtensionDescriptor.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.internal.modelqueryimpl;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.extension.ModelQueryExtension;
+
+/**
+ * Describes an extension to the <code>modelQueryExtension</code> extension
+ * point.
+ * 
+ */
+public class ModelQueryExtensionDescriptor
+{
+  private static final String CONTENT_TYPE_ATTRIBUTE = "contentType"; //$NON-NLS-1$
+  private static final String NAMESPACE_ATTRIBUTE = "namespace"; //$NON-NLS-1$
+  private static final String CLASS_ATTRIBUTE = "class"; //$NON-NLS-1$
+  private IConfigurationElement configuration;
+  private String contentTypeId;
+  private String namespace;
+  private ModelQueryExtension extension;
+
+  public ModelQueryExtensionDescriptor(IConfigurationElement element)
+  {
+    configuration = element;
+  }
+
+  public ModelQueryExtension createModelQueryExtension() throws CoreException
+  {
+    if (extension == null)
+    {  
+      extension = (ModelQueryExtension) configuration.createExecutableExtension(CLASS_ATTRIBUTE);
+    }  
+    return extension;
+  }
+
+  public String getContentTypeId()
+  {
+    if (contentTypeId == null)
+    {
+      contentTypeId = configuration.getAttribute(CONTENT_TYPE_ATTRIBUTE);
+    }
+    return contentTypeId;
+  }
+
+  public String getNamespace()
+  {
+    if (namespace == null)
+    {
+      namespace = configuration.getAttribute(NAMESPACE_ATTRIBUTE);
+    }
+    return namespace;
+  }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/internal/modelqueryimpl/ModelQueryExtensionManagerImpl.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/internal/modelqueryimpl/ModelQueryExtensionManagerImpl.java
new file mode 100644
index 0000000..72c28fd
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/internal/modelqueryimpl/ModelQueryExtensionManagerImpl.java
@@ -0,0 +1,125 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2008 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.internal.modelqueryimpl;
+        
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.extension.ModelQueryExtension;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.extension.ModelQueryExtensionManager;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+
+
+public class ModelQueryExtensionManagerImpl implements ModelQueryExtensionManager
+{           
+  protected ModelQueryExtensionRegistry modelQueryExtensionRegistry = new ModelQueryExtensionRegistry();
+
+  public List getDataTypeValues(Element element, CMNode cmNode)
+  {    
+    List list = new ArrayList();      
+    String contentTypeId = getContentTypeId(element);
+    String namespace = getNamespace(cmNode);
+    String name = cmNode.getNodeName();
+    
+    for (Iterator i = modelQueryExtensionRegistry.getApplicableExtensions(contentTypeId, namespace).iterator(); i.hasNext();)
+    {
+      ModelQueryExtension extension = (ModelQueryExtension)i.next();
+      String[] values = null;
+      if (cmNode.getNodeType() == CMNode.ATTRIBUTE_DECLARATION)
+      {  
+        values = extension.getAttributeValues(element, namespace, name);
+      }
+      else
+      {
+        values = extension.getElementValues(element, namespace, name);        
+      }
+      if (values != null)
+      {
+        list.addAll(Arrays.asList(values));
+      }  
+    }  
+    return list;  
+  }                               
+
+  public void filterAvailableElementContent(List cmnodes, Element element, CMElementDeclaration ed)
+  {
+	  filterAvailableElementContent(cmnodes, element, ed, ModelQuery.INCLUDE_CHILD_NODES);
+  }
+
+  public void filterAvailableElementContent(List cmnodes, Element element, CMElementDeclaration ed, int includeOptions)
+  {
+    String contentTypeId = getContentTypeId(element);
+    String parentNamespace = element.getNamespaceURI();
+
+	List modelQueryExtensions = modelQueryExtensionRegistry.getApplicableExtensions(contentTypeId, parentNamespace);
+	if((includeOptions & ModelQuery.INCLUDE_CHILD_NODES) > 0)
+	{
+      for (Iterator j = cmnodes.iterator(); j.hasNext(); )
+      {
+        CMNode cmNode = (CMNode)j.next();  
+        String namespace = getNamespace(cmNode);
+        String name = cmNode.getNodeName();
+      
+        boolean include = true;
+        for(int k = 0; k < modelQueryExtensions.size() && include; k++) {
+        {
+            ModelQueryExtension extension = (ModelQueryExtension)modelQueryExtensions.get(k);
+            include = extension.isApplicableChildElement(element, namespace, name);
+            if (!include)
+            {
+              // remove the cmNode from the list
+              j.remove();
+            }
+          }
+        }
+      }
+    }
+    // add MQE-provided content
+    for(int k = 0; k < modelQueryExtensions.size(); k++)
+    {
+        ModelQueryExtension extension = (ModelQueryExtension)modelQueryExtensions.get(k);
+        cmnodes.addAll(Arrays.asList(extension.getAvailableElementContent(element, parentNamespace, includeOptions)));
+    }
+  }
+  
+  private String getNamespace(CMNode cmNode)
+  {
+    String namespace = null;
+    CMDocument cmDocument = (CMDocument)cmNode.getProperty("CMDocument"); //$NON-NLS-1$
+    if (cmDocument != null)          
+    {     
+      namespace = (String)cmDocument.getProperty("http://org.eclipse.wst/cm/properties/targetNamespaceURI");    //$NON-NLS-1$
+    }
+    return namespace;
+  }
+  
+  private String getContentTypeId(Node node)
+  {
+    String contentTypeId = "org.eclipse.core.runtime.xml"; //$NON-NLS-1$
+    if (node instanceof IDOMNode)
+    {
+      IDOMNode domNode = (IDOMNode) node;
+      contentTypeId = domNode.getModel().getContentTypeIdentifier();
+    }   
+    return contentTypeId;
+  } 
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/internal/modelqueryimpl/ModelQueryExtensionRegistry.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/internal/modelqueryimpl/ModelQueryExtensionRegistry.java
new file mode 100644
index 0000000..5366f41
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/internal/modelqueryimpl/ModelQueryExtensionRegistry.java
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.internal.modelqueryimpl;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.wst.xml.core.internal.Logger;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.extension.ModelQueryExtension;
+
+public class ModelQueryExtensionRegistry
+{
+  protected static final String EXTENSION_POINT_ID = "modelQueryExtensions"; //$NON-NLS-1$
+  protected static final String TAG_NAME = "modelQueryExtension"; //$NON-NLS-1$
+  private List descriptors;
+
+  public List getApplicableExtensions(String contentTypeId, String namespace)
+  {
+    List list = new ArrayList();
+    if (contentTypeId != null)
+    {
+      ensureExtensionsLoaded();
+      for (Iterator i = descriptors.iterator(); i.hasNext();)
+      {
+        ModelQueryExtensionDescriptor descriptor = (ModelQueryExtensionDescriptor) i.next();
+        if (contentTypeId.equals(descriptor.getContentTypeId()))
+        {
+          if (descriptor.getNamespace() == null ||  descriptor.getNamespace().equals(namespace))
+          {  
+            try
+            {
+              ModelQueryExtension extension = descriptor.createModelQueryExtension();
+              list.add(extension);
+            }
+            catch (CoreException e) {
+            	Logger.logException("problem creating model query extension", e); //$NON-NLS-1$
+            }
+          }  
+        }
+      }
+    }
+    return list;
+  }
+  
+  /*
+   *  TODO : consider providing a non-plugin means add/remove extensions
+   *   
+  public void addExtension(ModelQueryExtension extension)
+  {     
+  }
+
+  public void removeExtension(ModelQueryExtensionDeprecated extension)
+  {
+  }*/
+
+  /**
+   * Reads all extensions.
+   * <p>
+   * This method can be called more than once in order to reload from a changed
+   * extension registry.
+   * </p>
+   */
+  private synchronized void reloadExtensions()
+  {
+    descriptors = new ArrayList();
+    String bundleid = "org.eclipse.wst.xml.core"; //$NON-NLS-1$      
+    IConfigurationElement[] elements = Platform.getExtensionRegistry().getConfigurationElementsFor(bundleid, EXTENSION_POINT_ID);
+    for (int i = 0; i < elements.length; i++)
+    {
+      ModelQueryExtensionDescriptor descriptor = new ModelQueryExtensionDescriptor(elements[i]);
+      descriptors.add(descriptor);
+    }
+  }
+
+  /**
+   * Ensures the extensions have been loaded at least once.
+   */
+  private void ensureExtensionsLoaded()
+  {
+    if (descriptors == null)
+    {
+      reloadExtensions();
+    }
+  }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/internal/util/CMDataTypeValueHelper.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/internal/util/CMDataTypeValueHelper.java
new file mode 100644
index 0000000..e09fa6c
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/internal/util/CMDataTypeValueHelper.java
@@ -0,0 +1,161 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.internal.util;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.DOMNamespaceHelper;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.NamespaceTable;
+
+
+public class CMDataTypeValueHelper
+{
+  protected int idCount = 0;
+
+
+  public String getValue(CMAttributeDeclaration ad, NamespaceTable namespaceTable)
+  {
+    String value = null;
+       
+    if (isXSIType(ad))         
+    {       
+      List list = getQualifiedXSITypes(ad, namespaceTable);
+      value = list.size() > 0 ? (String)list.get(0) : null;
+    } 
+
+    // shameless hack
+    //
+    if (value == null)
+    {
+      if (ad.getAttrName().equals("xml:lang"))     //$NON-NLS-1$
+      {
+        value = "EN"; //$NON-NLS-1$
+      }
+    }
+
+    if (value == null)
+    {
+      CMDataType dataType = ad.getAttrType();
+      if (dataType != null)
+      {
+        value = getValue(dataType);
+      }
+    }
+    return value;
+  }
+
+
+  public String getValue(CMDataType dataType)
+  {
+    String value = null;
+    value = dataType.getImpliedValue();
+
+    if (value == null)
+    {
+      String[] values = dataType.getEnumeratedValues();
+      if (values != null && values.length > 0)
+      {
+        value = values[0];
+      }
+    }
+
+    if (value == null)
+    {
+      value = dataType.generateInstanceValue();
+    }               
+
+    // Here is a special case where we handle DTD's ID related datatypes.
+    // These values must be generated/validate by considering the entire xml file
+    // so we can't rely on the 'generateInstanceValue' method.
+    //
+    // todo... find a nicer way to handle this    
+    if (value == null)
+    {
+      String dataTypeName = dataType.getDataTypeName();
+      if (dataTypeName != null)
+      {
+        if (dataTypeName.equals("ID")) //$NON-NLS-1$
+        {
+          value = "idvalue" + idCount++; //$NON-NLS-1$
+        }
+        else if (dataTypeName.equals("IDREF") || dataTypeName.equals("IDREFS")) //$NON-NLS-1$ //$NON-NLS-2$
+        {
+          value = "idvalue0"; //$NON-NLS-1$
+        }
+      }
+    }     
+    return value;
+  } 
+      
+
+  public boolean isValidEmptyValue(CMAttributeDeclaration ad)
+  {    
+    boolean result = true;
+    CMDataType dataType = ad.getAttrType();
+    if (dataType != null)
+    {                                                          
+      String propertyValue = (String)dataType.getProperty("isValidEmptyValue"); //$NON-NLS-1$
+      if (propertyValue != null && propertyValue.equals("false")) //$NON-NLS-1$
+      {
+        result = false;
+      }
+    }   
+    return result;
+  }
+
+
+  public boolean isXSIType(CMAttributeDeclaration ad)
+  {         
+    boolean result = false;
+    if (ad.getNodeName().equals("type"))  //$NON-NLS-1$
+    {
+      CMDocument cmDocument = (CMDocument)ad.getProperty("CMDocument"); //$NON-NLS-1$
+      if (cmDocument != null)
+      {
+        String namespaceName = (String)cmDocument.getProperty("http://org.eclipse.wst/cm/properties/targetNamespaceURI"); //$NON-NLS-1$
+        if (namespaceName != null && namespaceName.equals("http://www.w3.org/2001/XMLSchema-instance")) //$NON-NLS-1$
+        {           
+          result = true;
+        }
+      }
+    }                   
+    return result;
+  }
+   
+
+  public List getQualifiedXSITypes(CMAttributeDeclaration ad, NamespaceTable table)
+  {          
+    List list = new Vector();                                                 
+                                       
+    List xsiTypes = (List)ad.getProperty("XSITypes"); //$NON-NLS-1$
+    if (xsiTypes != null && xsiTypes.size() > 0)
+    {
+      for (Iterator i = xsiTypes.iterator(); i.hasNext(); )
+      { 
+        String uriQualifiedName = (String)i.next();
+        String[] components = DOMNamespaceHelper.getURIQualifiedNameComponents(uriQualifiedName);  
+        String prefix = table.getPrefixForURI(components[0] != null ? components[0] : ""); //$NON-NLS-1$
+        String typeName = (prefix != null && prefix.length() > 0) ? 
+                           prefix + ":" + components[1] :  //$NON-NLS-1$
+                           components[1];
+        list.add(typeName);
+      }
+    }           
+    return list;
+  }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/internal/util/CMValidator.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/internal/util/CMValidator.java
new file mode 100644
index 0000000..2de5590
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/internal/util/CMValidator.java
@@ -0,0 +1,1250 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2009 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     David Carver (STAR) - bug 297005 - Some static constants not made final.
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.internal.util;
+
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Stack;
+import java.util.Vector;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAnyElement;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMContent;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNodeList;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.CMVisitor;
+
+
+
+public class CMValidator
+{
+  protected static final StringElementContentComparator stringContentComparitor = new StringElementContentComparator();
+  protected Hashtable graphNodeTable = new Hashtable();
+
+  /**
+   * GraphNode
+   */
+  protected static class GraphNode
+  {
+    public String name;
+    public boolean isTerminal;
+    public Vector arcList = new Vector();
+
+    public GraphNode(String name)
+    {
+      this.name = name;
+    }
+
+    public void addArc(Arc arc)
+    {
+      arcList.addElement(arc);
+    }
+
+    public String toString()
+    {
+      return "[GraphNode " + name + "]"; //$NON-NLS-1$ //$NON-NLS-2$
+    }
+  }
+
+
+  /**
+   * Arc
+   */
+  protected static class Arc
+  {
+    public static final int ELEMENT  = 1;
+    public static final int REPEAT   = 2;
+    public static final int OPTIONAL = 3;
+    public static final int PREV_IN  = 4;
+    public static final int OUT_NEXT = 5;
+    public static final int LINK     = 6;
+
+    public int kind;
+    public String name;
+    public GraphNode node;
+    public CMNode cmNode;
+
+    public Arc(int kind, GraphNode node, CMNode cmNode)
+    {
+      this(kind, "", node, cmNode); //$NON-NLS-1$
+    }
+
+    protected Arc(int kind, String name, GraphNode node, CMNode cmNode)
+    {
+      this.name = name;
+      this.kind = kind;
+      this.node = node;
+      this.cmNode = cmNode;
+    }
+  }
+
+
+  /**
+   * GraphGenerator
+   */
+  protected static class GraphGenerator extends CMVisitor
+  {
+    public int indent;
+    public int count;
+    public GraphNode startGraphNode;
+    public Context context;
+
+    protected static class Context
+    {
+      GraphNode from;
+      GraphNode to;
+
+      Context(GraphNode from, GraphNode to)
+      {
+        this.from = from;
+        this.to = to;
+      }
+
+      GraphNode getLastGraphNode()
+      {
+        return (to != null) ? to : from;
+      }
+    }
+
+
+    protected GraphGenerator()
+    {
+      startGraphNode = new GraphNode(getGraphNodeName());
+      context = new Context(startGraphNode, null);
+    }
+
+
+    protected void generateGraph(CMElementDeclaration ed)
+    {
+      int contentType = ed.getContentType();
+
+      if (contentType == CMElementDeclaration.MIXED ||
+          contentType == CMElementDeclaration.ELEMENT)
+      {
+        visitCMNode(ed.getContent());
+      }
+      // CMElementDeclaration.PCDATA... no graph required
+      // CMElementDeclaration.ANY... no graph required
+      context.getLastGraphNode().isTerminal = true;
+    }
+
+
+    protected String getGraphNodeName()
+    {
+      return "n" + count++; //$NON-NLS-1$
+    }
+
+
+    protected GraphNode getStartGraphNode()
+    {
+      return startGraphNode;
+    }
+
+
+    /**
+     *                repeat
+     *             +----#-----+
+     *             |          |
+     *             v          |
+     *  prev --#-> in --'x'-> out --#-> next
+     *  |                               ^
+     *  |                               |
+     *  +----------------#--------------+
+     *                optional
+     *
+     */
+    protected void createArcs(GraphNode in, GraphNode out, CMContent cmContent)
+    {
+      createArcs(in, out, cmContent, false);
+    }
+
+    protected void createArcs(GraphNode in, GraphNode out, CMContent cmContent, boolean isAllGroup)
+    {
+      //println("+createArcs() " + ed.getDescription() + " " + ed.getMinOccur());
+      GraphNode prev = context.from;
+      GraphNode next = new GraphNode(getGraphNodeName());
+
+      prev.addArc(new Arc(Arc.PREV_IN, in, cmContent));
+      out.addArc(new Arc(Arc.OUT_NEXT, next, cmContent));
+
+      if (context.to != null)
+      {
+        next.addArc(new Arc(Arc.LINK, context.to, cmContent));
+      }
+      else
+      {
+        context.from = next;
+      }
+
+      if (cmContent.getMinOccur() == 0)
+      {
+        // todo... should we see if an optional arc has already been added?
+        prev.addArc(new Arc(Arc.OPTIONAL, next, cmContent));
+      }
+
+      if (cmContent.getMaxOccur() == -1 || cmContent.getMaxOccur() > 1 || isAllGroup)
+      {
+        out.addArc(new Arc(Arc.REPEAT, in, cmContent));
+      }
+    }
+
+
+    public void visitCMGroup(CMGroup group)
+    {
+      Context prevContext = context;
+      GraphNode in = new GraphNode("(" + getGraphNodeName()); //$NON-NLS-1$
+      GraphNode out = new GraphNode(")" + getGraphNodeName()); //$NON-NLS-1$
+
+      int groupOperator = group.getOperator();
+      if (groupOperator == CMGroup.SEQUENCE)
+      {
+        context = new Context(in, null);
+        super.visitCMGroup(group);
+        context.from.addArc(new Arc(Arc.LINK, out, group));
+      }
+      else if (groupOperator == CMGroup.CHOICE ||
+               groupOperator == CMGroup.ALL)
+      {
+        context = new Context(in, out);
+        super.visitCMGroup(group);
+      }
+
+      context = prevContext;
+      createArcs(in, out, group, groupOperator == CMGroup.ALL);
+    }
+
+
+    public void visitCMElementDeclaration(CMElementDeclaration ed)
+    {
+      GraphNode in = new GraphNode(getGraphNodeName());
+      GraphNode out = new GraphNode(getGraphNodeName());
+      createArcs(in, out, ed);
+      in.addArc(new Arc(Arc.ELEMENT, ed.getElementName(), out, ed));
+    }
+                            
+
+    public void visitCMAnyElement(CMAnyElement anyElement)
+    {
+      GraphNode in = new GraphNode(getGraphNodeName());
+      GraphNode out = new GraphNode(getGraphNodeName());
+      createArcs(in, out, anyElement);
+      in.addArc(new Arc(Arc.ELEMENT, "any", out, anyElement)); //$NON-NLS-1$
+    }
+  }
+
+  // todo.. implement cache strategy hook, handle name spaces, locals etc.
+  //
+  public GraphNode lookupOrCreateGraph(CMElementDeclaration element)
+  {
+    Object key = element;
+    GraphNode node = (GraphNode)graphNodeTable.get(key);
+    if (node == null)
+    {
+      node = createGraph(element);
+      graphNodeTable.put(key, node);
+    }
+    return node;
+  }
+
+  public GraphNode createGraph(CMElementDeclaration element)
+  {
+    GraphGenerator generator = new GraphGenerator();
+    generator.generateGraph(element);
+    return generator.getStartGraphNode();
+  }
+
+
+  public void printGraph(GraphNode node, Vector namedArcList, Vector unamedArcList, int indent)
+  {
+    //String decoration = node.isTerminal ? " *" : "";
+    //printlnIndented(indent, "GraphNode:" + node.name + decoration);
+
+    indent += 2;
+    for (Enumeration e = node.arcList.elements() ; e.hasMoreElements() ;)
+    {
+      Arc arc = (Arc)e.nextElement();
+      //boolean visit = false;
+      //printlnIndented(indent, "Arc:" + arc.name + " (" + arc.kind + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+      if (arc.kind == Arc.ELEMENT)
+      {
+        //table.add(currentGrammarObject, arc.grammarObject);
+        if (!namedArcList.contains(arc))
+        {
+          namedArcList.add(arc);
+          unamedArcList = new Vector();
+          printGraph(arc.node, namedArcList, unamedArcList, indent + 2);
+        }
+      }
+      else
+      {
+        if (!unamedArcList.contains(arc))
+        {
+          unamedArcList.add(arc);
+          printGraph(arc.node, namedArcList, unamedArcList, indent + 2);
+        }
+      }
+    }
+  }
+
+  public void printGraph(GraphNode node)
+  {
+    printGraph(node, new Vector(), new Vector(), 0);
+  }
+
+
+  public void validateElementList(ElementList initialList, GraphNode initialGraphNode, ElementContentComparator comparator, Result result, boolean initialLoopFlag) {
+	  Stack arcStack = new Stack();
+	  arcStack.push(new ArcStackItem(null, false));
+	  boolean loopFlag = initialLoopFlag;
+	  ElementList elementList = initialList;
+	  GraphNode graphNode = initialGraphNode;
+	  while(!arcStack.isEmpty() && !result.isValid) {
+		  ArcStackItem stackElement = (ArcStackItem) arcStack.peek();
+		  if(stackElement.isVisited) {
+			  arcStack.pop();
+			  if(stackElement.arc != null) {
+				  result.pop(stackElement.arc);
+				  continue;
+			  }
+		  } else {
+			  stackElement.isVisited = true;
+			  result.push(stackElement.arc);
+			  graphNode = stackElement.arc.node;
+			  loopFlag = stackElement.loopFlag;
+		  } 
+		  if(elementList == null && graphNode.isTerminal) {
+			  result.isValid = true;
+		  } else {
+			  for(Iterator arcIterator = graphNode.arcList.iterator(); arcIterator.hasNext();) {
+				  Arc arc = (Arc)arcIterator.next();
+				  boolean traverseArc = false;
+				  if (arc.kind == Arc.ELEMENT) {
+					  if(elementList != null && comparator.matches(elementList.head, arc.cmNode)) {
+						  loopFlag = false;
+						  traverseArc = true;
+						  elementList = elementList.tail; // increment our position in the list
+					  }
+				  } else if(arc.kind == Arc.REPEAT) {
+					  if(!loopFlag) {
+						  traverseArc = true;
+					  }
+					  loopFlag = true;
+				  } else {
+					  traverseArc = true;
+				  }
+				  if(traverseArc) {
+					  if (result.canPush(arc)) { // test to see if we can push this arc due to facet constraints  
+						  arcStack.push(new ArcStackItem(arc, loopFlag));
+					  }
+				  }
+			  }
+		  }
+	  }
+  }
+  
+  
+  private class ArcStackItem {
+	  
+	  Arc arc;
+	  boolean loopFlag;
+	  boolean isVisited;
+	  
+	  public ArcStackItem(Arc arc, boolean loopflag) {
+		  this.arc = arc;
+		  this.loopFlag = loopflag;
+		  this.isVisited = arc == null;
+	  }
+
+  }
+
+
+  /**
+   *
+   */
+  protected static ElementList createElementList(int contentType, List v, ElementContentComparator comparator, Result result)
+  {
+    ElementList first = null;
+    ElementList prev = null;
+
+    int size = v.size();
+    for (int i = 0; i < size; i++)
+    {
+      Object o = v.get(i);
+      if (o != null && !comparator.isIgnorable(o))
+      {
+        if (comparator.isElement(o))
+        {
+          ElementList list = new ElementList();
+          list.head = o;
+
+          if (prev != null)
+          {
+            prev.tail = list;
+          }
+          else
+          {
+            first = list;
+          }
+          prev = list;
+        }
+        else if (contentType == CMElementDeclaration.ELEMENT)
+        {
+          result.isValid = false;
+          result.errorIndex = i;
+          result.errorMessage = "Element can not include PCDATA content"; //$NON-NLS-1$
+        }
+      }
+    }
+    return first;
+  }
+
+  /**
+   *
+   */
+  public void validate(CMElementDeclaration ed, List elementContent, ElementContentComparator comparator, Result result)
+  {
+    int contentType = ed.getContentType();
+
+    if (contentType == CMElementDeclaration.MIXED ||
+        contentType == CMElementDeclaration.ELEMENT)
+    {
+      ElementList elementList = createElementList(contentType, elementContent, comparator, result);
+      if (result.isValid == true)
+      {  
+          boolean isGraphValidationNeeded = !(elementList == null && contentType == CMElementDeclaration.MIXED);
+                      
+          // explicitly handle 'All' groups
+          //
+          CMContent content = ed.getContent();
+          if (content != null && content.getNodeType() == CMNode.GROUP)
+          {
+            CMGroup group = (CMGroup)content;
+            if (group.getOperator() == CMGroup.ALL)
+            {
+              isGraphValidationNeeded = false;
+              validatAllGroupContent(elementContent, comparator, group, result);                               
+            }              
+          }  
+          
+          if (isGraphValidationNeeded)
+          {
+            // validate the elementList using a graph
+            //
+            result.isValid = false;
+            GraphNode node = lookupOrCreateGraph(ed);
+            validateElementList(elementList, node, comparator, result, false);
+          }
+      }
+    }
+    else if (contentType == CMElementDeclaration.PCDATA)
+    {
+      int size = elementContent.size();
+      for (int i = 0; i < size; i++)
+      {
+        Object o = elementContent.get(i);
+        if (comparator.isElement(o))
+        {
+          result.isValid = false;
+          result.errorIndex = i;
+          result.errorMessage = "Element may only include PCDATA content"; //$NON-NLS-1$
+          break;
+        }
+      }
+    }
+    else if (contentType == CMElementDeclaration.EMPTY)
+    {
+      int size = elementContent.size();
+      for (int i = 0; i < size; i++)
+      {
+        Object o = elementContent.get(i);
+        if (!comparator.isIgnorable(o))
+        {
+          result.isValid = false;
+          result.errorIndex = i;
+          result.errorMessage = "Element may not contain PCDATA or Element content"; //$NON-NLS-1$
+          break;
+        }
+      }
+    }
+    //else if (contentType == CMElementDeclaration.ANY)
+    // {
+    //   assume elementContent will always be valid for this content type
+    // }
+  }
+    
+  static class ItemCount
+  {
+    int count = 0;    
+  }
+  
+  private void validatAllGroupContent(List elementContent, ElementContentComparator comparator, CMGroup allGroup, Result result) 
+  {
+    boolean isValid = true;
+    boolean isPartiallyValid = true;
+    HashMap map = new HashMap();
+    CMNodeList list = allGroup.getChildNodes();
+    for (int j = list.getLength() - 1; j >= 0; j--)
+    {
+      CMNode node = list.item(j);      
+      if (map.get(node) == null)
+      {  
+        map.put(node, new ItemCount());
+      }  
+    }    
+    int validitionCount = 0;
+    for (Iterator i = elementContent.iterator(); i.hasNext(); validitionCount++)
+    {
+      Object o = i.next();        
+      if (comparator.isElement(o))
+      {              
+        // test to see if the element is listed in the all group
+        //
+        CMNode matchingCMNode = null;
+        for (int j = list.getLength() - 1; j >= 0; j--)
+        {
+          CMNode node = list.item(j);
+          if (comparator.matches(o, node))
+          {
+            matchingCMNode = node;
+            break;
+          }             
+        }                              
+        if (matchingCMNode == null)
+        {     
+          isPartiallyValid = false;
+          isValid = false;
+          break;
+        }
+        else
+        {  
+          // test to see that the element occurs only once
+          //
+          ItemCount itemCount = (ItemCount)map.get(matchingCMNode);
+          if (itemCount != null)
+          {  
+            if (itemCount.count > 0)
+            {
+              // we don't want to allow too many elements!
+              // we consider 'not enough' to be partially valid... but not 'too many'
+              isPartiallyValid = false;
+              break;
+            }  
+            else
+            {
+              itemCount.count++;
+            }  
+          }
+        }  
+      }  
+    }
+    if (isValid)
+    {  
+      for (int j = list.getLength() - 1; j >= 0; j--)
+      {
+        CMNode node = list.item(j);      
+        if (node.getNodeType() == CMNode.ELEMENT_DECLARATION)
+        {  
+          CMContent content = (CMContent)node;
+          ItemCount itemCount = (ItemCount)map.get(node);
+//          System.out.print("content " + content.getNodeName() + " " + content.getMinOccur());
+          if (itemCount.count < content.getMinOccur())
+          {  
+            isValid = false;
+            break;
+          }  
+        }  
+      }
+    }
+    if (result instanceof ElementPathRecordingResult && isPartiallyValid)
+    {
+      ((ElementPathRecordingResult)result).setPartialValidationCount(validitionCount);
+    }  
+    result.isValid = isValid;
+  }  
+  
+  
+  public void getOriginArray(CMElementDeclaration ed, List elementContent, ElementContentComparator comparator, ElementPathRecordingResult result)
+  {
+    CMNode[] cmNodeArray = null;
+    validate(ed, elementContent, comparator, result);
+    if (result.isValid)
+    {
+      CMDataType dataType = ed.getDataType();
+      int size = elementContent.size();
+      cmNodeArray = new CMNode[size];
+      Vector originList = result.getElementOriginList();
+      int originListSize = originList.size(); 
+      int originListIndex = 0;
+      for (int i = 0; i < size; i++)
+      {
+        Object o = elementContent.get(i);
+        if (comparator.isElement(o))
+        {     
+          if (originListIndex < originListSize)
+          {
+            cmNodeArray[i] = (CMNode)originList.get(originListIndex);
+            originListIndex++;
+          }
+        }
+        else if (comparator.isPCData(o))
+        {
+          cmNodeArray[i] = dataType;
+        }
+        // else the CMNode at this index is null
+      }
+      result.setOriginArray(cmNodeArray);
+    }
+  }
+  
+  private void collectNamedArcs(GraphNode node, List namedArcList, int indent)
+  {
+    //printlnIndented(indent, "GraphNode:" + node.name + decoration);
+    indent += 2;
+    for (Iterator i = node.arcList.iterator(); i.hasNext() ;)
+    {
+      Arc arc = (Arc)i.next();
+      //printlnIndented(indent, "Arc:" + arc.name + " (" + arc.kind + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+      if (arc.kind == Arc.ELEMENT)
+      { 
+        if (!namedArcList.contains(arc))
+        {
+          namedArcList.add(arc);
+          collectNamedArcs(arc.node, namedArcList, indent + 2);
+        }
+      }
+      else if (arc.kind != Arc.REPEAT && arc.kind != Arc.OPTIONAL)
+      {
+        collectNamedArcs(arc.node, namedArcList, indent + 2);
+      }
+    }
+  }
+  
+  
+  private List getMatchingArcs(CMElementDeclaration ed, String elementName)
+  {
+    List arcList = new ArrayList();
+    GraphNode graphNode = lookupOrCreateGraph(ed);
+    if (elementName == null)
+    {
+      // here we add the 'root' arc
+      for (Iterator i = graphNode.arcList.iterator(); i.hasNext() ;)
+      {
+        Arc arc = (Arc)i.next();
+        if (arc.kind == Arc.PREV_IN)
+        {
+          arcList.add(arc);
+          break;
+        }  
+      }
+    }
+    else
+    { 
+      List namedArcs = new ArrayList();
+      collectNamedArcs(graphNode, namedArcs, 0);
+      for (Iterator i = namedArcs.iterator(); i.hasNext(); )
+      {
+        Arc arc = (Arc)i.next();
+        if (arc.cmNode != null && elementName.equals(arc.cmNode.getNodeName()))
+        {  
+          arcList.add(arc);
+        }  
+      }  
+    }      
+    return arcList;
+  }
+
+  
+  private void collectNextSiblings(GraphNode node, List nextSiblingList, List namedArcList, List unamedArcList, int indent)
+  {
+    //printlnIndented(indent, "GraphNode:" + node.name + decoration);
+    indent += 2;
+    for (Iterator i = node.arcList.iterator(); i.hasNext(); )
+    {
+      Arc arc = (Arc)i.next();
+      if (arc.kind == Arc.ELEMENT)
+      {       
+        if (!namedArcList.contains(arc))
+        {
+          if (arc.cmNode != null)
+          {  
+            nextSiblingList.add(arc.cmNode);
+            if (arc.cmNode.getNodeType() == CMNode.ELEMENT_DECLARATION ||
+                arc.cmNode.getNodeType() == CMNode.ANY_ELEMENT)
+            {              
+              namedArcList.add(arc);
+              CMContent cmNode = (CMContent)arc.cmNode; 
+              if (cmNode.getMinOccur() == 0)
+              {
+                unamedArcList = new ArrayList();
+                collectNextSiblings(arc.node, nextSiblingList, namedArcList, unamedArcList, indent + 2);
+              }
+            }            
+          }
+        }
+      }  
+      else
+      {
+        if (!unamedArcList.contains(arc))
+        {
+          unamedArcList.add(arc);
+          collectNextSiblings(arc.node, nextSiblingList, namedArcList, unamedArcList, indent + 2);
+        }
+      }
+    }  
+  }
+    
+  public CMNode[] getNextSiblings(CMElementDeclaration ed, String elementName)
+  {
+    List arcList = getMatchingArcs(ed, elementName);
+    List nextSiblingList = new ArrayList();
+    for (Iterator i = arcList.iterator(); i.hasNext(); )
+    {
+      Arc arc = (Arc)i.next();
+      collectNextSiblings(arc.node, nextSiblingList, new ArrayList(), new ArrayList(), 0);      
+    }  
+    CMNode[] result = new CMNode[nextSiblingList.size()];
+    nextSiblingList.toArray(result);    
+    //System.out.print("getNextSibling(" +elementName + ")");
+    //for (int i = 0; i < result.length; i++)
+    //{
+    //  System.out.print("[" + result[i].getNodeName() + "]");
+    //}  
+    //System.out.println();
+    return result;
+  }
+
+  /**
+   *
+   */
+  public static class Result
+  {
+    public boolean isValid = true;
+    public int errorIndex = -1;
+    public String errorMessage;
+    public boolean isRepeatTraversed; // detects if a repeat has been traversed
+
+    public boolean canPush(Arc arc)
+    {
+      return true;
+    }
+    
+    public void push(Arc arc)
+    {
+      // overide this method to record traversed nodes
+    }
+    public void pop(Arc arc)
+    {
+      // overide this method to record traversed nodes
+    }
+    public CMNode[] getOriginArray()
+    {
+      return null;
+    }
+  }
+
+  /**
+   *
+   */
+  public static class ElementPathRecordingResult extends Result
+  {  
+    protected List activeItemCountList = new ArrayList();
+    protected List inactiveItemCountList = new ArrayList();    
+    protected Vector elementOriginStack = new Vector();
+    protected CMNode[] originArray = null;
+    protected int partialValidationCount = 0;
+
+    
+    // this method is used to support facet counts
+    //
+    public boolean canPush(Arc arc)
+    {     
+      boolean result = true;        
+      try
+      {        
+        if (arc.kind == Arc.REPEAT)
+        {          
+          if (arc.cmNode instanceof CMContent)
+          {
+            CMContent content = (CMContent)arc.cmNode;
+            
+            // we only need to do 'special' facet checking if the maxOccurs is > 1
+            // values of '0' and '-1' (unbounded) work 'for free' without any special checking
+            //
+            if (content.getMaxOccur() > 1)
+            {  
+              ItemCount itemCount = (ItemCount)activeItemCountList.get(activeItemCountList.size() - 1);
+              
+              // here we need to compute if we can do another repeat
+              // if we increase the repeat count by '1' will this violate the maxOccurs
+              //
+              if (itemCount.count + 1 >= content.getMaxOccur())
+              {
+                result = false;
+              }
+            }
+            //System.out.println("canPush REPEAT (" + itemCount.count + ")" + content.getNodeName() + " result= " + result);            
+          } 
+        }       
+      }
+      catch (Exception e)
+      {
+        e.printStackTrace();
+      }
+      //System.out.flush();
+      return result;
+    }
+    
+    public void push(Arc arc)
+    {
+      if (arc.kind == Arc.ELEMENT)
+      {
+        //System.out.println("[X]push(" + arc.kind + ")" + arc.cmNode.getNodeName());
+        elementOriginStack.add(arc.cmNode);
+        partialValidationCount = Math.max(elementOriginStack.size(), partialValidationCount);
+      }
+      else if (arc.kind == Arc.PREV_IN)
+      {
+        //System.out.println("[X]push(" + arc.kind + ")" + arc.cmNode.getNodeName());
+        activeItemCountList.add(new ItemCount());   
+      }
+      else if (arc.kind == Arc.OUT_NEXT)
+      {        
+        //System.out.println("[X]push(" + arc.kind + ")" + arc.cmNode.getNodeName() + "[" + arc + "]");
+        int size = activeItemCountList.size();
+        ItemCount itemCount = (ItemCount)activeItemCountList.get(size - 1);
+        activeItemCountList.remove(size - 1);
+        inactiveItemCountList.add(itemCount); 
+      }      
+      else if (arc.kind == Arc.REPEAT)
+      {
+        //System.out.println("[X]push(" + arc.kind + ")" + arc.cmNode.getNodeName());
+        ItemCount itemCount = (ItemCount)activeItemCountList.get(activeItemCountList.size() - 1);
+        itemCount.count++;
+        //System.out.println("repeat(" + itemCount.count + ")" + arc.cmNode.getNodeName());
+      }        
+    }
+
+    public void pop(Arc arc)
+    {
+      if (arc.kind == Arc.ELEMENT)
+      {
+        //System.out.println("[X]pop(" + arc.kind + ")" + arc.cmNode.getNodeName());
+        int size = elementOriginStack.size();
+        elementOriginStack.remove(size - 1);
+      }
+      else if (arc.kind == Arc.PREV_IN)
+      {
+        //System.out.println("[X]pop(" + arc.kind + ")" + arc.cmNode.getNodeName());
+        activeItemCountList.remove(activeItemCountList.size() - 1);        
+      }
+      else if (arc.kind == Arc.OUT_NEXT)
+      {
+        //System.out.println("[X]pop(" + arc.kind + ")" + arc.cmNode.getNodeName());
+        int size = inactiveItemCountList.size();
+        ItemCount itemCount = (ItemCount)inactiveItemCountList.get(size - 1);
+        inactiveItemCountList.remove(size - 1);
+        activeItemCountList.add(itemCount);     
+      }  
+      else if (arc.kind == Arc.REPEAT)
+      {
+        //System.out.println("[X]pop(" + arc.kind + ")" + arc.cmNode.getNodeName());
+        ItemCount itemCount = (ItemCount)activeItemCountList.get(activeItemCountList.size() - 1);
+        itemCount.count--;
+      }     
+    }
+
+    public Vector getElementOriginList()
+    {
+      return elementOriginStack;
+    }
+
+    public CMNode[] getOriginArray()
+    {
+      return originArray;
+    }
+
+    public void setOriginArray(CMNode[] originArray)
+    {
+      this.originArray = originArray;
+    }
+    
+    public int getPartialValidationCount()
+    {
+      return partialValidationCount;
+    }
+
+    public void setPartialValidationCount(int partialValidationCount)
+    {
+      this.partialValidationCount = partialValidationCount;
+    }
+  }  
+
+  /**
+   *
+   */
+  public static class PathRecordingResult extends Result
+  {
+    protected Vector arcList = new Vector();
+
+    public void push(Arc arc)
+    {
+      arcList.add(arc);
+    }
+
+    public void pop(Arc arc)
+    {
+      int size = arcList.size();
+      arcList.remove(size - 1);
+    }
+
+    public List getArcList()
+    {
+      List list = new Vector();
+      for (Iterator iterator = arcList.iterator(); iterator.hasNext(); )
+      {
+        Arc arc = (Arc)iterator.next();
+        if (arc.kind == Arc.ELEMENT)
+        {
+          list.add(arc);
+        }
+      }
+      return list;
+    }
+
+    public MatchModelNode getMatchModel()
+    {
+      MatchModelNodeBuilder builder = new MatchModelNodeBuilder(arcList);
+      builder.buildMatchModel();
+      return builder.getRoot();
+    }
+  }
+
+  /**
+   *
+   */
+  public static class MatchModelNode
+  {
+    public CMNode cmNode;
+    public List children = new Vector();
+    public Object data;
+
+    public MatchModelNode(MatchModelNode parent, CMNode cmNode)
+    {
+      this.cmNode = cmNode;
+    }
+
+    public void printModel(int indent)
+    {
+      //String cmNodeName = cmNode != null ? cmNode.getNodeName() : "null";
+      //printlnIndented(indent, "MatchModelNode : " + cmNodeName);
+      for (Iterator iterator = children.iterator(); iterator.hasNext(); )
+      {
+        MatchModelNode child = (MatchModelNode)iterator.next();
+        child.printModel(indent + 2);
+      }
+    }
+  }
+
+  public static class MatchModelNodeBuilder
+  {
+    protected List arcList;
+    protected List stack = new Vector();
+    protected MatchModelNode root;
+    protected MatchModelNode current;
+
+    public MatchModelNodeBuilder(List arcList)
+    {
+      this.arcList = arcList;
+      root = new MatchModelNode(null, null);
+      push(root);
+    }
+
+    protected void push(MatchModelNode node)
+    {
+      current = node;
+      stack.add(node);
+    }
+
+    protected void pop()
+    {
+      int size = stack.size();
+      stack.remove(size - 1);
+      current = (MatchModelNode)stack.get(size - 2);
+    }
+
+    public boolean isCMGroup(CMNode cmNode)
+    {
+      return cmNode != null && cmNode.getNodeType() == CMNode.GROUP;
+    }
+
+    public void buildMatchModel()
+    {
+      for (Iterator iterator = arcList.iterator(); iterator.hasNext(); )
+      {
+        Arc arc = (Arc)iterator.next();
+
+        if (arc.kind == Arc.ELEMENT)
+        {
+          current.children.add(new MatchModelNode(current, arc.cmNode));
+        }
+        else if (arc.kind == Arc.PREV_IN)
+        {
+          if (isCMGroup(arc.cmNode))
+          {
+            MatchModelNode newModelNode = new MatchModelNode(current, arc.cmNode);
+            current.children.add(newModelNode);
+            push(newModelNode);
+          }
+        }
+        else if (arc.kind == Arc.OUT_NEXT)
+        {
+          if (isCMGroup(arc.cmNode))
+          {
+            pop();
+          }
+        }
+        else if (arc.kind == Arc.REPEAT)
+        {
+          if (isCMGroup(arc.cmNode))
+          {
+            pop();
+            MatchModelNode newModelNode = new MatchModelNode(current, arc.cmNode);
+            current.children.add(newModelNode);
+            push(newModelNode);
+          }
+        }
+      }
+    }
+
+    public MatchModelNode getRoot()
+    {
+      return root;
+    }
+  }
+
+
+  /**
+   *
+   */
+  public interface ElementContentComparator
+  {
+    public boolean isIgnorable(Object o);
+    public boolean isPCData(Object o);
+    public boolean isElement(Object o);
+    public boolean matches(Object o, CMNode cmNode);
+  }
+
+  /**
+   * A linked list
+   */
+  public static class ElementList
+  {
+    protected Object head;
+    protected ElementList tail;
+
+    public static ElementList create(List v)
+    {
+      ElementList first = null;
+      ElementList prev = null;
+
+      for (Iterator iterator = v.iterator(); iterator.hasNext(); )
+      {
+        Object o = iterator.next();
+        if (o != null)
+        {
+          ElementList list = new ElementList();
+          list.head = o;
+
+          if (prev != null)
+          {
+            prev.tail = list;
+          }
+          else
+          {
+            first = list;
+          }
+          prev = list;
+        }
+      }
+      return first;
+    }
+
+
+    public String toString()
+    {
+      String string = "[" + head + "],"; //$NON-NLS-1$ //$NON-NLS-2$
+
+      if (tail != null)
+      {
+        string += tail.toString();
+      }
+
+      return string;
+    }
+  }
+
+  /**
+   * StringElementContentComparator
+   */
+  public static class StringElementContentComparator implements ElementContentComparator
+  {
+    public boolean isIgnorable(Object o)
+    {
+      String string = o.toString();
+      return string.startsWith("!") || string.startsWith("?"); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    public boolean isPCData(Object o)
+    {
+      String string = o.toString();
+      return string.startsWith("'") || string.startsWith("\""); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    public boolean isElement(Object o)
+    {
+      return !isIgnorable(o) && !isPCData(o);
+    }
+
+    public boolean matches(Object o, CMNode cmNode)
+    {
+      boolean result = false;
+      if (cmNode.getNodeType() == CMNode.ELEMENT_DECLARATION)
+      { 
+        CMElementDeclaration element = (CMElementDeclaration)cmNode;
+        String name = o.toString();                              
+        int index = name.indexOf("]"); //$NON-NLS-1$
+        if (index != -1)
+        {
+          name = name.substring(index + 1);
+        }
+        result = name.equalsIgnoreCase(element.getElementName());        
+
+        // TODO... here's we consider substitution groups... revisit to see if this should be moved into validator code
+        if (!result)
+        {
+          CMNodeList cmNodeList = (CMNodeList)element.getProperty("SubstitutionGroup");   //$NON-NLS-1$
+          if (cmNodeList != null)
+          {
+            int cmNodeListLength = cmNodeList.getLength();
+            if (cmNodeListLength > 1)
+            {                        
+              for (int i = 0; i < cmNodeListLength; i++)
+              {                                                               
+                CMElementDeclaration alternativeCMElementDeclaration = (CMElementDeclaration)cmNodeList.item(i);
+                String altName = alternativeCMElementDeclaration.getElementName();
+                result = name.equalsIgnoreCase(altName);
+                if (result)
+                {
+                  break;
+                }
+              }
+            }
+          }
+        }         
+      }   
+      else if (cmNode.getNodeType() == CMNode.ANY_ELEMENT)
+      {                                   
+        String string = o.toString();
+        if (string.equals("*")) //$NON-NLS-1$
+        {
+          result = true;
+        }
+        else
+        {
+          CMAnyElement anyElement = (CMAnyElement)cmNode;
+          String anyElementURI = anyElement.getNamespaceURI();    
+          if (anyElementURI != null)
+          {           
+            if (anyElementURI.equals("##any")) //$NON-NLS-1$
+            {                               
+              result = true;
+            }
+            else if (anyElementURI.equals("##other")) //$NON-NLS-1$
+            {     
+              result = true;    
+              CMDocument cmDocument = (CMDocument)anyElement.getProperty("CMDocument");   //$NON-NLS-1$
+              if (cmDocument != null)
+              {
+                String excludedURI = (String)cmDocument.getProperty("http://org.eclipse.wst/cm/properties/targetNamespaceURI"); //$NON-NLS-1$
+                if (excludedURI != null)
+                { 
+                  String specifiedURI = getURIForContentSpecification(string);
+                  if (specifiedURI != null && excludedURI.equals(specifiedURI))
+                  { 
+                    result = false;
+                  } 
+                }
+              }
+            } 
+            else if (anyElementURI.equals("##targetNamespace")) //$NON-NLS-1$
+            {
+              result = true;
+              CMDocument cmDocument = (CMDocument)anyElement.getProperty("CMDocument");   //$NON-NLS-1$
+              if (cmDocument != null)
+              {     
+                String targetNamespaceURI = (String)cmDocument.getProperty("http://org.eclipse.wst/cm/properties/targetNamespaceURI"); //$NON-NLS-1$
+                String specifiedURI = getURIForContentSpecification(string);
+                if (specifiedURI != null && !targetNamespaceURI.equals(specifiedURI))
+                { 
+                  result = false;
+                } 
+              }
+            }
+            else  
+            {        
+              result = true;
+              String specifiedURI = getURIForContentSpecification(string);
+              if (specifiedURI != null && !anyElementURI.equals(specifiedURI))
+              { 
+                result = false;
+              }      
+            }
+          }  
+          else 
+          {          
+            result = true;
+          }        
+        }
+      }
+      return result;
+    }     
+    
+
+    protected String getURIForContentSpecification(String specification)
+    {           
+      String result = null;
+      int index = specification.indexOf("]"); //$NON-NLS-1$
+      if (index != -1)
+      {                
+        result = specification.substring(1, index);
+      } 
+      return result;  
+    }
+  }      
+
+  public static List createStringList(String arg[], int startIndex)
+  {
+    Vector v = new Vector();
+    for (int i = startIndex; i < arg.length; i++)
+    {
+      v.add(arg[i]);
+    }
+    return v;
+  }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/internal/util/DOMValidator.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/internal/util/DOMValidator.java
new file mode 100644
index 0000000..4a11a27
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/internal/util/DOMValidator.java
@@ -0,0 +1,424 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.internal.util;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAnyElement;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNodeList;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.CMVisitor;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.DOMNamespaceHelper;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.Text;
+
+
+/**
+ * A special CMValidator that knows about DOMs
+ */
+public class DOMValidator extends CMValidator
+{               
+  protected String getNamespaceURI(Node node)
+  {   
+    return DOMNamespaceHelper.getNamespaceURI(node);
+    //return node.getNamespaceURI();
+  }
+          
+
+  //
+  // This is a temporary hack!!
+  //
+  protected String getFallbackNamepaceURI(CMElementDeclaration ed)
+  {   
+    String fallbackNamepaceURI = null;
+    CMDocument cmDocument = (CMDocument)ed.getProperty("CMDocument"); //$NON-NLS-1$
+    if (cmDocument != null)
+    {
+      fallbackNamepaceURI = (String)cmDocument.getProperty("http://org.eclipse.wst/cm/properties/targetNamespaceURI");   //$NON-NLS-1$
+    }  
+    return fallbackNamepaceURI;
+  }
+
+  /**
+   * Encode the Element's NodeList as a List of strings that the validator recognizes
+   */
+  public List createContentSpecificationList(Element element, CMElementDeclaration ed)
+  {                                                                    
+    boolean isNamespaceAware = isNamespaceAware(ed);
+    Vector v = new Vector();         
+    for (Node childNode = element.getFirstChild(); childNode != null; childNode = childNode.getNextSibling())
+    { 
+      v.add(createContentSpecification(childNode, isNamespaceAware, isNamespaceAware ? getFallbackNamepaceURI(ed) : null));
+    }
+    return v;
+  }
+
+
+  public List createContentSpecificationList(List nodeList, CMElementDeclaration ed)
+  {             
+    boolean isNamespaceAware = isNamespaceAware(ed);
+    Vector v = new Vector();            
+ 
+    for (Iterator i = nodeList.iterator(); i.hasNext(); )
+    {
+      Node node = (Node)i.next();
+      v.add(createContentSpecification(node, isNamespaceAware, getFallbackNamepaceURI(ed)));
+    }
+    return v;
+  }
+
+
+  /**
+   * Encode the Node as a string that the validator recognizes
+   */
+  public String createContentSpecification(Node node, boolean isNamespaceAware, String fallbackNamepaceURI)
+  {
+    String result = "!"; //$NON-NLS-1$
+    switch (node.getNodeType())
+    {
+      case Node.ELEMENT_NODE :
+      {  
+        String nodeName = node.getNodeName();  
+        if (nodeName.startsWith("jsp:")) //$NON-NLS-1$
+        {  
+          result = "!"; // treat it as a comment so that it's ignored by the validator //$NON-NLS-1$
+        }
+        else
+        {
+          if (isNamespaceAware)
+          {
+            result = DOMNamespaceHelper.getUnprefixedName(nodeName);
+            String uri = getNamespaceURI(node);
+            if (uri != null)
+            {
+              result = "[" + uri + "]" + result;    //$NON-NLS-1$ //$NON-NLS-2$
+            } 
+            else if (fallbackNamepaceURI != null)
+            {
+              result = "[" + fallbackNamepaceURI + "]" + result;   //$NON-NLS-1$ //$NON-NLS-2$
+            }
+          }  
+          else
+          {
+            result = nodeName;
+          }
+        }        
+        //ContentModelManager.println("result " + result);
+        break;
+      }
+      case Node.PROCESSING_INSTRUCTION_NODE :
+      {
+        result = "?"; //$NON-NLS-1$
+        break;
+      }
+      case Node.COMMENT_NODE :
+      {
+        result = "!"; //$NON-NLS-1$
+        break;
+      }
+      case Node.CDATA_SECTION_NODE :
+      {
+        result = "\"" + node.getNodeName() + "\""; //$NON-NLS-1$ //$NON-NLS-2$
+        break;
+      }
+      case Node.TEXT_NODE :
+      {
+        String data = ((Text)node).getData();
+        // here we test to see if the test node is 'ignorable'
+        if (data != null && data.trim().length() > 0)
+        {
+          result = "\"" + node.getNodeName() + "\""; //$NON-NLS-1$ //$NON-NLS-2$
+        }
+        else
+        {
+          result = "!"; // todo... use another symbol? //$NON-NLS-1$
+        }
+        break;
+      }
+    }
+    return result;
+  }
+
+
+  /**
+   *
+   */
+  public List createContentSpecificationList(CMNode cmNode)
+  {
+    List list = new Vector();
+    switch (cmNode.getNodeType())
+    {
+      case CMNode.ELEMENT_DECLARATION :
+      {         
+        list.add(createContentSpecificationForCMElementDeclaration((CMElementDeclaration)cmNode));   
+        break;
+      }
+      case CMNode.DATA_TYPE :
+      {
+        list.add("\"" + cmNode.getNodeName() + "\""); //$NON-NLS-1$ //$NON-NLS-2$
+        break;
+      }
+      case CMNode.GROUP :
+      {
+        createContentSpecificationListForCMGroup((CMGroup)cmNode, list);
+        break;
+      }
+      case CMNode.ANY_ELEMENT :
+      {
+        list.add("*"); //$NON-NLS-1$
+        break;
+      }
+      default :
+      {
+        list.add("!"); //$NON-NLS-1$
+      }
+    }
+    return list;
+  }
+     
+
+  /**
+   * 
+   */              
+  protected String createContentSpecificationForCMElementDeclaration(CMElementDeclaration ed)
+  {  
+    CMDocument document = (CMDocument)ed.getProperty("CMDocument"); //$NON-NLS-1$
+    String uri = document != null ? (String)document.getProperty("http://org.eclipse.wst/cm/properties/targetNamespaceURI") : null; //$NON-NLS-1$
+    String string = ed.getNodeName();
+    if (uri != null)
+    {            
+      string = "[" + uri + "]" + string; //$NON-NLS-1$ //$NON-NLS-2$
+    }
+    return string;
+  }
+  
+  /**
+   *
+   */
+  protected void createContentSpecificationListForCMGroup(CMGroup group, List list)
+  {         
+    CMGroupContentVisitor visitor = new CMGroupContentVisitor(group, list);
+    visitor.visitCMNode(group);
+  } 
+     
+  protected class CMGroupContentVisitor extends CMVisitor
+  {  
+    protected CMGroup root;                             
+    protected List list;
+
+    public CMGroupContentVisitor(CMGroup root, List list)
+    {                                        
+      this.root = root;        
+      this.list = list;
+    }
+
+    public void visitCMElementDeclaration(CMElementDeclaration ed)
+    {           
+      if (ed.getMinOccur() > 0)
+      {
+        list.add(createContentSpecificationForCMElementDeclaration(ed));
+      }
+    }       
+
+    public void visitCMAnyElement(CMAnyElement anyElement)
+    {   
+      list.add("*"); //$NON-NLS-1$
+    }
+
+    public void visitCMGroup(CMGroup group)
+    {                              
+      if (group == root || group.getMinOccur() > 0)
+      {
+        int op = group.getOperator();
+        if (op == CMGroup.SEQUENCE)
+        {
+          super.visitCMGroup(group);
+        }
+        else if (op == CMGroup.CHOICE)
+        {
+          CMNodeList nodeList = group.getChildNodes();
+          if (nodeList.getLength() > 0)
+          {
+            visitCMNode(nodeList.item(0));
+          }      
+        }
+      }
+    }
+  }
+
+  public boolean isNamespaceAware(CMElementDeclaration ed)
+  { 
+    return ed != null ? ed.getProperty("http://org.eclipse.wst/cm/properties/isNameSpaceAware") != null : false; //$NON-NLS-1$
+  }
+     
+  /**
+   *
+   */
+  public CMNode[] getOriginArray(CMElementDeclaration ed, Element element)
+  {
+    ElementPathRecordingResult result = new ElementPathRecordingResult();
+    getOriginArray(ed, createContentSpecificationList(element, ed), stringContentComparitor, result);
+    return result.getOriginArray();
+  }
+                   
+  /**
+   *
+   */
+  public MatchModelNode getMatchModel(CMElementDeclaration ed, Element element)
+  {
+    MatchModelNode matchModelNode = null;
+    PathRecordingResult result = new PathRecordingResult();
+    validate(ed, createContentSpecificationList(element, ed), stringContentComparitor, result);
+    if (result.isValid)
+    {
+      matchModelNode = result.getMatchModel();
+    }
+    return matchModelNode;
+  }
+                           
+
+  public List clone(List list)
+  {   
+    List result = new Vector(list.size());
+    result.addAll(list);
+    return result;
+  }
+ 
+  /**
+   *
+   */
+  public boolean canInsert(CMElementDeclaration ed, List contentSpecificationList, int insertIndex, CMNode cmNode)
+  {           
+    List clonedList = clone(contentSpecificationList);
+    insert(clonedList, insertIndex, cmNode);
+    boolean result = isPartiallyValid(ed, clonedList);   
+    return result;
+  }  
+
+  /**
+   *
+   */
+  public boolean canInsert(CMElementDeclaration ed, List contentSpecificationList, int insertIndex, List cmNodeList)
+  {              
+    List clonedList = clone(contentSpecificationList);
+    insert(clonedList, insertIndex, cmNodeList);
+    return isValid(ed, clonedList);
+  }  
+
+  /**
+   *
+   */
+  public boolean canRemove(CMElementDeclaration ed, List contentSpecificationList, int startRemoveIndex)
+  {
+    return canRemove(ed, contentSpecificationList, startRemoveIndex, startRemoveIndex);
+  }
+
+  /**
+   *
+   */
+  public boolean canRemove(CMElementDeclaration ed, List contentSpecificationList, int startRemoveIndex, int endRemoveIndex)
+  {
+    List clonedList = clone(contentSpecificationList);
+    remove(clonedList, startRemoveIndex, endRemoveIndex);
+    return isValid(ed, clonedList);
+  }
+                        
+  /**
+   *
+   */
+  public boolean canReplace(CMElementDeclaration ed, List contentSpecificationList, int startRemoveIndex, int endRemoveIndex, CMNode cmNode)
+  {
+    List clonedList = clone(contentSpecificationList);
+    remove(clonedList, startRemoveIndex, endRemoveIndex); 
+    insert(clonedList, startRemoveIndex, cmNode);
+    return isValid(ed, clonedList);
+  }
+
+  /**
+   *
+   */                      
+  public boolean isValid(CMElementDeclaration ed, List contentSpecificationList)
+  {
+    Result result = new Result();
+    validate(ed, contentSpecificationList, stringContentComparitor, result);
+    return result.isValid;
+  }
+
+  public boolean isPartiallyValid(CMElementDeclaration ed, List contentSpecificationList)
+  {
+    CMValidator.ElementPathRecordingResult result = new CMValidator.ElementPathRecordingResult();
+    validate(ed, contentSpecificationList, stringContentComparitor, result);
+    int count = getElementCount(contentSpecificationList);
+    //System.out.println("elementOriginList " + result.getPartialValidationCount() + "vs" + count);
+    return result.getPartialValidationCount() >= count;
+  }  
+  
+  public int getElementCount(List contentSpecificationList)
+  {
+    int count = 0;
+    for (Iterator i = contentSpecificationList.iterator(); i.hasNext(); )
+    {
+      if (stringContentComparitor.isElement(i.next()))
+      {
+        count++;
+      }  
+    }  
+    return count;
+  }
+
+  protected Result validate(CMElementDeclaration ed, Element element)
+  {
+    Result result = new Result();
+    validate(ed, createContentSpecificationList(element, ed), stringContentComparitor, result);
+    return result;
+  }
+
+
+  protected void remove(List stringList, int startRemoveIndex, int endRemoveIndex)
+  {
+    if (startRemoveIndex != -1)
+    {
+      for (int i = startRemoveIndex; i <= endRemoveIndex; i++)
+      {
+        stringList.remove(i);
+      }
+    }
+  }
+
+  protected void insert(List stringList, int insertIndex, CMNode cmNode)
+  {
+    if (insertIndex != -1)
+    {
+      stringList.addAll(insertIndex, createContentSpecificationList(cmNode));
+    }
+  }
+
+  protected void insert(List stringList, int insertIndex, List cmNodeList)
+  {
+    if (insertIndex != -1)
+    {
+      int insertListSize = cmNodeList.size();
+      for (int i = insertListSize - 1; i >= 0; i--)
+      {
+        CMNode cmNode = (CMNode)cmNodeList.get(i);
+        stringList.addAll(insertIndex, createContentSpecificationList(cmNode));
+      }
+    }
+  }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelquery/CMDocumentManager.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelquery/CMDocumentManager.java
new file mode 100644
index 0000000..6fbee2a
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelquery/CMDocumentManager.java
@@ -0,0 +1,141 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.modelquery;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.CMDocumentCache;
+
+
+/**
+ * The CMDocumentManager can be visualized as a table of CMDocument
+ * references, each with a corresponding entry in a CMDocument cache. The
+ * CMDocumentManager also performs the task of loading CMDocuments providing
+ * support for synchronous and asynchronous loading.
+ * 
+ * publicIdTable CMDocumentCache ---------------------------
+ * --------------------------------------- | publicId | resolvedURI | -> |
+ * resolvedURI | status | CMDocument | ---------------------------
+ * --------------------------------------- | (null) | file:/x.dtd | |
+ * file:/x.dtd | loading | (null) | ---------------------------
+ * --------------------------------------- | http:/... | file:/y.xsd | |
+ * file:/y.xsd | loaded | | ---------------------------
+ * ---------------------------------------
+ * 
+ */
+public interface CMDocumentManager {
+	/**
+	 * This property specifies WHEN CMDocuments are loaded. Setting this
+	 * property to true allows the CMDocumentManager to load CMDocuments on
+	 * demand. Settings this property a false puts the onus on the client to
+	 * call addCMDocumentReference() to explicity trigger a load. This allows
+	 * the client to control exactly when loading should take place. )
+	 */
+	public static final String PROPERTY_AUTO_LOAD = "autoLoad"; //$NON-NLS-1$
+
+	/**
+	 * This property specifies HOW CMDocuments are loaded. When set to false,
+	 * the getCMDocument() method will load the CMDocument synchronously and
+	 * return a CMDocument object when loading is successful. When set to
+	 * true, the getCMDocument() will load the CMDocument asynchronously and
+	 * will immediately return null. When loading is complete, the
+	 * CMDocumentManager will inform its listeners that the CMDocument has
+	 * been loaded.
+	 */
+	public static final String PROPERTY_ASYNC_LOAD = "asyncLoad"; //$NON-NLS-1$
+
+	/**
+	 * 
+	 */
+	public static final String PROPERTY_USE_CACHED_RESOLVED_URI = "useCachedResovledURI"; //$NON-NLS-1$
+
+	/**
+	 * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=136399
+	 * Allows a client to control whether the document manager attempts to resolve a
+	 * CM document's URI. When set to false, the CM systemID will be assumed to point
+	 * to an already resolved URI. By default this property is set to true.
+	 */
+	public static final String PROPERTY_PERFORM_URI_RESOLUTION = "performURIResolution"; //$NON-NLS-1$
+	
+	/**
+	 * Set the enabled state of a property.
+	 */
+	public void setPropertyEnabled(String propertyName, boolean enabled);
+
+	/**
+	 * Get the enabled state of the property.
+	 */
+	public boolean getPropertyEnabled(String propertyName);
+
+	/**
+	 * Adds a listener. Listeners should expect to receive call backs on a
+	 * secondary thread when asynchronously loading is used.
+	 */
+	public void addListener(CMDocumentManagerListener listener);
+
+	/**
+	 * Removes a listener.
+	 */
+	public void removeListener(CMDocumentManagerListener listener);
+
+	/**
+	 * Lookup or create a CMDocument (depending on PROPERTY_AUTO_LOAD).
+	 * 
+	 * @param publicId
+	 * @param systemId
+	 * @param type -
+	 *            'dtd', 'xsd', 'tld', etc. if null is given as the type, then
+	 *            the type is calculated as last segment (e.g. file extension)
+	 *            of the resolved URI
+	 * @return
+	 */
+	public CMDocument getCMDocument(String publicId, String systemId, String type);
+
+	/**
+	 * Lookup a CMDocument.
+	 */
+	public CMDocument getCMDocument(String publicId);
+
+	/**
+	 * Get the status of a CMDocument.
+	 */
+	public int getCMDocumentStatus(String publicId);
+
+	/**
+	 * Creates a CMDocument and adds the associated CMDocument reference
+	 * information to the table. Calling this method always triggers a
+	 * CMDocument load.
+	 */
+	public void addCMDocumentReference(String publicId, String systemId, String type);
+
+	/**
+	 * Add an existingCMDocument and the reference information to the table.
+	 */
+	public void addCMDocument(String publicId, String systemId, String resolvedURI, String type, CMDocument cmDocument);
+
+	/**
+	 * Remove all entries from the table.
+	 */
+	public void removeAllReferences();
+
+	/**
+	 * Get the CMDocumentCache that is used to store loaded CMDocuments and
+	 * associated status.
+	 */
+	public CMDocumentCache getCMDocumentCache();
+
+	/**
+	 * Builds a CMDocument given a resoulvedURI. Note that no entries are
+	 * added to the table.
+	 */
+	public CMDocument buildCMDocument(String publicId, String resolvedURI, String type);
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelquery/CMDocumentManagerListener.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelquery/CMDocumentManagerListener.java
new file mode 100644
index 0000000..bd607dc
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelquery/CMDocumentManagerListener.java
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.modelquery;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.util.CMDocumentCacheListener;
+
+/**
+ *
+ */
+public interface CMDocumentManagerListener extends CMDocumentCacheListener
+{                    
+  public void propertyChanged(CMDocumentManager cmDocumentManager, String propertyName);
+}       
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelquery/CMDocumentReference.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelquery/CMDocumentReference.java
new file mode 100644
index 0000000..1d57f46
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelquery/CMDocumentReference.java
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.modelquery;
+
+
+public interface CMDocumentReference
+{
+  public String getPublicId();
+  public String getSystemId();
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelquery/CMDocumentReferenceProvider.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelquery/CMDocumentReferenceProvider.java
new file mode 100644
index 0000000..d7dc8bf
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelquery/CMDocumentReferenceProvider.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.modelquery;
+
+import java.util.List;
+
+import org.w3c.dom.Node;
+ 
+/**
+ * The interface is used to abstract the task of computing the document references associated with a DOM
+ * or a particular node within the DOM.  
+ */
+public interface CMDocumentReferenceProvider
+{
+  List getCMDocumentReferences(Node node, boolean deep);
+  String resolveGrammarURI(String publicId, String systemId);
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelquery/IExternalSchemaLocationProvider.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelquery/IExternalSchemaLocationProvider.java
new file mode 100644
index 0000000..4ce7583
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelquery/IExternalSchemaLocationProvider.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.modelquery;
+
+import java.net.URI;
+import java.util.Map;
+
+public interface IExternalSchemaLocationProvider {
+	String SCHEMA_LOCATION = "http://apache.org/xml/properties/schema/external-schemaLocation"; //$NON-NLS-1$
+	String NO_NAMESPACE_SCHEMA_LOCATION = "http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation"; //$NON-NLS-1$
+
+	/**
+	 * Provided the file path URI, this will return the external schema location. The schema location is associated to a specific property,
+	 * which serves as the key in the map. The supported properties are:
+	 * 
+	 * <p><b>http://apache.org/xml/properties/schema/external-schemaLocation</b> - The value for this property follows the same rules
+	 * as the schemaLocation attribute for an XML document (i.e., multiple schemas are acceptable and must be white-space separated).</p>
+	 * 
+	 * <p><b>http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation</b> - The value for this property follows the same
+	 * rules as the noNamespaceSchemaLocation attribute for an XML document (i.e., only one schema is allowed).
+	 * 
+	 * @param filePath the path for the XML file
+	 * @return a {@link Map} associating the external-schemaLocation and/or external-noNamespaceSchemaLocation to the schema location
+	 */
+	Map getExternalSchemaLocation(URI fileURI);
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelquery/ModelQuery.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelquery/ModelQuery.java
new file mode 100644
index 0000000..5d300e8
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelquery/ModelQuery.java
@@ -0,0 +1,195 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.modelquery;
+
+import java.util.List;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.extension.ModelQueryExtensionManager;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+
+/**
+ * This class provides an interface for performing higher level queries based on
+ * a xml model (DOM) and one or more associated content models (CMDocument).
+ *
+ * The queries provided can be organized into three groups:
+ *
+ * 1) DOM Node to CMNode mapping
+ *      Given a grammatically valid DOM Node the corresponding CMNode can be determined.
+ *      (i.e. Element -> CMElementDeclaration, Attr -> CMAttributeDeclaration, CharacterData -> CMDataType)
+ *
+ * 2) DOM editing tests ("Can I do this?")
+ *      Questions such as canInsert, canRemove, canReplace can assist in the editing of a DOM.
+ *
+ *      The validityChecking argument determines the strictness of the validity testing that occurs.
+ *
+ *      - VALIDITY_NONE    : The current content of the Element is ignored.
+ *                           Only the content model is considered.
+ *                           This is most useful for codeassist related queries.
+ *
+ *      - VALIDITY_STRICT  : The current content of the Element is considered.
+ *                           Returns true only if the operation preserves content validity.
+ *                           This is useful when DOM editing needs to be constrained to maintain validity.
+ *
+ *      - VALIDITY_PARTIAL : Some optimized compromise between the two options above.
+ *
+ * 3) DOM editing actions ("What can I do here?")
+ *      These methods return ModelQueryActions that are relevant at some specified DOM Node.
+ *      The actions indicate what kinds of DOM Node can be inserted where (at what index).
+ */
+public interface ModelQuery
+{
+  public static final int VALIDITY_NONE = 0;
+  public static final int VALIDITY_PARTIAL = 1;
+  public static final int VALIDITY_STRICT = 2;
+
+  public static final int INCLUDE_ALL = 0xFF;
+  public static final int INCLUDE_ATTRIBUTES = 0x01;
+  public static final int INCLUDE_CHILD_NODES = 0x02;
+  public static final int INCLUDE_SEQUENCE_GROUPS = 0x04;
+  public static final int INCLUDE_TEXT_NODES = 0x08;
+  public static final int INCLUDE_ENCLOSING_REPLACE_ACTIONS = 0x10;
+
+  public static final int EDIT_MODE_UNCONSTRAINED = 0;
+  public static final int EDIT_MODE_CONSTRAINED_LENIENT= 1;
+  public static final int EDIT_MODE_CONSTRAINED_STRICT = 2;
+
+
+  void setEditMode(int editMode);
+
+  int  getEditMode();
+
+  /**
+   * Returns the CMDocument that corresponds to the DOM Node.
+   * or null if no CMDocument is appropriate for the DOM Node.
+   */
+  CMDocument getCorrespondingCMDocument(Node node);
+
+  /**
+   * Returns the corresponding CMNode for the DOM Node
+   * or null if no CMNode is appropriate for the DOM Node.
+   */
+  CMNode getCMNode(Node node);
+
+  /**
+   * Returns the corresponding CMAttribute for the DOM Node
+   * or null if no CMNode is appropriate for the DOM Node.
+   */
+  CMAttributeDeclaration getCMAttributeDeclaration(Attr attr);
+
+  /**
+   * Returns the corresponding CMAttribute for the DOM Node
+   * or null if no CMNode is appropriate for the DOM Node.
+   */
+  CMElementDeclaration getCMElementDeclaration(Element element);
+
+  /**
+   * Returns true if the content of the element is valid
+   */
+  boolean isContentValid(Element element);
+
+  /**
+   * Returns the CMNode of the parent element's content model
+   * that corresponds to the node
+   */
+  CMNode getOrigin(Node node);
+
+  /**
+   * Returns an array of CMNodes of the parent element's content model
+   * that corresponds to the node
+   */
+  CMNode[] getOriginArray(Element element);
+
+  /**
+   * Returns a list of all CMNode 'meta data' that may be potentially added to the element.
+   */
+  List getAvailableContent(Element element, CMElementDeclaration ed, int includeOptions);
+
+  /**
+   * Can a DOM Node corresponding to the CMNode 'meta data' be added to the parent
+   */
+  boolean canInsert(Element parent, CMNode cmNode, int index, int validityChecking);
+
+  /**
+   * Can multiple DOM Nodes corresponding to the list of CMNode 'meta data' be added to the parent
+   */
+  boolean canInsert(Element parent, List cmNodeList, int index, int validityChecking);
+
+  /**
+   * Can the DOM Node be removed
+   */
+  boolean canRemove(Node node, int validityChecking);
+
+  /**
+   * Can the list of DOM Nodes be removed
+   */
+  boolean canRemove(List nodeList, int validityChecking);
+
+  /**
+   * Can the children within the indicated indices be replaced with a DOM Node corresponding to the CMNode 'meta data'
+   */
+  boolean canReplace(Element parent, int startIndex, int endIndex, CMNode cmNode, int validityChecking);
+
+  /**
+   * Can the children within the indicated indices be replaced with multiple DOM Nodes corresponding to the list of CMNode 'meta data'
+   */
+  boolean canReplace(Element parent, int startIndex, int endIndex, List cmNodeList, int validityChecking);
+
+  /**
+   *
+   */
+  void getInsertActions(Element parent, CMElementDeclaration ed, int index, int includeOptions, int validityChecking, List actionList);
+
+  /**
+   *
+   */
+  void getInsertActions(Document parent, CMDocument cmDocument, int index, int includeOptions, int validityChecking, List actionList);
+
+  /**
+   * Return a list of replace actions that can be performed on the parent's content
+   */
+  void getReplaceActions(Element parent, CMElementDeclaration ed, int includeOptions, int validityChecking, List actionList);
+
+  /**
+   * Return a list of replace actions that can be performed on the selected children of that parent 
+   */
+  void getReplaceActions(Element parent, CMElementDeclaration ed, List selectedChildren, int includeOptions, int validityChecking, List actionList);
+
+                        
+  /** 
+   *  @deprecated - use getPossibleDataTypeValues()
+   */
+  List getDataTypeValues(Element element, CMNode cmNode);
+
+  /**
+   * This methods return an array of possible values corresponding to the datatype of the CMNode (either an CMAttributeDeclaration or a CMElementDeclaration)
+   */
+  String[] getPossibleDataTypeValues(Element element, CMNode cmNode);
+
+  /**
+   * This method may return null if a CMDocumentManager is not used by the ModelQuery
+   */
+  CMDocumentManager getCMDocumentManager();                                       
+
+  /**
+   * This method may return null the ModelQuery doesn't support the use of extensions
+   */
+  ModelQueryExtensionManager getExtensionManager();   
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelquery/ModelQueryAction.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelquery/ModelQueryAction.java
new file mode 100644
index 0000000..059c4ff
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelquery/ModelQueryAction.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.modelquery;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.w3c.dom.Node;
+
+
+public interface ModelQueryAction
+{
+  public static final int INSERT  = 1;
+  public static final int REMOVE  = 2;
+  public static final int REPLACE = 4;
+
+  public int getKind();
+  /**
+   * if start index == -1 then no insert is possible
+   * if start index != -1 and endIndex == -1 then an insert at any position is possible
+   */
+  public int getStartIndex();
+  public int getEndIndex();
+  public Node getParent();
+  public CMNode getCMNode();
+  public Object getUserData();
+  public void setUserData(Object object);
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelquery/ModelQueryAssociationProvider.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelquery/ModelQueryAssociationProvider.java
new file mode 100644
index 0000000..7777756
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelquery/ModelQueryAssociationProvider.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.modelquery;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.Text;
+
+
+/**
+ * 
+ *
+ */
+public interface ModelQueryAssociationProvider extends ModelQueryCMProvider
+{
+  public CMNode getCMNode(Node node);
+  public CMDataType getCMDataType(Text text); 
+  public CMAttributeDeclaration getCMAttributeDeclaration(Attr attr);
+  public CMElementDeclaration getCMElementDeclaration(Element element);
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelquery/ModelQueryCMProvider.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelquery/ModelQueryCMProvider.java
new file mode 100644
index 0000000..f0f9373
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelquery/ModelQueryCMProvider.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.modelquery;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.w3c.dom.Node;
+
+
+
+/**
+ *
+ */
+public interface ModelQueryCMProvider
+{
+  /**
+   * Returns the CMDocument that corresponds to the DOM Node.
+   * or null if no CMDocument is appropriate for the DOM Node.
+   */
+  CMDocument getCorrespondingCMDocument(Node node);
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelquery/extension/ModelQueryExtension.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelquery/extension/ModelQueryExtension.java
new file mode 100644
index 0000000..b417f56
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelquery/extension/ModelQueryExtension.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2008 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.modelquery.extension;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+public abstract class ModelQueryExtension
+{  
+  protected static final String[] EMPTY_STRING_ARRAY = {};
+  protected static final CMNode[] EMPTY_CMNODE_ARRAY = {};
+  
+  /**
+ * @param ownerElement - the owner element
+ * @param namespace - the active namespace
+ * @param name - the name of an attribute node
+ * @return valid values for the given attribute
+ */
+public String[] getAttributeValues(Element ownerElement, String namespace, String name)
+  {
+    return EMPTY_STRING_ARRAY;
+  }
+  
+  public String[] getElementValues(Node parentNode, String namespace, String name)
+  {
+    return EMPTY_STRING_ARRAY;
+  }
+  
+  /**
+ * @param parentNode
+ * @param namespace
+ * @param name
+ * @return whether a child element of the given parentNode is valid given the active namespace
+ */
+public boolean isApplicableChildElement(Node parentNode, String namespace, String name)
+  {
+    return true;
+  }
+  
+  /**
+ * @param parentElement - the parent Element when asking for children, the owner Element when asking for attributes 
+ * @param namespace - the active namespace
+ * @param includeOptions - ModelQuery.INCLUDE_ATTRIBUTES or ModelQuery.INCLUDE_CHILD_NODES
+ * @return additional valid CMAttributeDeclarations or CMElementDeclarations 
+ */
+public CMNode[] getAvailableElementContent(Element parentElement, String namespace, int includeOptions) 
+  {
+	  return EMPTY_CMNODE_ARRAY;
+  }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelquery/extension/ModelQueryExtensionManager.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelquery/extension/ModelQueryExtensionManager.java
new file mode 100644
index 0000000..31c440f
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelquery/extension/ModelQueryExtensionManager.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2008 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.modelquery.extension;
+
+import java.util.List;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.w3c.dom.Element;
+
+
+
+public interface ModelQueryExtensionManager
+{
+  List getDataTypeValues(Element element, CMNode cmNode);                             
+
+  void filterAvailableElementContent(List availableContent, Element element, CMElementDeclaration ed);
+
+  void filterAvailableElementContent(List availableContent, Element element, CMElementDeclaration ed, int includeOptions);
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelqueryimpl/BaseAssociationProvider.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelqueryimpl/BaseAssociationProvider.java
new file mode 100644
index 0000000..54242f6
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelqueryimpl/BaseAssociationProvider.java
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.modelqueryimpl;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQueryAssociationProvider;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.Text;
+
+
+/**
+ *
+ */
+public abstract class BaseAssociationProvider implements ModelQueryAssociationProvider
+{                    
+  public BaseAssociationProvider()
+  {
+  }
+
+  public CMNode getCMNode(Node node)
+  {
+    CMNode result = null;
+    switch (node.getNodeType())
+    {
+      case Node.ATTRIBUTE_NODE :
+      {
+        result = getCMAttributeDeclaration((Attr)node);
+        break;
+      }
+      case Node.ELEMENT_NODE :
+      {
+        result = getCMElementDeclaration((Element)node);
+        break;
+      }
+      case Node.CDATA_SECTION_NODE :
+      case Node.TEXT_NODE :
+      {
+        result = getCMDataType((Text)node);
+        break;
+      }
+    }
+    return result;
+  }
+
+
+  public CMDataType getCMDataType(Text text)
+  {
+    CMDataType result = null;
+    Node parentNode = text.getParentNode();
+    if (parentNode != null && parentNode.getNodeType() == Node.ELEMENT_NODE)
+    {
+      CMElementDeclaration ed = getCMElementDeclaration((Element)parentNode);
+      result = ed.getDataType();
+    }
+    return result;
+  }
+
+
+  public CMAttributeDeclaration getCMAttributeDeclaration(Attr attr)
+  {
+    CMAttributeDeclaration result = null;
+    Element element = attr.getOwnerElement();
+    if (element != null)
+    {
+      CMElementDeclaration ed = getCMElementDeclaration(element);
+      if (ed != null)
+      {
+        result = (CMAttributeDeclaration)ed.getAttributes().getNamedItem(attr.getName());
+      }
+    }
+    return result;
+  }          
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelqueryimpl/CMDocumentLoader.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelqueryimpl/CMDocumentLoader.java
new file mode 100644
index 0000000..a5937ae
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelqueryimpl/CMDocumentLoader.java
@@ -0,0 +1,278 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2011 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.modelqueryimpl;
+                          
+import java.io.File;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.wst.sse.core.utils.StringUtils;
+import org.eclipse.wst.xml.core.internal.Logger;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.CMDocumentManager;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.IExternalSchemaLocationProvider;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.CMDocumentCache;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.NamespaceInfo;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.NamespaceTable;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+
+/**
+ *
+ */
+public class CMDocumentLoader
+{                                           
+  private final static boolean _trace = Boolean.valueOf(Platform.getDebugOption("org.eclipse.wst.xml.core/externalSchemaLocation")).booleanValue(); //$NON-NLS-1$
+  protected Document document;
+  protected ModelQuery modelQuery;
+  protected CMDocumentManager cmDocumentManager;
+  protected boolean isInferredGrammarEnabled = true;  
+  protected CMDocumentLoadingNamespaceTable namespaceTable;
+  protected int count = 0;
+    
+  public CMDocumentLoader(Document document, ModelQuery modelQuery)
+  {                             
+    this(document, modelQuery.getCMDocumentManager());
+  }
+  
+  public CMDocumentLoader(Document document, CMDocumentManager cmDocumentManager)
+  {   
+    this.document = document;                     
+    this.cmDocumentManager = cmDocumentManager;  	
+  }
+  
+  public void loadCMDocuments()
+  {          
+    //System.out.println("----------loadCMDocuments ------------");          
+    //long time = System.currentTimeMillis();
+       
+    boolean walkDocument = false;
+            
+    cmDocumentManager.removeAllReferences();
+      
+    String[] doctypeInfo = XMLAssociationProvider.getDoctypeInfo(document);
+    if (doctypeInfo != null)
+    {
+      // load the doctype if required
+      walkDocument = handleGrammar(doctypeInfo[0], doctypeInfo[1], "DTD"); //$NON-NLS-1$
+    }                                   
+    else
+    {                           
+      Element element = getRootElement(document);
+      if (element != null)
+      {
+        namespaceTable = new CMDocumentLoadingNamespaceTable(document);   
+        namespaceTable.addElement(element);
+        if (namespaceTable.isNamespaceEncountered())
+        {   
+          walkDocument = true;
+          //System.out.println("isNamespaceAware");
+        }
+        else
+        {
+          namespaceTable = null;
+          walkDocument = isInferredGrammarEnabled;
+          //System.out.println("is NOT namespaceAware");
+        }        
+      }
+    } 
+
+    if (walkDocument)
+    {
+    	if (!checkExternalSchema())
+    		visitNode(document);   
+    } 
+
+    //System.out.println("--- elapsed time (" + count + ") = " + (System.currentTimeMillis() - time));
+  }
+
+  protected boolean checkExternalSchema() {
+	  boolean externalSchemaLoaded = false;
+	  if (document instanceof IDOMDocument) {
+		  final String baseLocation = ((IDOMDocument) document).getModel().getBaseLocation();
+		  if (baseLocation == null)
+			  return false;
+		  final IPath basePath = new Path(baseLocation);
+		  IFile file = null;
+		  if (basePath.segmentCount() > 1) {
+			  file = ResourcesPlugin.getWorkspace().getRoot().getFile(basePath);
+		  }
+		  final URI uri = (file == null || !file.isAccessible()) ? new File(baseLocation).toURI() : file.getLocationURI();
+		  if (uri != null) {
+			  IExternalSchemaLocationProvider[] providers = ExternalSchemaLocationProviderRegistry.getInstance().getProviders();
+			  for (int i = 0; i < providers.length; i++) {
+				  long time = _trace ? System.currentTimeMillis(): 0;
+				  final Map locations = providers[i].getExternalSchemaLocation(uri);
+				  if (_trace) {
+					  long diff = System.currentTimeMillis() - time;
+					  if (diff > 250)
+						  Logger.log(Logger.INFO, "Schema location provider took [" + diff + "ms] for URI [" + uri + "]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+				  }
+				  if (locations != null && !locations.isEmpty()) {
+					  // Use the externalSchemaLocation
+					  if (namespaceTable != null && namespaceTable.isNamespaceEncountered()) {
+						  final String location = locations.get(IExternalSchemaLocationProvider.SCHEMA_LOCATION).toString();
+						  if (location != null) {
+							  final String[] ids = StringUtils.asArray(location);
+							  // namespace : location pairs
+							  if (ids.length >= 2 && ids.length % 2 == 0) {
+								  if (!externalSchemaLoaded)
+									  cmDocumentManager.removeAllReferences();
+								  for (int j = 0; j < ids.length; j+=2) {
+									  handleGrammar(ids[j], ids[j + 1], "XSD"); //$NON-NLS-1$
+									  externalSchemaLoaded = true;
+								  }
+							  }
+						  }
+					  }
+					  else { // noNamespace
+						  handleGrammar(uri.toString(), locations.get(IExternalSchemaLocationProvider.NO_NAMESPACE_SCHEMA_LOCATION).toString(), "XSD"); //$NON-NLS-1$
+						  externalSchemaLoaded = true;
+						  break;
+					  }
+				  }
+			  }
+		  }
+	  }
+	  return externalSchemaLoaded;
+  }
+
+  public boolean handleGrammar(String publicId, String systemId, String type)
+  {           
+    boolean result = false;
+    
+    int status = cmDocumentManager.getCMDocumentStatus(publicId);
+    if (status == CMDocumentCache.STATUS_NOT_LOADED)
+    {
+      cmDocumentManager.addCMDocumentReference(publicId, systemId, type);
+    }                 
+    else if (status == CMDocumentCache.STATUS_ERROR)
+    {
+      result = true;
+    }
+    return result;
+  } 
+    
+
+  public void handleElement(Element element)
+  {  
+    visitChildNodes(element);
+  }
+
+                             
+  public void handleElementNS(Element element)
+  {
+    namespaceTable.addElement(element);
+    visitChildNodes(element);
+  }
+                                                    
+
+  public void visitNode(Node node)
+  {                    
+    int nodeType = node.getNodeType();
+    if (nodeType == Node.ELEMENT_NODE)
+    {
+      count++;       
+
+      Element element = (Element)node;    
+      if (namespaceTable == null)
+      {
+        handleElement(element); 
+      }
+      else
+      {
+        handleElementNS(element);
+      }            
+    }
+    else if (nodeType == Node.DOCUMENT_NODE)
+    {
+      visitChildNodes(node);
+    }
+  }
+
+
+  protected void visitChildNodes(Node node)
+  {   
+	  for (Node child = node.getFirstChild(); child != null; child = child.getNextSibling()) 
+    {
+	    visitNode(child);
+    }
+	}             
+
+
+  protected class CMDocumentLoadingNamespaceTable extends NamespaceTable
+  {                                        
+    protected List newNamespaceList;
+
+    public CMDocumentLoadingNamespaceTable(Document document)
+    {                                                          
+      super(document);     
+    }  
+                                           
+
+    public void addElement(Element element)
+    {                               
+      newNamespaceList = null;
+      super.addElement(element);  
+      if (newNamespaceList != null)
+      {
+        for (Iterator i = newNamespaceList.iterator(); i.hasNext(); )
+        {
+          NamespaceInfo info = (NamespaceInfo)i.next();
+          handleGrammar(info.uri, info.locationHint, "XSD"); //$NON-NLS-1$
+        }
+      }
+    }                 
+     
+                               
+    protected void internalAddNamespaceInfo(String key, NamespaceInfo info)
+    {
+      super.internalAddNamespaceInfo(key, info);           
+      if (newNamespaceList == null)
+      {
+        newNamespaceList = new ArrayList();
+      }
+      newNamespaceList.add(info);    
+    }                     
+  }
+
+  
+  protected Element getRootElement(Document document)
+  {
+    Element result = null;
+    NodeList nodeList = document.getChildNodes();
+    int nodeListLength = nodeList.getLength();
+    for (int i = 0 ; i < nodeListLength; i++)
+    {
+      Node node = nodeList.item(i);
+      if (node.getNodeType() == Node.ELEMENT_NODE)
+      {
+        result = (Element)node;
+        break;
+      }
+    }
+    return result;
+  }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelqueryimpl/CMDocumentManagerImpl.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelqueryimpl/CMDocumentManagerImpl.java
new file mode 100644
index 0000000..3e4af8c
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelqueryimpl/CMDocumentManagerImpl.java
@@ -0,0 +1,318 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.modelqueryimpl;
+                          
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.wst.xml.core.internal.Logger;
+import org.eclipse.wst.xml.core.internal.XMLCoreMessages;
+import org.eclipse.wst.xml.core.internal.XMLCorePlugin;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.contentmodel.ContentModelManager;
+import org.eclipse.wst.xml.core.internal.contentmodel.internal.annotation.AnnotationUtility;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.CMDocumentManager;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.CMDocumentManagerListener;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.CMDocumentReferenceProvider;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelqueryimpl.GlobalCMDocumentCache.GlobalCacheQueryResponse;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.CMDocumentCache;
+import org.eclipse.wst.xml.core.internal.preferences.XMLCorePreferenceNames;
+
+import com.ibm.icu.text.MessageFormat;
+
+/**
+ *
+ */
+public class CMDocumentManagerImpl implements CMDocumentManager
+{
+  protected CMDocumentCache cmDocumentCache;
+  protected CMDocumentReferenceProvider cmDocumentReferenceProvider;
+  protected List listenerList = new Vector(); 
+  protected Hashtable propertyTable = new Hashtable();
+  protected Hashtable publicIdTable = new Hashtable();
+  private boolean globalCMDocumentCacheEnabled ;
+
+       
+  public CMDocumentManagerImpl(CMDocumentCache cmDocumentCache, CMDocumentReferenceProvider cmDocumentReferenceProvider)
+  {
+    this.cmDocumentCache = cmDocumentCache;                                                                            
+    this.cmDocumentReferenceProvider = cmDocumentReferenceProvider;
+    setPropertyEnabled(PROPERTY_AUTO_LOAD, true);
+    setPropertyEnabled(PROPERTY_USE_CACHED_RESOLVED_URI, false);
+    setPropertyEnabled(PROPERTY_PERFORM_URI_RESOLUTION, true);
+    initializeGlobalCMDocumentCacheSettings();
+  }         
+
+       
+  public CMDocumentCache getCMDocumentCache()
+  {
+    return cmDocumentCache;
+  }
+
+ 
+  public void setPropertyEnabled(String propertyName, boolean value)
+  {
+    propertyTable.put(propertyName, value ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$
+    for (Iterator i = listenerList.iterator(); i.hasNext(); )
+    {
+      CMDocumentManagerListener listener = (CMDocumentManagerListener)i.next();
+      listener.propertyChanged(this, propertyName);
+    }
+  }                                        
+
+        
+  public boolean getPropertyEnabled(String propertyName)
+  {
+    Object object = propertyTable.get(propertyName);
+    return object != null && object.equals("true"); //$NON-NLS-1$
+  }
+
+
+  public void addListener(CMDocumentManagerListener listener)
+  {
+    listenerList.add(listener);
+    cmDocumentCache.addListener(listener);
+  }
+
+
+  public void removeListener(CMDocumentManagerListener listener)
+  {
+    listenerList.remove(listener);
+    cmDocumentCache.removeListener(listener);
+  }                       
+   
+                   
+  protected String lookupResolvedURI(String publicId)
+  {
+    String key = publicId != null ? publicId : ""; //$NON-NLS-1$
+    return (String)publicIdTable.get(key);
+  }
+    
+
+  protected String lookupOrCreateResolvedURI(String publicId, String systemId)
+  {                    
+    String resolvedURI = null;                  
+
+    String key = publicId != null ? publicId : ""; //$NON-NLS-1$
+
+    if (getPropertyEnabled(PROPERTY_USE_CACHED_RESOLVED_URI))
+    {
+      resolvedURI = (String)publicIdTable.get(key);
+    }   
+
+    if (resolvedURI == null)
+    {
+      resolvedURI = cmDocumentReferenceProvider.resolveGrammarURI(publicId, systemId);
+      if (resolvedURI == null)
+      {
+        resolvedURI = ""; //$NON-NLS-1$
+      }
+      publicIdTable.put(key, resolvedURI);     
+    }                       
+  
+    return resolvedURI;
+  }
+
+
+  public int getCMDocumentStatus(String publicId)
+  {                                           
+    int status = CMDocumentCache.STATUS_NOT_LOADED; 
+    String resolvedURI = lookupResolvedURI(publicId);
+    if (resolvedURI != null)
+    {                      
+      status = cmDocumentCache.getStatus(resolvedURI);
+    }
+    return status;
+  }    
+              
+
+  public CMDocument getCMDocument(String publicId)
+  {                                           
+    CMDocument result = null;
+    String resolvedURI = lookupResolvedURI(publicId);
+    if (resolvedURI != null)
+    {                      
+      result = cmDocumentCache.getCMDocument(resolvedURI);
+    }
+    return result;
+  }    
+  
+
+  /* (non-Javadoc)
+ * @see org.eclipse.wst.xml.core.internal.contentmodel.modelquery.CMDocumentManager#getCMDocument(java.lang.String, java.lang.String, java.lang.String)
+ */
+public CMDocument getCMDocument(String publicId, String systemId, String type)
+  {                
+    CMDocument cmDocument = null;                           
+    String resolvedURI = null;
+
+    if (getPropertyEnabled(PROPERTY_AUTO_LOAD))
+    {
+      // See https://bugs.eclipse.org/bugs/show_bug.cgi?id=136399
+      
+      if (getPropertyEnabled(PROPERTY_PERFORM_URI_RESOLUTION))
+      {
+        resolvedURI = lookupOrCreateResolvedURI(publicId, systemId);
+      }
+      else
+      {
+        resolvedURI = systemId;
+      }
+    }    
+    else
+    {
+      resolvedURI = lookupResolvedURI(publicId);
+    } 
+
+    if (resolvedURI != null)
+    {                   
+      int status = cmDocumentCache.getStatus(resolvedURI);
+      if (status == CMDocumentCache.STATUS_LOADED)
+      {                      
+        cmDocument = cmDocumentCache.getCMDocument(resolvedURI);
+      }   
+      else if (status == CMDocumentCache.STATUS_NOT_LOADED)
+      {     
+        if (getPropertyEnabled(PROPERTY_AUTO_LOAD))
+        {
+          cmDocument = loadCMDocument(publicId, resolvedURI, type, getPropertyEnabled(PROPERTY_ASYNC_LOAD));
+        }
+      }
+    }
+    return cmDocument;   
+  } 
+  
+  public void addCMDocumentReference(String publicId, String systemId, String type)
+  {
+    String resolvedURI = lookupOrCreateResolvedURI(publicId, systemId);
+    if (resolvedURI != null && resolvedURI.length() > 0)
+    {                                                                      
+      int status = cmDocumentCache.getStatus(resolvedURI);
+      if (status == CMDocumentCache.STATUS_NOT_LOADED)
+      {                      
+        loadCMDocument(publicId, resolvedURI, type, getPropertyEnabled(PROPERTY_ASYNC_LOAD));
+      }         
+    } 
+  }
+     
+
+  public void addCMDocument(String publicId, String systemId, String resolvedURI, String type, CMDocument cmDocument)
+  {
+    String key = publicId != null ? publicId : ""; //$NON-NLS-1$
+    publicIdTable.put(key, resolvedURI);
+    cmDocumentCache.putCMDocument(resolvedURI, cmDocument);
+  }
+
+
+  protected CMDocument loadCMDocument(final String publicId, final String resolvedURI, final String type, boolean async)
+  {                                                      
+    CMDocument result = null;
+                         
+    //System.out.println("about to build CMDocument(" + publicId + ", " + unresolvedURI + " = " + resolvedURI + ")");
+    if (async)
+    {     
+      cmDocumentCache.setStatus(resolvedURI, CMDocumentCache.STATUS_LOADING);
+      //Thread thread = new Thread(new AsyncBuildOperation(publicId, resolvedURI, type));
+      //thread.start();
+      Job job = new Job(XMLCoreMessages.loading + resolvedURI)
+      {
+        public boolean belongsTo(Object family)
+        {
+          boolean result = (family == CMDocumentManager.class);
+          return result;
+        }
+        
+        protected IStatus run(IProgressMonitor monitor)
+        {
+          try
+          {
+        	  buildCMDocument(publicId, resolvedURI, type);
+          }
+          catch (Exception e)
+          {
+        	  Logger.logException(MessageFormat.format(XMLCoreMessages.CMDocument_load_exception, new Object[]{resolvedURI, publicId}), e);
+          }
+          return Status.OK_STATUS;
+        }
+      };
+      job.schedule();
+    }
+    else
+    {                
+      result = buildCMDocument(publicId, resolvedURI, type);
+    }          
+    return result;
+  } 
+
+    
+
+  public synchronized CMDocument buildCMDocument(String publicId, String resolvedURI, String type)
+  {                                     
+    cmDocumentCache.setStatus(resolvedURI, CMDocumentCache.STATUS_LOADING);
+    boolean documentCacheable = false;
+    if(globalCMDocumentCacheEnabled) {
+    	GlobalCacheQueryResponse response = GlobalCMDocumentCache.getInstance().getCMDocument(resolvedURI);
+    	CMDocument cachedCMDocument = response.getCachedCMDocument();
+    	documentCacheable = response.isDocumentCacheable();
+    	if(cachedCMDocument != null) {
+    		cmDocumentCache.putCMDocument(resolvedURI, cachedCMDocument);
+    		return cachedCMDocument;
+    	}
+    }
+
+    CMDocument result = null;         
+    if (resolvedURI != null && resolvedURI.length() > 0)
+    {
+      // TODO... pass the TYPE thru to the CMDocumentBuilder
+      result = ContentModelManager.getInstance().createCMDocument(resolvedURI, type);
+    }
+    if (result != null)
+    { 
+      // load the annotation files for the document 
+      if (publicId != null)
+      {    
+        AnnotationUtility.loadAnnotationsForGrammar(publicId, result);
+      }
+      if(globalCMDocumentCacheEnabled && documentCacheable) {
+    	  GlobalCMDocumentCache.getInstance().putCMDocument(resolvedURI, result);
+      }
+      cmDocumentCache.putCMDocument(resolvedURI, result);
+    }
+    else
+    {
+      cmDocumentCache.setStatus(resolvedURI, CMDocumentCache.STATUS_ERROR);
+    }
+    return result;
+  } 
+
+  public void removeAllReferences()
+  {
+    // TODO... initiate a timed release of the entries in the CMDocumentCache
+    publicIdTable = new Hashtable();
+  }
+  
+  private void initializeGlobalCMDocumentCacheSettings() {
+	  Preferences preferences = XMLCorePlugin.getDefault().getPluginPreferences();
+	  if(preferences != null) {
+		  globalCMDocumentCacheEnabled = preferences.getBoolean(XMLCorePreferenceNames.CMDOCUMENT_GLOBAL_CACHE_ENABLED);
+	  }
+  }
+
+}                                            
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelqueryimpl/CMDocumentReferenceImpl.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelqueryimpl/CMDocumentReferenceImpl.java
new file mode 100644
index 0000000..f4edabd
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelqueryimpl/CMDocumentReferenceImpl.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.modelqueryimpl;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.CMDocumentReference;
+
+public class CMDocumentReferenceImpl implements CMDocumentReference
+{              
+  protected String systemId;
+  protected String publicId;
+
+  public CMDocumentReferenceImpl(String publicId, String systemId)
+  {
+    this.publicId = publicId;                                    
+    this.systemId = systemId;
+  }
+
+  public String getPublicId()
+  {                          
+    return publicId;
+  }
+
+  public String getSystemId()
+  {                          
+    return systemId;
+  }      
+  
+  public String toString()
+  {
+    return "[" + publicId + ", " + systemId + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+  }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelqueryimpl/ExternalSchemaLocationProviderRegistry.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelqueryimpl/ExternalSchemaLocationProviderRegistry.java
new file mode 100644
index 0000000..594c5d8
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelqueryimpl/ExternalSchemaLocationProviderRegistry.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.modelqueryimpl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.wst.xml.core.internal.Logger;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.IExternalSchemaLocationProvider;
+
+/**
+ * A registry for all external schema location providers.
+ * 
+ */
+public class ExternalSchemaLocationProviderRegistry {
+
+	private static ExternalSchemaLocationProviderRegistry fRegistry;
+	private IExternalSchemaLocationProvider[] fProviders;
+
+	private ExternalSchemaLocationProviderRegistry() {
+		fProviders = new IExternalSchemaLocationProvider[0];
+		IConfigurationElement[] elements = Platform.getExtensionRegistry().getConfigurationElementsFor("org.eclipse.wst.xml.core", "externalSchemaLocations"); //$NON-NLS-1$ //$NON-NLS-2$
+		List providers = new ArrayList(elements.length);
+		try {
+			for (int i = 0; i < elements.length; i++) {
+				providers.add(elements[i].createExecutableExtension("class"));
+			}
+		}
+		catch (CoreException e) {
+			Logger.logException(e);
+		}
+		fProviders = new IExternalSchemaLocationProvider[elements.length];
+		providers.toArray(fProviders);
+	}
+
+	public IExternalSchemaLocationProvider[] getProviders() {
+		return fProviders;
+	}
+
+	public static synchronized ExternalSchemaLocationProviderRegistry getInstance() {
+		if (fRegistry == null)
+			fRegistry = new ExternalSchemaLocationProviderRegistry();
+		return fRegistry;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelqueryimpl/GlobalCMDocumentCache.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelqueryimpl/GlobalCMDocumentCache.java
new file mode 100644
index 0000000..ca981f1
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelqueryimpl/GlobalCMDocumentCache.java
@@ -0,0 +1,121 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.modelqueryimpl;
+
+import java.lang.ref.SoftReference;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.wst.sse.core.internal.util.AbstractMemoryListener;
+import org.eclipse.wst.xml.core.internal.Logger;
+import org.eclipse.wst.xml.core.internal.XMLCorePlugin;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalog;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalogEntry;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.INextCatalog;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventConstants;
+
+public class GlobalCMDocumentCache {
+	
+	private static GlobalCMDocumentCache globalDocumentCache = new GlobalCMDocumentCache();
+	private Map systemCatalogEntries = getSystemCatalogEntries();
+	private MemoryListener memoryListener;
+	private final static String CATEGORY = "CMDocumentGlobalCache"; //$NON-NLS-1$
+	
+	protected GlobalCMDocumentCache() {
+		Logger.trace(CATEGORY, "Cache initialized"); //$NON-NLS-1$
+		memoryListener = new MemoryListener();
+		memoryListener.connect();
+	}
+
+	public static GlobalCMDocumentCache getInstance() {
+		return globalDocumentCache;
+	}
+	
+	public synchronized GlobalCacheQueryResponse getCMDocument(String grammarURI) {
+		//Logger.trace(CATEGORY, "Query for: " + grammarURI); //$NON-NLS-1$
+		Object systemCatalogEntry = systemCatalogEntries.get(grammarURI);
+		if(systemCatalogEntry != null) {
+			//Logger.trace(CATEGORY, "Document " + grammarURI + " is in system catalog"); //$NON-NLS-1$ //$NON-NLS-2$
+			Object object = ((SoftReference)systemCatalogEntry).get();
+			if(object != null) {
+				//Logger.trace(CATEGORY, "Document " + grammarURI + "is in cache, returning cached version"); //$NON-NLS-1$ //$NON-NLS-2$
+				return new GlobalCacheQueryResponse((CMDocument)object, true);
+			} else {
+				//Logger.trace(CATEGORY, "Document " + grammarURI + " is not in cache"); //$NON-NLS-1$ //$NON-NLS-2$
+				return new GlobalCacheQueryResponse(null, true);
+			}
+		}
+		//Logger.trace(CATEGORY, "Document " + grammarURI + " is not in system catalog, not cached"); //$NON-NLS-1$ //$NON-NLS-2$
+		return new GlobalCacheQueryResponse(null, false);
+	}
+	
+	public synchronized void putCMDocument(String grammarURI, CMDocument cmDocument) {
+		//Logger.trace(CATEGORY, "Document: " + grammarURI + " added to global cache"); //$NON-NLS-1$ //$NON-NLS-2$
+		systemCatalogEntries.put(grammarURI, new SoftReference(cmDocument));
+	}
+	
+	private synchronized static HashMap getSystemCatalogEntries(){
+		HashMap systemCatalogURIs = new HashMap();
+		ICatalog systemCatalog = null;
+		ICatalog defaultCatalog = XMLCorePlugin.getDefault().getDefaultXMLCatalog();
+		INextCatalog[] nextCatalogs = defaultCatalog.getNextCatalogs();
+		for (int i = 0; i < nextCatalogs.length; i++) {
+			INextCatalog catalog = nextCatalogs[i];
+			ICatalog referencedCatalog = catalog.getReferencedCatalog();
+			if (referencedCatalog != null) {
+				if (XMLCorePlugin.SYSTEM_CATALOG_ID.equals(referencedCatalog.getId())) {
+					systemCatalog = referencedCatalog;
+				}
+			}
+		}
+		if(systemCatalog != null) {
+			ICatalogEntry[] catalogEntries = systemCatalog.getCatalogEntries();
+			for (int i = 0; i < catalogEntries.length; i++) {
+				systemCatalogURIs.put(catalogEntries[i].getURI(), new SoftReference(null));
+			}
+		}
+		return systemCatalogURIs;
+	}
+	
+	public class GlobalCacheQueryResponse {
+		
+		private CMDocument cachedDocument;
+		private boolean documentCacheable;
+		
+		public GlobalCacheQueryResponse(CMDocument cachedCMDocument, boolean documentCacheable) {
+			this.cachedDocument = cachedCMDocument;
+			this.documentCacheable = documentCacheable;
+		}
+		
+		public CMDocument getCachedCMDocument() {
+			return cachedDocument;
+		}
+		
+		public boolean isDocumentCacheable() {
+			return documentCacheable;
+		}
+		
+	}
+
+	private class MemoryListener extends AbstractMemoryListener {
+		protected void handleMemoryEvent(Event event) {
+			Object topic = event.getProperty(EventConstants.EVENT_TOPIC);
+			if(SEV_SERIOUS.equals(topic) || SEV_CRITICAL.equals(topic)) {
+				Logger.trace(CATEGORY, "Serious severity low memory event received, flushing global CMDocument cache."); //$NON-NLS-1$
+				systemCatalogEntries = getSystemCatalogEntries();
+			}
+		}
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelqueryimpl/InferredGrammarBuildingCMDocumentLoader.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelqueryimpl/InferredGrammarBuildingCMDocumentLoader.java
new file mode 100644
index 0000000..c91e72c
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelqueryimpl/InferredGrammarBuildingCMDocumentLoader.java
@@ -0,0 +1,189 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.modelqueryimpl;
+                          
+import java.util.Hashtable;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.internal.modelqueryimpl.InferredGrammarFactory;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.CMDocumentManager;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.CMDocumentCache;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+
+/**
+ *
+ */
+public class InferredGrammarBuildingCMDocumentLoader extends CMDocumentLoader
+{     
+  protected CMElementDeclaration inferredCMElementDeclaration;
+  protected CMDocument inferredCMDocument;
+  protected InferredGrammarFactory inferredGrammarFactory;
+  protected Hashtable createdCMDocumentTable;
+
+  public InferredGrammarBuildingCMDocumentLoader(Document document, ModelQuery modelQuery)
+  {                             
+    this(document, modelQuery.getCMDocumentManager());
+  }
+  
+  public InferredGrammarBuildingCMDocumentLoader(Document document, CMDocumentManager cmDocumentManager)
+  {                             
+    super(document, cmDocumentManager);
+    createdCMDocumentTable = new Hashtable();             
+    inferredGrammarFactory = new InferredGrammarFactory();
+  }     
+
+     
+  public void loadCMDocuments()
+  {   
+    //System.out.println("----------loadCMDocuments ------------");          
+    if (inferredGrammarFactory != null)
+    {
+      //long time = System.currentTimeMillis();
+      super.loadCMDocuments();
+      //System.out.println("--- elapsed time (" + count + ") = " + (System.currentTimeMillis() - time));
+      //inferredGrammarFactory.debugPrint(createdCMDocumentTable.values());
+    }
+    
+  }
+
+  public void handleElement(Element element)
+  { 
+    CMElementDeclaration parentInferredCMElementDeclaration = inferredCMElementDeclaration;
+                
+    if (inferredCMDocument == null)
+    {     
+      String cacheKey = "inferred-document";                    //$NON-NLS-1$
+      inferredCMDocument = inferredGrammarFactory.createCMDocument("");   //$NON-NLS-1$
+      cmDocumentManager.addCMDocument("", "", cacheKey, "DTD", inferredCMDocument); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+      createdCMDocumentTable.put(cacheKey, inferredCMDocument);
+    } 
+
+    inferredCMElementDeclaration = inferredGrammarFactory.createCMElementDeclaration(inferredCMDocument, element, false);                             
+     
+    if (parentInferredCMElementDeclaration != null)
+    {
+      inferredGrammarFactory.createCMContent(inferredCMDocument, parentInferredCMElementDeclaration, inferredCMDocument, inferredCMElementDeclaration, false, null);
+    }     
+       
+
+    visitChildNodes(element);   
+           
+    // reset the 'current' state to inital values
+    inferredCMElementDeclaration = parentInferredCMElementDeclaration;
+  }
+  
+
+  public void handleElementNS(Element element)
+  {                             
+    CMDocument parentInferredCMDocument = inferredCMDocument;
+    CMElementDeclaration parentInferredCMElementDeclaration = inferredCMElementDeclaration;
+        
+    inferredCMDocument = null;                                                            
+    inferredCMElementDeclaration = null;
+
+    // by adding the element to the namespaceTable, handleGrammar() will get called for any schema references
+    if (element.getParentNode() != document)
+    {
+      namespaceTable.addElement(element);
+    }
+
+    String prefix = element.getPrefix();
+    String uri = namespaceTable.getURIForPrefix(prefix);
+
+    if (uri == null && element.getParentNode() == document)
+    {
+      // when this is the root element
+      // we need to add an implied "no namespace schema location"
+      uri = "ommitted-namespace"; //$NON-NLS-1$
+      namespaceTable.addNamespaceInfo(prefix, uri, ""); //$NON-NLS-1$
+    }  
+
+    // here's where we update the inferred grammar if required
+    // 
+    boolean createCMElementDeclaration = true;
+          
+    boolean isLocal = (uri == null && prefix == null);         
+    if (isLocal)
+    {          
+      if (parentInferredCMDocument == null)
+      {
+        // this is a local element... and the parent is not inferred (e.g) it has a known grammar
+        // so we don't need to create an element declaration for this element
+        createCMElementDeclaration = false; 
+      }                             
+      else
+      {
+        if (uri == null)
+        {
+          uri = "ommitted-namespace"; //$NON-NLS-1$
+        }
+      }
+    }
+
+    if (createCMElementDeclaration)
+    {            
+      if (isLocal)
+      {
+        inferredCMDocument = parentInferredCMDocument;
+        inferredCMElementDeclaration = inferredGrammarFactory.createCMElementDeclaration(inferredCMDocument, element, true);       
+      }          
+      else
+      {
+        boolean createCMDocument = false;
+
+        String cacheKey = "inferred-document" + uri;  //$NON-NLS-1$
+        inferredCMDocument = (CMDocument)createdCMDocumentTable.get(cacheKey);
+
+        if (inferredCMDocument == null)
+        {
+          // we don't have an inferred document for this uri yet... let's see of we need one
+          int status = cmDocumentManager.getCMDocumentStatus(uri);                                                                                           
+          if (status == CMDocumentCache.STATUS_NOT_LOADED || status == CMDocumentCache.STATUS_ERROR)
+          {                  
+            // the cache does not contain a 'proper' CMDocument for this uri
+            // so we need to create an inferred one
+            createCMDocument = true;
+          } 
+        } 
+                
+        if (createCMDocument)
+        {           
+          //System.out.println("encountered element {" + element.getNodeName() + "} ... creating inferred CMDocument for " + uri);
+          inferredCMDocument = inferredGrammarFactory.createCMDocument(uri);
+          cmDocumentManager.addCMDocument(uri, "", cacheKey, "XSD", inferredCMDocument); //$NON-NLS-1$ //$NON-NLS-2$
+          createdCMDocumentTable.put(cacheKey, inferredCMDocument);
+        }
+
+        if (inferredCMDocument != null)
+        {
+          inferredCMElementDeclaration = inferredGrammarFactory.createCMElementDeclaration(inferredCMDocument, element, false);
+        }                                                                                                                                                   
+      }
+
+      if (parentInferredCMElementDeclaration != null)
+      {
+        inferredGrammarFactory.createCMContent(parentInferredCMDocument, parentInferredCMElementDeclaration, inferredCMDocument, inferredCMElementDeclaration, isLocal, uri);
+      } 
+    }               
+          
+    visitChildNodes(element);
+      
+    // reset the 'current' state to inital values
+    inferredCMElementDeclaration = parentInferredCMElementDeclaration;
+    inferredCMDocument = parentInferredCMDocument;
+  }                                                                                                       
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelqueryimpl/ModelQueryActionHelper.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelqueryimpl/ModelQueryActionHelper.java
new file mode 100644
index 0000000..b66a0d6
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelqueryimpl/ModelQueryActionHelper.java
@@ -0,0 +1,574 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.modelqueryimpl;
+
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNodeList;
+import org.eclipse.wst.xml.core.internal.contentmodel.internal.util.CMValidator;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQueryAction;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+
+/**
+ *
+ */
+public class ModelQueryActionHelper
+{
+  protected ModelQueryImpl modelQuery;
+
+  protected static class Action implements ModelQueryAction
+  {
+    public int kind;
+    public int startIndex;
+    public int endIndex;
+    public Node parent;
+    public CMNode cmNode;
+    public Object userData;
+
+    public Action(int kind, Node parent, CMNode cmNode)
+    {
+      this.kind = kind;
+      this.parent = parent;
+      this.cmNode = cmNode;
+    }
+
+    public Action(int kind, Node parent, CMNode cmNode, int startIndex, int endIndex)
+    {
+      this.kind = kind;
+      this.parent = parent;
+      this.cmNode = cmNode;
+      this.startIndex = startIndex;
+      this.endIndex = endIndex;
+    }
+
+    public int getKind()
+    {
+      return kind;
+    }
+
+    public int getStartIndex()
+    {
+      return startIndex;
+    }
+
+    public int getEndIndex()
+    {
+      return endIndex;
+    }
+
+    public Node getParent()
+    {
+      return parent;
+    }
+
+    public CMNode getCMNode()
+    {
+      return cmNode;
+    }
+
+    public Object getUserData()
+    {
+      return userData;
+    }
+
+    public void setUserData(Object object)
+    {
+      userData = object;
+    }
+
+    public void performAction()
+    {
+    }
+  }
+
+
+  public ModelQueryActionHelper(ModelQueryImpl modelQuery)
+  {
+    this.modelQuery = modelQuery;
+  }
+
+
+  public void getAllActions(Element parent, CMElementDeclaration ed, int validityChecking, List actionList)
+  {
+  }
+
+
+  // insert actions
+  //
+  public void getInsertActions(Element parent, CMElementDeclaration ed, int index, int includeOptions, int validityChecking, List actionList)
+  {
+    if ((includeOptions & ModelQuery.INCLUDE_ATTRIBUTES) != 0)
+    {
+      getInsertAttributeActions(parent, ed, validityChecking, actionList);
+    }
+    includeOptions &= ~ModelQuery.INCLUDE_ATTRIBUTES;
+    if ((includeOptions & ModelQuery.INCLUDE_CHILD_NODES) != 0)
+    {
+      if (index != -1)
+      {
+        getInsertChildNodeActionsAtIndex(parent, ed, index, includeOptions, validityChecking, actionList);
+      }
+      else
+      {
+        getInsertChildNodeActions(parent, ed, includeOptions, validityChecking, actionList);
+      }
+    }
+  }
+
+
+
+  protected void getInsertAttributeActions(Element parent, CMElementDeclaration ed, int validityChecking, List actionList)
+  {
+    // get actions for each insertable attribute
+    //
+    List availableAttributeList = modelQuery.getAvailableContent(parent, ed, ModelQuery.INCLUDE_ATTRIBUTES);
+
+    for (Iterator i = availableAttributeList.iterator(); i.hasNext(); )
+    {
+      CMAttributeDeclaration ad = (CMAttributeDeclaration)i.next();
+      if (modelQuery.canInsert(parent, ed, ad, 0, validityChecking))
+      {
+        Action action = new Action(ModelQueryAction.INSERT, parent, ad);
+        actionList.add(action);
+      }
+    }
+  }
+
+
+  protected void getInsertChildNodeActionsAtIndex(Element parent, CMElementDeclaration ed, int index, int includeOptions, int validityChecking, List actionList)
+  {                       
+    // get actions for each insertable attribute
+    //
+    int size = parent.getChildNodes().getLength();
+    if (index <= size)
+    {                                                                                          
+      List contentSpecificationList = modelQuery.getValidator().createContentSpecificationList(parent, ed); 
+      List availableChildNodeList = modelQuery.getAvailableContent(parent, ed, includeOptions);
+
+      boolean isSimpleChoice = isSimpleChoiceGroupContentModel(ed);
+     
+      for (Iterator i = availableChildNodeList.iterator(); i.hasNext(); )
+      {
+        CMNode cmNode = (CMNode)i.next();      
+        if (isSimpleChoice || modelQuery.canInsert(parent, ed, cmNode, index, validityChecking, contentSpecificationList))
+        {
+          Action action = new Action(ModelQueryAction.INSERT, parent, cmNode, index, index);
+          actionList.add(action);
+        }
+      }
+    }
+  }
+                  
+ 
+  protected boolean isSimpleChoiceGroupContentModel(CMElementDeclaration ed)
+  {       
+    boolean result = false;
+    CMNode cmNode = ed.getContent();
+    if (cmNode != null && cmNode.getNodeType() == CMNode.GROUP)
+    {
+      CMGroup cmGroup = (CMGroup)cmNode;
+      if (cmGroup.getOperator() == CMGroup.CHOICE && cmGroup.getMaxOccur() == -1)
+      {                   
+        result = true;
+        CMNodeList list = cmGroup.getChildNodes();
+        for (int i = list.getLength() - 1; i >= 0; i--)
+        {
+          if (list.item(i).getNodeType() != CMNode.ELEMENT_DECLARATION)
+          {
+            result = false;
+            break;
+          }
+        }
+      }
+    }
+    return result;
+  }
+
+
+  protected void getInsertChildNodeActions(Element parent, CMElementDeclaration ed, int includeOptions, int validityChecking, List actionList)
+  {
+    int size = parent.getChildNodes().getLength();
+    List contentSpecificationList = modelQuery.getValidator().createContentSpecificationList(parent, ed);
+    List availableChildNodeList = modelQuery.getAvailableContent(parent, ed, includeOptions);
+
+    boolean isSimpleChoice = isSimpleChoiceGroupContentModel(ed);
+
+    for (Iterator iterator = availableChildNodeList.iterator(); iterator.hasNext(); )
+    {
+      CMNode cmNode = (CMNode)iterator.next();
+      for (int i = size; i >= 0; i--)
+      {
+        if (isSimpleChoice || modelQuery.canInsert(parent, ed, cmNode, i, validityChecking, contentSpecificationList))
+        {
+          Action action = new Action(ModelQueryAction.INSERT, parent, cmNode, i, i);
+          actionList.add(action);
+          break;
+        }
+      }
+    }
+  }
+
+  public void getInsertActions(Document parent, CMDocument cmDocument, int index, int includeOptions, int validityChecking, List actionList)
+  {
+    // get the root element and doctype index (if any)
+    //
+    int doctypeIndex = -1;
+    DocumentType doctype = null;
+    Element rootElement = null;
+    NodeList nodeList = parent.getChildNodes();
+    int nodeListLength = nodeList.getLength();
+    for (int i = 0; i < nodeListLength; i++)
+    {
+      Node childNode = nodeList.item(i);
+      if (childNode.getNodeType() == Node.ELEMENT_NODE)
+      {
+        rootElement = (Element)childNode;
+        break;
+      }
+      else if (childNode.getNodeType() == Node.DOCUMENT_TYPE_NODE)
+      {
+        doctype = (DocumentType)childNode;
+        doctypeIndex = i;
+      }
+    }
+
+    // make sure that root elements are only added after the doctype (if any)
+    if (rootElement == null && index > doctypeIndex)
+    {
+      CMNamedNodeMap map = cmDocument.getElements();
+      int mapLength = map.getLength();
+      for (int i = 0; i < mapLength; i++)
+      {
+        CMNode cmNode = map.item(i);
+
+        boolean canAdd = true;
+        if (validityChecking == ModelQuery.VALIDITY_STRICT)
+        {
+          canAdd = doctype == null || doctype.getName().equals(cmNode.getNodeName());
+        }
+
+        if (canAdd)
+        {
+          Action action = new Action(ModelQueryAction.INSERT, parent, cmNode, index, index);
+          actionList.add(action);
+        }
+      }
+    }
+  }
+
+
+
+  public void getInsertChildNodeActionTable(Element parent, CMElementDeclaration ed, int validityChecking, Hashtable actionTable)
+  {
+  }
+
+
+  public void getReplaceActions(Element parent, CMElementDeclaration ed, int includeOptions, int validityChecking, List actionList)
+  {
+    CMValidator.MatchModelNode matchModelNode = modelQuery.getValidator().getMatchModel(ed, parent);
+    if (matchModelNode != null)
+    {
+      MatchModelVisitor visitor = new MatchModelVisitor(parent, actionList);
+      visitor.visitMatchModelNode(matchModelNode);
+    }     
+  }
+
+  public void getReplaceActions(Element parent, CMElementDeclaration ed, List selectedChildren, int includeOptions, int validityChecking, List actionList)
+  {
+    int[] range = getRange(parent, selectedChildren);
+    if (range != null)
+    {                
+      if (isContiguous(parent, range, selectedChildren))
+      {
+        List tempList = new Vector();
+        getReplaceActions(parent, ed, includeOptions, validityChecking, tempList);
+        if ((includeOptions & ModelQuery.INCLUDE_ENCLOSING_REPLACE_ACTIONS) != 0)
+        {
+          removeActionsNotContainingRange(tempList, range[0], range[1]);            
+        }
+        else
+        {
+          removeActionsNotMatchingRange(tempList, range[0], range[1]);    
+        }
+        actionList.addAll(tempList);
+      }
+    }   
+    
+    if (selectedChildren.size() == 1)
+    {
+      Node node = (Node)selectedChildren.get(0);
+      if (node.getNodeType() == Node.ELEMENT_NODE)
+      {        
+        Element childElement = (Element)node;       
+        CMNode childEd = modelQuery.getCMElementDeclaration(childElement);
+        if (childEd != null)
+        {         
+
+          CMNode childOrigin= modelQuery.getOrigin(childElement);
+
+          CMNodeList cmNodeList = childOrigin != null ? 
+                                    (CMNodeList)childOrigin.getProperty("SubstitutionGroup") : //$NON-NLS-1$
+                                    (CMNodeList)childEd.getProperty("SubstitutionGroup"); //$NON-NLS-1$
+
+          if (cmNodeList != null && cmNodeList.getLength() > 1)
+          {                                                 
+            int replaceIndex = getIndex(parent, childElement);
+            String childEdName = childEd.getNodeName();
+            for (int i = 0; i < cmNodeList.getLength(); i++)
+            {         
+              CMNode substitution = cmNodeList.item(i);
+              if (!substitution.getNodeName().equals(childEdName) && !Boolean.TRUE.equals(substitution.getProperty("Abstract"))) //$NON-NLS-1$
+              {
+                Action action = new Action(ModelQueryAction.REPLACE, parent, cmNodeList.item(i), replaceIndex, replaceIndex);
+                actionList.add(action);
+              }
+            }
+          }
+        }
+      }   
+    }
+  }     
+           
+  
+  // returns true if the selected nodes are contiguous
+  //  
+  protected boolean isContiguous(Element parent, int[] range, List selectedNodeList)
+  {         
+    boolean result = true;
+    NodeList nodeList = parent.getChildNodes();
+	// issue: nodeListLength was never read, but in theory, 
+	// nodelList.getLength() might cause some clearing of cached 
+	// data, or something, so leaving in a potential meaningless call, for now.
+    //int nodeListLength = nodeList.getLength();
+	nodeList.getLength();
+    for (int i = range[0]; i < range[1]; i++)
+    {       
+      Node node = nodeList.item(i);    
+      if (!isWhitespaceNode(node) && !selectedNodeList.contains(node))
+      {             
+        result = false;
+        break;
+      }                       
+    }         
+    return result;
+  }
+ 
+ 
+  protected int[] getRange(Element parent, List list)
+  {
+    int[] result = null;
+    int first = -1;
+    int last = -1;                     
+
+    NodeList nodeList = parent.getChildNodes();
+    int nodeListLength = nodeList.getLength();
+    for (int i = 0; i < nodeListLength; i++)
+    {       
+      Node node = nodeList.item(i);    
+      if (list.contains(node))
+      {             
+        first = (first == -1) ? i : Math.min(first, i);        
+        last = Math.max(last, i);
+      }    
+    }
+   
+    if (first != -1 && last!= -1)
+    {             
+      result = new int[2];
+      result[0] = first;
+      result[1] = last;
+    }   
+    return result;
+  } 
+
+
+  protected boolean isWhitespaceNode(Node node)
+  {
+    return node.getNodeType() == Node.TEXT_NODE &&
+           node.getNodeValue().trim().length() == 0;
+  } 
+
+
+  protected int getIndex(Node parentNode, Node child)
+  {
+    NodeList nodeList = parentNode.getChildNodes();
+    int index = -1;
+    int size = nodeList.getLength();
+    for (int i = 0; i < size; i++)
+    {
+      if (nodeList.item(i) == child)
+      {
+        index = i;
+        break;
+      }
+    }
+    return index;
+  }                    
+
+
+  protected boolean isActionContainingRange(ModelQueryAction action, int startIndex, int endIndex)
+  {
+    int actionStartIndex = action.getStartIndex();
+    int actionEndIndex = action.getEndIndex();
+
+    return (actionStartIndex <= startIndex &&
+            actionEndIndex >= endIndex);
+  } 
+           
+
+  protected boolean isActionMatchingRange(ModelQueryAction action, int startIndex, int endIndex)
+  {
+    int actionStartIndex = action.getStartIndex();
+    int actionEndIndex = action.getEndIndex();
+    return (actionStartIndex == startIndex &&        
+            actionEndIndex == endIndex);
+  } 
+           
+
+  protected void removeActionsNotContainingRange(List actionList, int startIndex, int endIndex)
+  {
+    for (int i = actionList.size() - 1; i >= 0; i--)
+    {
+      ModelQueryAction action = (ModelQueryAction)actionList.get(i);
+      if (!isActionContainingRange(action, startIndex, endIndex))
+      {
+        actionList.remove(i);
+      }
+    }
+  }
+
+
+  protected void removeActionsNotMatchingRange(List actionList, int startIndex, int endIndex)
+  {
+    for (int i = actionList.size() - 1; i >= 0; i--)
+    {
+      ModelQueryAction action = (ModelQueryAction)actionList.get(i);
+      if (!isActionMatchingRange(action, startIndex, endIndex))
+      {
+        actionList.remove(i);
+      }
+    }
+  }
+
+
+  public static class MatchModelVisitor
+  {
+    int indent;
+    int elementIndex;
+    Node parent;
+    List actionList;
+
+    public MatchModelVisitor(Node parent, List actionList)
+    {
+      this.parent = parent;
+      this.actionList = actionList;
+    }
+
+    public int indexOfNextElement(int start)
+    {
+      NodeList nodeList = parent.getChildNodes();
+      int length = nodeList.getLength();
+      int result = length;
+      for (int i = start; i < length; i++)
+      {
+        Node node = nodeList.item(i);
+        if (node.getNodeType() == Node.ELEMENT_NODE)
+        {
+          result = i;
+          break;
+        }
+      }
+      return result;
+    }
+
+    public void visitMatchModelNode(CMValidator.MatchModelNode matchModelNode)
+    {
+      int startIndex = indexOfNextElement(elementIndex);
+
+      //String cmNodeName = matchModelNode.cmNode != null ? matchModelNode.cmNode.getNodeName() : "null";
+      //printIndented(indent, "+MatchModelNode : " + cmNodeName +  " " + startIndex);
+
+      indent += 2;
+      for (Iterator iterator = matchModelNode.children.iterator(); iterator.hasNext(); )
+      {
+        CMValidator.MatchModelNode child = (CMValidator.MatchModelNode)iterator.next();
+        visitMatchModelNode(child);
+      }
+      indent -= 2;
+
+      if (matchModelNode.cmNode != null)
+      {
+        int nodeType = matchModelNode.cmNode.getNodeType();
+        if (nodeType == CMNode.GROUP)
+        {
+          CMGroup group = (CMGroup)matchModelNode.cmNode;
+          if (group.getOperator() == CMGroup.CHOICE)
+          {
+            addReplaceActions(matchModelNode, group, startIndex, elementIndex - 1);
+          }
+        }
+        else if (nodeType == CMNode.ELEMENT_DECLARATION)
+        {
+          elementIndex = startIndex + 1;
+        }
+        //printIndented(indent, "-MatchModelNode : " + cmNodeName +  " " + (elementIndex - 1));
+      }
+    }
+
+    public void addReplaceActions(CMValidator.MatchModelNode matchModelNode, CMGroup group, int startIndex, int endIndex)
+    {
+      CMNode excludeCMNode = null;
+      if (matchModelNode.children.size() > 0)
+      {
+        CMValidator.MatchModelNode child = (CMValidator.MatchModelNode)matchModelNode.children.get(0);
+        excludeCMNode = child.cmNode;
+      }
+
+      CMNodeList nodeList = group.getChildNodes();
+      int size = nodeList.getLength();
+      for (int i = 0; i < size; i++)
+      {
+        CMNode alternative = nodeList.item(i);
+        if (alternative != excludeCMNode)
+        {
+          Action action = new Action(ModelQueryAction.REPLACE, parent, alternative, startIndex, endIndex);
+          actionList.add(action);
+        }
+      }
+    }
+  }
+
+  //public static void printIndented(int indent, String string)
+  //{
+  //  for (int i = 0; i < indent; i++)
+  //  {
+  //    System.out.print(" ");
+  //  }
+  //  System.out.println(string);
+  //}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelqueryimpl/ModelQueryImpl.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelqueryimpl/ModelQueryImpl.java
new file mode 100644
index 0000000..3c6485e
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelqueryimpl/ModelQueryImpl.java
@@ -0,0 +1,849 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2009 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.modelqueryimpl;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAnyElement;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNodeList;
+import org.eclipse.wst.xml.core.internal.contentmodel.internal.modelqueryimpl.ModelQueryExtensionManagerImpl;
+import org.eclipse.wst.xml.core.internal.contentmodel.internal.util.CMDataTypeValueHelper;
+import org.eclipse.wst.xml.core.internal.contentmodel.internal.util.DOMValidator;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.CMDocumentManager;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQueryAssociationProvider;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.extension.ModelQueryExtensionManager;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.CMVisitor;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.DOMNamespaceHelper;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.NamespaceInfo;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.NamespaceTable;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+
+
+/**
+ * This class implements a large portion of the ModelQuery interfaces.
+ * Some work is delegated to the DOMHelper, CMDocumentManager, and DOMValidator.
+ */
+public class ModelQueryImpl implements ModelQuery
+{
+  protected ModelQueryAssociationProvider modelQueryAssociationProvider;
+  protected ModelQueryActionHelper modelQueryActionHelper;
+  protected DOMValidator validator;   
+  protected ModelQueryExtensionManagerImpl extensionManager;   
+  protected CMDataTypeValueHelper valueHelper;
+  protected int editMode = EDIT_MODE_CONSTRAINED_STRICT;
+
+  public ModelQueryImpl(ModelQueryAssociationProvider modelQueryAssociationProvider)
+  {
+    this.modelQueryAssociationProvider = modelQueryAssociationProvider;
+    modelQueryActionHelper = createModelQueryActionHelper();
+    validator = new DOMValidator();                         
+    extensionManager = new ModelQueryExtensionManagerImpl();
+    valueHelper = new CMDataTypeValueHelper();
+  }
+                         
+  public int getEditMode()
+  {
+    return editMode;
+  }
+                    
+  public void setEditMode(int editMode)
+  {
+    this.editMode =editMode;
+  }
+
+
+  // factory methods
+  public ModelQueryActionHelper createModelQueryActionHelper()
+  {
+    return new ModelQueryActionHelper(this);
+  } 
+
+  public DOMValidator getValidator()
+  {
+    return validator;
+  }
+
+  public CMDocument getCorrespondingCMDocument(Node node)
+  {
+    return modelQueryAssociationProvider.getCorrespondingCMDocument(node);
+  }
+
+  public CMNode getCMNode(Node node)
+  {
+    return modelQueryAssociationProvider.getCMNode(node);
+  }
+
+  public CMDataType getCMDataType(Text text)
+  {
+    return modelQueryAssociationProvider.getCMDataType(text);
+  }
+
+  public CMAttributeDeclaration getCMAttributeDeclaration(Attr attr)
+  {
+    return modelQueryAssociationProvider.getCMAttributeDeclaration(attr);
+  }
+
+  public CMElementDeclaration getCMElementDeclaration(Element element)
+  {
+    return modelQueryAssociationProvider.getCMElementDeclaration(element);
+  }
+   
+  public CMDocumentManager getCMDocumentManager()
+  {
+    CMDocumentManager result = null;
+    if (modelQueryAssociationProvider instanceof XMLAssociationProvider)
+    {             
+      XMLAssociationProvider xmlAssociationProvider = (XMLAssociationProvider)modelQueryAssociationProvider;
+      result = xmlAssociationProvider.getCMDocumentManager();
+    }    
+    return result;
+  }
+       
+
+  /**
+   * @deprected - use 3 arg version below
+   */
+  public List getCMDocumentList(Element element, String uri)
+  {        
+    return Collections.EMPTY_LIST;
+  }
+
+  public List getCMDocumentList(Element element, CMElementDeclaration ed, String uri)
+  {                
+    List result = new ArrayList();
+    if (modelQueryAssociationProvider instanceof XMLAssociationProvider)
+    {              
+      XMLAssociationProvider xmlAssociationProvider = (XMLAssociationProvider)modelQueryAssociationProvider;
+     
+      // todo... revist... handle each ##thing explicitly
+      //          
+      if (uri == null)
+      {
+        uri = "##any"; //$NON-NLS-1$
+      }               
+
+      if (uri.equals("##targetNamespace")) //$NON-NLS-1$
+      {                                                      
+        CMDocument cmDocument = (CMDocument)ed.getProperty("CMDocument"); //$NON-NLS-1$
+        if (cmDocument != null)
+        {  
+          result.add(cmDocument);
+        }
+      }
+      else if (uri.equals("##any") || uri.equals("##other")) //$NON-NLS-1$ //$NON-NLS-2$
+      {                                        
+        String excludedURI = null;
+        if (uri.equals("##other")) //$NON-NLS-1$
+        {
+          CMDocument cmDocument = (CMDocument)ed.getProperty("CMDocument");        //$NON-NLS-1$
+          if (cmDocument != null)
+          {
+            excludedURI = (String)cmDocument.getProperty("http://org.eclipse.wst/cm/properties/targetNamespaceURI"); //$NON-NLS-1$
+          }
+        }
+                               
+        // in this case we should consider all of the schema related to this document
+        //
+        NamespaceTable namespaceTable = new NamespaceTable(element.getOwnerDocument());
+        namespaceTable.addElementLineage(element);
+        List list = namespaceTable.getNamespaceInfoList();
+        for (Iterator i = list.iterator(); i.hasNext();)
+        {
+          NamespaceInfo info = (NamespaceInfo)i.next();
+          if (info.uri != null && !info.uri.equals(excludedURI))
+          {
+            CMDocument document = xmlAssociationProvider.getCMDocument(info.uri, info.locationHint, "XSD"); //$NON-NLS-1$
+            if (document != null)
+            {
+              result.add(document);
+            }
+          }
+        }
+      }   
+      else
+      {        
+        CMDocument document = xmlAssociationProvider.getCMDocument(element, uri);
+        if (document != null)
+        {
+          result.add(document);
+        }
+      }      
+    }
+    return result;
+  }
+
+
+  public CMDocument getCMDocument(Element element, String uri)
+  {                
+
+    CMDocument result = null;
+    if (modelQueryAssociationProvider instanceof XMLAssociationProvider)
+    {             
+      XMLAssociationProvider xmlAssociationProvider = (XMLAssociationProvider)modelQueryAssociationProvider;
+      result = xmlAssociationProvider.getCMDocument(element, uri);
+    }
+    //ContentModelManager.println("ModelQueryImpl.getCMDocument(" + element.getNodeName() + ", " + uri + ") = " + result);
+    return result;
+  }
+
+  public boolean isContentValid(Element element)
+  {               
+    CMElementDeclaration ed = getCMElementDeclaration(element);
+    return isContentValid(ed, element);
+  }
+
+  public boolean isContentValid(CMElementDeclaration ed, Element element)
+  {                                               
+    boolean result = true;    
+    if (ed != null)
+    { 
+      // first check to see if all the required attributes are present
+      //                                                      
+      CMNamedNodeMap map = ed.getAttributes();
+      int mapLength = map.getLength();
+      for (int i = 0; i < mapLength; i++)
+      {                                                           
+        CMAttributeDeclaration ad = (CMAttributeDeclaration)map.item(i);
+        String attributeName = DOMNamespaceHelper.computeName(ad, element, null);
+        if (ad.getUsage() == CMAttributeDeclaration.REQUIRED)
+        {               
+           Attr attr = element.getAttributeNode(attributeName);
+           if (attr == null)
+           {
+             result = false;
+             break;
+           }
+        }
+      }
+
+      // now check to see of the children validate properly
+      //
+      if (result) 
+      {
+        CMNode[] originArray = getOriginArray(element);
+        result = originArray != null && originArray.length == element.getChildNodes().getLength();
+      }
+    }
+    return result;
+  }
+
+
+  public CMNode getOrigin(Node node)
+  {
+    CMNode result = null;
+    // todo... make sure parent is right
+    //
+    Node parentNode = getParentOrOwnerNode(node);
+    if (parentNode != null && parentNode.getNodeType() == Node.ELEMENT_NODE)
+    {
+      Element parentElement = (Element)parentNode;
+      CMNode[] array = getOriginArray(parentElement);
+      if (array != null)
+      {
+        int index = getIndexOfNode(parentElement.getChildNodes(), node);
+        if (index < array.length)
+        {
+          result = array[index];
+        }
+      }
+    }
+    return result;
+  }
+
+  public CMNode[] getOriginArray(Element element)
+  {
+    CMElementDeclaration ed = getCMElementDeclaration(element);
+    return (ed != null) ? getValidator().getOriginArray(ed, element) : null;
+  }
+
+  public int getIndexOfNode(NodeList nodeList, Node node)
+  {
+    int result = -1;
+    int size = nodeList.getLength();
+    for (int i = 0; i < size; i++)
+    {
+       if (nodeList.item(i) == node)
+       {
+         result = i;
+         break;
+       }
+    }
+    return result;
+  }
+
+
+  /**
+   * Returns a list of all CMNode 'meta data' that may be potentially added to the element.
+   */
+  public List getAvailableContent(Element element, CMElementDeclaration ed, int includeOptions)
+  {
+    AvailableContentCMVisitor visitor = new AvailableContentCMVisitor(element, ed);
+    List list = visitor.computeAvailableContent(includeOptions);
+    if (extensionManager != null)
+    {                    
+      extensionManager.filterAvailableElementContent(list, element, ed, includeOptions);
+    }  
+    return list;
+  }  
+
+
+  public boolean canInsert(Element parent, CMNode cmNode, int index, int validityChecking)
+  {
+    boolean result = true;
+    CMElementDeclaration ed = getCMElementDeclaration(parent);
+    if (ed != null)
+    {
+      result = canInsert(parent, ed, cmNode, index, validityChecking);
+    }
+    return result;
+  }
+
+
+  public boolean canInsert(Element parent, CMElementDeclaration ed, CMNode cmNode, int index, int validityChecking)
+  {
+    return canInsert(parent, ed, cmNode, index, validityChecking, null);
+  }         
+
+  protected boolean canInsert(Element parent, CMElementDeclaration ed, CMNode cmNode, int index, int validityChecking, Object reuseableData)
+  {
+    boolean result = true;
+    switch (cmNode.getNodeType())
+    {
+      case CMNode.ATTRIBUTE_DECLARATION :
+      {
+        String attributeName = DOMNamespaceHelper.computeName(cmNode, parent, null);
+        result = parent.getAttributeNode(attributeName) == null;
+        break;
+      }
+      case CMNode.ELEMENT_DECLARATION :
+      case CMNode.GROUP :
+      {
+        if (validityChecking == VALIDITY_STRICT)
+        {                                  
+          // create list                       
+          List contentSpecificationList = null;
+          if (reuseableData != null)
+          {                            
+            contentSpecificationList = (List)reuseableData;
+          }    
+          else
+          {                                                                                  
+            contentSpecificationList = getValidator().createContentSpecificationList(parent, ed);
+          }
+          result = getValidator().canInsert(ed, contentSpecificationList, index, cmNode);
+        }
+        break;
+      }
+      case CMNode.DATA_TYPE :
+      {
+        int contentType = ed.getContentType();
+        result = (contentType == CMElementDeclaration.MIXED ||
+                  contentType == CMElementDeclaration.PCDATA ||
+                  contentType == CMElementDeclaration.ANY);
+        break;
+      }
+      default :
+      {
+        result = false;
+        break;
+      }
+    }
+    return result;
+  }
+
+  public boolean canInsert(Element parent, List cmNodeList, int index, int validityChecking)
+  {
+    // todo
+    return true;
+  }
+
+
+  public boolean canRemove(Node node, int validityChecking)
+  {
+    boolean result = true;      
+    if (validityChecking == VALIDITY_STRICT)
+    {
+      int nodeType = node.getNodeType();
+      switch (nodeType)
+      {
+        case Node.ATTRIBUTE_NODE:
+        {
+          CMAttributeDeclaration ad = getCMAttributeDeclaration((Attr)node);
+          if (ad != null)
+          {
+            result = (ad.getUsage() == CMAttributeDeclaration.OPTIONAL);
+          }
+          break;
+        }
+        case Node.ELEMENT_NODE:
+        {
+          Node parentNode = node.getParentNode();
+          if (parentNode.getNodeType() == Node.ELEMENT_NODE)
+          {
+            Element parentElement = (Element)parentNode;
+            CMElementDeclaration ed = getCMElementDeclaration(parentElement);
+            if (ed != null)
+            {
+              List contentSpecificationList = getValidator().createContentSpecificationList(parentElement, ed);
+              int index = getIndexOfNode(parentElement.getChildNodes(), node);
+              result = getValidator().canRemove(ed, contentSpecificationList, index);
+            }
+          }
+          break;
+        }
+      }
+    }
+    return result;
+  }
+
+
+  public boolean canRemove(List nodeList, int validityChecking)
+  {
+    boolean result = true;
+
+    if (validityChecking == VALIDITY_STRICT)
+    {
+      Element parentElement = null;
+      List childList = null;
+
+      for (Iterator i = nodeList.iterator(); i.hasNext(); )
+      {
+        Node node = (Node)i.next();
+
+        if (parentElement == null)
+        {
+          parentElement = getParentOrOwnerElement(node);
+        }
+        else if (parentElement != getParentOrOwnerElement(node))
+        {
+          // make sure the parent are the same
+          result = false;
+          break;
+        }
+
+        if (parentElement == null)
+        {
+          result = true;
+          break;
+        }
+
+        int nodeType = node.getNodeType();
+        if (nodeType == Node.ATTRIBUTE_NODE)
+        {
+          if (!canRemove(node, validityChecking))
+          {
+            result = false;
+            break;
+          }
+        }
+        else
+        {
+          if (childList == null)
+          {
+            childList = nodeListToList(parentElement.getChildNodes());
+          }
+          childList.remove(node);
+        }
+      }
+
+      if (result && childList != null)
+      {
+        CMElementDeclaration ed = getCMElementDeclaration(parentElement);
+        if (ed != null)
+        {                                
+          List contentSpecificationList = getValidator().createContentSpecificationList(childList, ed);
+          result = getValidator().isValid(ed, contentSpecificationList);
+        }
+      }
+    }
+
+    return result;
+  }
+
+  public boolean canReplace(Element parent, int startIndex, int endIndex, CMNode cmNode, int validityChecking)
+  {
+    return true;
+  }
+
+  public boolean canReplace(Element parent, int startIndex, int endIndex, List cmNodeList, int validityChecking)
+  {
+    return true;
+  }     
+   
+  /**
+   * This method is experimental... use at your own risk
+   */
+  public boolean canWrap(Element childElement, CMElementDeclaration wrapElement, int validityChecking)
+  {                        
+    boolean result = true;  
+    Node parentNode = childElement.getParentNode();                      
+    if (parentNode.getNodeType() == Node.ELEMENT_NODE)
+    {           
+      Element parentElement = (Element)parentNode;      
+      CMElementDeclaration parentEd = getCMElementDeclaration(parentElement);
+      if (parentEd != null)
+      {                                                                                         
+        if (validityChecking == VALIDITY_STRICT)
+        {
+          int index = getIndexOfNode(parentElement.getChildNodes(), childElement);
+
+          List contentSpecificationList = getValidator().createContentSpecificationList(parentElement, parentEd);
+          List subList = contentSpecificationList.subList(index, index + 1);
+          result = getValidator().canReplace(parentEd, contentSpecificationList, index, index, wrapElement);
+          if (result)
+          {
+            result = getValidator().isValid(wrapElement, subList);
+          }
+        }
+      }
+    }
+    else
+    {
+      result = false;
+    }                
+    return result;
+  }
+
+  public void getInsertActions(Element parent, CMElementDeclaration ed, int index, int includeOptions, int validityChecking, List actionList)
+  {
+    modelQueryActionHelper.getInsertActions(parent, ed, index, includeOptions, validityChecking, actionList);
+  }
+
+  public void getInsertActions(Document parent, CMDocument cmDocument, int index, int includeOptions, int validityChecking, List actionList)
+  {
+    modelQueryActionHelper.getInsertActions(parent, cmDocument, index, includeOptions, validityChecking, actionList);
+  }
+
+  public void getReplaceActions(Element parent, CMElementDeclaration ed, int includeOptions, int validityChecking, List actionList)
+  {
+    modelQueryActionHelper.getReplaceActions(parent, ed, includeOptions, validityChecking, actionList);
+  }                     
+
+  public void getReplaceActions(Element parent, CMElementDeclaration ed, List selectedChildren, int includeOptions, int validityChecking, List actionList)
+  {
+    modelQueryActionHelper.getReplaceActions(parent, ed, selectedChildren, includeOptions, validityChecking, actionList);
+  }
+
+  public void getInsertChildNodeActionTable(Element parent, CMElementDeclaration ed, int validityChecking, Hashtable actionTable)
+  {
+    modelQueryActionHelper.getInsertChildNodeActionTable(parent, ed, validityChecking, actionTable);
+  }
+
+  public void getActionTable(Element parent, CMElementDeclaration ed, int index, int validityChecking, Hashtable actionTable)
+  {
+    //modelQueryActionHelper.getAllActions(parent, ed, validityChecking, actionList);
+  }
+
+
+  // some helper methods
+  //
+  protected Node getParentOrOwnerNode(Node node)
+  {
+    return (node.getNodeType() == Node.ATTRIBUTE_NODE) ?
+           ((Attr)node).getOwnerElement() :
+           node.getParentNode();
+  }
+
+  protected Element getParentOrOwnerElement(Node node)
+  {
+    Node parent = getParentOrOwnerNode(node);
+    return (parent.getNodeType() == Node.ELEMENT_NODE) ? (Element)parent : null;
+  }
+               
+
+  protected List nodeListToList(NodeList nodeList)
+  {
+    int size = nodeList.getLength();
+    List v = new ArrayList(size);
+    for (int i = 0; i < size; i++)
+    {
+      v.add(nodeList.item(i));
+    }
+    return v;
+  }   
+   
+  /**
+  protected List getCMNodeList(NodeList nodeList)
+  {
+    int size = nodeList.getLength();
+    Vector v = new Vector(size);
+    for (int i = 0; i < size; i++)
+    {
+      v.add(getCMNode(nodeList.item(i));
+    }
+    return v;
+  }
+  */  
+
+  public class AvailableContentCMVisitor extends CMVisitor
+  {
+    public Hashtable childNodeTable = new Hashtable();
+    public Hashtable attributeTable = new Hashtable();
+    public Element rootElement;
+    public CMElementDeclaration rootElementDeclaration; 
+    public boolean isRootVisited;
+    protected boolean includeSequenceGroups;
+
+    public AvailableContentCMVisitor(Element rootElement, CMElementDeclaration rootElementDeclaration)
+    {                                     
+      this.rootElement = rootElement;
+      this.rootElementDeclaration = rootElementDeclaration;
+    }
+
+    protected String getKey(CMNode cmNode)
+    {
+      String key = cmNode.getNodeName();
+      CMDocument cmDocument = (CMDocument)cmNode.getProperty("CMDocument"); //$NON-NLS-1$
+      if (cmDocument != null)
+      {                         
+        String namespaceURI = (String)cmDocument.getProperty("http://org.eclipse.wst/cm/properties/targetNamespaceURI");    //$NON-NLS-1$
+        if (namespaceURI != null)
+        {   
+          key = "[" + namespaceURI + "]" + key; //$NON-NLS-1$ //$NON-NLS-2$
+        }
+      }
+      return key;
+    }
+    
+    protected void addToTable(Hashtable table, CMNode cmNode)
+    {
+      String nodeName = cmNode.getNodeName();
+      if (nodeName != null && nodeName.length() > 0)
+      {  
+        table.put(getKey(cmNode), cmNode);
+      }  
+    }
+
+    public List computeAvailableContent(int includeOptions)
+    {                   
+      List v = new ArrayList();  
+
+      int contentType = rootElementDeclaration.getContentType();
+      includeSequenceGroups = ((includeOptions & INCLUDE_SEQUENCE_GROUPS) != 0);
+      visitCMNode(rootElementDeclaration);
+      
+      if ((includeOptions & INCLUDE_ATTRIBUTES) != 0)
+      {
+        v.addAll(attributeTable.values());
+        CMAttributeDeclaration nillableAttribute = (CMAttributeDeclaration)rootElementDeclaration.getProperty("http://org.eclipse.wst/cm/properties/nillable"); //$NON-NLS-1$
+        if (nillableAttribute != null)
+        {
+          v.add(nillableAttribute);
+        }
+      }  
+
+      if ((includeOptions & INCLUDE_CHILD_NODES) != 0)
+      {      
+        if (contentType == CMElementDeclaration.MIXED ||
+            contentType == CMElementDeclaration.ELEMENT)
+        {
+          v.addAll(childNodeTable.values());
+        }
+        else if (contentType == CMElementDeclaration.ANY)
+        {      
+          CMDocument cmDocument =  (CMDocument)rootElementDeclaration.getProperty("CMDocument"); //$NON-NLS-1$
+          if (cmDocument != null)
+          {
+            CMNamedNodeMap elements = cmDocument.getElements();            
+            for (Iterator i = elements.iterator(); i.hasNext(); )
+            {
+              v.add(i.next());
+            } 
+          }
+        }
+      }
+      return v;
+    }   
+
+    public void visitCMAnyElement(CMAnyElement anyElement)
+    {            
+      String uri = anyElement.getNamespaceURI();                          
+      List list = getCMDocumentList(rootElement, rootElementDeclaration, uri);
+      for (Iterator iterator = list.iterator(); iterator.hasNext(); )
+      {
+        CMDocument cmdocument = (CMDocument)iterator.next();
+        if (cmdocument != null)
+        {                          
+          CMNamedNodeMap map = cmdocument.getElements();
+          int size = map.getLength();
+          for (int i = 0; i < size; i++)
+          {                       
+            CMNode ed = map.item(i);                  
+            addToTable(childNodeTable,ed);
+          }        
+        }                
+      }
+    }
+
+    public void visitCMAttributeDeclaration(CMAttributeDeclaration ad)
+    {
+      super.visitCMAttributeDeclaration(ad);
+      attributeTable.put(ad.getNodeName(), ad);
+    }
+
+    public void visitCMElementDeclaration(CMElementDeclaration ed)
+    {
+      if (ed == rootElementDeclaration && !isRootVisited)
+      {
+        isRootVisited = true;
+        super.visitCMElementDeclaration(ed);
+      }
+      else
+      {                                                                                  
+        if (!Boolean.TRUE.equals(ed.getProperty("Abstract"))) //$NON-NLS-1$
+        {
+          addToTable(childNodeTable,ed);
+        }
+
+        CMNodeList substitutionGroup = (CMNodeList)ed.getProperty("SubstitutionGroup"); //$NON-NLS-1$
+        if (substitutionGroup != null)
+        {
+          handleSubstitutionGroup(substitutionGroup);
+        }
+      }
+    }                                              
+
+    protected void handleSubstitutionGroup(CMNodeList substitutionGroup)
+    {
+      int substitutionGroupLength = substitutionGroup.getLength();
+      if (substitutionGroupLength > 1)
+      {
+        for (int i = 0; i < substitutionGroupLength; i++)
+        {
+          CMNode ed = substitutionGroup.item(i);
+          if (!Boolean.TRUE.equals(ed.getProperty("Abstract"))) //$NON-NLS-1$
+          {
+            addToTable(childNodeTable,ed);
+          }
+        }
+      }
+    }
+
+    public void visitCMGroup(CMGroup group)
+    {
+      if (includeSequenceGroups)
+      {
+        if (group.getOperator() == CMGroup.SEQUENCE &&
+            group.getChildNodes().getLength() > 1 &&
+            includesRequiredContent(group))
+        {                                        
+          childNodeTable.put(group, group);
+        }
+      }  
+      super.visitCMGroup(group);
+    }   
+
+    public boolean includesRequiredContent(CMGroup group)
+    {
+      List list = getValidator().createContentSpecificationList(group);
+      return list.size() > 1;
+    }
+  }    
+
+ 
+  /**
+   * @deprected - use getPossibleDataTypeValues()
+   */
+  public List getDataTypeValues(Element element, CMNode cmNode)
+  {                                                                             
+    return Arrays.asList(getPossibleDataTypeValues(element, cmNode));
+  }
+  
+  /**
+   * This methods return an array of possible values corresponding to the datatype of the CMNode (either an CMAttributeDeclaration or a CMElementDeclaration)
+   */
+  public String[] getPossibleDataTypeValues(Element element, CMNode cmNode)
+  {
+    List list = new ArrayList();                            
+                               
+    if (cmNode != null)
+    {       
+      CMDataType dataType = null;
+      if (cmNode.getNodeType() == CMNode.ATTRIBUTE_DECLARATION)
+      {
+        dataType = ((CMAttributeDeclaration)cmNode).getAttrType();
+      }
+      else if (cmNode.getNodeType() == CMNode.ELEMENT_DECLARATION)
+      {
+        dataType = ((CMElementDeclaration)cmNode).getDataType();
+      }         
+     
+      String[] enumeratedValues = dataType != null ? dataType.getEnumeratedValues() : null;      
+      if (enumeratedValues != null)
+      {
+        for (int i = 0; i < enumeratedValues.length; i++)
+        {
+          list.add(enumeratedValues[i]);
+        } 
+      }                              
+    }
+                         
+    addValuesForXSIType(element, cmNode, list);
+    
+    if (extensionManager != null)
+    {                    
+      list.addAll(extensionManager.getDataTypeValues(element, cmNode));
+    }          
+    
+    // Remove duplicates
+    List duplicateFreeList = new ArrayList();
+    Iterator iterator = list.iterator();
+    while(iterator.hasNext()) {
+    	Object next = iterator.next();
+    	if(duplicateFreeList.indexOf(next) == -1) {
+    		duplicateFreeList.add(next);
+    	}
+    }
+    
+    return (String[]) duplicateFreeList.toArray(new String[duplicateFreeList.size()]);
+  }    
+
+           
+  protected void addValuesForXSIType(Element element, CMNode cmNode, List list)
+  {               
+    if (cmNode != null && cmNode.getNodeType() == CMNode.ATTRIBUTE_DECLARATION) 
+    {                         
+      CMAttributeDeclaration ad = (CMAttributeDeclaration)cmNode;                              
+      if (valueHelper.isXSIType(ad))
+      {             
+        NamespaceTable table = new NamespaceTable(element.getOwnerDocument());
+        table.addElementLineage(element);
+        list.addAll(valueHelper.getQualifiedXSITypes(ad, table));     
+      }
+    }
+  }
+    
+
+  public ModelQueryExtensionManager getExtensionManager()
+  {
+    return extensionManager;
+  }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelqueryimpl/SimpleAssociationProvider.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelqueryimpl/SimpleAssociationProvider.java
new file mode 100644
index 0000000..de5242f
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelqueryimpl/SimpleAssociationProvider.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.modelqueryimpl;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQueryCMProvider;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+
+/**
+ *
+ */
+public class SimpleAssociationProvider extends BaseAssociationProvider
+{
+  protected ModelQueryCMProvider modelQueryCMProvider;
+          
+  public SimpleAssociationProvider(ModelQueryCMProvider modelQueryCMProvider)
+  {                                              
+    this.modelQueryCMProvider = modelQueryCMProvider;
+  }
+
+  public CMDocument getCorrespondingCMDocument(Node node)
+  {
+    return modelQueryCMProvider.getCorrespondingCMDocument(node);
+  }
+  
+  public CMElementDeclaration getCMElementDeclaration(Element element)
+  {
+    CMElementDeclaration result = null;
+    CMDocument cmDocument = getCorrespondingCMDocument(element);
+    if (cmDocument != null)
+    {        
+      result = (CMElementDeclaration)cmDocument.getElements().getNamedItem(element.getNodeName());    
+    }
+    return result;
+  }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelqueryimpl/XMLAssociationProvider.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelqueryimpl/XMLAssociationProvider.java
new file mode 100644
index 0000000..a05d6a9
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/modelqueryimpl/XMLAssociationProvider.java
@@ -0,0 +1,489 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2011 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.modelqueryimpl;
+
+import java.io.File;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.wst.xml.core.internal.Logger;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.CMDocumentManager;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.CMDocumentReferenceProvider;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.IExternalSchemaLocationProvider;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.CMDocumentCache;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.DOMNamespaceHelper;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.NamespaceInfo;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.NamespaceTable;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+
+/**
+ *
+ */
+public abstract class XMLAssociationProvider extends BaseAssociationProvider implements CMDocumentReferenceProvider
+{              
+  protected CMDocumentCache cmDocumentCache; 
+  protected CMDocumentManagerImpl documentManager;
+
+  private final static boolean _trace = Boolean.valueOf(Platform.getDebugOption("org.eclipse.wst.xml.core/externalSchemaLocation")).booleanValue(); //$NON-NLS-1$
+
+  public XMLAssociationProvider(CMDocumentCache cmDocumentCache)
+  {
+    this.cmDocumentCache = cmDocumentCache; 
+    documentManager = new CMDocumentManagerImpl(cmDocumentCache, this);
+  }                              
+
+  public CMDocumentManager getCMDocumentManager()
+  {
+    return documentManager;
+  }
+ 
+      
+  public static String[] getDoctypeInfo(Document document)
+  {   
+    String[] result = null;
+    DocumentType doctype = document.getDoctype();
+
+    // defect 206833 ... here we test for DTDs that are declared inline
+    // since we currently have no way of making use of inline DTDs we ingore them
+    // so that the implict DTD (if any) can be used
+    if (doctype != null && (doctype.getPublicId() != null || doctype.getSystemId() != null))
+    {
+      result = new String[2];
+      result[0] = doctype.getPublicId();
+      result[1] = doctype.getSystemId();
+    }   
+    else if (getImplictDoctype(document) != null)
+    {
+      result = getImplictDoctype(document);
+    }                  
+    return result;
+  }   
+
+
+  protected static String[] getImplictDoctype(Document document)
+  { 
+    String[] result = null;
+    /*
+    DOMExtension domExtension = DOMExtensionProviderRegistry.getInstance().getDOMExtension(document);
+    if (domExtension != null)
+    {
+      result = domExtension.getImplicitDoctype();
+    }*/
+    return result;
+  }
+
+  public CMDocument getCorrespondingCMDocument(Node node)
+  {        
+    return getCorrespondingCMDocument(node, true);
+  }
+
+  protected CMDocument getCorrespondingCMDocument(Node node, boolean getDocumentFromCMNode)
+  {            
+    CMDocument result = null;
+    try
+    {
+      Document document = node.getNodeType() == Node.DOCUMENT_NODE ? (Document)node : node.getOwnerDocument();
+   
+      String[] doctypeInfo = getDoctypeInfo(document);
+
+      if (doctypeInfo != null)
+      {
+        result = getCMDocument(doctypeInfo[0], doctypeInfo[1], "DTD"); //$NON-NLS-1$
+      }                                             
+      // defect 211236 ... in some cases calling this method can result in a cycle
+      // we use the getDocumentFromCMNode as a flag to avoid this 
+      // TODO... see if there is a way to re-organize to avoid the need for this flag
+      else if (getDocumentFromCMNode)
+      {
+        CMNode cmNode = getCMNode(node);
+        if (cmNode != null)       
+        {                
+          // todo... add a getCMDocument() methods to CMNode
+          // for now use the getProperty interface
+          result = (CMDocument)cmNode.getProperty("CMDocument"); //$NON-NLS-1$
+        }
+      }
+    }
+    catch (Exception e)
+    {
+      Logger.logException("exception locating CMDocument for " + node, e); //$NON-NLS-1$
+    }
+    return result;
+  }    
+
+      
+  public CMDocument getCMDocument(Element element, String uri)
+  {
+    CMDocument result = null;
+    NamespaceTable namespaceTable = new NamespaceTable(element.getOwnerDocument());
+    namespaceTable.addElementLineage(element);
+    NamespaceInfo namespaceInfo = namespaceTable.getNamespaceInfoForURI(uri);
+    if (namespaceInfo != null)
+    {
+      result = getCMDocument(namespaceInfo.uri, namespaceInfo.locationHint, "XSD"); //$NON-NLS-1$
+    }
+    return result;
+  }         
+  
+                          
+  public CMDocument getCMDocument(String publicId, String systemId, String type)
+  {                   
+    //String resolvedGrammarURI = resolveGrammarURI(document, publicId, systemId);
+    return documentManager.getCMDocument(publicId, systemId, type);  
+  }
+
+  //public CMDocument getCMDocument(Document document, String publicId, String systemId)
+  //{                   
+  //  //String resolvedGrammarURI = resolveGrammarURI(document, publicId, systemId);
+  //  return documentManager.getCMDocument(publicId, systemId);  
+  //}
+   
+  public String resolveGrammarURI(String publicId, String systemId)
+  {
+    return resolveGrammarURI(null, publicId, systemId);
+  }
+
+
+  /**
+   * This method should be specialized in order to implement specialized uri resolution
+   */
+  protected String resolveGrammarURI(Document document, String publicId, String systemId)
+  {
+    return systemId;
+  }
+  
+
+  public CMElementDeclaration getCMElementDeclaration(Element element)
+  { 
+    CMElementDeclaration result = null; 
+    Document document = element.getOwnerDocument();
+    String[] doctypeInfo = getDoctypeInfo(document);
+    if (doctypeInfo != null)
+    {   
+      // we have detected doctype information so we assume that we can locate the CMElementDeclaration 
+      // in the CMDocument's table of global elements 
+      CMDocument cmDocument = getCorrespondingCMDocument(element, false);
+
+      // TODO... consider replacing above with 
+      // CMDocument cmDocument = getCMDocument(document, doctypeInfo[0], doctypeInfo[1]);
+
+      if (cmDocument != null)
+      {        
+        result = (CMElementDeclaration)cmDocument.getElements().getNamedItem(element.getNodeName());    
+                 
+        // this is a hack to get our xsl code assist working... we might want to handle similar
+        // grammar behaviour via some established model query setting 
+        if (result == null && getImplictDoctype(document) != null)
+        {         
+          Node parent = element.getParentNode();
+          if (parent != null && parent.getNodeType() == Node.ELEMENT_NODE)
+          {
+            result = getCMElementDeclaration((Element)parent);
+          }
+        }
+      }
+    }    
+    else
+    {  
+      // here we use a namespaceTable to consider if the root element has any namespace information
+      //
+      NamespaceTable namespaceTable = new NamespaceTable(element.getOwnerDocument());
+      List list = NamespaceTable.getElementLineage(element);
+      Element rootElement = (Element)list.get(0);
+      namespaceTable.addElement(rootElement);
+         
+      if (namespaceTable.isNamespaceEncountered())
+      {                                         
+        // we assume that this is an XMLSchema style namespace aware document
+        result = getCMElementDeclaration(element, list, namespaceTable);
+      }
+      else
+      { 
+    	  result = checkExternalSchema(element);
+    	  if (result == null) {
+    		// we assume that this is an inferred CMDocument for a DTD style 'namespaceless' document
+  	        CMDocument cmDocument = getCMDocument("", "", "DTD"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+		      if (cmDocument != null) {
+				  result = (CMElementDeclaration)cmDocument.getElements().getNamedItem(element.getNodeName());
+			  }
+    	  }
+      }
+    }             
+    return result;
+  } 
+     
+  protected CMElementDeclaration checkExternalSchema(Element element) {
+	  final Document document = element.getOwnerDocument();
+	  if (document instanceof IDOMDocument) {
+		  final String baseLocation = ((IDOMDocument) document).getModel().getBaseLocation();
+		  if (baseLocation == null)
+			  return null;
+		  final IPath basePath = new Path(baseLocation);
+		  IFile file = null;
+		  if (basePath.segmentCount() > 1) {
+			  file = ResourcesPlugin.getWorkspace().getRoot().getFile(basePath);
+		  }
+		  final URI uri = (file == null || !file.isAccessible()) ? new File(baseLocation).toURI() : file.getLocationURI();
+		  if (uri != null) {
+			  IExternalSchemaLocationProvider[] providers = ExternalSchemaLocationProviderRegistry.getInstance().getProviders();
+			  for (int i = 0; i < providers.length; i++) {
+				  long time = _trace ? System.currentTimeMillis(): 0;
+				  final Map locations = providers[i].getExternalSchemaLocation(uri);
+				  if (_trace) {
+					  long diff = System.currentTimeMillis() - time;
+					  if (diff > 250)
+						  Logger.log(Logger.INFO, "Schema location provider took [" + diff + "ms] for URI [" + uri + "]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+				  }
+				  if (locations != null && !locations.isEmpty()) {
+					  Object location = locations.get(IExternalSchemaLocationProvider.NO_NAMESPACE_SCHEMA_LOCATION);
+					  if (location != null)
+						  return getCMElementDeclaration(element, NamespaceTable.getElementLineage(element), uri.toString(), location.toString());
+				  }
+			  }
+		  }
+	  }
+	  return null;
+  }
+
+  protected CMElementDeclaration getCMElementDeclaration(Element targetElement, List list, String publicId, String systemId)
+  {         
+    CMElementDeclaration currentED = null;
+    try
+    {    
+      int listSize = list.size();
+      for (int i = 0; i < listSize; i++)
+      {
+        Element element = (Element)list.get(i);                                     
+
+        final String nodeName = element.getNodeName();
+ 
+        CMElementDeclaration ed = null;
+ 
+        // see if the element is a local of the currentED
+        //             
+        if (currentED != null)
+        {  
+          ed = (CMElementDeclaration)currentED.getLocalElements().getNamedItem(nodeName);
+        } 
+                                                                   
+        if (ed == null) 
+        {               
+            CMDocument cmDocument = getCMDocument(publicId, systemId, "XSD"); //$NON-NLS-1$
+            if (cmDocument != null)
+            { 
+              ed = (CMElementDeclaration)cmDocument.getElements().getNamedItem(nodeName);   
+            }                                        
+        }                                                   
+        currentED = ed;     
+      }                                       
+    }
+    catch (Exception e)
+    { 
+      Logger.logException("exception locating element declaration for " + targetElement, e); //$NON-NLS-1$
+    } 
+  
+    return currentED;
+  }  
+
+  protected CMElementDeclaration getCMElementDeclaration(Element targetElement, List list, NamespaceTable namespaceTable)
+  {         
+    CMElementDeclaration currentED = null;
+    try
+    {    
+      int listSize = list.size();
+      for (int i = 0; i < listSize; i++)
+      {
+        Element element = (Element)list.get(i);                                     
+                    
+        if (i != 0)
+        {
+          namespaceTable.addElement(element);                        
+        }
+
+        String nodeName = element.getNodeName();
+        String unprefixedName = DOMNamespaceHelper.getUnprefixedName(nodeName);
+        String prefix = DOMNamespaceHelper.getPrefix(nodeName);
+ 
+        CMElementDeclaration ed = null;
+ 
+        // see if the element is a local of the currentED
+        //             
+        if (currentED != null)
+        {  
+          ed = (CMElementDeclaration)currentED.getLocalElements().getNamedItem(unprefixedName);
+        } 
+                                                                   
+        if (ed == null) 
+        {               
+          NamespaceInfo namespaceInfo = namespaceTable.getNamespaceInfoForPrefix(prefix);                   
+          if (namespaceInfo != null) 
+          {
+            CMDocument cmDocument = getCMDocument(namespaceInfo.uri, namespaceInfo.locationHint, "XSD"); //$NON-NLS-1$
+            if (cmDocument != null)
+            { 
+              ed = (CMElementDeclaration)cmDocument.getElements().getNamedItem(unprefixedName);   
+            }                                        
+          }
+        }                                                   
+        currentED = ed;     
+
+        // handle XSIType     
+        if (currentED != null)
+        {
+          CMElementDeclaration derivedED = getDerivedCMElementDeclaration(element, currentED, namespaceTable);
+          if (derivedED != null)
+          {                           
+            currentED = derivedED;
+          }    
+        }
+      }                                       
+    }
+    catch (Exception e)
+    { 
+      Logger.logException("exception locating element declaration for " + targetElement, e); //$NON-NLS-1$
+    } 
+  
+    return currentED;
+  }  
+      
+
+  protected CMElementDeclaration getDerivedCMElementDeclaration(Element element, CMElementDeclaration ed, NamespaceTable namespaceTable)
+  {                      
+    CMElementDeclaration result = null;
+    String xsiPrefix = namespaceTable.getPrefixForURI("http://www.w3.org/2001/XMLSchema-instance"); //$NON-NLS-1$
+    if (xsiPrefix != null)
+    {
+      String xsiTypeValue = element.hasAttribute(xsiPrefix + ":type") ? element.getAttribute(xsiPrefix + ":type") : null; //$NON-NLS-1$ //$NON-NLS-2$
+      if (xsiTypeValue != null && xsiTypeValue.length() > 0)
+      {  
+        String typePrefix = DOMNamespaceHelper.getPrefix(xsiTypeValue);
+        String typeName = DOMNamespaceHelper.getUnprefixedName(xsiTypeValue);
+        String typeURI = namespaceTable.getURIForPrefix(typePrefix);
+        String uriQualifiedTypeName = typeName;
+        if (typeURI != null && typeURI.length() > 0) 
+        {
+          uriQualifiedTypeName = "[" +  typeURI + "]" + typeName; //$NON-NLS-1$ //$NON-NLS-2$
+        }
+        result = (CMElementDeclaration)ed.getProperty("DerivedElementDeclaration=" + uriQualifiedTypeName);   //$NON-NLS-1$
+      }
+    }                                                                                                    
+    return result;
+  }   
+
+
+  public CMAttributeDeclaration getCMAttributeDeclaration(Attr attr)
+  {
+    CMAttributeDeclaration result = null;
+    Element element = attr.getOwnerElement();
+    if (element != null)
+    {
+      CMElementDeclaration ed = getCMElementDeclaration(element);
+      if (ed != null)
+      {                                                
+        result = (CMAttributeDeclaration)ed.getAttributes().getNamedItem(attr.getName());
+        if (result == null)
+        {                                              
+          // try to get the unprefixed name             
+          String name = DOMNamespaceHelper.getUnprefixedName(attr.getName());
+          result = (CMAttributeDeclaration)ed.getAttributes().getNamedItem(name);
+        }                                                                        
+        if (result == null)
+        {
+          // todo... perhaps this is a globally defined attribute... 
+        }
+      }
+    }
+    return result;
+  }               
+
+  /**
+   * This method returns a list of CMDocumentReferences associated with a particular node or subtree
+   */                                                                                                          
+  public List getCMDocumentReferences(Node node, boolean deep)
+  { 
+    List result = new ArrayList();  
+    Document document = (node.getNodeType() == Node.DOCUMENT_NODE) ? (Document)node : node.getOwnerDocument();
+    DocumentType doctype = document.getDoctype();
+    // defect 206833 ... here we test for DTDs that are declared inline
+    // since we currently have no way of making use of inline DTDs we ingore them
+    // so that the implict DTD (if any) can be used
+    if (doctype != null && (doctype.getPublicId() != null || doctype.getSystemId() != null))
+    {                                                                               
+      String uri = resolveGrammarURI(document, doctype.getPublicId(), doctype.getSystemId());
+      result.add(new CMDocumentReferenceImpl(doctype.getPublicId(), uri));
+    }   
+    else if (getImplictDoctype(document) != null)
+    {                  
+      String[] implicitDoctype = getImplictDoctype(document);
+      String uri = resolveGrammarURI(document, implicitDoctype[0], implicitDoctype[1]);
+      result.add(new CMDocumentReferenceImpl(implicitDoctype[0], uri));
+    }                              
+    else
+    {   
+      NamespaceTable namespaceTable = new NamespaceTable(document);
+      if (node.getNodeType() == Node.ELEMENT_NODE)
+      {
+		    namespaceTable.addElement((Element)node);
+      }                                     
+      if (deep)
+      {
+        addChildElementsToNamespaceTable(node, namespaceTable);
+      }
+	    List list = namespaceTable.getNamespaceInfoList();
+		  for (Iterator i = list.iterator(); i.hasNext();) 
+      {
+			  NamespaceInfo info = (NamespaceInfo) i.next();    
+        String uri = resolveGrammarURI(document, info.uri, info.locationHint);
+        result.add(new CMDocumentReferenceImpl(info.uri, uri));
+		  }	
+    } 
+    return result;
+  }
+
+  protected void addChildElementsToNamespaceTable(Node node, NamespaceTable namespaceTable)
+  {
+    NodeList nodeList = node.getChildNodes();
+	  if (nodeList != null) 
+    {
+		  int nodeListLength = nodeList.getLength();
+		  for (int i = 0; i < nodeListLength; i++) 
+      {
+			  Node childNode = nodeList.item(i);
+        if (childNode.getNodeType() == Node.ELEMENT_NODE)
+        {   
+          namespaceTable.addElement((Element)childNode);
+          addChildElementsToNamespaceTable(childNode, namespaceTable);
+        }
+		  }
+	  }
+  }  
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/util/CMDescriptionBuilder.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/util/CMDescriptionBuilder.java
new file mode 100644
index 0000000..a82ab1c
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/util/CMDescriptionBuilder.java
@@ -0,0 +1,140 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2008 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.util;
+
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAnyElement;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMContent;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNodeList;
+
+public class CMDescriptionBuilder extends CMVisitor
+{
+  protected StringBuffer sb;
+  protected CMNode root;
+  protected boolean isRootVisited;
+  public String buildDescription(CMNode node)
+  {
+    sb = new StringBuffer();
+    root = node;
+    isRootVisited = false;
+    visitCMNode(node);
+    return sb.toString();
+  }       
+
+  public void visitCMAnyElement(CMAnyElement anyElement)
+  {
+    sb.append("namespace:uri=\"" + anyElement.getNamespaceURI() + "\""); //$NON-NLS-1$ //$NON-NLS-2$
+  }
+
+  public void visitCMDataType(CMDataType dataType)
+  {
+    sb.append("#PCDATA"); //$NON-NLS-1$
+  }
+
+  public void visitCMDocument(CMDocument document)
+  {
+    CMNamedNodeMap map = document.getElements();
+    int size = map.getLength();
+    for (int i = 0; i < size; i++)
+    {
+      visitCMNode(map.item(i));
+    }
+  }
+
+  public void visitCMGroup(CMGroup group)
+  {
+    int op = group.getOperator();
+    if (op == CMGroup.ALL)
+    {
+      sb.append("all"); //$NON-NLS-1$
+    }
+
+    sb.append("("); //$NON-NLS-1$
+
+    String separator = ", "; //$NON-NLS-1$
+
+    if (op == CMGroup.CHOICE)
+    {
+      separator = " | "; //$NON-NLS-1$
+    }
+    
+   
+    CMNodeList nodeList = group.getChildNodes();
+    int size = nodeList.getLength();
+    for (int i = 0; i < size; i++)
+    {
+      visitCMNode(nodeList.item(i));
+      if (i < size - 1)
+      {
+        sb.append(separator);
+      }
+    }
+    
+    sb.append(")"); //$NON-NLS-1$
+    addOccurenceSymbol(group);
+  }
+
+  public void visitCMElementDeclaration(CMElementDeclaration ed)
+  {
+    if (ed == root && !isRootVisited)
+    {
+      isRootVisited = true;
+      CMContent content = ed.getContent();
+      if (content != null)
+      {
+        if (content.getNodeType() != CMNode.GROUP)
+        {
+          sb.append("("); //$NON-NLS-1$
+          visitCMNode(content);
+          sb.append(")"); //$NON-NLS-1$
+        }
+        else
+        {
+          visitCMNode(content);
+        }
+      }
+    }
+    else
+    {
+      sb.append(ed.getElementName());
+      addOccurenceSymbol(ed);
+    }
+  }
+
+  public void addOccurenceSymbol(CMContent content)
+  {
+    int min = content.getMinOccur();
+    int max = content.getMaxOccur();
+    if (min == 0)
+    {
+      if (max > 1 || max == -1)
+      {
+        sb.append("*"); //$NON-NLS-1$
+      }
+      else
+      {
+        sb.append("?"); //$NON-NLS-1$
+      }
+    }
+    else if (max > 1 || max == -1)
+    {
+      sb.append("+"); //$NON-NLS-1$
+    }
+  }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/util/CMDocumentCache.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/util/CMDocumentCache.java
new file mode 100644
index 0000000..670ff53
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/util/CMDocumentCache.java
@@ -0,0 +1,203 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.util;
+
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+
+
+
+/**
+ *
+ */
+public class CMDocumentCache
+{                                     
+  public static final int STATUS_NOT_LOADED = 0;
+  public static final int STATUS_LOADING    = 2;
+  public static final int STATUS_LOADED     = 3;
+  public static final int STATUS_ERROR      = 4;
+
+  protected class Entry
+  {
+    public String uri;
+    public int status = STATUS_NOT_LOADED;
+    public float progress;
+    public CMDocument cmDocument;
+
+    public Entry(String uri)
+    {                      
+      this.uri = uri;         
+    }
+
+    public Entry(String uri, int status, CMDocument cmDocument)
+    {                                     
+      this.uri = uri;
+      this.status = status;      
+      this.cmDocument = cmDocument;
+    }
+  }
+
+  protected Hashtable hashtable;
+  protected List listenerList = new Vector();
+
+
+  /**
+   * temporarily public until caching problem is solved
+   */
+  public CMDocumentCache()
+  {
+    hashtable = new Hashtable();
+  }
+
+  public void addListener(CMDocumentCacheListener listener)
+  {
+    listenerList.add(listener);
+  }
+
+  public void removeListener(CMDocumentCacheListener listener)
+  {
+    listenerList.remove(listener);
+  }   
+
+  /**
+   *
+   */
+  public CMDocument getCMDocument(String grammarURI)
+  {
+    CMDocument result = null;
+    if (grammarURI != null)
+    {  
+      Entry entry = (Entry)hashtable.get(grammarURI);
+      if (entry != null)
+      {
+        result = entry.cmDocument;
+      }   
+    }
+    return result;
+  }    
+
+  /**
+   *
+   */
+  public int getStatus(String grammarURI)
+  {
+    int result = STATUS_NOT_LOADED;
+    if (grammarURI != null)
+    {  
+      Entry entry = (Entry)hashtable.get(grammarURI);
+      if (entry != null)
+      {
+        result = entry.status;
+      }      
+      
+    }
+    return result;
+  }            
+            
+  /**
+   *
+   */
+  protected Entry lookupOrCreate(String grammarURI)
+  {
+    Entry entry = (Entry)hashtable.get(grammarURI);
+    if (entry == null)
+    {
+      entry = new Entry(grammarURI);                       
+      hashtable.put(grammarURI, entry);
+    }
+    return entry;
+  }
+
+    
+  /**
+   *
+   */
+  public void putCMDocument(String grammarURI, CMDocument cmDocument)
+  {                                    
+    if (grammarURI != null && cmDocument != null)
+    {                           
+      Entry entry = lookupOrCreate(grammarURI);
+      int oldStatus = entry.status;
+      entry.status = STATUS_LOADED;
+      entry.cmDocument = cmDocument;  
+      notifyCacheUpdated(grammarURI, oldStatus, entry.status, entry.cmDocument);  
+    }
+  }
+     
+  /**
+   *
+   */
+  public void setStatus(String grammarURI, int status)
+  {
+    if (grammarURI != null)
+    {
+      Entry entry = lookupOrCreate(grammarURI);
+      int oldStatus = entry.status;
+      entry.status = status;
+      notifyCacheUpdated(grammarURI, oldStatus, entry.status, entry.cmDocument);   
+    }
+  }
+     
+  /**
+   *
+   */
+  public void clear()
+  {
+    hashtable.clear();
+    notifyCacheCleared();
+  }  
+
+  /**
+   *
+   */
+  protected void notifyCacheUpdated(String uri, int oldStatus, int newStatus, CMDocument cmDocument)
+  {      
+    List list = new Vector();
+    list.addAll(listenerList);
+    for (Iterator i = list.iterator(); i.hasNext(); )
+    {
+      CMDocumentCacheListener listener = (CMDocumentCacheListener)i.next();
+      listener.cacheUpdated(this, uri, oldStatus, newStatus, cmDocument);
+    }
+  }
+
+  /**
+   *
+   */
+  protected void notifyCacheCleared()
+  {     
+    List list = new Vector();
+    list.addAll(listenerList);
+    for (Iterator i = list.iterator(); i.hasNext(); )
+    {
+      CMDocumentCacheListener listener = (CMDocumentCacheListener)i.next();
+      listener.cacheCleared(this);
+    }
+  }
+  
+  public List getCMDocuments()
+  {
+  	List list = new ArrayList();  	
+  	for (Iterator i = hashtable.values().iterator(); i.hasNext(); )
+  	{
+  		Entry entry = (Entry)i.next();
+  		list.add(entry.cmDocument);
+  	}
+  	return list;
+  }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/util/CMDocumentCacheListener.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/util/CMDocumentCacheListener.java
new file mode 100644
index 0000000..d9f6dcd
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/util/CMDocumentCacheListener.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.util;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+
+
+/**
+ * todo... add more interface methods
+ */
+public interface CMDocumentCacheListener
+{
+  /** Tells the client that the cache has been cleared.
+   *  This gives clients an opportunity to flush any state that depends on the CMDocument
+   *  since this CMDocument will be recomputed on a subsequent 'lookup' request
+   */
+  public void cacheCleared(CMDocumentCache cache); 
+
+  /** 
+   *  Tells the client that the cache has been updated.  
+   */
+  public void cacheUpdated(CMDocumentCache cache, String uri, int oldStatus, int newStatus, CMDocument cmDocument);
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/util/CMVisitor.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/util/CMVisitor.java
new file mode 100644
index 0000000..89bb9d6
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/util/CMVisitor.java
@@ -0,0 +1,135 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2008 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.util;
+
+import java.util.Stack;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAnyElement;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNodeList;
+
+public class CMVisitor
+{
+  protected int indent = 0;
+  protected Stack visitedCMGroupStack = new Stack();
+
+  public void visitCMNode(CMNode node)
+  {
+    if (node != null)
+    {
+      //ContentModelManager.printlnIndented("visitCMNode : " + node.getNodeName() + " " + node);
+      indent += 2;
+      int nodeType = node.getNodeType();
+      switch (nodeType)
+      {
+        case CMNode.ANY_ELEMENT :
+        {
+          visitCMAnyElement((CMAnyElement)node);
+          break;
+        }
+        case CMNode.ATTRIBUTE_DECLARATION :
+        {
+          visitCMAttributeDeclaration((CMAttributeDeclaration)node);
+          break;
+        }
+        case CMNode.DATA_TYPE :
+        {
+          visitCMDataType((CMDataType)node);
+          break;
+        }
+        case CMNode.DOCUMENT :
+        {
+          visitCMDocument((CMDocument)node);
+          break;
+        }
+        case CMNode.ELEMENT_DECLARATION :
+        {
+          visitCMElementDeclaration((CMElementDeclaration)node);
+          break;
+        }
+        case CMNode.GROUP :
+        {
+          CMGroup group = (CMGroup)node;
+          
+          // This is to prevent recursion.
+          if (visitedCMGroupStack.contains(group))
+          {
+            break;
+          }
+          
+          // Push the current group to check later to avoid potential recursion
+          visitedCMGroupStack.push(group);
+          
+          visitCMGroup(group);
+
+          // Pop the current group
+          visitedCMGroupStack.pop();
+          break;
+        }
+      }
+      indent -= 2;
+    }
+  }
+      
+  public void visitCMAnyElement(CMAnyElement anyElement)
+  {
+  }
+
+  public void visitCMAttributeDeclaration(CMAttributeDeclaration ad)
+  {
+  }
+
+  public void visitCMDataType(CMDataType dataType)
+  {
+  }
+
+  public void visitCMDocument(CMDocument document)
+  {
+    CMNamedNodeMap map = document.getElements();
+    int size = map.getLength();
+    for (int i = 0; i < size; i++)
+    {
+      visitCMNode(map.item(i));
+    }
+  }
+
+  public void visitCMGroup(CMGroup group)
+  {
+    CMNodeList nodeList = group.getChildNodes();
+    int size = nodeList.getLength();
+    for (int i = 0; i < size; i++)
+    {
+      visitCMNode(nodeList.item(i));
+    }
+  }
+
+  public void visitCMElementDeclaration(CMElementDeclaration ed)
+  {
+    CMNamedNodeMap nodeMap = ed.getAttributes();
+    int size = nodeMap.getLength();
+    for (int i = 0; i < size; i++)
+    {
+      visitCMNode(nodeMap.item(i));
+    }
+
+    visitCMNode(ed.getContent());
+
+    visitCMDataType(ed.getDataType());
+  }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/util/ContentBuilder.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/util/ContentBuilder.java
new file mode 100644
index 0000000..14d02b1
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/util/ContentBuilder.java
@@ -0,0 +1,171 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.util;
+
+import java.util.Vector;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAnyElement;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMContent;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNodeList;
+
+                   
+/**
+ * This class lets you traverse a 'CM' model providing callbacks to build content.
+ */
+public class ContentBuilder extends CMVisitor
+{
+  public static final int BUILD_ALL_CONTENT = 1;
+  public static final int BUILD_ONLY_REQUIRED_CONTENT = 2;
+  protected int buildPolicy = BUILD_ALL_CONTENT;
+
+  protected boolean alwaysVisit;
+  protected Vector visitedCMElementDeclarationList = new Vector();
+
+  public ContentBuilder()
+  {
+  }
+                
+  public void setBuildPolicy(int buildPolicy)
+  {
+    this.buildPolicy = buildPolicy;
+  }
+
+  public int getBuildPolicy()
+  {
+    return buildPolicy;
+  }                
+           
+  protected void createAnyElementNode(CMAnyElement anyElement)
+  {
+  }
+
+  protected void createElementNodeStart(CMElementDeclaration ed)
+  {      
+  }
+
+  protected void createElementNodeEnd(CMElementDeclaration ed)
+  {
+  }
+
+  protected void createTextNode(CMDataType dataType)
+  {
+  } 
+
+  protected void createAttributeNode(CMAttributeDeclaration attribute)
+  {
+  } 
+ 
+  public void visitCMElementDeclaration(CMElementDeclaration ed)
+  {
+    int forcedMin = (buildPolicy == BUILD_ALL_CONTENT || alwaysVisit) ? 1 : 0;
+    int min = Math.max(ed.getMinOccur(), forcedMin);                          
+    alwaysVisit = false;
+
+    if (min > 0 && !visitedCMElementDeclarationList.contains(ed))
+    {
+      visitedCMElementDeclarationList.add(ed);
+      for (int i = 1; i <= min; i++)
+      {       
+        createElementNodeStart(ed);       
+        
+        // instead of calling super.visitCMElementDeclaration()
+        // we duplicate the code with some minor modifications
+        CMNamedNodeMap nodeMap = ed.getAttributes();
+        int size = nodeMap.getLength();
+        for (int j = 0; j < size; j++)
+        {
+          visitCMNode(nodeMap.item(j));
+        }
+
+        CMContent content = ed.getContent();
+        if (content != null)
+        {
+          visitCMNode(content);
+        }
+
+        if (ed.getContentType() == CMElementDeclaration.PCDATA)
+        {
+          CMDataType dataType = ed.getDataType();
+          if (dataType != null)
+          {
+            visitCMDataType(dataType);
+          }
+        }
+        // end duplication
+        createElementNodeEnd(ed);  
+      }
+      int size = visitedCMElementDeclarationList.size();
+      visitedCMElementDeclarationList.remove(size - 1);
+    }
+  }
+    
+
+  public void visitCMDataType(CMDataType dataType)
+  {
+    createTextNode(dataType);   
+  }
+
+
+  public void visitCMGroup(CMGroup e)
+  { 
+    int forcedMin = (buildPolicy == BUILD_ALL_CONTENT || alwaysVisit) ? 1 : 0;
+    int min = Math.max(e.getMinOccur(), forcedMin);                          
+    alwaysVisit = false;
+
+    for (int i = 1; i <= min; i++)
+    {   
+      if (e.getOperator() == CMGroup.CHOICE)
+      {
+        // add only 1 element from the group
+        // todo... perhaps add something other than the first one        
+        CMNodeList nodeList = e.getChildNodes();
+        if (nodeList.getLength() > 0)
+        {
+          visitCMNode(nodeList.item(0));
+        }
+      }
+      else // SEQUENCE, ALL
+      {
+        // visit all of the content
+        super.visitCMGroup(e);
+      }
+    }
+  } 
+
+  public void visitCMAttributeDeclaration(CMAttributeDeclaration ad)
+  {
+    if (alwaysVisit ||
+        buildPolicy == BUILD_ALL_CONTENT ||
+        ad.getUsage() == CMAttributeDeclaration.REQUIRED)
+    {
+      createAttributeNode(ad);      
+    }
+  }                     
+  
+
+  public void visitCMAnyElement(CMAnyElement anyElement)
+  {  
+    int forcedMin = (buildPolicy == BUILD_ALL_CONTENT || alwaysVisit) ? 1 : 0;
+    alwaysVisit = false; 
+    int min = Math.max(anyElement.getMinOccur(), forcedMin);                          
+    for (int i = 1; i <= min; i++)
+    {                                
+      createAnyElementNode(anyElement);
+    }
+  }     
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/util/DOMContentBuilder.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/util/DOMContentBuilder.java
new file mode 100644
index 0000000..9d23576
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/util/DOMContentBuilder.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.util;
+
+import java.util.List;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.w3c.dom.Node;
+
+
+public interface DOMContentBuilder
+{
+  public static final int BUILD_OPTIONAL_ATTRIBUTES = 1;
+  public static final int BUILD_OPTIONAL_ELEMENTS = 1<<1;
+  public static final int BUILD_FIRST_CHOICE = 1<<2;
+  public static final int BUILD_TEXT_NODES = 1<<3;
+  public static final int BUILD_FIRST_SUBSTITUTION = 1<<4;
+  
+  public static final int 
+    BUILD_ONLY_REQUIRED_CONTENT =
+      BUILD_FIRST_CHOICE
+      | BUILD_TEXT_NODES;
+  public static final int 
+    BUILD_ALL_CONTENT = 
+      BUILD_OPTIONAL_ATTRIBUTES 
+      | BUILD_OPTIONAL_ELEMENTS 
+      | BUILD_FIRST_CHOICE
+      | BUILD_TEXT_NODES;
+      
+  public static final String PROPERTY_BUILD_BLANK_TEXT_NODES = "buildBlankTextNodes"; //$NON-NLS-1$
+  
+  public void setBuildPolicy(int buildPolicy);
+  public int  getBuildPolicy();
+  public void setProperty(String propertyName, Object value);
+  public Object getProperty(String propertyName);
+  public List getResult();
+  public void build(Node parent, CMNode child);
+  public void createDefaultRootContent(CMDocument cmDocument, CMElementDeclaration rootCMElementDeclaration) throws Exception;
+  public void createDefaultRootContent(CMDocument cmDocument, CMElementDeclaration rootCMElementDeclaration, List namespaceInfoList) throws Exception;
+  public void createDefaultContent(Node parent, CMElementDeclaration ed) throws Exception;
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/util/DOMContentBuilderImpl.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/util/DOMContentBuilderImpl.java
new file mode 100644
index 0000000..290f6f5
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/util/DOMContentBuilderImpl.java
@@ -0,0 +1,636 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.util;
+
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Stack;
+import java.util.Vector;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAnyElement;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMContent;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNodeList;
+import org.eclipse.wst.xml.core.internal.contentmodel.ContentModelManager;
+import org.eclipse.wst.xml.core.internal.contentmodel.internal.util.CMDataTypeValueHelper;
+import org.w3c.dom.Attr;
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.ProcessingInstruction;
+import org.w3c.dom.Text;
+
+
+/**
+ * todo... common up this code with 'ContentBuilder'
+ */
+public class DOMContentBuilderImpl extends CMVisitor implements DOMContentBuilder {
+	protected int buildPolicy = BUILD_ALL_CONTENT;
+	protected Hashtable propertyTable = new Hashtable();
+
+	protected boolean alwaysVisit = false;
+	protected List resultList;
+	protected Document document;
+	protected Node currentParent;
+	protected Node topParent;
+	protected Vector visitedCMElementDeclarationList = new Vector();
+	protected boolean attachNodesToParent = true;
+	protected NamespaceTable namespaceTable;
+
+	protected List namespaceInfoList;
+	protected Element rootElement; // this is used only teporarily via
+									// createDefaultRootContent
+	protected ExternalCMDocumentSupport externalCMDocumentSupport;
+
+	public boolean supressCreationOfDoctypeAndXMLDeclaration;
+
+	protected CMDataTypeValueHelper valueHelper = new CMDataTypeValueHelper();
+
+	protected int numOfRepeatableElements = 1;
+	protected Stack cmGroupStack = new Stack();
+	protected int depthLimit = -1;
+
+	protected int domLevel;
+	private int originalBuildPolicy;
+	
+	public interface ExternalCMDocumentSupport {
+		public CMDocument getCMDocument(Element element, String uri);
+	}
+
+	public void setExternalCMDocumentSupport(ExternalCMDocumentSupport externalCMDocumentSupport) {
+		this.externalCMDocumentSupport = externalCMDocumentSupport;
+	}
+
+	public DOMContentBuilderImpl(Document document) {
+		this.document = document;
+		namespaceTable = new NamespaceTable(document);
+	}
+
+	public void setBuildPolicy(int buildPolicy) {
+		this.buildPolicy = buildPolicy;
+	}
+
+	public int getBuildPolicy() {
+		return buildPolicy;
+	}
+
+	protected boolean buildAllContent(int policy) {
+		return (policy & BUILD_ALL_CONTENT) == BUILD_ALL_CONTENT;
+	}
+
+	protected boolean buildOptionalElements(int policy) {
+		return (policy & BUILD_OPTIONAL_ELEMENTS) == BUILD_OPTIONAL_ELEMENTS;
+	}
+
+	protected boolean buildOptionalAttributes(int policy) {
+		return (policy & BUILD_OPTIONAL_ATTRIBUTES) == BUILD_OPTIONAL_ATTRIBUTES;
+	}
+
+	protected boolean buildFirstChoice(int policy) {
+		return (policy & BUILD_FIRST_CHOICE) == BUILD_FIRST_CHOICE;
+	}
+
+	protected boolean buildTextNodes(int policy) {
+		return (policy & BUILD_TEXT_NODES) == BUILD_TEXT_NODES;
+	}
+
+	protected boolean buildFirstSubstitution(int policy) {
+		return (policy & BUILD_FIRST_SUBSTITUTION) == BUILD_FIRST_SUBSTITUTION;
+	}
+
+	public List getResult() {
+		return resultList;
+	}
+
+	public void setProperty(String propertyName, Object value) {
+		propertyTable.put(propertyName, value);
+	}
+
+	public Object getProperty(String propertyName) {
+		return propertyTable.get(propertyName);
+	}
+
+	public void build(Node parent, CMNode child) {
+		resultList = new Vector();
+		topParent = parent;
+		currentParent = parent;
+		if (parent instanceof Element) {
+			namespaceTable.addElementLineage((Element) parent);
+		}
+		attachNodesToParent = false;
+		alwaysVisit = true;
+		visitCMNode(child);
+	}
+
+	public void createDefaultRootContent(CMDocument cmDocument, CMElementDeclaration rootCMElementDeclaration, List namespaceInfoList) throws Exception {
+		this.namespaceInfoList = namespaceInfoList;
+		createDefaultRootContent(cmDocument, rootCMElementDeclaration);
+	}
+
+	public void createDefaultRootContent(CMDocument cmDocument, CMElementDeclaration rootCMElementDeclaration) throws Exception {
+		String grammarFileName = cmDocument.getNodeName();
+		if (!supressCreationOfDoctypeAndXMLDeclaration) {
+			// TODO cs... investigate to see if this code path is ever used,
+			// doesn't seem to be
+			// for now I'm setting the encoding to UTF-8 just incase this code
+			// path is used somewhere
+			//
+			String piValue = "version=\"1.0\""; //$NON-NLS-1$
+			String encoding = "UTF-8"; //$NON-NLS-1$
+			piValue += " encoding=\"" + encoding + "\""; //$NON-NLS-1$ //$NON-NLS-2$      
+			ProcessingInstruction pi = document.createProcessingInstruction("xml", piValue); //$NON-NLS-1$
+			document.appendChild(pi);
+
+			// if we have a 'dtd' then add a DOCTYPE tag
+			//
+			if (grammarFileName != null && grammarFileName.endsWith("dtd")) //$NON-NLS-1$
+			{
+				DOMImplementation domImpl = document.getImplementation();
+				DocumentType documentType = domImpl.createDocumentType(rootCMElementDeclaration.getElementName(), grammarFileName, grammarFileName);
+				document.appendChild(documentType);
+			}
+		}
+
+		// if we have a schema add an xsi:schemaLocation attribute
+		//
+		if (grammarFileName != null && grammarFileName.endsWith("xsd") && namespaceInfoList != null) //$NON-NLS-1$
+		{
+			DOMNamespaceInfoManager manager = new DOMNamespaceInfoManager();
+			String name = rootCMElementDeclaration.getNodeName();
+			if (namespaceInfoList.size() > 0) {
+				NamespaceInfo info = (NamespaceInfo) namespaceInfoList.get(0);
+				if (info.prefix != null && info.prefix.length() > 0) {
+					name = info.prefix + ":" + name; //$NON-NLS-1$
+				}
+			}
+			rootElement = createElement(rootCMElementDeclaration, name, document);
+			manager.addNamespaceInfo(rootElement, namespaceInfoList, true);
+		}
+		createDefaultContent(document, rootCMElementDeclaration);
+	}
+
+	public void createDefaultContent(Node parent, CMElementDeclaration ed) {
+		currentParent = parent;
+		alwaysVisit = true;
+		originalBuildPolicy = buildPolicy;
+		visitCMElementDeclaration(ed);
+	}
+
+	public String computeName(CMNode cmNode, Node parent) {
+		String prefix = null;
+		return DOMNamespaceHelper.computeName(cmNode, parent, prefix, namespaceTable);
+	}
+
+	// overide the following 'create' methods to control how nodes are created
+	//
+	protected Element createElement(CMElementDeclaration ed, String name, Node parent) {
+		return document.createElement(name);
+	}
+
+	protected Attr createAttribute(CMAttributeDeclaration ad, String name, Node parent) {
+		return document.createAttribute(name);
+	}
+
+	protected Text createTextNode(CMDataType dataType, String value, Node parent) {
+		return document.createTextNode(value);
+	}
+
+	protected void handlePushParent(Element parent, CMElementDeclaration ed) {
+	  domLevel++;
+	}
+
+	protected void handlePopParent(Element element, CMElementDeclaration ed) {
+      domLevel--;
+	}
+
+	// The range must be between 1 and 99.
+	public void setNumOfRepeatableElements(int i) {
+		numOfRepeatableElements = i;
+	}
+
+	protected int getNumOfRepeatableElements() {
+		return numOfRepeatableElements;
+	}
+
+	public void visitCMElementDeclaration(CMElementDeclaration ed) {
+		int forcedMin = (buildOptionalElements(buildPolicy) || alwaysVisit) ? 1 : 0;
+		int min = Math.max(ed.getMinOccur(), forcedMin);
+
+		// Correct the min value if the element is contained in
+		// a group.
+		if (!cmGroupStack.isEmpty()) {
+			CMGroup group = (CMGroup) cmGroupStack.peek();
+			int gmin = group.getMinOccur();
+			if (gmin == 0)
+				if (buildOptionalElements(buildPolicy)) { 
+					/* do nothing: min = min */
+				}
+				else {
+					min = min * gmin; // min = 0
+				}
+			else {
+				min = min * gmin;
+			}
+		}
+
+		int max = Math.min(ed.getMaxOccur(), getNumOfRepeatableElements());
+		if (max < min)
+			max = min;
+
+		alwaysVisit = false;
+
+		// Note - ed may not be abstract but has substitutionGroups
+		// involved.
+		if (buildFirstSubstitution(buildPolicy) || isAbstract(ed)) // leave
+																	// this
+																	// for
+																	// backward
+																	// compatibility
+																	// for now
+		{
+			// Note - To change so that if ed is optional, we do not
+			// generate anything here.
+			ed = getSubstitution(ed);
+
+			// Note - the returned ed may be an abstract element in
+			// which case the xml will be invalid.
+		}
+
+		if (min > 0 && !visitedCMElementDeclarationList.contains(ed)) {
+			visitedCMElementDeclarationList.add(ed);
+			for (int i = 1; i <= max; i++) {
+				// create an Element for each
+				Element element = null;
+				if (rootElement != null) {
+					element = rootElement;
+					rootElement = null;
+				}
+				else {
+					element = createElement(ed, computeName(ed, currentParent), currentParent);
+				}
+
+				// visit the children of the GrammarElement
+				Node oldParent = currentParent;
+				currentParent = element;
+				handlePushParent(element, ed);
+
+				namespaceTable.addElement(element);
+
+				boolean oldAttachNodesToParent = attachNodesToParent;
+				attachNodesToParent = true;
+
+				// instead of calling super.visitCMElementDeclaration()
+				// we duplicate the code with some minor modifications
+				CMNamedNodeMap nodeMap = ed.getAttributes();
+				int size = nodeMap.getLength();
+				for (int j = 0; j < size; j++) {
+					visitCMNode(nodeMap.item(j));
+				}
+
+				CMContent content = ed.getContent();
+				if (content != null) {
+					visitCMNode(content);
+				}
+
+				if (ed.getContentType() == CMElementDeclaration.PCDATA) {
+					CMDataType dataType = ed.getDataType();
+					if (dataType != null) {
+						visitCMDataType(dataType);
+					}
+				}
+				// end duplication
+				attachNodesToParent = oldAttachNodesToParent;
+				handlePopParent(element, ed);
+				currentParent = oldParent;
+				linkNode(element);
+			}
+			int size = visitedCMElementDeclarationList.size();
+			visitedCMElementDeclarationList.remove(size - 1);
+		}
+	}
+
+
+	public void visitCMDataType(CMDataType dataType) {
+		Text text = null;
+		String value = null;
+
+		// For backward compatibility:
+		// Previous code uses a property value but new one uses
+		// buildPolicy.
+		if (getProperty(PROPERTY_BUILD_BLANK_TEXT_NODES) != null && getProperty(PROPERTY_BUILD_BLANK_TEXT_NODES).equals("true")) //$NON-NLS-1$
+			buildPolicy = buildPolicy ^ BUILD_TEXT_NODES;
+
+		if (buildTextNodes(buildPolicy)) {
+			value = valueHelper.getValue(dataType);
+			if (value == null) {
+				if (currentParent != null && currentParent.getNodeType() == Node.ELEMENT_NODE) {
+					value = currentParent.getNodeName();
+				}
+				else {
+					value = "pcdata"; //$NON-NLS-1$
+				}
+			}
+		}
+		else {
+			value = ""; //$NON-NLS-1$
+		}
+		text = createTextNode(dataType, value, currentParent);
+		linkNode(text);
+	}
+
+	public void visitCMNode(CMNode node) {
+		if (depthLimit != -1) {
+			if (domLevel > depthLimit) {
+				buildPolicy = buildPolicy &= ~BUILD_OPTIONAL_ELEMENTS;
+			} else {
+				buildPolicy = originalBuildPolicy;
+			}
+		}
+		super.visitCMNode(node);
+	}
+
+	public void visitCMGroup(CMGroup e) {
+		cmGroupStack.push(e);
+
+		int forcedMin = (buildOptionalElements(buildPolicy) || alwaysVisit) ? 1 : 0;
+		int min = Math.max(e.getMinOccur(), forcedMin);
+
+		int max = 0;
+		if (e.getMaxOccur() == -1) // unbounded
+			max = getNumOfRepeatableElements();
+		else
+			max = Math.min(e.getMaxOccur(), getNumOfRepeatableElements());
+
+		if (max < min)
+			max = min;
+
+		alwaysVisit = false;
+
+		for (int i = 1; i <= max; i++) {
+			if (e.getOperator() == CMGroup.CHOICE && buildFirstChoice(buildPolicy)) {
+				CMNode hintNode = null;
+
+				// todo... the CMGroup should specify the hint... but it seems
+				// as though
+				// the Yamato guys are making the CMElement specify the hint.
+				// I do it that way for now until... we should fix this post
+				// GA
+				//    
+				int listSize = visitedCMElementDeclarationList.size();
+				if (listSize > 0) {
+					CMElementDeclaration ed = (CMElementDeclaration) visitedCMElementDeclarationList.get(listSize - 1);
+					Object contentHint = ed.getProperty("contentHint"); //$NON-NLS-1$
+					if (contentHint instanceof CMNode) {
+						hintNode = (CMNode) contentHint;
+					}
+				}
+
+				// see if this hint corresponds to a valid choice
+				//
+				CMNode cmNode = null;
+
+				if (hintNode != null) {
+					CMNodeList nodeList = e.getChildNodes();
+					int nodeListLength = nodeList.getLength();
+					for (int j = 0; j < nodeListLength; j++) {
+						if (hintNode == nodeList.item(j)) {
+							cmNode = hintNode;
+						}
+					}
+				}
+
+				// if no cmNode has been determined from the hint, just use
+				// the first choice
+				//
+				if (cmNode == null) {
+					CMNodeList nodeList = e.getChildNodes();
+					if (nodeList.getLength() > 0) {
+						cmNode = nodeList.item(0);
+					}
+				}
+
+				if (cmNode != null) {
+					// Bug 330260
+					// Problem - Add child element also adds optional grand-child elements
+					// This assumes 'e' is a model group choice, case 1. However 'e' could be a model group definition, case 2, where the
+					// first child is a model group. In the first case (choice), the first child is an
+					// element. Upon visiting the element (visitCMElementDeclaration), the minOccurs of the
+					// choice is ALSO considered. If its minOccurs is 0, then the first element is not added as a child.
+					// However, in the second case (model group definition), the first child is a choice, but the multiplicity is [1,1],
+					// meaning, it is required. So the first element is then added as child, even though
+					// the model group definition reference is optional. (minOccurs is not checked in this method, visitCMGroup)
+					// Visit the node only if it is not a GROUP (model group). If it is an element, then visit it.
+					if (!(cmNode.getNodeType() == CMNode.GROUP && min > 0)) {
+						visitCMNode(cmNode);
+					}
+				}
+			}
+			else if (e.getOperator() == CMGroup.ALL // ALL
+						|| e.getOperator() == CMGroup.SEQUENCE) // SEQUENCE
+			{
+				// visit all of the content
+				super.visitCMGroup(e);
+			}
+		}
+
+		cmGroupStack.pop();
+	}
+
+	static int count = 0;
+
+	public void visitCMAttributeDeclaration(CMAttributeDeclaration ad) {
+		if (alwaysVisit || buildOptionalAttributes(buildPolicy) || ad.getUsage() == CMAttributeDeclaration.REQUIRED) {
+			alwaysVisit = false;
+			String name = computeName(ad, currentParent);
+			String value = valueHelper.getValue(ad, namespaceTable);
+			Attr attr = createAttribute(ad, name, currentParent);
+			attr.setValue(value != null ? value : ""); //$NON-NLS-1$
+			linkNode(attr);
+		}
+	}
+
+	protected boolean isAbstract(CMNode ed) {
+		boolean result = false;
+		if (ed != null) {
+			Object value = ed.getProperty("Abstract"); //$NON-NLS-1$
+			result = (value == Boolean.TRUE);
+		}
+		return result;
+	}
+
+	protected CMElementDeclaration getSubstitution(CMElementDeclaration ed) {
+		CMElementDeclaration result = ed;
+		CMNodeList l = (CMNodeList) ed.getProperty("SubstitutionGroup"); //$NON-NLS-1$
+		if (l != null) {
+			for (int i = 0; i < l.getLength(); i++) {
+				CMNode candidate = l.item(i);
+				if (!isAbstract(candidate) && (candidate instanceof CMElementDeclaration)) {
+					result = (CMElementDeclaration) candidate;
+					break;
+				}
+			}
+		}
+		return result;
+	}
+
+	protected CMElementDeclaration getParentCMElementDeclaration() {
+		CMElementDeclaration ed = null;
+		int listSize = visitedCMElementDeclarationList.size();
+		if (listSize > 0) {
+			ed = (CMElementDeclaration) visitedCMElementDeclarationList.get(listSize - 1);
+		}
+		return ed;
+	}
+
+	public void visitCMAnyElement(CMAnyElement anyElement) {
+		// ingnore buildPolicy for ANY elements... only create elements if
+		// absolutely needed
+		//
+		int forcedMin = alwaysVisit ? 1 : 0;
+		int min = Math.max(anyElement.getMinOccur(), forcedMin);
+		alwaysVisit = false;
+
+		String uri = anyElement.getNamespaceURI();
+		String targetNSProperty = "http://org.eclipse.wst/cm/properties/targetNamespaceURI"; //$NON-NLS-1$
+		CMDocument parentCMDocument = (CMDocument) anyElement.getProperty("CMDocument"); //$NON-NLS-1$
+		CMElementDeclaration ed = null;
+
+		// System.out.println("parentCMDocument = " + parentCMDocument);
+		// //$NON-NLS-1$
+		if (parentCMDocument != null) {
+			if (uri == null || uri.startsWith("##") || uri.equals(parentCMDocument.getProperty(targetNSProperty))) //$NON-NLS-1$
+			{
+				ed = getSuitableElement(getParentCMElementDeclaration(), parentCMDocument);
+			}
+		}
+
+
+		if (ed == null && externalCMDocumentSupport != null && uri != null && !uri.startsWith("##") && currentParent instanceof Element) //$NON-NLS-1$
+		{
+			CMDocument externalCMDocument = externalCMDocumentSupport.getCMDocument((Element) currentParent, uri);
+			if (externalCMDocument != null) {
+				ed = getSuitableElement(null, externalCMDocument);
+			}
+		}
+
+		for (int i = 1; i <= min; i++) {
+			if (ed != null) {
+				visitCMElementDeclaration(ed);
+			}
+			else {
+				Element element = document.createElement("ANY-ELEMENT"); //$NON-NLS-1$
+				linkNode(element);
+			}
+		}
+	}
+
+	protected CMElementDeclaration getSuitableElement(CMNamedNodeMap nameNodeMap) {
+		CMElementDeclaration result = null;
+		int size = nameNodeMap.getLength();
+		for (int i = 0; i < size; i++) {
+			CMElementDeclaration candidate = (CMElementDeclaration) nameNodeMap.item(i);
+			if (!visitedCMElementDeclarationList.contains(candidate)) {
+				result = candidate;
+				break;
+			}
+		}
+		return result;
+	}
+
+	protected CMElementDeclaration getSuitableElement(CMElementDeclaration ed, CMDocument cmDocument) {
+		CMElementDeclaration result = null;
+
+		if (ed != null) {
+			result = getSuitableElement(ed.getLocalElements());
+		}
+
+		if (result == null && cmDocument != null) {
+			result = getSuitableElement(cmDocument.getElements());
+		}
+
+		return result;
+	}
+
+
+	public void linkNode(Node node) {
+		if (attachNodesToParent && currentParent != null) {
+			if (node.getNodeType() == Node.ATTRIBUTE_NODE) {
+				((Element) currentParent).setAttributeNode((Attr) node);
+			}
+			else {
+				currentParent.appendChild(node);
+			}
+		}
+		else if (resultList != null) {
+			resultList.add(node);
+		}
+	}
+
+	public static void testPopulateDocumentFromGrammarFile(Document document, String grammarFileName, String rootElementName, boolean hack) {
+		try {
+			CMDocument cmDocument = ContentModelManager.getInstance().createCMDocument(grammarFileName, null);
+			CMNamedNodeMap elementMap = cmDocument.getElements();
+			CMElementDeclaration element = (CMElementDeclaration) elementMap.getNamedItem(rootElementName);
+
+			DOMContentBuilderImpl contentBuilder = new DOMContentBuilderImpl(document);
+			contentBuilder.supressCreationOfDoctypeAndXMLDeclaration = hack;
+			contentBuilder.createDefaultRootContent(cmDocument, element);
+
+			System.out.println();
+			System.out.println("-----------------------------"); //$NON-NLS-1$
+			DOMWriter writer = new DOMWriter();
+			if (hack) {
+				writer.print(document, grammarFileName);
+			}
+			else {
+				writer.print(document);
+			}
+			System.out.println("-----------------------------"); //$NON-NLS-1$
+		}
+		catch (Exception e) {
+			System.out.println("Error: " + e); //$NON-NLS-1$
+			e.printStackTrace();
+		}
+	}
+	
+	public void setOptionalElementDepthLimit(int depth) {
+		depthLimit = depth;
+	}
+	
+
+	// test
+	//
+	/*
+	 * public static void main(String arg[]) { if (arg.length >= 2) { try {
+	 * CMDocumentFactoryRegistry.getInstance().registerCMDocumentBuilderWithClassName("org.eclipse.wst.xml.core.internal.contentmodel.mofimpl.CMDocumentBuilderImpl");
+	 * 
+	 * String grammarFileName = arg[0]; String rootElementName = arg[1];
+	 * 
+	 * Document document =
+	 * (Document)Class.forName("org.apache.xerces.dom.DocumentImpl").newInstance();
+	 * testPopulateDocumentFromGrammarFile(document, grammarFileName,
+	 * rootElementName, true); } catch (Exception e) {
+	 * System.out.println("DOMContentBuilderImpl error"); e.printStackTrace(); } }
+	 * else { System.out.println("Usage : java
+	 * org.eclipse.wst.xml.util.DOMContentBuildingCMVisitor grammarFileName
+	 * rootElementName"); } }
+	 */
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/util/DOMNamespaceHelper.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/util/DOMNamespaceHelper.java
new file mode 100644
index 0000000..049d445
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/util/DOMNamespaceHelper.java
@@ -0,0 +1,198 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.util;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+
+public class DOMNamespaceHelper
+{                
+  protected static String getURIForPrefix(Element element, String prefix)
+  {              
+    String result = null;
+	  String nsAttrName = null;
+	  if (prefix != null && prefix.length() > 0) 
+    {
+		  nsAttrName = "xmlns:" + prefix; //$NON-NLS-1$
+	  }
+	  else 
+    {
+		  nsAttrName = "xmlns"; //$NON-NLS-1$
+	  }
+            
+    // assume the node is qualified... look up the URI base on the prefix
+    //
+	  for (Node node = element; node != null; node = node.getParentNode()) 
+    {
+	   	if (node.getNodeType() == Node.ELEMENT_NODE)
+      {
+        Element theElement = (Element)node;
+		    Attr attr = theElement.getAttributeNode(nsAttrName);
+		    if (attr != null) 
+        {
+          result = attr.getValue();
+        }
+      }
+      else
+      {
+        break;
+      }
+    }
+         
+    // see if we can find some info from an 'implicit' namespace
+    //
+    if (result == null)
+    {                                
+      NamespaceTable table = new NamespaceTable(element.getOwnerDocument());
+      result = table.getURIForPrefix(prefix);
+    }
+    return result;
+	}
+
+  public static String getNamespaceURI(Node node)
+  {            
+    String result = null;
+    if (node.getNodeType() == Node.ELEMENT_NODE)
+    {               
+      Element element = (Element)node;
+      String prefix = element.getPrefix();
+      result = getURIForPrefix(element, prefix);
+    }
+    else if (node.getNodeType() == Node.ATTRIBUTE_NODE)
+    {      
+      Attr attr = (Attr)node;
+      String prefix = attr.getPrefix();
+      result = getURIForPrefix(attr.getOwnerElement(), prefix);
+    }
+    return result;
+  }                 
+
+  // todo... this is an ugly hack... needs to be fixed
+  //
+  public static String computePrefix(CMNode cmNode, Node parentNode)
+  {
+    String result = null;
+    for (Node node = parentNode; node != null; node = node.getParentNode())
+    {
+      if (node.getNodeType() == Node.ELEMENT_NODE)
+      {
+        result = getPrefix(node.getNodeName());
+        if (result != null)
+        {
+          break;
+        }
+      }
+    }
+    return result;
+  }        
+
+
+  public static String getPrefix(String name)
+  {
+    String prefix = null;
+    int index = name.indexOf(":"); //$NON-NLS-1$
+    if (index != -1)
+    {
+      prefix = name.substring(0, index);
+    }
+    return prefix;
+  }
+
+
+  public static String getUnprefixedName(String name)
+  {
+    int index = name.indexOf(":"); //$NON-NLS-1$
+    if (index != -1)
+    {
+      name = name.substring(index + 1);
+    }
+    return name;
+  }
+
+
+  public static String computeName(CMNode cmNode, Node parent, String prefix)
+  {     
+    return computeName(cmNode, parent, prefix, null);
+  }   
+
+
+  public static String computeName(CMNode cmNode, Node parent, String prefix, NamespaceTable namespaceTable)
+  {
+    String result = cmNode.getNodeName();
+
+    // if the cmNode has a hard coded prefix then we don't need to do anything
+    //
+    if (getPrefix(result) == null)
+    {              
+      String qualification = (String)cmNode.getProperty("http://org.eclipse.wst/cm/properties/nsPrefixQualification"); //$NON-NLS-1$
+      // see if we need a namespace prefix
+      //
+      if (qualification != null && qualification.equals("qualified")) //$NON-NLS-1$
+      {            
+        if (prefix == null)                 
+        {
+          // todo... add getCMDocument() method to CMNode
+          // for now use this getProperty() hack
+          CMDocument cmDocument = (CMDocument)cmNode.getProperty("CMDocument"); //$NON-NLS-1$
+          if (cmDocument != null)          
+          {     
+            String namespaceURI = (String)cmDocument.getProperty("http://org.eclipse.wst/cm/properties/targetNamespaceURI");    //$NON-NLS-1$
+            if (namespaceURI != null)
+            {   
+              // use the NamespaceTable to figure out the correct prefix for this namespace uri
+              //      
+              if (namespaceTable == null)
+              {                                            
+                Document document = parent.getNodeType() == Node.DOCUMENT_NODE ? (Document)parent : parent.getOwnerDocument();
+                namespaceTable = new NamespaceTable(document);
+                if (parent instanceof Element)
+                {
+                  namespaceTable.addElementLineage((Element)parent);
+                }
+              }
+              prefix = namespaceTable.getPrefixForURI(namespaceURI);
+            }
+          }
+        }
+        if (prefix != null && prefix.length() > 0)
+        {
+          result = prefix + ":" + result; //$NON-NLS-1$
+        }
+      }    
+    }
+    return result;
+  }  
+  
+
+  public static String[] getURIQualifiedNameComponents(String uriQualifiedName)
+  {
+    String[] result = new String[2];
+    int firstIndex = uriQualifiedName.indexOf("["); //$NON-NLS-1$
+    int lastIndex = uriQualifiedName.indexOf("]"); //$NON-NLS-1$
+    if (firstIndex != -1 && lastIndex > firstIndex)
+    {
+      result[0] = uriQualifiedName.substring(firstIndex + 1, lastIndex);
+      result[1] = uriQualifiedName.substring(lastIndex + 1);
+    }  
+    else
+    {
+      result[1] = uriQualifiedName;
+    }                              
+    return result;
+  }   
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/util/DOMNamespaceInfoManager.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/util/DOMNamespaceInfoManager.java
new file mode 100644
index 0000000..747efbc
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/util/DOMNamespaceInfoManager.java
@@ -0,0 +1,225 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.util;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+
+/**
+ * DOMNamespaceInfoManager          
+ *
+ *
+ */
+public class DOMNamespaceInfoManager
+{                               
+  public static final String XSI_URI = "http://www.w3.org/2001/XMLSchema-instance"; //$NON-NLS-1$
+
+  public DOMNamespaceInfoManager()
+  {
+  }                 
+
+  public List getNamespaceInfoList(Element element)
+  {
+    NamespaceInfoReader reader = new NamespaceInfoReader();
+    return reader.getNamespaceInfoList(element);
+  }            
+   
+  public void removeNamespaceInfo(Element element)
+  {     
+    NamespaceInfoRemover remover = new NamespaceInfoRemover();
+    remover.removeNamespaceInfo(element);
+  }
+
+  public void addNamespaceInfo(Element element, List namespaceInfoList, boolean needsXSI)
+  {  
+    // first we create an xmlns attribute for each namespace
+    //                   
+    Document document = element.getOwnerDocument();
+                                
+    String schemaLocationValue = "";      //$NON-NLS-1$
+
+    for (Iterator iterator = namespaceInfoList.iterator(); iterator.hasNext(); )
+    {
+      NamespaceInfo nsInfo = (NamespaceInfo)iterator.next();
+      nsInfo.normalize();
+               
+      if (nsInfo.uri != null) 
+      {            
+        String attrName = nsInfo.prefix != null ? "xmlns:" + nsInfo.prefix : "xmlns"; //$NON-NLS-1$ //$NON-NLS-2$
+        Attr namespaceAttr = document.createAttribute(attrName);  
+        namespaceAttr.setValue(nsInfo.uri);
+        element.setAttributeNode(namespaceAttr);   
+
+        // in this case we use the attribute "xsi:schemaLocation"
+        // here we build up its value
+        //
+        if (nsInfo.locationHint != null)
+        {
+          schemaLocationValue += nsInfo.uri;
+          schemaLocationValue += " "; //$NON-NLS-1$
+          schemaLocationValue += nsInfo.locationHint;
+          schemaLocationValue += " ";    //$NON-NLS-1$
+        }   
+
+        if (nsInfo.uri.equals(XSI_URI))
+        {
+          needsXSI = false;
+        }
+      }     
+      else if (nsInfo.locationHint != null)
+      {
+        // in this case we use the attribute "xsi:noNamespaceSchemaLocation"
+        //
+        Attr attr = document.createAttribute("xsi:noNamespaceSchemaLocation");   //$NON-NLS-1$
+        attr.setValue(nsInfo.locationHint);
+        element.setAttributeNode(attr);
+      } 
+    } 
+
+    if (needsXSI)
+    {
+      // we add an xmlns:xsi attribute to define 'xsi:schemaLocation' attribute
+      //   
+      Attr attr = document.createAttribute("xmlns:xsi"); //$NON-NLS-1$
+      attr.setValue(XSI_URI);
+      element.setAttributeNode(attr);
+    }
+
+    if (schemaLocationValue.length() > 0)
+    {
+      // create the "xsi:schemaLocation" attribute
+      //
+      Attr attr = document.createAttribute("xsi:schemaLocation"); //$NON-NLS-1$
+      attr.setValue(schemaLocationValue);
+      element.setAttributeNode(attr);
+    }                             
+  } 
+       
+  /**
+   *
+   */
+  protected static class NamespaceInfoReader extends NamespaceAttributeVisitor
+  {  
+    protected List namespaceInfoList = new Vector();
+
+    public List getNamespaceInfoList(Element element)
+    {
+      visitElement(element);
+      return namespaceInfoList;
+    }
+                       
+
+    public void visitXSINoNamespaceSchemaLocationAttribute(Attr attr, String value)
+    {
+      NamespaceInfo info = createNamespaceInfo();
+      info.locationHint = value;      
+    }
+    
+    public void visitXMLNamespaceAttribute(Attr attr, String prefix, String uri)
+    {           
+      NamespaceInfo info = createNamespaceInfo();
+      info.uri = uri;
+      info.prefix = prefix;      
+      super.visitXMLNamespaceAttribute(attr, prefix, uri);
+    }
+
+    public void visitXSISchemaLocationValuePair(String uri, String locationHint)
+    {    
+      NamespaceInfo info = getNamespaceInfoForURI(uri);            
+      if (info != null)
+      {
+        info.locationHint = locationHint;
+      } 
+      else
+      {
+        info = createNamespaceInfo();
+        info.uri = uri;
+        info.locationHint = locationHint;
+      }
+    }                                                                 
+
+    protected NamespaceInfo getNamespaceInfoForURI(String uri)
+    {    
+      NamespaceInfo result = null;
+      for (Iterator i = namespaceInfoList.iterator(); i.hasNext(); )
+      {
+        NamespaceInfo info = (NamespaceInfo)i.next();
+        if (info.uri != null && info.uri.equals(uri))
+        {
+          result = info;
+          break;
+        }
+      }         
+      return result;
+    }     
+
+    protected NamespaceInfo createNamespaceInfo()
+    {
+      NamespaceInfo info = new NamespaceInfo();
+      namespaceInfoList.add(info);
+      return info;
+    }
+  }
+     
+                                                
+  /**
+   *
+   */
+  protected static class NamespaceInfoRemover extends NamespaceAttributeVisitor
+  {                   
+    protected List attributesToRemove = new Vector();
+
+    public void removeNamespaceInfo(Element element)
+    {  
+      visitElement(element);
+      removeAttributes();
+    }   
+
+    public void visitXSINoNamespaceSchemaLocationAttribute(Attr attr, String value)
+    {
+      attributesToRemove.add(attr);
+    }        
+    
+    public void visitXMLNamespaceAttribute(Attr attr, String namespacePrefix, String namespaceURI)
+    {   
+      attributesToRemove.add(attr);
+      super.visitXMLNamespaceAttribute(attr, namespacePrefix, namespaceURI);
+    }
+    
+    public void visitXSISchemaLocationAttribute(Attr attr, String value)
+    {
+      attributesToRemove.add(attr);
+    }   
+
+    public void removeAttributes()
+    {
+      for (Iterator i = attributesToRemove.iterator(); i.hasNext(); )
+      {
+        Attr attr = (Attr)i.next();
+        Element element = attr.getOwnerElement();
+        if (element != null)
+        {
+          element.removeAttributeNode(attr);
+        }
+      }
+    }   
+  }
+
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/util/DOMVisitor.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/util/DOMVisitor.java
new file mode 100644
index 0000000..0742f7b
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/util/DOMVisitor.java
@@ -0,0 +1,133 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.util;
+
+import org.w3c.dom.Attr;
+import org.w3c.dom.CDATASection;
+import org.w3c.dom.Comment;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.ProcessingInstruction;
+import org.w3c.dom.Text;
+
+// todo.. move this class to another package (perhaps xmlutility)
+//
+public class DOMVisitor
+{         
+  public void visitNode(Node node)
+  {
+    switch (node.getNodeType())
+    {
+      case Node.ATTRIBUTE_NODE :
+      {
+        visitAttr((Attr)node);
+        break;
+      }
+      case Node.CDATA_SECTION_NODE :
+      {
+        visitCDATASection((CDATASection)node);
+        break;
+      }
+      case Node.COMMENT_NODE :
+      {
+        visitComment((Comment)node);
+        break;
+      }
+      case Node.DOCUMENT_NODE :
+      {
+        visitDocument((Document)node);
+        break;
+      }
+      case Node.DOCUMENT_TYPE_NODE :
+      {
+        visitDocumentType((DocumentType)node);
+        break;
+      }
+      case Node.ELEMENT_NODE :
+      {
+        visitElement((Element)node);
+        break;
+      }
+      case Node.PROCESSING_INSTRUCTION_NODE :
+      {
+        visitProcessingInstruction((ProcessingInstruction)node);
+        break;
+      }
+      case Node.TEXT_NODE :
+      {
+        visitText((Text)node);
+        break;
+      }
+    }  
+  }    
+    
+  protected void visitDocument(Document document)
+  {                   
+    visitChildNodesHelper(document);
+  }
+
+  protected void visitDocumentType(DocumentType doctype)
+  {         
+
+  }  
+
+  protected void visitElement(Element element)
+  {        
+    visitAttributesHelper(element);
+    visitChildNodesHelper(element);
+  } 
+ 
+
+  public void visitAttr(Attr attr)
+  {                                  
+  }
+
+  protected void visitText(Text text)
+  {    
+  }
+
+  protected void visitCDATASection(CDATASection cdataSection)
+  {                       
+  }     
+
+  protected void visitComment(Comment comment)
+  {                   
+  }   
+
+  protected void visitProcessingInstruction(ProcessingInstruction pi)
+  {    
+  }
+ 
+
+  protected void visitChildNodesHelper(Node node)
+  {
+    NodeList children = node.getChildNodes();
+    for (int i = 0; i < children.getLength(); i++)
+    {
+      visitNode(children.item(i));
+    }
+  }
+
+  protected void visitAttributesHelper(Node node)
+  {
+    NamedNodeMap map = node.getAttributes();
+    for (int i = 0; i < map.getLength(); i++ )
+    {
+      visitNode(map.item(i));
+    }
+  }         
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/util/DOMWriter.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/util/DOMWriter.java
new file mode 100644
index 0000000..736c1f3
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/util/DOMWriter.java
@@ -0,0 +1,411 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.util;
+
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.io.UnsupportedEncodingException;
+import java.io.Writer;
+
+import org.w3c.dom.Attr;
+import org.w3c.dom.CDATASection;
+import org.w3c.dom.Comment;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.ProcessingInstruction;
+import org.w3c.dom.Text;
+
+
+/**
+ * This is a hacked up dom writer stolen from a Xerces sample.
+ * I'd like to use an exisitng 'generic DOM' writer
+ * If anyone can find such a thing then please go ahead and junk this.
+ *
+ * @version
+ */
+public class DOMWriter
+{
+  protected boolean formattingEnabled = true;
+   protected boolean outputDoctypeEnabled = true;
+   protected PrintWriter out;
+   protected int indent = 0;  
+
+   public DOMWriter() throws UnsupportedEncodingException
+   {
+     this(System.out);
+   }
+
+   public DOMWriter(OutputStream outputSteam)
+   {
+     out = new PrintWriter(outputSteam);
+   }
+
+   public DOMWriter(Writer writer)
+   {
+     out = new PrintWriter(writer);
+   }
+
+   public void setFormattingEnabled(boolean enabled)
+   {
+     formattingEnabled = enabled;
+   }
+
+   public boolean getFormattingEnabled()
+   {
+     return formattingEnabled;
+   }
+
+   public void setOutputDoctypeEnabled(boolean enabled)
+   {
+     outputDoctypeEnabled = enabled;
+   }
+
+   public class XMLVisitor
+   {
+     protected boolean currentElementHasChildElements = false;
+
+     public void visitNode(Node node)
+     {
+       switch (node.getNodeType())
+       {
+         case Node.ATTRIBUTE_NODE :
+         {
+           visitAttr((Attr)node);
+           break;
+         }
+         case Node.CDATA_SECTION_NODE :
+         {
+           visitCDATASection((CDATASection)node);
+           break;
+         }
+         case Node.COMMENT_NODE :
+         {
+           visitComment((Comment)node);
+           break;
+         }
+         case Node.DOCUMENT_NODE :
+         {
+           visitDocument((Document)node);
+           break;
+         }
+         case Node.DOCUMENT_TYPE_NODE :
+         {
+           visitDocumentType((DocumentType)node);
+           break;
+         }
+         case Node.ELEMENT_NODE :
+         {
+           visitElement((Element)node);
+           break;
+         }
+         case Node.PROCESSING_INSTRUCTION_NODE :
+         {
+           visitProcessingInstruction((ProcessingInstruction)node);
+           break;
+         }
+         case Node.TEXT_NODE :
+         {
+           visitText((Text)node);
+           break;
+         }
+       }
+     }
+
+     public void visitDocument(Document document)
+     {
+       visitChildNodesHelper(document);
+     }
+
+     public void visitDocumentType(DocumentType doctype)
+     {                       
+       if (outputDoctypeEnabled)
+       {
+         String data = getDocumentTypeData(doctype);
+         print("<!DOCTYPE " + data + ">"); //$NON-NLS-1$ //$NON-NLS-2$
+       }
+     }
+
+     public void visitElement(Element element)
+     {                                  
+       if (!doShow(element))
+         return;
+
+       boolean parentElementHasChildNodes = currentElementHasChildElements;
+       currentElementHasChildElements = hasChildElements(element);
+
+       printIndent();
+       print("<"); //$NON-NLS-1$
+       print(element.getNodeName());
+       visitAttributesHelper(element);
+
+       boolean hasChildNodes = element.getChildNodes().getLength() > 0;                
+       boolean isRootElement = element.getParentNode().getNodeType() == Node.DOCUMENT_NODE;
+       if (hasChildNodes || isRootElement)
+       {
+         if (currentElementHasChildElements)
+         {
+           println(">"); //$NON-NLS-1$
+         }
+         else
+         {
+           print(">"); //$NON-NLS-1$
+         }
+         indent += 2;
+         visitChildNodesHelper(element);
+         indent -= 2;
+
+         if (currentElementHasChildElements || isRootElement)
+         {
+           printIndent();
+         }
+         print("</"); //$NON-NLS-1$
+         print(element.getNodeName());
+         println(">"); //$NON-NLS-1$
+       }
+       else
+       {
+         println("/>"); //$NON-NLS-1$
+       }
+
+       currentElementHasChildElements = parentElementHasChildNodes;
+     }
+
+     public void visitAttr(Attr attr)
+     {
+       print(" "); //$NON-NLS-1$
+       print(attr.getNodeName());
+       print("=\""); //$NON-NLS-1$
+       print(createPrintableCharacterData(attr.getValue()));
+       print("\""); //$NON-NLS-1$
+     }
+
+     public void visitText(Text text)
+     {
+       if (currentElementHasChildElements)
+       {
+         printIndent();
+         print(createPrintableCharacterData(text.getNodeValue()));
+         println();
+       }
+       else
+       {
+         print(createPrintableCharacterData(text.getNodeValue()));
+       }
+     }
+
+     public void visitCDATASection(CDATASection cdataSection)
+     {
+     }
+
+     public void visitComment(Comment comment)
+     {
+       printIndent();
+       print("<!--"); //$NON-NLS-1$
+       print(comment.getNodeValue());
+       println("-->"); //$NON-NLS-1$
+     }
+
+     public void visitProcessingInstruction(ProcessingInstruction pi)
+     {
+       printIndent();
+       print("<?"); //$NON-NLS-1$
+       print(pi.getNodeName());
+       print(" "); //$NON-NLS-1$
+       print(pi.getNodeValue());
+       println("?>"); //$NON-NLS-1$
+     }
+             
+
+     public boolean hasChildElements(Node node)
+     {
+       boolean result = false;
+       NodeList children = node.getChildNodes();
+       for (int i = 0; i < children.getLength(); i++)
+       {
+         if (children.item(i).getNodeType() == Node.ELEMENT_NODE)
+         {
+           result = true;
+           break;
+         }
+       }
+       return result;
+     }
+
+     public void visitChildNodesHelper(Node node)
+     {
+       NodeList children = node.getChildNodes();
+       for (int i = 0; i < children.getLength(); i++)
+       {
+         visitNode(children.item(i));
+       }
+     }
+
+     public void visitAttributesHelper(Node node)
+     {
+       NamedNodeMap map = node.getAttributes();
+       for (int i = 0; i < map.getLength(); i++ )
+       {
+         visitNode(map.item(i));
+       }
+     }
+   }
+
+  /** an ugly hack until I restruct this code a little
+   *  
+   */  
+  protected boolean doShow(Element element)    
+  {
+    return true;
+  }
+                                               
+  /** converts DOM text values to 'printable' values 
+   *  - converts '&' to '&amp;'
+   */
+  protected String createPrintableCharacterData(String string)
+  {              
+    String result = ""; //$NON-NLS-1$
+    int index = 0;                             
+    while (true)
+    {                                                 
+      int ampersandIndex = string.indexOf("&", index); //$NON-NLS-1$
+      if (ampersandIndex != -1)
+      {
+        result += string.substring(index, ampersandIndex);
+        result += "&amp;"; //$NON-NLS-1$
+        index = ampersandIndex + 1; 
+      }
+      else
+      {
+        break;
+      }
+    } 
+    result += string.substring(index);
+    return result;
+  }
+
+
+  /** Prints the specified node, recursively. */
+  public void print(Node node)
+  {
+    // is there anything to do?
+    if (node != null)
+    {
+      XMLVisitor visitor = new XMLVisitor();
+      visitor.visitNode(node);
+    }
+    out.flush();
+  }
+
+  /** a temporary hack to workaround our inability to create a DocumentType tag*/
+  public void print(Document document, String grammarURL)
+  {
+    String systemId = null;
+    if (grammarURL.endsWith("dtd")) //$NON-NLS-1$
+    {
+      int lastSlashIndex = Math.max(grammarURL.lastIndexOf("/"), grammarURL.lastIndexOf("\\")); //$NON-NLS-1$ //$NON-NLS-2$
+      if (lastSlashIndex != -1)
+      {
+        systemId = grammarURL.substring(lastSlashIndex + 1);
+      }
+    }
+    print(document, "UTF-8", grammarURL, null, systemId); //$NON-NLS-1$
+
+  }
+
+  /** a temporary hack to workaround our inability to create a DocumentType tag*/
+  public void print(Document document, String encoding, String grammarFileName, String publicId, String systemId)
+  {
+    out.println("<?xml version=\"1.0\"" + " encoding=\"" + encoding + "\"?>");   //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+    if (grammarFileName.endsWith(".dtd")) //$NON-NLS-1$
+    {
+      String docTypeLine = "<!DOCTYPE " + document.getDocumentElement().getNodeName() + " "; //$NON-NLS-1$ //$NON-NLS-2$
+      if (publicId != null) 
+      {
+        docTypeLine += "PUBLIC \"" + publicId + "\" "; //$NON-NLS-1$ //$NON-NLS-2$
+        if (systemId != null)
+        {
+          docTypeLine += "\"" + systemId + "\" "; //$NON-NLS-1$ //$NON-NLS-2$
+        }
+        docTypeLine += ">"; //$NON-NLS-1$
+        out.println(docTypeLine);
+      }
+      else if (systemId != null)
+      {
+        docTypeLine += "SYSTEM \"" + systemId + "\" >"; //$NON-NLS-1$ //$NON-NLS-2$
+        out.println(docTypeLine);
+      }
+    }
+    print(document);
+  }  
+
+  public static String getDocumentTypeData(DocumentType doctype)
+  {
+    String data = doctype.getName();
+    if (doctype.getPublicId() != null)
+    {
+      data += " PUBLIC \"" + doctype.getPublicId() + "\""; //$NON-NLS-1$ //$NON-NLS-2$
+      String systemId = doctype.getSystemId();
+      if (systemId == null)
+      {
+        systemId = ""; //$NON-NLS-1$
+      }
+      data += " \"" + systemId + "\"";      //$NON-NLS-1$ //$NON-NLS-2$
+    }
+    else
+    {
+      data += " SYSTEM \"" + doctype.getSystemId() + "\""; //$NON-NLS-1$ //$NON-NLS-2$
+    }
+    return data;
+  }     
+
+  public void println()
+  {
+    if (formattingEnabled)
+    {
+      out.println();
+    }
+  }
+
+  public void println(String string)
+  {
+    if (formattingEnabled)
+    {
+      out.println(string);
+    }
+    else
+    {
+      out.print(string);
+    }
+  }
+
+  public void printIndent()
+  {             
+    if (formattingEnabled)
+    {
+      for (int i = 0; i < indent; i++)
+      {
+        out.print(" "); //$NON-NLS-1$
+      }
+    }
+  }       
+
+  public void print(String string)
+  {
+    out.print(string);
+  }
+}
+
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/util/InferredGrammarFactory.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/util/InferredGrammarFactory.java
new file mode 100644
index 0000000..d4a3c40
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/util/InferredGrammarFactory.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.util;
+
+import java.util.Collection;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.w3c.dom.Element;
+
+
+// this interface is used to build a grammar document given a local file name
+//
+public interface InferredGrammarFactory
+{   
+  public CMDocument createCMDocument(String uri); 
+  public CMElementDeclaration createCMElementDeclaration(CMDocument cmDocument, Element element, boolean isLocal);
+  public void createCMContent(CMDocument parentCMDocument, CMElementDeclaration parentEd, CMDocument childCMDocument, CMElementDeclaration childEd, boolean isLocal, String uri);
+  public void debugPrint(Collection collection); 
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/util/NamespaceAttributeVisitor.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/util/NamespaceAttributeVisitor.java
new file mode 100644
index 0000000..58d193d
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/util/NamespaceAttributeVisitor.java
@@ -0,0 +1,110 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     David Carver - STAR - bug 198807 - attribute order dependancy.
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.util;
+
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+
+import com.ibm.icu.util.StringTokenizer;
+
+
+public class NamespaceAttributeVisitor
+{                                      
+  public static final String XML_SCHEMA_INSTANCE_URI = "http://www.w3.org/2001/XMLSchema-instance"; //$NON-NLS-1$
+  public String xsiPrefix = "xsi"; //$NON-NLS-1$
+
+  public void visitXMLNamespaceAttribute(Attr attr, String namespacePrefix, String namespaceURI)
+  {   
+    if (namespaceURI.equals(XML_SCHEMA_INSTANCE_URI))
+    {
+      xsiPrefix = namespacePrefix;
+    }
+  } 
+
+  public void visitXSINoNamespaceSchemaLocationAttribute(Attr attr, String value)
+  {
+  }
+
+  public void visitXSISchemaLocationAttribute(Attr attr, String value)
+  {
+    StringTokenizer st = new StringTokenizer(value);          
+    while (true)
+    {
+      String nsURI = st.hasMoreTokens() ? st.nextToken() : null;
+      String locationHint = st.hasMoreTokens() ? st.nextToken() : null;            
+      if (nsURI != null && locationHint != null)
+      {    
+        visitXSISchemaLocationValuePair(nsURI, locationHint);          
+      }
+      else
+      {
+        break;
+      }
+    }
+  }   
+
+  public void visitXSISchemaLocationValuePair(String uri, String locationHint)
+  {
+  }
+
+  public void visitElement(Element element)
+  {
+    NamedNodeMap map = element.getAttributes();
+    int mapLength = map.getLength();
+    
+    // First retrieve all the namespaces so that they are loaded before
+    // doing any special prefix handling.  This allows the attributes to be
+    // defined in any order, but the namespaces have to be retrieved first.
+    
+    for (int i = 0; i < mapLength; i++)
+    {
+      Attr attr = (Attr)map.item(i);
+      String prefix = DOMNamespaceHelper.getPrefix(attr.getName());
+      String unprefixedName = DOMNamespaceHelper.getUnprefixedName(attr.getName());
+      if (prefix != null && unprefixedName != null)
+      {
+        if (prefix.equals("xmlns")) //$NON-NLS-1$
+        {
+          visitXMLNamespaceAttribute(attr, unprefixedName, attr.getValue());
+        }
+      }
+      else if (unprefixedName != null)
+      {
+        if (unprefixedName.equals("xmlns")) //$NON-NLS-1$
+        {
+          visitXMLNamespaceAttribute(attr, "", attr.getValue()); //$NON-NLS-1$
+        }
+      }      
+
+    }
+
+    for (int i = 0; i < mapLength; i++)
+    {
+      Attr attr = (Attr)map.item(i);
+      String prefix = DOMNamespaceHelper.getPrefix(attr.getName());
+      String unprefixedName = DOMNamespaceHelper.getUnprefixedName(attr.getName());
+      if (prefix != null && unprefixedName != null)
+      {
+       	if (prefix.equals(xsiPrefix) && unprefixedName.equals("schemaLocation")) //$NON-NLS-1$
+        {
+          visitXSISchemaLocationAttribute(attr, attr.getValue());
+        }
+        else if (prefix.equals(xsiPrefix) && unprefixedName.equals("noNamespaceSchemaLocation")) //$NON-NLS-1$
+        {
+          visitXSINoNamespaceSchemaLocationAttribute(attr, attr.getValue());
+        }
+      }
+    }
+  }      
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/util/NamespaceInfo.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/util/NamespaceInfo.java
new file mode 100644
index 0000000..56af91b
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/util/NamespaceInfo.java
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.util;
+
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+public class NamespaceInfo
+{                        
+  public String uri;
+  public String prefix;
+  public String locationHint;
+  public boolean isPrefixRequired; 
+  protected Hashtable hashtable;
+
+  public NamespaceInfo()
+  {
+  }
+
+  public NamespaceInfo(String uri, String prefix, String locationHint)
+  {                                                                  
+    this.uri = uri;                             
+    this.prefix = prefix;
+    this.locationHint = locationHint;
+  }   
+
+  public NamespaceInfo(NamespaceInfo that)
+  {                                               
+    this.uri = that.uri;                             
+    this.prefix = that.prefix;
+    this.locationHint = that.locationHint;
+    // todo... see if we need to clone the hastable 
+  }
+
+  public void normalize()
+  {
+    uri = getNormalizedValue(uri);
+    prefix  = getNormalizedValue(prefix);
+    locationHint= getNormalizedValue(locationHint);
+  }
+
+  protected String getNormalizedValue(String string)
+  {
+    return (string != null && string.trim().length() == 0) ? null : string;
+  }
+    
+  public void setProperty(String property, Object value)
+  {
+    if (hashtable == null)
+    {
+      hashtable = new Hashtable();
+    }
+    hashtable.put(property, value);
+  }
+
+  public Object getProperty(String property)
+  {
+    return (hashtable != null) ? hashtable.get(property) : null;
+  }
+
+  public static List cloneNamespaceInfoList(List oldList)
+  {  
+    List newList = new Vector(oldList.size());
+    for (Iterator i = oldList.iterator(); i.hasNext(); )
+    {
+      NamespaceInfo oldInfo = (NamespaceInfo)i.next();
+      newList.add(new NamespaceInfo(oldInfo));
+    }               
+    return newList;
+  }
+}      
diff --git a/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/util/NamespaceTable.java b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/util/NamespaceTable.java
new file mode 100644
index 0000000..71d115d
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-contentmodel/org/eclipse/wst/xml/core/internal/contentmodel/util/NamespaceTable.java
@@ -0,0 +1,257 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2009 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contentmodel.util;
+                          
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+
+public class NamespaceTable extends NamespaceAttributeVisitor
+{                   
+  public Hashtable hashtable = new Hashtable();
+
+/**
+ * @deprecated
+ * @param document - no longer used
+ */
+public NamespaceTable(Document document)
+  {         
+	  this();
+    //DOMExtension domExtension = DOMExtensionProviderRegistry.getInstance().getDOMExtension(document);
+    //if (domExtension != null)
+    //{                          
+    //  addNamespaceInfoList(domExtension.getImplictNamespaceInfoList(), true);
+    // }
+  }   
+
+  private NamespaceTable()
+  {       
+	  super();
+  }  
+
+  public boolean isNamespaceEncountered()
+  {
+    return hashtable.values().size() > 0;
+  }
+
+  public String getPrefixForURI(String uri)
+  {           
+    String result = null;
+    NamespaceInfo entry = getNamespaceInfoForURI(uri, true);
+    if (entry != null) 
+    {
+      result = entry.prefix;
+    }                         
+    return result;
+  }
+      
+
+  public String getURIForPrefix(String prefix)
+  {           
+    String result = null;
+    NamespaceInfo info = getNamespaceInfoForPrefix(prefix);
+    if (info != null) 
+    {
+      result = info.uri;
+    }                         
+    return result;
+  }    
+
+          
+  protected boolean isMatchingString(String a, String b)
+  {
+    return ((a == null && b == null) || (a != null && b != null && a.equals(b)));
+  }
+   
+
+  public NamespaceInfo getNamespaceInfoForURI(String uri)
+  {                                                     
+    return getNamespaceInfoForURI(uri, false);
+  }
+
+
+  public NamespaceInfo getNamespaceInfoForURI(String uri, boolean testImplied)
+  {
+    NamespaceInfo result = null;
+    for (Iterator i = hashtable.values().iterator(); i.hasNext(); )
+    {                    
+      NamespaceInfo nsInfo = (NamespaceInfo)i.next(); 
+      if (isMatchingString(nsInfo.uri, uri))
+      {                 
+        result = nsInfo;
+        if (testImplied && nsInfo.getProperty("isImplied") != null) //$NON-NLS-1$
+        {
+          // continue
+        }            
+        else
+        {
+          break;
+        }
+      }
+    }
+    return result;
+  } 
+
+
+  public void setLocationHintForURI(String uri, String locationHint)
+  {      
+   // List list = new Vector();
+    for (Iterator i = hashtable.values().iterator(); i.hasNext(); )
+    {                    
+      NamespaceInfo nsInfo = (NamespaceInfo)i.next(); 
+      if (isMatchingString(nsInfo.uri, uri))
+      {                                               
+        nsInfo.locationHint = locationHint;
+      }
+    }
+  }
+    
+
+  public NamespaceInfo getNamespaceInfoForPrefix(String prefix)
+  {                                      
+    prefix = prefix != null ? prefix : ""; //$NON-NLS-1$
+    return (NamespaceInfo)hashtable.get(prefix);
+  }   
+
+
+  public void visitXMLNamespaceAttribute(Attr attr, String namespacePrefix, String namespaceURI)
+  {                                 
+    NamespaceInfo nsInfo = new NamespaceInfo();      
+    nsInfo.prefix = namespacePrefix;
+    nsInfo.uri = namespaceURI;      
+   
+    NamespaceInfo matchingNamespaceInfo = getNamespaceInfoForURI(namespaceURI);
+    if (matchingNamespaceInfo != null)
+    {                           
+      nsInfo.locationHint = matchingNamespaceInfo.locationHint;
+    }                                      
+
+    internalAddNamespaceInfo(namespacePrefix, nsInfo);
+
+    super.visitXMLNamespaceAttribute(attr, namespacePrefix, namespaceURI);
+  } 
+                 
+  public void visitXSISchemaLocationValuePair(String uri, String locationHint)
+  {
+    setLocationHintForURI(uri, locationHint);
+  }   
+
+  public void addNamespaceInfo(NamespaceInfo info)
+  {                           
+    String key  = (info.prefix != null) ? info.prefix : ""; //$NON-NLS-1$
+    internalAddNamespaceInfo(key, info);
+  }
+
+  protected void internalAddNamespaceInfo(String key, NamespaceInfo info)
+  {
+    hashtable.put(key, info);
+  }
+
+  protected void addNamespaceInfoList(List list, boolean isImplied)
+  {       
+    if (list != null)
+    {
+      for (Iterator i = list.iterator(); i.hasNext(); )
+      {
+        NamespaceInfo info = (NamespaceInfo)i.next();
+        NamespaceInfo clone = new NamespaceInfo(info);    
+        if (isImplied)
+        {
+          clone.setProperty("isImplied", "true"); //$NON-NLS-1$ //$NON-NLS-2$
+        }
+        addNamespaceInfo(clone);
+      }
+    }
+  }
+
+  public void addNamespaceInfoList(List list)
+  {  
+    addNamespaceInfoList(list, false);  
+  }
+
+  public void visitXSINoNamespaceSchemaLocationAttribute(Attr attr, String locationHint)
+  {
+    addNoNamespaceSchemaLocation(locationHint);
+  } 
+
+  public void addNoNamespaceSchemaLocation(String locationHint)
+  {
+    NamespaceInfo nsInfo = new NamespaceInfo();      
+    nsInfo.prefix = null;
+    nsInfo.uri = "";       //$NON-NLS-1$
+    nsInfo.locationHint = locationHint;  
+    internalAddNamespaceInfo("", nsInfo); //$NON-NLS-1$
+  } 
+
+  public void addNamespaceInfo(String prefix, String uri, String locationHint)
+  {
+    NamespaceInfo nsInfo = new NamespaceInfo();      
+    nsInfo.prefix = prefix;
+    nsInfo.uri = uri;      
+    nsInfo.locationHint = locationHint;  
+    internalAddNamespaceInfo(prefix != null ? prefix : "", nsInfo); //$NON-NLS-1$
+  } 
+
+  public void addElement(Element element)
+  {   
+    visitElement(element);  
+  }      
+         
+  public void addElementLineage(Element targetElement)
+  {
+    List list = NamespaceTable.getElementLineage(targetElement);                 
+    for (Iterator i = list.iterator(); i.hasNext(); )
+    {
+      Element element = (Element)i.next();
+      addElement(element);
+    }            
+  }
+
+  public static List getElementLineage(Element element)
+  {          
+    List result = new ArrayList();             
+    for (Node node = element; node != null; node = node.getParentNode())
+    {                               
+      if (node.getNodeType() == Node.ELEMENT_NODE)
+      {
+        result.add(0, node);                      
+      }
+      else
+      {
+        break;
+      }
+    }  
+    return result;
+  }    
+
+  public Collection getNamespaceInfoCollection()
+  {              
+    return hashtable.values();
+  } 
+
+  public List getNamespaceInfoList()
+  {                               
+    List list = new Vector();
+    list.addAll(hashtable.values());
+    return list;
+  }
+} 
diff --git a/bundles/org.eclipse.wst.xml.core/src-emfModelSynch/org/eclipse/wst/xml/core/internal/emf2xml/EMF2DOMSSEAdapter.java b/bundles/org.eclipse.wst.xml.core/src-emfModelSynch/org/eclipse/wst/xml/core/internal/emf2xml/EMF2DOMSSEAdapter.java
new file mode 100644
index 0000000..318f731
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-emfModelSynch/org/eclipse/wst/xml/core/internal/emf2xml/EMF2DOMSSEAdapter.java
@@ -0,0 +1,492 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.xml.core.internal.emf2xml;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+import org.eclipse.emf.common.notify.Notifier;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.wst.common.internal.emf.resource.EMF2DOMAdapter;
+import org.eclipse.wst.common.internal.emf.resource.EMF2DOMAdapterImpl;
+import org.eclipse.wst.common.internal.emf.resource.EMF2DOMRenderer;
+import org.eclipse.wst.common.internal.emf.resource.Translator;
+import org.eclipse.wst.common.internal.emf.resource.TranslatorResource;
+import org.eclipse.wst.common.internal.emf.utilities.Assert;
+import org.eclipse.wst.common.internal.emf.utilities.DOMUtilities;
+import org.eclipse.wst.common.internal.emf.utilities.FeatureValueConversionException;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapter;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+import org.eclipse.wst.xml.core.internal.Logger;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.Text;
+
+public class EMF2DOMSSEAdapter extends EMF2DOMAdapterImpl implements INodeAdapter {
+	
+	private Class resourceClass;
+	public EMF2DOMSSEAdapter(Node node, EMF2DOMRenderer renderer, Translator translator) {
+		super(node, renderer, translator);
+	}
+
+	public EMF2DOMSSEAdapter(Notifier object, Node node, EMF2DOMRenderer renderer, Translator translator) {
+		super(object, node, renderer, translator);
+	}
+
+	public EMF2DOMSSEAdapter(TranslatorResource resource, Document document, EMF2DOMRenderer renderer, Translator translator) {
+		super(resource, document, renderer, translator);
+	}
+
+	protected String calcIndentString(Node node) {
+		Assert.isNotNull(node);
+		Assert.isNotNull(node.getParentNode(), "Node must be connected into the tree"); //$NON-NLS-1$
+
+		Node parent = node.getParentNode();
+
+		String indentString = getNewlineString(node);
+
+		// Find indentation string for this node based on its sibling or
+		// parent
+		Node previousSibling = DOMUtilities.getPreviousNodeSibling(node);
+		if (previousSibling != null) {
+			indentString = primGetIndentString(previousSibling);
+		}
+		else {
+			String parentIndentString = primGetIndentString(parent);
+			indentString = parentIndentString + DOMUtilities.INDENT_STRING;
+		}
+		return indentString;
+	}
+
+	/*
+	 * Prints out a DOM notification for debugging.
+	 */
+	protected void debugDOMNotify(INodeNotifier notifier, int eventType, Object changedFeature, Object oldValue, Object newValue) {
+		if (fDebug) {
+			String notifType = ""; //$NON-NLS-1$
+			switch (eventType) {
+				case INodeNotifier.ADD :
+					notifType = "ADD"; //$NON-NLS-1$
+					break;
+				case INodeNotifier.REMOVE :
+					notifType = "REMOVE"; //$NON-NLS-1$
+					break;
+				case INodeNotifier.CHANGE :
+					notifType = "CHANGE"; //$NON-NLS-1$
+					break;
+				case INodeNotifier.CONTENT_CHANGED :
+					notifType = "CONTENT_CHANGED"; //$NON-NLS-1$
+					break;
+				case INodeNotifier.STRUCTURE_CHANGED :
+					notifType = "STRUCTURE_CHANGE"; //$NON-NLS-1$
+					break;
+			}
+			Logger.log(Logger.INFO_DEBUG, "DOM Change: " + notifType); //$NON-NLS-1$
+			Logger.log(Logger.INFO_DEBUG, "\tnotifier      : " + notifier); //$NON-NLS-1$
+			Logger.log(Logger.INFO_DEBUG, "\tchangedFeature: " + changedFeature); //$NON-NLS-1$
+			Logger.log(Logger.INFO_DEBUG, "\toldValue      : " + oldValue); //$NON-NLS-1$
+			Logger.log(Logger.INFO_DEBUG, "\tnewValue      : " + newValue); //$NON-NLS-1$
+		}
+	}
+
+	protected void disableUndoManagementIfNecessary() {
+		IDOMModel model = getXMLModel();
+		if (model != null && model.getUndoManager() != null)
+			model.disableUndoManagement();
+	}
+
+	protected void enableUndoManagement() {
+		IDOMModel model = getXMLModel();
+		if (model != null && model.getUndoManager() != null)
+			model.enableUndoManagement();
+	}
+
+	protected String getNewlineString(Node node) {
+		/*
+		 * We should always have IDOMNode, and IStructuredDocument, and
+		 * consquently a valid "preferred" line delimiter, but just to be
+		 * safe, we'll assign something by default.
+		 */
+		if (node instanceof IDOMNode) {
+			IDOMNode xmlNode = (IDOMNode) node;
+			IStructuredDocument document = xmlNode.getStructuredDocument();
+			if (document != null) {
+				return document.getLineDelimiter();
+			}
+		}
+		return DOMUtilities.NEWLINE_STRING;
+	}
+
+	protected IDOMModel getXMLModel() {
+		if (getNode() != null)
+			return ((IDOMNode) getNode()).getModel();
+		return null;
+	}
+
+	protected IDOMNode getXMLNode() {
+		return (IDOMNode) getNode();
+	}
+
+	/*
+	 * Do nothing for SSE, we will tolerate anything they add
+	 */
+	protected void handleFeatureValueConversionException(FeatureValueConversionException ex) {
+		// Do nothing
+	}
+
+	/*
+	 * Do nothing for SSE, we will tolerate anything they add
+	 */
+	protected void handleInvalidMultiNodes(String nodeName) {
+		// Do nothing
+	}
+
+	protected void indent(Node node, Translator map) {
+		Assert.isNotNull(node.getParentNode(), "Node must be connected into the tree"); //$NON-NLS-1$
+		Assert.isNotNull(node);
+
+		String indentString = calcIndentString(node);
+
+		// Indent before the start tag
+		indentStartTag(indentString, node, map);
+
+		// Indent before the end tag
+		indentEndTag(indentString, node, map);
+	}
+
+	/**
+	 * Indent before the end tag of the <node>passed in.
+	 */
+	protected void indentEndTag(String indentString, Node node, Translator map) {
+		if (!map.shouldIndentEndTag(node))
+			return;
+		String domPath = map.getDOMPath();
+
+		if ((!map.isManagedByParent() && !map.isDOMTextValue()) || (map.isManagedByParent() && domPath.length() != 0) && node.getNodeName().equals(domPath)) {
+			Text newWS = node.getOwnerDocument().createTextNode(getNewlineString(node) + indentString); //$NON-NLS-1$
+			DOMUtilities.insertBeforeNode(node, newWS, null);
+		}
+	}
+
+	/**
+	 * Indent before the start tag of the <node>passed in.
+	 */
+	protected void indentStartTag(String indentString, Node node, Translator map) {
+		Node parent = node.getParentNode();
+		Text newWS = node.getOwnerDocument().createTextNode(getNewlineString(node) + indentString); //$NON-NLS-1$
+		DOMUtilities.insertAfterNode(parent, newWS, DOMUtilities.getPreviousNodeSibling(node));
+	}
+
+	protected boolean isEmptyTag(Element parent) {
+		return ((IDOMElement) parent).isEmptyTag();
+	}
+
+	/*
+	 * This method is called when the DOM node changes. It attempts to update
+	 * MOF object based on the changes.
+	 */
+	public void notifyChanged(INodeNotifier notifier, int eventType, Object changedFeature, Object oldValue, Object newValue, int pos) {
+
+		if (!isNotificationEnabled())
+			return;
+
+		debugDOMNotify(notifier, eventType, changedFeature, oldValue, newValue);
+
+		if (notifier != getNode() && eventType != INodeNotifier.CHANGE) {
+			// This is the case where the notification was sent from a
+			// sub node. Use the notifiers name to determine which
+			// MOF feature to update. Note that is is assumed that if
+			// the eventType is CHANGE then it attribute on a path node
+			// changing. This was put in for the EGL group.
+			if (notifier instanceof Element) {
+				if (eventType == INodeNotifier.STRUCTURE_CHANGED || eventType == INodeNotifier.CONTENT_CHANGED || eventType == INodeNotifier.CHANGE) {
+					Element notifyingNode = (Element) notifier;
+					Translator map = findTranslator(notifyingNode.getNodeName(), false);
+					if (map != null)
+						updateMOFFeature(map, getNode(), getEObject());
+				}
+			}
+		}
+		else {
+			// Update everything on STRUCTURE_CHANGE or CONTENT_CHANGE.
+			// Other event types occur too often.
+			if (eventType == INodeNotifier.STRUCTURE_CHANGED || eventType == INodeNotifier.CONTENT_CHANGED) {
+				updateMOF();
+			}
+			// Update just the attribute that changed.
+			else if (eventType == INodeNotifier.CHANGE) {
+				Translator map = findTranslator(changedFeature.toString(), true);
+				if (map != null)
+					updateMOFFeature(map, getNode(), getEObject());
+			}
+		}
+	}
+
+	protected void postUpdateDOMFeature(Translator map, Node node, EObject mofObject) {
+		enableUndoManagement();
+	}
+
+	protected void preUpdateDOMFeature(Translator map, Node node, EObject mofObject) {
+		super.preUpdateDOMFeature(map, node, mofObject);
+		disableUndoManagementIfNecessary();
+	}
+
+	protected void primAddDOMAdapter(Node aNode, EMF2DOMAdapter anAdapter) {
+		((IDOMNode) aNode).addAdapter((EMF2DOMSSEAdapter) anAdapter);
+	}
+
+	/**
+	 * Create an adapter for a child DOM node
+	 * 
+	 * @param node
+	 *            org.w3c.dom.Node The node to create the adapter for.
+	 */
+	protected EMF2DOMAdapter primCreateAdapter(EObject mofObject, Translator childMap) {
+		Element newNode = createNewNode(mofObject, childMap);
+		return new EMF2DOMSSEAdapter(mofObject, newNode, fRenderer, childMap);
+	}
+
+	/**
+	 * Create an adapter for a child DOM node
+	 * 
+	 * @param node
+	 *            org.w3c.dom.Node The node to create the adapter for.
+	 */
+	protected EMF2DOMAdapter primCreateAdapter(Node node, Translator childMap) {
+		return new EMF2DOMSSEAdapter(node, fRenderer, childMap);
+	}
+	protected EMF2DOMAdapter createAdapter(Node node, Translator childMap) {
+
+		//Assert.isNotNull(childMap.getChildAdapterClass());
+		Assert.isNotNull(node);
+
+		EMF2DOMAdapter adapter = primGetExistingAdapter(node,childMap);
+
+		if (adapter != null) {
+			if (adapter.isMOFProxy() || adapter.getTarget() == null) {
+				removeDOMAdapter(node, adapter);
+				if (adapter.getTarget() != null) {
+					adapter.getTarget().eAdapters().remove(adapter);
+				}
+				adapter = null;
+			}
+		}
+		if (adapter == null) {
+			adapter = primCreateAdapter(node, childMap);
+		}
+		return adapter;
+	}
+	protected void addDOMAdapter(Node childNode) {
+
+		// Only add the adapter if this is an child node that will not be
+		// adapted. For instance a subtree that maps to a MOF attribute
+		// setting.
+		if (childNode.getNodeType() == Node.ELEMENT_NODE) {
+			EMF2DOMAdapter attrAdapter = primGetExistingAdapter(childNode);
+
+			if (attrAdapter == null || attrAdapter.getNode() != getNode()) {
+				// If the node is adapted, but not by this adapter then remove
+				// it. This happens to non-object children when the parent tag
+				// name is changed.
+				removeDOMAdapter(childNode, attrAdapter);
+
+				if (fDebug) {
+					org.eclipse.jem.util.logger.proxy.Logger.getLogger().logError("\tCHILD: Adding DOM adapter: " + this); //$NON-NLS-1$
+					org.eclipse.jem.util.logger.proxy.Logger.getLogger().logError("\t\tto: " + childNode); //$NON-NLS-1$
+				}
+				primAddDOMAdapter(childNode, this);
+			}
+		}
+	}
+	
+	protected EMF2DOMAdapter primGetExistingAdapter(Node aNode, Translator childMap) {
+		INodeNotifier sseNode = (INodeNotifier) aNode;
+		Collection adapters = sseNode.getAdapters();
+		for (Iterator iterator = adapters.iterator(); iterator.hasNext();) {
+			INodeAdapter adapter = (INodeAdapter) iterator.next();
+			// First Check if it's an EMF2DOMAdapter
+			if (adapter != null && adapter.isAdapterForType(EMF2DOMAdapter.ADAPTER_CLASS)) {
+				// Cast to EMF2DOMAdapter
+				EMF2DOMSSEAdapter e2DAdapter = (EMF2DOMSSEAdapter) adapter;
+				Object adapterTarget = e2DAdapter.getTarget();
+				//Translator adapterTranslator = e2DAdapter.fTranslator;
+				
+				//Handle the cases where either adapter's target is null 
+				if ((getTarget() == null) || (adapterTarget == null))
+					if (resourceClass != null && resourceClass.equals(e2DAdapter.getResourceClass()))
+						return e2DAdapter;
+					else
+						continue;
+				
+				
+				// Check if target is an EMF resource
+				if (getTarget() instanceof Resource) {
+					/*
+					 * Now check if it's the right one (Multiple resources
+					 * could be attached)
+					 */
+					if (adapterTarget != null && adapterTarget == getTarget()) {
+						return e2DAdapter;
+					}
+				}
+				else {
+					// Check if targets are EObjects with the same resources
+					EObject myTarget = (EObject) getTarget();
+					/*
+					 * Now check if it's the right one (Multiple resources could
+					 * be attached)
+					 */
+					if (adapterTarget != null && ((EObject)adapterTarget).eResource() == myTarget.eResource()) {
+						return e2DAdapter;
+					}
+				}
+				
+				if (adapterTarget instanceof EObject) {
+					if (((EObject) e2DAdapter.getTarget()).eResource() == null && e2DAdapter.fTranslator == childMap) {
+						return e2DAdapter;
+					}
+				}
+			}
+		}
+		return null;
+	}
+	
+	protected EMF2DOMAdapter primGetExistingAdapter(Node aNode) {
+		INodeNotifier sseNode = (INodeNotifier) aNode;
+		Collection adapters = sseNode.getAdapters();
+		for (Iterator iterator = adapters.iterator(); iterator.hasNext();) {
+			INodeAdapter adapter = (INodeAdapter) iterator.next();
+			// First Check if it's an EMF2DOMAdapter
+			if (adapter != null && adapter.isAdapterForType(EMF2DOMAdapter.ADAPTER_CLASS)) {
+				// Cast to EMF2DOMAdapter
+				EMF2DOMSSEAdapter e2DAdapter = (EMF2DOMSSEAdapter) adapter;
+				Object adapterTarget = e2DAdapter.getTarget();
+				
+				//Handle the cases where either adapter's target is null 
+				if ((getTarget() == null) || (adapterTarget == null))
+					if (resourceClass != null && resourceClass.equals(e2DAdapter.getResourceClass()))
+						return e2DAdapter;
+					else
+						continue;
+				
+				
+				// Check if target is an EMF resource
+				if (getTarget() instanceof Resource) {
+					/*
+					 * Now check if it's the right one (Multiple resources
+					 * could be attached)
+					 */
+					if (adapterTarget != null && adapterTarget == getTarget()) {
+						return e2DAdapter;
+					}
+				}
+				else {
+					// Check if targets are EObjects with the same resources
+					EObject myTarget = (EObject) getTarget();
+					/*
+					 * Now check if it's the right one (Multiple resources could
+					 * be attached)
+					 */
+					if (adapterTarget != null && ((EObject)adapterTarget).eResource() == myTarget.eResource()) {
+						return e2DAdapter;
+					}
+				}
+				
+				if (adapterTarget instanceof EObject) {
+					if (((EObject) e2DAdapter.getTarget()).eResource() == null) {
+						return e2DAdapter;
+					}
+				}
+			}
+		}
+		return null;
+	}
+
+	protected String primGetIndentString(Node node) {
+		IStructuredDocument flatModel = ((IDOMNode) node).getStructuredDocument();
+		int nodeStartOff = ((IDOMNode) node).getStartOffset();
+
+		int startOff = Math.max(0, nodeStartOff - 100);
+		int endOff = nodeStartOff;
+
+		try {
+			String text = flatModel.get(startOff, endOff - startOff);
+
+			int inx = text.length() - 1;
+			if (inx >= 0) {
+				for (; inx >= 0; inx--) {
+					char ch = text.charAt(inx);
+					if (Character.isWhitespace(ch) && ch != '\n' && ch != '\r') {
+						continue;
+					}
+					inx++;
+					break;
+				}
+
+				return text.substring(inx);
+			}
+		}
+		catch (BadLocationException ex) {
+			Logger.logException(ex);
+		}
+		return ""; //$NON-NLS-1$
+	}
+
+	protected void removeDOMAdapter(Node aNode, EMF2DOMAdapter anAdapter) {
+		((IDOMNode) aNode).removeAdapter((INodeAdapter) anAdapter);
+	}
+
+
+	protected void reorderDOMChild(Node parentNode, Node childNode, Node insertBeforeNode, Translator map) {
+		super.reorderDOMChild(parentNode, childNode, insertBeforeNode, map);
+		// Since reordering deletes all the whitespace before the node, we
+		// must indent .
+		if (insertBeforeNode != null && insertBeforeNode.getNodeType() == Node.ELEMENT_NODE)
+			indentStartTag(calcIndentString(insertBeforeNode), insertBeforeNode, map);
+		else
+			indentStartTag(calcIndentString(childNode), childNode, map);
+	}
+
+	protected void setEmptyTag(Element element) {
+		((IDOMElement) element).setEmptyTag(true);
+	}
+
+	public void updateDOM() {
+		if (!isNotificationEnabled())
+			return;
+		try {
+			disableUndoManagementIfNecessary();
+			primUpdateDOM();
+		}
+		finally {
+			enableUndoManagement();
+		}
+	}
+
+	public Class getResourceClass() {
+		return resourceClass;
+	}
+
+	protected void initChildTranslators() {
+		if (fRenderer != null && fRenderer.getResource() != null)
+			resourceClass = fRenderer.getResource().getClass();
+		super.initChildTranslators();
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-emfModelSynch/org/eclipse/wst/xml/core/internal/emf2xml/EMF2DOMSSERenderer.java b/bundles/org.eclipse.wst.xml.core/src-emfModelSynch/org/eclipse/wst/xml/core/internal/emf2xml/EMF2DOMSSERenderer.java
new file mode 100644
index 0000000..40289d7
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-emfModelSynch/org/eclipse/wst/xml/core/internal/emf2xml/EMF2DOMSSERenderer.java
@@ -0,0 +1,656 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.xml.core.internal.emf2xml;
+
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.resource.ResourceSet;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.eclipse.jem.util.emf.workbench.ProjectResourceSet;
+import org.eclipse.jem.util.emf.workbench.WorkbenchResourceHelperBase;
+import org.eclipse.wst.common.internal.emf.resource.EMF2DOMAdapter;
+import org.eclipse.wst.common.internal.emf.resource.EMF2DOMRenderer;
+import org.eclipse.wst.common.internal.emf.resource.TranslatorResource;
+import org.eclipse.wst.common.internal.emf.utilities.DOMUtilities;
+import org.eclipse.wst.common.internal.emfworkbench.WorkbenchResourceHelper;
+import org.eclipse.wst.common.internal.emfworkbench.integration.ResourceSetWorkbenchEditSynchronizer;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.model.ModelLifecycleEvent;
+import org.eclipse.wst.sse.core.internal.provisional.IModelLifecycleListener;
+import org.eclipse.wst.sse.core.internal.provisional.IModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.IModelStateListener;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapter;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.xml.core.internal.Logger;
+import org.eclipse.wst.xml.core.internal.document.DocumentTypeImpl;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.w3c.dom.Node;
+
+
+public class EMF2DOMSSERenderer extends EMF2DOMRenderer implements IModelStateListener, IModelLifecycleListener {
+
+	protected Object aboutToChangeNode = null;
+
+	protected boolean isBatchChanges = false;
+
+	private boolean isSaving = false;
+
+	private IModelManager modelManager;
+	
+	private Class resourceClass;
+	
+	private boolean reverting = false;
+
+	/** The XML DOM model */
+	protected IDOMModel xmlModel;
+
+	/** Used internally; the unique id for the xml model */
+	protected String xmlModelId;
+
+	protected boolean xmlModelReverted = false;
+
+	public EMF2DOMSSERenderer() {
+		super();
+	}
+
+	public void accessForRead() {
+		if (!resource.isNew()) {
+			String id = getModelManagerId();
+			getModelManager().getExistingModelForRead(id);
+		}
+	}
+
+	public void accessForWrite() {
+		modelAccessForWrite();
+	}
+
+	/**
+	 * see batchModelEnd
+	 * 
+	 */
+
+	public void batchModeEnd() {
+		getXMLModel().changedModel();
+		setRootNodeAdapterNotificationEnabled(true);
+		isBatchChanges = false;
+	}
+
+	/**
+	 * batchModeStart and batchModeEnd is a pair that controls notifications,
+	 * and tread access. They should always be called in a try/finally block.
+	 * 
+	 * setBatchModel begins the processing where notifications are not sent
+	 * out on each change, but saved up until the endBatchMode called.
+	 * 
+	 * This pair of calls can also, indirectly, "lock" the DOM Model to access
+	 * from only one thread, so it should not be locked for long periods of
+	 * time. That's also why it is important to have the endBatchMode in a
+	 * finally block to be sure it is always called, or the DOM will be left
+	 * in a locked, unusable, state and only shortly away from severere
+	 * program error.
+	 * 
+	 * <pre><code>
+	 * Example
+	 * </code>
+	 *  
+	 *  try { 
+	 *  		batchModelStart();
+	 *  		...do a some work ...
+	 *  		}
+	 *  	finally {
+	 *  		endBatchMode();
+	 *  		}
+	 *  
+	 *  
+	 * </pre>
+	 */
+	public void batchModeStart() {
+		isBatchChanges = true;
+		getXMLModel().aboutToChangeModel();
+		setRootNodeAdapterNotificationEnabled(false);
+	}
+
+	private void cacheSynchronizationStamp() {
+		IFile file = WorkbenchResourceHelper.getFile(resource);
+		if (file != null) {
+			if (xmlModel != null)
+				xmlModel.resetSynchronizationStamp(file);
+		}
+	}
+
+	/**
+	 * Create a new Document given
+	 * 
+	 * @aResource.
+	 */
+	protected void createDocument() {
+		TranslatorResource res = getResource();
+		res.setDefaults();
+		IFile file = WorkbenchResourceHelper.getFile(resource);
+		InputStream is = DOMUtilities.createHeaderInputStream(res.getDoctype(), res.getPublicId(), res.getSystemId());
+		if (is == null)
+			return;
+		try {
+			try {
+				List folders = new ArrayList();
+				IContainer container = file.getParent();
+				while (null != container && !container.exists() && container instanceof IFolder) {
+					folders.add(container);
+					container = container.getParent();
+				}
+				IFolder folder = null;
+				for (int i = 0; i < folders.size(); i++) {
+					folder = (IFolder) folders.get(i);
+					folder.create(true, true, null);
+				}
+				file.create(is, true, null);
+				file.setLocal(true, 1, null);
+			}
+			catch (CoreException e1) {
+				Logger.logException(e1);
+			}
+			finally {
+				if (null != is) {
+					is.close();
+				}
+			}
+			initializeXMLModel(file, resource.getWriteCount() != 0);
+		}
+		catch (IOException ex) {
+			Logger.log(Logger.ERROR, "IWAE0017E Unexpected IO exception occurred creating xml document");//$NON-NLS-1$
+		}
+	}
+
+	protected void createDOMTreeIfNecessary() {
+		if (needsToCreateDOM)
+			createDOMTree();
+	}
+
+	protected EMF2DOMAdapter createRootDOMAdapter() {
+		return new EMF2DOMSSEAdapter(getResource(), document, this, getResource().getRootTranslator());
+	}
+
+	public void deRegisterAsModelLifecycleListener() {
+		if (xmlModel != null)
+			xmlModel.removeModelLifecycleListener(this);
+	}
+
+	public void deRegisterAsModelStateListener() {
+		if (xmlModel != null)
+			xmlModel.removeModelStateListener(this);
+	}
+
+	private void deregisterFromXMLModel() {
+		
+		deRegisterAsModelStateListener();
+		deRegisterAsModelLifecycleListener();
+		// This try/catch block is a hack to fix defect 204114. This occurs
+		// because
+		// the model manager plugin is shut down and unloaded before the j2ee
+		// plugin.
+		// Calling getModelManager() can result in a class cast exception that
+		// should
+		// be ignored.
+		// ModelManager mgr = null;
+		try {
+			getModelManager();
+		}
+		catch (ClassCastException exc) {
+			return;
+		}
+		if (xmlModel != null) {
+			int writeCount = resource.getWriteCount();
+			int readCount = resource.getReadCount();
+			for (int i = 0; i < writeCount; i++)
+				xmlModel.releaseFromEdit();
+			for (int ii = 0; ii < readCount; ii++)
+				xmlModel.releaseFromRead();
+		}
+		EMF2DOMAdapter adapter = (EMF2DOMAdapter) EcoreUtil.getAdapter(resource.eAdapters(), EMF2DOMAdapter.ADAPTER_CLASS);
+		if (adapter != null) {
+			adapter.removeAdapters(adapter.getNode());
+		}
+		xmlModel = null;
+		xmlModelId = null;
+	}
+
+	public void doSave(OutputStream outputStream, Map options) throws IOException {
+
+		try {
+			isSaving = true;
+			if (null != outputStream) {
+				throw new RuntimeException(this.getClass().getName() + " should not use an OutputStream for saving");} //$NON-NLS-1$
+			createDOMTreeIfNecessary();
+			ResourceSetWorkbenchEditSynchronizer synchronizer = (ResourceSetWorkbenchEditSynchronizer) ((ProjectResourceSet) resource.getResourceSet()).getSynchronizer();
+			IFile aFile = WorkbenchResourceHelper.getFile(resource);
+			try {
+				synchronizer.preSave(aFile, resource);
+				xmlModel.save(aFile);
+			}
+			catch (CoreException ex) {
+				synchronizer.removeFromRecentlySavedList(aFile);
+				Logger.logException(ex);
+			}
+			cacheSynchronizationStamp();
+		}
+		finally {
+			isSaving = false;
+		}
+	}
+
+	public EMF2DOMAdapter getExistingDOMAdapter(Node node) {
+		//IDOMNode xNode = (IDOMNode) node;
+		//return (EMF2DOMSSEAdapter) xNode.getAdapterFor(EMF2DOMAdapter.ADAPTER_CLASS);
+
+		INodeNotifier sseNode = (INodeNotifier) node;
+		Collection adapters = sseNode.getAdapters();
+		for (Iterator iterator = adapters.iterator(); iterator.hasNext();) {
+			INodeAdapter adapter = (INodeAdapter) iterator.next();
+			// First Check if it's an EMF2DOMAdapter
+			if (adapter != null && adapter.isAdapterForType(EMF2DOMAdapter.ADAPTER_CLASS)) {
+				// Cast to EMF2DOMSSEAdapter
+				EMF2DOMSSEAdapter e2DAdapter = (EMF2DOMSSEAdapter) adapter;
+				//Handle the cases where either adapter's target is null 
+				//Use the resourceClass to make sure the resource type is identical
+				if (getResource() == null || e2DAdapter.getTarget() == null)
+					if(resourceClass.equals(e2DAdapter.getResourceClass()))
+						return e2DAdapter;
+					else
+						continue;
+				
+				// First check if targets are resources
+				if (e2DAdapter.getTarget() instanceof Resource) {
+					/*
+					 * Now check if it's the right one (Multiple resources
+					 * could be attached)
+					 */
+					if (e2DAdapter.getTarget() == getResource()) {
+						return e2DAdapter;
+					}
+				} else {
+					// Check if targets are EObjects with the same resources
+					TranslatorResource myTarget = getResource();
+					EObject adapterTarget = (EObject) e2DAdapter.getTarget();
+					/*
+					 * Now check if it's the right one (Multiple resources could
+					 * be attached)
+					 */
+					if (adapterTarget.eResource() == myTarget || adapterTarget.eResource() == null) {
+						return e2DAdapter;
+					}
+				}
+			}
+		}
+		return null;
+	
+	}
+
+	protected IModelManager getModelManager() {
+		if (modelManager == null)
+			modelManager = StructuredModelManager.getModelManager();
+		return modelManager;
+	}
+
+	/**
+	 * Return id used to key the XML resource in the XML ModelManager.
+	 */
+	protected String getModelManagerId() {
+		if (xmlModelId == null) {
+			IFile file = WorkbenchResourceHelper.getFile(getResource());
+			if (file != null) {
+				xmlModelId = getModelManager().calculateId(file);
+			}
+			else {
+				xmlModelId = resource.getURI() + Long.toString(System.currentTimeMillis());
+			}
+		}
+		return xmlModelId;
+	}
+
+	protected ResourceSet getResourceSet() {
+		return resource == null ? null : resource.getResourceSet();
+	}
+
+	/**
+	 * Return the DOM model for this resource.
+	 */
+	public IDOMModel getXMLModel() {
+		return xmlModel;
+	}
+
+	public String getXMLModelId() {
+		return xmlModelId;
+	}	
+	
+	private IDOMModel initializeXMLModel(IFile file, boolean forWrite) throws UnsupportedEncodingException, IOException {
+		if (file == null || !file.exists())
+			throw new FileNotFoundException((file == null) ? "null" : file.getFullPath().toOSString()); //$NON-NLS-1$
+		try {
+			IModelManager manager = getModelManager();
+			String id = manager.calculateId(file);			
+			if (forWrite) {
+				IDOMModel mod = (IDOMModel)manager.getExistingModelForEdit(id);
+				if (mod == null)
+					setXMLModel((IDOMModel) manager.getModelForEdit(file));
+				else {
+					setXMLModel(mod);
+				}
+			}
+			else {
+				IDOMModel mod = (IDOMModel)manager.getExistingModelForRead(id);
+				if (mod == null)
+					setXMLModel((IDOMModel) manager.getModelForRead(file));
+				else {
+					setXMLModel(mod);
+				}
+			}
+			setXMLModelId(getXMLModel().getId());
+			needsToCreateDOM = false;
+		}
+		catch (CoreException e) {
+			Logger.logException(e);
+			return null;
+		}
+		String id = getXMLModel().getId();
+		syncReferenceCounts(id, forWrite);
+		if (xmlModel != null)
+			document = xmlModel.getDocument();
+		return xmlModel;
+	}
+
+	public boolean isBatchMode() {
+		return isBatchChanges;
+	}
+
+	public boolean isModified() {
+		return (getXMLModel() != null && getXMLModel().isDirty());
+	}
+
+	public boolean isShared() {
+		
+		if( xmlModel == null) { //resource could be in process of being unloaded - check with model manager
+			String id = getModelManagerId();
+			return getModelManager().isShared(id);
+		}
+		if (getResourceSet() == null)
+			return false;
+		return xmlModel.isShared();
+	}
+
+	public boolean isSharedForWrite() {
+		if (getResourceSet() == null || xmlModel == null)
+			return false;
+		return xmlModel.isSharedForEdit();
+	}
+
+	protected void loadDocument(InputStream in, Map options) throws IOException {
+		if (null != in) {
+			throw new RuntimeException(this.getClass().getName() + " should not use an InputStream for loading");} //$NON-NLS-1$
+		IFile file = WorkbenchResourceHelper.getFile(resource);
+		initializeXMLModel(file, (resource.getWriteCount() != 0));
+		cacheSynchronizationStamp();
+	}
+
+	protected boolean managesDOMAdapters() {
+		return false;
+	}
+
+	public void modelAboutToBeChanged(IStructuredModel model) {
+		if (model.getStructuredDocument() != null)
+			aboutToChangeNode = model.getStructuredDocument().getFirstStructuredDocumentRegion();
+	}
+
+	public void modelAboutToBeReinitialized(IStructuredModel structuredModel) {
+		// TODO Auto-generated method stub
+
+	}
+
+	private void modelAccessForWrite() {
+		String id = getModelManagerId();
+		getModelManager().getExistingModelForEdit(id);
+	}
+
+	public void modelChanged(IStructuredModel model) {
+		if (isBatchChanges)
+			return;
+		try {
+			if (reverting && aboutToChangeNode != null && model.getStructuredDocument() != null
+					&& model.getStructuredDocument().getFirstStructuredDocumentRegion() != aboutToChangeNode) {
+				String id = getModelManagerId();
+				IStructuredModel tempModel = null;
+				try {
+					tempModel = getModelManager().getExistingModelForEdit(id);
+					xmlModelReverted = true;
+					resource.unload();
+				} finally {
+					if (tempModel != null && (tempModel.getReferenceCountForEdit() > 0)) {
+						tempModel.releaseFromEdit();
+					}
+					reverting = false;
+				}
+			}
+		} finally {
+			aboutToChangeNode = null;
+		}
+	} 
+	
+	public void modelDirtyStateChanged(IStructuredModel model, boolean isDirty) {
+		if (!isDirty && resource.isModified()) { // The XMLModel was saved
+			resource.setModified(false);
+			long stamp = WorkbenchResourceHelper.computeModificationStamp(resource);
+			WorkbenchResourceHelper.setSynhronizationStamp(resource, stamp);
+			IProject proj = WorkbenchResourceHelper.getProject(resource);
+			ResourceSetWorkbenchEditSynchronizer synchronizer = (ResourceSetWorkbenchEditSynchronizer) ((ProjectResourceSet) WorkbenchResourceHelperBase.getResourceSet(proj)).getSynchronizer();
+			IFile aFile = WorkbenchResourceHelper.getFile(resource);
+			synchronizer.preSave(aFile, resource);
+		}
+		if (isDirty)
+			resource.setModified(true);
+	}
+
+	public void modelReinitialized(IStructuredModel structuredModel) {
+		// TODO Auto-generated method stub
+
+	}
+
+	public void modelResourceDeleted(IStructuredModel model) {
+		// Do nothing
+	}
+
+	public void modelResourceMoved(IStructuredModel oldModel, IStructuredModel newModel) {
+		// Do nothing
+	}
+
+	/**
+	 * This method is called just prior to being removed from the ResourceSet.
+	 * Ensure that all reference counts to the XMLModel are removed.
+	 */
+	public void preDelete() {
+		if (resource.isLoaded())
+			deregisterFromXMLModel();
+	}
+
+	public void preUnload() {
+		deregisterFromXMLModel();
+	}
+
+	public void processPostModelEvent(ModelLifecycleEvent event) {
+		if (event.getType() == ModelLifecycleEvent.MODEL_REVERT)
+			reverting = false;
+
+	}
+
+	public void processPreModelEvent(ModelLifecycleEvent event) {
+		if (event.getType() == ModelLifecycleEvent.MODEL_REVERT)
+			reverting = true;
+			
+		if (!isSaving) {
+			if (event.getType() == ModelLifecycleEvent.MODEL_SAVED) {
+				ResourceSetWorkbenchEditSynchronizer synchronizer = (ResourceSetWorkbenchEditSynchronizer) ((ProjectResourceSet) resource.getResourceSet()).getSynchronizer();
+				IFile aFile = WorkbenchResourceHelper.getFile(resource);
+				synchronizer.preSave(aFile, resource);
+			}
+		}
+		
+	}
+
+
+	public void registerAsModelLifecycleListener() {
+		this.xmlModel.addModelLifecycleListener(this);
+	}
+
+	/**
+	 * Insert the method's description here. Creation date: (9/7/2001 10:49:53
+	 * AM)
+	 */
+	public void registerAsModelStateListener() {
+		this.xmlModel.addModelStateListener(this);
+	}
+
+	public void releaseFromRead() {
+		if (xmlModel != null)
+			xmlModel.releaseFromRead();
+	}
+
+	public void releaseFromWrite() {
+		if (xmlModel != null)
+			xmlModel.releaseFromEdit();
+	}
+
+	public void removeDOMAdapter(Node aNode, EMF2DOMAdapter anAdapter) {
+		((IDOMNode) aNode).removeAdapter((EMF2DOMSSEAdapter) anAdapter);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jem.internal.util.emf.xml.EMF2DOMRenderer#replaceDocumentType(java.lang.String,
+	 *      java.lang.String, java.lang.String)
+	 */
+	public void replaceDocumentType(String docTypeName, String publicId, String systemId) {
+		if (document == null)
+			return;
+		DocumentTypeImpl docType = (DocumentTypeImpl) document.getDoctype();
+		if (docType == null)
+			return;
+		if (publicId == null && systemId == null)
+			document.removeChild(docType);
+		else {
+			docType.setPublicId(publicId);
+			docType.setSystemId(systemId);
+		}
+	}
+
+	/**
+	 * @deprecated use batchModeStart and BatchModeEnd instead even if you do
+	 *             not use batchModelStart/End, you still need to use the
+	 *             try/finally pattern documented there.
+	 */
+
+	public void setBatchMode(boolean isBatch) {
+
+		// This is some extra processing for clients to know they may be using
+		// incorrectly
+		if (isBatch) {
+			if (isBatchChanges) {
+				Logger.log(Logger.INFO_DEBUG, "setBatch was set to true when it was already true. This can be an indication of invalid calling order"); //$NON-NLS-1$
+			}
+		}
+
+
+		if (isBatch) {
+			batchModeStart();
+		}
+		else {
+			batchModeEnd();
+		}
+	}
+
+	private void setRootNodeAdapterNotificationEnabled(boolean b) {
+		EObject root = resource.getRootObject();
+		if (root != null) {
+			EMF2DOMAdapter adapter = (EMF2DOMAdapter) EcoreUtil.getExistingAdapter(root, EMF2DOMAdapter.ADAPTER_CLASS);
+			if (adapter != null) {
+				adapter.setNotificationEnabled(b);
+				if (b)
+					adapter.updateDOM();
+			}
+		}
+	}
+
+	/**
+	 * Return the DOM model for this resource.
+	 */
+	public void setXMLModel(IDOMModel xmlModel) {
+		deRegisterAsModelStateListener();
+		deRegisterAsModelLifecycleListener();
+		this.xmlModel = xmlModel;
+		registerAsModelStateListener();
+		registerAsModelLifecycleListener();
+	}
+
+	public void setXMLModelId(String id) {
+		xmlModelId = id;
+	}
+
+	private void syncReferenceCounts(String id, boolean forWrite) {
+		int editIndex = 0, readIndex = 0;
+		if (forWrite)
+			editIndex++;
+		else
+			readIndex++;
+		int writeCount = resource.getWriteCount();
+		int readCount = resource.getReadCount();
+		for (int i = writeCount; i > editIndex; i--)
+			modelManager.getExistingModelForEdit(id);
+		for (int i = readCount; i > readIndex; i--)
+			modelManager.getExistingModelForRead(id);
+	}
+
+	public boolean useStreamsForIO() {
+		return false;
+	}
+
+	public boolean wasReverted() {
+		return xmlModelReverted;
+	}
+
+	public void setResource(TranslatorResource resource) {
+		super.setResource(resource);
+		if (resource != null)
+			resourceClass = resource.getClass();
+	}
+	public boolean isReverting() {
+		return this.reverting;
+	}
+
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-emfModelSynch/org/eclipse/wst/xml/core/internal/emf2xml/EMF2DOMSSERendererFactory.java b/bundles/org.eclipse.wst.xml.core/src-emfModelSynch/org/eclipse/wst/xml/core/internal/emf2xml/EMF2DOMSSERendererFactory.java
new file mode 100644
index 0000000..9b79123
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-emfModelSynch/org/eclipse/wst/xml/core/internal/emf2xml/EMF2DOMSSERendererFactory.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.xml.core.internal.emf2xml;
+
+import org.eclipse.wst.common.internal.emf.resource.Renderer;
+import org.eclipse.wst.common.internal.emf.resource.RendererFactory;
+
+/**
+ * @author schacher
+ */
+public class EMF2DOMSSERendererFactory extends RendererFactory {
+
+	public static final EMF2DOMSSERendererFactory INSTANCE = new EMF2DOMSSERendererFactory();
+
+	public EMF2DOMSSERendererFactory() {
+		// Default constructor
+	}
+
+
+	public Renderer createRenderer() {
+		return new EMF2DOMSSERenderer();
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-search/org/eclipse/wst/xml/core/internal/search/ComponentSearchContributor.java b/bundles/org.eclipse.wst.xml.core/src-search/org/eclipse/wst/xml/core/internal/search/ComponentSearchContributor.java
new file mode 100644
index 0000000..6c1dcde
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-search/org/eclipse/wst/xml/core/internal/search/ComponentSearchContributor.java
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.xml.core.internal.search;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.eclipse.wst.common.core.search.pattern.QualifiedName;
+
+public abstract class ComponentSearchContributor  {
+
+	protected HashMap declarations;
+
+	protected HashMap references;
+
+	protected String[] namespaces;
+
+	public ComponentSearchContributor() {
+		super();
+	}
+
+	public XMLSearchPattern getDeclarationPattern(QualifiedName componentName) {
+		return (XMLSearchPattern) getDeclarations().get(componentName);
+	}
+
+	protected Map getDeclarations() {
+		if (declarations == null) {
+			initializeDeclarations();
+		}
+		return declarations;
+	}
+
+	protected Map getReferences() {
+		if (references == null) {
+			initializeReferences();
+		}
+		return references;
+	}
+
+	public XMLSearchPattern[] getReferencesPatterns(QualifiedName componentName) {
+		List references = (List) getReferences().get(componentName);
+		if (references != null) {
+			return (XMLSearchPattern[]) references
+					.toArray(new XMLSearchPattern[references.size()]);
+		}
+		return new XMLSearchPattern[0];
+	}
+	
+	
+	public boolean supports(QualifiedName componentName){
+		return getReferencesPatterns(componentName).length > 0 ||
+			getDeclarationPattern(componentName) != null;
+	}
+
+	public String[] getSupportedNamespaces() {
+		return namespaces;
+	}
+
+	protected abstract void initializeDeclarations();
+
+	protected abstract void initializeReferences();
+
+	protected abstract void initializeSupportedNamespaces();
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-search/org/eclipse/wst/xml/core/internal/search/TargetNamespaceReferencePattern.java b/bundles/org.eclipse.wst.xml.core/src-search/org/eclipse/wst/xml/core/internal/search/TargetNamespaceReferencePattern.java
new file mode 100644
index 0000000..6321b7c
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-search/org/eclipse/wst/xml/core/internal/search/TargetNamespaceReferencePattern.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.xml.core.internal.search;
+
+import org.eclipse.wst.common.core.search.pattern.SearchPattern;
+
+public class TargetNamespaceReferencePattern extends SearchPattern {
+	
+	String namespaceURI;
+	
+	public TargetNamespaceReferencePattern(int matchRule, String namespaceuri) {
+		super(matchRule);
+		namespaceURI = namespaceuri;
+	}
+	
+	public TargetNamespaceReferencePattern(String namespaceuri) {
+		super();
+		namespaceURI = namespaceuri;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-search/org/eclipse/wst/xml/core/internal/search/XMLComponentDeclarationPattern.java b/bundles/org.eclipse.wst.xml.core/src-search/org/eclipse/wst/xml/core/internal/search/XMLComponentDeclarationPattern.java
new file mode 100644
index 0000000..19f475b
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-search/org/eclipse/wst/xml/core/internal/search/XMLComponentDeclarationPattern.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.xml.core.internal.search;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.wst.common.core.search.pattern.QualifiedName;
+
+public class XMLComponentDeclarationPattern extends XMLComponentSearchPattern {
+
+	public XMLComponentDeclarationPattern(QualifiedName elementQName, QualifiedName typeQName, int matchRule) {
+		super(null, elementQName, typeQName, matchRule);
+		
+	}
+
+	public XMLComponentDeclarationPattern(IFile file, QualifiedName elementQName, QualifiedName typeQName) {
+		super(file, elementQName, typeQName);
+	}
+	
+	public XMLComponentDeclarationPattern(QualifiedName elementQName, QualifiedName typeQName) {
+		super(null, elementQName, typeQName);
+	}
+
+	
+	
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-search/org/eclipse/wst/xml/core/internal/search/XMLComponentReferencePattern.java b/bundles/org.eclipse.wst.xml.core/src-search/org/eclipse/wst/xml/core/internal/search/XMLComponentReferencePattern.java
new file mode 100644
index 0000000..e68a8a4
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-search/org/eclipse/wst/xml/core/internal/search/XMLComponentReferencePattern.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.xml.core.internal.search;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.wst.common.core.search.pattern.QualifiedName;
+
+public class XMLComponentReferencePattern extends XMLComponentSearchPattern{
+
+	public XMLComponentReferencePattern(IFile file, QualifiedName elementQName, QualifiedName typeQName, int matchRule) {
+		super(file, elementQName, typeQName, matchRule);
+		
+	}
+
+	public XMLComponentReferencePattern(IFile file, QualifiedName elementQName, QualifiedName typeQName) {
+		super(file, elementQName, typeQName);
+		
+	}
+	
+	public XMLComponentReferencePattern(QualifiedName elementQName, QualifiedName typeQName) {
+		super(null, elementQName, typeQName);
+		
+	}
+	
+	
+	
+	
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-search/org/eclipse/wst/xml/core/internal/search/XMLComponentSearchPattern.java b/bundles/org.eclipse.wst.xml.core/src-search/org/eclipse/wst/xml/core/internal/search/XMLComponentSearchPattern.java
new file mode 100644
index 0000000..dff3048
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-search/org/eclipse/wst/xml/core/internal/search/XMLComponentSearchPattern.java
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.xml.core.internal.search;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.wst.common.core.search.SearchParticipant;
+import org.eclipse.wst.common.core.search.pattern.ComponentSearchPattern;
+import org.eclipse.wst.common.core.search.pattern.QualifiedName;
+
+/**
+ * XML component search pattern is a composite pattern that combines XML element pattern.
+ *
+ */
+public class XMLComponentSearchPattern extends ComponentSearchPattern {
+	
+	/**
+	 * Containing element patterns
+	 * @deprecated
+	 */
+	XMLSearchPattern[] children = new XMLSearchPattern[0];
+	
+	/**
+	 * A map of XMLSearchPattern[] by {@link SearchParticipant search participant}.
+	 */
+	protected Map childPatternsByParticipant = new HashMap();
+	
+	public XMLComponentSearchPattern(IFile file, QualifiedName elementQName, QualifiedName typeQName, int matchRule) {
+		super(file, elementQName, typeQName, matchRule);
+		
+	}
+
+
+	public XMLComponentSearchPattern(IFile file, QualifiedName elementQName, QualifiedName typeQName) {
+		super(file, elementQName, typeQName);
+		
+	}
+
+	/**
+	 * @deprecated Use {@link #getChildren(SearchParticipant)} instead.
+	 */
+	public XMLSearchPattern[] getChildren(){
+		return children;
+	}
+	
+    /**
+     * @deprecated Use {@link #addChildren(SearchParticipant, XMLSearchPattern[])} instead.
+     */
+	public void setChildren(XMLSearchPattern[] patterns){
+		children = patterns;
+		
+	}
+	
+	/**
+	 * Provides the child patterns contributed by the given search participant. 
+	 * @param searchParticipant the {@link SearchParticipant search participant} that contributed the patterns.
+     * @see XMLComponentSearchPattern#addChildren(SearchParticipant, XMLSearchPattern[]) addChildren
+	 * @return an array with the {@link XMLSearchPattern patterns} contributed by the {@link SearchParticipant search participant}.
+	 */
+	public XMLSearchPattern[] getChildren(SearchParticipant searchParticipant){
+	  XMLSearchPattern[] childPatterns = getChildren();
+	  if (searchParticipant != null){
+	    childPatterns = (XMLSearchPattern[])childPatternsByParticipant.get(searchParticipant);
+	    if (childPatterns == null){
+	      childPatterns = getChildren();
+	    }
+	  }
+	  return childPatterns;
+	}
+
+	/**
+	 * Saves the child patterns contributed by the given search participant.
+	 * @param searchParticipant the {@link SearchParticipant search participant} that is contributing the child search patterns.
+	 * @param childPatterns the child patterns contributed by the {@link SearchParticipant searchParticipant search participant}.
+	 * @see XMLComponentSearchPattern#getChildren(SearchParticipant) getChildren
+	 */
+	public void addChildren(SearchParticipant searchParticipant, XMLSearchPattern[] childPatterns){
+	  if (searchParticipant != null && childPatterns != null) {
+	    childPatternsByParticipant.put(searchParticipant, childPatterns);
+	  }
+	  else {
+	    children = childPatterns;
+	  }
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-search/org/eclipse/wst/xml/core/internal/search/XMLSearchParticipant.java b/bundles/org.eclipse.wst.xml.core/src-search/org/eclipse/wst/xml/core/internal/search/XMLSearchParticipant.java
new file mode 100644
index 0000000..b709f58
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-search/org/eclipse/wst/xml/core/internal/search/XMLSearchParticipant.java
@@ -0,0 +1,387 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.xml.core.internal.search;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.wst.common.core.search.SearchMatch;
+import org.eclipse.wst.common.core.search.SearchParticipant;
+import org.eclipse.wst.common.core.search.SearchRequestor;
+import org.eclipse.wst.common.core.search.document.ComponentDeclarationEntry;
+import org.eclipse.wst.common.core.search.document.Entry;
+import org.eclipse.wst.common.core.search.document.FileReferenceEntry;
+import org.eclipse.wst.common.core.search.document.SearchDocument;
+import org.eclipse.wst.common.core.search.document.SearchDocumentSet;
+import org.eclipse.wst.common.core.search.pattern.ComponentSearchPattern;
+import org.eclipse.wst.common.core.search.pattern.FileReferencePattern;
+import org.eclipse.wst.common.core.search.pattern.SearchPattern;
+import org.eclipse.wst.common.core.search.scope.ContentTypeSearchScope;
+import org.eclipse.wst.common.core.search.scope.SearchScope;
+import org.eclipse.wst.common.uriresolver.internal.provisional.URIResolver;
+import org.eclipse.wst.common.uriresolver.internal.provisional.URIResolverPlugin;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
+import org.eclipse.wst.xml.core.internal.search.impl.IXMLSearchConstants;
+import org.eclipse.wst.xml.core.internal.search.impl.XMLSearchDocument;
+import org.eclipse.wst.xml.core.internal.search.matching.PatternMatcher;
+import org.eclipse.wst.xml.core.internal.search.matching.XMLSearchPatternMatcher;
+import org.eclipse.wst.xml.core.internal.search.quickscan.XMLQuickScan;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ *
+ */
+public abstract class XMLSearchParticipant extends SearchParticipant {
+	
+	protected static final boolean debugPerf = "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.wst.xml.core.internal.search/perf")); //$NON-NLS-1$ //$NON-NLS-2$
+
+	public XMLSearchParticipant() {
+		super();
+	}
+
+	
+	/*
+ public  boolean initialize(SearchPattern pattern, String[] contentTypes){
+		
+	    super.initialize(pattern, contentTypes);
+		this.supportedContentTypes = contentTypes;
+		
+		if(pattern instanceof XMLComponentSearchPattern){
+			return true;
+		}
+		return false;
+	}*/
+
+	
+
+	public SearchDocument createSearchDocument(String documentPath) {
+
+		return new XMLSearchDocument(documentPath, this);
+
+	}
+
+	public String getDescription() {
+		return "XML search participant"; //$NON-NLS-1$
+	}
+
+
+
+	private void locateMatches(SearchPattern pattern, SearchDocument document,
+			SearchRequestor requestor, Map searchOptions, IProgressMonitor monitor) {
+
+        // TODO... utilize search options (that should get passed down via the SearchEngine)
+        // to specify if accurate source coordinates are req'd if not, simply use the SAX results
+        //
+        if (pattern.getMatchRule() == SearchPattern.R_PATTERN_MATCH)
+        {          
+          IFile file = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(new Path(document.getPath()));
+          // TODO.. don't assume the category is COMPONENT_DECL... handle any arbitarty category
+          Entry[] entries = document.getEntries(IXMLSearchConstants.COMPONENT_DECL, null, 0);
+          for (int i = 0; i < entries.length; i++)
+          {
+            // TODO.. don't assume this is just a component declaration entry            
+            ComponentDeclarationEntry entry = (ComponentDeclarationEntry)entries[i];
+            SearchMatch searchMatch = new SearchMatch(null, 0, 0, file);
+            searchMatch.map.put("name", entry.getName()); //$NON-NLS-1$
+            searchMatch.map.put("metaName", entry.getMetaName()); //$NON-NLS-1$
+            try
+            {
+              requestor.acceptSearchMatch(searchMatch);
+            }
+            catch (Exception e)
+            {              
+            }
+          }  
+        }
+        else 
+        {  if (document.getModel() instanceof IDOMModel) {
+			IDOMModel domModel = (IDOMModel) document.getModel();
+			IDOMElement contextNode = (IDOMElement) domModel.getDocument()
+					.getDocumentElement();
+			DOMVisitor visitor = new DOMVisitor(document.getPath(), pattern,
+					requestor);
+			visitor.visit(contextNode);
+		}
+        }
+	}
+	
+	private PatternMatcher getAdapter(Object adaptableObject, Class adapterType) {
+		if (PatternMatcher.class.equals(adapterType) &&
+				(adaptableObject instanceof XMLSearchPattern ||
+				adaptableObject instanceof XMLComponentSearchPattern) ) {
+			return new XMLSearchPatternMatcher(this);
+		} 
+		return null; 
+	}
+
+	private class DOMVisitor {
+
+		String path;
+		SearchPattern pattern;
+		SearchRequestor requestor;
+		PatternMatcher matcher;
+
+		
+		protected DOMVisitor(String path, SearchPattern pattern,
+				SearchRequestor requestor) {
+			super();
+			this.path = path;
+			this.pattern = pattern;
+			
+			matcher = (PatternMatcher)pattern.getAdapter(PatternMatcher.class);
+			if(matcher == null){
+				matcher = getAdapter(pattern, PatternMatcher.class);
+			}
+			this.requestor = requestor;
+		}
+
+		private void visit(Node node) {
+			if (node.getNodeType() == Node.ELEMENT_NODE) {
+				match((Element)node);
+				NodeList nodeList = node.getChildNodes();
+				for (int i = 0; i < nodeList.getLength(); i++) {
+					Node aNode = nodeList.item(i);
+					visit(aNode);
+				}
+			}
+		}
+
+		private void match(Element node) {
+			IFile file = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(
+					new Path(path));
+			if(matcher != null){
+				matcher.locateMatches(pattern, file, node, requestor);
+			}
+
+			
+		}
+
+	}
+
+	public SearchScope selectDocumentLocations(SearchPattern pattern, SearchScope scope, Map searchOptions, IProgressMonitor monitor) {
+		/*
+		 * gate #1: reduce the scope to the files with the content type that
+		 * could be searched using this participant
+		 */ 
+		String[] contentTypes = getSupportedContentTypes();	
+		if(contentTypes != null && contentTypes.length > 0){
+			scope = new ContentTypeSearchScope(scope, contentTypes);
+		}
+		return super.selectDocumentLocations(pattern, scope, searchOptions, monitor);
+	}
+	
+	public abstract ComponentSearchContributor getSearchContributor();
+
+
+	public void beginSearching(SearchPattern pattern, Map searchOptions) {
+		
+		super.beginSearching(pattern, searchOptions);
+		if(pattern instanceof XMLComponentDeclarationPattern){
+			XMLComponentDeclarationPattern componentPattern = (XMLComponentDeclarationPattern)pattern;
+			XMLSearchPattern childPattern = getSearchContributor().getDeclarationPattern(componentPattern.getMetaName());
+			if(childPattern != null){
+					childPattern.setSearchName(componentPattern.getName().getLocalName());
+					childPattern.setSearchNamespace(componentPattern.getName().getNamespace());
+	     			componentPattern.addChildren(this, new XMLSearchPattern[]{childPattern});
+			}
+			
+		}
+		else if(pattern instanceof XMLComponentReferencePattern){
+			XMLComponentReferencePattern componentPattern = (XMLComponentReferencePattern)pattern;
+			XMLSearchPattern[] childPatterns = getSearchContributor().getReferencesPatterns(componentPattern.getMetaName());
+			for (int i = 0; i < childPatterns.length; i++) {
+				XMLSearchPattern childPattern = childPatterns[i];
+				childPattern.setSearchName(componentPattern.getName().getLocalName());
+				childPattern.setSearchNamespace(componentPattern.getName().getNamespace());				
+			}
+			componentPattern.addChildren(this, childPatterns);
+			
+		}
+	}
+	
+	
+	/**
+	 * The intend of this method is to limit the search to the files that have content 
+	 * which can be searched for the given pattern. It is called from 
+	 * {@link #selectDocumentLocations(SearchPattern, SearchScope, IProgressMonitor)}
+	 * 
+	 * @param pattern the search pattern that is searched for
+	 * @return content type's unique identifiers that could be searched for the given pattern.
+	 */
+	public abstract String[] getSupportedContentTypes();
+
+	public void populateSearchDocument(SearchDocument document, SearchPattern pattern)
+	{
+		PatternMatcher matcher = (PatternMatcher)pattern.getAdapter(PatternMatcher.class);
+		if(matcher == null){
+			matcher = getAdapter(pattern, PatternMatcher.class);
+		}
+		XMLQuickScan.populateSearchDocument(document, matcher, pattern);		
+	}
+
+	public void locateMatches(SearchDocumentSet documentSet, SearchPattern pattern, SearchScope scope, SearchRequestor requestor, Map searchOptions, IProgressMonitor monitor) throws CoreException
+	{
+		long time = System.currentTimeMillis();
+		
+		// TODO: use the file reference entries in the documents to reduce the scope to the referenced files only
+		// SearchDocument[] documents = documentSet.getSearchDocuments(id);
+                
+        // check to see if the search pattern is qualified by a file location
+        // if this is the case then we can use file scoping rules to prune the matches
+        IFile targetFile = null;
+        if (pattern instanceof ComponentSearchPattern)
+        {
+          ComponentSearchPattern componentSearchPattern = (ComponentSearchPattern)pattern;
+          targetFile = componentSearchPattern.getFile();                                       
+        }		
+        
+		// here we should have in scope only referenced files
+		IFile[] files = scope.enclosingFiles();  
+		for (int i = 0; i < files.length; i++)
+		{
+			IFile file = files[i];
+			String path = file.getLocation().toString();
+			SearchDocument document = documentSet.getSearchDocument(path, id); 
+			if (document != null)
+			{              
+			Entry[] entries = document.getEntries(getSearchEntryCategory(pattern), null, 0);           
+			if ((entries != null && entries.length > 0) || (searchOptions != null && searchOptions.get("searchDirtyContent") != null))
+            {
+              //for (int j = 0; j < entries.length; j++)
+              //{
+              //  Entry entry = entries[j];
+                //System.out.println("entry " + entry.getCategory() + " " + entry.getKey() + " " + entry.getClass().getName());                 
+              //}  
+              
+              boolean isInScope = true;
+              if (targetFile != null)
+              {
+                try
+                {
+                  isInScope = isLinked(documentSet, "file:///" + path, "file:///" + targetFile.getLocation().toString()); //$NON-NLS-1$ //$NON-NLS-2$
+                  //if (path.endsWith("CancelSelection.wsdl")  && path.indexOf("clone1") != -1)
+                  //{
+                  //  fileReferenceTable.debug(qualifiedPath, 0, 5);
+                  //}                   
+                }
+                catch (Exception e)
+                {
+                  e.printStackTrace();
+                }
+              }              
+              if (isInScope)
+              { 
+			    this.locateMatches(pattern, document, requestor, searchOptions, monitor);
+              }  
+            }
+			}
+		}
+		
+		
+		if (debugPerf)
+		{
+			System.out
+					.println("" //$NON-NLS-1$
+							+ getDescription()
+							+ ": " + (System.currentTimeMillis() - time) + "ms for locateMatches"); //$NON-NLS-1$ //$NON-NLS-2$
+		}
+
+		
+	}
+    
+    private boolean isLinked(SearchDocumentSet set, String source, String target)
+    {
+      return isLinked(set, source, target, new HashMap());
+    }
+    
+    private boolean isLinked(SearchDocumentSet set, String source, String target, HashMap visited)
+    {
+      if (source.equals(target))
+        return true;
+      
+      String fileProtocol = "file:///";             //$NON-NLS-1$
+      
+      // Fix for bug 204174 - Begin
+      if(target.charAt(fileProtocol.length()) == '/')  //$NON-NLS-1$
+      {
+          target = fileProtocol + target.substring(fileProtocol.length() + 1);
+      }
+      // Fix for bug 204174 - End
+            
+      if (source.startsWith(fileProtocol))
+      {    
+        
+      SearchDocument document = set._tempGetSearchDocumetn(source.substring(fileProtocol.length()));      
+      if (document != null)
+      {        
+        URIResolver uriResolver = URIResolverPlugin.createResolver();        
+        Entry[] entries = document.getEntries(IXMLSearchConstants.REF, null, 0);
+        String[] resolveEntry = new String[entries.length];        
+        for (int j = 0; j < entries.length; j++)
+        {
+          Entry entry = entries[j];
+          if (entry instanceof FileReferenceEntry)
+          {
+            FileReferenceEntry fileReferenceEntry = (FileReferenceEntry)entry;
+            // TODO.. record an utilize the public id from the fileReferenceEntry
+            //
+            if (fileReferenceEntry.getRelativeFilePath() != null)
+            {  
+              String resolvedURI = uriResolver.resolve(source, null, fileReferenceEntry.getRelativeFilePath());
+              resolveEntry[j] = resolvedURI;
+              if (resolvedURI.equals(target))
+              {
+                return true;
+              }             
+            }  
+          }
+        }
+        // now see if there's an indirect link from the source to the target
+        // we keep track of the nodes we've already visited to avoid cycles
+        if (visited.get(source) == null)
+        {
+          visited.put(source, Boolean.TRUE);
+          for (int j = 0; j < entries.length; j++)
+          {                     
+            String resolvedURI = resolveEntry[j];
+            if (resolvedURI != null && isLinked(set, resolveEntry[j], target, visited))                
+              return true;            
+          }    
+        }                      
+      }            
+      } 
+      return false;
+    }
+    
+   
+    
+	public static String getSearchEntryCategory(SearchPattern pattern){
+		if(pattern instanceof XMLComponentDeclarationPattern){
+			return IXMLSearchConstants.COMPONENT_DECL;
+		}
+		else if(pattern instanceof XMLComponentReferencePattern){
+			return IXMLSearchConstants.COMPONENT_REF;
+		}
+		else if(pattern instanceof FileReferencePattern){
+		   return IXMLSearchConstants.COMPONENT_REF;
+		}
+		return null;
+	}   
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-search/org/eclipse/wst/xml/core/internal/search/XMLSearchPattern.java b/bundles/org.eclipse.wst.xml.core/src-search/org/eclipse/wst/xml/core/internal/search/XMLSearchPattern.java
new file mode 100644
index 0000000..e3b58e1
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-search/org/eclipse/wst/xml/core/internal/search/XMLSearchPattern.java
@@ -0,0 +1,111 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.xml.core.internal.search;
+
+import org.eclipse.wst.common.core.search.pattern.SearchPattern;
+
+public class XMLSearchPattern extends SearchPattern{
+	
+	private String elementNamespace = null;
+	private String elementName = null;
+	private String attributeName = null;
+	private String searchName = null;
+	private String searchNamespace = null;
+	private String parentName = null;
+    private int depth = -1;
+
+    public XMLSearchPattern(String elementNamespace, String parentElementName,String elementName, String attributeName) {
+    	this(elementNamespace, parentElementName, elementName, attributeName, -1);
+    }
+	
+	public XMLSearchPattern(String elementNamespace, String elementName, String attributeName) {
+       this(elementNamespace, null, elementName, attributeName, -1);
+    }
+    
+    public XMLSearchPattern(String elementNamespace, String elementName, String attributeName, int depth) {
+    	this(elementNamespace, null, elementName, attributeName, depth);       
+    }
+           
+    private XMLSearchPattern(String elementNamespace, String parentElementName, String elementName, String attributeName, int depth) {
+        super();
+        this.attributeName = attributeName;
+        this.elementName = elementName;
+        this.parentName = parentElementName;
+        this.elementNamespace = elementNamespace;
+        this.depth = depth;
+    }
+    
+	public XMLSearchPattern(){
+		
+	}
+	
+	public String getAttributeName() {
+		return attributeName;
+	}
+
+	public String getElementName() {
+		return elementName;
+	}
+
+	public String getElementNamespace() {
+		return elementNamespace;
+	}
+
+	public String getSearchName() {
+		return searchName;
+	}
+
+	public String getSearchNamespace() {
+		return searchNamespace;
+	}
+
+	public void setSearchName(String searchName) {
+		this.searchName = searchName;
+	}
+
+	public void setSearchNamespace(String searchNamespace) {
+		this.searchNamespace = searchNamespace;
+	}
+
+	public void setAttributeName(String attributeName) {
+		this.attributeName = attributeName;
+	}
+
+	public void setElementName(String elementName) {
+		this.elementName = elementName;
+	}
+
+	public void setElementNamespace(String elementNamespace) {
+		this.elementNamespace = elementNamespace;
+	}
+
+  public int getDepth()
+  {
+    return depth;
+  }
+
+  public void setDepth(int depth)
+  {
+    this.depth = depth;
+  }
+
+public String getParentName() {
+	return parentName;
+}
+
+public void setParentName(String parentName) {
+	this.parentName = parentName;
+}
+	
+
+	
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.xml.core/src-search/org/eclipse/wst/xml/core/internal/search/impl/IXMLSearchConstants.java b/bundles/org.eclipse.wst.xml.core/src-search/org/eclipse/wst/xml/core/internal/search/impl/IXMLSearchConstants.java
new file mode 100644
index 0000000..d160d81
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-search/org/eclipse/wst/xml/core/internal/search/impl/IXMLSearchConstants.java
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.xml.core.internal.search.impl;
+
+public interface IXMLSearchConstants
+{
+		String REF= "outLink"; //$NON-NLS-1$
+		String COMPONENT_DECL = "componentDecl"; //$NON-NLS-1$
+		String COMPONENT_REF = "componentDecl"; //$NON-NLS-1$
+	
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-search/org/eclipse/wst/xml/core/internal/search/impl/Messages.java b/bundles/org.eclipse.wst.xml.core/src-search/org/eclipse/wst/xml/core/internal/search/impl/Messages.java
new file mode 100644
index 0000000..d7ae22f
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-search/org/eclipse/wst/xml/core/internal/search/impl/Messages.java
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.xml.core.internal.search.impl;
+
+import java.text.MessageFormat;
+import org.eclipse.osgi.util.NLS;
+
+public class Messages extends NLS {
+	
+	private static final String BUNDLE_NAME = "org.eclipse.wst.xml.core.internal.search.messages";//$NON-NLS-1$
+
+	
+	static {
+		NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+	}
+	private Messages() {
+		// Do not instantiate
+	}
+	
+	/**
+	 * Bind the given message's substitution locations with the given string values.
+	 * 
+	 * @param message the message to be manipulated
+	 * @return the manipulated String
+	 */
+	public static String bind(String message) {
+		return bind(message, null);
+	}
+	
+	/**
+	 * Bind the given message's substitution locations with the given string values.
+	 * 
+	 * @param message the message to be manipulated
+	 * @param binding the object to be inserted into the message
+	 * @return the manipulated String
+	 */
+	public static String bind(String message, Object binding) {
+		return bind(message, new Object[] {binding});
+	}
+
+	/**
+	 * Bind the given message's substitution locations with the given string values.
+	 * 
+	 * @param message the message to be manipulated
+	 * @param binding1 An object to be inserted into the message
+	 * @param binding2 A second object to be inserted into the message
+	 * @return the manipulated String
+	 */
+	public static String bind(String message, Object binding1, Object binding2) {
+		return bind(message, new Object[] {binding1, binding2});
+	}
+
+	/**
+	 * Bind the given message's substitution locations with the given string values.
+	 * 
+	 * @param message the message to be manipulated
+	 * @param bindings An array of objects to be inserted into the message
+	 * @return the manipulated String
+	 */
+	public static String bind(String message, Object[] bindings) {
+		return MessageFormat.format(message, bindings);
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-search/org/eclipse/wst/xml/core/internal/search/impl/XMLSearchDocument.java b/bundles/org.eclipse.wst.xml.core/src-search/org/eclipse/wst/xml/core/internal/search/impl/XMLSearchDocument.java
new file mode 100644
index 0000000..7908adf
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-search/org/eclipse/wst/xml/core/internal/search/impl/XMLSearchDocument.java
@@ -0,0 +1,105 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.xml.core.internal.search.impl;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.wst.common.core.search.document.Entry;
+import org.eclipse.wst.common.core.search.document.SearchDocument;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
+import org.eclipse.wst.xml.core.internal.search.XMLSearchParticipant;
+
+public class XMLSearchDocument extends SearchDocument {
+	
+	IDOMModel model;
+	Map entries = new HashMap(); // category -> set (entry)	
+
+	public XMLSearchDocument(String documentPath, XMLSearchParticipant participant) {
+		super(documentPath, participant);
+	}
+
+	public Object getModel() {
+		if(model == null){
+            //System.out.println("creating DOM for " + getPath());
+			IFile file = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(new Path(getPath()));
+			if(file != null){
+				try {
+					model = (IDOMModel)StructuredModelManager.getModelManager().getModelForEdit(file);
+				} catch (IOException e) {
+					e.printStackTrace();
+				} catch (CoreException e) {
+					e.printStackTrace();
+				}
+			
+			}
+		}
+		return model;
+	}
+
+	public Entry[] getEntries(String category, String key, int matchRule)
+	{
+		// TODO use matchRule
+		Set results = new HashSet();
+		if(category != null){
+			Set values = (Set)entries.get(category);
+			if(values == null){
+				return new Entry[0];
+			}
+			if(key == null || "".equals(key) || "*".equals(key)){ //$NON-NLS-1$ //$NON-NLS-2$
+				// entries with any key in the given category
+				results.addAll(values);
+			}
+			else{
+				// entries with the specified key in the given category
+				for (Iterator iter = values.iterator(); iter.hasNext();)
+				{
+					Entry entry = (Entry) iter.next();
+					if(key.equals(entry.getKey())){
+						results.add(entry);
+					}
+				}
+			}
+			
+		}
+		return (Entry[]) results.toArray(new Entry[results.size()]);
+	}
+
+	public void putEntry(Entry entry)
+	{
+		if(entry.getCategory() != null){
+			Set values = (Set)entries.get(entry.getCategory());
+			if(values == null){
+				entries.put(entry.getCategory(), values=new HashSet());
+			}
+			values.add(entry);
+		}
+		
+	}
+
+    public void dispose()
+    {     
+      if (model != null)
+      {  
+        model.releaseFromEdit();        
+      }  
+    }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-search/org/eclipse/wst/xml/core/internal/search/impl/messages.properties b/bundles/org.eclipse.wst.xml.core/src-search/org/eclipse/wst/xml/core/internal/search/impl/messages.properties
new file mode 100644
index 0000000..43aea95
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-search/org/eclipse/wst/xml/core/internal/search/impl/messages.properties
@@ -0,0 +1,10 @@
+###############################################################################
+# Copyright (c) 2005, 2006 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
+###############################################################################
diff --git a/bundles/org.eclipse.wst.xml.core/src-search/org/eclipse/wst/xml/core/internal/search/matching/PatternMatcher.java b/bundles/org.eclipse.wst.xml.core/src-search/org/eclipse/wst/xml/core/internal/search/matching/PatternMatcher.java
new file mode 100644
index 0000000..fa518e8
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-search/org/eclipse/wst/xml/core/internal/search/matching/PatternMatcher.java
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.xml.core.internal.search.matching;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.wst.common.core.search.SearchMatch;
+import org.eclipse.wst.common.core.search.SearchRequestor;
+import org.eclipse.wst.common.core.search.pattern.SearchPattern;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMAttr;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+
+/**
+ * This class contains matching implementation.  
+ * <p>
+ * Subclasses of the PatternMatches should provide an implementation of the specific pattern matching.
+ * </p>
+ * <p>
+ * Subclasses of the PatternMatches should be set as adapters for the patterns that they match.
+ * </p>
+ * An implementation of {@link org.eclipse.wst.common.core.search.SearchParticipant#selectDocumentLocations()} will call 
+ * { @link PatternMatcher#matches() } on the adapter on pattern matcher.
+ * 
+ * An implementation of {@link org.eclipse.wst.common.core.search.SearchParticipant#locateMatches()} will call 
+ * { @link PatternMatcher#locateMatches() } on the adapter on pattern matcher.
+ *
+ */
+public abstract class PatternMatcher {
+	
+	
+	/**
+	 * This method does dive actual match location to the requestor if there are matches
+	 */
+	public abstract void locateMatches(SearchPattern pattern, IFile file, Element element, SearchRequestor requestor);
+
+	/**
+	 * This method only answers if the pattern matches element, it does not give actual match location
+	 */
+	public abstract boolean matches(SearchPattern pattern, Object element);
+    
+    protected SearchMatch createSearchMatch(IFile file, Attr attributeNode)
+    {
+        int start = 0;
+        int length = 0;
+        if(attributeNode instanceof IDOMAttr){
+            IDOMAttr domAttr = (IDOMAttr)attributeNode;
+            start = domAttr.getValueRegionStartOffset();
+            length = domAttr.getValueRegionText().length();
+        }
+        SearchMatch match = new SearchMatch(attributeNode, start, length, file);
+        return match;
+    }
+	
+	protected void addMatch(SearchPattern pattern, IFile file, Attr attributeNode, SearchRequestor requestor) {
+        //System.out.println("addMatch " + pattern + " " + attributeNode.getName() + "=" + attributeNode.getValue());
+		if (attributeNode != null) {
+				SearchMatch match = createSearchMatch(file, attributeNode);                
+				if(requestor != null){
+					try {
+						requestor.acceptSearchMatch(match);
+					} catch (CoreException e) {
+						//do nothing
+					}
+				}
+		}
+	}
+
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-search/org/eclipse/wst/xml/core/internal/search/matching/SAXSearchElement.java b/bundles/org.eclipse.wst.xml.core/src-search/org/eclipse/wst/xml/core/internal/search/matching/SAXSearchElement.java
new file mode 100644
index 0000000..a9ec4a1
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-search/org/eclipse/wst/xml/core/internal/search/matching/SAXSearchElement.java
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.xml.core.internal.search.matching;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.xml.sax.Attributes;
+
+public class SAXSearchElement{
+	Attributes attributes;
+	String elementName;
+	String elementNamespace;
+	Map namespaceMap = new HashMap(); // Map of string prefix keys and namespace
+	String targetNamespace = ""; //$NON-NLS-1$
+	String parentName;
+    int depth = -1;
+	
+	public SAXSearchElement() {
+		super();
+	}
+	public Attributes getAttributes() {
+		return attributes;
+	}
+	public String getElementName() {
+		return elementName;
+	}
+	public String getElementNamespace() {
+		return elementNamespace;
+	}
+	public Map getNamespaceMap() {
+		return namespaceMap;
+	}
+	public String getTargetNamespace() {
+		return targetNamespace;
+	}
+	public void setAttributes(Attributes attributes) {
+		this.attributes = attributes;
+	}
+	public void setElementName(String elementName) {
+		this.elementName = elementName;
+	}
+	public void setElementNamespace(String elementNamespace) {
+		this.elementNamespace = elementNamespace;
+	}
+	public void setNamespaceMap(Map namespaceMap) {
+		this.namespaceMap = namespaceMap;
+	}
+	public void setTargetNamespace(String targetNamespace) {
+		this.targetNamespace = targetNamespace;
+	}
+  public int getDepth()
+  {
+    return depth;
+  }
+  public void setDepth(int depth)
+  {
+    this.depth = depth;
+  }
+public String getParentName() {
+	return parentName;
+}
+public void setParentName(String parentName) {
+	this.parentName = parentName;
+}
+	
+	
+	
+	
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.xml.core/src-search/org/eclipse/wst/xml/core/internal/search/matching/XMLSearchPatternMatcher.java b/bundles/org.eclipse.wst.xml.core/src-search/org/eclipse/wst/xml/core/internal/search/matching/XMLSearchPatternMatcher.java
new file mode 100644
index 0000000..b38e354
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-search/org/eclipse/wst/xml/core/internal/search/matching/XMLSearchPatternMatcher.java
@@ -0,0 +1,237 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.xml.core.internal.search.matching;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.wst.common.core.search.SearchMatch;
+import org.eclipse.wst.common.core.search.SearchParticipant;
+import org.eclipse.wst.common.core.search.SearchRequestor;
+import org.eclipse.wst.common.core.search.pattern.QualifiedName;
+import org.eclipse.wst.common.core.search.pattern.SearchPattern;
+import org.eclipse.wst.xml.core.internal.search.XMLComponentSearchPattern;
+import org.eclipse.wst.xml.core.internal.search.XMLSearchPattern;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+
+public class XMLSearchPatternMatcher extends PatternMatcher{
+	
+   /**
+    * The active search participant.
+    */
+    private SearchParticipant searchParticipant;
+  
+    /**
+     * Constructs a pattern matcher given a search participant.
+     * @param searchParticipant the active {@link SearchParticipant search participant}.
+     */
+    public XMLSearchPatternMatcher(SearchParticipant searchParticipant)
+    {
+      this.searchParticipant = searchParticipant;
+    }
+    
+	protected String computeNamespaceForPrefix(Element element, String prefix)
+	{
+	  String result = null;
+	  for (Node node = element; node != null; node = node.getParentNode())
+	  {
+		if (node.getNodeType() == Node.ELEMENT_NODE)
+		{
+		  Element e = (Element)node;
+		  String attributeName = (prefix != null && prefix.length() > 0) ? ("xmlns:" + prefix) : "xmlns";  //$NON-NLS-1$ //$NON-NLS-2$
+		  result = e.hasAttribute(attributeName) ? e.getAttribute(attributeName) : null;
+		  if (result != null && result.length() > 0)
+		  {
+			 break;  
+		  }	  
+		}	
+	  }	  
+	  return result;
+	}
+	
+
+	protected void initialize(XMLSearchPattern pattern, Element domElement) {
+	
+			pattern.setElementName(domElement.getLocalName());
+			pattern.setElementNamespace(domElement.getNamespaceURI());
+            // TODO (cs) set the depth attribute on the pattern
+            //
+			String actualValue = domElement.hasAttribute(pattern.getAttributeName()) ? domElement.getAttribute(pattern.getAttributeName()) : null;
+			 if(actualValue != null && actualValue.length() > 0){
+					int n = actualValue.indexOf(":"); //$NON-NLS-1$
+					if(n > 0){
+						String prefix = actualValue.substring(0, n);
+						pattern.setSearchName(actualValue.substring(n+1));      
+						
+						String namespace = computeNamespaceForPrefix(domElement, prefix);
+						pattern.setSearchNamespace(namespace);
+					
+					}
+					else {
+						pattern.setSearchName(actualValue);
+						pattern.setSearchNamespace(domElement.getOwnerDocument().getDocumentElement().getAttribute("targetNamespace")); //$NON-NLS-1$
+					}
+			    }
+		
+	}
+	
+	protected void initialize(XMLSearchPattern pattern, SAXSearchElement saxElement) {
+		
+		pattern.setElementName(saxElement.getElementName());
+		pattern.setElementNamespace(saxElement.getElementNamespace());
+        pattern.setDepth(saxElement.getDepth());
+        pattern.setParentName(saxElement.getParentName());
+		String actualValue = saxElement.getAttributes().getValue(pattern.getAttributeName());
+		 if(actualValue != null){
+				int n = actualValue.indexOf(":"); //$NON-NLS-1$
+				if(n > 0){
+					String prefix = actualValue.substring(0, n);
+					pattern.setSearchName(actualValue.substring(n+1));
+					pattern.setSearchNamespace((String)saxElement.getNamespaceMap().get(prefix));
+				
+				}
+				else {
+					pattern.setSearchName(actualValue);
+					pattern.setSearchNamespace(saxElement.getTargetNamespace());
+				}
+		    }
+	
+	}
+	
+	XMLSearchPattern searchPattern;
+	
+	public XMLSearchPatternMatcher() {
+		super();
+		
+	}
+
+	
+
+	
+	/**
+	 * This method does dive actual match location to the requestor if there are matches
+	 */
+	
+	public void locateMatches(SearchPattern pattern, IFile file, Element element, SearchRequestor requestor) {
+		if(pattern instanceof XMLComponentSearchPattern){
+			XMLSearchPattern[] childPatterns = ((XMLComponentSearchPattern)pattern).getChildren(searchParticipant);
+			if (childPatterns == null){
+			  return;
+			}
+			for (int i = 0; i < childPatterns.length; i++) {
+				PatternMatcher matcher = (PatternMatcher)childPatterns[i].getAdapter(PatternMatcher.class);
+				if(matcher == null){
+					matcher = this;
+				}
+				if(matcher != null){
+					matcher.locateMatches(childPatterns[i], file, element, requestor);
+				}
+			}
+		}
+		else if(pattern instanceof XMLSearchPattern){
+			if(matches(pattern, element)){
+				Attr attribute = element.getAttributeNode(((XMLSearchPattern)pattern).getAttributeName());
+				addMatch(pattern, file, attribute, requestor);
+			}
+		
+		}
+	}
+	
+	/**
+	 * This method only answers if the pattern matches element, it does not give actual match location
+	 */
+	public boolean matches(SearchPattern pattern, Object element){
+		if(pattern instanceof XMLComponentSearchPattern){
+			XMLSearchPattern[] childPatterns = ((XMLComponentSearchPattern)pattern).getChildren(searchParticipant);
+            if (childPatterns == null){
+              return false;
+            }
+			for (int i = 0; i < childPatterns.length; i++) {
+				PatternMatcher matcher = (PatternMatcher)childPatterns[i].getAdapter(PatternMatcher.class);
+				if(matcher == null){
+					matcher = this;
+				}
+				if(matcher != null){
+					if(matcher.matches(childPatterns[i], element)){
+						return true;
+					}
+				}
+				
+			}
+		}
+		else if(pattern instanceof XMLSearchPattern){
+			
+			XMLSearchPattern possibleMatch = new XMLSearchPattern();
+			possibleMatch.setAttributeName(((XMLSearchPattern)pattern).getAttributeName());
+			if(element instanceof Element){
+				initialize(possibleMatch, (Element)element);
+			}
+			else if(element instanceof SAXSearchElement){
+				initialize(possibleMatch, (SAXSearchElement)element);
+			}
+			searchPattern = (XMLSearchPattern)pattern;
+			return matchesPattern(possibleMatch);
+		}
+		return false;
+	}
+	
+	protected boolean matchesPattern(SearchPattern pattern) {
+		if(searchPattern != null && pattern instanceof XMLSearchPattern){
+			XMLSearchPattern decodedPattern = (XMLSearchPattern)pattern;
+            if(searchPattern.getElementName().equals(decodedPattern.getElementName()) &&                    
+					searchPattern.getElementNamespace().equals(decodedPattern.getElementNamespace())){                
+                if(searchPattern.getParentName() != null &&
+                   decodedPattern.getParentName() != null &&
+                   !searchPattern.getParentName().equals(decodedPattern.getParentName()))
+                {
+                  return false;  
+                }  
+                if(searchPattern.getSearchName() == null)
+                {  
+                  return false;
+                }
+                else if ("*".equals(searchPattern.getSearchName())) //$NON-NLS-1$
+                {
+                  return true;
+                }  
+                else if(searchPattern.getSearchNamespace() == null){
+					return searchPattern.getSearchName().equals(decodedPattern.getSearchName());
+				}
+				else{
+					return searchPattern.getSearchName().equals(decodedPattern.getSearchName()) &&
+					searchPattern.getSearchNamespace().equals(decodedPattern.getSearchNamespace());
+				}
+			}
+		}
+		
+		return false;
+	}
+	
+    
+    protected SearchMatch createSearchMatch(IFile file, Attr attributeNode)
+    {
+      SearchMatch match = super.createSearchMatch(file, attributeNode);
+      // todo... remove this ugly hack!!
+      if ("name".equals(attributeNode.getName())) //$NON-NLS-1$
+      {
+        QualifiedName qualifiedName = new QualifiedName("todo-compute-targetNamespace", attributeNode.getValue()); //$NON-NLS-1$
+        match.map.put("name", qualifiedName); //$NON-NLS-1$
+      }
+      //Element element = attributeNode.getOwnerDocument().getDocumentElement();
+      //if (element.getAttribute("targetNamespace"))
+      //{        
+      //}  
+      return match;
+    }
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-search/org/eclipse/wst/xml/core/internal/search/quickscan/XMLQuickScan.java b/bundles/org.eclipse.wst.xml.core/src-search/org/eclipse/wst/xml/core/internal/search/quickscan/XMLQuickScan.java
new file mode 100644
index 0000000..bf8a14c
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-search/org/eclipse/wst/xml/core/internal/search/quickscan/XMLQuickScan.java
@@ -0,0 +1,117 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.search.quickscan;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import org.eclipse.wst.common.core.search.document.SearchDocument;
+import org.eclipse.wst.common.core.search.pattern.SearchPattern;
+import org.eclipse.wst.xml.core.internal.search.matching.PatternMatcher;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.XMLReader;
+
+/**
+ * 
+ */
+public class XMLQuickScan
+{
+    /*
+	public static String getTargetNamespace(String fullFilePath)
+	{
+		XMLQuickScanContentHandler handler = new XMLQuickScanContentHandler();
+		parseFile(fullFilePath, handler);
+		return handler.getTargetNamespace();
+	}*/
+	
+	/*
+	 * Returns information about matches encountered based on the criteria
+	 * provided.
+	 *
+	public static boolean hasMatch(String fullFilePath, PatternMatcher matcher, SearchPattern pattern)
+	{
+		XMLQuickScanContentHandler handler = new XMLQuickScanContentHandler(matcher, pattern);
+		parseFile(fullFilePath, handler);
+		return handler.hasMatch();
+	}*/
+	
+	public static boolean populateSearchDocument(SearchDocument document, PatternMatcher matcher, SearchPattern pattern)
+	{
+		XMLQuickScanContentHandler handler = new XMLQuickScanContentHandler(document, matcher, pattern);
+		parseFile(document.getPath(), handler);
+		return handler.hasMatch();
+	}
+
+    private static XMLReader reader;
+    private static XMLReader getOrCreateReader()
+    {
+       if (reader == null)
+       {
+         try
+         {
+          SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
+          reader = parser.getXMLReader();  
+          reader.setFeature("http://xml.org/sax/features/namespaces", true); //$NON-NLS-1$
+          reader.setErrorHandler(new InternalErrorHandler());          
+         }
+         catch (Exception e)
+         {           
+         }
+       } 
+       return reader;
+    }
+    
+    static class InternalErrorHandler implements ErrorHandler
+    {
+      public void error(SAXParseException exception) throws SAXException
+      {          
+      }
+      
+      public void fatalError(SAXParseException exception) throws SAXException
+      {
+      }
+      public void warning(SAXParseException exception) throws SAXException
+      {        
+      }
+    }
+    
+	private synchronized static void parseFile(String fullFilePath,
+			XMLQuickScanContentHandler handler)
+	{
+		FileInputStream inputStream = null;
+		try
+		{            
+			inputStream = new FileInputStream(new File(fullFilePath));
+			XMLReader reader = getOrCreateReader();
+            reader.setContentHandler(handler);
+			//System.out.println("parseFile" + reader + " (" +  fullFilePath + ")");			
+			reader.parse(new InputSource(inputStream));
+		} catch (Exception e)
+		{
+			// skip the file
+		} 
+		finally{
+			if(inputStream != null){
+				try {
+					inputStream.close();
+				} catch (IOException e) {
+					// can not do much 
+				}
+			}
+			
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-search/org/eclipse/wst/xml/core/internal/search/quickscan/XMLQuickScanContentHandler.java b/bundles/org.eclipse.wst.xml.core/src-search/org/eclipse/wst/xml/core/internal/search/quickscan/XMLQuickScanContentHandler.java
new file mode 100644
index 0000000..65d87cd
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-search/org/eclipse/wst/xml/core/internal/search/quickscan/XMLQuickScanContentHandler.java
@@ -0,0 +1,212 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.xml.core.internal.search.quickscan;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Stack;
+
+import org.eclipse.wst.common.core.search.document.ComponentDeclarationEntry;
+import org.eclipse.wst.common.core.search.document.ComponentReferenceEntry;
+import org.eclipse.wst.common.core.search.document.FileReferenceEntry;
+import org.eclipse.wst.common.core.search.document.SearchDocument;
+import org.eclipse.wst.common.core.search.pattern.QualifiedName;
+import org.eclipse.wst.common.core.search.pattern.SearchPattern;
+import org.eclipse.wst.xml.core.internal.search.XMLComponentDeclarationPattern;
+import org.eclipse.wst.xml.core.internal.search.XMLComponentReferencePattern;
+import org.eclipse.wst.xml.core.internal.search.impl.IXMLSearchConstants;
+import org.eclipse.wst.xml.core.internal.search.matching.PatternMatcher;
+import org.eclipse.wst.xml.core.internal.search.matching.SAXSearchElement;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * This class is a SAX content handler, it should be recycled before scanning a file for the new SearchPattern.
+ *
+ */
+public class XMLQuickScanContentHandler extends DefaultHandler
+{
+	private Map namespaceMap = new HashMap(); // Map of string prefix keys and namespace
+	private String targetNamespace = ""; //$NON-NLS-1$
+	
+	private SearchPattern pattern;
+	private SearchDocument document;  // we'll add useful entries in the search document as we parsing
+	private SAXSearchElement searchElement = new SAXSearchElement();
+
+	private boolean hasMatch = false;
+	private Stack currentPath = new Stack();
+	private PatternMatcher matcher;
+	
+	public static final String XMLSCHEMA_NAMESPACE = "http://www.w3.org/2001/XMLSchema"; //$NON-NLS-1$
+  public static final String WSDL_NAMESPACE = "http://schemas.xmlsoap.org/wsdl/"; //$NON-NLS-1$
+
+	
+	public XMLQuickScanContentHandler(PatternMatcher matcher, SearchPattern pattern) {
+		super();
+		this.pattern = pattern;
+		this.matcher = matcher;
+	}
+	
+	public XMLQuickScanContentHandler(SearchDocument document, PatternMatcher matcher, SearchPattern pattern) {
+		super();
+		this.pattern = pattern;
+		this.matcher = matcher;
+		this.document = document;
+	}
+	
+	public XMLQuickScanContentHandler() {
+		super();
+	}
+
+	public void startElement(String uri, String localName, String qName,
+			Attributes attributes) throws SAXException
+	{	
+		// Search for targetNamespace if we haven't encountered it yet.
+		if (targetNamespace.equals("")) //$NON-NLS-1$
+		{
+			int nAttributes = attributes.getLength();
+			for (int i = 0; i < nAttributes; i++)
+			{
+				if ("targetNamespace".equals(attributes.getQName(i))) //$NON-NLS-1$
+				{
+					targetNamespace = attributes.getValue(i);
+					break;
+				}
+			}
+		}
+		
+		// collect link info
+    
+    // TODO This code should be refactored to delegate the responsibility to
+    // detect links between files to the search providers/contributors.
+    // The current code only handles the XSD and WSDL cases. 
+    
+		if("import".equals(localName) && namespaceMatches(uri)){ //$NON-NLS-1$
+			FileReferenceEntry documentEntry = new FileReferenceEntry();
+			documentEntry.setCategory(IXMLSearchConstants.REF);
+			documentEntry.setKey("import"); //$NON-NLS-1$
+			String namespace = attributes.getValue("namespace"); //$NON-NLS-1$
+			String location = attributes.getValue(getLocationAttributeName(uri)); //$NON-NLS-1$
+			documentEntry.setPublicIdentifier(namespace);
+			documentEntry.setRelativeFilePath(location);            
+			document.putEntry(documentEntry);
+		}
+		if(("redefine".equals(localName)|| "include".equals(localName)) && //$NON-NLS-1$ //$NON-NLS-2$
+				namespaceMatches(uri)){
+			FileReferenceEntry documentEntry = new FileReferenceEntry();
+			documentEntry.setCategory(IXMLSearchConstants.REF);
+			documentEntry.setKey("include"); //$NON-NLS-1$
+			String location = attributes.getValue(getLocationAttributeName(uri)); //$NON-NLS-1$
+			documentEntry.setPublicIdentifier(uri);
+			documentEntry.setRelativeFilePath(location);
+			document.putEntry(documentEntry);
+		}
+		
+		
+        // issue (cs) you may want to try perf measurements to compate reusing the same
+        // instance of a SAXSearchElement instead of newing one each time 
+		//XMLSearchPattern.SAXSearchElement searchElement = new XMLSearchPattern.SAXSearchElement();
+		searchElement.setElementName(localName);
+		searchElement.setElementNamespace(uri);
+		searchElement.setAttributes(attributes);
+		searchElement.setNamespaceMap(namespaceMap);
+		searchElement.setTargetNamespace(targetNamespace);
+		if (currentPath.size() > 0)
+		{
+		  String parentName = (String)currentPath.peek();
+		  searchElement.setParentName(parentName);
+		}			
+	
+
+		if(matcher != null){
+			if(matcher.matches(pattern, searchElement)){
+				hasMatch = true;
+				if(pattern instanceof XMLComponentReferencePattern){
+					ComponentReferenceEntry documentEntry = new ComponentReferenceEntry();
+					documentEntry.setCategory(IXMLSearchConstants.COMPONENT_REF);
+					QualifiedName name = new QualifiedName(uri, localName);
+					documentEntry.setKey(name.toString());
+					documentEntry.setName(name);
+					document.putEntry(documentEntry);
+				}
+				else if(pattern instanceof XMLComponentDeclarationPattern){
+					ComponentDeclarationEntry documentEntry = new ComponentDeclarationEntry();
+					documentEntry.setCategory(IXMLSearchConstants.COMPONENT_DECL);
+                    QualifiedName name = new QualifiedName(targetNamespace, attributes.getValue("name")); //$NON-NLS-1$
+					QualifiedName metaName = new QualifiedName(uri, localName);                    
+					documentEntry.setKey(name.toString());
+                    documentEntry.setName(name);
+					documentEntry.setMetaName(metaName);
+					document.putEntry(documentEntry);
+				}
+			}
+		}
+		currentPath.push(localName); //$NON-NLS-1$		
+	}
+
+  private String getLocationAttributeName(String uri)
+  {
+    if (XMLSCHEMA_NAMESPACE.equals(uri))
+    {
+      return "schemaLocation";
+    }
+    
+    else if (WSDL_NAMESPACE.equals(uri))
+    {
+      return "location";
+    }
+    
+    return "";
+  }
+
+  private boolean namespaceMatches(String uri)
+  {
+    return XMLSCHEMA_NAMESPACE.equals(uri) ||
+          WSDL_NAMESPACE.equals(uri);
+  }
+	
+	public void endElement(String uri, String localName, String qName)
+			throws SAXException
+	{
+		currentPath.pop();
+	}
+
+	/**
+	 * Callback for SAX parser
+	 * 
+	 * @see org.xml.sax.ContentHandler#startPrefixMapping(java.lang.String,
+	 *      java.lang.String)
+	 */
+	public void startPrefixMapping(String arg0, String arg1)
+			throws SAXException
+	{
+		if (arg0 != null && arg0.length() > 0)
+		{
+			this.namespaceMap.put(arg0, arg1);
+		}
+	}
+
+	public String getTargetNamespace() {
+		return targetNamespace;
+	}
+
+	public void setTargetNamespace(String targetNamespace) {
+		this.targetNamespace = targetNamespace;
+	}
+
+	public boolean hasMatch() {
+		return hasMatch;
+	}
+
+	
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/AnnotationMsg.java b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/AnnotationMsg.java
new file mode 100644
index 0000000..5ba65d9
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/AnnotationMsg.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *     
+ ********************************************************************************/
+package org.eclipse.wst.xml.core.internal.validation;
+
+public class AnnotationMsg {
+	public static String PROBMLEM_ID = "ProblemId"; //$NON-NLS-1$
+	public static String LENGTH = "Length"; //$NON-NLS-1$
+	public static String ATTRVALUETEXT = "AttributeValueText"; //$NON-NLS-1$
+	public static String ATTRVALUENO = "AttributeValueNo"; //$NON-NLS-1$
+	public static String ATTRNO = "AttrNo"; //$NON-NLS-1$
+	private int problemId;
+	private Object attributeValueText;
+	private int length;
+	
+	public AnnotationMsg(int problemId, Object attributeValueText, int length) {
+		super();
+		this.problemId = problemId;
+		this.attributeValueText = attributeValueText;
+		this.length = length;
+	}
+	public int getProblemId() {
+		return problemId;
+	}
+
+	public Object getAttributeValueText() {
+		return attributeValueText;
+	}
+
+	public int getLength(){
+		return length;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/MarkupValidator.java b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/MarkupValidator.java
new file mode 100644
index 0000000..a6d19bf
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/MarkupValidator.java
@@ -0,0 +1,929 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.validation;
+
+import java.util.Locale;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceProxy;
+import org.eclipse.core.resources.IResourceProxyVisitor;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.core.runtime.content.IContentDescription;
+import org.eclipse.core.runtime.content.IContentType;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+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.ITextRegionContainer;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList;
+import org.eclipse.wst.validation.AbstractValidator;
+import org.eclipse.wst.validation.ValidationResult;
+import org.eclipse.wst.validation.ValidationState;
+import org.eclipse.wst.validation.internal.core.Message;
+import org.eclipse.wst.validation.internal.core.ValidationException;
+import org.eclipse.wst.validation.internal.operations.IWorkbenchContext;
+import org.eclipse.wst.validation.internal.operations.LocalizedMessage;
+import org.eclipse.wst.validation.internal.provisional.core.IMessage;
+import org.eclipse.wst.validation.internal.provisional.core.IReporter;
+import org.eclipse.wst.validation.internal.provisional.core.IValidationContext;
+import org.eclipse.wst.validation.internal.provisional.core.IValidator;
+import org.eclipse.wst.xml.core.internal.Logger;
+import org.eclipse.wst.xml.core.internal.XMLCoreMessages;
+import org.eclipse.wst.xml.core.internal.XMLCorePlugin;
+import org.eclipse.wst.xml.core.internal.preferences.XMLCorePreferenceNames;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+import org.w3c.dom.Node;
+
+/**
+ * Basic XML syntax checking step.
+ */
+public class MarkupValidator extends AbstractValidator implements IValidator {
+	public static final int ELEMENT_ERROR_LIMIT = 25;
+    public static final int PARTIAL = 1;
+    public static final int TOTAL = 0;
+	private String DQUOTE = "\""; //$NON-NLS-1$
+	private String SQUOTE = "'"; //$NON-NLS-1$
+	
+
+	private IDocument fDocument;
+
+	private IContentType fRootContentType = null;
+
+    private IReporter fReporter = null;
+  
+	private static final String ANNOTATIONMSG = AnnotationMsg.class.getName();
+
+	public void getAnnotationMsg(IReporter reporter, int problemId, LocalizedMessage message, Object attributeValueText, int len){
+		AnnotationMsg annotation = new AnnotationMsg(problemId, attributeValueText,len);
+		message.setAttribute(ANNOTATIONMSG, annotation);
+		reporter.addMessage(this, message);
+	}
+	
+		
+	private void addAttributeError(String messageText, String attributeValueText, int start, int length, int problemId, IStructuredDocumentRegion sdRegion, IReporter reporter, int messageSeverity) {
+
+		if (sdRegion.isDeleted()) {
+			return;
+		}
+
+		int lineNo = getLineNumber(start);
+		LocalizedMessage message = new LocalizedMessage(messageSeverity, messageText);
+		message.setOffset(start);
+		message.setLength(length);
+		message.setLineNo(lineNo);
+		
+
+		getAnnotationMsg(reporter, problemId, message, attributeValueText,length);
+		
+	}
+
+	private void checkAttributesInEndTag(IStructuredDocumentRegion structuredDocumentRegion, IReporter reporter) {
+
+		if (structuredDocumentRegion.isDeleted()) {
+			return;
+		}
+
+		ITextRegionList textRegions = structuredDocumentRegion.getRegions();
+		int errorCount = 0;
+		int start = structuredDocumentRegion.getEndOffset();
+		int end = structuredDocumentRegion.getEndOffset();
+		for (int i = 0; (i < textRegions.size()) && (errorCount < ELEMENT_ERROR_LIMIT) && !structuredDocumentRegion.isDeleted(); i++) {
+			ITextRegion textRegion = textRegions.get(i);
+			if ((textRegion.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) || (textRegion.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_EQUALS) || (textRegion.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE)) {
+				if (start > structuredDocumentRegion.getStartOffset(textRegion)) {
+					start = structuredDocumentRegion.getStartOffset(textRegion);
+				}
+				end = structuredDocumentRegion.getEndOffset(textRegion);
+				errorCount++;
+			}
+		}
+		// create one error for all attributes in the end tag
+		if (errorCount > 0) {
+			// Position p = new Position(start, end - start);
+			String messageText = XMLCoreMessages.End_tag_has_attributes;
+			LocalizedMessage message = new LocalizedMessage(getPluginPreference().getInt(XMLCorePreferenceNames.END_TAG_WITH_ATTRIBUTES), messageText);
+			message.setOffset(start);
+			message.setLength(end - start);
+			message.setLineNo(getLineNumber(start));
+
+			getAnnotationMsg(reporter, ProblemIDsXML.AttrsInEndTag, message, null,end-start);
+			
+		}
+	}
+
+
+	private void checkClosingBracket(IStructuredDocumentRegion structuredDocumentRegion, IReporter reporter) {
+
+		if (structuredDocumentRegion.isDeleted()) {
+			return;
+		}
+
+		ITextRegionList regions = structuredDocumentRegion.getRegions();
+		ITextRegion r = null;
+		boolean closed = false;
+		for (int i = 0; (i < regions.size()) && !structuredDocumentRegion.isDeleted(); i++) {
+			r = regions.get(i);
+			if ((r.getType() == DOMRegionContext.XML_TAG_CLOSE) || (r.getType() == DOMRegionContext.XML_EMPTY_TAG_CLOSE)) {
+				closed = true;
+			}
+		}
+		if (!closed) {
+
+			String messageText = XMLCoreMessages.ReconcileStepForMarkup_6;
+
+			int start = structuredDocumentRegion.getStartOffset();
+			int length = structuredDocumentRegion.getText().trim().length();
+			int lineNo = getLineNumber(start);
+
+			LocalizedMessage message = new LocalizedMessage(getPluginPreference().getInt(XMLCorePreferenceNames.MISSING_CLOSING_BRACKET) , messageText);
+			message.setOffset(start);
+			message.setLength(length);
+			message.setLineNo(lineNo);
+			getAnnotationMsg(reporter, ProblemIDsXML.MissingClosingBracket, message, null,length);
+
+			
+		}
+	}
+
+	private void checkEmptyTag(IStructuredDocumentRegion structuredDocumentRegion, IReporter reporter) {
+
+		if (structuredDocumentRegion.isDeleted()) {
+			return;
+		}
+
+		// navigate to name
+		ITextRegionList regions = structuredDocumentRegion.getRegions();
+		if (regions.size() == 2) {
+			// missing name region
+			if ((regions.get(0).getType() == DOMRegionContext.XML_TAG_OPEN) && (regions.get(1).getType() == DOMRegionContext.XML_TAG_CLOSE)) {
+				String messageText = XMLCoreMessages.ReconcileStepForMarkup_3;
+				int start = structuredDocumentRegion.getStartOffset();
+				int length = structuredDocumentRegion.getLength();
+				int lineNo = getLineNumber(start);
+
+				LocalizedMessage message = new LocalizedMessage(getPluginPreference().getInt(XMLCorePreferenceNames.MISSING_TAG_NAME) , messageText);
+				message.setOffset(start);
+				message.setLength(length);
+				message.setLineNo(lineNo);
+
+				getAnnotationMsg(reporter, ProblemIDsXML.EmptyTag, message, null,length);
+			}
+		}
+	}
+
+	private int getLineNumber(int start) {
+		int lineNo = -1;
+		try {
+			lineNo = getDocument().getLineOfOffset(start) + 1;
+		}
+		catch (BadLocationException e) {
+			Logger.logException(e);
+		}
+		return lineNo;
+	}
+
+	private void checkForAttributeValue(IStructuredDocumentRegion structuredDocumentRegion, IReporter reporter) {
+		if (structuredDocumentRegion.isDeleted()) {
+			return;
+		}
+
+		// check for attributes without a value
+		// track the attribute/equals/value sequence using a state of 0, 1 ,2
+		// representing the name, =, and value, respectively
+		int attrState = 0;
+		ITextRegionList textRegions = structuredDocumentRegion.getRegions();
+		// ReconcileAnnotationKey key = createKey(structuredDocumentRegion,
+		// getScope());
+
+		int errorCount = 0;
+		for (int i = 0; (i < textRegions.size()) && (errorCount < ELEMENT_ERROR_LIMIT); i++) {
+			ITextRegion textRegion = textRegions.get(i);
+			if ((textRegion.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) || isTagCloseTextRegion(textRegion)) {
+				// dangling name and '='
+				if ((attrState == 2) && (i >= 2)) {
+					// create annotation
+					ITextRegion nameRegion = textRegions.get(i - 2);
+					if (!(nameRegion instanceof ITextRegionContainer)) {
+						Object[] args = {structuredDocumentRegion.getText(nameRegion)};
+						String messageText = NLS.bind(XMLCoreMessages.Attribute__is_missing_a_value, args);
+
+						int start = structuredDocumentRegion.getStartOffset(nameRegion);
+						int end = structuredDocumentRegion.getEndOffset();
+						int lineNo = getLineNumber(start);
+						int textLength = structuredDocumentRegion.getText(nameRegion).trim().length();
+
+						LocalizedMessage message = new LocalizedMessage(getPluginPreference().getInt(XMLCorePreferenceNames.ATTRIBUTE_HAS_NO_VALUE) , messageText);
+						message.setOffset(start);
+						message.setLength(textLength);
+						message.setLineNo(lineNo);
+
+						// quick fix info
+						ITextRegion equalsRegion = textRegions.get(i - 2 + 1);
+						int insertOffset = structuredDocumentRegion.getTextEndOffset(equalsRegion) - end;
+						Object[] additionalFixInfo = {structuredDocumentRegion.getText(nameRegion), new Integer(insertOffset)};
+
+						getAnnotationMsg(reporter, ProblemIDsXML.MissingAttrValue, message, additionalFixInfo,textLength);
+						errorCount++;
+					}
+				}
+				// name but no '=' (XML only)
+				else if ((attrState == 1) && (i >= 1)) {
+					// create annotation
+					ITextRegion previousRegion = textRegions.get(i - 1);
+					if (!(previousRegion instanceof ITextRegionContainer)) {
+						Object[] args = {structuredDocumentRegion.getText(previousRegion)};
+						String messageText = NLS.bind(XMLCoreMessages.Attribute__has_no_value, args);
+						int start = structuredDocumentRegion.getStartOffset(previousRegion);
+						int textLength = structuredDocumentRegion.getText(previousRegion).trim().length();
+						int lineNo = getLineNumber(start);
+
+						LocalizedMessage message = new LocalizedMessage(getPluginPreference().getInt(XMLCorePreferenceNames.ATTRIBUTE_HAS_NO_VALUE), messageText);
+						message.setOffset(start);
+						message.setLength(textLength);
+						message.setLineNo(lineNo);
+
+						getAnnotationMsg(reporter, ProblemIDsXML.NoAttrValue, message, structuredDocumentRegion.getText(previousRegion),textLength);
+				
+
+						errorCount++;
+					}
+				}
+				attrState = 1;
+			}
+			else if (textRegion.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_EQUALS) {
+				attrState = 2;
+			}
+			else if (textRegion.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
+				attrState = 0;
+			}
+		}
+
+	}
+
+	private void checkForSpaceBeforeName(IStructuredDocumentRegion structuredDocumentRegion, IReporter reporter) {
+
+		if (structuredDocumentRegion.isDeleted()) {
+			return;
+		}
+
+		String sdRegionText = structuredDocumentRegion.getFullText();
+		if (sdRegionText.startsWith(" ")) { //$NON-NLS-1$
+			IStructuredDocumentRegion prev = structuredDocumentRegion.getPrevious();
+			if (prev != null) {
+				// this is possibly the case of "< tag"
+				if ((prev.getRegions().size() == 1) && isStartTag(prev)) {
+					// add the error for preceding space in tag name
+					String messageText = XMLCoreMessages.ReconcileStepForMarkup_2;
+					int start = structuredDocumentRegion.getStartOffset();
+					// find length of whitespace
+					int length = sdRegionText.trim().equals("") ? sdRegionText.length() : sdRegionText.indexOf(sdRegionText.trim()); //$NON-NLS-1$
+
+					LocalizedMessage message = new LocalizedMessage(getPluginPreference().getInt(XMLCorePreferenceNames.WHITESPACE_BEFORE_TAGNAME) , messageText);
+					message.setOffset(start);
+					message.setLength(length);
+					message.setLineNo(getLineNumber(start));
+					getAnnotationMsg(reporter, ProblemIDsXML.SpacesBeforeTagName, message, null,length);
+				}
+			}
+		}
+	}
+
+	private void checkNoNamespaceInPI(IStructuredDocumentRegion structuredDocumentRegion, IReporter reporter) {
+
+		if (structuredDocumentRegion.isDeleted()) {
+			return;
+		}
+
+		// navigate to name
+		ITextRegionList regions = structuredDocumentRegion.getRegions();
+		ITextRegion r = null;
+		int errorCount = 0;
+		for (int i = 0; (i < regions.size()) && (errorCount < ELEMENT_ERROR_LIMIT) && !structuredDocumentRegion.isDeleted(); i++) {
+			r = regions.get(i);
+			if (r.getType() == DOMRegionContext.XML_TAG_NAME) {
+				String piText = structuredDocumentRegion.getText(r);
+				int index = piText.indexOf(":"); //$NON-NLS-1$
+				if (index != -1) {
+					String messageText = XMLCoreMessages.ReconcileStepForMarkup_4;
+					int start = structuredDocumentRegion.getStartOffset(r) + index;
+					int length = piText.trim().length() - index;
+
+					LocalizedMessage message = new LocalizedMessage(getPluginPreference().getInt(XMLCorePreferenceNames.NAMESPACE_IN_PI_TARGET) , messageText);
+					message.setOffset(start);
+					message.setLength(length);
+					message.setLineNo(getLineNumber(start));
+
+					
+					getAnnotationMsg(reporter, ProblemIDsXML.NamespaceInPI, message, null,length);
+
+					errorCount++;
+				}
+			}
+		}
+	}
+
+	private void checkQuotesForAttributeValues(IStructuredDocumentRegion structuredDocumentRegion, IReporter reporter) {
+		ITextRegionList regions = structuredDocumentRegion.getRegions();
+		ITextRegion r = null;
+		String attrValueText = ""; //$NON-NLS-1$
+		int errorCount = 0;
+		for (int i = 0; (i < regions.size()) && (errorCount < ELEMENT_ERROR_LIMIT); i++) {
+			r = regions.get(i);
+			if (r.getType() != DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
+				continue;
+			}
+
+			attrValueText = structuredDocumentRegion.getText(r);
+			// attribute value includes quotes in the string
+			// split up attribute value on quotes
+			/*
+			 * WORKAROUND till
+			 * http://dev.icu-project.org/cgi-bin/icu-bugs/incoming?findid=5207
+			 * is fixed. (Also see BUG143628)
+			 */
+
+			java.util.StringTokenizer st = new java.util.StringTokenizer(attrValueText, "\"'", true); //$NON-NLS-1$
+			int size = st.countTokens();
+			// get the pieces of the attribute value
+			String one = "", two = ""; //$NON-NLS-1$ //$NON-NLS-2$
+			if (size > 0) {
+				one = st.nextToken();
+			}
+			if (size > 1) {
+				two = st.nextToken();
+			}
+			if (size > 2) {
+				// should be handled by parsing...
+				// as in we can't have an attribute value like: <element
+				// attr="a"b"c"/>
+				// and <element attr='a"b"c' /> is legal
+				continue;
+			}
+
+
+			if (size == 1) {
+				if (one.equals(DQUOTE) || one.equals(SQUOTE)) {
+					// missing closing quote
+					String message = XMLCoreMessages.ReconcileStepForMarkup_0;
+					addAttributeError(message, attrValueText, structuredDocumentRegion.getStartOffset(r), attrValueText.trim().length(), ProblemIDsXML.Unclassified, structuredDocumentRegion, reporter, getPluginPreference().getInt(XMLCorePreferenceNames.MISSING_CLOSING_QUOTE));
+					errorCount++;
+				}
+				else {
+					// missing both
+					String message = XMLCoreMessages.ReconcileStepForMarkup_1;
+					addAttributeError(message, attrValueText, structuredDocumentRegion.getStartOffset(r), attrValueText.trim().length(), ProblemIDsXML.AttrValueNotQuoted, structuredDocumentRegion, reporter, getPluginPreference().getInt(XMLCorePreferenceNames.MISSING_CLOSING_QUOTE));
+					errorCount++;
+				}
+			}
+			else if (size == 2) {
+				if ((one.equals(SQUOTE) && !two.equals(SQUOTE)) || (one.equals(DQUOTE) && !two.equals(DQUOTE))) {
+					// missing closing quote
+					String message = XMLCoreMessages.ReconcileStepForMarkup_0;
+					addAttributeError(message, attrValueText, structuredDocumentRegion.getStartOffset(r), attrValueText.trim().length(), ProblemIDsXML.Unclassified, structuredDocumentRegion, reporter, getPluginPreference().getInt(XMLCorePreferenceNames.MISSING_CLOSING_QUOTE));
+					errorCount++;
+				}
+			}
+		}
+		// end of region for loop
+	}
+
+	private void checkStartEndTagPairs(IStructuredDocumentRegion sdRegion, IReporter reporter) {
+
+		if (sdRegion.isDeleted()) {
+			return;
+		}
+
+		// check start/end tag pairs
+		IDOMNode xmlNode = getXMLNode(sdRegion);
+
+		if (xmlNode == null) {
+			return;
+		}
+
+		boolean selfClosed = false;
+		String tagName = null;
+
+		/**
+		 * For tags that aren't meant to be EMPTY, make sure it's empty or has an end tag
+		 */
+		if (xmlNode.isContainer()) {
+			IStructuredDocumentRegion endRegion = xmlNode.getEndStructuredDocumentRegion();
+			if (endRegion == null) {
+				IStructuredDocumentRegion startRegion = xmlNode.getStartStructuredDocumentRegion();
+				if (startRegion != null && !startRegion.isDeleted() && DOMRegionContext.XML_TAG_OPEN.equals(startRegion.getFirstRegion().getType())) {
+					// analyze the tag (check self closing)
+					ITextRegionList regions = startRegion.getRegions();
+					ITextRegion r = null;
+					int start = sdRegion.getStart();
+					int length = sdRegion.getTextLength();
+					for (int i = 0; i < regions.size(); i++) {
+						r = regions.get(i);
+						if (r.getType() == DOMRegionContext.XML_TAG_NAME) {
+							tagName = sdRegion.getText(r);
+							start = sdRegion.getStartOffset(r);
+							length = r.getTextLength();
+						}
+						else if (r.getType() == DOMRegionContext.XML_EMPTY_TAG_CLOSE) {
+							selfClosed = true;
+						}
+					}
+
+
+					if (!selfClosed && (tagName != null)) {
+						Object[] args = {tagName};
+						String messageText = NLS.bind(XMLCoreMessages.Missing_end_tag_, args);
+
+						int lineNumber = getLineNumber(start);
+
+						LocalizedMessage message = new LocalizedMessage(getPluginPreference().getInt(XMLCorePreferenceNames.MISSING_END_TAG) , messageText);
+						message.setOffset(start);
+						message.setLength(length);
+						message.setLineNo(lineNumber);
+						Object[] additionalFixInfo = getStartEndFixInfo(xmlNode, tagName, r);
+	
+						getAnnotationMsg(reporter, ProblemIDsXML.MissingEndTag, message, additionalFixInfo,length);
+					}
+				}
+			}
+			else {
+				IStructuredDocumentRegion startRegion = xmlNode.getStartStructuredDocumentRegion();
+				if (startRegion == null || startRegion.isDeleted()) {
+					// analyze the tag (check self closing)
+					ITextRegionList regions = endRegion.getRegions();
+					ITextRegion r = null;
+					int start = sdRegion.getStart();
+					int length = sdRegion.getTextLength();
+					for (int i = 0; i < regions.size(); i++) {
+						r = regions.get(i);
+						if (r.getType() == DOMRegionContext.XML_TAG_NAME) {
+							tagName = sdRegion.getText(r);
+							start = sdRegion.getStartOffset(r);
+							length = r.getTextLength();
+						}
+					}
+
+					if (tagName != null) {
+						Object[] args = {tagName};
+						String messageText = NLS.bind(XMLCoreMessages.Missing_start_tag_, args);
+
+						int lineNumber = getLineNumber(start);
+
+						LocalizedMessage message = new LocalizedMessage(getPluginPreference().getInt(XMLCorePreferenceNames.MISSING_START_TAG), messageText);
+						message.setOffset(start);
+						message.setLength(length);
+						message.setLineNo(lineNumber);
+						Object[] additionalFixInfo = getStartEndFixInfo(xmlNode, tagName, r);
+												
+						getAnnotationMsg(reporter, ProblemIDsXML.MissingStartTag, message, additionalFixInfo,length);
+						
+					}
+				}
+			}
+
+		}
+		/*
+		 * Check for an end tag that has no start tag
+		 */
+		else {
+			IStructuredDocumentRegion startRegion = xmlNode.getStartStructuredDocumentRegion();
+			if (startRegion == null) {
+				IStructuredDocumentRegion endRegion = xmlNode.getEndStructuredDocumentRegion();
+				if (!endRegion.isDeleted()) {
+					// get name
+					ITextRegionList regions = endRegion.getRegions();
+					ITextRegion r = null;
+					for (int i = 0; i < regions.size(); i++) {
+						r = regions.get(i);
+						if (r.getType() == DOMRegionContext.XML_TAG_NAME) {
+							tagName = sdRegion.getText(r);
+						}
+					}
+
+					if (!selfClosed && (tagName != null)) {
+						String messageText = XMLCoreMessages.Indicate_no_grammar_specified_severities_error;
+
+						int start = sdRegion.getStart();
+						int lineNumber = getLineNumber(start);
+
+						// SEVERITY_STRUCTURE == IMessage.HIGH_SEVERITY
+						IMessage message = new LocalizedMessage(IMessage.HIGH_SEVERITY, messageText);
+						message.setOffset(start);
+						message.setLength(sdRegion.getTextLength());
+						message.setLineNo(lineNumber);
+
+						reporter.addMessage(this, message);
+					}
+				}
+			}
+		}
+	}
+
+	private Object[] getStartEndFixInfo(IDOMNode xmlNode, String tagName, ITextRegion r) {
+		// quick fix info
+		String tagClose = "/>"; //$NON-NLS-1$
+		int tagCloseOffset = xmlNode.getFirstStructuredDocumentRegion().getEndOffset();
+		if ((r != null) && (r.getType() == DOMRegionContext.XML_TAG_CLOSE)) {
+			tagClose = "/"; //$NON-NLS-1$
+			tagCloseOffset--;
+		}
+		IDOMNode firstChild = (IDOMNode) xmlNode.getFirstChild();
+		while ((firstChild != null) && (firstChild.getNodeType() == Node.TEXT_NODE)) {
+			firstChild = (IDOMNode) firstChild.getNextSibling();
+		}
+		int endOffset = xmlNode.getEndOffset(); 
+		int firstChildStartOffset = firstChild == null ? endOffset : firstChild.getStartOffset();
+		Object[] additionalFixInfo = {tagName, tagClose, new Integer(tagCloseOffset), new Integer(xmlNode.getFirstStructuredDocumentRegion().getEndOffset()), // startTagEndOffset
+					new Integer(firstChildStartOffset), // firstChildStartOffset
+					new Integer(endOffset)}; // endOffset
+		return additionalFixInfo;
+	}
+
+	private void checkStartingSpaceForPI(IStructuredDocumentRegion structuredDocumentRegion, IReporter reporter) {
+
+		if (structuredDocumentRegion.isDeleted()) {
+			return;
+		}
+
+		IStructuredDocumentRegion prev = structuredDocumentRegion.getPrevious();
+		if ((prev != null) && prev.getStartOffset() == 0) {
+			if (prev.getType() == DOMRegionContext.XML_CONTENT) {
+				String messageText = XMLCoreMessages.ReconcileStepForMarkup_5;
+				int start = prev.getStartOffset();
+				int length = prev.getLength();
+
+				LocalizedMessage message = new LocalizedMessage(getPluginPreference().getInt(XMLCorePreferenceNames.WHITESPACE_AT_START) , messageText);
+				message.setOffset(start);
+				message.setLength(length);
+				message.setLineNo(getLineNumber(start));
+
+			
+				getAnnotationMsg(reporter, ProblemIDsXML.SpacesBeforePI, message, null,length);
+				
+				// Position p = new Position(start, length);
+				//				
+				// ReconcileAnnotationKey key =
+				// createKey(structuredDocumentRegion, getScope());
+				// TemporaryAnnotation annotation = new TemporaryAnnotation(p,
+				// SEVERITY_SYNTAX_ERROR, message, key,
+				// ProblemIDsXML.SpacesBeforePI);
+				// results.add(annotation);
+			}
+		}
+	}
+
+	public int getScope() {
+		return PARTIAL;
+	}
+
+	private IDOMNode getXMLNode(IStructuredDocumentRegion sdRegion) {
+
+		if (sdRegion == null) {
+			return null;
+		}
+
+		IStructuredModel xModel = null;
+		IDOMNode xmlNode = null;
+		// get/release models should always be in a try/finally block
+		try {
+			xModel = StructuredModelManager.getModelManager().getExistingModelForRead(getDocument());
+			// xModel is sometime null, when closing editor, for example
+			if (xModel != null) {
+				xmlNode = (IDOMNode) xModel.getIndexedRegion(sdRegion.getStart());
+			}
+		}
+		finally {
+			if (xModel != null) {
+				xModel.releaseFromRead();
+			}
+		}
+		return xmlNode;
+	}
+
+	/**
+	 * Determines whether the IStructuredDocumentRegion is a XML "end tag"
+	 * since they're not allowed to have attribute ITextRegions
+	 * 
+	 * @param structuredDocumentRegion
+	 */
+	private boolean isEndTag(IStructuredDocumentRegion structuredDocumentRegion) {
+		if ((structuredDocumentRegion == null) || structuredDocumentRegion.isDeleted()) {
+			return false;
+		}
+		return structuredDocumentRegion.getFirstRegion().getType() == DOMRegionContext.XML_END_TAG_OPEN;
+	}
+
+	/**
+	 * Determines if the IStructuredDocumentRegion is an XML Processing
+	 * Instruction
+	 * 
+	 * @param structuredDocumentRegion
+	 * 
+	 */
+	private boolean isPI(IStructuredDocumentRegion structuredDocumentRegion) {
+		if ((structuredDocumentRegion == null) || structuredDocumentRegion.isDeleted()) {
+			return false;
+		}
+		return structuredDocumentRegion.getFirstRegion().getType() == DOMRegionContext.XML_PI_OPEN;
+	}
+
+	/**
+	 * Determines whether the IStructuredDocumentRegion is a XML "start tag"
+	 * since they need to be checked for proper XML attribute region sequences
+	 * 
+	 * @param structuredDocumentRegion
+	 * 
+	 */
+	private boolean isStartTag(IStructuredDocumentRegion structuredDocumentRegion) {
+		if ((structuredDocumentRegion == null) || structuredDocumentRegion.isDeleted()) {
+			return false;
+		}
+		return structuredDocumentRegion.getFirstRegion().getType() == DOMRegionContext.XML_TAG_OPEN;
+	}
+
+	// Because we check the "proper" closing separately from attribute
+	// sequencing, we need to know what's
+	// an appropriate close.
+	private boolean isTagCloseTextRegion(ITextRegion textRegion) {
+		return (textRegion.getType() == DOMRegionContext.XML_TAG_CLOSE) || (textRegion.getType() == DOMRegionContext.XML_EMPTY_TAG_CLOSE);
+	}
+
+	/**
+	 * Determines if the IStructuredDocumentRegion is XML Content
+	 * 
+	 * @param structuredDocumentRegion
+	 * 
+	 */
+	private boolean isXMLContent(IStructuredDocumentRegion structuredDocumentRegion) {
+		if ((structuredDocumentRegion == null) || structuredDocumentRegion.isDeleted()) {
+			return false;
+		}
+		return structuredDocumentRegion.getFirstRegion().getType() == DOMRegionContext.XML_CONTENT;
+	}
+
+	private IDocument getDocument() {
+		return fDocument;
+	}
+
+	public void connect(IDocument document) {
+		fDocument = document;
+	}
+
+	public void disconnect(IDocument document) {
+		fDocument = null;
+	}
+
+	public void validate(IStructuredDocumentRegion structuredDocumentRegion, IReporter reporter) {
+
+		if (structuredDocumentRegion == null) {
+			return;
+		}
+
+		if (isStartTag(structuredDocumentRegion)) {
+			// check for attributes without a value
+			checkForAttributeValue(structuredDocumentRegion, reporter);
+			// check if started tag is ended
+			checkStartEndTagPairs(structuredDocumentRegion, reporter);
+			// check empty tag <>
+			checkEmptyTag(structuredDocumentRegion, reporter);
+			// check that each attribute has quotes
+			checkQuotesForAttributeValues(structuredDocumentRegion, reporter);
+			// check that the closing '>' is there
+			checkClosingBracket(structuredDocumentRegion, reporter);
+		}
+		else if (isEndTag(structuredDocumentRegion)) {
+			// check if ending tag was started
+			checkStartEndTagPairs(structuredDocumentRegion, reporter);
+			// check for attributes in an end tag
+			checkAttributesInEndTag(structuredDocumentRegion, reporter);
+			// check that the closing '>' is there
+			checkClosingBracket(structuredDocumentRegion, reporter);
+		}
+		else if (isPI(structuredDocumentRegion)) {
+			// check validity of processing instruction
+			checkStartingSpaceForPI(structuredDocumentRegion, reporter);
+			checkNoNamespaceInPI(structuredDocumentRegion, reporter);
+		}
+		else if (isXMLContent(structuredDocumentRegion)) {
+			checkForSpaceBeforeName(structuredDocumentRegion, reporter);
+		}
+		else if (isXMLDoctypeDeclaration(structuredDocumentRegion)) {
+			checkDocumentTypeReferences(structuredDocumentRegion, reporter);
+		}
+	}
+
+	/**
+	 * @param structuredDocumentRegion
+	 * @param reporter
+	 */
+	private void checkDocumentTypeReferences(IStructuredDocumentRegion structuredDocumentRegion, IReporter reporter) {
+	}
+
+	/**
+	 * @param structuredDocumentRegion
+	 * @return
+	 */
+	private boolean isXMLDoctypeDeclaration(IStructuredDocumentRegion structuredDocumentRegion) {
+		if ((structuredDocumentRegion == null) || structuredDocumentRegion.isDeleted()) {
+			return false;
+		}
+		return structuredDocumentRegion.getFirstRegion().getType() == DOMRegionContext.XML_DECLARATION_OPEN && structuredDocumentRegion.getType().equals(DOMRegionContext.XML_DOCTYPE_DECLARATION);
+	}
+
+	public void cleanup(IReporter reporter) {
+		fDocument = null;
+	}
+
+	public void validate(IValidationContext helper, IReporter reporter) throws ValidationException {
+		String[] uris = helper.getURIs();
+		IWorkspaceRoot wsRoot = ResourcesPlugin.getWorkspace().getRoot();
+		if (uris.length > 0) {
+			IFile currentFile = null;
+
+			for (int i = 0; i < uris.length && !reporter.isCancelled(); i++) {
+				// might be called with just project path?
+				IPath path = new Path(uris[i]);
+				if (path.segmentCount() > 1) {
+					currentFile = wsRoot.getFile(path);
+					if (shouldValidate(currentFile, true)) {
+						validateV1File(currentFile, reporter);
+					}
+				}
+				else if (uris.length == 1) {
+					validateV1Project(helper, reporter);
+				}
+			}
+		}
+		else
+			validateV1Project(helper, reporter);
+	}
+	
+	private boolean shouldValidate(IResourceProxy proxy) {
+		if(proxy.getType() == IResource.FILE) {
+			String name = proxy.getName();
+			if(name.toLowerCase(Locale.US).endsWith(".xml")) { //$NON-NLS-1$
+				return true;
+			}
+		}
+		return shouldValidate(proxy.requestResource(), false);
+	}
+	
+	private boolean shouldValidate(IResource file, boolean checkExtension) {
+		if (file == null || !file.exists() || file.getType() != IResource.FILE)
+			return false;
+		if (checkExtension) {
+			String extension = file.getFileExtension();
+			if (extension != null && "xml".endsWith(extension.toLowerCase(Locale.US))) //$NON-NLS-1$
+				return true;
+		}
+
+		IContentDescription contentDescription = null;
+		try {
+			contentDescription = ((IFile) file).getContentDescription();
+			if (contentDescription != null) {
+				IContentType contentType = contentDescription.getContentType();
+				return contentDescription != null && contentType.isKindOf(getXMLContentType());
+			}
+		}
+		catch (CoreException e) {
+			Logger.logException(e);
+		}
+		return false;
+	}
+
+	/**
+	 * @param helper
+	 * @param reporter
+	 */
+	private void validateV1Project(IValidationContext helper, final IReporter reporter) {
+		// if uris[] length 0 -> validate() gets called for each project
+		if (helper instanceof IWorkbenchContext) {
+			IProject project = ((IWorkbenchContext) helper).getProject();
+			IResourceProxyVisitor visitor = new IResourceProxyVisitor() {
+				public boolean visit(IResourceProxy proxy) throws CoreException {
+					if (shouldValidate(proxy)) {
+						validateV1File((IFile) proxy.requestResource(), reporter);
+					}
+					return true;
+				}
+			};
+			try {
+				// collect all jsp files for the project
+				project.accept(visitor, IResource.DEPTH_INFINITE);
+			}
+			catch (CoreException e) {
+				Logger.logException(e);
+			}
+		}
+	}
+	
+
+	/**
+	 * @param currentFile
+	 * @param reporter
+	 */
+	private void validateV1File(IFile currentFile, IReporter reporter) {
+		Message message = new LocalizedMessage(IMessage.LOW_SEVERITY, currentFile.getFullPath().toString().substring(1));
+		reporter.displaySubtask(MarkupValidator.this, message);
+
+		IStructuredModel model = null;
+		try {
+			model = StructuredModelManager.getModelManager().getModelForRead(currentFile);
+			IStructuredDocument document = null;
+			if (model != null) {
+				document = model.getStructuredDocument();
+				connect(document);
+				IStructuredDocumentRegion validationRegion = document.getFirstStructuredDocumentRegion();
+				while (validationRegion != null) {
+					validate(validationRegion, reporter);
+					validationRegion = validationRegion.getNext();
+				}
+				disconnect(document);
+			}
+		}
+		catch (Exception e) {
+			Logger.logException(e);
+		}
+		finally {
+			if (model != null) {
+				model.releaseFromRead();
+			}
+		}
+	}
+
+	/**
+	 * @return
+	 */
+	private IContentType getXMLContentType() {
+		if (fRootContentType == null) {
+			fRootContentType = Platform.getContentTypeManager().getContentType("org.eclipse.core.runtime.xml"); //$NON-NLS-1$
+		}
+		return fRootContentType;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.validation.AbstractValidator#validate(org.eclipse.core.resources.IResource, int, org.eclipse.wst.validation.ValidationState, org.eclipse.core.runtime.IProgressMonitor)
+	 */
+	public ValidationResult validate(IResource resource, int kind, ValidationState state, IProgressMonitor monitor) {
+		if (resource.getType() != IResource.FILE)
+			return null;
+		ValidationResult result = new ValidationResult();
+		fReporter = result.getReporter(monitor);
+
+		validateV1File((IFile) resource, fReporter);
+		
+		return result;
+	}
+	
+	public IReporter validate(IResource resource, int kind, ValidationState state) {
+		validate(resource,kind,state,new NullProgressMonitor());
+		return fReporter;
+	}
+	private Preferences getPluginPreference(){
+		return XMLCorePlugin.getDefault().getPluginPreferences();
+	}
+
+	public void validate(IRegion dirtyRegion, IValidationContext helper, IReporter reporter) {
+		if (getDocument() == null) {
+			return;
+		}
+		if (!(getDocument() instanceof IStructuredDocument)) {
+			return;
+		}
+
+		// remove old messages
+		reporter.removeAllMessages(this);
+
+		IStructuredDocumentRegion[] regions = ((IStructuredDocument) fDocument).getStructuredDocumentRegions(dirtyRegion.getOffset(), dirtyRegion.getLength());
+		for (int i = 0; i < regions.length; i++) {
+			validate(regions[i], reporter);
+		}
+	}
+	
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/ProblemIDsXML.java b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/ProblemIDsXML.java
new file mode 100644
index 0000000..cf34e74
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/ProblemIDsXML.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 20010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.validation;
+
+public interface ProblemIDsXML {
+	int AttrsInEndTag = 3;
+	int AttrValueNotQuoted = 13;
+	int EmptyTag = 1;
+	int InvalidAttrValue = 11;
+	int MissingAttrValue = 4;
+	int MissingClosingBracket = 14;
+	int MissingEndTag = 2;
+	int MissingRequiredAttr = 12;
+	int MissingStartTag = 15;
+	int NamespaceInPI = 8;
+	int NoAttrValue = 5;
+	int SpacesBeforePI = 7;
+	int SpacesBeforeTagName = 6;
+	int Unclassified = 0;
+	int UnknownAttr = 10;
+	int UnknownElement = 9;
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/ValidatorHelper.java b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/ValidatorHelper.java
new file mode 100644
index 0000000..57cae08
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/ValidatorHelper.java
@@ -0,0 +1,361 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.xml.core.internal.validation;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.net.URL;
+import java.util.List;
+import java.util.Vector;
+
+import org.eclipse.wst.common.uriresolver.internal.provisional.URIResolver;
+import org.eclipse.wst.common.uriresolver.internal.provisional.URIResolverPlugin;
+import org.eclipse.wst.common.uriresolver.internal.util.URIHelper;
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.ext.LexicalHandler;
+
+import com.ibm.icu.util.StringTokenizer;
+
+/**
+ * A helper class for the XML validator.
+ * 
+ * @author Craig Salter, IBM
+ * @author Lawrence Mandel, IBM
+ */
+public class ValidatorHelper
+{                           
+  public List namespaceURIList = new Vector();
+  public boolean isGrammarEncountered = false;    
+  public boolean isDTDEncountered = false;
+  public boolean isNamespaceEncountered = false;
+  public String schemaLocationString = ""; //$NON-NLS-1$
+  public int numDTDElements = 0;
+
+  /**
+   * Constructor.
+   */
+  public ValidatorHelper()
+  {
+  }
+ 
+  /**
+   * Create an XML Reader.
+   * 
+   * @return An XML Reader if one can be created or null.
+   * @throws Exception
+   */
+  protected XMLReader createXMLReader(String uri) throws Exception
+  {     
+    XMLReader reader = null;
+    
+    reader = new org.apache.xerces.parsers.SAXParser();     
+    reader.setFeature("http://apache.org/xml/features/continue-after-fatal-error", false); //$NON-NLS-1$
+    reader.setFeature("http://xml.org/sax/features/namespace-prefixes", true); //$NON-NLS-1$
+    reader.setFeature("http://xml.org/sax/features/namespaces", false); //$NON-NLS-1$
+    reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); //$NON-NLS-1$
+    reader.setContentHandler(new MyContentHandler(uri));
+    reader.setErrorHandler(new InternalErrorHandler()); 
+
+    LexicalHandler lexicalHandler = new LexicalHandler()
+    {      
+      public void startDTD (String name, String publicId, String systemId)
+      {
+        isGrammarEncountered = true;   
+        isDTDEncountered = true;
+      }
+
+      public void endDTD() throws SAXException
+      {
+      }
+
+      public void startEntity(String name) throws SAXException
+      {
+      }
+
+      public void endEntity(String name) throws SAXException
+      {
+      }
+
+      public void startCDATA() throws SAXException
+      {
+      }
+
+      public void endCDATA() throws SAXException
+      {
+      }
+ 
+      public void comment (char ch[], int start, int length) throws SAXException
+      {
+      }
+    };
+    reader.setProperty("http://xml.org/sax/properties/lexical-handler", lexicalHandler); //$NON-NLS-1$
+    
+    return reader;
+  }  
+
+  /**
+   * An error handler to suppress error and warning information.
+   */
+  private class InternalErrorHandler implements org.xml.sax.ErrorHandler
+  {
+	public InternalErrorHandler()
+	{
+	  super();
+	}
+	
+    public void error(SAXParseException exception) throws SAXException
+    {
+    }
+
+    public void fatalError(SAXParseException exception) throws SAXException
+    {
+    }
+
+    public void warning(SAXParseException exception) throws SAXException
+    {
+    }
+  }
+
+ 
+  /**
+   * Figures out the information needed for validation.
+   * 
+   * @param uri The uri of the file to validate.
+   * @param uriResolver A helper to resolve locations.
+   */
+  public void computeValidationInformation(String uri, Reader characterStream, URIResolver uriResolver)
+  {
+    try
+    {
+      XMLReader reader = createXMLReader(uri);  
+      InputSource inputSource = new InputSource(uri);
+      inputSource.setCharacterStream(characterStream);
+      reader.parse(inputSource);
+    }
+    catch (Exception e)
+    {     
+      //System.out.println(e);
+    }
+  }
+  
+ 
+
+  /**
+   * Handle the content while parsing the file.
+   */
+  class MyContentHandler extends org.xml.sax.helpers.DefaultHandler
+  {      
+    /* (non-Javadoc)
+     * @see org.xml.sax.ErrorHandler#error(org.xml.sax.SAXParseException)
+     */
+    boolean isRootElement = true;
+    String baseURI;
+    
+    MyContentHandler(String uri)
+    {
+      this.baseURI = uri;  
+    }
+    
+    public void error(SAXParseException e) throws SAXException
+    {
+    }
+    /* (non-Javadoc)
+     * @see org.xml.sax.ErrorHandler#fatalError(org.xml.sax.SAXParseException)
+     */
+    public void fatalError(SAXParseException e) throws SAXException
+    {
+    }
+    /* (non-Javadoc)
+     * @see org.xml.sax.ErrorHandler#warning(org.xml.sax.SAXParseException)
+     */
+    public void warning(SAXParseException e) throws SAXException
+    {
+    }
+    public String getPrefix(String name)
+    {
+      String prefix = null;
+      int index = name.indexOf(":"); //$NON-NLS-1$
+      if (index != -1)
+      {
+        prefix = name.substring(0, index);
+      }
+      return prefix;
+    }    
+        
+    public String getUnprefixedName(String name)
+    {
+      int index = name.indexOf(":"); //$NON-NLS-1$
+      if (index != -1)
+      {
+        name = name.substring(index + 1);
+      }
+      return name;
+    }
+    
+    public String getPrefixedName(String prefix, String localName)
+    {
+      return prefix != null && prefix.length() > 0 ? prefix + ":" + localName : localName;      //$NON-NLS-1$
+    }
+
+    public void startElement(String namespaceURI, String localName, String rawName, Attributes atts)
+    {      
+      //String explicitLocation = null;
+      if (isRootElement)
+      {  
+        
+        isRootElement = false;  
+        int nAtts = atts.getLength();    
+        String schemaInstancePrefix = null;
+        for (int i =0; i < nAtts; i++)
+        {              
+          String attributeName = atts.getQName(i);       
+          if (attributeName.equals("xmlns") || attributeName.startsWith("xmlns:")) //$NON-NLS-1$ //$NON-NLS-2$
+          {                                         
+            isNamespaceEncountered = true;    
+            String value = atts.getValue(i);                 
+            if (value.startsWith("http://www.w3.org/") && value.endsWith("/XMLSchema-instance")) //$NON-NLS-1$ //$NON-NLS-2$
+            {
+              schemaInstancePrefix = attributeName.equals("xmlns") ? "" : getUnprefixedName(attributeName); //$NON-NLS-1$ //$NON-NLS-2$
+            }                   
+          }                 
+        }
+        
+        String prefix = getPrefix(rawName);
+        String rootElementNamespaceDeclarationName = (prefix != null && prefix.length() > 0) ? "xmlns:" + prefix : "xmlns"; //$NON-NLS-1$ //$NON-NLS-2$
+        String rootElementNamespace = rootElementNamespaceDeclarationName != null ? atts.getValue(rootElementNamespaceDeclarationName) : null;        
+        
+        String location = null;
+        
+        // first we use any 'xsi:schemaLocation' or 'xsi:noNamespaceSchemaLocation' attribute
+        // to determine a location
+        if (schemaInstancePrefix != null)
+        {                     
+          location = atts.getValue(getPrefixedName(schemaInstancePrefix, "noNamespaceSchemaLocation")); //$NON-NLS-1$
+          if (location == null)
+          {            
+        	String schemaLoc = atts.getValue(getPrefixedName(schemaInstancePrefix, "schemaLocation"));  //$NON-NLS-1$
+            location = getSchemaLocationForNamespace(schemaLoc, rootElementNamespace);
+          }  
+        }  
+        if (rootElementNamespace == null)
+        {
+          rootElementNamespace = "";
+        }
+        
+        location = URIResolverPlugin.createResolver().resolve(baseURI, rootElementNamespace, location);    
+        location = URIResolverPlugin.createResolver().resolvePhysicalLocation(baseURI, rootElementNamespace, location);
+        if (location != null)
+        {
+          location = URIHelper.addImpliedFileProtocol(location);
+        }
+        
+        schemaLocationString = location;
+        
+        if (location != null)
+        {  
+          InputStream is = null;
+          try
+          {
+            URL url = new URL(location);
+            is = url.openStream();
+            isGrammarEncountered = true;
+          }
+          catch(Exception e)
+          {
+        	// Do nothing.
+          }
+          finally
+          {
+        	if(is != null)
+        	{
+        	  try
+        	  {
+        	    is.close();
+        	  }
+        	  catch(Exception e)
+        	  {
+        		// Do nothing.
+        	  }
+        	}
+          }
+        }        
+      }
+    }     
+    /* (non-Javadoc)
+     * @see org.xml.sax.ext.DeclHandler#elementDecl(java.lang.String, java.lang.String)
+     */
+    public void elementDecl(String name, String model) 
+    {
+      numDTDElements++;
+    }
+    
+    // The xsiSchemaLocationValue is a list of namespace/location pairs that are separated by whitespace 
+    // this method walks the list of pairs looking for the specified namespace and returns the associated
+    // location.
+    //   
+    protected String getSchemaLocationForNamespace(String xsiSchemaLocationValue, String namespace)
+    {      
+      String result = null;
+      if (xsiSchemaLocationValue != null && namespace != null)
+      {
+        
+        StringTokenizer st = new StringTokenizer(xsiSchemaLocationValue);
+        while(st.hasMoreTokens())
+        {
+          if(st.nextToken().equals(namespace))
+          {
+            if(st.hasMoreTokens())
+            {
+              result = st.nextToken();
+            }
+          }
+          else
+          {
+            if(st.hasMoreTokens())
+            {
+              st.nextToken();
+            }
+          }
+        }
+      }
+      return result;
+    }         
+  }   
+       
+  
+  /**
+   * Replace all instances in the string of the old pattern with the new pattern.
+   * 
+   * @param string The string to replace the patterns in.
+   * @param oldPattern The old pattern to replace.
+   * @param newPattern The pattern used for replacement.
+   * @return The modified string with all occurrances of oldPattern replaced by new Pattern.
+   */
+  protected static String replace(String string, String oldPattern, String newPattern)
+  {     
+    int index = 0;
+    while (index != -1)
+    {
+      index = string.indexOf(oldPattern, index);
+      if (index != -1)
+      {
+        string = string.substring(0, index) + newPattern + string.substring(index + oldPattern.length());
+        index = index + oldPattern.length();
+      }
+    }
+    return string;
+  }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/XMLNestedValidatorContext.java b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/XMLNestedValidatorContext.java
new file mode 100644
index 0000000..29c5e7e
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/XMLNestedValidatorContext.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (c) 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.validation;
+
+
+import java.util.HashSet;
+
+import org.eclipse.wst.xml.core.internal.validation.core.NestedValidatorContext;
+
+
+/**
+ * XMLNestedValidatorContext is used to store state data needed during an XML
+ * validation session.
+ */
+public class XMLNestedValidatorContext extends NestedValidatorContext
+{
+  /**
+   * A set of inaccessible locations URIs (String).
+   */
+  private HashSet inaccessibleLocationURIs = new HashSet();
+
+  /**
+   * Determines if a location URI was marked as inaccessible.
+   * 
+   * @param locationURI
+   *          the location URI to test. Must not be null.
+   * @return true if a location URI was marked as inaccessible, false otherwise.
+   */
+  public boolean isURIMarkedInaccessible(String locationURI)
+  {
+    return locationURI != null && inaccessibleLocationURIs.contains(locationURI);
+  }
+
+  /**
+   * Marks the given location URI as inaccessible.
+   * 
+   * @param locationURI
+   *          the location URI to mark as inaccessible. Must not be null.
+   */
+  public void markURIInaccessible(String locationURI)
+  {
+    if (locationURI != null)
+    {
+      inaccessibleLocationURIs.add(locationURI);
+    }
+  }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/XMLValidationConfiguration.java b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/XMLValidationConfiguration.java
new file mode 100644
index 0000000..dd451551
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/XMLValidationConfiguration.java
@@ -0,0 +1,121 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2009 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
+ *     David Carver (STAR) - bug 297005 - Some static constants not made final.
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.validation;
+
+/**
+ * An XML validation configuration allows setting specific configuration
+ * information for a WTP XML validation run. Any features and properties
+ * set on this configuration should not be confused with those from
+ * parsers such as Xerces. (This object does not by default wrap features
+ * and properties from specific parsers.)
+ */
+public class XMLValidationConfiguration 
+{
+  /**
+   * @deprecated
+   */
+  public static final String WARN_NO_GRAMMAR = "WARN_NO_GRAMMAR"; //$NON-NLS-1$
+  public static final String INDICATE_NO_GRAMMAR = "INDICATE_NO_GRAMMAR"; //$NON-NLS-1$
+  public static final String USE_XINCLUDE = "USE_XINCLUDE"; //$NON-NLS-1$
+  public static final String HONOUR_ALL_SCHEMA_LOCATIONS = "HONOUR_ALL_SCHEMA_LOCATIONS"; //$NON-NLS-1$
+
+  private boolean warn_no_grammar_value = false;
+  private int indicate_no_grammar_value = 1;
+  private boolean use_xinclude = false;
+  private boolean honour_all_schema_locations_value = false;
+  
+  /**
+   * Set a feature of this configuration.
+   * 
+   * @param feature
+   * 		The feature to set.
+   * @param value
+   * 		The value to set for the feature.
+   * @throws 
+   * 		An exception is thrown if the feature is not recognized.
+   */
+  public void setFeature(String feature, boolean value) throws Exception
+  {
+	if(WARN_NO_GRAMMAR.equals(feature))
+	  warn_no_grammar_value = value;
+    else if(USE_XINCLUDE.equals(feature))
+      use_xinclude = value;
+    else if(HONOUR_ALL_SCHEMA_LOCATIONS.equals(feature))
+      honour_all_schema_locations_value = value;
+	else
+	  throw new Exception("Feature not recognized."); //$NON-NLS-1$
+	
+  }
+  
+  /**
+   * Set a feature of this configuration.
+   * 
+   * @param feature
+   * 		The feature to set.
+   * @param value
+   * 		The value to set for the feature.
+   * @throws 
+   * 		An exception is thrown if the feature is not recognized.
+   */
+  public void setFeature(String feature, int value) throws Exception
+  {
+	if(INDICATE_NO_GRAMMAR.equals(feature))
+	  indicate_no_grammar_value = value;
+	else
+	  throw new IllegalArgumentException("Feature not recognized."); //$NON-NLS-1$
+	
+  }
+  
+  
+  /**
+   * Get the value for a given feature. If the feature is not defined
+   * this method will throw an exception.
+   * 
+   * @param feature
+   * 		The feature for which to retrieve the value.
+   * @return
+   * 		The feature's value, true or false.
+   * @throws 
+   * 		An exception is thrown if the feature is not recognized.
+   */
+  public boolean getFeature(String feature) throws Exception
+  {
+	if(WARN_NO_GRAMMAR.equals(feature))
+	  return warn_no_grammar_value;
+	else if(USE_XINCLUDE.equals(feature))
+      return use_xinclude;
+    if(HONOUR_ALL_SCHEMA_LOCATIONS.equals(feature))
+      return honour_all_schema_locations_value;
+			
+	throw new Exception("Feature not recognized."); //$NON-NLS-1$
+  }
+
+  /**
+   * Get the value for a given feature. If the feature is not defined
+   * this method will throw an exception.
+   * 
+   * @param feature
+   * 		The feature for which to retrieve the value.
+   * @return
+   * 		The feature's value, true or false.
+   * @throws 
+   * 		An exception is thrown if the feature is not recognized.
+   */
+  public int getIntFeature(String feature) throws Exception
+  {
+	if(INDICATE_NO_GRAMMAR.equals(feature))
+	  return indicate_no_grammar_value;
+	
+	throw new IllegalArgumentException("Feature not recognized."); //$NON-NLS-1$
+  }
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/XMLValidationInfo.java b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/XMLValidationInfo.java
new file mode 100644
index 0000000..1113eb9
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/XMLValidationInfo.java
@@ -0,0 +1,199 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2009 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
+ *     David Carver - STAR - [205989] - [validation] validate XML after XInclude resolution
+ *******************************************************************************/
+
+package org.eclipse.wst.xml.core.internal.validation;
+
+import java.util.Stack;
+
+import org.apache.xerces.xni.XMLLocator;
+import org.eclipse.wst.xml.core.internal.XMLCorePlugin;
+import org.eclipse.wst.xml.core.internal.preferences.XMLCorePreferenceNames;
+import org.eclipse.wst.xml.core.internal.validation.core.ValidationInfo;
+import org.eclipse.wst.xml.core.internal.validation.errorcustomization.ErrorCustomizationManager;
+
+
+/**
+ * A validation information object specific to XML validators.
+ */
+public class XMLValidationInfo extends ValidationInfo implements XMLValidationReport
+{
+  protected boolean grammarEncountered = false;
+  protected boolean dtdEncountered = false;
+  protected boolean namespaceEncountered = false;
+  protected int elementDeclCount = 0;
+  protected String currentErrorKey;
+  protected Object messageArguments[] = null;
+  protected XMLLocator locator = null;
+  protected ErrorCustomizationManager errorCustomizationManager = null;
+  
+  /**
+   * A stack of start tag locations, used to move errors
+   * reported at the close tag to be reported at the start tag.
+   */
+  protected Stack startElementLocations = new Stack();
+  
+  /**
+   * Constructor.
+   * 
+   * @param uri The URI of the file this report describes.
+   */
+  public XMLValidationInfo(String uri)
+  {
+    super(uri);
+  }
+  
+  public boolean isGrammarEncountered()
+  {
+    return grammarEncountered;
+  }
+  
+  /**
+   * Set whether a grammar has been encountered or not.
+   * 
+   * @param grammarEncountered Set true if a grammar has been encountered, false otherwise.
+   */
+  public void setGrammarEncountered(boolean grammarEncountered)
+  {
+    this.grammarEncountered = grammarEncountered;
+  }
+  
+  public boolean isDTDWithoutElementDeclarationEncountered()
+  {
+    return dtdEncountered && elementDeclCount == 0;
+  }
+  
+  /**
+   * Set whether a DTD without an element declaration was encountered.
+   * 
+   * @param dtdWithoutElementDeclarationEncountered Set true if a DTD without an
+   *         element declaration was encountered, false otherwise.
+   */
+  public void setDTDEncountered(boolean dtdEncountered)
+  {
+    this.dtdEncountered = dtdEncountered;
+  }
+  
+  public boolean isNamespaceEncountered()
+  {
+    return namespaceEncountered;
+  }
+  
+  /**
+   * Set whether a namespace was encountered.
+   * 
+   * @param namespaceEncountered Set true if a namespace was encountered, false otherwise.
+   */
+  public void setNamespaceEncountered(boolean namespaceEncountered)
+  {
+    this.namespaceEncountered = namespaceEncountered;
+  }
+  
+  /**
+   * Increase the element declaration count for DTD elements by one.
+   */
+  public void increaseElementDeclarationCount()
+  {
+    this.elementDeclCount++;
+  }
+  
+  /**
+   * Set the number of DTD elements encountered.
+   * 
+   * @param count The number of DTD elements encountered.
+   */
+  public void setElementDeclarationCount(int count)
+  {
+  	elementDeclCount = count;
+  }
+  
+  /**
+   * Get the XML locator if one has been specified.
+   * 
+   * @return The XML locator if one has been specified or null.
+   */
+  public XMLLocator getXMLLocator()
+  {
+    return locator;
+  }
+  
+  /**
+   * Set the XMLLocator.
+   * 
+   * @param locator The XMLLocator to set.
+   */
+  public void setXMLLocator(XMLLocator locator)
+  {
+    this.locator = locator;
+  }
+  
+  /**
+   * Get the current error key.
+   * 
+   * @return Returns the currentErrorKey.
+   */
+  public String getCurrentErrorKey()
+  {
+    return currentErrorKey;
+  }
+  
+  /**
+   * Set the current error key.
+   * 
+   * @param currentErrorKey The currentErrorKey to set.
+   */
+  public void setCurrentErrorKey(String currentErrorKey)
+  {
+    this.currentErrorKey = currentErrorKey;
+  }
+
+public Object[] getMessageArguments() {
+	return messageArguments;
+}
+
+
+public void setMessageArguments(Object[] messageArguments) {
+	this.messageArguments = messageArguments;
+}
+
+  /**
+   * Get the start elements locations.
+   * 
+   * @return 
+   * 		A stack containing the start element locations.
+   */
+  protected Stack getStartElementLocations()
+  {
+    return startElementLocations;
+  }
+  
+  /**
+   * Get the error customization manager for this validation run.
+   * 
+   * @return
+   * 	The error customization manager for this validation run.
+   */
+  protected ErrorCustomizationManager getErrorCustomizationManager()
+  {
+	  if(errorCustomizationManager == null)
+	  {
+		  errorCustomizationManager = new ErrorCustomizationManager();
+	  }
+	  return errorCustomizationManager;
+  }
+  
+  /**
+   * @deprecated Use {@link XMLValidationConfiguration} instead.
+   */
+  public boolean isUseXInclude() {
+	  return XMLCorePlugin.getDefault().getPluginPreferences().getBoolean(XMLCorePreferenceNames.USE_XINCLUDE);
+  }
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/XMLValidationMessages.java b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/XMLValidationMessages.java
new file mode 100644
index 0000000..7cd08da
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/XMLValidationMessages.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.validation;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Strings used by XML Validation
+ */
+public class XMLValidationMessages extends NLS {
+	private static final String BUNDLE_NAME = "org.eclipse.wst.xml.core.internal.validation.xmlvalidation";//$NON-NLS-1$
+
+	public static String _UI_PROBLEMS_VALIDATING_UNKNOWN_HOST;
+	public static String _UI_PROBLEMS_VALIDATING_FILE_NOT_FOUND;
+	public static String _UI_PROBLEMS_CONNECTION_REFUSED;
+	public static String _UI_REF_FILE_ERROR_MESSAGE;
+	public static String _WARN_NO_GRAMMAR;
+
+	static {
+		// load message values from bundle file
+		NLS.initializeMessages(BUNDLE_NAME, XMLValidationMessages.class);
+	}
+
+	private XMLValidationMessages() {
+		// cannot create new instance
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/XMLValidationReport.java b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/XMLValidationReport.java
new file mode 100644
index 0000000..5a4f1f6
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/XMLValidationReport.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.xml.core.internal.validation;
+
+import org.eclipse.wst.xml.core.internal.validation.core.ValidationReport;
+
+/**
+ * An interface represention a validation report for XML validation.
+ * 
+ * @author Lawrence Mandel, IBM
+ */
+public interface XMLValidationReport extends ValidationReport
+{
+  
+  /**
+   * Returns whether a grammar was encountered during the validation.
+   * 
+   * @return True if a grammar was encountered, false otherwise.
+   */
+  public boolean isGrammarEncountered();
+  
+  /**
+   * Returns whether a namespace was encountered.
+   * 
+   * @return True if a namespace was encountered, false otherwise.
+   */
+  public boolean isNamespaceEncountered();
+  
+  /**
+   * Returns whether a DTD without element declarations was encountered.
+   * 
+   * @return True if a DTD without element declarations was encountered.
+   */
+  public boolean isDTDWithoutElementDeclarationEncountered();
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/XMLValidator.java b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/XMLValidator.java
new file mode 100644
index 0000000..58ef83b
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/XMLValidator.java
@@ -0,0 +1,925 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2011 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
+ *     David Carver - STAR - [205989] - [validation] validate XML after XInclude resolution
+ *******************************************************************************/
+
+package org.eclipse.wst.xml.core.internal.validation;
+
+import java.io.BufferedReader;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.StringReader;
+import java.net.ConnectException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.apache.xerces.impl.XMLErrorReporter;
+import org.apache.xerces.impl.msg.XMLMessageFormatter;
+import org.apache.xerces.parsers.XIncludeAwareParserConfiguration;
+import org.apache.xerces.xni.Augmentations;
+import org.apache.xerces.xni.NamespaceContext;
+import org.apache.xerces.xni.QName;
+import org.apache.xerces.xni.XMLAttributes;
+import org.apache.xerces.xni.XMLLocator;
+import org.apache.xerces.xni.XMLResourceIdentifier;
+import org.apache.xerces.xni.XNIException;
+import org.apache.xerces.xni.parser.XMLEntityResolver;
+import org.apache.xerces.xni.parser.XMLInputSource;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.URIUtil;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.wst.common.uriresolver.internal.provisional.URIResolver;
+import org.eclipse.wst.common.uriresolver.internal.util.URIHelper;
+import org.eclipse.wst.validation.ValidationResult;
+import org.eclipse.wst.validation.internal.ValOperation;
+import org.eclipse.wst.validation.internal.operations.LocalizedMessage;
+import org.eclipse.wst.validation.internal.provisional.core.IReporter;
+import org.eclipse.wst.xml.core.internal.Logger;
+import org.eclipse.wst.xml.core.internal.XMLCorePlugin;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.IExternalSchemaLocationProvider;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelqueryimpl.ExternalSchemaLocationProviderRegistry;
+import org.eclipse.wst.xml.core.internal.preferences.XMLCorePreferenceNames;
+import org.eclipse.wst.xml.core.internal.validation.core.LazyURLInputStream;
+import org.eclipse.wst.xml.core.internal.validation.core.NestedValidatorContext;
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.ext.DeclHandler;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * This class performs validation using a xerces sax parser.  
+ * Here's a quick overview of the details : 
+ *   - an ErrorHandler is used to collect errors into a list (so they may be displayed by the UI)
+ *   - an EntityResolver is used along with the xerces "external-schemaLocation" property to implement XML Catalog support
+ */
+public class XMLValidator
+{
+  protected URIResolver uriResolver = null;
+  protected Hashtable ingoredErrorKeyTable = new Hashtable();
+  protected Set adjustLocationErrorKeySet = new TreeSet();
+
+  protected static final String IGNORE_ALWAYS = "IGNORE_ALWAYS"; //$NON-NLS-1$
+  protected static final String IGNORE_IF_DTD_WITHOUT_ELEMENT_DECL = "IGNORE_IF_DTD_WITHOUT_ELEMENT_DECL"; //$NON-NLS-1$
+  protected static final String PREMATURE_EOF = "PrematureEOF"; //$NON-NLS-1$
+  protected static final String ROOT_ELEMENT_TYPE_MUST_MATCH_DOCTYPEDECL = "RootElementTypeMustMatchDoctypedecl"; //$NON-NLS-1$
+  protected static final String MSG_ELEMENT_NOT_DECLARED = "MSG_ELEMENT_NOT_DECLARED"; //$NON-NLS-1$
+  
+  // WTP XML validator specific key.
+  protected static final String NO_GRAMMAR_FOUND = "NO_GRAMMAR_FOUND"; //$NON-NLS-1$
+  
+  private static final String FILE_NOT_FOUND_KEY = "FILE_NOT_FOUND"; //$NON-NLS-1$
+   
+  private MarkupValidator val = new MarkupValidator();
+  
+  private final String ANNOTATIONMSG = AnnotationMsg.class.getName();
+
+  private final static boolean _trace = Boolean.valueOf(Platform.getDebugOption("org.eclipse.wst.xml.core/externalSchemaLocation")).booleanValue(); //$NON-NLS-1$
+  /**
+   * Constructor.
+   */
+  public XMLValidator()
+  {                          
+    // Here we add some error keys that we need to filter out when we're validation 
+    // against a DTD without any element declarations.       
+    ingoredErrorKeyTable.put(PREMATURE_EOF, IGNORE_ALWAYS);
+    ingoredErrorKeyTable.put(ROOT_ELEMENT_TYPE_MUST_MATCH_DOCTYPEDECL, IGNORE_IF_DTD_WITHOUT_ELEMENT_DECL);
+    ingoredErrorKeyTable.put(MSG_ELEMENT_NOT_DECLARED, IGNORE_IF_DTD_WITHOUT_ELEMENT_DECL);
+    
+    // Here we add some error keys that we need to adjust the location information for.
+    // The location information will be adjusted to place the message on the line of the starting
+    // element instead of on the line of the closing element.
+    adjustLocationErrorKeySet.add("MSG_CONTENT_INVALID"); //$NON-NLS-1$
+    adjustLocationErrorKeySet.add("MSG_CONTENT_INCOMPLETE"); //$NON-NLS-1$
+    adjustLocationErrorKeySet.add("cvc-complex-type.2.4.b"); //$NON-NLS-1$
+    adjustLocationErrorKeySet.add("cvc-complex-type.2.3"); //$NON-NLS-1$
+  }
+
+  /**
+   * Set the URI Resolver to use.
+   * 
+   * @param uriResolver The URI Resolver to use.
+   */
+  public void setURIResolver(URIResolver uriResolver)
+  {
+    this.uriResolver = uriResolver;
+    //entityResolver = new MyEntityResolver(uriResolver);
+  }
+
+ 
+  /**
+   * Create an XML Reader.
+   * 
+   * @return The newly created XML reader or null if unsuccessful.
+   * @throws Exception
+   */
+  protected XMLReader createXMLReader(final XMLValidationInfo valinfo, XMLEntityResolver entityResolver) throws Exception
+  {     
+    XMLReader reader = null;
+    // move to Xerces-2... add the contextClassLoader stuff
+    ClassLoader prevClassLoader = Thread.currentThread().getContextClassLoader();
+    try
+    {
+      Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
+      MyStandardParserConfiguration configuration = new MyStandardParserConfiguration(valinfo);
+      reader = new org.apache.xerces.parsers.SAXParser(configuration)
+      {
+    	private XMLLocator locator = null;
+    	
+        /* (non-Javadoc)
+         * @see org.apache.xerces.parsers.AbstractSAXParser#startDocument(org.apache.xerces.xni.XMLLocator, java.lang.String, org.apache.xerces.xni.NamespaceContext, org.apache.xerces.xni.Augmentations)
+         */
+        public void startDocument(org.apache.xerces.xni.XMLLocator theLocator, java.lang.String encoding, NamespaceContext nscontext, org.apache.xerces.xni.Augmentations augs) 
+        {
+          locator = theLocator;
+          valinfo.setXMLLocator(theLocator);
+          super.startDocument(theLocator, encoding, nscontext, augs); 
+        }
+
+        /* (non-Javadoc)
+         * @see org.apache.xerces.parsers.AbstractSAXParser#startElement(org.apache.xerces.xni.QName, org.apache.xerces.xni.XMLAttributes, org.apache.xerces.xni.Augmentations)
+         */
+        public void startElement(QName arg0, XMLAttributes arg1, Augmentations arg2) throws XNIException 
+        {
+          valinfo.getStartElementLocations().push(new LocationCoordinate(locator.getLineNumber(), locator.getColumnNumber()));
+		  super.startElement(arg0, arg1, arg2);
+		}
+        
+		/* (non-Javadoc)
+		 * @see org.apache.xerces.parsers.AbstractSAXParser#endElement(org.apache.xerces.xni.QName, org.apache.xerces.xni.Augmentations)
+		 */
+		public void endElement(QName arg0, Augmentations arg1) throws XNIException {
+			super.endElement(arg0, arg1);
+			valinfo.getStartElementLocations().pop();
+		}
+      };
+
+      reader.setFeature("http://apache.org/xml/features/continue-after-fatal-error", false); //$NON-NLS-1$
+      reader.setFeature("http://xml.org/sax/features/namespace-prefixes", valinfo.isNamespaceEncountered()); //$NON-NLS-1$
+      reader.setFeature("http://xml.org/sax/features/namespaces", valinfo.isNamespaceEncountered());               //$NON-NLS-1$
+     
+      reader.setContentHandler(new DefaultHandler()
+      {
+        public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
+          valinfo.getErrorCustomizationManager().startElement(uri, localName);                    
+        }
+        
+        public void endElement(String uri, String localName, String qName) throws SAXException {
+          valinfo.getErrorCustomizationManager().endElement(uri, localName);
+        }
+      });      
+      
+      // MH make sure validation works even when a customer entityResolver is note set (i.e. via setURIResolver())
+      if (entityResolver != null)
+      {  
+        reader.setProperty("http://apache.org/xml/properties/internal/entity-resolver", entityResolver); //$NON-NLS-1$
+      }  
+      reader.setProperty("http://xml.org/sax/properties/declaration-handler", new MyDeclHandler());      //$NON-NLS-1$
+    } 
+    catch(Exception e)
+    { 
+      Logger.logException(e);
+      //e.printStackTrace();
+    }
+    finally
+    {
+      Thread.currentThread().setContextClassLoader(prevClassLoader);
+    }
+    return reader;
+  }  
+
+  /**
+   * Validate the file located at the given URI.
+   * 
+   * @param uri The URI of the file to validate.
+   * @return Returns an XML validation report.
+   */
+  public XMLValidationReport validate(String uri)
+  {
+    return validate(uri, null, new XMLValidationConfiguration());  
+  }
+
+  final String createStringForInputStream(InputStream inputStream)
+  {
+    // Here we are reading the file and storing to a stringbuffer.
+    StringBuffer fileString = new StringBuffer();
+    try
+    {
+      InputStreamReader inputReader = new InputStreamReader(inputStream, "UTF-8"); //$NON-NLS-1$
+      BufferedReader reader = new BufferedReader(inputReader);
+      char[] chars = new char[1024];
+      int numberRead = reader.read(chars);
+      while (numberRead != -1)
+      {
+        fileString.append(chars, 0, numberRead);
+        numberRead = reader.read(chars);
+      }
+    }
+    catch (Exception e)
+    {
+      //TODO: log error message
+      //e.printStackTrace();
+    }
+    return fileString.toString();
+  }
+  /**
+   * Validate the inputStream
+   * 
+   * @param uri The URI of the file to validate.
+   * @param the inputStream of the file to validate
+   * @return Returns an XML validation report.
+   */
+  public XMLValidationReport validate(String uri, InputStream inputStream)
+  {
+	return validate(uri, inputStream, new XMLValidationConfiguration());
+  }
+  /**
+   * Validate the inputStream
+   * 
+   * @param uri 
+   * 		The URI of the file to validate.
+   * @param inputstream
+   * 		The inputStream of the file to validate
+   * @param configuration
+   * 		A configuration for this validation session.
+   * @return 
+   * 		Returns an XML validation report.
+   */
+  public XMLValidationReport validate(String uri, InputStream inputStream, XMLValidationConfiguration configuration)
+  {
+    return validate(uri, inputStream, configuration, null);  
+  }
+ 
+  /**
+   * Validate the inputStream
+   * 
+   * @param uri 
+   *    The URI of the file to validate.
+   * @param inputstream
+   *    The inputStream of the file to validate
+   * @param configuration
+   *    A configuration for this validation session.
+   * @param result
+   *    The validation result
+   * @return 
+   *    Returns an XML validation report.
+   */
+  public XMLValidationReport validate(String uri, InputStream inputStream, XMLValidationConfiguration configuration, ValidationResult result)
+  {
+	  return validate(uri, inputStream, configuration, null, null);
+  }
+  
+  /**
+   * Validate the inputStream
+   * 
+   * @param uri 
+   *    The URI of the file to validate.
+   * @param inputstream
+   *    The inputStream of the file to validate
+   * @param configuration
+   *    A configuration for this validation session.
+   * @param result
+   *    The validation result
+   * @param context
+   *    The validation context   
+   * @return 
+   *    Returns an XML validation report.
+   */
+  public XMLValidationReport validate(String uri, InputStream inputStream, XMLValidationConfiguration configuration, ValidationResult result, NestedValidatorContext context)
+  {
+    String grammarFile = ""; //$NON-NLS-1$
+    Reader reader1 = null; // Used for the preparse.
+    Reader reader2 = null; // Used for validation parse.
+    
+    if (inputStream != null)
+    {  
+      String string = createStringForInputStream(inputStream);
+      reader1 = new StringReader(string);
+      reader2 = new StringReader(string);
+    } 
+        
+    XMLValidationInfo valinfo = new XMLValidationInfo(uri);
+    MyEntityResolver entityResolver = new MyEntityResolver(uriResolver, context); 
+    ValidatorHelper helper = new ValidatorHelper(); 
+    try
+    {  
+        helper.computeValidationInformation(uri, reader1, uriResolver);
+        valinfo.setDTDEncountered(helper.isDTDEncountered);
+        valinfo.setElementDeclarationCount(helper.numDTDElements);
+        valinfo.setNamespaceEncountered(helper.isNamespaceEncountered);
+        valinfo.setGrammarEncountered(helper.isGrammarEncountered);
+        
+        XMLReader reader = createXMLReader(valinfo, entityResolver);
+        // Set the configuration option
+        if (configuration.getFeature(XMLValidationConfiguration.HONOUR_ALL_SCHEMA_LOCATIONS))
+        {
+            reader.setFeature("http://apache.org/xml/features/honour-all-schemaLocations", true); //$NON-NLS-1$
+        }
+        if (configuration.getFeature(XMLValidationConfiguration.USE_XINCLUDE))
+        {
+          reader.setFeature("http://apache.org/xml/features/xinclude", true); //$NON-NLS-1$      
+        }
+
+        // Support external schema locations
+        boolean isGrammarEncountered = helper.isGrammarEncountered;
+        if (!isGrammarEncountered) {
+        	isGrammarEncountered = checkExternalSchemas(reader, valinfo.getFileURI());
+        }
+        reader.setFeature("http://xml.org/sax/features/validation", isGrammarEncountered);  //$NON-NLS-1$
+        reader.setFeature("http://apache.org/xml/features/validation/schema", isGrammarEncountered); //$NON-NLS-1$
+
+        XMLErrorHandler errorhandler = new XMLErrorHandler(valinfo);
+        reader.setErrorHandler(errorhandler);
+        
+        InputSource inputSource = new InputSource(uri);
+        inputSource.setCharacterStream(reader2);
+        reader.parse(inputSource);   
+        if(configuration.getIntFeature(XMLValidationConfiguration.INDICATE_NO_GRAMMAR) > 0 && 
+        		valinfo.isValid() && !isGrammarEncountered)
+        {
+          if(configuration.getIntFeature(XMLValidationConfiguration.INDICATE_NO_GRAMMAR) == 1)
+            valinfo.addWarning(XMLValidationMessages._WARN_NO_GRAMMAR, 1, 0, uri, NO_GRAMMAR_FOUND, null);
+          else // 2
+              valinfo.addError(XMLValidationMessages._WARN_NO_GRAMMAR, 1, 0, uri, NO_GRAMMAR_FOUND, null);
+        }
+
+        if (helper.isDTDEncountered)
+          grammarFile = entityResolver.getLocation();
+        else
+          grammarFile = helper.schemaLocationString;
+    }
+    catch (SAXParseException saxParseException)
+    {
+      // These errors are caught by the error handler.
+      //addValidationMessage(valinfo, saxParseException);
+    }                 
+    catch (IOException ioException)
+    {
+      addValidationMessage(valinfo, ioException);
+    }                 
+    catch (Exception exception)
+    {  
+    	Logger.logException(exception.getLocalizedMessage(), exception);
+    }
+
+    // Now set up the dependencies
+    // Wrap with try catch so that if something wrong happens, validation can
+    // still proceed as before
+    if (result != null)
+    {
+      try
+      {
+        IResource resource = getWorkspaceFileFromLocation(grammarFile);
+        ArrayList resources = new ArrayList();
+        if (resource != null)
+          resources.add(resource);
+        result.setDependsOn((IResource [])resources.toArray(new IResource [0]));
+      }
+      catch (Exception e)
+      {
+        Logger.logException(e.getLocalizedMessage(), e);
+      }
+    }
+
+    if ( XMLCorePlugin.getDefault().getPluginPreferences().getBoolean(XMLCorePreferenceNames.MARKUP_VALIDATION)){
+	    IReporter reporter = executeMarkupValidator(uri);
+	    if (reporter != null){
+		    List msgList = reporter.getMessages();
+		    for (int i = 0;i < msgList.size();i++){
+		    	LocalizedMessage msg = (LocalizedMessage)msgList.get(i);
+		    	if (msg.getSeverity() == 2)
+		    		valinfo.addError(msg.getLocalizedMessage(), msg.getLineNumber(), msg.getOffset(),valinfo.getFileURI(),"null",getMsgArguments(msg) ); //$NON-NLS-1$
+		    	else if (msg.getSeverity() == 1)
+		    		valinfo.addWarning(msg.getLocalizedMessage(), msg.getLineNumber(), msg.getOffset(),valinfo.getFileURI(),"null", getMsgArguments(msg)); //$NON-NLS-1$
+		    }
+	    }
+    }
+    
+    return valinfo;
+       
+  }
+
+	private boolean checkExternalSchemas(XMLReader reader, String fileURI) throws Exception {
+		boolean isGrammarEncountered = false;
+		final StringBuffer schemaLocation = new StringBuffer();
+		String noNamespaceSchemaLocation = null;
+		// Check the schema provider extension point
+		IExternalSchemaLocationProvider[] providers = ExternalSchemaLocationProviderRegistry.getInstance().getProviders();
+		for (int i = 0; i < providers.length; i++) {
+			URI uri = null;
+			try {
+				uri = URIUtil.fromString(fileURI);
+			}
+			catch (URISyntaxException e) {
+				Logger.logException(e.getLocalizedMessage(), e);
+			}
+			if (uri != null) {
+				long time = _trace ? System.currentTimeMillis(): 0;
+				final Map locations = providers[i].getExternalSchemaLocation(uri);
+				if (_trace) {
+					  long diff = System.currentTimeMillis() - time;
+					  if (diff > 250)
+						  Logger.log(Logger.INFO, "Schema location provider took [" + diff + "ms] for URI [" + fileURI + "]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+				  }
+				if (locations != null && !locations.isEmpty()) {
+					Object path = locations.get(IExternalSchemaLocationProvider.SCHEMA_LOCATION);
+					if (path instanceof String) {
+						if (schemaLocation.length() > 0) {
+							schemaLocation.append(' ');
+						}
+						schemaLocation.append(path);
+					}
+					path = locations.get(IExternalSchemaLocationProvider.NO_NAMESPACE_SCHEMA_LOCATION);
+					if (path instanceof String) {
+						noNamespaceSchemaLocation = (String)path;
+					}
+				}
+			}
+		}
+
+		if (schemaLocation.length() > 0) {
+			reader.setProperty(IExternalSchemaLocationProvider.SCHEMA_LOCATION, schemaLocation.toString());
+			isGrammarEncountered = true;
+		}
+		if (noNamespaceSchemaLocation != null) {
+			reader.setProperty(IExternalSchemaLocationProvider.NO_NAMESPACE_SCHEMA_LOCATION, noNamespaceSchemaLocation);
+			isGrammarEncountered = true;
+		}
+		return isGrammarEncountered;
+	}
+ 
+  private Object[] getMsgArguments(LocalizedMessage msg){
+	  Object obj = msg.getAttribute(ANNOTATIONMSG);
+	  return new Object[]{obj};
+  }
+ 
+
+	private IReporter executeMarkupValidator(String uri){
+		Path path = new Path(uri);
+		String fileProtocol = "file://"; //$NON-NLS-1$
+		int index = uri.indexOf(fileProtocol);
+		
+		IFile resource = null;
+		if (index == 0){
+			String transformedUri = uri.substring(fileProtocol.length());
+			Path transformedPath = new Path(transformedUri);
+			resource = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(transformedPath);
+		}
+		else {
+			resource = ResourcesPlugin.getWorkspace().getRoot().getFile(path);
+			
+		}
+		IReporter reporter = null;
+		if (resource != null){
+		    reporter = val.validate(resource, 0, new ValOperation().getState()) ;
+		}
+		return reporter;
+	}
+  
+  /**
+   * Add a validation message to the specified list.
+   * 
+   * @param valinfo The validation info object to add the error to.
+   * @param exception The exception that contains the validation information.
+   */
+  protected void addValidationMessage(XMLValidationInfo valinfo, IOException exception)
+  { 
+    String validationMessageStr = exception.getMessage();
+	Throwable cause = exception.getCause() != null ? exception.getCause() : exception;
+	while(validationMessageStr == null && cause != null){
+		String localizedMessage = cause.getLocalizedMessage();
+	    cause = cause.getCause();
+	    if(cause == null && localizedMessage != null )
+	    {
+	      validationMessageStr = localizedMessage;
+	    }
+	}
+	
+	if (validationMessageStr != null)
+    {
+      if (cause instanceof FileNotFoundException)
+      {
+        validationMessageStr = NLS.bind(XMLValidationMessages._UI_PROBLEMS_VALIDATING_FILE_NOT_FOUND, new Object [] { validationMessageStr });
+      }
+      else if (cause instanceof UnknownHostException)
+      {
+    	validationMessageStr = NLS.bind(XMLValidationMessages._UI_PROBLEMS_VALIDATING_UNKNOWN_HOST, new Object [] { validationMessageStr });
+      }
+      else if(cause instanceof ConnectException)
+      {
+    	validationMessageStr = XMLValidationMessages._UI_PROBLEMS_CONNECTION_REFUSED;
+      }
+    }
+
+    if (validationMessageStr != null)
+    {
+      XMLLocator locator = valinfo.getXMLLocator();
+      valinfo.addWarning(validationMessageStr, locator != null ? locator.getLineNumber() : 1, locator != null ? locator.getColumnNumber() : 0, valinfo.getFileURI(), FILE_NOT_FOUND_KEY, null);
+    }
+  }
+                                                                    
+  /**
+   * Add a validation message to the specified list.
+   * 
+   * @param valinfo The validation info object to add the error to.
+   * @param exception The exception that contains the validation information.
+   */
+  protected void addValidationMessage(XMLValidationInfo valinfo, SAXParseException exception)
+  { 
+    if (exception.getMessage() != null)
+    { 
+      valinfo.addError(exception.getLocalizedMessage(), exception.getLineNumber(), exception.getColumnNumber(), exception.getSystemId());
+    }
+  }
+
+  
+  /**
+   * A custom entity resolver that uses the URI resolver specified to resolve entities.
+   */
+  protected class MyEntityResolver implements XMLEntityResolver 
+  {
+    private URIResolver uriResolver;
+    private String resolvedDTDLocation;
+    private NestedValidatorContext context;
+   
+    /**
+     * Constructor.
+     * 
+     * @param uriResolver The URI resolver to use with this entity resolver.
+     * @param context The XML validator context.
+     */
+    public MyEntityResolver(URIResolver uriResolver, NestedValidatorContext context)
+    {
+      this.uriResolver = uriResolver;
+      this.context = context;
+    }
+    
+    /* (non-Javadoc)
+     * @see org.apache.xerces.xni.parser.XMLEntityResolver#resolveEntity(org.apache.xerces.xni.XMLResourceIdentifier)
+     */
+    public XMLInputSource resolveEntity(XMLResourceIdentifier rid) throws XNIException, IOException
+    {
+        XMLInputSource inputSource = _internalResolveEntity(uriResolver, rid, context);
+        if (inputSource != null)
+        {
+          resolvedDTDLocation = inputSource.getSystemId();
+        }
+        return inputSource;
+    }
+   
+    public String getLocation()
+    {
+      return resolvedDTDLocation;
+    }
+  }
+  
+  // cs : I've refactored the common SAX based resolution code into this method for use by other validators 
+  // (i.e. XML Schema, WSDL etc).   The other approach is maintain a copy for each validator that has
+  // identical code.  In any case we should strive to ensure that the validators perform resolution consistently. 
+  public static XMLInputSource _internalResolveEntity(URIResolver uriResolver, XMLResourceIdentifier rid) throws  IOException
+  {
+    return _internalResolveEntity(uriResolver, rid, null);
+  }
+  
+  public static XMLInputSource _internalResolveEntity(URIResolver uriResolver, XMLResourceIdentifier rid, NestedValidatorContext context) throws  IOException
+  {
+    XMLInputSource is = null;
+    
+    if (uriResolver != null)
+    {         
+      String id = rid.getPublicId();
+      if(id == null)
+      {
+        id = rid.getNamespace();
+      }
+      
+      String location = null;
+      if (id != null || rid.getLiteralSystemId() != null)
+      {  
+        location = uriResolver.resolve(rid.getBaseSystemId(), id, rid.getLiteralSystemId());
+      }  
+      
+      if (location != null)
+      {                     
+        String physical = uriResolver.resolvePhysicalLocation(rid.getBaseSystemId(), id, location);
+
+        // if physical is already a known bad uri, just go ahead and throw an exception
+        if (context instanceof XMLNestedValidatorContext)
+        {
+          XMLNestedValidatorContext xmlContext = ((XMLNestedValidatorContext)context);
+
+          if (xmlContext.isURIMarkedInaccessible(physical))
+          {
+        	 throw new FileNotFoundException(physical);
+          }
+        }
+        
+        is = new XMLInputSource(rid.getPublicId(), location, location);
+        
+        // This block checks that the file exists. If it doesn't we need to throw
+        // an exception so Xerces will report an error. note: This may not be
+        // necessary with all versions of Xerces but has specifically been 
+        // experienced with the version included in IBM's 1.4.2 JDK.
+        InputStream isTemp = null;
+        try
+        {
+          isTemp = new URL(physical).openStream();
+        }
+        catch (IOException e)
+        {
+          // physical was a bad url, so cache it so we know next time
+          if (context instanceof XMLNestedValidatorContext)
+          {
+            XMLNestedValidatorContext xmlContext = ((XMLNestedValidatorContext)context);
+            xmlContext.markURIInaccessible(physical);
+          }
+          throw e;
+        }
+        finally
+        {
+          if(isTemp != null)
+          {
+            isTemp.close();
+          }
+        }
+        is.setByteStream(new LazyURLInputStream(physical));      
+      }
+    }
+    return is;    
+  }      
+  
+  /**
+   * An error handler to catch errors encountered while parsing the XML document.
+   */
+  protected class XMLErrorHandler implements org.xml.sax.ErrorHandler
+  {
+
+    private final int ERROR = 0;
+    private final int WARNING = 1;
+    private XMLValidationInfo valinfo;
+    
+    /**
+     * Constructor.
+     * 
+     * @param valinfo The XML validation info object that will hold the validation messages.
+     */
+    public XMLErrorHandler(XMLValidationInfo valinfo)
+    {
+      this.valinfo = valinfo;
+    }
+
+    /**
+     * Add a validation message with the given severity.
+     * 
+     * @param exception The exception that contains the message.
+     * @param severity The severity of the message.
+     */
+    
+    protected void addValidationMessage(SAXParseException exception, int severity)
+    {
+      if(exception.getSystemId() != null)
+      {       	
+    	int lineNumber = exception.getLineNumber();
+    	int columnNumber = exception.getColumnNumber();
+    	
+    	// For the following three errors the line number will be modified to use that of the start
+    	// tag instead of the end tag. Unless its a self ending tag and in that case the startElementLocations will be empty
+    	String currentErrorKey = valinfo.currentErrorKey;
+    	if (currentErrorKey != null && adjustLocationErrorKeySet.contains(currentErrorKey) && valinfo.getStartElementLocations().size() > 0)  
+    	{
+    	  LocationCoordinate adjustedCoordinates = (LocationCoordinate)valinfo.getStartElementLocations().peek();
+    	  lineNumber = adjustedCoordinates.getLineNumber();
+    	  columnNumber = adjustedCoordinates.getColumnNumner();
+    	}
+    	
+        if(severity == WARNING)
+        {
+          valinfo.addWarning(exception.getLocalizedMessage(), lineNumber, columnNumber, exception.getSystemId());
+        }
+        else
+        {
+          valinfo.addError(exception.getLocalizedMessage(), lineNumber, columnNumber, exception.getSystemId(), valinfo.getCurrentErrorKey(), valinfo.getMessageArguments());
+        }
+      }
+    }
+
+    /* (non-Javadoc)
+     * @see org.xml.sax.ErrorHandler#error(org.xml.sax.SAXParseException)
+     */
+    public void error(SAXParseException exception) throws SAXException
+    {
+      addValidationMessage(exception, ERROR);
+    }
+
+    /* (non-Javadoc)
+     * @see org.xml.sax.ErrorHandler#fatalError(org.xml.sax.SAXParseException)
+     */
+    public void fatalError(SAXParseException exception) throws SAXException
+    {
+      addValidationMessage(exception, ERROR);
+    }
+
+    /* (non-Javadoc)
+     * @see org.xml.sax.ErrorHandler#warning(org.xml.sax.SAXParseException)
+     */
+    public void warning(SAXParseException exception) throws SAXException
+    {
+      addValidationMessage(exception, WARNING);
+    }
+  }
+                                                                          
+  /** 
+   * This class is used to count the elementDecls that are encountered in a DTD.
+   */
+  protected class MyDeclHandler implements DeclHandler 
+  {
+    
+    /**
+     * Constructor.
+     * 
+     * @param valinfo The XMLValidationInfo object that will count the declarations.
+     */
+    public MyDeclHandler()
+    {
+    }
+    
+    /* (non-Javadoc)
+     * @see org.xml.sax.ext.DeclHandler#attributeDecl(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String)
+     */
+    public void attributeDecl(String eName, String aName, String type, String valueDefault, String value) 
+    {
+    }                                    
+
+    /* (non-Javadoc)
+     * @see org.xml.sax.ext.DeclHandler#elementDecl(java.lang.String, java.lang.String)
+     */
+    public void elementDecl(String name, String model) 
+    {
+      //valinfo.increaseElementDeclarationCount();
+    }
+  
+    /* (non-Javadoc)
+     * @see org.xml.sax.ext.DeclHandler#externalEntityDecl(java.lang.String, java.lang.String, java.lang.String)
+     */
+    public void externalEntityDecl(String name, String publicId, String systemId) 
+    {
+    }      
+
+    /* (non-Javadoc)
+     * @see org.xml.sax.ext.DeclHandler#internalEntityDecl(java.lang.String, java.lang.String)
+     */
+    public void internalEntityDecl(String name, String value) 
+    {
+    }
+  }
+
+  /**
+   * A XIncludeAwareParserConfiguration that creates an error reporter which can ignore
+   * DTD error messages for DTD's with no elements defined.
+   */
+
+  protected class MyStandardParserConfiguration extends XIncludeAwareParserConfiguration
+  {
+  	XMLValidationInfo valinfo = null;
+    List reportedExceptions = new ArrayList(); 
+  	
+  	/**
+  	 * Constructor.
+  	 * 
+  	 * @param valinfo The XMLValidationInfo object to use.
+  	 */
+  	public MyStandardParserConfiguration(XMLValidationInfo valinfo)
+  	{
+  	  this.valinfo = valinfo;
+  	  
+  	  XMLErrorReporter errorReporter = createErrorReporter();
+      if (errorReporter.getMessageFormatter(XMLMessageFormatter.XML_DOMAIN) == null) {
+          XMLMessageFormatter xmft = new XMLMessageFormatter();
+          errorReporter.putMessageFormatter(XMLMessageFormatter.XML_DOMAIN, xmft);
+          errorReporter.putMessageFormatter(XMLMessageFormatter.XMLNS_DOMAIN, xmft);
+      }  	  
+      fErrorReporter = errorReporter;
+	  setProperty(ERROR_REPORTER, errorReporter);
+	  fCommonComponents.remove(fErrorReporter);
+	  fCommonComponents.add(fErrorReporter);
+  	}
+
+    /* (non-Javadoc)
+     * @see org.apache.xerces.parsers.DTDConfiguration#createErrorReporter()
+     */
+    protected XMLErrorReporter createErrorReporter() 
+    {
+    	return new XMLErrorReporter()
+		{
+    		/* (non-Javadoc)
+    		 * @see org.apache.xerces.impl.XMLErrorReporter#reportError(java.lang.String, java.lang.String, java.lang.Object[], short)
+    		 */
+    		public void reportError(String domain, String key, Object[] arguments, short severity) throws XNIException 
+    	    {                    
+		      boolean reportError = true;
+              valinfo.setCurrentErrorKey(key);  
+			  valinfo.setMessageArguments(arguments);
+		      String ignoreCondition = (String)ingoredErrorKeyTable.get(key);
+		      if (ignoreCondition != null)
+		      {
+		        if (ignoreCondition.equals(XMLValidator.IGNORE_IF_DTD_WITHOUT_ELEMENT_DECL))
+		        {                    
+		          boolean isDTDWithoutElementDeclarationEncountered = valinfo.isDTDWithoutElementDeclarationEncountered(); 
+		          reportError = !isDTDWithoutElementDeclarationEncountered;  
+		        }
+		        else 
+		        {
+		          reportError = false;
+		        }
+		      }
+		      if ("schema_reference.4".equals(key) && arguments.length > 0) //$NON-NLS-1$
+              {
+                Object location = arguments[0];  
+                if (location != null)
+                {  
+                  if(reportedExceptions.contains(location))
+                  {
+                    reportError = false;
+                  }
+                  else
+                  {
+                    reportedExceptions.add(location);
+                  }
+                }
+              }          
+		      if (reportError)
+		      {
+		        super.reportError(domain, key, arguments, severity);
+		        valinfo.getErrorCustomizationManager().considerReportedError(valinfo, key, arguments);
+		      }
+		    }
+		};
+    }
+  }
+  
+  /** 
+   * A line and column number coordinate.
+   */
+  protected class LocationCoordinate
+  {	
+	private int lineNo = -1;
+    private int columnNo = -1;
+    
+    public LocationCoordinate(int lineNumber, int columnNumber)
+    {
+      this.lineNo = lineNumber;
+      this.columnNo = columnNumber;
+    }
+    	
+    public int getLineNumber()
+    { 
+      return this.lineNo;
+    }
+    	
+    public int getColumnNumner()
+    { 
+      return this.columnNo;
+    } 
+  }
+  
+  protected IResource getWorkspaceFileFromLocation(String location)
+  {
+    if (location == null) return null;
+    IWorkspace workspace = ResourcesPlugin.getWorkspace();
+    // To canonicalize the EMF URI
+    IPath canonicalForm = new Path(location);
+    // Need to convert to absolute location...
+    IPath pathLocation = new Path(URIHelper.removeProtocol(canonicalForm.toString()));
+    // ...to find the resource file that is in the workspace
+    IResource resourceFile = workspace.getRoot().getFileForLocation(pathLocation);
+    // If the resource is resolved to a file from http, or a file outside
+    // the workspace, then we will just ignore it.
+    return resourceFile;
+  }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/core/AbstractNestedValidator.java b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/core/AbstractNestedValidator.java
new file mode 100644
index 0000000..4183f42
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/core/AbstractNestedValidator.java
@@ -0,0 +1,539 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 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
+ *******************************************************************************/
+
+package org.eclipse.wst.xml.core.internal.validation.core;
+
+import java.io.InputStream;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.ISchedulingRule;
+import org.eclipse.wst.validation.AbstractValidator;
+import org.eclipse.wst.validation.ValidationResult;
+import org.eclipse.wst.validation.ValidationState;
+import org.eclipse.wst.validation.internal.core.Message;
+import org.eclipse.wst.validation.internal.core.ValidationException;
+import org.eclipse.wst.validation.internal.provisional.core.IMessage;
+import org.eclipse.wst.validation.internal.provisional.core.IReporter;
+import org.eclipse.wst.validation.internal.provisional.core.IValidationContext;
+import org.eclipse.wst.validation.internal.provisional.core.IValidator;
+import org.eclipse.wst.validation.internal.provisional.core.IValidatorJob;
+import org.eclipse.wst.xml.core.internal.validation.AnnotationMsg;
+
+/**
+ * An abstract validator that assists validators in running and contributing
+ * nested messages in the validation results. 
+ * *note: Subclasses do not need to contribute nested messages in order to
+ * benefit from the use of this class. This class takes care of iterating
+ * through results for validators that use the standard context.
+ */
+public abstract class AbstractNestedValidator extends AbstractValidator implements IValidatorJob 
+{
+  // Locally used, non-UI strings.
+  private static final String REFERENCED_FILE_ERROR_OPEN = "referencedFileError("; //$NON-NLS-1$
+  private static final String REFERENCED_FILE_ERROR_CLOSE = ")"; //$NON-NLS-1$
+  private static final String FILE_PROTOCOL_NO_SLASH = "file:"; //$NON-NLS-1$
+  private static final String FILE_PROTOCOL = "file:///"; //$NON-NLS-1$
+  private final String GET_FILE = "getFile"; //$NON-NLS-1$
+  private final String GET_PROJECT_FILES = "getAllFiles"; //$NON-NLS-1$
+  private final String GET_INPUTSTREAM = "inputStream"; //$NON-NLS-1$
+  
+  // Internal strings. These strings are common addition information types.
+  protected static final String COLUMN_NUMBER_ATTRIBUTE = "columnNumber"; //$NON-NLS-1$
+  protected static final String SQUIGGLE_SELECTION_STRATEGY_ATTRIBUTE = "squiggleSelectionStrategy"; //$NON-NLS-1$
+  protected static final String SQUIGGLE_NAME_OR_VALUE_ATTRIBUTE = "squiggleNameOrValue"; //$NON-NLS-1$
+
+  /**
+   * Perform the validation using version 2 of the validation framework.
+   */
+  public ValidationResult validate(IResource resource, int kind, ValidationState state, IProgressMonitor monitor){
+	  ValidationResult result = new ValidationResult();  
+	  IReporter reporter = result.getReporter(monitor);
+		IFile file = null;
+		if (resource instanceof IFile)file = (IFile)resource;
+		if (file != null)
+		{
+		  NestedValidatorContext nestedcontext = getNestedContext(state, false);
+	      boolean teardownRequired = false;
+	      if (nestedcontext == null)
+	      {
+	        // validationstart was not called, so manually setup and tear down
+	        nestedcontext = getNestedContext(state, true);
+	        setupValidation(nestedcontext);
+	        teardownRequired = true;
+	      }
+
+		  validate(file, null, result, reporter, nestedcontext);
+
+	      if (teardownRequired)
+	        teardownValidation(nestedcontext);
+		}
+	    return result;
+  }
+ 
+
+  /* (non-Javadoc)
+   * @see org.eclipse.wst.validation.internal.provisional.core.IValidatorJob#validateInJob(org.eclipse.wst.validation.internal.provisional.core.IValidationContext, org.eclipse.wst.validation.internal.provisional.core.IReporter)
+   */
+  public IStatus validateInJob(IValidationContext context, IReporter reporter) throws ValidationException 
+  {
+	NestedValidatorContext nestedcontext = new NestedValidatorContext();
+	setupValidation(nestedcontext);
+	String[] fileURIs = context.getURIs();
+	if (fileURIs != null && fileURIs.length > 0) 
+	{
+	  int numFiles = fileURIs.length;
+	  for (int i = 0; i < numFiles && !reporter.isCancelled(); i++) 
+	  {
+	    String fileName = fileURIs[i];
+	    if (fileName != null)
+	    {          
+	      Object []parms = {fileName};
+
+	      IFile file = (IFile) context.loadModel(GET_FILE, parms);
+	      if (file != null && shouldValidate(file)) 
+	      { 
+	    	// The helper may not have a file stored in it but may have an InputStream if being
+	    	// called from a source other than the validation framework such as an editor.
+	        if (context.loadModel(GET_INPUTSTREAM) instanceof InputStream)
+	        {
+	          validate(file, (InputStream)context.loadModel(GET_INPUTSTREAM), null, reporter, nestedcontext); //do we need the fileName?  what is int ruleGroup?
+	        }
+	        else
+	        {
+	    	  validate(file, null, null, reporter, nestedcontext);
+	        }
+	      }
+	    }
+	  }
+	}
+	// TODO: Is this needed? Shouldn't the framework pass the complete list? 
+	// Should I know that I'm validating a project as opposed to files?
+	else 
+    {
+      Object []parms = {getValidatorID()};
+      Collection files = (Collection) context.loadModel(GET_PROJECT_FILES, parms);
+      // files can be null if they're outside of the workspace
+      if (files != null) {
+	      Iterator iter = files.iterator();
+	      while (iter.hasNext() && !reporter.isCancelled()) 
+	      {
+	        IFile file = (IFile) iter.next();
+	        if(shouldValidate(file))
+	        {
+		      validate(file, null, null, reporter, nestedcontext);
+	        }
+	      }
+      }
+    }
+	
+	teardownValidation(nestedcontext);
+	if(reporter.isCancelled())
+	  return Status.CANCEL_STATUS;
+    return Status.OK_STATUS;
+  }
+  
+  /**
+   * Provides the id of this validator. The ID is used by the validation
+   * framework. It usually is the fully qualified class name of the class
+   * implementing the IValidator interface.
+   * 
+   * @return a String with the ID of this validator.
+   */
+  protected String getValidatorID()
+  {
+    return this.getClass().getName();
+  }
+  
+  /**
+   * Perform set up before validation runs. Subclasses may implement this
+   * method to perform validation specific set up.
+   * 
+   * @param context
+   * 		The context of the current validation.
+   */
+  protected void setupValidation(NestedValidatorContext context)
+  {
+	// Default implementation does nothing.
+  }
+  
+  /**
+   * Perform tear down after validation runs. Subclasses may implement this
+   * method to perform validation specific tear down.
+   * 
+   * @param context
+   * 		The context of the current validation.
+   */
+  protected void teardownValidation(NestedValidatorContext context)
+  {
+	// Default implementation does nothing.
+  }
+  
+  /* (non-Javadoc)
+   * @see org.eclipse.wst.validation.internal.provisional.core.IValidatorJob#getSchedulingRule(org.eclipse.wst.validation.internal.provisional.core.IValidationContext)
+   */
+  public ISchedulingRule getSchedulingRule(IValidationContext arg0) 
+  {
+	// TODO review whether returning a null rule is correct. Gary had a suggestion in the bug report.
+	return null;
+  }
+
+  /* (non-Javadoc)
+   * @see org.eclipse.wst.validation.internal.provisional.core.IValidator#cleanup(org.eclipse.wst.validation.internal.provisional.core.IReporter)
+   */
+  public void cleanup(IReporter arg0) 
+  {
+    // No cleanup to perform. Subclasses are free to implement this method.
+  }
+
+  /* (non-Javadoc)
+   * @see org.eclipse.wst.validation.internal.provisional.core.IValidator#validate(org.eclipse.wst.validation.internal.provisional.core.IValidationContext, org.eclipse.wst.validation.internal.provisional.core.IReporter)
+   */
+  public void validate(IValidationContext context, IReporter reporter) throws ValidationException 
+  {  
+	validateInJob(context, reporter);
+  }
+	
+	
+  /**
+   * Determine if a given file should be validated. 
+   * 
+   * @param file The file that may be validated.
+   * @return True if the file should be validated, false otherwise.
+   */
+  private static boolean shouldValidate(IFile file) 
+  {
+	IResource resource = file;
+	do 
+	{
+	  if (resource.isDerived() || resource.isTeamPrivateMember() || 
+		  !resource.isAccessible() || resource.getName().charAt(0) == '.') 
+	  {
+		return false;
+	  }
+	  resource = resource.getParent();
+	}while ((resource.getType() & IResource.PROJECT) == 0);
+	
+	return true;
+  }
+  
+  /**
+   * Validate the given file and use the reporter for the validation messages.
+   * This method does not perform the validation logic but rather delegates
+   * to the validate method in subclasses to validate. This method is responsible
+   * for reporting the messages that result from validation.
+   * 
+   * @param file 
+   * 		An IFile to validate.
+   * @param inputstream 
+   * 		An InputStream that represents the file. The InputStream may be null
+   * 		in which case the files should be validated from the IFile.
+   * @param result - The validation result
+   * @param reporter 
+   * 		The reporter with which to report validation messages.
+   * @param context
+   * 		The context of the current validation.
+   */
+  private void validate(IFile file, InputStream inputstream, ValidationResult result, IReporter reporter, NestedValidatorContext context)
+  {  
+	Message message = new LocalizedMessage(IMessage.LOW_SEVERITY, file.getFullPath().toString());
+    reporter.displaySubtask(this, message);
+    
+	String locationString = null;		
+	if (file.getLocation() != null) {
+		locationString = file.getLocation().toString();
+	}
+	if (locationString == null && file.getLocationURI() != null) {
+		locationString = file.getLocationURI().toString();
+	}
+	if (locationString == null) {
+		locationString = file.getFullPath().toString();
+	}
+	String uri = createURIForFilePath(locationString);
+
+	clearMarkers(file, this, reporter);
+	
+	ValidationReport valreport = null;
+	if (result == null)
+	  valreport = validate(uri, inputstream, context);
+	else
+	  valreport = validate(uri, inputstream, context, result);
+	
+	createMarkers(file, valreport.getValidationMessages(), reporter);
+	        
+	try
+	{
+	  file.setSessionProperty(ValidationMessage.ERROR_MESSAGE_MAP_QUALIFIED_NAME, valreport.getNestedMessages());
+	}
+	catch(CoreException e)
+	{
+	  System.out.println("Unable to set nested messages property."); //$NON-NLS-1$
+	}
+  }
+	
+  /**
+   * Validate the given file and use the reporter for the validation messages.
+   * Clients must implement this method with their specific validation logic.
+   * 
+   * @param uri
+   * 		The URI of the file to validate.
+   * @param inputstream 
+   * 		An InputStream that represents the file. The InputStream may be null
+   * 		in which case the files should be validated from the IFile.
+   * @param context
+   * 		The context of the current validation.
+   * @return
+   * 		A validation report summarizing the validation.
+   */
+  public abstract ValidationReport validate(String uri, InputStream inputstream, NestedValidatorContext context);
+  
+  /**
+   * Validate the given file and use the reporter for the validation messages.
+   * Clients should override this method with their specific validation logic.
+   * This method should now be used instead of the abstract version.
+   * Design decision to not make this abstract.
+   * 
+   * @param uri
+   * @param inputstream
+   * @param context
+   * @param result
+   * @return
+   */
+  public ValidationReport validate(String uri, InputStream inputstream, NestedValidatorContext context, ValidationResult result)
+  {
+    return validate(uri, inputstream, context);
+  }
+
+  /**
+   * This method clears all the markers on the given IFile for a specified
+   * validator.
+   * This is a convenience method for subclasses.
+   * 
+   * @param iFile
+   * 		The IFile from which to clear the markers.
+   * @param validator
+   * 		The validator for which to remove the markers.
+   * @param reporter
+   * 		The reporter that can remove the markers.
+   */
+  private void clearMarkers(IFile iFile, IValidator validator, IReporter reporter)
+  {
+	if (fileIsAccessible(iFile))
+	{
+	  reporter.removeAllMessages(validator, iFile);
+	}
+  }
+	  
+  /**
+   * Test whether the given file is accessible and may be used for validation. A file is 
+   * available if 
+   * 1. It is not null.
+   * 2. It exists. 
+   * 3. The project containing the file is accessible.
+   * 
+   * @param file 
+   * 		The file to check to ensure it is accessible.
+   * @return 
+   * 		True if the file is accessible, false otherwise.
+   */
+  private boolean fileIsAccessible(IFile file)
+  {
+    if (file != null && file.exists() && file.getProject().isAccessible())
+	{
+	  return true;
+	}
+	return false;
+  }
+	  
+  /**
+   * Format a file name into a correct URI. 
+   * This is a convenience method for subclasses.
+   * 
+   * @param filename 
+   * 		The file name to format.
+   * @return 
+   * 		
+   * The formatted URI.
+   */
+  private String createURIForFilePath(String filename)
+  {
+	if(!filename.startsWith(FILE_PROTOCOL_NO_SLASH))
+	{
+	  while(filename.startsWith("/")) //$NON-NLS-1$
+	  {
+	    filename = filename.substring(1);
+	  }
+	  filename = FILE_PROTOCOL + filename;
+	}
+	return filename;
+  }
+	  
+  /**
+   * Create markers for the valiation messages generated from the validation.
+   * 
+   * @param iFile
+   *          The resource to create the markers on.
+   * @param valmessages
+   *          The array of validation messages.
+   */
+  public void createMarkers(IFile iFile, ValidationMessage[] valmessages, IReporter reporter)
+  {
+    if (!fileIsAccessible(iFile))
+    {
+      return;
+    }
+    int nummessages = valmessages.length;
+    for (int i = 0; i < nummessages; i++)
+    {
+      ValidationMessage validationMessage = valmessages[i];
+      String uri = validationMessage.getUri();
+
+      LocalizedMessage message;
+      if (validationMessage.getSeverity() == ValidationMessage.SEV_LOW)
+      {
+        message = new LocalizedMessage(IMessage.NORMAL_SEVERITY, 
+        		validationMessage.getMessage(), iFile);
+      }
+      else
+      { 
+        message = new LocalizedMessage(IMessage.HIGH_SEVERITY, validationMessage.getMessage(), iFile);
+      }
+      
+      message.setLineNo(validationMessage.getLineNumber());
+      addInfoToMessage(validationMessage, message);
+      Object[] objlist = validationMessage.getMessageArguments();
+      if (objlist != null && objlist.length ==1 ){
+    	  Object obj = objlist[0];
+    	  if (obj instanceof AnnotationMsg){
+	    	 message.setAttribute(AnnotationMsg.PROBMLEM_ID, new Integer(((AnnotationMsg)obj).getProblemId()));
+	    	 message.setAttribute(AnnotationMsg.LENGTH, new Integer(((AnnotationMsg)obj).getLength()));
+	    	  Object obj1 = ((AnnotationMsg)obj).getAttributeValueText();
+	    	  if (obj1 instanceof String){
+	    		  message.setAttribute(AnnotationMsg.ATTRVALUETEXT, obj1);
+	    	  }
+	    	  else if ( obj1 instanceof Object[]){
+	    		  Object[] objArray = (Object[])obj1;
+	    		  message.setAttribute(AnnotationMsg.ATTRVALUENO, new Integer(objArray.length));
+	    		  for (int j=0; j <objArray.length;j++){
+	    			  Object obj2 = objArray[j];
+	    			  String attrName = AnnotationMsg.ATTRNO + j;
+	    			  message.setAttribute(attrName, obj2);
+	    		  }
+	    		  
+	    	  }
+    	  }
+      }
+      List nestederrors = validationMessage.getNestedMessages();
+      if (nestederrors != null && !nestederrors.isEmpty())
+      {
+        message.setGroupName(REFERENCED_FILE_ERROR_OPEN + uri + REFERENCED_FILE_ERROR_CLOSE);
+      }
+
+      reporter.addMessage(this, message);
+	      
+    }
+  }
+	  
+  /**
+   * This method allows the addition of information to the validation message
+   * @param validationmessage
+   * 		The ValidationMessage to retrieve the information from.
+   * @param message
+   * 		The IMessage to add the information to.
+   */
+  protected void addInfoToMessage (ValidationMessage validationmessage, IMessage message)
+  { 
+	// This method may be overridden by subclasses
+  }
+
+  /**
+   * Get the nested validation context.
+   * 
+   * @param state
+   *          the validation state.
+   * @param create
+   *          when true, a new context will be created if one is not found
+   * @return the nested validation context.
+   */
+  protected NestedValidatorContext getNestedContext(ValidationState state, boolean create)
+  {
+    NestedValidatorContext context = null;
+    if (create)
+    {
+      context = new NestedValidatorContext();
+    }
+    return context;
+  }
+
+  /**
+   * A localized message is a specialized type of IMessage that allows setting
+   * and using a localized message string for a message.
+   */
+  class LocalizedMessage extends Message 
+  {
+    private String _message = null;
+
+	public LocalizedMessage(int severity, String messageText) 
+	{
+	  this(severity, messageText, null);
+	}
+
+	public LocalizedMessage(int severity, String messageText, IResource targetObject) 
+	{
+	  this(severity, messageText, (Object) targetObject);
+	}
+
+	public LocalizedMessage(int severity, String messageText, Object targetObject) 
+	{
+	  super(null, severity, null);
+	  setLocalizedMessage(messageText);
+	  setTargetObject(targetObject);
+	}
+
+	public void setLocalizedMessage(String message) 
+	{
+	  _message = message;
+	}
+
+	public String getLocalizedMessage() 
+	{
+	  return _message;
+	}
+
+	public String getText() 
+	{
+	  return getLocalizedMessage();
+	}
+
+	public String getText(ClassLoader cl) 
+	{
+	  return getLocalizedMessage();
+	}
+
+	public String getText(Locale l) 
+	{
+	  return getLocalizedMessage();
+	}
+
+	public String getText(Locale l, ClassLoader cl) 
+	{
+	  return getLocalizedMessage();
+	}
+  }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/core/Helper.java b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/core/Helper.java
new file mode 100644
index 0000000..d9497af
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/core/Helper.java
@@ -0,0 +1,259 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.xml.core.internal.validation.core;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRunnable;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.wst.validation.internal.operations.ValidatorManager;
+import org.eclipse.wst.validation.internal.operations.WorkbenchContext;
+import org.eclipse.wst.validation.internal.provisional.core.IMessage;
+
+
+/**
+ * A helper class for validation in the validation framework.
+ * 
+ * @author Ernest Mah (ernest@ca.ibm.com)
+ * @author Lawrence Mandel, IBM
+ */
+public class Helper extends WorkbenchContext
+{
+  public static final String GET_PROJECT_FILES = "getAllFiles"; //$NON-NLS-1$
+  public static final String GET_FILE = "getFile"; //$NON-NLS-1$
+  //dw private static final IContainer[] NO_CONTAINERS = new IContainer[0];
+  public static final String VALIDATION_MARKER = "org.eclipse.wst.validation.problemmarker"; //$NON-NLS-1$
+  public static final String VALIDATION_MARKER_OWNER = "owner";   //$NON-NLS-1$
+
+  /**
+   * Constructor.
+   */
+  public Helper()
+  {
+    super();
+
+    // the following will register the helper's symbolic methods
+    Class [] args = new Class[1] ;
+    args[0] = String.class ;  // a string argument denoting a specific JSP.
+    
+    registerModel(GET_FILE, "getFile", args);//$NON-NLS-1$
+    registerModel(GET_PROJECT_FILES, "getFiles", args);//$NON-NLS-1$
+  }
+
+  /**
+   * Get the IFile for the given filename.
+   * 
+   * @param filename The name of the file to retrieve.
+   * @return An IFile representing the file specified or null if it can't be resolved.
+   */
+  public IFile getFile(String filename)
+  {
+    //    System.out.println("file name = " + filename);
+    IResource res = getProject().findMember(filename, true); // true means include phantom resources
+    if (res instanceof IFile) 
+    {
+      return (IFile) res;
+    }
+    return null;
+  }
+  
+  /**
+   * Get the collection of files from the project that are relevant for the
+   * validator with the given class name.
+   * 
+   * @param validatorClassName The name of the validator class.
+   * @return The collection of files relevant for the validator class specified.
+   */
+  public Collection getFiles(String validatorClassName)
+  {
+    IProject project = getProject();
+    List files = new ArrayList();
+    getFiles(files, project, validatorClassName);
+    return files;
+  }
+
+  /**
+   * Get the collection of files from the project that are relevant for the
+   * validator with the given class name.
+   * 
+   * @param files The files relevant for the class name.
+   * @param resource The resource to look for files in.
+   * @param validatorClassName The name of the validator class.
+   */
+  protected void getFiles(Collection files, IContainer resource, String validatorClassName)
+  {
+    try
+    {
+      IResource [] resourceArray = resource.members(false);
+      for (int i=0; i<resourceArray.length; i++)
+      {       
+        if (ValidatorManager.getManager().isApplicableTo(validatorClassName, resourceArray[i])) 
+        {
+          if (resourceArray[i] instanceof IFile) 
+          {
+            files.add(resourceArray[i]);
+          }
+        }
+        if (resourceArray[i].getType() == IResource.FOLDER)
+         getFiles(files,(IContainer)resourceArray[i], validatorClassName) ;
+      }
+    }
+    catch (Exception e) {}
+  }
+
+  
+/**
+ * Return the name of the resource, without the project-specific information 
+ * in front.
+ *
+ * This method is used by ValidationOperation to calculate the non-environment 
+ * specific names of the files. Only the IWorkbenchContext implementation knows how 
+ * much information to strip off of the IResource name. For example, if there is
+ * an EJB Project named "MyEJBProject", and it uses the default names for the 
+ * source and output folders, "source" and "ejbModule", respectively, then the
+ * current implementation of EJB Helper knows how much of that structure is 
+ * eclipse-specific. 
+ *
+ * Since the "source" folder contains Java source files, a portable name would
+ * be the fully-qualified name of the Java class, without the eclipse-specific
+ * project and folder names in front of the file name. The EJBHelper knows that 
+ * everything up to the "source" folder, for example, can be removed, because, 
+ * according to the definition of the EJB Project, everything contained
+ * in the source folder is java source code. So if there is an IResource in an
+ * EJB Project named "/MyEJBProject/source/com/ibm/myclasses/MyJavaFile.java",
+ * this method would make this name portable by stripping off the
+ * "/MyEJBProject/source", and returning "com/ibm/myclasses/MyJavaFile.java".
+ *
+ * The output of this method is used by the ValidationOperation, when it
+ * is calculating the list of added/changed/deleted file names for incremental
+ * validation. If getPortableName(IResource) returns null, that means
+ * that the IWorkbenchContext's implementation does not support that particular
+ * type of resource, and the resource should not be included in the array of
+ * IFileDelta objects in the IValidator's "validate" method. 
+ * 
+ * @param resource The resource to get the name from.
+ * @return The portable name of the resource.
+ */
+public String getPortableName(IResource resource)
+  {
+    //    System.out.println("get portablename for " + resource);
+    return resource.getProjectRelativePath().toString();
+  }
+
+/**
+ * When an IValidator associates a target object with an IMessage,
+ * the WorkbenchReporter eventually resolves that target object
+ * with an IResource. Sometimes more than one target object resolves
+ * to the same IResource (usually the IProject, which is the default
+ * IResource when an IFile cannot be found). This method is called,
+ * by the WorkbenchReporter, so that the WorkbenchReporter can 
+ * distinguish between the IMessages which are on the same IResource, 
+ * but refer to different target objects. This is needed for the 
+ * removeAllMessages(IValidator, Object) method, so that when one
+ * target object removes all of its messages, that it doesn't remove
+ * another target object's messages.
+ *
+ * This method may return null only if object is null. Otherwise, an
+ * id which can uniquely identify a particular object must be returned.
+ * The id needs to be unique only within one particular IValidator.
+ * 
+ * @param object The object from which to get the name.
+ * @return The name of the object or null if the object is null.
+ */
+public String getTargetObjectName(Object object)
+  {
+    if (object == null) 
+    {
+      return null;
+    }
+    
+    //    System.out.println("get targetname for " + object);
+    return object.toString();
+  }
+  
+  /**
+   * Delete the markers of the specified type from the specified resource.
+   * 
+   * @param resource The resource to delete the markers from.
+   * @param markerType The type of markers to delete from the resource.
+   * @param attributeName The name of the attribute which the markers must have to be deleted.
+   * @param attributeValue The value of the attribute corresponding to attributeName which the markers must have to be deleted.
+   * @throws CoreException
+   */
+  public static void deleteMarkers(IResource resource, String markerType, final String attributeName, final Object attributeValue) throws CoreException
+  {          
+    final IMarker[] v400Markers = resource.findMarkers(IMarker.PROBLEM, false, IResource.DEPTH_INFINITE);
+    final IMarker[] markers = resource.findMarkers(markerType, true, IResource.DEPTH_INFINITE);
+    IWorkspaceRunnable op = new IWorkspaceRunnable() 
+     {
+       public void run(IProgressMonitor progressMonitor) throws CoreException 
+       {    
+         // this fixes defect 193406
+         // here we remove markers that may have been added by the v400 code
+         // hopefully the '.markers' metadata files will be removed for the V5 install
+         // and this kludge will not be needed there
+         for (int i = 0; i < v400Markers.length; i++)
+         {
+           IMarker marker = markers[i];           
+           marker.delete();           
+         }
+    
+         for (int i = 0; i < markers.length; i++) 
+         {
+           IMarker marker = markers[i];
+           
+           Object value = marker.getAttribute(attributeName);
+           if (value != null &&
+               value.equals(attributeValue)) 
+           {
+             marker.delete();
+           }
+         }
+       }
+     };
+    
+    try
+    {
+      ResourcesPlugin.getWorkspace().run(op, null);
+    }
+    catch (Exception e) { }
+  }
+  
+  /**
+   * Get the validation framework severity for the given severity.
+   * 
+   * @param severity The severity to convert to validation framework severity.
+   * @return The validation framework severity for the given severity.
+   */
+  static public int getValidationFrameworkSeverity(int severity)
+  {
+    switch (severity)
+    {
+      case IMarker.SEVERITY_ERROR:
+        return IMessage.HIGH_SEVERITY;
+      case IMarker.SEVERITY_WARNING:
+        return IMessage.NORMAL_SEVERITY;
+      case IMarker.SEVERITY_INFO:
+        return IMessage.LOW_SEVERITY;
+    }
+    return IMessage.LOW_SEVERITY;  
+  }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/core/LazyURLInputStream.java b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/core/LazyURLInputStream.java
new file mode 100644
index 0000000..2498b50
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/core/LazyURLInputStream.java
@@ -0,0 +1,161 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.xml.core.internal.validation.core;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+
+
+/**
+ * This class allows InputStreams to be created and returned to xerces without
+ * actually opening file handles or network connections until it is absolutely
+ * neccessary.
+ */
+public class LazyURLInputStream extends InputStream
+{  
+  static int debugTotalOpenStreamCount = 0; 
+  protected InputStream inner;
+  protected String url;
+  protected boolean error;
+  boolean hasMarks;
+  boolean pretendFileIsStillOpen;
+
+  public LazyURLInputStream(String url)
+  {
+    this.url = url;
+	inner = null;
+	pretendFileIsStillOpen = false;
+  }
+
+  private void createInnerStreamIfRequired() throws IOException
+  {
+    if (inner == null && !error)
+    {
+      debugTotalOpenStreamCount++;
+    
+      try
+      {
+        inner = new URL(url).openStream();
+		pretendFileIsStillOpen = false;
+		hasMarks = false;
+      }
+      finally 
+      {
+        if (inner == null)
+        {  
+          error = true;
+        }
+      }
+    }
+  }
+
+	protected void closeStream() throws IOException {
+		if (inner != null && !pretendFileIsStillOpen) {
+			inner.close();
+			pretendFileIsStillOpen = true;
+		}
+  	}
+
+  public int available() throws IOException
+  {
+	if (pretendFileIsStillOpen) return 0;
+	createInnerStreamIfRequired();
+	if (inner == null) throw new IOException("Stream not available"); //$NON-NLS-1$
+	return inner.available();
+  }
+
+  public void close() throws IOException
+  {
+	if (pretendFileIsStillOpen) {
+		// Stop behaving as if the stream were still open.
+		pretendFileIsStillOpen = false;
+	} else {
+		if (inner != null) {
+			debugTotalOpenStreamCount--;
+			inner.close();
+		}
+	}
+  }
+
+  public void mark(int readlimit)
+  {
+	if (pretendFileIsStillOpen) return;
+	hasMarks = true;
+	try {
+		createInnerStreamIfRequired();
+		inner.mark(readlimit);
+	} catch (IOException e) {
+		// TODO Auto-generated catch block
+		e.printStackTrace();
+	}
+  }
+
+  public boolean markSupported()
+  {
+	if (pretendFileIsStillOpen) return false;
+	try {
+		createInnerStreamIfRequired();
+		if (inner == null) return false;
+		return inner.markSupported();
+	} catch (IOException e) {
+		// TODO Auto-generated catch block
+		e.printStackTrace();
+	}
+	return false;
+  }
+
+  public int read() throws IOException
+  {
+	if (pretendFileIsStillOpen) return -1;
+	createInnerStreamIfRequired();
+	if (inner == null) throw new IOException("Stream not available"); //$NON-NLS-1$
+	int bytesRead = inner.read();
+	if (bytesRead == -1 && !hasMarks) closeStream();
+	return bytesRead;
+  }
+
+
+	public int read(byte[] b) throws IOException {
+		if (pretendFileIsStillOpen) return -1;
+		createInnerStreamIfRequired();
+		if (inner == null) throw new IOException("Stream not available"); //$NON-NLS-1$
+		int bytesRead = inner.read(b);
+		if (bytesRead == -1 && !hasMarks) closeStream();
+		return bytesRead;
+	}
+
+  public int read(byte[] b, int off, int len) throws IOException
+  {    
+	if (pretendFileIsStillOpen) return -1;
+	createInnerStreamIfRequired();
+	if (inner == null) throw new IOException("Stream not available"); //$NON-NLS-1$
+	int bytesRead = inner.read(b, off, len);
+	if (bytesRead == -1 && !hasMarks) closeStream();
+	return bytesRead;
+  }
+
+  public void reset() throws IOException
+  {
+	if (pretendFileIsStillOpen) return;
+	createInnerStreamIfRequired();
+	if (inner == null) throw new IOException("Stream not available"); //$NON-NLS-1$
+	inner.reset();
+  }
+
+  public long skip(long n) throws IOException
+  {   
+	if (pretendFileIsStillOpen) return 0;
+	createInnerStreamIfRequired();
+	if (inner == null) throw new IOException("Stream not available"); //$NON-NLS-1$
+	return inner.skip(n);
+  }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/core/NestedValidatorContext.java b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/core/NestedValidatorContext.java
new file mode 100644
index 0000000..3c2710a
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/core/NestedValidatorContext.java
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.xml.core.internal.validation.core;
+
+
+/**
+ * A context class for validators to be able to determine the context of
+ * given validation session. Currently this class is only used to identify
+ * the unique context.
+ */
+public class NestedValidatorContext 
+{
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/core/ValidationInfo.java b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/core/ValidationInfo.java
new file mode 100644
index 0000000..f8f5e07
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/core/ValidationInfo.java
@@ -0,0 +1,287 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     David Carver (STAR) - bug 297005 - Some static constants not made final.
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.validation.core;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.wst.xml.core.internal.validation.XMLValidationMessages;
+
+/**
+ * This class handles messages from a validator. This class can handle
+ * 
+ * @author Lawrence Mandel, IBM
+ */
+public class ValidationInfo implements ValidationReport
+{
+  private boolean WRAPPER_ERROR_SUPPORT_ENABLED = true;
+  public static final int  SEV_ERROR = 0;
+  public static final int SEV_WARNING = 1;
+  
+  private String validating_file_uri = null;
+  private URL validating_file_url = null;
+  private boolean valid = true;
+  private List messages = new ArrayList();
+  private HashMap nestedMessages = new HashMap();
+
+  /**
+   * Constructor.
+   * 
+   * @param uri
+   *            The URI of the file for the validation.
+   */
+  public ValidationInfo(String uri)
+  {
+    if(uri != null)
+    {
+      this.validating_file_uri = uri;
+      try
+      {
+        this.validating_file_url = new URL(uri);
+      } catch (MalformedURLException e)
+      {
+      }
+    }
+  }
+
+  public String getFileURI()
+  {
+    return validating_file_uri;
+  }
+
+  public boolean isValid()
+  {
+    return valid;
+  }
+
+  /**
+   * Add an error message.
+   * 
+   * @param message The message to add.
+   * @param line The line location of the message.
+   * @param column The column location of the message.
+   * @param uri The URI of the file that contains the message.
+   */
+  public void addError(String message, int line, int column, String uri)
+  {
+    addError(message, line, column, uri, null, null);
+  }  
+  
+  /**
+   * 
+   * Add an error message.
+   * 
+   * @param message The message to add.
+   * @param line The line location of the message.
+   * @param column The column location of the message.
+   * @param uri The URI of the file that contains the message.
+   * @param key The key for the message.
+   * @param messageArguments more information about the error
+   */
+  public void addError(String message, int line, int column, String uri, String key, Object[] messageArguments)
+  {    
+    if(addMessage(message, line, column, uri, SEV_ERROR, key, messageArguments))
+    {
+      valid = false;
+    }
+  }
+
+  /**
+   * Add a warning message.
+   * 
+   * @param message The string message of the warning.
+   * @param line The line location of the warning.
+   * @param column The column location of the warning.
+   * @param uri The URI of the file that contains the warning.
+   */
+  public void addWarning(String message, int line, int column, String uri)
+  {
+    addWarning(message, line, column, uri, null, null);
+  }
+  
+  /**
+   * 
+   * Add an error message.
+   * 
+   * @param message The message to add.
+   * @param line The line location of the message.
+   * @param column The column location of the message.
+   * @param uri The URI of the file that contains the message.
+   * @param key The key for the message.
+   * @param messageArguments more information about the error
+   */
+  public void addWarning(String message, int line, int column, String uri, String key, Object[] messageArguments)
+  {    
+    addMessage(message, line, column, uri, SEV_WARNING, key, messageArguments);
+  }
+  
+  /**
+   * Add a message to the list. Return true if successful, false otherwise.
+   * 
+   * @param message The message to add to the list.
+   * @param line The line location of the message.
+   * @param column The column location of the message.
+   * @param uri The URI of the file that contains the message.
+   * @param severity The severity of the message.
+   * @param key the Xerces error key for this error
+   * @param messageArguments more information on the error
+   * @return True if the message was successfully added, false otherwise.
+   */
+  private boolean addMessage(String message, int line, int column, String uri, int severity, String key, Object[] messageArguments)
+  {
+    boolean successfullyAdded = false;
+    // If the message if null there is nothing to add.
+    if(message == null)
+    {
+      return successfullyAdded;
+    }
+    String errorURI = normalize(uri);
+    URL errorURL = null;
+    if (errorURI != null)
+    {
+      try
+      {
+        errorURL = new URL(errorURI);
+      } catch (MalformedURLException e)
+      {
+      }
+      //errorURI = normalizeURI(errorURI);
+    }
+    //boolean doDialog = true;
+    if (errorURL != null)
+    {
+      successfullyAdded = true;
+      // Add to the appropriate list if nested error support is off or
+      // this message is for the current file.
+      if (!WRAPPER_ERROR_SUPPORT_ENABLED || validating_file_url.sameFile(errorURL))
+      {
+
+        ValidationMessage valmes = new ValidationMessage(message, line,
+            column, validating_file_uri, key, messageArguments);
+        if (severity == SEV_ERROR)
+        {
+          valmes.setSeverity(ValidationMessage.SEV_NORMAL);
+        } else if (severity == SEV_WARNING)
+        {
+          valmes.setSeverity(ValidationMessage.SEV_LOW);
+        }
+        messages.add(valmes);
+      }
+      // If nested error support is enabled create a nested error.
+      else if (WRAPPER_ERROR_SUPPORT_ENABLED)
+      {
+        String nesteduri = errorURL.toExternalForm();
+        ValidationMessage nestedmess = new ValidationMessage(message, line,
+            column, nesteduri, key, messageArguments);
+        if(severity == SEV_WARNING)
+        {
+          nestedmess.setSeverity(ValidationMessage.SEV_LOW);
+        }
+        else
+        {
+          nestedmess.setSeverity(ValidationMessage.SEV_NORMAL);
+        }
+
+        ValidationMessage container = (ValidationMessage) nestedMessages.get(nesteduri);
+        if(container == null)
+        {
+          container = new ValidationMessage(NLS.bind(XMLValidationMessages._UI_REF_FILE_ERROR_MESSAGE, new Object [] { nesteduri }), 1, 0, nesteduri);
+       
+          // Initially set the nested error to a warning. This will automatically be changed
+          // to an error if a nested message has a severity of error.
+          container.setSeverity(ValidationMessage.SEV_LOW);
+          nestedMessages.put(nesteduri, container);
+          messages.add(container);
+        }
+        container.addNestedMessage(nestedmess);
+      }
+    }
+    return successfullyAdded;
+  }
+  
+  
+  /**
+   * Add a nested message to the validation information.
+   * 
+   * @param message The string message of the validation message.
+   * @param line The line location of the validation message.
+   * @param column The column location of the validation message.
+   * @param uri The URI of the validation message.
+   * @param severity The severity of the validation message.
+   */
+//  public void addNestedMessage(String message, int line, int column, String uri, int severity)
+//  {
+//    ValidationMessage nestedmess = new ValidationMessage(message, line, column, uri);
+//    if(severity == SEV_WARNING)
+//    {
+//      nestedmess.setSeverity(ValidationMessage.SEV_LOW);
+//    }
+//    else
+//    {
+//      nestedmess.setSeverity(ValidationMessage.SEV_NORMAL);
+//    }
+//    ValidationMessage container = (ValidationMessage)nestedMessages.get(uri);
+//    if(container == null)
+//    {
+//      container = new ValidationMessage(XMLCoreValidationPlugin.getResourceString(_UI_REF_FILE_ERROR_MESSAGE, uri), 1, 0, validating_file_uri);
+//      // Initially set the nested error to a warning. This will automatically be changed
+//      // to an error if a nested message has a severity of error.
+//      container.setSeverity(ValidationMessage.SEV_LOW);
+//      nestedMessages.put(uri, container);
+//      messages.add(container);
+//    }
+//    container.addNestedMessage(nestedmess);
+//  }
+
+  /**
+   * @see org.eclipse.wsdl.validate.ValidationReport#getValidationMessages()
+   */
+  public ValidationMessage[] getValidationMessages()
+  {
+    return (ValidationMessage[])messages.toArray(new ValidationMessage[messages.size()]);
+  }
+
+  public HashMap getNestedMessages()
+  {
+    return nestedMessages;
+  }
+  
+  /**
+   * Put the URI in a standard format.
+   * 
+   * @param uri The URI to put into a standard format.
+   * @return The standard format of the URI.
+   */
+  private String normalize(String uri)
+  {
+//    if(uri.startsWith("platform:"))
+//    {
+//      try
+//      {
+//        uri = Platform.resolve(new URL(uri)).toString();
+//      }
+//      catch(Exception e)
+//      {
+//      }
+//    }
+    uri = uri.replaceAll("%20"," "); //$NON-NLS-1$ //$NON-NLS-2$
+    uri = uri.replaceAll("%5E", "^"); //$NON-NLS-1$ //$NON-NLS-2$
+    uri = uri.replace('\\','/');
+    
+    return uri;
+  }
+  
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/core/ValidationMessage.java b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/core/ValidationMessage.java
new file mode 100644
index 0000000..e2662c0
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/core/ValidationMessage.java
@@ -0,0 +1,202 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 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
+ *     David Carver (STAR) - bug 297005 - Some static constants not made final.
+ *******************************************************************************/
+
+package org.eclipse.wst.xml.core.internal.validation.core;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.wst.validation.internal.provisional.core.IMessage;
+
+/**
+ * A class for holding validation message information. Holds the message and the
+ * message location.
+ */
+public class ValidationMessage
+{
+  public static final QualifiedName ERROR_MESSAGE_MAP_QUALIFIED_NAME = new QualifiedName("org.eclipse.wst.xml.validation", "errorMessageMap"); //$NON-NLS-1$ //$NON-NLS-2$
+  protected String message;
+  protected int lineNumber;
+  protected int columnNumber;
+  protected String uri;
+  protected List nestedErrors;
+  protected String key;
+  protected Object[] messageArguments;
+  protected int startOffset;
+  protected int severity = IMessage.NORMAL_SEVERITY;
+  public static final int SEV_HIGH = IMessage.HIGH_SEVERITY;
+  public static final int SEV_NORMAL = IMessage.NORMAL_SEVERITY;
+  public static final int SEV_LOW = IMessage.LOW_SEVERITY;
+
+  /**
+   * Constructor.
+   * 
+   * @param message The message for the validation message.
+   * @param lineNumber The line location of the message.
+   * @param columnNumber The column location of the message.
+   */
+  public ValidationMessage(String message, int lineNumber, int columnNumber)
+  {
+    this(message, lineNumber, columnNumber, null);
+  }
+
+  /** 
+   * Constructor.
+   * 
+   * @param message The message for the validation message.
+   * @param lineNumber The line location of the message.
+   * @param columnNumber The column location of the message.
+   * @param uri The uri of the file the message is for.
+   */
+   public ValidationMessage(String message, int lineNumber, int columnNumber, String uri)
+  {
+     this(message, lineNumber, columnNumber, uri, null, null);
+  }
+   
+   /** 
+    * Constructor.
+    * 
+    * @param message The message for the validation message.
+    * @param lineNumber The line location of the message.
+    * @param columnNumber The column location of the message.
+    * @param uri The uri of the file the message is for.
+    * @param key a unique string representing the error
+    * @param messageArguments the arguments Xerces uses to create the message
+    */
+    public ValidationMessage(String message, int lineNumber, int columnNumber, String uri, String key, Object[] messageArguments)
+   {
+     this.message = message;
+     this.lineNumber = lineNumber;
+     this.columnNumber = columnNumber;
+     this.uri = uri;
+     this.key = key;
+	 this.messageArguments = messageArguments;
+     this.startOffset = 0;    
+   }
+   
+
+  /**
+   * Get the message for this valiation message.
+   * 
+   * @return The message for this validation message.
+   */
+  public String getMessage()
+  {
+    return message;
+  }
+
+  /**
+   * Get the column location.
+   * 
+   * @return The column number.
+   */
+  public int getColumnNumber()
+  {
+    return columnNumber;
+  }
+
+  /**
+   * Get the line location.
+   * 
+   * @return The line number.
+   */
+  public int getLineNumber()
+  {
+    return lineNumber;
+  }
+
+  /**
+   * Get the uri for the file that contains the message.
+   * 
+   * @return The uri of the file that contains the message.
+   */
+  public String getUri()
+  {
+    return uri;
+  }
+  
+  /**
+   * Add a nested validation message to this validation message.
+   * 
+   * @param validationMessage The validation message to add as a nested message.
+   */
+  public void addNestedMessage(ValidationMessage validationMessage)
+  {
+    if (nestedErrors == null)
+    {
+      nestedErrors = new ArrayList();
+    }
+    nestedErrors.add(validationMessage);
+    int validaitonmessageSeverity = validationMessage.getSeverity();
+    if(validaitonmessageSeverity == SEV_NORMAL || validaitonmessageSeverity == SEV_HIGH)
+    {
+      setSeverity(SEV_NORMAL);
+    }
+  }
+
+  /**
+   * Get the list of nested validation messages.
+   * 
+   * @return The list of nested validation messages.
+   */
+  public List getNestedMessages()
+  {
+    return nestedErrors != null ? nestedErrors : Collections.EMPTY_LIST;
+  }
+  
+  /**
+   * Get the severity of the defect.
+   * 
+   * @return The severity of the defect.
+   */
+  public int getSeverity()
+  {
+  	return severity;
+  }
+  
+  /**
+   * Set the severity of the message.
+   * 
+   * @param sev The severity to set.
+   */
+  public void setSeverity(int sev)
+  {
+  	severity = sev;
+  }
+  
+  public void setStartOffset(int offset)
+  {
+    this.startOffset = offset;
+  }
+  
+  /**
+   * @return Returns the key.
+   */
+  public String getKey()
+  {
+    return key;
+  }
+  
+  public Object[] getMessageArguments()
+  {
+	  return this.messageArguments;
+  }
+  
+
+  public void setMessage(String message)
+  {
+    this.message = message;
+  }  
+                                     
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/core/ValidationReport.java b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/core/ValidationReport.java
new file mode 100644
index 0000000..dbb1570
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/core/ValidationReport.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.validation.core;
+
+import java.util.HashMap;
+
+/**
+ * An interface for a validation report.
+ * 
+ * @author Lawrence Mandel, IBM
+ */
+public interface ValidationReport
+{
+  /**
+   * Returns the URI for the file the report refers to.
+   * 
+   * @return The URI for the file the report refers to.
+   */
+  public String getFileURI();
+  
+  /**
+   * Returns whether the file is valid. The file may have warnings associated with it.
+   * 
+   * @return True if the file is valid, false otherwise.
+   */
+  public boolean isValid();
+
+  /**
+   * Returns an array of validation messages.
+   * 
+   * @return An array of validation messages.
+   */
+  public ValidationMessage[] getValidationMessages();
+  
+  public HashMap getNestedMessages();
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/core/logging/CommandLineLogger.java b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/core/logging/CommandLineLogger.java
new file mode 100644
index 0000000..0d38f38
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/core/logging/CommandLineLogger.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.xml.core.internal.validation.core.logging;
+
+/**
+ * A logger that will print log info to System.out.
+ * 
+ * @author Lawrence Mandel, IBM
+ */
+public class CommandLineLogger implements ILogger
+{
+  public void logError(String error, Throwable exception)
+  {
+    System.out.println(error);
+    System.out.println(exception.toString());
+  }
+
+  public void logWarning(String warning, Throwable exception)
+  {
+    System.out.println(warning);
+    System.out.println(exception.toString());
+  }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/core/logging/EclipseLogger.java b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/core/logging/EclipseLogger.java
new file mode 100644
index 0000000..573cf2d
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/core/logging/EclipseLogger.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.xml.core.internal.validation.core.logging;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.wst.xml.core.internal.XMLCorePlugin;
+
+
+/**
+ * A logger that will log to the log file in the eclipse metadata directory.
+ */
+public class EclipseLogger implements ILogger
+{
+  
+  public void logError(String error, Throwable exception)
+  {
+    XMLCorePlugin.getDefault().getLog().log(new Status(IStatus.ERROR, XMLCorePlugin.getDefault().getBundle().getSymbolicName(), IStatus.ERROR, error, exception));
+  }
+ 
+  public void logWarning(String warning, Throwable exception)
+  {
+    XMLCorePlugin.getDefault().getLog().log(new Status(IStatus.WARNING, XMLCorePlugin.getDefault().getBundle().getSymbolicName(), IStatus.WARNING, warning, exception));
+  }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/core/logging/ILogger.java b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/core/logging/ILogger.java
new file mode 100644
index 0000000..e81a410
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/core/logging/ILogger.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.validation.core.logging;
+
+/**
+ * The interface for a standard logger. Allows for logging errors and warnings.
+ * 
+ * @author Lawrence Mandel, IBM
+ */
+public interface ILogger
+{
+  /**
+   * Log an error message.
+   * 
+   * @param error The error message to log.
+   * @param exception The exception to log.
+   */
+  public void logError(String error, Throwable exception);
+
+  /**
+   * Log a warning message.
+   * 
+   * @param warning The warning message to log.
+   * @param exception The exception to log.
+   */
+  public void logWarning(String warning, Throwable exception);
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/core/logging/LoggerFactory.java b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/core/logging/LoggerFactory.java
new file mode 100644
index 0000000..81549e3
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/core/logging/LoggerFactory.java
@@ -0,0 +1,102 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.validation.core.logging;
+
+/**
+ * The logger factory allows for simple use of whatever logging mechanism is in
+ * place. The tool can specify a custom logging class and can request the
+ * logger from this class.
+ * 
+ * @author Lawrence Mandel, IBM
+ * 
+ * @deprecated - not used in WTP or by any adopters as of 9/12/2007
+ */
+public class LoggerFactory
+{
+  private static ILogger      logger            = null;
+  private static ClassLoader  classloader       = null;
+  private static String       loggerClass       = null;
+  private static final String commandlinelogger = "org.eclipse.wst.xml.validation.internal.core.logging.CommandLineLogger"; //$NON-NLS-1$
+  private static final String eclipselogger     = "org.eclipse.wst.xml.validation.internal.core.logging.EclipseLogger"; //$NON-NLS-1$
+  private static String       defaultlogger     = commandlinelogger;
+
+  /**
+   * Get the one and only instance of the logger.
+   * 
+   * @return The one and only instance of the logger.
+   */
+  public static ILogger getLoggerInstance()
+  {
+    if(logger == null)
+    {
+      if(loggerClass != null)
+      {
+        if(classloader != null)
+        {
+          try
+          {
+            Class lc = classloader.loadClass(loggerClass);
+            logger = (ILogger) lc.newInstance();
+          }
+          catch (Exception e)
+          {
+          }
+        }
+        if(logger == null)
+        {
+          try
+          {
+            Class lc = LoggerFactory.class.getClassLoader().loadClass(loggerClass);
+            logger = (ILogger) lc.newInstance();
+          }
+          catch (Exception e)
+          {
+          }
+        }
+      }
+      if(logger == null)
+      {
+        try
+        {
+          Class lc = LoggerFactory.class.getClassLoader().loadClass(defaultlogger);
+          logger = (ILogger) lc.newInstance();
+        }
+        catch (Exception e)
+        {
+        }
+      }
+    }
+    return logger;
+  }
+
+  /**
+   * Specify the logger implementation to be used.
+   * 
+   * @param classname
+   *            The name of the logger class.
+   * @param loggerclassloader
+   *            The classloader to use to load the logger. If null, the default
+   *            classloader will be used.
+   */
+  public static void specifyLogger(String classname, ClassLoader loggerclassloader)
+  {
+    loggerClass = classname;
+    classloader = loggerclassloader;
+  }
+
+  /**
+   * Set the default logger to the eclipse logger.
+   */
+  public static void useEclipseLogger()
+  {
+    defaultlogger = eclipselogger;
+  }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/eclipse/ErrorCustomizationPluginRegistryReader.java b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/eclipse/ErrorCustomizationPluginRegistryReader.java
new file mode 100644
index 0000000..44a6481
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/eclipse/ErrorCustomizationPluginRegistryReader.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (c) 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.validation.eclipse;
+
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtensionPoint;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.wst.xml.core.internal.validation.errorcustomization.ErrorCustomizationRegistry;
+import org.eclipse.wst.xml.core.internal.validation.errorcustomization.ErrorMessageCustomizerDelegate;
+import org.osgi.framework.Bundle;
+/**
+ * This class reads the plug-in manifests and registers each extension
+ * error customizer with the ErrorCustomizationRegistry.
+ */
+public class ErrorCustomizationPluginRegistryReader {
+	
+	  protected static final String PLUGIN_ID = "org.eclipse.wst.xml.core"; //$NON-NLS-1$
+	  protected static final String ATT_CLASS = "class"; //$NON-NLS-1$
+	  protected static final String ATT_NAMESPACE = "namespace"; //$NON-NLS-1$
+	  protected static final String EXTENSION_POINT_ID = "errorCustomizer"; //$NON-NLS-1$
+	  protected static final String tagName = EXTENSION_POINT_ID;
+
+	  /**
+	   * Read from plugin registry for the errorcustomizer extension.
+	   */
+	  public void readRegistry()
+	  {
+	    IExtensionRegistry pluginRegistry = Platform.getExtensionRegistry();
+	    IExtensionPoint point = pluginRegistry.getExtensionPoint(PLUGIN_ID, EXTENSION_POINT_ID);
+	    if (point != null)
+	    {
+	      IConfigurationElement[] elements = point.getConfigurationElements();
+	      for (int i = 0; i < elements.length; i++)
+	      {
+	        readElement(elements[i]);
+	      }
+	    }
+	  }
+
+	  /**
+	   * readElement() - parse and deal with an extension like:
+	   *
+	   * <extension point="org.eclipse.wst.xml.core.errorCustomizer"
+	   *            id="specificErrorCustomizer"
+	   *            name="Specific Error Customizer">
+	   *   <errorCustomizer
+	   *   			namespace="http://specificnamespace"
+	   *   			class="org.eclipse.wst.xml.core.MySpecificErrorCustomizer/>
+	   * </extension>
+	   */
+	  protected void readElement(IConfigurationElement element)
+	  {
+	    if (element.getName().equals(tagName))
+	    {
+	      String errorCustomizerClass = element.getAttribute(ATT_CLASS);
+	      String namespace = element.getAttribute(ATT_NAMESPACE);
+
+	      if (errorCustomizerClass != null)
+	      {
+	        try
+	        {
+	          Bundle pluginBundle = Platform.getBundle(element.getDeclaringExtension().getContributor().getName());
+	          ErrorMessageCustomizerDelegate delegate = new ErrorMessageCustomizerDelegate(pluginBundle, errorCustomizerClass);
+	          ErrorCustomizationRegistry.getInstance().addErrorMessageCustomizer(namespace, delegate);
+	        }
+	        catch (Exception e)
+	        {
+	        }
+	      }
+	    }
+	  }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/eclipse/Validator.java b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/eclipse/Validator.java
new file mode 100644
index 0000000..4aae874
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/eclipse/Validator.java
@@ -0,0 +1,151 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.xml.core.internal.validation.eclipse;
+
+import java.io.InputStream;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.wst.validation.ValidationResult;
+import org.eclipse.wst.validation.ValidationState;
+import org.eclipse.wst.validation.internal.provisional.core.IMessage;
+import org.eclipse.wst.xml.core.internal.XMLCorePlugin;
+import org.eclipse.wst.xml.core.internal.preferences.XMLCorePreferenceNames;
+import org.eclipse.wst.xml.core.internal.validation.XMLNestedValidatorContext;
+import org.eclipse.wst.xml.core.internal.validation.XMLValidationConfiguration;
+import org.eclipse.wst.xml.core.internal.validation.XMLValidationReport;
+import org.eclipse.wst.xml.core.internal.validation.core.AbstractNestedValidator;
+import org.eclipse.wst.xml.core.internal.validation.core.NestedValidatorContext;
+import org.eclipse.wst.xml.core.internal.validation.core.ValidationMessage;
+import org.eclipse.wst.xml.core.internal.validation.core.ValidationReport;
+
+public class Validator extends AbstractNestedValidator
+{
+  private static final String XML_VALIDATOR_CONTEXT = "org.eclipse.wst.xml.core.validatorContext"; //$NON-NLS-1$
+  protected int indicateNoGrammar = 0;
+  
+  /**
+   * Set any preferences for XML validation.
+   * 
+   * @see org.eclipse.wst.xml.core.internal.validation.core.AbstractNestedValidator#setupValidation(org.eclipse.wst.xml.core.internal.validation.core.NestedValidatorContext)
+   */
+  protected void setupValidation(NestedValidatorContext context) 
+  {
+	super.setupValidation(context);
+	indicateNoGrammar = XMLCorePlugin.getDefault().getPluginPreferences().getInt(XMLCorePreferenceNames.INDICATE_NO_GRAMMAR);
+  }
+
+  /* (non-Javadoc)
+   * @see org.eclipse.wst.xml.core.internal.validation.core.AbstractNestedValidator#validate(java.lang.String, java.io.InputStream, org.eclipse.wst.xml.core.internal.validation.core.NestedValidatorContext)
+   */
+  public ValidationReport validate(String uri, InputStream inputstream, NestedValidatorContext context)
+  {
+    return validate(uri, inputstream, context, null);
+  }
+
+  public ValidationReport validate(String uri, InputStream inputstream, NestedValidatorContext context, ValidationResult result)
+  {
+    XMLValidator validator = XMLValidator.getInstance();
+
+    XMLValidationConfiguration configuration = new XMLValidationConfiguration();
+    try
+    {
+      Preferences pluginPreferences = XMLCorePlugin.getDefault().getPluginPreferences();
+      configuration.setFeature(XMLValidationConfiguration.INDICATE_NO_GRAMMAR, indicateNoGrammar);
+      configuration.setFeature(XMLValidationConfiguration.USE_XINCLUDE, pluginPreferences.getBoolean(XMLCorePreferenceNames.USE_XINCLUDE));
+      configuration.setFeature(XMLValidationConfiguration.HONOUR_ALL_SCHEMA_LOCATIONS, pluginPreferences.getBoolean(XMLCorePreferenceNames.HONOUR_ALL_SCHEMA_LOCATIONS));
+    }
+    catch(Exception e)
+    {
+      // TODO: Unable to set the preference. Log this problem.
+    }
+    
+    XMLValidationReport valreport = validator.validate(uri, inputstream, configuration, result, context);
+              
+    return valreport;
+  }
+	  
+  /**
+   * Store additional information in the message parameters. For XML validation there
+   * are three additional pieces of information to store:
+   * param[0] = the column number of the error
+   * param[1] = the 'squiggle selection strategy' for which DOM part to squiggle
+   * param[2] = the name or value of what is to be squiggled
+   * 
+   * @see org.eclipse.wst.xml.core.internal.validation.core.AbstractNestedValidator#addInfoToMessage(org.eclipse.wst.xml.core.internal.validation.core.ValidationMessage, org.eclipse.wst.validation.internal.provisional.core.IMessage)
+   */
+  protected void addInfoToMessage(ValidationMessage validationMessage, IMessage message)
+  { 
+	String key = validationMessage.getKey();
+	if(key != null)
+	{
+      XMLMessageInfoHelper messageInfoHelper = new XMLMessageInfoHelper();
+      String[] messageInfo = messageInfoHelper.createMessageInfo(key, validationMessage.getMessageArguments());
+      
+      message.setAttribute(COLUMN_NUMBER_ATTRIBUTE, new Integer(validationMessage.getColumnNumber()));
+      message.setAttribute(SQUIGGLE_SELECTION_STRATEGY_ATTRIBUTE, messageInfo[0]);
+      message.setAttribute(SQUIGGLE_NAME_OR_VALUE_ATTRIBUTE, messageInfo[1]);
+	}
+  }
+  
+  /**
+   * Get the nested validation context.
+   * 
+   * @param state
+   *          the validation state.
+   * @param create
+   *          when true, a new context will be created if one is not found
+   * @return the nested validation context.
+   */
+  protected NestedValidatorContext getNestedContext(ValidationState state, boolean create)
+  {
+    NestedValidatorContext context = null;
+    Object o = state.get(XML_VALIDATOR_CONTEXT);
+    if (o instanceof XMLNestedValidatorContext)
+      context = (XMLNestedValidatorContext)o;
+    else if (create)
+    {
+      context = new XMLNestedValidatorContext();
+    }
+    return context;
+  }
+  
+  public void validationStarting(IProject project, ValidationState state, IProgressMonitor monitor)
+  {
+    if (project != null)
+    {
+      NestedValidatorContext context = getNestedContext(state, false);
+      if (context == null)
+      {
+        context = getNestedContext(state, true);
+        setupValidation(context);
+        state.put(XML_VALIDATOR_CONTEXT, context);
+      }
+      super.validationStarting(project, state, monitor);
+    }
+  }
+  
+  public void validationFinishing(IProject project, ValidationState state, IProgressMonitor monitor)
+  {
+    if (project != null)
+    {
+      super.validationFinishing(project, state, monitor);
+      NestedValidatorContext context = getNestedContext(state, false);
+      if (context != null)
+      {
+        teardownValidation(context);
+        state.put(XML_VALIDATOR_CONTEXT, null);
+      }
+    }
+  }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/eclipse/XMLMessageInfoHelper.java b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/eclipse/XMLMessageInfoHelper.java
new file mode 100644
index 0000000..42e7526
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/eclipse/XMLMessageInfoHelper.java
@@ -0,0 +1,112 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 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
+ *******************************************************************************/
+
+package org.eclipse.wst.xml.core.internal.validation.eclipse;
+
+/**
+ * The message info helper determines the selection strategy for elements
+ * in a SSE editor.
+ *
+ */
+public class XMLMessageInfoHelper
+{
+  public XMLMessageInfoHelper()
+  {
+    super();
+  }
+
+  /**
+   *  Returns an array containing information about what should be underlined with the red "squiggles"
+   *  using the errorKey, and the messageArguments.
+   *  <br>Position 0 of the array returned contains the selection Strategy, or what DOM Element to underline.  
+   *  For example "ATTRIBUTE_NAME"  
+   *  <br>Position 1 contains the name or value to squiggle.
+   *  <p>For example, if we wanted to squiggle the attribute name of an attribute name
+   *  foo this method would return {"ATTRIBUTE_NAME", "foo"}
+   *  </p>
+   *  @param errorKey 
+   *  		The error key given by the Xerces parser.
+   *  @param messageArguments 
+   *  		The arguments used by Xerces to "fill in the blanks" of their messages.
+   *  @return 
+   *  		An array containing the squiggle information.
+   *  @see org.eclipse.wst.xml.ui.internal.validation.DelegatingSourceValidator
+   *  
+   */
+  public String[] createMessageInfo(String errorKey, Object[] messageArguments)
+  { 
+    String selectionStrategy = null;
+    String nameOrValue = null;
+    
+    if(errorKey != null)
+    {
+      if (errorKey.equals("cvc-complex-type.2.4.a") || errorKey.equals("cvc-complex-type.2.4.d") || errorKey.equals("cvc-complex-type.2.4.b") || errorKey.equals("MSG_CONTENT_INVALID") //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+        | errorKey.equals("MSG_CONTENT_INCOMPLETE") || errorKey.equals("MSG_REQUIRED_ATTRIBUTE_NOT_SPECIFIED") || errorKey.equals("cvc-complex-type.4") || errorKey.equals("ElementPrefixUnbound")   ) //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+      {
+        selectionStrategy = "START_TAG"; //$NON-NLS-1$
+      }
+      else if (errorKey.equals("cvc-type.3.1.3")) //$NON-NLS-1$
+      {
+        selectionStrategy = "TEXT"; //$NON-NLS-1$
+      }
+      else if (errorKey.equals("cvc-complex-type.2.3")) //$NON-NLS-1$
+      {
+    	selectionStrategy = "FIRST_NON_WHITESPACE_TEXT"; //$NON-NLS-1$
+      }
+      else if (errorKey.equals("cvc-type.3.1.1")) //$NON-NLS-1$
+      {
+        selectionStrategy = "ALL_ATTRIBUTES"; //$NON-NLS-1$
+      }
+      else if (errorKey.equals("cvc-complex-type.3.2.2") || errorKey.equals("MSG_ATTRIBUTE_NOT_DECLARED")) //$NON-NLS-1$ //$NON-NLS-2$
+      {
+        selectionStrategy = "ATTRIBUTE_NAME"; //$NON-NLS-1$
+	    //in this case we need nameOrValue to be the name of the attribute to underline
+	    nameOrValue = (String)messageArguments[1];
+      }
+      else if (errorKey.equals("cvc-attribute.3") || errorKey.equals("MSG_ATTRIBUTE_VALUE_NOT_IN_LIST") || errorKey.equals("cvc-complex-type.3.1")) //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+      {	
+    	selectionStrategy = "ATTRIBUTE_VALUE";   //$NON-NLS-1$
+		//in this case we need nameOrValue to be the name of the Attribute
+    	if (errorKey.equals("cvc-attribute.3") || errorKey.equals("cvc-complex-type.3.1")) //$NON-NLS-1$ //$NON-NLS-2$
+    	{ 
+    	  nameOrValue = (String)messageArguments[1];
+    	}
+    	else if (errorKey.equals("MSG_ATTRIBUTE_VALUE_NOT_IN_LIST")) //$NON-NLS-1$
+    	{	
+    	  nameOrValue = (String)messageArguments[0];
+    	}
+      }
+      else if (errorKey.equals("cvc-elt.4.2")) //$NON-NLS-1$
+      {	
+    	selectionStrategy="VALUE_OF_ATTRIBUTE_WITH_GIVEN_VALUE"; //$NON-NLS-1$
+		//in this case we need nameOrValue to be the value of the attribute we want to unerline
+    	nameOrValue = (String)messageArguments[1];	
+      }
+      else if (errorKey.equals("EntityNotDeclared")) //$NON-NLS-1$
+      {  	
+    	selectionStrategy="TEXT_ENTITY_REFERENCE"; //$NON-NLS-1$
+        nameOrValue = (String)messageArguments[0];
+      }
+      else if (errorKey.equals("ElementUnterminated")) //$NON-NLS-1$
+      {
+        selectionStrategy = "ENTIRE_ELEMENT"; //$NON-NLS-1$
+      }
+      else if (errorKey.equals("ETagUnterminated") || errorKey.equals("ETagRequired"))  //$NON-NLS-1$  //$NON-NLS-2$
+      {
+        selectionStrategy = "END_TAG";   //$NON-NLS-1$
+      }
+    }
+    String messageInfo[] = new String[2];
+    messageInfo[0] = selectionStrategy != null? selectionStrategy: ""; //$NON-NLS-1$
+    messageInfo[1] = nameOrValue;
+    return messageInfo;
+  }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/eclipse/XMLValidator.java b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/eclipse/XMLValidator.java
new file mode 100644
index 0000000..d481058
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/eclipse/XMLValidator.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.xml.core.internal.validation.eclipse;
+
+import org.eclipse.wst.common.uriresolver.internal.provisional.URIResolverPlugin;
+
+/**
+ * An XML validator specific to Eclipse. This validator will wrap the internal
+ * XML validator and provide automatic URI resolution support. This class also
+ * reads from the plug-in registry and registers all error customizers with the
+ * registry.
+ */
+public class XMLValidator extends org.eclipse.wst.xml.core.internal.validation.XMLValidator
+{
+  private static XMLValidator instance = null;
+  
+  /**
+   * Return the one and only instance of the XML validator. The validator
+   * can be reused and cannot be customized so there should only be one instance of it.
+   * 
+   * @return The one and only instance of the XML validator.
+   */
+  public static XMLValidator getInstance()
+  {
+    if(instance == null)
+    {
+      instance = new XMLValidator();
+    }
+    return instance;
+  }
+  /**
+   * Constructor. Create the XML validator, set the URI resolver and
+   * get the extension error customizers from the registry.
+   */
+  protected XMLValidator()
+  {
+    setURIResolver(URIResolverPlugin.createResolver());
+    new ErrorCustomizationPluginRegistryReader().readRegistry();
+  }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/errorcustomization/ElementInformation.java b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/errorcustomization/ElementInformation.java
new file mode 100644
index 0000000..649c99e
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/errorcustomization/ElementInformation.java
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * Copyright (c) 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.validation.errorcustomization;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A simple class to store information about an XML element.
+ */
+public class ElementInformation
+{
+  protected String localName;
+  protected String namespace;
+  protected List children = new ArrayList();
+
+  /**
+   * Constructor.
+   * 
+   * @param uri
+   * 		The namespace URI of the element.
+   * @param localName
+   * 		The local name of the element.
+   */
+  public ElementInformation(String uri, String localName)
+  {
+    this.localName = localName;
+    this.namespace = uri;
+  }
+  
+  /**
+   * Get the namespace of this element.
+   * 
+   * @return
+   * 		The namespace of this element.
+   */
+  public String getNamespace()
+  {
+	return namespace;
+  }
+  
+  /**
+   * Get the local name of this element.
+   * 
+   * @return
+   * 		The local name of this element.
+   */
+  public String getLocalname()
+  {
+	return localName;
+  }
+  
+  /**
+   * Get the list of children of this element. The list contains
+   * ElementInformation objects representing the children of this element.
+   * 
+   * @return
+   * 		The list of children of this element.
+   */
+  public List getChildren()
+  {
+	return children;
+  }
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/errorcustomization/ErrorCustomizationManager.java b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/errorcustomization/ErrorCustomizationManager.java
new file mode 100644
index 0000000..745acc0
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/errorcustomization/ErrorCustomizationManager.java
@@ -0,0 +1,110 @@
+/*******************************************************************************
+ * Copyright (c) 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.validation.errorcustomization;
+
+import java.util.Stack;
+
+import org.eclipse.wst.xml.core.internal.validation.core.ValidationInfo;
+import org.eclipse.wst.xml.core.internal.validation.core.ValidationMessage;
+
+/**
+ * This class tracks the context of the parsed document to help identify error
+ * conditions
+ */
+public class ErrorCustomizationManager
+{
+  protected Stack elementInformationStack = new Stack();
+  protected ErrorMessageInformation messageForConsideration;
+
+  /**
+   * This method should be called in the start element method of the XML validator's
+   * content handler.
+   * 
+   * @param uri
+   * 		The namespace of the element.
+   * @param localName
+   * 		The local name of the element.
+   */
+  public void startElement(String uri, String localName)
+  { 
+    ElementInformation elementInformation = new ElementInformation(uri, localName);
+    if (elementInformationStack.size() > 0)
+    {
+      ElementInformation parent = (ElementInformation) elementInformationStack.peek();
+      parent.children.add(elementInformation);
+    }
+    elementInformationStack.push(elementInformation);
+  }
+
+  /**
+   * This method should be called in the end element method of the XML validator's
+   * content handler.
+   * 
+   * @param uri
+   * 		The namespace of the element.
+   * @param localName
+   * 		The local name of the element.
+   */
+  public void endElement(String uri, String localName)
+  {   
+    if (elementInformationStack.size() > 0)
+    {
+      ElementInformation elementInformation = (ElementInformation)elementInformationStack.pop();
+      if (messageForConsideration != null)
+      {  
+        IErrorMessageCustomizer[] customizers = ErrorCustomizationRegistry.getInstance().getCustomizers(elementInformation.getNamespace());
+        int numCustomizers = customizers.length;
+        for(int i = 0; i < numCustomizers; i++)
+        {
+          String message = customizers[i].customizeMessage(elementInformation, messageForConsideration.key, messageForConsideration.arguments);
+          if(message != null)
+          {
+        	messageForConsideration.message.setMessage(message);
+        	break;
+          }
+        }
+      }  
+    }
+  }
+
+  /**
+   * Consider the reported error for customization.
+   * 
+   * @param valInfo
+   * 		The current ValidationInfo object containing validation specific information.
+   * @param key
+   * 		The key related to the message.
+   * @param arguments
+   * 		Any message arguments.
+   */
+  public void considerReportedError(ValidationInfo valInfo, String key, Object[] arguments)
+  {
+    messageForConsideration = null;
+    ValidationMessage[] messages = valInfo.getValidationMessages();
+    if (messages.length > 0)
+    {  
+      messageForConsideration = new ErrorMessageInformation();
+      messageForConsideration.key = key;
+      messageForConsideration.arguments = arguments;
+      messageForConsideration.message = messages[messages.length - 1]; 
+    }
+  }
+  
+  /**
+   * A simple class to hold error message information.
+   */
+  public class ErrorMessageInformation
+  {
+	public String key = null;
+	public Object[] arguments = null;
+	public ValidationMessage message = null;
+  }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/errorcustomization/ErrorCustomizationRegistry.java b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/errorcustomization/ErrorCustomizationRegistry.java
new file mode 100644
index 0000000..2094879
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/errorcustomization/ErrorCustomizationRegistry.java
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ * Copyright (c) 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.validation.errorcustomization;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * The error customization regsitry manages all registered
+ * IErrorMessageCustomizers by namespace.
+ */
+public class ErrorCustomizationRegistry 
+{
+  protected static ErrorCustomizationRegistry registry = null;
+  protected Map customizers = new HashMap();
+  
+  /**
+   * Restricted constructor in keeping with the singleton pattern.
+   */
+  protected ErrorCustomizationRegistry()
+  {
+  }
+  
+  /**
+   * Get the one and only instance of the registry.
+   * 
+   * @return
+   * 		The one and only instance of the registry.
+   */
+  public static ErrorCustomizationRegistry getInstance()
+  {
+	if(registry == null)
+	{
+	  registry = new ErrorCustomizationRegistry();
+	}
+	return registry;
+  }
+  
+  /**
+   * Add a customizer to the registry. 
+   * 
+   * @param namespace
+   * 		The namespace the customizer will act on.
+   * @param customizer
+   * 		The error customizer to register.
+   */
+  public void addErrorMessageCustomizer(String namespace, IErrorMessageCustomizer customizer)
+  {
+	// To register a customizer for the no namespace use an empty string.
+	if(namespace == null)
+	{
+	  namespace = ""; //$NON-NLS-1$
+	}
+	List customizersForNS = (List)customizers.get(namespace);
+	if(customizersForNS == null)
+	{
+	  customizersForNS = new ArrayList();
+	  customizers.put(namespace, customizersForNS);
+	}
+	if(customizer != null)
+	{
+	  customizersForNS.add(customizer);
+	}
+  }
+  
+  /**
+   * Get the error customizers for a given namespace.
+   * 
+   * @param namespace
+   * 		The namespace for which to retrieve the customizers.
+   * @return
+   * 		An array of customizers registered for this namespace.
+   */
+  public IErrorMessageCustomizer[] getCustomizers(String namespace)
+  {
+	if(namespace == null)
+	{
+	  namespace = ""; //$NON-NLS-1$
+	}
+	List customizersForNS = (List)customizers.get(namespace);
+	if(customizersForNS == null)
+	{
+	  customizersForNS = new ArrayList();
+	}
+	return (IErrorMessageCustomizer[])customizersForNS.toArray(new IErrorMessageCustomizer[customizersForNS.size()]);
+  }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/errorcustomization/ErrorMessageCustomizerDelegate.java b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/errorcustomization/ErrorMessageCustomizerDelegate.java
new file mode 100644
index 0000000..07147c1
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/errorcustomization/ErrorMessageCustomizerDelegate.java
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * Copyright (c) 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.validation.errorcustomization;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.wst.xml.core.internal.XMLCorePlugin;
+import org.osgi.framework.Bundle;
+
+/**
+ * An error message customizer delegate is used to allow for
+ * lazy loading of error customizers.
+ *
+ */
+public class ErrorMessageCustomizerDelegate implements IErrorMessageCustomizer
+{
+  protected Bundle bundle = null;
+  protected String classname = null;
+  protected IErrorMessageCustomizer customizer = null;
+  
+  public ErrorMessageCustomizerDelegate(Bundle bundle, String classname)
+  {
+	this.bundle = bundle;
+	this.classname = classname;
+  }
+
+  /* (non-Javadoc)
+   * @see org.eclipse.wst.xml.core.internal.validation.errorcustomization.IErrorMessageCustomizer#customizeMessage(org.eclipse.wst.xml.core.internal.validation.errorcustomization.ElementInformation, java.lang.String, java.lang.Object[])
+   */
+  public String customizeMessage(ElementInformation elementInfo, String errorKey, Object[] arguments) 
+  {
+	if(customizer == null)
+	{
+	  loadCustomizer();
+	}
+	if(customizer == null)
+	{
+	  return null;
+	}
+	return customizer.customizeMessage(elementInfo, errorKey, arguments);
+  }
+  
+  /**
+   * Load the customizer class.
+   */
+  protected void loadCustomizer()
+  {
+	try
+	{
+	  Class customizerClass = bundle.loadClass(classname);
+	  customizer = (IErrorMessageCustomizer)customizerClass.newInstance();
+	}
+	catch(Exception e)
+	{
+	  XMLCorePlugin.getDefault().getLog().log(
+			  new Status(IStatus.WARNING, 
+					     XMLCorePlugin.getDefault().getBundle().getSymbolicName(), 
+					     IStatus.OK, 
+					     "The XML validator error customizer was unable to load class " + classname, e)); //$NON-NLS-1$
+	}
+  }
+  
+  
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/errorcustomization/IErrorMessageCustomizer.java b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/errorcustomization/IErrorMessageCustomizer.java
new file mode 100644
index 0000000..ac6d1e0
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/errorcustomization/IErrorMessageCustomizer.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.validation.errorcustomization;
+
+/**
+ * An error message customizer will be called by the XML validator to customize
+ * XML validation errors for a given namespace. The customizer can be used to 
+ * create clearer errors for specific application domains.
+ */
+public interface IErrorMessageCustomizer 
+{
+  /**
+   * Return a customized error message for the given element. Null should be returned
+   * if the message should not be customized.
+   * 
+   * @param elementInformation
+   * 		The information about the element for which to customize the error.
+   * @param errorKey
+   * 		The key for the error for which to replace the message.
+   * @param arguments
+   * 		Arguments related the the error message.
+   * @return
+   * 		A customized error message or null if this customizer will not customize the message.
+   */
+  public String customizeMessage(ElementInformation elementInfo, String errorKey, Object[] arguments);
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/xmlvalidation.properties b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/xmlvalidation.properties
new file mode 100644
index 0000000..161065a
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src-validation/org/eclipse/wst/xml/core/internal/validation/xmlvalidation.properties
@@ -0,0 +1,32 @@
+###############################################################################
+# Copyright (c) 2001, 2006 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
+###############################################################################
+!-- Constants for strings  
+
+! Usage:
+!   {0} replaced with the host name
+!
+_UI_PROBLEMS_VALIDATING_UNKNOWN_HOST             = The file cannot be validated as the host "{0}" is currently unreachable.
+
+! Usage:
+!   {0} replaced with the file name
+!
+_UI_PROBLEMS_VALIDATING_FILE_NOT_FOUND           = The file cannot be validated as the XML definition "{0}" that is specified as describing the syntax of the file cannot be located.
+
+_UI_PROBLEMS_CONNECTION_REFUSED                  = The file cannot be validated as there was a connection problem.
+
+!
+! Referenced File Dialog Related Message
+!
+_UI_REF_FILE_ERROR_MESSAGE                       = Referenced file contains errors ({0}).  For more information, right click on the message in the Problems View and select "Show Details..."
+
+# Warning when no grammar is located.
+_WARN_NO_GRAMMAR                                 = No grammar constraints (DTD or XML schema) detected for the document.
+ 
diff --git a/bundles/org.eclipse.wst.xml.core/src/.cvsignore b/bundles/org.eclipse.wst.xml.core/src/.cvsignore
new file mode 100644
index 0000000..101c29e
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/.cvsignore
@@ -0,0 +1 @@
+notebook.jpage
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/DebugAdapterFactory.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/DebugAdapterFactory.java
new file mode 100644
index 0000000..266b80a
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/DebugAdapterFactory.java
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal;
+
+import java.util.ArrayList;
+
+import org.eclipse.wst.sse.core.internal.PropagatingAdapterFactory;
+import org.eclipse.wst.sse.core.internal.provisional.AbstractAdapterFactory;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapter;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapterFactory;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+
+
+public class DebugAdapterFactory extends AbstractAdapterFactory implements PropagatingAdapterFactory {
+
+	/**
+	 * Constructor for DebugAdapterFactory.
+	 */
+	public DebugAdapterFactory() {
+		this(IDebugAdapter.class, true);
+	}
+
+	/**
+	 * Constructor  for DebugAdapterFactory.
+	 * 
+	 * @param fAdapterKey
+	 * @param registerAdapters
+	 */
+	private DebugAdapterFactory(Object adapterKey, boolean registerAdapters) {
+		super(adapterKey, registerAdapters);
+	}
+
+	
+	public void addContributedFactories(INodeAdapterFactory factory) {
+		//none expected
+	}
+
+	public INodeAdapterFactory copy() {
+		return new DebugAdapterFactory(getAdapterKey(), isShouldRegisterAdapter());
+	}
+
+	protected INodeAdapter createAdapter(INodeNotifier target) {
+		EveryNodeDebugAdapter result = null;
+		result = EveryNodeDebugAdapter.getInstance();
+		return result;
+
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.wst.sse.core.IAdapterFactory#isFactoryForType(java.lang.Object)
+	 */
+	public boolean isFactoryForType(Object type) {
+
+		return IDebugAdapter.class == type;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.wst.sse.core.PropagatingAdapterFactory#setContributedFactories(java.util.ArrayList)
+	 */
+	public void setContributedFactories(ArrayList list) {
+		// none expected
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/EveryNodeDebugAdapter.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/EveryNodeDebugAdapter.java
new file mode 100644
index 0000000..baa718c
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/EveryNodeDebugAdapter.java
@@ -0,0 +1,284 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal;
+
+import org.eclipse.jface.text.DocumentEvent;
+import org.eclipse.jface.text.IDocumentListener;
+import org.eclipse.wst.sse.core.internal.provisional.IModelStateListener;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.provisional.events.AboutToBeChangedEvent;
+import org.eclipse.wst.sse.core.internal.provisional.events.IModelAboutToBeChangedListener;
+import org.eclipse.wst.sse.core.internal.provisional.events.IStructuredDocumentListener;
+import org.eclipse.wst.sse.core.internal.provisional.events.NewDocumentEvent;
+import org.eclipse.wst.sse.core.internal.provisional.events.NoChangeEvent;
+import org.eclipse.wst.sse.core.internal.provisional.events.RegionChangedEvent;
+import org.eclipse.wst.sse.core.internal.provisional.events.RegionsReplacedEvent;
+import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentRegionsReplacedEvent;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+import org.eclipse.wst.sse.core.internal.util.Debug;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+
+
+/**
+ * Purely for use in debugging
+ */
+public class EveryNodeDebugAdapter implements IDebugAdapter {
+
+	static class InternalDocumentListener implements IDocumentListener {
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see org.eclipse.jface.text.IDocumentListener#documentAboutToBeChanged(org.eclipse.jface.text.DocumentEvent)
+		 */
+		public void documentAboutToBeChanged(DocumentEvent event) {
+			Debug.println("IdocumentAboutToBeChanged: " + event); //$NON-NLS-1$
+
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see org.eclipse.jface.text.IDocumentListener#documentChanged(org.eclipse.jface.text.DocumentEvent)
+		 */
+		public void documentChanged(DocumentEvent event) {
+			Debug.println("IdocumentChanged: " + event); //$NON-NLS-1$
+
+		}
+
+	}
+
+	static class InternalModelStateListener implements IModelStateListener {
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see org.eclipse.wst.sse.core.IModelStateListener#modelAboutToBeChanged(org.eclipse.wst.sse.core.IStructuredModel)
+		 */
+		public void modelAboutToBeChanged(IStructuredModel model) {
+			Debug.println("modelAboutToBeChanged: " + model); //$NON-NLS-1$
+
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see org.eclipse.wst.sse.core.IModelStateListener#modelChanged(org.eclipse.wst.sse.core.IStructuredModel)
+		 */
+		public void modelChanged(IStructuredModel model) {
+			Debug.println("modelChanged: " + model); //$NON-NLS-1$
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see org.eclipse.wst.sse.core.IModelStateListener#modelDirtyStateChanged(org.eclipse.wst.sse.core.IStructuredModel,
+		 *      boolean)
+		 */
+		public void modelDirtyStateChanged(IStructuredModel model, boolean isDirty) {
+			Debug.println("modelDirtyStateChanged: " + model); //$NON-NLS-1$
+
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see org.eclipse.wst.sse.core.IModelStateListener#modelResourceDeleted(org.eclipse.wst.sse.core.IStructuredModel)
+		 */
+		public void modelResourceDeleted(IStructuredModel model) {
+			Debug.println("modelResourceDeleted: " + model); //$NON-NLS-1$
+
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see org.eclipse.wst.sse.core.IModelStateListener#modelResourceMoved(org.eclipse.wst.sse.core.IStructuredModel,
+		 *      org.eclipse.wst.sse.core.IStructuredModel)
+		 */
+		public void modelResourceMoved(IStructuredModel oldModel, IStructuredModel newModel) {
+			Debug.println("modelResourceMoved: " + "oldModel: " + oldModel + "newModel: " + newModel); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+		}
+
+		public void modelAboutToBeReinitialized(IStructuredModel structuredModel) {
+			Debug.println("modelAboutToBeReinitialized: " + "structuredModel: " + structuredModel); //$NON-NLS-1$ //$NON-NLS-2$
+
+		}
+
+		public void modelReinitialized(IStructuredModel structuredModel) {
+			Debug.println("modelReinitialized: " + "structuredModel: " + structuredModel); //$NON-NLS-1$ //$NON-NLS-2$
+
+		}
+
+	}
+
+	static class InternalStructuredDocumentAboutToChange implements IModelAboutToBeChangedListener {
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see org.eclipse.wst.sse.core.events.IModelAboutToBeChangedListener#modelAboutToBeChanged(org.eclipse.wst.sse.core.events.AboutToBeChangedEvent)
+		 */
+		public void modelAboutToBeChanged(AboutToBeChangedEvent structuredDocumentEvent) {
+			Debug.println("structuredDocumentAboutToBeChanged: " + structuredDocumentEvent); //$NON-NLS-1$
+
+		}
+
+	}
+
+	static class InternalStructuredDocumentListener implements IStructuredDocumentListener {
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see org.eclipse.wst.sse.core.events.IStructuredDocumentListener#newModel(org.eclipse.wst.sse.core.events.NewDocumentContentEvent)
+		 */
+		public void newModel(NewDocumentEvent structuredDocumentEvent) {
+			Debug.println("structuredDocumentChanged - newModel: " + structuredDocumentEvent); //$NON-NLS-1$
+
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see org.eclipse.wst.sse.core.events.IStructuredDocumentListener#noChange(org.eclipse.wst.sse.core.events.NoChangeEvent)
+		 */
+		public void noChange(NoChangeEvent structuredDocumentEvent) {
+			Debug.println("structuredDocumentChanged - noChange: " + structuredDocumentEvent); //$NON-NLS-1$
+
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see org.eclipse.wst.sse.core.events.IStructuredDocumentListener#nodesReplaced(org.eclipse.wst.sse.core.events.StructuredDocumentRegionsReplacedEvent)
+		 */
+		public void nodesReplaced(StructuredDocumentRegionsReplacedEvent structuredDocumentEvent) {
+			Debug.println("structuredDocumentChanged - nodesReplaced: " + structuredDocumentEvent); //$NON-NLS-1$
+
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see org.eclipse.wst.sse.core.events.IStructuredDocumentListener#regionChanged(org.eclipse.wst.sse.core.events.RegionChangedEvent)
+		 */
+		public void regionChanged(RegionChangedEvent structuredDocumentEvent) {
+			Debug.println("structuredDocumentChanged - regionChanged: " + structuredDocumentEvent); //$NON-NLS-1$
+
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see org.eclipse.wst.sse.core.events.IStructuredDocumentListener#regionsReplaced(org.eclipse.wst.sse.core.events.RegionsReplacedEvent)
+		 */
+		public void regionsReplaced(RegionsReplacedEvent structuredDocumentEvent) {
+			Debug.println("structuredDocumentChanged - regionsReplaced: " + structuredDocumentEvent); //$NON-NLS-1$
+
+		}
+
+	}
+
+	private static EveryNodeDebugAdapter singletonInstance;
+
+	public static EveryNodeDebugAdapter getInstance() {
+		if (singletonInstance == null) {
+			singletonInstance = new EveryNodeDebugAdapter();
+		}
+		return singletonInstance;
+	}
+
+	InternalDocumentListener fInternalDocumentListener;
+	InternalModelStateListener fInternalModelStateListener;
+	InternalStructuredDocumentAboutToChange fInternalStructuredDocumentAboutToChange;
+	InternalStructuredDocumentListener fInternalStructuredDocumentListener;
+	IStructuredModel fModel;
+
+	/**
+	 * 
+	 */
+	public EveryNodeDebugAdapter() {
+		super();
+		fInternalDocumentListener = new InternalDocumentListener();
+		fInternalStructuredDocumentAboutToChange = new InternalStructuredDocumentAboutToChange();
+		fInternalStructuredDocumentListener = new InternalStructuredDocumentListener();
+		fInternalModelStateListener = new InternalModelStateListener();
+	}
+
+	/**
+	 * @param target
+	 */
+	public EveryNodeDebugAdapter(INodeNotifier target) {
+		this();
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.wst.sse.core.INodeAdapter#isAdapterForType(java.lang.Object)
+	 */
+	public boolean isAdapterForType(Object type) {
+		return (type == IDebugAdapter.class);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.wst.sse.core.INodeAdapter#notifyChanged(org.eclipse.wst.sse.core.INodeNotifier,
+	 *      int, java.lang.Object, java.lang.Object, java.lang.Object, int)
+	 */
+	public void notifyChanged(INodeNotifier notifier, int eventType, Object changedFeature, Object oldValue, Object newValue, int pos) {
+		if (notifier instanceof IDOMNode) {
+			setModel(((IDOMNode) notifier).getModel());
+		}
+		Debug.println("notifier: " + notifier + " " + INodeNotifier.EVENT_TYPE_STRINGS[eventType] + " changedFeature: " + changedFeature + " oldValue: " + oldValue + " newValue: " + newValue + " pos: " + pos); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
+
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.wst.sse.core.internal.IDebugAdapter#setDocument(org.eclipse.wst.sse.core.text.IStructuredDocument)
+	 */
+	private void setModel(IStructuredModel structuredModel) {
+		if (fModel == structuredModel)
+			return;
+
+		if (fModel != null) {
+			fModel.removeModelStateListener(fInternalModelStateListener);
+			//
+			IStructuredDocument structuredDocument = fModel.getStructuredDocument();
+			if (structuredDocument != null) {
+				structuredDocument.removeDocumentListener(fInternalDocumentListener);
+				structuredDocument.removeDocumentAboutToChangeListener(fInternalStructuredDocumentAboutToChange);
+				structuredDocument.removeDocumentChangedListener(fInternalStructuredDocumentListener);
+			}
+		}
+		fModel = structuredModel;
+		if (fModel != null) {
+
+			fModel.addModelStateListener(fInternalModelStateListener);
+			//
+			IStructuredDocument structuredDocument = fModel.getStructuredDocument();
+			if (structuredDocument != null) {
+				structuredDocument.addDocumentListener(fInternalDocumentListener);
+				structuredDocument.addDocumentAboutToChangeListener(fInternalStructuredDocumentAboutToChange);
+				structuredDocument.addDocumentChangedListener(fInternalStructuredDocumentListener);
+			}
+		}
+
+
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/IDebugAdapter.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/IDebugAdapter.java
new file mode 100644
index 0000000..35c5712
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/IDebugAdapter.java
@@ -0,0 +1,19 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal;
+
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapter;
+
+
+public interface IDebugAdapter extends INodeAdapter {
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/Logger.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/Logger.java
new file mode 100644
index 0000000..798c9bb
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/Logger.java
@@ -0,0 +1,157 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal;
+
+import com.ibm.icu.util.StringTokenizer;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.osgi.framework.Bundle;
+
+/**
+ * Small convenience class to log messages to plugin's log file and also, if
+ * desired, the console. This class should only be used by classes in this
+ * plugin. Other plugins should make their own copy, with appropriate ID.
+ */
+public class Logger {
+	private static final String PLUGIN_ID = "org.eclipse.wst.xml.core"; //$NON-NLS-1$
+	
+	public static final int ERROR = IStatus.ERROR; // 4
+	public static final int ERROR_DEBUG = 200 + ERROR;
+	public static final int INFO = IStatus.INFO; // 1
+	public static final int INFO_DEBUG = 200 + INFO;
+
+	public static final int OK = IStatus.OK; // 0
+
+	public static final int OK_DEBUG = 200 + OK;
+
+	private static final String TRACEFILTER_LOCATION = "/debug/tracefilter"; //$NON-NLS-1$
+	public static final int WARNING = IStatus.WARNING; // 2
+	public static final int WARNING_DEBUG = 200 + WARNING;
+
+	/**
+	 * Adds message to log.
+	 * 
+	 * @param level
+	 *            severity level of the message (OK, INFO, WARNING, ERROR,
+	 *            OK_DEBUG, INFO_DEBUG, WARNING_DEBUG, ERROR_DEBUG)
+	 * @param message
+	 *            text to add to the log
+	 * @param exception
+	 *            exception thrown
+	 */
+	protected static void _log(int level, String message, Throwable exception) {
+		if (level == OK_DEBUG || level == INFO_DEBUG || level == WARNING_DEBUG || level == ERROR_DEBUG) {
+			if (!isDebugging())
+				return;
+		}
+
+		int severity = IStatus.OK;
+		switch (level) {
+			case INFO_DEBUG :
+			case INFO :
+				severity = IStatus.INFO;
+				break;
+			case WARNING_DEBUG :
+			case WARNING :
+				severity = IStatus.WARNING;
+				break;
+			case ERROR_DEBUG :
+			case ERROR :
+				severity = IStatus.ERROR;
+		}
+		message = (message != null) ? message : "null"; //$NON-NLS-1$
+		Status statusObj = new Status(severity, PLUGIN_ID, severity, message, exception);
+		Bundle bundle = Platform.getBundle(PLUGIN_ID);
+		if (bundle != null) 
+			Platform.getLog(bundle).log(statusObj);
+	}
+
+	/**
+	 * Prints message to log if category matches /debug/tracefilter option.
+	 * 
+	 * @param message
+	 *            text to print
+	 * @param category
+	 *            category of the message, to be compared with
+	 *            /debug/tracefilter
+	 */
+	protected static void _trace(String category, String message, Throwable exception) {
+		if (isTracing(category)) {
+			message = (message != null) ? message : "null"; //$NON-NLS-1$
+			Status statusObj = new Status(IStatus.OK, PLUGIN_ID, IStatus.OK, message, exception);
+			Bundle bundle = Platform.getBundle(PLUGIN_ID);
+			if (bundle != null) 
+				Platform.getLog(bundle).log(statusObj);
+		}
+	}
+
+	/**
+	 * @return true if the platform is debugging
+	 */
+	public static boolean isDebugging() {
+		return Platform.inDebugMode();
+	}
+
+	/**
+	 * Determines if currently tracing a category
+	 * 
+	 * @param category
+	 * @return true if tracing category, false otherwise
+	 */
+	public static boolean isTracing(String category) {
+		if (!isDebugging())
+			return false;
+
+		String traceFilter = Platform.getDebugOption(PLUGIN_ID + TRACEFILTER_LOCATION);
+		if (traceFilter != null) {
+			StringTokenizer tokenizer = new StringTokenizer(traceFilter, ","); //$NON-NLS-1$
+			while (tokenizer.hasMoreTokens()) {
+				String cat = tokenizer.nextToken().trim();
+				if (category.equals(cat)) {
+					return true;
+				}
+			}
+		}
+		return false;
+	}
+
+	public static void log(int level, String message) {
+		_log(level, message, null);
+	}
+
+	public static void log(int level, String message, Throwable exception) {
+		_log(level, message, exception);
+	}
+
+	public static void logException(String message, Throwable exception) {
+		_log(ERROR, message, exception);
+	}
+
+	public static void logException(Throwable exception) {
+		_log(ERROR, exception.getMessage(), exception);
+	}
+
+	public static void trace(String category, String message) {
+		_trace(category, message, null);
+	}
+
+	public static void traceException(String category, String message, Throwable exception) {
+		_trace(category, message, exception);
+	}
+
+	public static void traceException(String category, Throwable exception) {
+		_trace(category, exception.getMessage(), exception);
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/XMLCoreMessages.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/XMLCoreMessages.java
new file mode 100644
index 0000000..831c0a2
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/XMLCoreMessages.java
@@ -0,0 +1,63 @@
+/**********************************************************************
+ * Copyright (c) 2005, 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 - Initial API and implementation
+ * Jesper Steen Moeller - Added XML Catalogs 1.1 support
+ **********************************************************************/
+package org.eclipse.wst.xml.core.internal;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Strings used by XML Core
+ * 
+ * @plannedfor 1.0
+ */
+public class XMLCoreMessages {
+	private static final String BUNDLE_NAME = "org.eclipse.wst.xml.core.internal.XMLCorePluginResources";//$NON-NLS-1$
+	
+	public static String Invalid_character_lt_fo_ERROR_;
+	public static String Invalid_character_gt_fo_ERROR_;
+	public static String Invalid_character_amp_fo_ERROR_;
+	public static String Invalid_character__f_EXC_;
+	public static String loading;
+	public static String Catalog_entry_key_not_set;
+	public static String Catalog_entry_uri_not_set;
+	public static String Catalog_rewrite_startString_not_set;
+	public static String Catalog_rewrite_prefix_not_set;
+	public static String Catalog_suffix_string_not_set;
+	public static String Catalog_suffix_uri_not_set;
+	public static String Catalog_delegate_prefix_not_set;
+	public static String Catalog_delegate_catalog_not_set;
+	public static String Catalog_next_catalog_location_uri_not_set;
+	public static String Catalog_resolution_null_catalog;
+	public static String Catalog_resolution_malformed_url;
+	public static String Catalog_resolution_io_exception;
+	public static String CMDocument_load_exception;
+	public static String End_tag_has_attributes;
+	public static String Attribute__is_missing_a_value;
+	public static String Attribute__has_no_value;
+	public static String Missing_end_tag_;
+	public static String Missing_start_tag_;
+	public static String ReconcileStepForMarkup_0;
+	public static String ReconcileStepForMarkup_1;
+	public static String ReconcileStepForMarkup_2;
+	public static String ReconcileStepForMarkup_3;
+	public static String ReconcileStepForMarkup_4;
+	public static String ReconcileStepForMarkup_5;
+	public static String ReconcileStepForMarkup_6;
+	public static String Indicate_no_grammar_specified_severities_error;
+
+	static {
+		// load message values from bundle file
+		NLS.initializeMessages(BUNDLE_NAME, XMLCoreMessages.class);
+	}
+	
+	private XMLCoreMessages() {
+		// cannot create new instance
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/XMLCorePlugin.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/XMLCorePlugin.java
new file mode 100644
index 0000000..bb148a2
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/XMLCorePlugin.java
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal;
+
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.Plugin;
+import org.eclipse.wst.xml.core.internal.catalog.Catalog;
+import org.eclipse.wst.xml.core.internal.catalog.CatalogSet;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalog;
+
+
+/**
+ * The main plugin class to be used in the desktop.
+ */
+public class XMLCorePlugin extends Plugin {
+	// The shared instance.
+	private static XMLCorePlugin plugin;
+	public static final String USER_CATALOG_ID = "user_catalog"; //$NON-NLS-1$
+	public static final String DEFAULT_CATALOG_ID = "default_catalog"; //$NON-NLS-1$
+	public static final String SYSTEM_CATALOG_ID = "system_catalog"; //$NON-NLS-1$
+	private CatalogSet catalogSet = null;
+	private String defaultCatalogFileStateLocation;
+
+
+	/**
+	 * Returns the shared instance.
+	 */
+	public static XMLCorePlugin getDefault() {
+		return plugin;
+	}
+
+	/**
+	 * @deprecated use ResourcesPlugin.getWorkspace() directly
+	 */
+	public static IWorkspace getWorkspace() {
+		return ResourcesPlugin.getWorkspace();
+	}
+
+	/**
+	 * The constructor.
+	 */
+	public XMLCorePlugin() {
+		super();
+		plugin = this;
+	}
+
+	private String getPluginStateLocation(String fileName) {
+		String location = getStateLocation().append(fileName).toString();
+		String file_protocol = "file:"; //$NON-NLS-1$
+		if (location != null && !location.startsWith(file_protocol)) {
+			location = file_protocol + location;
+		}
+		return location;
+	}
+
+	public ICatalog getDefaultXMLCatalog() {
+		if (catalogSet == null) {
+			catalogSet = new CatalogSet();
+
+			defaultCatalogFileStateLocation = getPluginStateLocation(Catalog.DEFAULT_CATALOG_FILE);
+
+			catalogSet.putCatalogPersistenceLocation(DEFAULT_CATALOG_ID, defaultCatalogFileStateLocation);
+			catalogSet.putCatalogPersistenceLocation(SYSTEM_CATALOG_ID, getPluginStateLocation(Catalog.SYSTEM_CATALOG_FILE));
+			catalogSet.putCatalogPersistenceLocation(USER_CATALOG_ID, getPluginStateLocation(Catalog.USER_CATALOG_FILE));
+		}
+		return catalogSet.lookupOrCreateCatalog(DEFAULT_CATALOG_ID, defaultCatalogFileStateLocation);
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/XMLCorePluginResources.properties b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/XMLCorePluginResources.properties
new file mode 100644
index 0000000..d9f1fb7
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/XMLCorePluginResources.properties
@@ -0,0 +1,47 @@
+###############################################################################
+# Copyright (c) 2001, 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
+#     Jens Lukowski/Innoopract - initial renaming/restructuring
+#     Jesper Steen Moeller - Added XML Catalogs 1.1 support
+#     
+###############################################################################
+Invalid_character_lt_fo_ERROR_=Invalid character ('<') found
+Invalid_character_gt_fo_ERROR_=Invalid character ('>') found
+Invalid_character_amp_fo_ERROR_=Invalid character ('&') found
+Invalid_character__f_EXC_=Invalid character ('\"') found
+###############################################################################
+# contentmodel strings
+loading=loading 
+# catalog strings
+Catalog_entry_key_not_set=Catalog entry key is not set
+Catalog_entry_uri_not_set=Catalog entry URI is not set
+Catalog_rewrite_startString_not_set=Catalog rewrite start string is not set
+Catalog_rewrite_prefix_not_set=Catalog rewrite prefix is not set
+Catalog_suffix_string_not_set=Catalog suffix string is not set
+Catalog_suffix_uri_not_set=Catalog suffix URI is not set
+Catalog_delegate_prefix_not_set=Catalog delegate prefix is not set
+Catalog_delegate_catalog_not_set=Catalog delegate URI is not set
+Catalog_next_catalog_location_uri_not_set=Next catalog location URI is not set
+Catalog_resolution_null_catalog=Catalog resolution attempted with null catalog; ignored
+Catalog_resolution_malformed_url=Malformed URL exception trying to resolve
+Catalog_resolution_io_exception=I/O exception trying to resolve
+CMDocument_load_exception=An error occurred while loading document {0} with publicId {1}
+End_tag_has_attributes=End tag has attributes
+Attribute__is_missing_a_value=Attribute \"{0}\" is missing a value
+Attribute__has_no_value=Attribute \"{0}\"  has no value
+Missing_start_tag_=Missing start tag \"{0}\"
+Missing_end_tag_=Missing end tag \"{0}\"
+ReconcileStepForMarkup_0=Missing closing quote
+ReconcileStepForMarkup_1=Missing quotes for attribute value
+ReconcileStepForMarkup_2=A tagname cannot start with a space
+ReconcileStepForMarkup_3=Empty tags are not allowed
+ReconcileStepForMarkup_4=Namespaces are not allowed in a Processing Instruction target
+ReconcileStepForMarkup_5=Spaces are not allowed before a Processing Instruction
+ReconcileStepForMarkup_6=Tag missing closing bracket '>'
+Indicate_no_grammar_specified_severities_error=ErrorCMDocument_load_exception=An error occurred while loading document {0} with publicId {1}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/cleanup/CleanupProcessorXML.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/cleanup/CleanupProcessorXML.java
new file mode 100644
index 0000000..05a4af4
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/cleanup/CleanupProcessorXML.java
@@ -0,0 +1,128 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2009 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.cleanup;
+
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.wst.sse.core.internal.cleanup.AbstractStructuredCleanupProcessor;
+import org.eclipse.wst.sse.core.internal.cleanup.IStructuredCleanupHandler;
+import org.eclipse.wst.sse.core.internal.cleanup.IStructuredCleanupPreferences;
+import org.eclipse.wst.sse.core.internal.cleanup.StructuredCleanupPreferences;
+import org.eclipse.wst.sse.core.internal.encoding.CommonEncodingPreferenceNames;
+import org.eclipse.wst.sse.core.internal.format.IStructuredFormatProcessor;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.xml.core.internal.XMLCorePlugin;
+import org.eclipse.wst.xml.core.internal.document.DOMModelImpl;
+import org.eclipse.wst.xml.core.internal.document.TextImpl;
+import org.eclipse.wst.xml.core.internal.formatter.XMLFormatterFormatProcessor;
+import org.eclipse.wst.xml.core.internal.preferences.XMLCorePreferenceNames;
+import org.eclipse.wst.xml.core.internal.provisional.contenttype.ContentTypeIdForXML;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.w3c.dom.Node;
+import org.w3c.dom.ProcessingInstruction;
+
+
+public class CleanupProcessorXML extends AbstractStructuredCleanupProcessor {
+	protected IStructuredCleanupPreferences fCleanupPreferences = null;
+	
+	public void cleanupModel(IStructuredModel structuredModel) {
+		Preferences preferences = getModelPreferences();
+		if (preferences != null && preferences.getBoolean(XMLCorePreferenceNames.FIX_XML_DECLARATION)) {
+			IDOMDocument document = ((DOMModelImpl) structuredModel).getDocument();
+			if (!fixExistingXmlDecl(document)) {
+				String encoding = preferences.getString(CommonEncodingPreferenceNames.OUTPUT_CODESET);
+				Node xml = document.createProcessingInstruction("xml", "version=\"1.0\" " + "encoding=\"" + encoding +"\""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+				document.insertBefore(xml, document.getFirstChild());
+			}
+		}
+		super.cleanupModel(structuredModel);
+	}
+
+	/**
+	 * Is the node an XML declaration
+	 * @param node
+	 * @return true if the node is an XML declaration; otherwise, false.
+	 */
+	private boolean isXMLDecl(IDOMNode node) {
+		return node != null && node.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE && "xml".equalsIgnoreCase(((ProcessingInstruction) node).getTarget()); //$NON-NLS-1$
+	}
+
+	private boolean fixExistingXmlDecl(IDOMDocument document) {
+		IDOMNode node = (IDOMNode) document.getFirstChild();
+		while (node != null && node.getNodeType() == Node.TEXT_NODE && ((TextImpl) node).isWhitespace())
+			node = (IDOMNode) node.getNextSibling();
+		if (isXMLDecl(node)) {
+			document.insertBefore(node, document.getFirstChild());
+			return true;
+		}
+		return false;
+	}
+
+	protected IStructuredCleanupHandler getCleanupHandler(Node node) {
+		short nodeType = node.getNodeType();
+		IStructuredCleanupHandler cleanupHandler = null;
+		switch (nodeType) {
+			case Node.ELEMENT_NODE : {
+				cleanupHandler = new ElementNodeCleanupHandler();
+				break;
+			}
+			case Node.TEXT_NODE : {
+				cleanupHandler = new NodeCleanupHandler();
+				break;
+			}
+			default : {
+				cleanupHandler = new NodeCleanupHandler();
+			}
+		}
+
+		// init CleanupPreferences
+		cleanupHandler.setCleanupPreferences(getCleanupPreferences());
+
+		return cleanupHandler;
+	}
+
+	public IStructuredCleanupPreferences getCleanupPreferences() {
+		if (fCleanupPreferences == null) {
+			fCleanupPreferences = new StructuredCleanupPreferences();
+
+			Preferences preferences = getModelPreferences();
+			if (preferences != null) {
+				fCleanupPreferences.setCompressEmptyElementTags(preferences.getBoolean(XMLCorePreferenceNames.COMPRESS_EMPTY_ELEMENT_TAGS));
+				fCleanupPreferences.setInsertRequiredAttrs(preferences.getBoolean(XMLCorePreferenceNames.INSERT_REQUIRED_ATTRS));
+				fCleanupPreferences.setInsertMissingTags(preferences.getBoolean(XMLCorePreferenceNames.INSERT_MISSING_TAGS));
+				fCleanupPreferences.setQuoteAttrValues(preferences.getBoolean(XMLCorePreferenceNames.QUOTE_ATTR_VALUES));
+				fCleanupPreferences.setFormatSource(preferences.getBoolean(XMLCorePreferenceNames.FORMAT_SOURCE));
+				fCleanupPreferences.setConvertEOLCodes(preferences.getBoolean(XMLCorePreferenceNames.CONVERT_EOL_CODES));
+				fCleanupPreferences.setEOLCode(preferences.getString(XMLCorePreferenceNames.CLEANUP_EOL_CODE));
+			}
+		}
+
+		return fCleanupPreferences;
+	}
+
+	protected String getContentType() {
+		return ContentTypeIdForXML.ContentTypeID_XML;
+	}
+
+	protected IStructuredFormatProcessor getFormatProcessor() {
+		return new XMLFormatterFormatProcessor();
+	}
+
+	protected Preferences getModelPreferences() {
+		return XMLCorePlugin.getDefault().getPluginPreferences();
+	}
+
+	protected void refreshCleanupPreferences() {
+		fCleanupPreferences = null;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/cleanup/ElementNodeCleanupHandler.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/cleanup/ElementNodeCleanupHandler.java
new file mode 100644
index 0000000..10baa53
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/cleanup/ElementNodeCleanupHandler.java
@@ -0,0 +1,557 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     David Carver (Intalion) - Cleanup Repeated Conditional check in isXMLType method
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.cleanup;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.text.edits.InsertEdit;
+import org.eclipse.text.edits.MultiTextEdit;
+import org.eclipse.wst.sse.core.internal.cleanup.IStructuredCleanupHandler;
+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.ITextRegionList;
+import org.eclipse.wst.sse.core.utils.StringUtils;
+import org.eclipse.wst.xml.core.internal.Logger;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.modelquery.ModelQueryUtil;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMAttr;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
+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.provisional.document.ISourceGenerator;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+
+public class ElementNodeCleanupHandler extends NodeCleanupHandler {
+	protected static final char DOUBLE_QUOTE = '\"'; //$NON-NLS-1$
+	protected static final String DOUBLE_QUOTES = "\"\""; //$NON-NLS-1$
+	protected static final String EMPTY_TAG_CLOSE = "/>"; //$NON-NLS-1$
+	protected static final String END_TAG_OPEN = "</"; //$NON-NLS-1$
+	protected static final char SINGLE_QUOTE = '\''; //$NON-NLS-1$
+	protected static final String SINGLE_QUOTES = "''"; //$NON-NLS-1$
+
+	/** Non-NLS strings */
+	protected static final String START_TAG_OPEN = "<"; //$NON-NLS-1$
+	protected static final String TAG_CLOSE = ">"; //$NON-NLS-1$
+
+	public Node cleanup(Node node) {
+		Node newNode = cleanupChildren(node);
+		IDOMNode renamedNode = newNode instanceof IDOMNode ? (IDOMNode) newNode : null;
+
+		// call quoteAttrValue() first so it will close any unclosed attr
+		// quoteAttrValue() will return the new start tag if there is a
+		// structure change
+		renamedNode = quoteAttrValue(renamedNode);
+
+		// insert tag close if missing
+		// if node is not comment tag
+		// and not implicit tag
+		if (!isCommentTag(renamedNode) && !isImplicitTag(renamedNode)) {
+			IDOMModel structuredModel = renamedNode.getModel();
+
+			// save start offset before insertTagClose()
+			// or else renamedNode.getStartOffset() will be zero if
+			// renamedNode replaced by insertTagClose()
+			int startTagStartOffset = renamedNode.getStartOffset();
+
+			// for start tag
+			IStructuredDocumentRegion startTagStructuredDocumentRegion = renamedNode.getStartStructuredDocumentRegion();
+			insertTagClose(structuredModel, startTagStructuredDocumentRegion);
+
+			// update renamedNode and startTagStructuredDocumentRegion after
+			// insertTagClose()
+			renamedNode = (IDOMNode) structuredModel.getIndexedRegion(startTagStartOffset);
+			startTagStructuredDocumentRegion = renamedNode.getStartStructuredDocumentRegion();
+
+			// for end tag
+			IStructuredDocumentRegion endTagStructuredDocumentRegion = renamedNode.getEndStructuredDocumentRegion();
+			if (endTagStructuredDocumentRegion != startTagStructuredDocumentRegion)
+				insertTagClose(structuredModel, endTagStructuredDocumentRegion);
+		}
+
+		// call insertMissingTags() next, it will generate implicit tags if
+		// there are any
+		// insertMissingTags() will return the new missing start tag if one is
+		// missing
+		renamedNode = insertMissingTags(renamedNode);
+
+		renamedNode = compressEmptyElementTag(renamedNode);
+
+		renamedNode = insertRequiredAttrs(renamedNode);
+
+		return renamedNode;
+	}
+
+	protected Node cleanupChildren(Node node) {
+		Node parentNode = node;
+
+		if (node != null) {
+			Node childNode = node.getFirstChild();
+			while (childNode != null) {
+				// get cleanup handler
+				IStructuredCleanupHandler cleanupHandler = getCleanupHandler(childNode);
+
+				// cleanup each child
+				childNode = cleanupHandler.cleanup(childNode);
+
+				// get new parent node
+				parentNode = childNode.getParentNode();
+
+				// get next child node
+				childNode = childNode.getNextSibling();
+			}
+		}
+
+		return parentNode;
+	}
+
+	private IDOMNode compressEmptyElementTag(IDOMNode node) {
+		boolean compressEmptyElementTags = getCleanupPreferences().getCompressEmptyElementTags();
+		IDOMNode newNode = node;
+
+		IStructuredDocumentRegion startTagStructuredDocumentRegion = newNode.getFirstStructuredDocumentRegion();
+		IStructuredDocumentRegion endTagStructuredDocumentRegion = newNode.getLastStructuredDocumentRegion();
+
+		if (compressEmptyElementTags && startTagStructuredDocumentRegion != endTagStructuredDocumentRegion && startTagStructuredDocumentRegion != null) {
+			ITextRegionList regions = startTagStructuredDocumentRegion.getRegions();
+			ITextRegion lastRegion = regions.get(regions.size() - 1);
+			// format children and end tag if not empty element tag
+			if (lastRegion.getType() != DOMRegionContext.XML_EMPTY_TAG_CLOSE) {
+				NodeList childNodes = newNode.getChildNodes();
+				if (childNodes == null || childNodes.getLength() == 0 || (childNodes.getLength() == 1 && (childNodes.item(0)).getNodeType() == Node.TEXT_NODE && ((childNodes.item(0)).getNodeValue().trim().length() == 0))) {
+					IDOMModel structuredModel = newNode.getModel();
+					IStructuredDocument structuredDocument = structuredModel.getStructuredDocument();
+
+					int startTagStartOffset = newNode.getStartOffset();
+					int offset = endTagStructuredDocumentRegion.getStart();
+					int length = endTagStructuredDocumentRegion.getLength();
+					structuredDocument.replaceText(structuredDocument, offset, length, ""); //$NON-NLS-1$
+					newNode = (IDOMNode) structuredModel.getIndexedRegion(startTagStartOffset); // save
+
+					offset = startTagStructuredDocumentRegion.getStart() + lastRegion.getStart();
+					structuredDocument.replaceText(structuredDocument, offset, 0, "/"); //$NON-NLS-1$
+					newNode = (IDOMNode) structuredModel.getIndexedRegion(startTagStartOffset); // save
+				}
+			}
+		}
+
+		return newNode;
+	}
+
+	protected IStructuredCleanupHandler getCleanupHandler(Node node) {
+		short nodeType = node.getNodeType();
+		IStructuredCleanupHandler cleanupHandler = null;
+		switch (nodeType) {
+			case org.w3c.dom.Node.ELEMENT_NODE : {
+				cleanupHandler = new ElementNodeCleanupHandler();
+				break;
+			}
+			case org.w3c.dom.Node.TEXT_NODE : {
+				cleanupHandler = new NodeCleanupHandler();
+				break;
+			}
+			default : {
+				cleanupHandler = new NodeCleanupHandler();
+			}
+		}
+
+		// init CleanupPreferences
+		cleanupHandler.setCleanupPreferences(getCleanupPreferences());
+
+		return cleanupHandler;
+	}
+
+
+	protected ModelQuery getModelQuery(Node node) {
+		if (node.getNodeType() == Node.DOCUMENT_NODE) {
+			return ModelQueryUtil.getModelQuery((Document) node);
+		} else {
+			return ModelQueryUtil.getModelQuery(node.getOwnerDocument());
+		}
+	}
+
+	protected List getRequiredAttrs(Node node) {
+		List result = new ArrayList();
+
+		ModelQuery modelQuery = getModelQuery(node);
+		if (modelQuery != null) {
+			CMElementDeclaration elementDecl = modelQuery.getCMElementDeclaration((Element) node);
+			if (elementDecl != null) {
+				CMNamedNodeMap attrMap = elementDecl.getAttributes();
+				Iterator it = attrMap.iterator();
+				CMAttributeDeclaration attr = null;
+				while (it.hasNext()) {
+					attr = (CMAttributeDeclaration) it.next();
+					if (attr.getUsage() == CMAttributeDeclaration.REQUIRED) {
+						result.add(attr);
+					}
+				}
+			}
+		}
+
+		return result;
+	}
+
+	private IDOMNode insertEndTag(IDOMNode node) {
+		IDOMNode newNode = node;
+		IDOMElement element = (IDOMElement) node;
+		if (element.isCommentTag())
+			return node; // do nothing
+
+		int startTagStartOffset = node.getStartOffset();
+		IDOMModel structuredModel = node.getModel();
+
+		if (isEmptyElement(element)) {
+			IStructuredDocument structuredDocument = structuredModel.getStructuredDocument();
+			IStructuredDocumentRegion startStructuredDocumentRegion = node.getStartStructuredDocumentRegion();
+			ITextRegionList regions = startStructuredDocumentRegion.getRegions();
+			ITextRegion lastRegion = regions.get(regions.size() - 1);
+			structuredDocument.replaceText(structuredDocument, startStructuredDocumentRegion.getStartOffset(lastRegion), lastRegion.getLength(), EMPTY_TAG_CLOSE);
+
+			if (regions.size() > 1) {
+				ITextRegion regionBeforeTagClose = regions.get(regions.size() - 1 - 1);
+
+				// insert a space separator before tag close if the previous
+				// region does not have extra spaces
+				if (regionBeforeTagClose.getTextLength() == regionBeforeTagClose.getLength())
+					structuredDocument.replaceText(structuredDocument, startStructuredDocumentRegion.getStartOffset(lastRegion), 0, " "); //$NON-NLS-1$
+			}
+		} else {
+			String tagName = node.getNodeName();
+			String endTag = END_TAG_OPEN.concat(tagName).concat(TAG_CLOSE);
+
+			IDOMNode lastChild = (IDOMNode) node.getLastChild();
+			int endTagStartOffset = 0;
+			if (lastChild != null)
+				// if this node has children, insert the end tag after the
+				// last child
+				endTagStartOffset = lastChild.getEndOffset();
+			else
+				// if this node does not has children, insert the end tag
+				// after the start tag
+				endTagStartOffset = node.getEndOffset();
+
+			IStructuredDocument structuredDocument = structuredModel.getStructuredDocument();
+			structuredDocument.replaceText(structuredDocument, endTagStartOffset, 0, endTag);
+		}
+
+		newNode = (IDOMNode) structuredModel.getIndexedRegion(startTagStartOffset); // save
+		// new
+		// node
+
+		return newNode;
+	}
+
+	private IDOMNode insertMissingTags(IDOMNode node) {
+		boolean insertMissingTags = getCleanupPreferences().getInsertMissingTags();
+		IDOMNode newNode = node;
+
+		if (insertMissingTags) {
+			IStructuredDocumentRegion startTagStructuredDocumentRegion = node.getStartStructuredDocumentRegion();
+			if (startTagStructuredDocumentRegion == null) {
+				// implicit start tag; generate tag for it
+				newNode = insertStartTag(node);
+				startTagStructuredDocumentRegion = newNode.getStartStructuredDocumentRegion();
+			}
+
+			IStructuredDocumentRegion endTagStructuredDocumentRegion = newNode.getEndStructuredDocumentRegion();
+			ITextRegionList startStructuredDocumentRegionRegions = startTagStructuredDocumentRegion.getRegions();
+			if (startTagStructuredDocumentRegion != null && startStructuredDocumentRegionRegions != null && (startStructuredDocumentRegionRegions.get(startStructuredDocumentRegionRegions.size() - 1)).getType() == DOMRegionContext.XML_EMPTY_TAG_CLOSE) {
+
+			} else {
+				if (startTagStructuredDocumentRegion == null) {
+					// start tag missing
+					if (isStartTagRequired(newNode))
+						newNode = insertStartTag(newNode);
+				} else if (endTagStructuredDocumentRegion == null) {
+					// end tag missing
+					if (isEndTagRequired(newNode))
+						newNode = insertEndTag(newNode);
+				}
+			}
+		}
+
+		return newNode;
+	}
+
+	private IDOMNode insertRequiredAttrs(IDOMNode node) {
+		boolean insertRequiredAttrs = getCleanupPreferences().getInsertRequiredAttrs();
+		IDOMNode newNode = node;
+
+		if (insertRequiredAttrs) {
+			List requiredAttrs = getRequiredAttrs(newNode);
+			if (requiredAttrs.size() > 0) {
+				NamedNodeMap currentAttrs = node.getAttributes();
+				List insertAttrs = new ArrayList();
+				if (currentAttrs.getLength() == 0)
+					insertAttrs.addAll(requiredAttrs);
+				else {
+					for (int i = 0; i < requiredAttrs.size(); i++) {
+						String requiredAttrName = ((CMAttributeDeclaration) requiredAttrs.get(i)).getAttrName();
+						boolean found = false;
+						for (int j = 0; j < currentAttrs.getLength(); j++) {
+							String currentAttrName = currentAttrs.item(j).getNodeName();
+							if (requiredAttrName.compareToIgnoreCase(currentAttrName) == 0) {
+								found = true;
+								break;
+							}
+						}
+						if (!found)
+							insertAttrs.add(requiredAttrs.get(i));
+					}
+				}
+				if (insertAttrs.size() > 0) {
+					IStructuredDocumentRegion startStructuredDocumentRegion = newNode.getStartStructuredDocumentRegion();
+					int index = startStructuredDocumentRegion.getEndOffset();
+					ITextRegion lastRegion = startStructuredDocumentRegion.getLastRegion();
+					if (lastRegion.getType() == DOMRegionContext.XML_TAG_CLOSE) {
+						index--;
+						lastRegion = startStructuredDocumentRegion.getRegionAtCharacterOffset(index - 1);
+					} else if (lastRegion.getType() == DOMRegionContext.XML_EMPTY_TAG_CLOSE) {
+						index = index - 2;
+						lastRegion = startStructuredDocumentRegion.getRegionAtCharacterOffset(index - 1);
+					}
+					MultiTextEdit multiTextEdit = new MultiTextEdit();
+					try {
+						for (int i = insertAttrs.size() - 1; i >= 0; i--) {
+							CMAttributeDeclaration attrDecl = (CMAttributeDeclaration) insertAttrs.get(i);
+							String requiredAttributeName = attrDecl.getAttrName();
+							String defaultValue = attrDecl.getDefaultValue();
+							if (defaultValue == null)
+								defaultValue = ""; //$NON-NLS-1$
+							String nameAndDefaultValue = " "; //$NON-NLS-1$
+							if (i == 0 && lastRegion.getLength() > lastRegion.getTextLength())
+								nameAndDefaultValue = ""; //$NON-NLS-1$
+							nameAndDefaultValue += requiredAttributeName + "=\"" + defaultValue + "\""; //$NON-NLS-1$ //$NON-NLS-2$
+							multiTextEdit.addChild(new InsertEdit(index, nameAndDefaultValue));
+							// BUG3381: MultiTextEdit applies all child
+							// TextEdit's basing on offsets
+							//          in the document before the first TextEdit, not
+							// after each
+							//          child TextEdit. Therefore, do not need to
+							// advance the index.
+							//index += nameAndDefaultValue.length();
+						}
+						multiTextEdit.apply(newNode.getStructuredDocument());
+					} catch (BadLocationException e) {
+						// log for now, unless we find reason not to
+						Logger.log(Logger.INFO, e.getMessage());
+					}
+				}
+			}
+		}
+
+		return newNode;
+	}
+
+	private IDOMNode insertStartTag(IDOMNode node) {
+		IDOMNode newNode = node;
+
+		if (isCommentTag(node))
+			return node; // do nothing
+
+		String tagName = node.getNodeName();
+		String startTag = START_TAG_OPEN.concat(tagName).concat(TAG_CLOSE);
+		int startTagStartOffset = node.getStartOffset();
+
+		IDOMModel structuredModel = node.getModel();
+		IStructuredDocument structuredDocument = structuredModel.getStructuredDocument();
+		structuredDocument.replaceText(structuredDocument, startTagStartOffset, 0, startTag);
+		newNode = (IDOMNode) structuredModel.getIndexedRegion(startTagStartOffset); // save
+		// new
+		// node
+
+		return newNode;
+	}
+
+	private void insertTagClose(IDOMModel structuredModel, IStructuredDocumentRegion flatNode) {
+		if (flatNode != null) {
+			ITextRegionList flatnodeRegions = flatNode.getRegions();
+			if (flatnodeRegions != null) {
+				ITextRegion lastRegion = flatnodeRegions.get(flatnodeRegions.size() - 1);
+				if (lastRegion != null) {
+					String regionType = lastRegion.getType();
+					if ((regionType != DOMRegionContext.XML_EMPTY_TAG_CLOSE) && (regionType != DOMRegionContext.XML_TAG_CLOSE)) {
+						IStructuredDocument structuredDocument = structuredModel.getStructuredDocument();
+
+						// insert ">" after lastRegion of flatNode
+						// as in "<a</a>" if flatNode is for start tag, or in
+						// "<a></a" if flatNode is for end tag
+						structuredDocument.replaceText(structuredDocument, flatNode.getTextEndOffset(lastRegion), 0, ">"); //$NON-NLS-1$
+					}
+				}
+			}
+		}
+	}
+
+	/**
+	 * @param renamedNode
+	 * @return
+	 */
+	private boolean isCommentTag(Node renamedNode) {
+		boolean result = false;
+		if (renamedNode instanceof IDOMElement) {
+			IDOMElement element = (IDOMElement) renamedNode;
+			result = element.isCommentTag();
+		}
+		return result;
+	}
+
+	private boolean isEmptyElement(IDOMElement element) {
+		Document document = element.getOwnerDocument();
+		if (document == null)
+			// undefined tag, return default
+			return false;
+
+		ModelQuery modelQuery = ModelQueryUtil.getModelQuery(document);
+		if (modelQuery == null)
+			// undefined tag, return default
+			return false;
+
+		CMElementDeclaration decl = modelQuery.getCMElementDeclaration(element);
+		if (decl == null)
+			// undefined tag, return default
+			return false;
+
+		return (decl.getContentType() == CMElementDeclaration.EMPTY);
+	}
+
+	private boolean isEndTagRequired(IDOMNode node) {
+		if (node == null)
+			return false;
+		return node.isContainer();
+	}
+
+	/**
+	 * A tag is implicit if it has not corresponding region in document.
+	 * 
+	 * @param renamedNode
+	 * @return
+	 */
+	private boolean isImplicitTag(IDOMNode renamedNode) {
+		return renamedNode.getStartStructuredDocumentRegion() == null;
+	}
+
+	/**
+	 * The end tags of HTML EMPTY content type, such as IMG, and HTML
+	 * undefined tags are parsed separately from the start tags. So inserting
+	 * the missing start tag is useless and even harmful.
+	 */
+	private boolean isStartTagRequired(IDOMNode node) {
+		if (node == null)
+			return false;
+		return node.isContainer();
+	}
+
+	private boolean isXMLType(IDOMModel structuredModel) {
+		boolean result = false;
+
+		if (structuredModel != null) {
+			IDOMDocument document = structuredModel.getDocument();
+
+			if (document != null)
+				result = document.isXMLType();
+		}
+
+		return result;
+	}
+
+	private IDOMNode quoteAttrValue(IDOMNode node) {
+		IDOMNode newNode = node;
+		//XMLElement element = (XMLElement) node;
+		if (isCommentTag(node))
+			return node; // do nothing
+
+		boolean quoteAttrValues = getCleanupPreferences().getQuoteAttrValues();
+
+		if (quoteAttrValues) {
+			NamedNodeMap attributes = newNode.getAttributes();
+			if (attributes != null) {
+				int attributesLength = attributes.getLength();
+				ISourceGenerator generator = node.getModel().getGenerator();
+
+				for (int i = 0; i < attributesLength; i++) {
+					attributes = newNode.getAttributes();
+					attributesLength = attributes.getLength();
+					IDOMAttr eachAttr = (IDOMAttr) attributes.item(i);
+					//ITextRegion oldAttrValueRegion =
+					// eachAttr.getValueRegion();
+					String oldAttrValue = eachAttr.getValueRegionText();
+					if (oldAttrValue == null) {
+						IDOMModel structuredModel = node.getModel();
+						if (isXMLType(structuredModel)) {
+							String newAttrValue = "\"" + eachAttr.getNameRegionText() + "\""; //$NON-NLS-1$ //$NON-NLS-2$
+
+							IStructuredDocument structuredDocument = structuredModel.getStructuredDocument();
+							if (eachAttr.getEqualRegion() != null)
+								// equal region exists
+								structuredDocument.replaceText(structuredDocument, eachAttr.getEndOffset(), 0, newAttrValue);
+							else
+								// no equal region
+								structuredDocument.replaceText(structuredDocument, eachAttr.getNameRegionTextEndOffset(), 0, "=".concat(newAttrValue)); //$NON-NLS-1$
+							newNode = (IDOMNode) structuredModel.getIndexedRegion(node.getStartOffset()); // save
+							// new
+							// node
+						}
+					} else {
+						//String oldAttrValue = oldAttrValueRegion.getText();
+						char quote = StringUtils.isQuoted(oldAttrValue) ? oldAttrValue.charAt(0) : DOUBLE_QUOTE;
+						String newAttrValue = generator.generateAttrValue(eachAttr, quote);
+
+						// There is a problem in
+						// StructuredDocumentRegionUtil.getAttrValue(ITextRegion)
+						// when the region is instanceof ContextRegion.
+						// Workaround for now...
+						if (oldAttrValue.length() == 1) {
+							char firstChar = oldAttrValue.charAt(0);
+							if (firstChar == SINGLE_QUOTE)
+								newAttrValue = SINGLE_QUOTES;
+							else if (firstChar == DOUBLE_QUOTE)
+								newAttrValue = DOUBLE_QUOTES;
+						}
+
+						if (newAttrValue != null) {
+							if (newAttrValue.compareTo(oldAttrValue) != 0) {
+								int attrValueStartOffset = eachAttr.getValueRegionStartOffset();
+								int attrValueLength = oldAttrValue.length();
+								int startTagStartOffset = node.getStartOffset();
+
+								IDOMModel structuredModel = node.getModel();
+								IStructuredDocument structuredDocument = structuredModel.getStructuredDocument();
+								structuredDocument.replaceText(structuredDocument, attrValueStartOffset, attrValueLength, newAttrValue);
+								newNode = (IDOMNode) structuredModel.getIndexedRegion(startTagStartOffset); // save
+								// new
+								// node
+							}
+						}
+					}
+				}
+			}
+		}
+
+		return newNode;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/cleanup/NodeCleanupHandler.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/cleanup/NodeCleanupHandler.java
new file mode 100644
index 0000000..95c2097
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/cleanup/NodeCleanupHandler.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.cleanup;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.wst.sse.core.internal.cleanup.IStructuredCleanupHandler;
+import org.eclipse.wst.sse.core.internal.cleanup.IStructuredCleanupPreferences;
+import org.eclipse.wst.sse.core.internal.cleanup.StructuredCleanupPreferences;
+import org.eclipse.wst.xml.core.internal.XMLCorePlugin;
+import org.eclipse.wst.xml.core.internal.preferences.XMLCorePreferenceNames;
+import org.w3c.dom.Node;
+
+
+public class NodeCleanupHandler implements IStructuredCleanupHandler {
+
+	protected IStructuredCleanupPreferences fCleanupPreferences = null;
+	protected IProgressMonitor fProgressMonitor = null;
+
+
+	public Node cleanup(Node node) {
+
+		return node;
+	}
+
+	public IStructuredCleanupPreferences getCleanupPreferences() {
+		if (fCleanupPreferences == null) {
+			fCleanupPreferences = new StructuredCleanupPreferences();
+
+			Preferences preferences = getModelPreferences();
+			if (preferences != null) {
+				fCleanupPreferences.setCompressEmptyElementTags(preferences.getBoolean(XMLCorePreferenceNames.COMPRESS_EMPTY_ELEMENT_TAGS));
+				fCleanupPreferences.setInsertRequiredAttrs(preferences.getBoolean(XMLCorePreferenceNames.INSERT_REQUIRED_ATTRS));
+				fCleanupPreferences.setInsertMissingTags(preferences.getBoolean(XMLCorePreferenceNames.INSERT_MISSING_TAGS));
+				fCleanupPreferences.setQuoteAttrValues(preferences.getBoolean(XMLCorePreferenceNames.QUOTE_ATTR_VALUES));
+				fCleanupPreferences.setFormatSource(preferences.getBoolean(XMLCorePreferenceNames.FORMAT_SOURCE));
+				fCleanupPreferences.setConvertEOLCodes(preferences.getBoolean(XMLCorePreferenceNames.CONVERT_EOL_CODES));
+				fCleanupPreferences.setEOLCode(preferences.getString(XMLCorePreferenceNames.CLEANUP_EOL_CODE));
+			}
+		}
+
+		return fCleanupPreferences;
+	}
+
+	protected Preferences getModelPreferences() {
+		return XMLCorePlugin.getDefault().getPluginPreferences();
+	}
+
+	public void setCleanupPreferences(IStructuredCleanupPreferences cleanupPreferences) {
+
+		fCleanupPreferences = cleanupPreferences;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/cleanup/XMLCleanupPreferencesImpl.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/cleanup/XMLCleanupPreferencesImpl.java
new file mode 100644
index 0000000..473c487
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/cleanup/XMLCleanupPreferencesImpl.java
@@ -0,0 +1,142 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.cleanup;
+
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.wst.sse.core.internal.SSECorePlugin;
+import org.eclipse.wst.xml.core.internal.provisional.IXMLPreferenceNames;
+
+/**
+ * @deprecated renamed to StructuredCleanupPreferences
+ * 
+ * TODO will delete in C5
+ */
+public class XMLCleanupPreferencesImpl {
+
+	private static XMLCleanupPreferencesImpl fInstance;
+
+	public synchronized static XMLCleanupPreferencesImpl getInstance() {
+
+		// added for one method in CleanupDialog ... may be better way
+		if (fInstance == null) {
+			fInstance = new XMLCleanupPreferencesImpl();
+		}
+		return fInstance;
+	}
+
+	private int fAttrNameCase;
+	private boolean fConvertEOLCodes;
+	private String fEOLCode;
+	private boolean fFormatSource;
+	private boolean fInsertMissingTags;
+	// private IPreferenceStore fPreferenceStore = null;
+	private Preferences fPreferences = null;
+	private boolean fQuoteAttrValues;
+	private int fTagNameCase;
+
+	public int getAttrNameCase() {
+
+		return fAttrNameCase;
+	}
+
+	public boolean getConvertEOLCodes() {
+
+		return fConvertEOLCodes;
+	}
+
+	public String getEOLCode() {
+
+		return fEOLCode;
+	}
+
+	public boolean getFormatSource() {
+
+		return fFormatSource;
+	}
+
+	public boolean getInsertMissingTags() {
+
+		return fInsertMissingTags;
+	}
+
+	public Preferences getPreferences() {
+
+		if (fPreferences == null) {
+			fPreferences = SSECorePlugin.getDefault().getPluginPreferences();
+		}
+		return fPreferences;
+	}
+
+	public boolean getQuoteAttrValues() {
+
+		return fQuoteAttrValues;
+	}
+
+	public int getTagNameCase() {
+
+		return fTagNameCase;
+	}
+
+	public void setAttrNameCase(int attrNameCase) {
+
+		fAttrNameCase = attrNameCase;
+	}
+
+	public void setConvertEOLCodes(boolean convertEOLCodes) {
+
+		fConvertEOLCodes = convertEOLCodes;
+	}
+
+	public void setEOLCode(String EOLCode) {
+
+		fEOLCode = EOLCode;
+	}
+
+	public void setFormatSource(boolean formatSource) {
+
+		fFormatSource = formatSource;
+	}
+
+	public void setInsertMissingTags(boolean insertMissingTags) {
+
+		fInsertMissingTags = insertMissingTags;
+	}
+
+	public void setPreferences(Preferences prefs) {
+
+		fPreferences = prefs;
+		updateOptions();
+	}
+
+	public void setQuoteAttrValues(boolean quoteAttrValues) {
+
+		fQuoteAttrValues = quoteAttrValues;
+	}
+
+	public void setTagNameCase(int tagNameCase) {
+
+		fTagNameCase = tagNameCase;
+	}
+
+	protected void updateOptions() {
+
+		Preferences p = getPreferences();
+		fTagNameCase = p.getInt(IXMLPreferenceNames.CLEANUP_TAG_NAME_CASE);
+		fAttrNameCase = p.getInt(IXMLPreferenceNames.CLEANUP_ATTR_NAME_CASE);
+		fInsertMissingTags = p.getBoolean(IXMLPreferenceNames.INSERT_MISSING_TAGS);
+		fQuoteAttrValues = p.getBoolean(IXMLPreferenceNames.QUOTE_ATTR_VALUES);
+		fFormatSource = p.getBoolean(IXMLPreferenceNames.FORMAT_SOURCE);
+		fConvertEOLCodes = p.getBoolean(IXMLPreferenceNames.CONVERT_EOL_CODES);
+		fEOLCode = p.getString(IXMLPreferenceNames.CLEANUP_EOL_CODE);
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/commentelement/CommentElementAdapter.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/commentelement/CommentElementAdapter.java
new file mode 100644
index 0000000..c06af5e
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/commentelement/CommentElementAdapter.java
@@ -0,0 +1,103 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.commentelement;
+
+
+
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.xml.core.internal.commentelement.impl.CommentElementConfiguration;
+import org.eclipse.wst.xml.core.internal.document.TagAdapter;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
+
+
+/**
+ */
+public class CommentElementAdapter implements TagAdapter {
+	private CommentElementConfiguration fConfiguration;
+
+	private boolean fEndTag;
+	private CommentElementHandler fHandler;
+
+	public CommentElementAdapter(boolean isEndTag, CommentElementHandler handler) {
+		fEndTag = isEndTag;
+		fHandler = handler;
+	}
+
+	private String generateCommentClose(IDOMElement element) {
+		return (element.isJSPTag()) ? "--%>" : "-->"; //$NON-NLS-1$ //$NON-NLS-2$
+	}
+
+	private String generateCommentOpen(IDOMElement element) {
+		return (element.isJSPTag()) ? "<%--" : "<!--"; //$NON-NLS-1$ //$NON-NLS-2$
+	}
+
+	private CommentElementConfiguration getConfiguration() {
+		return fConfiguration;
+	}
+
+	public String getEndTag(IDOMElement element) {
+		String content = fHandler.generateEndTagContent(element);
+		if (content == null) {
+			return null;
+		}
+		StringBuffer buffer = new StringBuffer();
+
+		buffer.append(generateCommentOpen(element));
+		buffer.append(content);
+		buffer.append(generateCommentClose(element));
+
+		return buffer.toString();
+	}
+
+	public String getHandlerID() {
+		return getConfiguration().getHandlerID();
+	}
+
+
+	public String getProperty(String name) {
+		return getConfiguration().getProperty(name);
+	}
+
+	public String getStartTag(IDOMElement element) {
+		String content = fHandler.generateStartTagContent(element);
+		if (content == null) {
+			return null;
+		}
+		StringBuffer buffer = new StringBuffer();
+
+		buffer.append(generateCommentOpen(element));
+		buffer.append(content);
+		buffer.append(generateCommentClose(element));
+
+		return buffer.toString();
+	}
+
+	public boolean isAdapterForType(Object type) {
+		return (type == CommentElementAdapter.class || type == TagAdapter.class);
+	}
+
+	public boolean isContainer() {
+		return (!fHandler.isEmpty());
+	}
+
+	public boolean isEndTag() {
+		return fEndTag;
+	}
+
+	public void notifyChanged(INodeNotifier notifier, int eventType, Object changedFeature, Object oldValue, Object newValue, int pos) {
+	}
+
+	public void setConfiguration(CommentElementConfiguration configuration) {
+		fConfiguration = configuration;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/commentelement/CommentElementHandler.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/commentelement/CommentElementHandler.java
new file mode 100644
index 0000000..93e8e6e
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/commentelement/CommentElementHandler.java
@@ -0,0 +1,107 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.commentelement;
+
+
+
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+
+/**
+ */
+public interface CommentElementHandler {
+	/**
+	 * This method is called when the prefix of the comment content matches
+	 * the string specified in &lt;startswith prefix=""/&gt; in plugin
+	 * extension. Comment content is parsed and new DOM element is created in
+	 * this method. Implementor has to do following:
+	 * <li>For start tag :
+	 * <ul>
+	 * <li>parse comment content and create new element instance.</li>
+	 * </ul>
+	 * </li>
+	 * <li>For end tag :
+	 * <ul>
+	 * <li>parse comment content and create new element instance.</li>
+	 * <li>make isEndTag flag true.</li>
+	 * <li>Parser framework searches mached start tag element instance after
+	 * this createElement call, and new instance is just thrown away.</li>
+	 * </ul>
+	 * </li>
+	 * <li>For empty tag :
+	 * <ul>
+	 * <li>parse comment content and create new element instance.</li>
+	 * <li>make isEndTag flag true.</li>
+	 * </ul>
+	 * </li>
+	 * 
+	 * @param document
+	 *            parent DOM document
+	 * @param data
+	 *            comment content. comment prefix (&lt;!-- or &lt;%--), suffix
+	 *            (--&gt; or --%&gt;), and surrounding spaces are trimmed.
+	 * @param isJSPTag
+	 *            true if the comment is JSP style comment. This information
+	 *            may be required by handler when the handler accepts both XML
+	 *            style and JSP style comment (namely,
+	 *            commenttype=&quot;both&quot; in plugin.xml).
+	 * @return comment element instance if the comment content is rightly
+	 *         parsed. if parse failed, returns null.
+	 */
+	Element createElement(Document document, String data, boolean isJSPTag);
+
+	/**
+	 * This method generates the source text of the end tag for the passed
+	 * element. Do not generate comment prefix (&lt;!-- or &lt;%--) and suffix
+	 * (--&gt; or --%&gt;). XMLGenerator uses this method to generate XML/HTML
+	 * source for a comment element.
+	 * 
+	 * @param element
+	 *            the comment element
+	 * @return generated tag string
+	 */
+	String generateEndTagContent(IDOMElement element);
+
+	/**
+	 * This method generates the source text of the start tag for the passed
+	 * element. Do not generate comment prefix (&lt;!-- or &lt;%--) and suffix
+	 * (--&gt; or --%&gt;). XMLGenerator uses this method to generate XML/HTML
+	 * source for a comment element.
+	 * 
+	 * @param element
+	 *            the comment element
+	 * @return generated tag string
+	 */
+	String generateStartTagContent(IDOMElement element);
+
+	/**
+	 * 
+	 * @param element
+	 *            the element
+	 * @return boolean whether the element is comment element or not
+	 */
+	boolean isCommentElement(IDOMElement element);
+
+	/**
+	 * 
+	 * @return boolean whether this element can have children or not
+	 */
+	boolean isEmpty();
+
+	/**
+	 * @return String
+	 */
+	//	String getElementPrefix();
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/commentelement/impl/BasicCommentElementHandler.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/commentelement/impl/BasicCommentElementHandler.java
new file mode 100644
index 0000000..caf6228
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/commentelement/impl/BasicCommentElementHandler.java
@@ -0,0 +1,135 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.commentelement.impl;
+
+
+
+import org.eclipse.wst.xml.core.internal.commentelement.CommentElementHandler;
+import org.eclipse.wst.xml.core.internal.commentelement.util.CommentElementFactory;
+import org.eclipse.wst.xml.core.internal.commentelement.util.TagScanner;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMAttr;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
+import org.eclipse.wst.xml.core.internal.provisional.document.ISourceGenerator;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+
+
+/**
+ */
+class BasicCommentElementHandler implements CommentElementHandler {
+
+	private String elementName;
+	private boolean isEmpty;
+
+	public BasicCommentElementHandler(String elementName, boolean isEmpty) {
+		super();
+		this.elementName = elementName;
+		this.isEmpty = isEmpty;
+	}
+
+
+	public Element createElement(Document document, String data, boolean isJSPTag) {
+		Element element = null;
+		String str = data.trim();
+		CommentElementFactory factory = new CommentElementFactory(document, isJSPTag, this);
+		if (str.charAt(0) == '/') { // end tag
+			TagScanner scanner = new TagScanner(str, 1); // skip '/'
+			String name = scanner.nextName();
+			if (name.equals(elementName)) {
+				element = factory.create(name, CommentElementFactory.IS_END);
+			}
+		} else { // start tag
+			TagScanner scanner = new TagScanner(str, 0);
+			String name = scanner.nextName();
+			if (name.equals(elementName)) {
+				element = factory.create(name, (isEmpty) ? CommentElementFactory.IS_EMPTY : CommentElementFactory.IS_START);
+				// set attributes
+				String attrName = scanner.nextName();
+				while (attrName != null) {
+					String attrValue = scanner.nextValue();
+					Attr attr = document.createAttribute(attrName);
+					if (attr != null) {
+						if (attrValue != null)
+							((IDOMAttr) attr).setValueSource(attrValue);
+						element.setAttributeNode(attr);
+					}
+					attrName = scanner.nextName();
+				}
+			}
+		}
+		return element;
+	}
+
+
+	public String generateEndTagContent(IDOMElement element) {
+		if (isEmpty) {
+			return null;
+		}
+		ISourceGenerator generator = element.getModel().getGenerator();
+		StringBuffer buffer = new StringBuffer();
+
+		buffer.append(" /"); //$NON-NLS-1$
+		String tagName = generator.generateTagName(element);
+		if (tagName != null) {
+			buffer.append(tagName);
+		}
+		buffer.append(' ');
+
+		return buffer.toString();
+	}
+
+	public String generateStartTagContent(IDOMElement element) {
+		ISourceGenerator generator = element.getModel().getGenerator();
+		StringBuffer buffer = new StringBuffer();
+
+		buffer.append(' ');
+		String tagName = generator.generateTagName(element);
+		if (tagName != null) {
+			buffer.append(tagName);
+		}
+
+		NamedNodeMap attributes = element.getAttributes();
+		int length = attributes.getLength();
+		for (int i = 0; i < length; i++) {
+			Attr attr = (Attr) attributes.item(i);
+			if (attr == null) {
+				continue;
+			}
+			buffer.append(' ');
+			String attrName = generator.generateAttrName(attr);
+			if (attrName != null) {
+				buffer.append(attrName);
+			}
+			String attrValue = generator.generateAttrValue(attr);
+			if (attrValue != null) {
+				// attr name only for HTML boolean and JSP
+				buffer.append('=');
+				buffer.append(attrValue);
+			}
+		}
+
+		buffer.append(' ');
+
+		return buffer.toString();
+	}
+
+	public boolean isCommentElement(IDOMElement element) {
+		return (element != null && element.getTagName().equals(elementName)) ? true : false;
+	}
+
+	public boolean isEmpty() {
+		return isEmpty;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/commentelement/impl/CommentElementConfiguration.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/commentelement/impl/CommentElementConfiguration.java
new file mode 100644
index 0000000..ef49f57
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/commentelement/impl/CommentElementConfiguration.java
@@ -0,0 +1,237 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2009 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.commentelement.impl;
+
+
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.InvalidRegistryObjectException;
+import org.eclipse.wst.xml.core.internal.Logger;
+import org.eclipse.wst.xml.core.internal.commentelement.CommentElementAdapter;
+import org.eclipse.wst.xml.core.internal.commentelement.CommentElementHandler;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+
+/**
+ */
+public class CommentElementConfiguration {
+	private Map fAttributes = null;
+	private boolean fCustom;
+	private IConfigurationElement fElement = null;
+
+	private boolean fEmpty;
+	private CommentElementHandler fHandler = null;
+	private String fID = null;
+	private boolean fJSPComment;
+	private String[] fPrefix = null;
+	private boolean fXMLComment;
+
+	CommentElementConfiguration(IConfigurationElement element) {
+		super();
+		fElement = element;
+		fCustom = element.getName().equalsIgnoreCase("handler-custom"); //$NON-NLS-1$
+
+		fillAttributes(element);
+
+		fXMLComment = fJSPComment = false;
+		String commentType = getProperty("commenttype"); //$NON-NLS-1$
+		if ("xml".equalsIgnoreCase(commentType)) { //$NON-NLS-1$
+			fXMLComment = true;
+		} else if ("jsp".equalsIgnoreCase(commentType)) { //$NON-NLS-1$
+			fJSPComment = true;
+		} else if ("both".equalsIgnoreCase(commentType)) { //$NON-NLS-1$
+			fXMLComment = fJSPComment = true;
+		}
+		String empty = getProperty("isempty"); //$NON-NLS-1$
+		fEmpty = Boolean.valueOf(empty).booleanValue(); //$NON-NLS-1$
+	}
+
+	public boolean acceptJSPComment() {
+		return fJSPComment;
+	}
+
+	public boolean acceptXMLComment() {
+		return fXMLComment;
+	}
+
+	public Element createElement(Document document, String data, boolean isJSPTag) {
+		IDOMElement element = (IDOMElement) getHandler().createElement(document, data, isJSPTag);
+		if (element != null) {
+			CommentElementAdapter adapter = (CommentElementAdapter) element.getAdapterFor(CommentElementAdapter.class);
+			if (adapter != null) {
+				adapter.setConfiguration(this);
+			}
+		}
+		return element;
+	}
+
+	private void fillAttributes(IConfigurationElement element) {
+		if (fAttributes == null) {
+			fAttributes = new HashMap();
+		} else {
+			fAttributes.clear();
+		}
+		String[] names = element.getAttributeNames();
+		if (names == null) {
+			return;
+		}
+		int length = names.length;
+		for (int i = 0; i < length; i++) {
+			String name = names[i];
+			fAttributes.put(name.toLowerCase(), element.getAttribute(name));
+		}
+	}
+
+	public CommentElementHandler getHandler() {
+		if (fHandler == null) {
+			if (fElement != null) {
+				try {
+					if (isCustom()) {
+						fHandler = (CommentElementHandler) fElement.createExecutableExtension("class"); //$NON-NLS-1$
+					} else {
+						String elementName = getProperty("elementname"); //$NON-NLS-1$
+						if (elementName != null) {
+							fHandler = new BasicCommentElementHandler(elementName, fEmpty);
+						}
+					}
+					//					((AbstractCommentElementHandler)fHandler).setElementPrefix(fElement.getAttribute("prefix"));
+				} catch (Exception e) {
+					// catch and log (and ignore) ANY exception created
+					// by executable extension.
+					Logger.logException(e);
+					fHandler = null;
+				}
+			}
+			if (fHandler == null) {
+				fHandler = new CommentElementHandler() {
+					public Element createElement(Document document, String data, boolean isJSPTag) {
+						return null;
+					}
+
+					public String generateEndTagContent(IDOMElement element) {
+						return null;
+					}
+
+					public String generateStartTagContent(IDOMElement element) {
+						return null;
+					}
+
+// removed in RC2, ro removed "unused" error/warning
+//					public String getElementPrefix() {
+//						return null;
+//					}
+
+					public boolean isCommentElement(IDOMElement element) {
+						return false;
+					}
+
+					public boolean isEmpty() {
+						return false;
+					}
+				};
+			}
+		}
+		return fHandler;
+	}
+
+	public String getHandlerID() {
+		if (fID == null) {
+			fID = getProperty("id"); //$NON-NLS-1$
+			if (fID == null) {
+				if (isCustom()) {
+					fID = getProperty("class"); //$NON-NLS-1$				
+				} else {
+					StringBuffer buf = new StringBuffer();
+					buf.append(fElement.getDeclaringExtension().getNamespace());
+					buf.append('.');
+					buf.append(getProperty("elementname")); //$NON-NLS-1$
+					fID = buf.toString();
+				}
+			}
+		}
+		return fID;
+	}
+
+
+	public String[] getPrefix() {
+		if (fPrefix == null) {
+			if (fElement != null) {
+				if (isCustom()) { // custom
+					IConfigurationElement[] prefixes = fElement.getChildren("startwith"); //$NON-NLS-1$	
+					if (prefixes != null) {
+						List prefixValues = new ArrayList(prefixes.length);
+						for (int i = 0; i < prefixes.length; i++) {
+							String prefix = prefixes[i].getAttribute("prefix"); //$NON-NLS-1$
+							if (prefix != null) {
+								prefixValues.add(prefix);
+							}
+							else {
+								try {
+									Logger.log(Logger.WARNING, "misconfigured comment element in" + fElement.getContributor().getName(), new IllegalArgumentException("startwith")); //$NON-NLS-1$ //$NON-NLS-2$
+								}
+								catch (InvalidRegistryObjectException e) {
+									// stale bundle?
+								}
+							}
+						}
+						if (!prefixValues.isEmpty()) {
+							fPrefix = (String[]) prefixValues.toArray(new String[prefixValues.size()]);
+						}
+					}
+				} else { // basic
+					String name = getProperty("elementname"); //$NON-NLS-1$
+					if (name != null) {
+						if (isEmpty()) {
+							fPrefix = new String[1];
+							fPrefix[0] = name;
+						} else {
+							fPrefix = new String[2];
+							fPrefix[0] = name;
+							fPrefix[1] = '/' + name;
+						}
+					}
+				}
+			}
+		}
+		if (fPrefix == null) {
+			fPrefix = new String[0];
+		}
+		return fPrefix;
+	}
+
+	public String getProperty(String name) {
+		return (fAttributes != null) ? (String) fAttributes.get(name) : null;
+	}
+
+	private boolean isCustom() {
+		return fCustom;
+	}
+
+	private boolean isEmpty() {
+		return fEmpty;
+	}
+
+	void setupCommentElement(IDOMElement element) {
+		element.setCommentTag(true);
+		CommentElementAdapter adapter = new CommentElementAdapter(false, fHandler);
+		adapter.setConfiguration(this);
+		element.addAdapter(adapter);
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/commentelement/impl/CommentElementRegistry.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/commentelement/impl/CommentElementRegistry.java
new file mode 100644
index 0000000..3516c9b
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/commentelement/impl/CommentElementRegistry.java
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2011 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.commentelement.impl;
+
+
+
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtensionPoint;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.wst.xml.core.internal.commentelement.CommentElementHandler;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
+
+
+/**
+ */
+public class CommentElementRegistry {
+
+	private static CommentElementRegistry fInstance = null;
+
+	public synchronized static CommentElementRegistry getInstance() {
+		if (fInstance == null) {
+			fInstance = new CommentElementRegistry();
+		}
+		return fInstance;
+	}
+
+	private String EXTENSION_POINT_ID = "commentElementHandler"; //$NON-NLS-1$
+	private CommentElementConfiguration[] fConfigurations = null;
+
+	private String PLUGIN_ID = "org.eclipse.wst.sse.core"; //$NON-NLS-1$
+
+	/**
+	 * Constructor for CommentElementRegistry.
+	 */
+	private CommentElementRegistry() {
+		super();
+	}
+
+	public synchronized CommentElementConfiguration[] getConfigurations() {
+		if (fConfigurations == null) {
+			IExtensionRegistry registry = Platform.getExtensionRegistry();
+			IExtensionPoint point = registry.getExtensionPoint(PLUGIN_ID, EXTENSION_POINT_ID);
+			if (point != null) {
+				IConfigurationElement[] elements = point.getConfigurationElements();
+				fConfigurations = new CommentElementConfiguration[elements.length];
+				for (int i = 0; i < elements.length; i++) {
+					fConfigurations[i] = new CommentElementConfiguration(elements[i]);
+				}
+			}
+			if (fConfigurations == null) {
+				fConfigurations = new CommentElementConfiguration[0];
+			}
+		}
+		return fConfigurations;
+	}
+
+	public boolean setupCommentElement(IDOMElement element) {
+		CommentElementConfiguration configurations[] = getConfigurations();
+		int length = configurations.length;
+		for (int i = 0; i < length; i++) {
+			CommentElementConfiguration conf = configurations[i];
+			boolean isJSP = element.isJSPTag();
+			if (isJSP && conf.acceptJSPComment() || !isJSP && conf.acceptXMLComment()) {
+				CommentElementHandler handler = conf.getHandler();
+				if (handler.isCommentElement(element)) {
+					conf.setupCommentElement(element);
+					return true;
+				}
+			}
+		}
+		return false;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/commentelement/util/CommentElementFactory.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/commentelement/util/CommentElementFactory.java
new file mode 100644
index 0000000..2ac27ba
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/commentelement/util/CommentElementFactory.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.commentelement.util;
+
+
+
+import org.eclipse.wst.xml.core.internal.commentelement.CommentElementAdapter;
+import org.eclipse.wst.xml.core.internal.commentelement.CommentElementHandler;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+
+/**
+ */
+public class CommentElementFactory {
+	public static final int IS_EMPTY = 4866;
+	public static final int IS_END = 1808;
+
+	public static final int IS_START = 28011;
+
+	private Document fDocument;
+	private CommentElementHandler fHandler;
+	private boolean fJSPTag;
+
+	/**
+	 * Constructor for CommentElementFactory.
+	 */
+	private CommentElementFactory() {
+		super();
+	}
+
+	public CommentElementFactory(Document document, boolean isJSPTag, CommentElementHandler handler) {
+		this();
+		fDocument = document;
+		fJSPTag = isJSPTag;
+		fHandler = handler;
+	}
+
+	public Element create(String name, int nodeType) {
+		IDOMElement element = (IDOMElement) fDocument.createElement(name);
+		if (element == null)
+			return null;
+		element.setCommentTag(true);
+		if (nodeType == IS_EMPTY) {
+			element.setEmptyTag(true);
+		}
+		element.setJSPTag(fJSPTag);
+
+		CommentElementAdapter adapter = new CommentElementAdapter((nodeType == IS_END), fHandler);
+		element.addAdapter(adapter);
+
+		return element;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/commentelement/util/TagScanner.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/commentelement/util/TagScanner.java
new file mode 100644
index 0000000..1d0d404
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/commentelement/util/TagScanner.java
@@ -0,0 +1,196 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.commentelement.util;
+
+
+
+/**
+ */
+public class TagScanner {
+
+	/**
+	 */
+	private static boolean isEqual(char c) {
+		return (c == '=');
+	}
+
+	/**
+	 */
+	private static boolean isQuote(char c) {
+		return (c == '"' || c == '\'');
+	}
+
+	/**
+	 */
+	private static boolean isSpace(char c) {
+		return Character.isWhitespace(c);
+	}
+
+	private int length = 0;
+	private int memOffset = 0;
+	private int offset = 0;
+	private boolean oneLine = false;
+
+	private String tag = null;
+
+	/**
+	 */
+	public TagScanner(String tag, int offset) {
+		super();
+
+		this.tag = tag;
+		this.offset = offset;
+		this.memOffset = -1;
+		if (tag != null)
+			this.length = tag.length();
+	}
+
+	/**
+	 */
+	public TagScanner(String tag, int offset, boolean oneLine) {
+		this(tag, offset);
+
+		this.oneLine = oneLine;
+	}
+
+	/**
+	 */
+	public int getNextOffset() {
+		int i;
+		char c;
+		for (i = offset; i < length; i++) {
+			c = tag.charAt(i);
+			if (isEnd(c))
+				break;
+			if (isQuote(c)) {
+				i++;
+				break;
+			}
+			if (!isSpace(c) && !isEqual(c))
+				break;
+		}
+		return i;
+	}
+
+	/**
+	 */
+	public int getOffset() {
+		return this.memOffset;
+	}
+
+	/**
+	 */
+	private final boolean isEnd(char c) {
+		return (this.oneLine && (c == '\r' || c == '\n'));
+	}
+
+	/**
+	 */
+	public boolean isNewLine() {
+		if (oneLine)
+			return false;
+		char c;
+		for (int i = memOffset - 1; 0 <= i; i--) {
+			c = tag.charAt(i);
+			if (c == '\r' || c == '\n')
+				return true;
+			if (!isSpace(c))
+				return false;
+		}
+		return false;
+	}
+
+	/**
+	 */
+	private char nextChar() {
+		for (; this.offset < this.length; this.offset++) {
+			char c = this.tag.charAt(this.offset);
+			if (isEnd(c))
+				break;
+			if (!isSpace(c))
+				return c;
+		}
+		return 0;
+	}
+
+	/**
+	 */
+	public String nextName() {
+		if (this.tag == null)
+			return null;
+		if (this.offset >= this.length)
+			return null;
+
+		if (nextChar() == 0)
+			return null;
+
+		int nameOffset = this.offset;
+		for (; this.offset < this.length; this.offset++) {
+			char c = this.tag.charAt(this.offset);
+			if (isEnd(c) || isSpace(c))
+				break;
+			if (isEqual(c) && this.offset > nameOffset)
+				break;
+		}
+		if (this.offset == nameOffset)
+			return null;
+
+		this.memOffset = nameOffset;
+		return this.tag.substring(nameOffset, this.offset);
+	}
+
+	/**
+	 */
+	public String nextValue() {
+		if (this.tag == null)
+			return null;
+		if (this.offset >= this.length)
+			return null;
+
+		char seperator = nextChar();
+		if (!isEqual(seperator))
+			return null;
+		this.offset++; // skip '='
+		char quote = nextChar();
+		if (quote == 0)
+			return null;
+		if (isQuote(quote))
+			this.offset++;
+		else
+			quote = 0;
+
+		int valueOffset = this.offset;
+		for (; this.offset < this.length; this.offset++) {
+			char c = this.tag.charAt(this.offset);
+			if (isEnd(c)) {
+				quote = 0;
+				break;
+			}
+			if (quote == 0) {
+				if (isSpace(c))
+					break;
+			} else {
+				if (c == quote)
+					break;
+			}
+		}
+		int valueEnd = this.offset;
+		if (quote != 0 && this.offset < this.length)
+			this.offset++;
+		if (valueEnd == valueOffset)
+			return null;
+
+		this.memOffset = valueOffset;
+		return this.tag.substring(valueOffset, valueEnd);
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/AbstractResourceEncodingDetector.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/AbstractResourceEncodingDetector.java
new file mode 100644
index 0000000..fcbcbea
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/AbstractResourceEncodingDetector.java
@@ -0,0 +1,258 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contenttype;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.nio.charset.Charset;
+import java.nio.charset.IllegalCharsetNameException;
+import java.nio.charset.UnsupportedCharsetException;
+
+import org.eclipse.core.resources.IStorage;
+import org.eclipse.core.runtime.CoreException;
+
+import org.eclipse.wst.sse.core.internal.encoding.CodedIO;
+import org.eclipse.wst.sse.core.internal.encoding.EncodingMemento;
+import org.eclipse.wst.sse.core.internal.encoding.IResourceCharsetDetector;
+
+
+public abstract class AbstractResourceEncodingDetector implements IResourceCharsetDetector {
+
+	protected EncodingMemento fEncodingMemento;
+
+	protected boolean fHeaderParsed;
+
+	protected Reader fReader;
+
+	/**
+	 *  
+	 */
+	public AbstractResourceEncodingDetector() {
+		super();
+	}
+
+	/**
+	 * Note: once this instance is created, trace info still needs to be
+	 * appended by caller, depending on the context its created.
+	 */
+	private void createEncodingMemento(String detectedCharsetName) {
+		fEncodingMemento = new EncodingMemento();
+		fEncodingMemento.setJavaCharsetName(getAppropriateJavaCharset(detectedCharsetName));
+		fEncodingMemento.setDetectedCharsetName(detectedCharsetName);
+		// TODO: if detectedCharset and spec default is
+		// null, need to use "work
+		// bench based" defaults.
+		fEncodingMemento.setAppropriateDefault(getSpecDefaultEncoding());
+	}
+
+	/**
+	 * convience method all subclasses can use (but not override)
+	 * 
+	 * @param detectedCharsetName
+	 * @param reason
+	 */
+	final protected void createEncodingMemento(String detectedCharsetName, String reason) {
+		createEncodingMemento(detectedCharsetName);
+	}
+
+	/**
+	 * convience method all subclasses can use (but not override)
+	 */
+	final protected void ensureInputSet() {
+		if (fReader == null) {
+			throw new IllegalStateException("input must be set before use"); //$NON-NLS-1$
+		}
+	}
+
+	/**
+	 * This method can return null, if invalid charset name (in which case
+	 * "appropriateDefault" should be used, if a name is really need for some
+	 * "save anyway" cases).
+	 * 
+	 * @param detectedCharsetName
+	 * @return
+	 */
+	private String getAppropriateJavaCharset(String detectedCharsetName) {
+		String result = null;
+		// 1. Check explicit mapping overrides from
+		// property file -- its here we pick up "rules" for cases
+		// that are not even in Java
+		result = CodedIO.checkMappingOverrides(detectedCharsetName);
+		// 2. Use the "canonical" name from JRE mappings
+		// Note: see Charset JavaDoc, the name you get one
+		// with can be alias,
+		// the name you get back is "standard" name.
+		Charset javaCharset = null;
+		try {
+			javaCharset = Charset.forName(detectedCharsetName);
+		} catch (UnsupportedCharsetException e) {
+			// only set invalid, if result is same as detected -- they won't
+			// be equal if
+			// overridden
+			if (result != null && result.equals(detectedCharsetName)) {
+				fEncodingMemento.setInvalidEncoding(detectedCharsetName);
+			}
+		} catch (IllegalCharsetNameException e) {
+			// only set invalid, if result is same as detected -- they won't
+			// be equal if
+			// overridden
+			if (result != null && result.equals(detectedCharsetName)) {
+				fEncodingMemento.setInvalidEncoding(detectedCharsetName);
+			}
+		}
+		// give priority to java cononical name, if present
+		if (javaCharset != null) {
+			result = javaCharset.name();
+			// but still allow overrides
+			result = CodedIO.checkMappingOverrides(result);
+		}
+		return result;
+	}
+
+	public String getEncoding() throws IOException {
+		return getEncodingMemento().getDetectedCharsetName();
+	}
+
+	// to ensure consist overall rules used, we'll mark as
+	// final,
+	// and require subclasses to provide certain pieces of
+	// the
+	// implementation
+	public EncodingMemento getEncodingMemento() throws IOException {
+		ensureInputSet();
+		if (!fHeaderParsed) {
+			parseInput();
+			// we keep track of if header's already been
+			// parse, so can make
+			// multiple 'get' calls, without causing
+			// reparsing.
+			fHeaderParsed = true;
+			// Note: there is a "hidden assumption" here
+			// that an empty
+			// string in content should be treated same as
+			// not present.
+		}
+		if (fEncodingMemento == null) {
+			handleSpecDefault();
+		}
+		if (fEncodingMemento == null) {
+			// safty net
+			fEncodingMemento = new NullMemento();
+		}
+		return fEncodingMemento;
+	}
+
+	/**
+	 * This is to return a default encoding -- as specified by an industry
+	 * content type spec -- when not present in the stream, for example, XML
+	 * specifies UTF-8, JSP specifies ISO-8859-1. This method should return
+	 * null if there is no such "spec default".
+	 */
+	abstract public String getSpecDefaultEncoding();
+
+	public EncodingMemento getSpecDefaultEncodingMemento() {
+		resetAll();
+		EncodingMemento result = null;
+		String enc = getSpecDefaultEncoding();
+		if (enc != null) {
+			createEncodingMemento(enc, EncodingMemento.DEFAULTS_ASSUMED_FOR_EMPTY_INPUT);
+			fEncodingMemento.setAppropriateDefault(enc);
+			result = fEncodingMemento;
+		}
+		return result;
+	}
+
+	private void handleSpecDefault() {
+		String encodingName;
+		encodingName = getSpecDefaultEncoding();
+		if (encodingName != null) {
+			//createEncodingMemento(encodingName,
+			// EncodingMemento.USED_CONTENT_TYPE_DEFAULT);
+			fEncodingMemento = new EncodingMemento();
+			fEncodingMemento.setJavaCharsetName(encodingName);
+			fEncodingMemento.setAppropriateDefault(encodingName);
+		}
+	}
+
+	/**
+	 * Every subclass must provide a way to parse the input. This method has
+	 * several critical responsibilities:
+	 * <li>set the fEncodingMemento field appropriately, according to the
+	 * results of the parse of fReader.</li>
+	 * <li>set fHarderParsed to true, to avoid wasted re-parsing.</li>
+	 */
+	abstract protected void parseInput() throws IOException;
+
+	/**
+	 *  
+	 */
+	protected void resetAll() {
+		fReader = null;
+		fHeaderParsed = false;
+		fEncodingMemento = null;
+	}
+
+	/**
+	 *  
+	 */
+	public void set(InputStream inputStream) {
+		resetAll();
+		fReader = new ByteReader(inputStream);
+		try {
+			fReader.mark(CodedIO.MAX_MARK_SIZE);
+		} catch (IOException e) {
+			// impossible, since we know ByteReader
+			// supports marking
+			throw new Error(e);
+		}
+	}
+
+	/**
+	 *  
+	 */
+	public void set(IStorage iStorage) throws CoreException {
+		resetAll();
+		InputStream inputStream = iStorage.getContents();
+		InputStream resettableStream = new BufferedInputStream(inputStream, CodedIO.MAX_BUF_SIZE);
+		resettableStream.mark(CodedIO.MAX_MARK_SIZE);
+		set(resettableStream);
+		// TODO we'll need to "remember" IFile, or
+		// get its (or its project's) settings, in case
+		// those are needed to handle cases when the
+		// encoding is not in the file stream.
+	}
+
+	/**
+	 * Note: this is not part of interface to help avoid confusion ... it
+	 * expected this Reader is a well formed character reader ... that is, its
+	 * all ready been determined to not be a unicode marked input stream. And,
+	 * its assumed to be in the correct position, at position zero, ready to
+	 * read first character.
+	 */
+	public void set(Reader reader) {
+		resetAll();
+		fReader = reader;
+		if (!fReader.markSupported()) {
+			fReader = new BufferedReader(fReader);
+		}
+		try {
+			fReader.mark(CodedIO.MAX_MARK_SIZE);
+		} catch (IOException e) {
+			// impossble, since we just checked if markable
+			throw new Error(e);
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/ByteReader.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/ByteReader.java
new file mode 100644
index 0000000..3d50b3f
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/ByteReader.java
@@ -0,0 +1,108 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contenttype;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+
+import org.eclipse.wst.sse.core.internal.encoding.CodedIO;
+
+/**
+ * This is an "adapter" class, simply to get in input stream to act like a
+ * reader. We could not use InputStreamReader directly because its internal
+ * buffers are not controllable, and it sometimes pulls too much out of input
+ * stream (even when it wasn't needed for our purposes).
+ * 
+ * The use of this class is highly specialized and by not means meant to be
+ * general purpose. Its use is restricted to those cases where the input
+ * stream can be regarded as ascii just long enough to determine what the real
+ * encoding should be.
+ */
+
+public class ByteReader extends Reader {
+
+	public static final int DEFAULT_BUFFER_SIZE = CodedIO.MAX_BUF_SIZE;
+
+	protected byte[] fBuffer;
+
+	protected InputStream fInputStream;
+
+	protected ByteReader() {
+		super();
+	}
+
+	public ByteReader(InputStream inputStream) {
+		this(inputStream, DEFAULT_BUFFER_SIZE);
+		if (!inputStream.markSupported()) {
+			throw new IllegalArgumentException("ByteReader is required to have a resettable stream"); //$NON-NLS-1$
+		}
+	}
+
+	public ByteReader(InputStream inputStream, int size) {
+		fInputStream = inputStream;
+		if (!inputStream.markSupported()) {
+			throw new IllegalArgumentException("ByteReader is required to have a resettable stream"); //$NON-NLS-1$
+		}
+		fBuffer = new byte[size];
+
+	}
+
+	public void close() throws IOException {
+		fInputStream.close();
+	}
+
+	public void mark(int readAheadLimit) throws IOException {
+		fInputStream.mark(readAheadLimit);
+	}
+
+	public boolean markSupported() {
+		return true;
+	}
+
+	public int read() throws IOException {
+		int b0 = fInputStream.read();
+		return (b0 & 0x00FF);
+	}
+
+	public int read(char ch[], int offset, int length) throws IOException {
+		if (length > fBuffer.length) {
+			length = fBuffer.length;
+		}
+
+		int count = fInputStream.read(fBuffer, 0, length);
+
+		for (int i = 0; i < count; i++) {
+			int b0 = fBuffer[i];
+			// the 0x00FF is to "lose" the negative bits filled in the byte to
+			// int conversion
+			// (and which would be there if cast directly from byte to char).
+			char c0 = (char) (b0 & 0x00FF);
+			ch[offset + i] = c0;
+		}
+		return count;
+	}
+
+	public boolean ready() throws IOException {
+		return fInputStream.available() > 0;
+	}
+
+	public void reset() throws IOException {
+		fInputStream.reset();
+	}
+
+	public long skip(long n) throws IOException {
+		return fInputStream.skip(n);
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/ContentDescriberForXML.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/ContentDescriberForXML.java
new file mode 100644
index 0000000..9e56e70
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/ContentDescriberForXML.java
@@ -0,0 +1,264 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contenttype;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+
+import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.core.runtime.content.IContentDescriber;
+import org.eclipse.core.runtime.content.IContentDescription;
+import org.eclipse.core.runtime.content.ITextContentDescriber;
+import org.eclipse.wst.sse.core.internal.encoding.EncodingMemento;
+import org.eclipse.wst.sse.core.internal.encoding.IContentDescriptionExtended;
+import org.eclipse.wst.sse.core.internal.encoding.IResourceCharsetDetector;
+
+
+public final class ContentDescriberForXML implements ITextContentDescriber {
+	private final static QualifiedName[] SUPPORTED_OPTIONS = {IContentDescription.CHARSET, IContentDescription.BYTE_ORDER_MARK, IContentDescriptionExtended.DETECTED_CHARSET, IContentDescriptionExtended.UNSUPPORTED_CHARSET, IContentDescriptionExtended.APPROPRIATE_DEFAULT};
+	/**
+	 * <code>restrictedMode</code> is used just for testing/experiments.
+	 * 
+	 * If in restrictedMode, our "custom" contentType is seen as valid only in
+	 * cases that the platform's standard one does not cover.
+	 */
+	private final static boolean restrictedMode = true;
+	private IResourceCharsetDetector getDetector() {
+			return new XMLResourceEncodingDetector();
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.core.runtime.content.IContentDescriber#describe(java.io.InputStream,
+	 *      org.eclipse.core.runtime.content.IContentDescription)
+	 */
+	public int describe(InputStream contents, IContentDescription description) throws IOException {
+		// for this special case, always assume invalid, unless
+		// our special circumstances are met.
+		int result = IContentDescriber.INVALID;
+
+		if (description == null) {
+			// purely request for validty
+			result = determineValidity(result, contents);
+		}
+		else {
+			result = calculateSupportedOptions(result, contents, description);
+		}
+		return result;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.core.runtime.content.ITextContentDescriber#describe(java.io.Reader,
+	 *      org.eclipse.core.runtime.content.IContentDescription)
+	 */
+	public int describe(Reader contents, IContentDescription description) throws IOException {
+		// for this special case, always assume invalid, unless
+		// our special circumstances are met.
+		int result = IContentDescriber.INVALID;
+
+		if (description == null) {
+			// purely request for validty
+			result = determineValidity(result, contents);
+		}
+		else {
+			result = calculateSupportedOptions(result, contents, description);
+		}
+		return result;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.core.runtime.content.IContentDescriber#getSupportedOptions()
+	 */
+	public QualifiedName[] getSupportedOptions() {
+
+		return SUPPORTED_OPTIONS;
+	}
+
+	private int calculateSupportedOptions(int result, InputStream contents, IContentDescription description) throws IOException {
+		int returnResult = result;
+		if (isRelevent(description)) {
+			IResourceCharsetDetector detector = getDetector();
+			contents.reset();
+			detector.set(contents);
+			returnResult = handleCalculations(result, description, detector);
+		}
+		return returnResult;
+	}
+
+	private int determineValidity(int result, InputStream contents) throws IOException {
+		int returnResult = result;
+		IResourceCharsetDetector detector = getDetector();
+		contents.reset();
+		detector.set(contents);
+		returnResult = determineValidity(detector, returnResult);
+		return returnResult;
+	}
+	private int determineValidity(int result, Reader contents) throws IOException {
+		int returnResult = result;
+		IResourceCharsetDetector detector = getDetector();
+		contents.reset();
+		detector.set(contents);
+		returnResult = determineValidity(detector, returnResult);
+		return returnResult;
+	}
+	/**
+	 * @param contents
+	 * @param description
+	 * @throws IOException
+	 */
+	private int calculateSupportedOptions(int result, Reader contents, IContentDescription description) throws IOException {
+		int returnResult = result;
+		if (isRelevent(description)) {
+			IResourceCharsetDetector detector = getDetector();
+			detector.set(contents);
+			returnResult = handleCalculations(result, description, detector);
+		}
+		return returnResult;
+	}
+
+	private void handleDetectedSpecialCase(IContentDescription description, Object detectedCharset, Object javaCharset) {
+		// since equal, we don't need to add, but if our detected version is
+		// different than
+		// javaCharset, then we should add it. This will happen, for example,
+		// if there's
+		// differences in case, or differences due to override properties
+		if (detectedCharset != null) {
+			// if (!detectedCharset.equals(javaCharset)) {
+			// description.setProperty(IContentDescriptionExtended.DETECTED_CHARSET,
+			// detectedCharset);
+			// }
+
+			// Once we detected a charset, we should set the property even
+			// though it's the same as javaCharset
+			// because there are clients that rely on this property to
+			// determine if the charset is actually detected in file or not.
+			description.setProperty(IContentDescriptionExtended.DETECTED_CHARSET, detectedCharset);
+		}
+	}
+
+	/**
+	 * @param description
+	 * @return
+	 */
+	private boolean isRelevent(IContentDescription description) {
+		boolean result = false;
+		if (description == null)
+			result = false;
+		else if (description.isRequested(IContentDescription.BYTE_ORDER_MARK))
+			result = true;
+		else if (description.isRequested(IContentDescription.CHARSET))
+			result = true;
+		else if (description.isRequested(IContentDescriptionExtended.APPROPRIATE_DEFAULT))
+			result = true;
+		else if (description.isRequested(IContentDescriptionExtended.DETECTED_CHARSET))
+			result = true;
+		else if (description.isRequested(IContentDescriptionExtended.UNSUPPORTED_CHARSET))
+			result = true;
+		return result;
+	}
+
+	/**
+	 * @param description
+	 * @param detector
+	 * @throws IOException
+	 */
+	private int handleCalculations(int result, IContentDescription description, IResourceCharsetDetector detector) throws IOException {
+		int returnResult = result;
+		EncodingMemento encodingMemento = ((XMLResourceEncodingDetector) detector).getEncodingMemento();
+		if (description != null) {
+			// TODO: I need to verify to see if this BOM work is always done
+			// by text type.
+			Object detectedByteOrderMark = encodingMemento.getUnicodeBOM();
+			if (detectedByteOrderMark != null) {
+				Object existingByteOrderMark = description.getProperty(IContentDescription.BYTE_ORDER_MARK);
+				// not sure why would ever be different, so if is different,
+				// may
+				// need to "push" up into base.
+				if (!detectedByteOrderMark.equals(existingByteOrderMark))
+					description.setProperty(IContentDescription.BYTE_ORDER_MARK, detectedByteOrderMark);
+			}
+
+
+			if (!encodingMemento.isValid()) {
+				// note: after setting here, its the mere presence of
+				// IContentDescriptionExtended.UNSUPPORTED_CHARSET
+				// in the resource's description that can be used to determine
+				// if invalid in those cases, the "detected" property contains
+				// an "appropriate default" to use.
+				description.setProperty(IContentDescriptionExtended.UNSUPPORTED_CHARSET, encodingMemento.getInvalidEncoding());
+				description.setProperty(IContentDescriptionExtended.APPROPRIATE_DEFAULT, encodingMemento.getAppropriateDefault());
+			}
+
+			Object detectedCharset = encodingMemento.getDetectedCharsetName();
+			Object javaCharset = encodingMemento.getJavaCharsetName();
+
+			// we always include detected, if its different than java
+			handleDetectedSpecialCase(description, detectedCharset, javaCharset);
+
+			if (javaCharset != null) {
+				Object existingCharset = description.getProperty(IContentDescription.CHARSET);
+				if (javaCharset.equals(existingCharset)) {
+					handleDetectedSpecialCase(description, detectedCharset, javaCharset);
+				}
+				else {
+					// we may need to add what we found, but only need to add
+					// if different from the default
+					Object defaultCharset = detector.getSpecDefaultEncoding();
+					if (defaultCharset != null) {
+						if (!defaultCharset.equals(javaCharset)) {
+							description.setProperty(IContentDescription.CHARSET, javaCharset);
+						}
+					}
+					else {
+						// assuming if there is no spec default, we always
+						// need to add.
+						// TODO: this is probably a dead branch in current
+						// code, should re-examine for removal.
+						description.setProperty(IContentDescription.CHARSET, javaCharset);
+					}
+				}
+			}
+		}
+
+		returnResult = determineValidity(detector, returnResult);
+		return returnResult;
+	}
+
+	private int determineValidity(IResourceCharsetDetector detector, int returnResult) {
+		// we always expect XMLResourceEncodingDetector, but just to make safe
+		// cast.
+		if (detector instanceof XMLResourceEncodingDetector) {
+			XMLResourceEncodingDetector xmlResourceDetector = (XMLResourceEncodingDetector) detector;
+			if (xmlResourceDetector.isDeclDetected()) {
+				if (restrictedMode) {
+					// if there is no initial whitespace, then platform's
+					// default one will do.
+					if (xmlResourceDetector.hasInitialWhiteSpace()) {
+						returnResult = IContentDescriber.VALID;
+					}
+				}
+				else {
+					returnResult = IContentDescriber.VALID;
+				}
+			}
+		}
+		return returnResult;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/EncodingParserConstants.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/EncodingParserConstants.java
new file mode 100644
index 0000000..d4542a4
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/EncodingParserConstants.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contenttype;
+
+
+public interface EncodingParserConstants {
+
+	final String EOF = "EOF"; //$NON-NLS-1$
+	final String InvalidTerminatedStringValue = "InvalidTerminatedStringValue"; //$NON-NLS-1$
+	final String InvalidTermintatedUnDelimitedStringValue = "InvalidTermintatedUnDelimitedStringValue"; //$NON-NLS-1$
+	final String MAX_CHARS_REACHED = "MAX_CHARS_REACHED"; //$NON-NLS-1$
+	final String StringValue = "strval"; //$NON-NLS-1$
+	final String UnDelimitedStringValue = "UnDelimitedStringValue"; //$NON-NLS-1$
+	public final String UTF16BE = "UTF16BE"; //$NON-NLS-1$
+	public final String UTF16LE = "UTF16LE"; //$NON-NLS-1$
+
+
+	public final String UTF83ByteBOM = "UTF83ByteBOM"; //$NON-NLS-1$
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/HeadParserToken.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/HeadParserToken.java
new file mode 100644
index 0000000..0f14b8b
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/HeadParserToken.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contenttype;
+
+public class HeadParserToken {
+	private int fStart;
+
+	private String fText;
+	private String fType;
+
+	protected HeadParserToken() {
+		super();
+	}
+
+	public HeadParserToken(String type, int start, String text) {
+		this();
+		fType = type;
+		fStart = start;
+		fText = text;
+
+	}
+
+	public String getText() {
+		return fText;
+	}
+
+	public String getType() {
+		return fType;
+	}
+
+	public String toString() {
+		return ("text: " + fText + " offset: " + fStart + " type: " + fType); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/IntStack.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/IntStack.java
new file mode 100644
index 0000000..52dbae6
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/IntStack.java
@@ -0,0 +1,114 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contenttype;
+
+/*
+ * 
+ * A non-resizable class implementing the behavior of java.util.Stack, but
+ * directly for the <code> integer </code> primitive.
+ */
+import java.util.EmptyStackException;
+
+public class IntStack {
+	private int[] list = null;
+
+	private int size = 0;
+
+	public IntStack() {
+		this(100);
+	}
+
+	public IntStack(int maxdepth) {
+		super();
+		list = new int[maxdepth];
+		initialize();
+	}
+
+	public void clear() {
+		initialize();
+	}
+
+	public boolean empty() {
+		return size == 0;
+	}
+
+	public int get(int slot) {
+		return list[slot];
+	}
+
+	private void initialize() {
+		for (int i = 0; i < list.length; i++)
+			list[i] = -1;
+	}
+
+	/**
+	 * Returns the int at the top of the stack without removing it
+	 * 
+	 * @return int at the top of this stack.
+	 * @exception EmptyStackException
+	 *                when empty.
+	 */
+	public int peek() {
+		if (size == 0)
+			throw new EmptyStackException();
+		return list[size - 1];
+	}
+
+	/**
+	 * Removes and returns the int at the top of the stack
+	 * 
+	 * @return int at the top of this stack.
+	 * @exception EmptyStackException
+	 *                when empty.
+	 */
+	public int pop() {
+		int value = peek();
+		list[size - 1] = -1;
+		size--;
+		return value;
+	}
+
+	/**
+	 * Pushes an item onto the top of this stack.
+	 * 
+	 * @param newValue -
+	 *            the int to be pushed onto this stack.
+	 * @return the <code>newValue</code> argument.
+	 */
+	public int push(int newValue) {
+		if (size == list.length) {
+			throw new StackOverflowError();
+		}
+		list[size++] = newValue;
+		return newValue;
+	}
+
+	public int size() {
+		return size;
+	}
+	
+	/* (non-Javadoc)
+	 * @see java.lang.Object#toString()
+	 */
+	public String toString() {
+		StringBuffer s = new StringBuffer(getClass().getName() + ":" +size + " [");
+		for (int i = 0; i < size; i++) {
+			s.append(list[i]);
+			if(i < size - 1) {
+				s.append(", ");
+			}
+		}
+		s.append("]");
+		return s.toString();
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/NullMemento.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/NullMemento.java
new file mode 100644
index 0000000..23f7462
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/NullMemento.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contenttype;
+
+import org.eclipse.wst.sse.core.internal.encoding.EncodingMemento;
+import org.eclipse.wst.sse.core.internal.encoding.NonContentBasedEncodingRules;
+
+
+
+/**
+ * This class can be used in place of an EncodingMemento (its super class),
+ * when there is not in fact ANY encoding information. For example, when a
+ * structuredDocument is created directly from a String
+ */
+public class NullMemento extends EncodingMemento {
+	/**
+	 *  
+	 */
+	public NullMemento() {
+		super();
+		String defaultCharset = NonContentBasedEncodingRules.useDefaultNameRules(null);
+		setJavaCharsetName(defaultCharset);
+		setAppropriateDefault(defaultCharset);
+		setDetectedCharsetName(null);
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/XMLDeclDetector.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/XMLDeclDetector.java
new file mode 100644
index 0000000..4bc3552
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/XMLDeclDetector.java
@@ -0,0 +1,156 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     David Carver (STAR) - bug 297006 - String Comparison
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contenttype;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+
+public class XMLDeclDetector {
+	private static final int MAX_BUF_SIZE = 1024 * 8;
+	private static final int MAX_MARK_SIZE = 1024 * 8;
+	protected boolean fHeaderParsed;
+	private boolean fIsXML;
+	protected Reader fReader;
+	//private boolean DEBUG = false;
+	private XMLHeadTokenizer fTokenizer;
+
+	private boolean canHandleAsUnicodeStream(String tokenType) {
+		boolean canHandleAsUnicodeStream = false;
+		if (EncodingParserConstants.UTF83ByteBOM.equals(tokenType)) {
+			canHandleAsUnicodeStream = true;
+			//fUnicode = "UTF-8"; //$NON-NLS-1$
+		} else if (EncodingParserConstants.UTF16BE.equals(tokenType)) {
+			canHandleAsUnicodeStream = true;
+			//fUnicode = "UTF-16BE"; //$NON-NLS-1$
+		} else if (EncodingParserConstants.UTF16LE.equals(tokenType)) {
+			canHandleAsUnicodeStream = true;
+			//fUnicode = "UTF-16"; //$NON-NLS-1$
+		}
+		return canHandleAsUnicodeStream;
+	}
+
+	final private void ensureInputSet() {
+		if (fReader == null) {
+			throw new IllegalStateException("input must be set before use"); //$NON-NLS-1$
+		}
+	}
+
+	//private String fUnicode;
+
+	/**
+	 * @return Returns the tokenizer.
+	 */
+	private XMLHeadTokenizer getTokenizer() {
+		if (fTokenizer == null) {
+			fTokenizer = new XMLHeadTokenizer();
+		}
+		return fTokenizer;
+	}
+
+	/**
+	 * @return Returns the isXML.
+	 */
+	public boolean isXML() throws IOException {
+		ensureInputSet();
+		if (!fHeaderParsed) {
+			parseInput();
+		}
+		return fIsXML;
+	}
+
+	private void parseInput() throws IOException {
+		XMLHeadTokenizer tokenizer = getTokenizer();
+		tokenizer.reset(fReader);
+		HeadParserToken token = null;
+		String tokenType = null;
+		do {
+			token = tokenizer.getNextToken();
+			tokenType = token.getType();
+			if (canHandleAsUnicodeStream(tokenType)) {
+				fReader.reset();
+				// this is (obviously) not always true.
+				// TODO: need to fix so we "remember" original iFile or
+				// inputstream, and
+				// create appropriate InputStreamReader.
+				// I'm not sure what to do for the set(reader) case ... if its
+				// even relevent.
+				// plus, ensure against infinite loops!
+				fIsXML = true;
+				//fReader = new InputStreamReader(fReader, fUnicode);
+				// parseInput();
+			} else {
+				if (XMLHeadTokenizerConstants.XMLDelEncoding.equals(tokenType)) {
+					fIsXML = true;
+				}
+			}
+		} while (tokenizer.hasMoreTokens());
+
+	}
+
+	private void resetAll() {
+		fReader = null;
+		fHeaderParsed = false;
+		fIsXML = false;
+		//fUnicode = null;
+
+	}
+
+	public void set(IFile iFile) throws CoreException {
+		resetAll();
+		InputStream inputStream = iFile.getContents(true);
+		InputStream resettableStream = new BufferedInputStream(inputStream, MAX_BUF_SIZE);
+		resettableStream.mark(MAX_MARK_SIZE);
+		set(resettableStream);
+	}
+
+	public void set(InputStream inputStream) {
+		resetAll();
+		fReader = new ByteReader(inputStream);
+		try {
+			fReader.mark(MAX_MARK_SIZE);
+		} catch (IOException e) {
+			// impossible, since we know ByteReader supports marking
+			throw new Error(e);
+		}
+	}
+
+	/**
+	 * Note: this is not part of interface to help avoid confusion ... it
+	 * expected this Reader is a well formed character reader ... that is, its
+	 * all ready been determined to not be a unicode marked input stream. And,
+	 * its assumed to be in the correct position, at position zero, ready to
+	 * read first character.
+	 */
+	public void set(Reader reader) {
+		resetAll();
+		fReader = reader;
+		if (!fReader.markSupported()) {
+			fReader = new BufferedReader(fReader);
+		}
+
+		try {
+			fReader.mark(MAX_MARK_SIZE);
+		} catch (IOException e) {
+			// impossble, since we just checked if markable
+			throw new Error(e);
+		}
+
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/XMLHeadTokenizer.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/XMLHeadTokenizer.java
new file mode 100644
index 0000000..76fb40b
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/XMLHeadTokenizer.java
@@ -0,0 +1,1451 @@
+/* The following code was generated by JFlex 1.4.2 on 7/28/08 9:29 AM */
+
+/*******************************************************************************
+ * Copyright (c) 2005, 2008 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
+ *******************************************************************************/
+/*nlsXXX*/
+package org.eclipse.wst.xml.core.internal.contenttype;
+import java.io.IOException;
+import java.io.Reader;
+
+import org.eclipse.wst.xml.core.internal.contenttype.EncodingParserConstants;
+import org.eclipse.wst.xml.core.internal.contenttype.XMLHeadTokenizerConstants;
+
+
+
+/**
+ * This class is a scanner generated by 
+ * <a href="http://www.jflex.de/">JFlex</a> 1.4.2
+ * on 7/28/08 9:29 AM from the specification file
+ * <tt>D:/workspaces/wtp301/workspace/org.eclipse.wst.xml.core/DevTimeSupport/HeadParsers/XMLHeadTokenizer.jFlex</tt>
+ */
+public class XMLHeadTokenizer {
+
+  /** This character denotes the end of file */
+  public static final int YYEOF = -1;
+
+  /** initial size of the lookahead buffer */
+  private static final int ZZ_BUFFERSIZE = 8192;
+
+  /** lexical states */
+  public static final int YYINITIAL = 0;
+  public static final int UnDelimitedString = 10;
+  public static final int DQ_STRING = 6;
+  public static final int SQ_STRING = 8;
+  public static final int ST_XMLDecl = 2;
+  public static final int QuotedAttributeValue = 4;
+
+  /**
+   * ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l
+   * ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l
+   *                  at the beginning of a line
+   * l is of the form l = 2*k, k a non negative integer
+   */
+  private static final int ZZ_LEXSTATE[] = { 
+     0,  1,  2,  2,  3,  3,  4,  4,  5,  5,  6, 6
+  };
+
+  /** 
+   * Translates characters to character classes
+   */
+  private static final String ZZ_CMAP_PACKED = 
+    "\1\11\10\0\1\6\1\10\2\0\1\7\22\0\1\6\1\0\1\33"+
+    "\2\0\1\35\1\0\1\34\24\0\1\13\1\12\1\32\1\14\3\0"+
+    "\1\27\1\30\1\21\1\0\1\31\1\0\1\24\2\0\1\17\1\16"+
+    "\1\26\1\25\2\0\1\22\1\23\2\0\1\20\1\0\1\15\12\0"+
+    "\1\27\1\30\1\21\1\0\1\31\1\0\1\24\2\0\1\17\1\16"+
+    "\1\26\1\25\2\0\1\22\1\23\2\0\1\20\1\0\1\15\102\0"+
+    "\1\4\3\0\1\5\17\0\1\3\16\0\1\1\20\0\1\3\16\0"+
+    "\1\1\1\2\170\0\1\2\ufe87\0";
+
+  /** 
+   * Translates characters to character classes
+   */
+  private static final char [] ZZ_CMAP = zzUnpackCMap(ZZ_CMAP_PACKED);
+
+  /** 
+   * Translates DFA states to action switch labels.
+   */
+  private static final int [] ZZ_ACTION = zzUnpackAction();
+
+  private static final String ZZ_ACTION_PACKED_0 =
+    "\7\0\13\1\2\2\1\1\1\2\1\3\1\4\1\5"+
+    "\1\6\1\1\1\5\1\7\1\1\1\5\1\10\1\1"+
+    "\1\11\1\12\1\13\12\0\1\14\5\0\1\2\1\3"+
+    "\1\4\1\6\2\0\1\15\1\7\2\0\1\10\1\11"+
+    "\1\16\3\0\1\14\4\0\1\2\1\15\14\0\1\17"+
+    "\5\0\1\17\6\0\1\20\3\0\1\20\2\0\1\21"+
+    "\1\0\1\21\1\0";
+
+  private static int [] zzUnpackAction() {
+    int [] result = new int[111];
+    int offset = 0;
+    offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result);
+    return result;
+  }
+
+  private static int zzUnpackAction(String packed, int offset, int [] result) {
+    int i = 0;       /* index in packed string  */
+    int j = offset;  /* index in unpacked array */
+    int l = packed.length();
+    while (i < l) {
+      int count = packed.charAt(i++);
+      int value = packed.charAt(i++);
+      do result[j++] = value; while (--count > 0);
+    }
+    return j;
+  }
+
+
+  /* error codes */
+  private static final int ZZ_UNKNOWN_ERROR = 0;
+  private static final int ZZ_NO_MATCH = 1;
+  private static final int ZZ_PUSHBACK_2BIG = 2;
+
+  /* error messages for the codes above */
+  private static final String ZZ_ERROR_MSG[] = {
+    "Unkown internal scanner error",
+    "Error: could not match input",
+    "Error: pushback value was too large"
+  };
+
+  /** the input device */
+  private java.io.Reader zzReader;
+
+  /** the current state of the DFA */
+  private int zzState;
+
+  /** the current lexical state */
+  private int zzLexicalState = YYINITIAL;
+
+  /** this buffer contains the current text to be matched and is
+      the source of the yytext() string */
+  private char zzBuffer[] = new char[ZZ_BUFFERSIZE];
+
+  /** the textposition at the last accepting state */
+  private int zzMarkedPos;
+
+  /** the current text position in the buffer */
+  private int zzCurrentPos;
+
+  /** startRead marks the beginning of the yytext() string in the buffer */
+  private int zzStartRead;
+
+  /** endRead marks the last character in the buffer, that has been read
+      from input */
+  private int zzEndRead;
+
+  /** number of newlines encountered up to the start of the matched text */
+//  private int yyline;
+
+  /** the number of characters up to the start of the matched text */
+  private int yychar;
+
+  /**
+   * the number of characters from the last newline up to the start of the 
+   * matched text
+   */
+//  private int yycolumn;
+
+  /** 
+   * zzAtBOL == true <=> the scanner is currently at the beginning of a line
+   */
+  private boolean zzAtBOL = true;
+
+  /** zzAtEOF == true <=> the scanner is at the EOF */
+  private boolean zzAtEOF;
+
+  /** denotes if the user-EOF-code has already been executed */
+  private boolean zzEOFDone;
+
+  /* user code: */
+
+
+	private boolean hasMore = true;
+	private final static int MAX_TO_SCAN = 8000;
+	StringBuffer string = new StringBuffer();
+	// state stack for easier state handling
+	private IntStack fStateStack = new IntStack();
+	private String valueText = null;
+
+
+	public XMLHeadTokenizer() {
+		super();
+	}
+
+	  public void reset (Reader in) {
+                /* the input device */
+                zzReader = in;
+
+                /* the current state of the DFA */
+                zzState = 0;
+
+                /* the current lexical state */
+                zzLexicalState = YYINITIAL;
+
+                /* this buffer contains the current text to be matched and is
+                 the source of the yytext() string */
+                java.util.Arrays.fill(zzBuffer, (char)0);
+
+                /* the textposition at the last accepting state */
+                zzMarkedPos = 0;
+
+                /* the textposition at the last state to be included in yytext */
+//                zzPushbackPos = 0;
+
+                /* the current text position in the buffer */
+                zzCurrentPos = 0;
+
+                /* startRead marks the beginning of the yytext() string in the buffer */
+                zzStartRead = 0;
+
+                /**
+                 * endRead marks the last character in the buffer, that has been read
+                 * from input
+                 */
+                zzEndRead = 0;
+
+                /* number of newlines encountered up to the start of the matched text */
+//                yyline = 0;
+
+                /* the number of characters up to the start of the matched text */
+                yychar = 0;
+
+                /**
+                 * the number of characters from the last newline up to the start
+                 * of the matched text
+                 */
+//                yycolumn = 0;
+
+                /**
+                 * yy_atBOL == true <=> the scanner is currently at the beginning
+                 * of a line
+                 */
+                zzAtBOL = true;
+
+                /* yy_atEOF == true <=> the scanner has returned a value for EOF */
+                zzAtEOF = false;
+
+                /* denotes if the user-EOF-code has already been executed */
+                zzEOFDone = false;
+
+
+                fStateStack.clear();
+
+                hasMore = true;
+  		
+  	}
+
+
+	public final HeadParserToken getNextToken() throws IOException {
+		String context = null;
+		context = primGetNextToken();
+		HeadParserToken result = null;
+		if (valueText != null) {
+			result = createToken(context, yychar, valueText);
+			valueText = null;
+		} else {
+			result = createToken(context, yychar, yytext());
+		}
+		return result;
+	}
+
+	public final boolean hasMoreTokens() {
+		return hasMore && yychar < MAX_TO_SCAN;
+	}
+	private void pushCurrentState() {
+		fStateStack.push(yystate());
+
+	}
+
+	private void popState() {
+		yybegin(fStateStack.pop());
+	}
+	
+	private HeadParserToken createToken(String context, int start, String text) {
+		return new HeadParserToken(context, start, text);
+	}	
+
+
+
+  /**
+   * Creates a new scanner
+   * There is also a java.io.InputStream version of this constructor.
+   *
+   * @param   in  the java.io.Reader to read input from.
+   */
+  public XMLHeadTokenizer(java.io.Reader in) {
+    this.zzReader = in;
+  }
+
+  /**
+   * Creates a new scanner.
+   * There is also java.io.Reader version of this constructor.
+   *
+   * @param   in  the java.io.Inputstream to read input from.
+   */
+  public XMLHeadTokenizer(java.io.InputStream in) {
+    this(new java.io.InputStreamReader(in));
+  }
+
+  /** 
+   * Unpacks the compressed character translation table.
+   *
+   * @param packed   the packed character translation table
+   * @return         the unpacked character translation table
+   */
+  private static char [] zzUnpackCMap(String packed) {
+    char [] map = new char[0x10000];
+    int i = 0;  /* index in packed string  */
+    int j = 0;  /* index in unpacked array */
+    while (i < 150) {
+      int  count = packed.charAt(i++);
+      char value = packed.charAt(i++);
+      do map[j++] = value; while (--count > 0);
+    }
+    return map;
+  }
+
+
+  /**
+   * Refills the input buffer.
+   *
+   * @return      <code>false</code>, iff there was new input.
+   * 
+   * @exception   java.io.IOException  if any I/O-Error occurs
+   */
+  private boolean zzRefill() throws java.io.IOException {
+
+    /* first: make room (if you can) */
+    if (zzStartRead > 0) {
+      System.arraycopy(zzBuffer, zzStartRead,
+                       zzBuffer, 0,
+                       zzEndRead-zzStartRead);
+
+      /* translate stored positions */
+      zzEndRead-= zzStartRead;
+      zzCurrentPos-= zzStartRead;
+      zzMarkedPos-= zzStartRead;
+      zzStartRead = 0;
+    }
+
+    /* is the buffer big enough? */
+    if (zzCurrentPos >= zzBuffer.length) {
+      /* if not: blow it up */
+      char newBuffer[] = new char[zzCurrentPos*2];
+      System.arraycopy(zzBuffer, 0, newBuffer, 0, zzBuffer.length);
+      zzBuffer = newBuffer;
+    }
+
+    /* finally: fill the buffer with new input */
+    int numRead = zzReader.read(zzBuffer, zzEndRead,
+                                            zzBuffer.length-zzEndRead);
+
+    if (numRead > 0) {
+      zzEndRead+= numRead;
+      return false;
+    }
+    // unlikely but not impossible: read 0 characters, but not at end of stream    
+    if (numRead == 0) {
+      int c = zzReader.read();
+      if (c == -1) {
+        return true;
+      } else {
+        zzBuffer[zzEndRead++] = (char) c;
+        return false;
+      }     
+    }
+
+	// numRead < 0
+    return true;
+  }
+
+    
+  /**
+   * Closes the input stream.
+   */
+  public final void yyclose() throws java.io.IOException {
+    zzAtEOF = true;            /* indicate end of file */
+    zzEndRead = zzStartRead;  /* invalidate buffer    */
+
+    if (zzReader != null)
+      zzReader.close();
+  }
+
+
+  /**
+   * Resets the scanner to read from a new input stream.
+   * Does not close the old reader.
+   *
+   * All internal variables are reset, the old input stream 
+   * <b>cannot</b> be reused (internal buffer is discarded and lost).
+   * Lexical state is set to <tt>ZZ_INITIAL</tt>.
+   *
+   * @param reader   the new input stream 
+   */
+  public final void yyreset(java.io.Reader reader) {
+    zzReader = reader;
+    zzAtBOL  = true;
+    zzAtEOF  = false;
+    zzEndRead = zzStartRead = 0;
+    zzCurrentPos = zzMarkedPos = 0;
+    yychar = 0;
+    zzLexicalState = YYINITIAL;
+  }
+
+
+  /**
+   * Returns the current lexical state.
+   */
+  public final int yystate() {
+    return zzLexicalState;
+  }
+
+
+  /**
+   * Enters a new lexical state
+   *
+   * @param newState the new lexical state
+   */
+  public final void yybegin(int newState) {
+    zzLexicalState = newState;
+  }
+
+
+  /**
+   * Returns the text matched by the current regular expression.
+   */
+  public final String yytext() {
+    return new String( zzBuffer, zzStartRead, zzMarkedPos-zzStartRead );
+  }
+
+
+  /**
+   * Returns the character at position <tt>pos</tt> from the 
+   * matched text. 
+   * 
+   * It is equivalent to yytext().charAt(pos), but faster
+   *
+   * @param pos the position of the character to fetch. 
+   *            A value from 0 to yylength()-1.
+   *
+   * @return the character at position pos
+   */
+  public final char yycharat(int pos) {
+    return zzBuffer[zzStartRead+pos];
+  }
+
+
+  /**
+   * Returns the length of the matched text region.
+   */
+  public final int yylength() {
+    return zzMarkedPos-zzStartRead;
+  }
+
+
+  /**
+   * Reports an error that occured while scanning.
+   *
+   * In a wellformed scanner (no or only correct usage of 
+   * yypushback(int) and a match-all fallback rule) this method 
+   * will only be called with things that "Can't Possibly Happen".
+   * If this method is called, something is seriously wrong
+   * (e.g. a JFlex bug producing a faulty scanner etc.).
+   *
+   * Usual syntax/scanner level error handling should be done
+   * in error fallback rules.
+   *
+   * @param   errorCode  the code of the errormessage to display
+   */
+  private void zzScanError(int errorCode) {
+    String message;
+    try {
+      message = ZZ_ERROR_MSG[errorCode];
+    }
+    catch (ArrayIndexOutOfBoundsException e) {
+      message = ZZ_ERROR_MSG[ZZ_UNKNOWN_ERROR];
+    }
+
+    throw new Error(message);
+  } 
+
+
+  /**
+   * Pushes the specified amount of characters back into the input stream.
+   *
+   * They will be read again by then next call of the scanning method
+   *
+   * @param number  the number of characters to be read again.
+   *                This number must not be greater than yylength()!
+   */
+  public void yypushback(int number)  {
+    if ( number > yylength() )
+      zzScanError(ZZ_PUSHBACK_2BIG);
+
+    zzMarkedPos -= number;
+  }
+
+
+  /**
+   * Contains user EOF-code, which will be executed exactly once,
+   * when the end of file is reached
+   */
+  private void zzDoEOF() {
+    if (!zzEOFDone) {
+      zzEOFDone = true;
+    	hasMore=false;
+
+    }
+  }
+
+
+  /**
+   * Resumes scanning until the next regular expression is matched,
+   * the end of input is encountered or an I/O-Error occurs.
+   *
+   * @return      the next token
+   * @exception   java.io.IOException  if any I/O-Error occurs
+   */
+  public String primGetNextToken() throws java.io.IOException {
+    int zzInput;
+    int zzAction;
+
+    // cached fields:
+    int zzCurrentPosL;
+    int zzMarkedPosL;
+    int zzEndReadL = zzEndRead;
+    char [] zzBufferL = zzBuffer;
+    char [] zzCMapL = ZZ_CMAP;
+
+
+    while (true) {
+      zzMarkedPosL = zzMarkedPos;
+
+      yychar+= zzMarkedPosL-zzStartRead;
+
+      if (zzMarkedPosL > zzStartRead) {
+        switch (zzBufferL[zzMarkedPosL-1]) {
+        case '\n':
+        case '\u000B':
+        case '\u000C':
+        case '\u0085':
+        case '\u2028':
+        case '\u2029':
+          zzAtBOL = true;
+          break;
+        case '\r': 
+          if (zzMarkedPosL < zzEndReadL)
+            zzAtBOL = zzBufferL[zzMarkedPosL] != '\n';
+          else if (zzAtEOF)
+            zzAtBOL = false;
+          else {
+            boolean eof = zzRefill();
+            zzMarkedPosL = zzMarkedPos;
+            zzEndReadL = zzEndRead;
+            zzBufferL = zzBuffer;
+            if (eof) 
+              zzAtBOL = false;
+            else 
+              zzAtBOL = zzBufferL[zzMarkedPosL] != '\n';
+          }
+          break;
+        default:
+          zzAtBOL = false;
+        }
+      }
+      zzAction = -1;
+
+      zzCurrentPosL = zzCurrentPos = zzStartRead = zzMarkedPosL;
+  
+      if (zzAtBOL)
+        zzState = ZZ_LEXSTATE[zzLexicalState+1];
+      else
+        zzState = ZZ_LEXSTATE[zzLexicalState];
+
+
+      zzForAction: {
+        while (true) {
+    
+          if (zzCurrentPosL < zzEndReadL)
+            zzInput = zzBufferL[zzCurrentPosL++];
+          else if (zzAtEOF) {
+            zzInput = YYEOF;
+            break zzForAction;
+          }
+          else {
+            // store back cached positions
+            zzCurrentPos  = zzCurrentPosL;
+            zzMarkedPos   = zzMarkedPosL;
+            boolean eof = zzRefill();
+            // get translated positions and possibly new buffer
+            zzCurrentPosL  = zzCurrentPos;
+            zzMarkedPosL   = zzMarkedPos;
+            zzBufferL      = zzBuffer;
+            zzEndReadL     = zzEndRead;
+            if (eof) {
+              zzInput = YYEOF;
+              break zzForAction;
+            }
+            else {
+              zzInput = zzBufferL[zzCurrentPosL++];
+            }
+          }
+          zzInput = zzCMapL[zzInput];
+
+          boolean zzIsFinal = false;
+          boolean zzNoLookAhead = false;
+
+          zzForNext: { switch (zzState) {
+            case 0:
+              switch (zzInput) {
+                default: zzIsFinal = true; zzNoLookAhead = true; zzState = 7; break zzForNext;
+              }
+
+            case 1:
+              switch (zzInput) {
+                case 1: zzIsFinal = true; zzState = 8; break zzForNext;
+                case 2: zzIsFinal = true; zzState = 9; break zzForNext;
+                case 3: zzIsFinal = true; zzState = 10; break zzForNext;
+                case 6: 
+                case 7: 
+                case 8: zzIsFinal = true; zzState = 11; break zzForNext;
+                case 9: zzIsFinal = true; zzState = 12; break zzForNext;
+                case 11: zzIsFinal = true; zzState = 13; break zzForNext;
+                default: zzIsFinal = true; zzNoLookAhead = true; zzState = 7; break zzForNext;
+              }
+
+            case 2:
+              switch (zzInput) {
+                case 9: zzIsFinal = true; zzState = 14; break zzForNext;
+                case 12: zzIsFinal = true; zzState = 15; break zzForNext;
+                case 16: zzIsFinal = true; zzState = 16; break zzForNext;
+                case 17: zzIsFinal = true; zzState = 17; break zzForNext;
+                default: zzIsFinal = true; zzNoLookAhead = true; zzState = 7; break zzForNext;
+              }
+
+            case 3:
+              switch (zzInput) {
+                case 6: 
+                case 7: zzIsFinal = true; zzState = 19; break zzForNext;
+                case 8: zzIsFinal = true; zzState = 20; break zzForNext;
+                case 9: zzIsFinal = true; zzState = 21; break zzForNext;
+                case 27: zzIsFinal = true; zzState = 22; break zzForNext;
+                case 28: zzIsFinal = true; zzState = 23; break zzForNext;
+                default: zzIsFinal = true; zzNoLookAhead = true; zzState = 18; break zzForNext;
+              }
+
+            case 4:
+              switch (zzInput) {
+                case 7: 
+                case 8: 
+                case 11: zzIsFinal = true; zzState = 25; break zzForNext;
+                case 9: zzIsFinal = true; zzState = 26; break zzForNext;
+                case 12: zzIsFinal = true; zzState = 27; break zzForNext;
+                case 27: zzIsFinal = true; zzState = 28; break zzForNext;
+                default: zzIsFinal = true; zzNoLookAhead = true; zzState = 24; break zzForNext;
+              }
+
+            case 5:
+              switch (zzInput) {
+                case 7: 
+                case 8: 
+                case 11: zzIsFinal = true; zzState = 25; break zzForNext;
+                case 28: zzIsFinal = true; zzState = 28; break zzForNext;
+                case 9: zzIsFinal = true; zzState = 29; break zzForNext;
+                case 29: zzIsFinal = true; zzState = 30; break zzForNext;
+                default: zzIsFinal = true; zzNoLookAhead = true; zzState = 24; break zzForNext;
+              }
+
+            case 6:
+              switch (zzInput) {
+                case 11: zzIsFinal = true; zzState = 25; break zzForNext;
+                case 12: zzIsFinal = true; zzState = 30; break zzForNext;
+                case 6: 
+                case 7: 
+                case 8: zzIsFinal = true; zzState = 31; break zzForNext;
+                case 9: zzIsFinal = true; zzState = 32; break zzForNext;
+                case 27: 
+                case 28: zzIsFinal = true; zzState = 33; break zzForNext;
+                default: zzIsFinal = true; zzNoLookAhead = true; zzState = 24; break zzForNext;
+              }
+
+            case 8:
+              switch (zzInput) {
+                case 2: zzIsFinal = true; zzNoLookAhead = true; zzState = 34; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 9:
+              switch (zzInput) {
+                case 1: zzIsFinal = true; zzNoLookAhead = true; zzState = 35; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 10:
+              switch (zzInput) {
+                case 4: zzState = 36; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 11:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzState = 37; break zzForNext;
+                case 9: zzState = 38; break zzForNext;
+                case 11: zzState = 39; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 12:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzState = 37; break zzForNext;
+                case 11: zzState = 39; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 13:
+              switch (zzInput) {
+                case 9: zzState = 40; break zzForNext;
+                case 12: zzState = 41; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 14:
+              switch (zzInput) {
+                case 12: zzState = 42; break zzForNext;
+                case 16: zzState = 43; break zzForNext;
+                case 17: zzState = 44; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 15:
+              switch (zzInput) {
+                case 9: zzState = 45; break zzForNext;
+                case 26: zzIsFinal = true; zzState = 46; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 16:
+              switch (zzInput) {
+                case 9: zzState = 47; break zzForNext;
+                case 17: zzState = 48; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 17:
+              switch (zzInput) {
+                case 9: zzState = 49; break zzForNext;
+                case 22: zzState = 50; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 19:
+              switch (zzInput) {
+                case 6: 
+                case 7: zzIsFinal = true; break zzForNext;
+                case 8: zzState = 51; break zzForNext;
+                case 9: zzIsFinal = true; zzState = 52; break zzForNext;
+                default: zzIsFinal = true; zzNoLookAhead = true; zzState = 18; break zzForNext;
+              }
+
+            case 20:
+              switch (zzInput) {
+                case 6: 
+                case 7: zzIsFinal = true; zzState = 19; break zzForNext;
+                case 8: zzState = 51; break zzForNext;
+                case 9: zzIsFinal = true; zzState = 52; break zzForNext;
+                default: zzIsFinal = true; zzNoLookAhead = true; zzState = 18; break zzForNext;
+              }
+
+            case 21:
+              switch (zzInput) {
+                case 27: zzIsFinal = true; zzState = 22; break zzForNext;
+                case 28: zzIsFinal = true; zzState = 23; break zzForNext;
+                case 6: 
+                case 7: 
+                case 8: zzState = 51; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 22:
+              switch (zzInput) {
+                case 9: zzIsFinal = true; zzNoLookAhead = true; zzState = 53; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 23:
+              switch (zzInput) {
+                case 9: zzIsFinal = true; zzNoLookAhead = true; zzState = 54; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 25:
+              switch (zzInput) {
+                case 9: zzIsFinal = true; zzNoLookAhead = true; zzState = 55; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 26:
+              switch (zzInput) {
+                case 7: 
+                case 8: 
+                case 11: zzIsFinal = true; zzState = 25; break zzForNext;
+                case 27: zzIsFinal = true; zzState = 28; break zzForNext;
+                case 12: zzState = 56; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 27:
+              switch (zzInput) {
+                case 9: zzState = 57; break zzForNext;
+                case 26: zzIsFinal = true; zzState = 58; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 28:
+              switch (zzInput) {
+                case 9: zzIsFinal = true; zzNoLookAhead = true; zzState = 59; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 29:
+              switch (zzInput) {
+                case 7: 
+                case 8: 
+                case 11: zzIsFinal = true; zzState = 25; break zzForNext;
+                case 28: zzIsFinal = true; zzState = 28; break zzForNext;
+                case 29: zzState = 60; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 30:
+              switch (zzInput) {
+                case 26: zzIsFinal = true; zzState = 25; break zzForNext;
+                case 9: zzState = 61; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 31:
+              switch (zzInput) {
+                case 9: zzIsFinal = true; zzNoLookAhead = true; zzState = 62; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 32:
+              switch (zzInput) {
+                case 11: zzIsFinal = true; zzState = 25; break zzForNext;
+                case 6: 
+                case 7: 
+                case 8: zzIsFinal = true; zzState = 31; break zzForNext;
+                case 27: 
+                case 28: zzIsFinal = true; zzState = 33; break zzForNext;
+                case 12: zzState = 60; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 33:
+              switch (zzInput) {
+                case 9: zzIsFinal = true; zzNoLookAhead = true; zzState = 63; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 36:
+              switch (zzInput) {
+                case 5: zzIsFinal = true; zzNoLookAhead = true; zzState = 64; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 37:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: break zzForNext;
+                case 9: zzState = 38; break zzForNext;
+                case 11: zzState = 39; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 38:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzState = 37; break zzForNext;
+                case 11: zzState = 39; break zzForNext;
+                case 9: zzState = 65; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 39:
+              switch (zzInput) {
+                case 9: zzState = 40; break zzForNext;
+                case 12: zzState = 41; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 40:
+              switch (zzInput) {
+                case 12: zzState = 41; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 41:
+              switch (zzInput) {
+                case 9: zzState = 66; break zzForNext;
+                case 13: zzState = 67; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 42:
+              switch (zzInput) {
+                case 9: zzState = 45; break zzForNext;
+                case 26: zzIsFinal = true; zzState = 46; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 43:
+              switch (zzInput) {
+                case 9: zzState = 47; break zzForNext;
+                case 17: zzState = 48; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 44:
+              switch (zzInput) {
+                case 9: zzState = 49; break zzForNext;
+                case 22: zzState = 50; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 45:
+              switch (zzInput) {
+                case 26: zzIsFinal = true; zzState = 46; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 46:
+              switch (zzInput) {
+                case 9: zzIsFinal = true; zzNoLookAhead = true; zzState = 68; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 47:
+              switch (zzInput) {
+                case 17: zzState = 48; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 48:
+              switch (zzInput) {
+                case 9: zzState = 69; break zzForNext;
+                case 18: zzState = 70; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 49:
+              switch (zzInput) {
+                case 22: zzState = 50; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 50:
+              switch (zzInput) {
+                case 9: zzState = 71; break zzForNext;
+                case 23: zzState = 72; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 51:
+              switch (zzInput) {
+                case 6: 
+                case 7: zzIsFinal = true; zzState = 19; break zzForNext;
+                case 8: break zzForNext;
+                case 9: zzIsFinal = true; zzState = 52; break zzForNext;
+                default: zzIsFinal = true; zzNoLookAhead = true; zzState = 18; break zzForNext;
+              }
+
+            case 52:
+              switch (zzInput) {
+                case 6: 
+                case 7: zzIsFinal = true; zzState = 19; break zzForNext;
+                case 8: zzState = 51; break zzForNext;
+                case 9: zzIsFinal = true; zzState = 73; break zzForNext;
+                default: zzIsFinal = true; zzNoLookAhead = true; zzState = 18; break zzForNext;
+              }
+
+            case 56:
+              switch (zzInput) {
+                case 9: zzState = 57; break zzForNext;
+                case 26: zzIsFinal = true; zzState = 58; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 57:
+              switch (zzInput) {
+                case 26: zzIsFinal = true; zzState = 58; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 58:
+              switch (zzInput) {
+                case 9: zzIsFinal = true; zzNoLookAhead = true; zzState = 74; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 60:
+              switch (zzInput) {
+                case 26: zzIsFinal = true; zzState = 25; break zzForNext;
+                case 9: zzState = 61; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 61:
+              switch (zzInput) {
+                case 26: zzIsFinal = true; zzState = 25; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 65:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzState = 37; break zzForNext;
+                case 11: zzState = 39; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 66:
+              switch (zzInput) {
+                case 13: zzState = 67; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 67:
+              switch (zzInput) {
+                case 9: zzState = 75; break zzForNext;
+                case 14: zzState = 76; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 69:
+              switch (zzInput) {
+                case 18: zzState = 70; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 70:
+              switch (zzInput) {
+                case 9: zzState = 77; break zzForNext;
+                case 19: zzState = 78; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 71:
+              switch (zzInput) {
+                case 23: zzState = 72; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 72:
+              switch (zzInput) {
+                case 9: zzState = 79; break zzForNext;
+                case 21: zzState = 80; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 73:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzState = 51; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 75:
+              switch (zzInput) {
+                case 14: zzState = 76; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 76:
+              switch (zzInput) {
+                case 9: zzState = 81; break zzForNext;
+                case 15: zzState = 82; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 77:
+              switch (zzInput) {
+                case 19: zzState = 78; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 78:
+              switch (zzInput) {
+                case 9: zzState = 83; break zzForNext;
+                case 20: zzState = 84; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 79:
+              switch (zzInput) {
+                case 21: zzState = 80; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 80:
+              switch (zzInput) {
+                case 9: zzState = 85; break zzForNext;
+                case 24: zzState = 86; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 81:
+              switch (zzInput) {
+                case 15: zzState = 82; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 82:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzIsFinal = true; zzState = 87; break zzForNext;
+                case 9: zzState = 88; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 83:
+              switch (zzInput) {
+                case 20: zzState = 84; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 84:
+              switch (zzInput) {
+                case 9: zzState = 89; break zzForNext;
+                case 21: zzState = 90; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 85:
+              switch (zzInput) {
+                case 24: zzState = 86; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 86:
+              switch (zzInput) {
+                case 9: zzState = 91; break zzForNext;
+                case 20: zzState = 92; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 87:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzIsFinal = true; break zzForNext;
+                case 9: zzIsFinal = true; zzState = 93; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 88:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzIsFinal = true; zzState = 87; break zzForNext;
+                case 9: zzState = 94; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 89:
+              switch (zzInput) {
+                case 21: zzState = 90; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 90:
+              switch (zzInput) {
+                case 9: zzState = 95; break zzForNext;
+                case 22: zzState = 96; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 91:
+              switch (zzInput) {
+                case 20: zzState = 92; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 92:
+              switch (zzInput) {
+                case 9: zzState = 97; break zzForNext;
+                case 22: zzState = 98; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 93:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzIsFinal = true; zzState = 87; break zzForNext;
+                case 9: zzState = 94; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 94:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzIsFinal = true; zzState = 87; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 95:
+              switch (zzInput) {
+                case 22: zzState = 96; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 96:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: break zzForNext;
+                case 9: zzState = 99; break zzForNext;
+                case 10: zzIsFinal = true; zzState = 100; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 97:
+              switch (zzInput) {
+                case 22: zzState = 98; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 98:
+              switch (zzInput) {
+                case 9: zzState = 101; break zzForNext;
+                case 25: zzState = 102; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 99:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzState = 96; break zzForNext;
+                case 10: zzIsFinal = true; zzState = 100; break zzForNext;
+                case 9: zzState = 103; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 100:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzIsFinal = true; zzState = 104; break zzForNext;
+                case 9: zzState = 105; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 101:
+              switch (zzInput) {
+                case 25: zzState = 102; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 102:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: break zzForNext;
+                case 9: zzState = 106; break zzForNext;
+                case 10: zzIsFinal = true; zzState = 107; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 103:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzState = 96; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 104:
+              switch (zzInput) {
+                case 9: zzIsFinal = true; zzState = 100; break zzForNext;
+                case 6: 
+                case 7: 
+                case 8: zzIsFinal = true; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 105:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzIsFinal = true; zzState = 104; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 106:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzState = 102; break zzForNext;
+                case 10: zzIsFinal = true; zzState = 107; break zzForNext;
+                case 9: zzState = 108; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 107:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzIsFinal = true; zzState = 109; break zzForNext;
+                case 9: zzState = 110; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 108:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzState = 102; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 109:
+              switch (zzInput) {
+                case 9: zzIsFinal = true; zzState = 107; break zzForNext;
+                case 6: 
+                case 7: 
+                case 8: zzIsFinal = true; break zzForNext;
+                default: break zzForAction;
+              }
+
+            case 110:
+              switch (zzInput) {
+                case 6: 
+                case 7: 
+                case 8: zzIsFinal = true; zzState = 109; break zzForNext;
+                default: break zzForAction;
+              }
+
+            default:
+              // if this is ever reached, there is a serious bug in JFlex
+              zzScanError(ZZ_UNKNOWN_ERROR);
+              break;
+          } }
+
+          if ( zzIsFinal ) {
+            zzAction = zzState;
+            zzMarkedPosL = zzCurrentPosL;
+            if ( zzNoLookAhead ) break zzForAction;
+          }
+
+        }
+      }
+
+      // store back cached position
+      zzMarkedPos = zzMarkedPosL;
+
+      switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) {
+        case 12: 
+          { yybegin(YYINITIAL); hasMore = false; return XMLHeadTokenizerConstants.XMLDeclEnd;
+          }
+        case 18: break;
+        case 14: 
+          { if (yychar == 0 ) {hasMore = false; return EncodingParserConstants.UTF83ByteBOM;}
+          }
+        case 19: break;
+        case 9: 
+          { yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTermintatedUnDelimitedStringValue;
+          }
+        case 20: break;
+        case 2: 
+          { yypushback(1); yybegin(UnDelimitedString); string.setLength(0);
+          }
+        case 21: break;
+        case 7: 
+          { popState(); valueText = string.toString(); return EncodingParserConstants.StringValue;
+          }
+        case 22: break;
+        case 10: 
+          { if (yychar == 0 ) {hasMore = false; return EncodingParserConstants.UTF16BE;}
+          }
+        case 23: break;
+        case 1: 
+          { if(yychar > MAX_TO_SCAN) {hasMore=false; return EncodingParserConstants.MAX_CHARS_REACHED;}
+          }
+        case 24: break;
+        case 6: 
+          { yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;
+          }
+        case 25: break;
+        case 5: 
+          { string.append( yytext() );
+          }
+        case 26: break;
+        case 13: 
+          { yypushback(yylength()); popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;
+          }
+        case 27: break;
+        case 4: 
+          { yybegin(SQ_STRING); string.setLength(0);
+          }
+        case 28: break;
+        case 3: 
+          { yybegin(DQ_STRING); string.setLength(0);
+          }
+        case 29: break;
+        case 8: 
+          { yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.UnDelimitedStringValue;
+          }
+        case 30: break;
+        case 17: 
+          { pushCurrentState(); yybegin(QuotedAttributeValue); return XMLHeadTokenizerConstants.XMLDelEncoding;
+          }
+        case 31: break;
+        case 15: 
+          { if (yychar == 0 ) {yybegin(ST_XMLDecl); return XMLHeadTokenizerConstants.XMLDeclStart;}
+          }
+        case 32: break;
+        case 11: 
+          { if (yychar == 0 ) {hasMore = false; return EncodingParserConstants.UTF16LE;}
+          }
+        case 33: break;
+        case 16: 
+          { pushCurrentState(); yybegin(QuotedAttributeValue); return XMLHeadTokenizerConstants.XMLDeclVersion;
+          }
+        case 34: break;
+        default: 
+          if (zzInput == YYEOF && zzStartRead == zzCurrentPos) {
+            zzAtEOF = true;
+            zzDoEOF();
+              {
+                hasMore = false; return EncodingParserConstants.EOF;
+              }
+          } 
+          else {
+            zzScanError(ZZ_NO_MATCH);
+          }
+      }
+    }
+  }
+
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/XMLHeadTokenizerConstants.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/XMLHeadTokenizerConstants.java
new file mode 100644
index 0000000..ccf23f8
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/XMLHeadTokenizerConstants.java
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contenttype;
+
+public interface XMLHeadTokenizerConstants extends EncodingParserConstants {
+
+	final String XMLDeclEnd = "XMLDeclEnd"; //$NON-NLS-1$
+	final String XMLDeclStart = "XMLDeclStart"; //$NON-NLS-1$
+	final String XMLDelEncoding = "XMLDelEncoding"; //$NON-NLS-1$
+	final String XMLDeclVersion = "XMLDeclVersion"; //$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/XMLResourceEncodingDetector.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/XMLResourceEncodingDetector.java
new file mode 100644
index 0000000..1f1079b
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/XMLResourceEncodingDetector.java
@@ -0,0 +1,142 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     David Carver (STAR) - bug 297006 - String Comparison
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contenttype;
+
+import java.io.IOException;
+
+import org.eclipse.core.runtime.content.IContentDescription;
+import org.eclipse.wst.sse.core.internal.encoding.EncodingMemento;
+import org.eclipse.wst.sse.core.internal.encoding.IResourceCharsetDetector;
+
+
+public class XMLResourceEncodingDetector extends AbstractResourceEncodingDetector implements IResourceCharsetDetector {
+	private XMLHeadTokenizer fTokenizer;
+	private boolean fDeclDetected = false;
+	private boolean fInitialWhiteSpace = false;
+
+	private boolean canHandleAsUnicodeStream(String tokenType) {
+		boolean canHandleAsUnicodeStream = false;
+		if (EncodingParserConstants.UTF83ByteBOM.equals(tokenType)) {
+			canHandleAsUnicodeStream = true;
+			String enc = "UTF-8"; //$NON-NLS-1$
+			createEncodingMemento(enc, EncodingMemento.DETECTED_STANDARD_UNICODE_BYTES);
+			fEncodingMemento.setUTF83ByteBOMUsed(true);
+		}
+		else if (EncodingParserConstants.UTF16BE.equals(tokenType) || EncodingParserConstants.UTF16LE.equals(tokenType)) {
+			canHandleAsUnicodeStream = true;
+			String enc = "UTF-16"; //$NON-NLS-1$
+			byte[] bom = (EncodingParserConstants.UTF16BE.equals(tokenType)) ? IContentDescription.BOM_UTF_16BE : IContentDescription.BOM_UTF_16LE;
+			createEncodingMemento(enc, EncodingMemento.DETECTED_STANDARD_UNICODE_BYTES);
+			fEncodingMemento.setUnicodeStream(true);
+			fEncodingMemento.setUnicodeBOM(bom);
+		}
+		return canHandleAsUnicodeStream;
+	}
+
+	public String getSpecDefaultEncoding() {
+		// by default, UTF-8 as per XML spec
+		final String enc = "UTF-8"; //$NON-NLS-1$
+		return enc;
+	}
+
+	/**
+	 * @return Returns the tokenizer.
+	 */
+	private XMLHeadTokenizer getTokenizer() {
+		// TODO: need to work on 'reset' in tokenizer, so new instance isn't
+		// always needed
+		// if (fTokenizer == null) {
+		fTokenizer = new XMLHeadTokenizer();
+		// }
+		return fTokenizer;
+	}
+
+	private boolean isLegalString(String valueTokenType) {
+		if (valueTokenType == null)
+			return false;
+		else
+			return valueTokenType.equals(EncodingParserConstants.StringValue) || valueTokenType.equals(EncodingParserConstants.UnDelimitedStringValue) || valueTokenType.equals(EncodingParserConstants.InvalidTerminatedStringValue) || valueTokenType.equals(EncodingParserConstants.InvalidTermintatedUnDelimitedStringValue);
+	}
+
+	protected void parseInput() throws IOException {
+		XMLHeadTokenizer tokenizer = getTokenizer();
+		tokenizer.reset(fReader);
+		HeadParserToken token = null;
+		String tokenType = null;
+		do {
+			token = tokenizer.getNextToken();
+			tokenType = token.getType();
+
+			// handle xml content type detection
+			if (tokenType == XMLHeadTokenizerConstants.XMLDeclStart) {
+				fDeclDetected = true;
+				String declText = token.getText();
+				if (declText.startsWith("<?")) { //$NON-NLS-1$
+					fInitialWhiteSpace = false;
+				}
+				else {
+					fInitialWhiteSpace = true;
+				}
+			}
+
+			// handle encoding detection
+			if (canHandleAsUnicodeStream(tokenType)) {
+				// side effect of canHandle is to create appropriate memento
+			}
+			else {
+				if (tokenType == XMLHeadTokenizerConstants.XMLDelEncoding) {
+					if (tokenizer.hasMoreTokens()) {
+						token = tokenizer.getNextToken();
+						tokenType = token.getType();
+						if (isLegalString(tokenType)) {
+							String enc = token.getText();
+							if (enc != null && enc.length() > 0) {
+								createEncodingMemento(enc, EncodingMemento.FOUND_ENCODING_IN_CONTENT);
+							}
+						}
+					}
+				}
+			}
+		}
+		while (tokenizer.hasMoreTokens());
+
+	}
+
+	public boolean isDeclDetected() {
+		if (!fHeaderParsed) {
+			try {
+				parseInput();
+			}
+			catch (IOException e) {
+				fDeclDetected = false;
+			}
+			// we keep track of if header's already been
+			// parse, so can make
+			// multiple 'get' calls, without causing
+			// reparsing.
+			fHeaderParsed = true;
+		}
+		// fDeclDetected is set as part of parsing.
+		return fDeclDetected;
+	}
+
+	public boolean hasInitialWhiteSpace() {
+		return fInitialWhiteSpace;
+	}
+
+	protected void resetAll() {
+	    super.resetAll();
+		fDeclDetected = false;
+		fInitialWhiteSpace = false;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/AttrImpl.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/AttrImpl.java
new file mode 100644
index 0000000..7c0af33
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/AttrImpl.java
@@ -0,0 +1,780 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *     Balazs Banfai: Bug 154737 getUserData/setUserData support for Node
+ *     https://bugs.eclipse.org/bugs/show_bug.cgi?id=154737
+ *     
+ *     David Carver (STAR) - bug 296999 - Inefficient use of new String()
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import java.util.Iterator;
+import java.util.List;
+
+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.ITextRegionContainer;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.modelquery.ModelQueryUtil;
+import org.eclipse.wst.xml.core.internal.provisional.IXMLCharEntity;
+import org.eclipse.wst.xml.core.internal.provisional.IXMLNamespace;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMAttr;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+import org.w3c.dom.Attr;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.UserDataHandler;
+
+
+/**
+ * AttrImpl class
+ */
+public class AttrImpl extends NodeImpl implements IDOMAttr {
+
+	private ITextRegion equalRegion = null;
+
+	private char[] fName = null;
+	private ITextRegion nameRegion = null;
+	private ElementImpl ownerElement = null;
+	private ITextRegion fValueRegion = null;
+	private char[] fValueSource = null;
+	private char[] fNamespaceURI = null;
+
+	/**
+	 * AttrImpl constructor
+	 */
+	protected AttrImpl() {
+		super();
+	}
+
+	/**
+	 * AttrImpl constructor
+	 * 
+	 * @param that
+	 *            AttrImpl
+	 */
+	protected AttrImpl(AttrImpl that) {
+		super(that);
+
+		if (that != null) {
+			this.fName = that.fName;
+			String valueSource = that.getValueSource();
+			if (valueSource != null)
+				this.fValueSource = valueSource.toCharArray();
+		}
+	}
+
+	/**
+	 * cloneNode method
+	 * 
+	 * @return org.w3c.dom.Node
+	 */
+	public Node cloneNode(boolean deep) {
+		AttrImpl cloned = new AttrImpl(this);
+		notifyUserDataHandlers(UserDataHandler.NODE_CLONED, cloned);
+		return cloned;
+	}
+
+	/**
+	 */
+	protected CMAttributeDeclaration getDeclaration() {
+		ElementImpl element = (ElementImpl) getOwnerElement();
+		if (element == null)
+			return null;
+		CMElementDeclaration elementDecl = element.getDeclaration();
+		if (elementDecl == null)
+			return null;
+
+		List nodes = ModelQueryUtil.getModelQuery(getOwnerDocument()).getAvailableContent(getOwnerElement(), elementDecl, ModelQuery.INCLUDE_ATTRIBUTES);
+		String name = getName();
+		for (int k = 0; k < nodes.size(); k++) {
+			CMNode cmnode = (CMNode) nodes.get(k);
+			if (cmnode.getNodeType() == CMNode.ATTRIBUTE_DECLARATION && name.equals(cmnode.getNodeName())) {
+				return (CMAttributeDeclaration) cmnode;
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * getEndOffset method
+	 * 
+	 * @return int
+	 */
+	public int getEndOffset() {
+		if (this.ownerElement == null)
+			return 0;
+		int offset = this.ownerElement.getStartOffset();
+		if (this.fValueRegion != null) {
+			return (offset + this.fValueRegion.getEnd());
+		}
+		if (this.equalRegion != null) {
+			return (offset + this.equalRegion.getEnd());
+		}
+		if (this.nameRegion != null) {
+			return (offset + this.nameRegion.getEnd());
+		}
+		return 0;
+	}
+
+
+	public ITextRegion getEqualRegion() {
+		return this.equalRegion;
+	}
+
+	public String getLocalName() {
+		if (this.fName == null)
+			return null;
+		int index = CharOperation.indexOf(this.fName, ':');
+		if (index < 0)
+			return new String(this.fName);
+		return new String(this.fName, index + 1, this.fName.length - index - 1);
+	}
+
+	/**
+	 * getName method
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getName() {
+		if (this.fName == null)
+			return NodeImpl.EMPTY_STRING;
+		return new String(this.fName);
+	}
+
+
+	public ITextRegion getNameRegion() {
+		return this.nameRegion;
+	}
+
+	public int getNameRegionEndOffset() {
+		if (this.ownerElement == null)
+			return 0;
+		// assuming the firstStructuredDocumentRegion is the one that contains
+		// attributes
+		IStructuredDocumentRegion flatNode = this.ownerElement.getFirstStructuredDocumentRegion();
+		if (flatNode == null)
+			return 0;
+		return flatNode.getEndOffset(this.nameRegion);
+	}
+
+	public int getNameRegionStartOffset() {
+		if (this.ownerElement == null)
+			return 0;
+		// assuming the firstStructuredDocumentRegion is the one that contains
+		// attributes
+		IStructuredDocumentRegion flatNode = this.ownerElement.getFirstStructuredDocumentRegion();
+		if (flatNode == null)
+			return 0;
+		return flatNode.getStartOffset(this.nameRegion);
+	}
+
+	public String getNameRegionText() {
+		if (this.ownerElement == null)
+			return null;
+		// assuming the firstStructuredDocumentRegion is the one that contains
+		// attributes
+		IStructuredDocumentRegion flatNode = this.ownerElement.getFirstStructuredDocumentRegion();
+		if (flatNode == null)
+			return null;
+		return flatNode.getText(this.nameRegion);
+	}
+
+	public int getNameRegionTextEndOffset() {
+		if (this.ownerElement == null)
+			return 0;
+		// assuming the firstStructuredDocumentRegion is the one that contains
+		// attributes
+		IStructuredDocumentRegion flatNode = this.ownerElement.getFirstStructuredDocumentRegion();
+		if (flatNode == null)
+			return 0;
+		return flatNode.getTextEndOffset(this.nameRegion);
+	}
+
+	public String getNamespaceURI() {
+		String nsAttrName = null;
+		String prefix = getPrefix();
+		if (prefix != null && prefix.length() > 0) {
+			if (prefix.equals(IXMLNamespace.XMLNS)) {
+				// fixed URI
+				return IXMLNamespace.XMLNS_URI;
+			}
+			else if (prefix.equals(IXMLNamespace.XML)) {
+				// fixed URI
+				return IXMLNamespace.XML_URI;
+			}
+
+			nsAttrName = IXMLNamespace.XMLNS_PREFIX + prefix;
+		}
+		else {
+			String name = getName();
+			if (name != null && name.equals(IXMLNamespace.XMLNS)) {
+				// fixed URI
+				return IXMLNamespace.XMLNS_URI;
+			}
+			// does not inherit namespace from owner element
+			// if (this.ownerElement != null) return
+			// this.ownerElement.getNamespaceURI();
+			if (this.fNamespaceURI == null)
+				return null;
+			return new String(this.fNamespaceURI);
+		}
+
+		for (Node node = this.ownerElement; node != null; node = node.getParentNode()) {
+			if (node.getNodeType() != ELEMENT_NODE)
+				break;
+			Element element = (Element) node;
+			Attr attr = element.getAttributeNode(nsAttrName);
+			if (attr != null)
+				return attr.getValue();
+		}
+
+		if (this.fNamespaceURI == null)
+			return null;
+		return new String(this.fNamespaceURI);
+	}
+
+	/**
+	 * getNodeName method
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getNodeName() {
+		return getName();
+	}
+
+	/**
+	 * getNodeType method
+	 * 
+	 * @return short
+	 */
+	public short getNodeType() {
+		return ATTRIBUTE_NODE;
+	}
+
+	/**
+	 * getNodeValue method
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getNodeValue() {
+		return getValue();
+	}
+
+	/**
+	 * getOwnerElement method
+	 * 
+	 * @return org.w3c.dom.Element
+	 */
+	public Element getOwnerElement() {
+		return this.ownerElement;
+	}
+
+	/**
+	 */
+	public String getPrefix() {
+		if (this.fName == null)
+			return null;
+		int index = CharOperation.indexOf(this.fName, ':');
+		if (index <= 0)
+			return null;
+		// exclude JSP tag in name
+		if (this.fName[0] == '<')
+			return null;
+		return new String(this.fName, 0, index);
+	}
+
+	/**
+	 * getSpecified method
+	 * 
+	 * @return boolean
+	 */
+	public boolean getSpecified() {
+		// if there is no underlying document region, 
+		// then this attributes value has not really be specified
+		// yet in the document, and any returned values, such as 
+		// an empty string or a default value are being supplied
+		// as per spec, not per what's in the users document.
+		return this.fValueRegion != null;
+	}
+
+	/**
+	 * getStartOffset method
+	 * 
+	 * @return int
+	 */
+	public int getStartOffset() {
+		if (this.ownerElement == null)
+			return 0;
+		int offset = this.ownerElement.getStartOffset();
+		if (this.nameRegion != null) {
+			return (offset + this.nameRegion.getStart());
+		}
+		if (this.equalRegion != null) {
+			return (offset + this.equalRegion.getStart());
+		}
+		if (this.fValueRegion != null) {
+			return (offset + this.fValueRegion.getStart());
+		}
+		return 0;
+	}
+
+	/**
+	 * getValue method
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getValue() {
+		return getValue(getValueSource());
+	}
+
+	/**
+	 * Returns value for the source
+	 */
+	private String getValue(String source) {
+		if (source == null)
+			return NodeImpl.EMPTY_STRING;
+		if (source.length() == 0)
+			return source;
+		StringBuffer buffer = null;
+		int offset = 0;
+		int length = source.length();
+		int ref = source.indexOf('&');
+		while (ref >= 0) {
+			int end = source.indexOf(';', ref + 1);
+			if (end > ref + 1) {
+				String name = source.substring(ref + 1, end);
+				String value = getCharValue(name);
+				if (value != null) {
+					if (buffer == null)
+						buffer = new StringBuffer(length);
+					if (ref > offset)
+						buffer.append(source.substring(offset, ref));
+					buffer.append(value);
+					offset = end + 1;
+					ref = end;
+				}
+			}
+			ref = source.indexOf('&', ref + 1);
+		}
+		if (buffer == null)
+			return source;
+		if (length > offset)
+			buffer.append(source.substring(offset));
+		return buffer.toString();
+	}
+
+	public ITextRegion getValueRegion() {
+		return this.fValueRegion;
+	}
+
+	/**
+	 * ISSUE: what should behavior be if this.value == null? It's an "error"
+	 * to be in that state, but seems to occur relatively easily ... probably
+	 * due to threading bugs ... but this just shows its needs to be spec'd.
+	 * 
+	 */
+	public int getValueRegionStartOffset() {
+		if (this.ownerElement == null)
+			return 0;
+		// assuming the firstStructuredDocumentRegion is the one that contains
+		// the valueRegion -- should make smarter?
+		IStructuredDocumentRegion structuredDocumentRegion = this.ownerElement.getFirstStructuredDocumentRegion();
+		if (structuredDocumentRegion == null)
+			return 0;
+		// ensure we never pass null to getStartOffset.
+		if (this.fValueRegion == null) {
+			return 0;
+		}
+		return structuredDocumentRegion.getStartOffset(this.fValueRegion);
+	}
+
+	public String getValueRegionText() {
+		if (this.ownerElement == null)
+			return null;
+		// assuming the firstStructuredDocumentRegion is the one that contains
+		// attributes
+		IStructuredDocumentRegion flatNode = this.ownerElement.getFirstStructuredDocumentRegion();
+		if (flatNode == null)
+			return null;
+		if (this.fValueRegion == null)
+			return null;
+		return flatNode.getText(this.fValueRegion);
+	}
+
+	/**
+	 */
+	public String getValueSource() {
+		if (this.fValueSource != null)
+			return new String(this.fValueSource);
+		// DW: 4/16/2003 due to change in structuredDocument ... we need a
+		// flatnode to
+		// get at region values. For now I'll assume this is always the first
+		// flatnode .. may need to make smarter later (e.g. to search for
+		// the flatnode that this.valueRegion belongs to.
+		// DW: 4/30/2003 For some reason, this method is getting called a lot
+		// Not sure if its a threading problem, or a fundamental error
+		// elsewhere.
+		// It needs more investigation, but in the use cases I've seen,
+		// doesn't
+		// seem to hurt to simply return null in those cases. I saw this null
+		// case,
+		// when trying go format an XML file.
+		if (this.ownerElement == null)
+			return null;
+		//attribute values will always be in the start region
+		IStructuredDocumentRegion ownerRegion = this.ownerElement.getStartStructuredDocumentRegion();
+		if (ownerRegion == null)
+			return null;
+		if (this.fValueRegion != null)
+			return StructuredDocumentRegionUtil.getAttrValue(ownerRegion, this.fValueRegion);
+		return NodeImpl.EMPTY_STRING;
+	}
+
+	private String getValueSource(ElementImpl ownerElement) {
+		if (this.fValueSource != null)
+			return new String(this.fValueSource);
+		// DW: 4/16/2003 due to change in structuredDocument ... we need a
+		// flatnode to
+		// get at region values. For now I'll assume this is always the first
+		// flatnode .. may need to make smarter later (e.g. to search for
+		// the flatnode that this.valueRegion belongs to.
+		if (this.fValueRegion != null)
+			return StructuredDocumentRegionUtil.getAttrValue(ownerElement.getStructuredDocumentRegion(), this.fValueRegion);
+		return NodeImpl.EMPTY_STRING;
+	}
+
+	/**
+	 */
+	private String getValueSource(String value) {
+		if (value == null)
+			return null;
+		if (value.length() == 0)
+			return value;
+		StringBuffer buffer = null;
+		int offset = 0;
+		int length = value.length();
+		int amp = value.indexOf('&');
+		while (amp >= 0) {
+			if (buffer == null)
+				buffer = new StringBuffer(length + 4);
+			if (amp > offset)
+				buffer.append(value.substring(offset, amp));
+			buffer.append(IXMLCharEntity.AMP_REF);
+			offset = amp + 1;
+			amp = value.indexOf('&', offset);
+		}
+		if (buffer == null)
+			return value;
+		if (length > offset)
+			buffer.append(value.substring(offset));
+		return buffer.toString();
+	}
+
+	/**
+	 * Check if Attr has JSP in value
+	 */
+	public boolean hasNestedValue() {
+		if (this.fValueRegion == null)
+			return false;
+		if (!(this.fValueRegion instanceof ITextRegionContainer))
+			return false;
+		ITextRegionList regions = ((ITextRegionContainer) this.fValueRegion).getRegions();
+		if (regions == null)
+			return false;
+		Iterator e = regions.iterator();
+		while (e.hasNext()) {
+			ITextRegion region = (ITextRegion) e.next();
+			if (region == null)
+				continue;
+			String regionType = region.getType();
+			if (regionType == DOMRegionContext.XML_TAG_OPEN || isNestedLanguageOpening(regionType))
+				return true;
+		}
+		return false;
+	}
+
+	/**
+	 * Check if Attr has only name but not equal sign nor value
+	 */
+	public boolean hasNameOnly() {
+		return (this.nameRegion != null && this.equalRegion == null && this.fValueRegion == null);
+	}
+
+	/**
+	 */
+	protected final boolean hasPrefix() {
+		if (this.fName == null || this.fName.length == 0)
+			return false;
+		return CharOperation.indexOf(this.fName, ':') > 0 && this.fName[0] != '<';
+	}
+	
+	/**
+	 */
+	protected final boolean ignoreCase() {
+		if (this.ownerElement != null) {
+			if (this.ownerElement.ignoreCase()) {
+				return !hasPrefix();
+			}
+		}
+		else {
+			DocumentImpl document = (DocumentImpl) getOwnerDocument();
+			if (document != null && document.ignoreCase()) {
+				// even in case insensitive document, if having prefix, it's
+				// case sensitive
+				return !hasPrefix();
+			}
+		}
+		return false;
+	}
+
+	/**
+	 */
+	public boolean isGlobalAttr() {
+		if (hasPrefix())
+			return false;
+		if (this.ownerElement == null)
+			return false;
+		return this.ownerElement.isGlobalTag();
+	}
+
+	/**
+	 */
+	public final boolean isXMLAttr() {
+		if (this.ownerElement != null) {
+			if (!this.ownerElement.isXMLTag()) {
+				return hasPrefix();
+			}
+		}
+		else {
+			DocumentImpl document = (DocumentImpl) getOwnerDocument();
+			if (document != null && !document.isXMLType()) {
+				// even in non-XML document, if having prefix, it's XML tag
+				return hasPrefix();
+			}
+		}
+		return true;
+	}
+
+	/**
+	 * matchName method
+	 * 
+	 * @return boolean
+	 * @param name
+	 *            java.lang.String
+	 */
+	protected boolean matchName(String name) {
+		if (name == null)
+			return (this.fName == null);
+		if (this.fName == null)
+			return false;
+		return CharOperation.equals(this.fName, name.toCharArray(), ignoreCase());
+	}
+
+	protected boolean matchName(char[] name) {
+		if (name == null)
+			return (this.fName == null);
+		if (this.fName == null)
+			return false;
+		return CharOperation.equals(this.fName, name, ignoreCase());
+	}
+
+
+	/**
+	 * notifyValueChanged method
+	 */
+	protected void notifyNameChanged() {
+		if (this.ownerElement == null)
+			return;
+		DocumentImpl document = (DocumentImpl) this.ownerElement.getContainerDocument();
+		if (document == null)
+			return;
+		DOMModelImpl model = (DOMModelImpl) document.getModel();
+		if (model == null)
+			return;
+		model.nameChanged(this);
+	}
+
+	/**
+	 * notifyValueChanged method
+	 */
+	protected void notifyValueChanged() {
+		if (this.ownerElement == null)
+			return;
+		DocumentImpl document = (DocumentImpl) this.ownerElement.getContainerDocument();
+		if (document == null)
+			return;
+		DOMModelImpl model = (DOMModelImpl) document.getModel();
+		if (model == null)
+			return;
+		model.valueChanged(this);
+	}
+
+	/**
+	 * removeRegions method
+	 */
+	void removeRegions() {
+		this.nameRegion = null;
+		this.fValueRegion = null;
+		this.equalRegion = null;
+	}
+
+	/**
+	 */
+	void resetRegions() {
+		this.fValueSource = getValueSource().toCharArray();
+		removeRegions();
+	}
+
+	/**
+	 */
+	void resetRegions(ElementImpl ownerElement) {
+		this.fValueSource = getValueSource(ownerElement).toCharArray();
+		removeRegions();
+	}
+
+	void setEqualRegion(ITextRegion equalRegion) {
+		this.equalRegion = equalRegion;
+	}
+
+	/**
+	 * setName method
+	 * 
+	 * @param name
+	 *            java.lang.String
+	 */
+	protected void setName(String name) {
+		String value = null;
+		int startOffset = 0;
+		if (this.ownerElement != null) {
+			value = getValue();
+			startOffset = this.ownerElement.getStartOffset();
+			this.ownerElement.notify(REMOVE, this, value, null, startOffset);
+		}
+		this.fName = CharacterStringPool.getCharString(name);
+		if (this.ownerElement != null) {
+			this.ownerElement.notify(ADD, this, null, value, startOffset);
+		}
+	}
+
+	void setNameRegion(ITextRegion nameRegion) {
+		this.nameRegion = nameRegion;
+	}
+
+	protected void setNamespaceURI(String namespaceURI) {
+		if (namespaceURI == null)
+			this.fNamespaceURI = null;
+		else
+			this.fNamespaceURI = namespaceURI.toCharArray();
+	}
+
+	/**
+	 * setNodeValue method
+	 * 
+	 * @param nodeValue
+	 *            java.lang.String
+	 */
+	public void setNodeValue(String nodeValue) throws DOMException {
+		setValue(nodeValue);
+	}
+
+	/**
+	 * setOwnerElement method
+	 * 
+	 * @param ownerElement
+	 *            org.w3c.dom.Element
+	 */
+	protected void setOwnerElement(Element ownerElement) {
+		this.ownerElement = (ElementImpl) ownerElement;
+	}
+
+	/**
+	 */
+	public void setPrefix(String prefix) throws DOMException {
+		if (this.ownerElement != null && !this.ownerElement.isDataEditable()) {
+			throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, DOMMessages.NO_MODIFICATION_ALLOWED_ERR);
+		}
+		int prefixLength = (prefix != null ? prefix.length() : 0);
+		String localName = getLocalName();
+		if (prefixLength == 0) {
+			setName(localName);
+			return;
+		}
+		if (localName == null)
+			localName = NodeImpl.EMPTY_STRING;
+		int localLength = localName.length();
+		StringBuffer buffer = new StringBuffer(prefixLength + 1 + localLength);
+		buffer.append(prefix);
+		buffer.append(':');
+		buffer.append(localName);
+		setName(buffer.toString());
+
+		notifyNameChanged();
+	}
+
+	/**
+	 * setValue method
+	 * 
+	 * @param value
+	 *            java.lang.String
+	 */
+	public void setValue(String value) {
+		// Remember: as we account for "floaters" in
+		// future, remember that some are created
+		// in the natural process of implementing
+		// DOM apis.
+		// this "self notification" of about/changed,
+		// is added for this case, because it known to
+		// be called from properties pages. Should be a
+		// added to all DOM Modifiying APIs eventually.
+		try {
+			getModel().aboutToChangeModel();
+			setValueSource(getValueSource(value));
+		}
+		finally {
+			getModel().changedModel();
+		}
+	}
+
+	void setValueRegion(ITextRegion valueRegion) {
+		this.fValueRegion = valueRegion;
+		if (valueRegion != null)
+			this.fValueSource = null;
+	}
+
+	public void setValueSource(String source) {
+		if (this.ownerElement != null && !this.ownerElement.isDataEditable()) {
+			throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, DOMMessages.NO_MODIFICATION_ALLOWED_ERR);
+		}
+		this.fValueSource = (source != null) ? source.toCharArray() : null;
+
+		notifyValueChanged();
+	}
+
+	/**
+	 * Subclasses must override
+	 * 
+	 * @param regionType
+	 * @return
+	 */
+	protected boolean isNestedLanguageOpening(String regionType) {
+		boolean result = false;
+		return result;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/CDATASectionImpl.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/CDATASectionImpl.java
new file mode 100644
index 0000000..1a3ad57
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/CDATASectionImpl.java
@@ -0,0 +1,148 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2009 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
+ *     
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *     Balazs Banfai: Bug 154737 getUserData/setUserData support for Node
+ *     https://bugs.eclipse.org/bugs/show_bug.cgi?id=154737
+ *     
+ *     David Carver (STAR) - bug 296999 - Inefficient use of new String()
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import java.util.Iterator;
+
+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.ITextRegionList;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+import org.w3c.dom.CDATASection;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Node;
+import org.w3c.dom.UserDataHandler;
+
+
+/**
+ * CDATASectionImpl class
+ */
+public class CDATASectionImpl extends TextImpl implements CDATASection {
+
+	/**
+	 * CDATASectionImpl constructor
+	 */
+	protected CDATASectionImpl() {
+		super();
+	}
+
+	/**
+	 * CDATASectionImpl constructor
+	 * 
+	 * @param that
+	 *            CDATASectionImpl
+	 */
+	protected CDATASectionImpl(CDATASectionImpl that) {
+		super(that);
+	}
+
+	/**
+	 * cloneNode method
+	 * 
+	 * @return org.w3c.dom.Node
+	 * @param deep
+	 *            boolean
+	 */
+	public Node cloneNode(boolean deep) {
+		CDATASectionImpl cloned = new CDATASectionImpl(this);
+		notifyUserDataHandlers(UserDataHandler.NODE_CLONED, cloned);
+		return cloned;
+	}
+
+	/**
+	 * getData method
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getData() throws DOMException {
+		// instead of super(TextImpl).getData(), call getCharacterData()
+		char[] data = getCharacterData();
+		if (data == null) {
+			String sdata = getData(getStructuredDocumentRegion());
+			if (sdata != null)
+				return sdata;
+			return NodeImpl.EMPTY_STRING;
+		}
+		return new String(data);
+	}
+
+	/**
+	 */
+	private String getData(IStructuredDocumentRegion flatNode) {
+		if (flatNode == null)
+			return null;
+		ITextRegionList regions = flatNode.getRegions();
+		if (regions == null)
+			return null;
+
+		ITextRegion contentRegion = null;
+		StringBuffer buffer = null;
+		Iterator e = regions.iterator();
+		while (e.hasNext()) {
+			ITextRegion region = (ITextRegion) e.next();
+			String regionType = region.getType();
+			if (regionType == DOMRegionContext.XML_CDATA_OPEN || regionType == DOMRegionContext.XML_CDATA_CLOSE) {
+				continue;
+			}
+			if (contentRegion == null) { // first content
+				contentRegion = region;
+			} else { // multiple contents
+				if (buffer == null) {
+					buffer = new StringBuffer(flatNode.getText(contentRegion));
+				}
+				buffer.append(flatNode.getText(region));
+			}
+		}
+
+		if (buffer != null)
+			return buffer.toString();
+		if (contentRegion != null)
+			return flatNode.getText(contentRegion);
+		return null;
+	}
+
+	/**
+	 * getNodeName method
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getNodeName() {
+		return "#cdata-section";//$NON-NLS-1$
+	}
+
+	/**
+	 * getNodeType method
+	 * 
+	 * @return short
+	 */
+	public short getNodeType() {
+		return CDATA_SECTION_NODE;
+	}
+
+	/**
+	 */
+	public boolean isClosed() {
+		IStructuredDocumentRegion flatNode = getStructuredDocumentRegion();
+		if (flatNode == null)
+			return true; // will be generated
+		String regionType = StructuredDocumentRegionUtil.getLastRegionType(flatNode);
+		return (regionType == DOMRegionContext.XML_CDATA_CLOSE);
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/CMNodeUtil.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/CMNodeUtil.java
new file mode 100644
index 0000000..ae533ab
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/CMNodeUtil.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+
+
+/**
+ */
+public class CMNodeUtil {
+
+	/**
+	 */
+	public static CMAttributeDeclaration getAttributeDeclaration(Attr attr) {
+		if (attr == null)
+			return null;
+		return ((AttrImpl) attr).getDeclaration();
+	}
+
+	/**
+	 */
+	public static CMElementDeclaration getElementDeclaration(Element element) {
+		if (element == null)
+			return null;
+		return ((ElementImpl) element).getDeclaration();
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/CharOperation.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/CharOperation.java
new file mode 100644
index 0000000..2f9f8a9
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/CharOperation.java
@@ -0,0 +1,107 @@
+/*******************************************************************************

+ * Copyright (c) 2009, 2011 IBM Corporation and others.

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *     IBM Corporation - initial API and implementation

+ *******************************************************************************/

+package org.eclipse.wst.xml.core.internal.document;

+

+class CharOperation {

+

+	private CharOperation() {

+	}

+

+	static int indexOf(char[] array, char c) {

+		return indexOf(array, c, 0);

+	}

+

+	static int indexOf(char[] array, char c, int start) {

+		for (int i = start; i < array.length; i++) {

+			if (array[i] == c)

+				return i;

+		}

+		return -1;

+	}

+

+

+	/**

+	 * note: This method taken from

+	 * org.eclipse.jdt.core.compiler.CharOperation

+	 * 

+	 * Answers true if the two arrays are identical character by character,

+	 * otherwise false, respecting the value of ignoreCase. <br>

+	 * <br>

+	 * For example:

+	 * <ol>

+	 * <li>

+	 * 

+	 * <pre>

+	 *    first = null

+	 *    second = null

+	 *    result => true

+	 * </pre>

+	 * 

+	 * </li>

+	 * <li>

+	 * 

+	 * <pre>

+	 *    first = { }

+	 *    second = null

+	 *    result => false

+	 * </pre>

+	 * 

+	 * </li>

+	 * <li>

+	 * 

+	 * <pre>

+	 *    first = { 'a' }

+	 *    second = { 'a' }

+	 *    result => true

+	 * </pre>

+	 * 

+	 * </li>

+	 * <li>

+	 * 

+	 * <pre>

+	 *    first = { 'a' }

+	 *    second = { 'A' }

+	 *    result => false

+	 * </pre>

+	 * 

+	 * </li>

+	 * </ol>

+	 * 

+	 * @param first

+	 *            the first array

+	 * @param second

+	 *            the second array

+	 * @return true if the two arrays are identical character by character,

+	 *         otherwise false, acounting for <code>ignoreCase</code>

+	 */

+	public static final boolean equals(char[] first, char[] second, boolean ignoreCase) {

+		if (first == second)

+			return true;

+		if (first == null || second == null)

+			return false;

+		if (first.length != second.length)

+			return false;

+

+		for (int i = first.length; --i >= 0;) {

+			if (ignoreCase) {

+				if (Character.toUpperCase(first[i]) != Character.toUpperCase(second[i])) {

+					return false;

+				}

+			}

+			else {

+				if (first[i] != second[i]) {

+					return false;

+				}

+			}

+		}

+		return true;

+	}

+}

diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/CharacterDataImpl.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/CharacterDataImpl.java
new file mode 100644
index 0000000..d1b931e
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/CharacterDataImpl.java
@@ -0,0 +1,355 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     David Carver (STAR) - bug 296999 - Inefficient use of new String()
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.w3c.dom.CharacterData;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Node;
+
+
+/**
+ * CharacterDataImpl class
+ */
+public abstract class CharacterDataImpl extends NodeImpl implements CharacterData {
+
+	private char[] data = null;
+
+	/**
+	 * CharacterDataImpl constructor
+	 */
+	protected CharacterDataImpl() {
+		super();
+	}
+
+	/**
+	 * CharacterDataImpl constructor
+	 * 
+	 * @param that
+	 *            CharacterDataImpl
+	 */
+	protected CharacterDataImpl(CharacterDataImpl that) {
+		super(that);
+
+		if (that != null) {
+			this.data = that.getData().toCharArray();
+		}
+	}
+
+	/**
+	 * appendData method
+	 * 
+	 * @param arg
+	 *            java.lang.String
+	 */
+	public void appendData(String arg) throws DOMException {
+		if (arg == null)
+			return;
+
+		String data = getData();
+		if (data == null)
+			data = arg;
+		else
+			data += arg;
+		setData(data);
+	}
+
+	/**
+	 * deleteData method
+	 * 
+	 * @param offset
+	 *            int
+	 * @param count
+	 *            int
+	 */
+	public void deleteData(int offset, int count) throws DOMException {
+		if (count == 0)
+			return;
+		if (!isDataEditable()) {
+			throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, DOMMessages.NO_MODIFICATION_ALLOWED_ERR);
+		}
+
+		if (count < 0 || offset < 0) {
+			throw new DOMException(DOMException.INDEX_SIZE_ERR, DOMMessages.INDEX_SIZE_ERR);
+		}
+
+		String data = getData();
+		if (data == null) {
+			throw new DOMException(DOMException.INDEX_SIZE_ERR, DOMMessages.INDEX_SIZE_ERR);
+		}
+		int length = data.length();
+		if (offset > length) {
+			throw new DOMException(DOMException.INDEX_SIZE_ERR, DOMMessages.INDEX_SIZE_ERR);
+		}
+		if (offset == 0) {
+			if (count > length) {
+				throw new DOMException(DOMException.INDEX_SIZE_ERR, DOMMessages.INDEX_SIZE_ERR);
+			}
+			if (count == length)
+				data = NodeImpl.EMPTY_STRING;
+			else
+				data = data.substring(count);
+		} else {
+			int end = offset + count;
+			if (end > length) {
+				throw new DOMException(DOMException.INDEX_SIZE_ERR, DOMMessages.INDEX_SIZE_ERR);
+			}
+			if (end == length)
+				data = data.substring(0, offset);
+			else
+				data = data.substring(0, offset) + data.substring(end);
+		}
+		setData(data);
+	}
+
+	/**
+	 */
+	protected final char[] getCharacterData() {
+		return this.data;
+	}
+
+	/**
+	 * getData method
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getData() throws DOMException {
+		char[] cdata = getCharacterData();
+		if (cdata != null)
+			return new String(cdata);
+		return null;
+	}
+
+	/**
+	 * getLength method
+	 * 
+	 * @return int
+	 */
+	public int getLength() {
+		String data = getData();
+		if (data == null)
+			return 0;
+		return data.length();
+	}
+
+	/**
+	 * getNodeValue method
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getNodeValue() {
+		return getData();
+	}
+
+	/**
+	 * insertData method
+	 * 
+	 * @param offset
+	 *            int
+	 * @param arg
+	 *            java.lang.String
+	 */
+	public void insertData(int offset, String arg) throws DOMException {
+		if (arg == null)
+			return;
+
+		if (!isDataEditable()) {
+			throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, DOMMessages.NO_MODIFICATION_ALLOWED_ERR);
+		}
+
+		if (offset < 0) {
+			throw new DOMException(DOMException.INDEX_SIZE_ERR, DOMMessages.INDEX_SIZE_ERR);
+		}
+
+		String data = getData();
+		if (data == null) {
+			if (offset > 0) {
+				throw new DOMException(DOMException.INDEX_SIZE_ERR, DOMMessages.INDEX_SIZE_ERR);
+			}
+			data = arg;
+		} else if (offset == 0) {
+			data = arg + data;
+		} else {
+			int length = data.length();
+			if (offset > length) {
+				throw new DOMException(DOMException.INDEX_SIZE_ERR, DOMMessages.INDEX_SIZE_ERR);
+			}
+			if (offset == length)
+				data += arg;
+			else
+				data = data.substring(0, offset) + arg + data.substring(offset);
+		}
+		setData(data);
+	}
+
+	/**
+	 * isJSPContent method
+	 * 
+	 * @return boolean
+	 */
+	public boolean isJSPContent() {
+		Node parent = getParentNode();
+		if (parent == null || parent.getNodeType() != Node.ELEMENT_NODE)
+			return false;
+		ElementImpl element = (ElementImpl) parent;
+		return element.isJSPContainer();
+	}
+
+	/**
+	 * replaceData method
+	 * 
+	 * @param offset
+	 *            int
+	 * @param count
+	 *            int
+	 * @param arg
+	 *            java.lang.String
+	 */
+	public void replaceData(int offset, int count, String arg) throws DOMException {
+		if (!isDataEditable()) {
+			throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, DOMMessages.NO_MODIFICATION_ALLOWED_ERR);
+		}
+
+		if (arg == null) {
+			deleteData(offset, count);
+			return;
+		}
+		if (count == 0) {
+			insertData(offset, arg);
+			return;
+		}
+		if (offset < 0 || count < 0) {
+			throw new DOMException(DOMException.INDEX_SIZE_ERR, DOMMessages.INDEX_SIZE_ERR);
+		}
+
+		String data = getData();
+		if (data == null) {
+			throw new DOMException(DOMException.INDEX_SIZE_ERR, DOMMessages.INDEX_SIZE_ERR);
+		} else if (offset == 0) {
+			int length = data.length();
+			if (count > length) {
+				throw new DOMException(DOMException.INDEX_SIZE_ERR, DOMMessages.INDEX_SIZE_ERR);
+			}
+			if (count == length)
+				data = arg;
+			else
+				data = arg + data.substring(count);
+		} else {
+			int length = data.length();
+			int end = offset + count;
+			if (end > length) {
+				throw new DOMException(DOMException.INDEX_SIZE_ERR, DOMMessages.INDEX_SIZE_ERR);
+			}
+			if (end == length)
+				data = data.substring(0, offset) + arg;
+			else
+				data = data.substring(0, offset) + arg + data.substring(end);
+		}
+		setData(data);
+	}
+
+	/**
+	 */
+	void resetStructuredDocumentRegions() {
+		this.data = getData().toCharArray();
+		setStructuredDocumentRegion(null);
+	}
+
+	/**
+	 * setData method
+	 * 
+	 * @param data
+	 *            java.lang.String
+	 */
+	public void setData(String data) throws DOMException {
+		if (!isDataEditable()) {
+			throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, DOMMessages.NO_MODIFICATION_ALLOWED_ERR);
+		}
+
+		this.data = (data != null ? data.toCharArray() : null);
+
+		notifyValueChanged();
+	}
+
+	/**
+	 * setNodeValue method
+	 * 
+	 * @param nodeValue
+	 *            java.lang.String
+	 */
+	public void setNodeValue(String nodeValue) throws DOMException {
+		setData(nodeValue);
+	}
+
+	/**
+	 */
+	void setStructuredDocumentRegion(IStructuredDocumentRegion flatNode) {
+		super.setStructuredDocumentRegion(flatNode);
+		if (flatNode != null)
+			this.data = null;
+	}
+
+	/**
+	 * substringData method
+	 * 
+	 * @return java.lang.String
+	 * @param offset
+	 *            int
+	 * @param count
+	 *            int
+	 */
+	public String substringData(int offset, int count) throws DOMException {
+		if (count == 0)
+			return NodeImpl.EMPTY_STRING;
+		if (offset < 0 || count < 0) {
+			throw new DOMException(DOMException.INDEX_SIZE_ERR, DOMMessages.INDEX_SIZE_ERR);
+		}
+
+		String data = getData();
+		if (data == null) {
+			throw new DOMException(DOMException.INDEX_SIZE_ERR, DOMMessages.INDEX_SIZE_ERR);
+		}
+		int length = data.length();
+		if (offset == 0 && count == length)
+			return data;
+		if (offset > length) {
+			throw new DOMException(DOMException.INDEX_SIZE_ERR, DOMMessages.INDEX_SIZE_ERR);
+		}
+		int end = offset + count;
+		if (end > length) {
+			throw new DOMException(DOMException.INDEX_SIZE_ERR, DOMMessages.INDEX_SIZE_ERR);
+		}
+		return data.substring(offset, end);
+	}
+
+	/**
+	 * toString method
+	 * 
+	 * @return java.lang.String
+	 */
+	public String toString() {
+		StringBuffer buffer = new StringBuffer();
+		buffer.append(getNodeName());
+		buffer.append('(');
+		buffer.append(getData());
+		buffer.append(')');
+		IStructuredDocumentRegion flatNode = getStructuredDocumentRegion();
+		if (flatNode != null) {
+			buffer.append('@');
+			buffer.append(flatNode.toString());
+		}
+		return buffer.toString();
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/CharacterStringPool.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/CharacterStringPool.java
new file mode 100644
index 0000000..3bdb388
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/CharacterStringPool.java
@@ -0,0 +1,100 @@
+/*******************************************************************************
+ * Copyright (c) 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+import java.util.LinkedHashMap;
+
+/**
+ * Organizes a pool of frequently used Strings as character arrays.
+ * 
+ */
+final class CharacterStringPool {
+
+	static private LinkedHashMap fPool = new LimitedHashMap();
+
+	static private class LimitedHashMap extends LinkedHashMap {
+		private static final long serialVersionUID = 1L;
+		private static final int MAX = 500;
+
+		public LimitedHashMap() {
+			super(MAX / 10, .75f, true);
+		}
+		protected boolean removeEldestEntry(java.util.Map.Entry eldest) {
+			return size() > MAX;
+		}
+	}
+
+	static private class CharArray {
+		char[] fArray;
+		/**
+		 * Answers a hashcode for the array. Algorithm from org.eclipse.jdt.core.compiler.CharOperation
+		 *
+		 * @param array the array for which a hashcode is required
+		 * @return the hashcode
+		 * @throws NullPointerException if array is null
+		 */
+		public int hashCode() {
+			int length = fArray.length;
+			int hash = length == 0 ? 31 : fArray[0];
+			if (length < 8) {
+				for (int i = length; --i > 0;)
+					hash = (hash * 31) + fArray[i];
+			} else {
+				// 8 characters is enough to compute a decent hash code, don't waste time examining every character
+				for (int i = length - 1, last = i > 16 ? i - 16 : 0; i > last; i -= 2)
+					hash = (hash * 31) + fArray[i];
+			}
+			return hash & 0x7FFFFFFF;
+		}
+
+		public boolean equals(Object obj) {
+			if (this == obj)
+				return true;
+			if (!(obj instanceof CharArray))
+				return false;
+			CharArray other = (CharArray) obj;
+			if (fArray.length != other.fArray.length)
+				return false;
+			for (int i = 0; i < fArray.length; i++) {
+				if (fArray[i] != other.fArray[i])
+					return false;
+			}
+			return true;
+		}
+	}
+
+	private CharacterStringPool() {
+	}
+
+	/**
+	 * Returns the character array for <code>string</code>. If
+	 * the character array is already in the pool for character arrays,
+	 * the array is reused.
+	 * 
+	 * @param string the string to retrieve the character array for
+	 * @return a pooled instance of the character array
+	 */
+	public static char[] getCharString(String string) {
+		CharArray array = new CharArray();
+		array.fArray = string.toCharArray();
+
+		Object obj = null;
+		synchronized (fPool) {
+			obj = fPool.get(array);
+			if (obj == null) {
+				obj = array;
+				fPool.put(obj, obj);
+			}
+		}
+		return ((CharArray) obj).fArray;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/CommentImpl.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/CommentImpl.java
new file mode 100644
index 0000000..4a817e0
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/CommentImpl.java
@@ -0,0 +1,204 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *     Balazs Banfai: Bug 154737 getUserData/setUserData support for Node
+ *     https://bugs.eclipse.org/bugs/show_bug.cgi?id=154737
+ *     David Carver (STAR) - bug 296999 - Inefficient use of new String()
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import java.util.Iterator;
+
+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.ITextRegionList;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+import org.w3c.dom.Comment;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Node;
+import org.w3c.dom.UserDataHandler;
+
+
+/**
+ * CommentImpl class
+ */
+public class CommentImpl extends CharacterDataImpl implements Comment {
+
+	private boolean isJSPTag = false;
+
+	/**
+	 * CommentImpl constructor
+	 */
+	protected CommentImpl() {
+		super();
+	}
+
+	/**
+	 * CommentImpl constructor
+	 * 
+	 * @param that
+	 *            CommentImpl
+	 */
+	protected CommentImpl(CommentImpl that) {
+		super(that);
+
+		if (that != null) {
+			this.isJSPTag = that.isJSPTag;
+		}
+	}
+
+	/**
+	 * cloneNode method
+	 * 
+	 * @return org.w3c.dom.Node
+	 * @param deep
+	 *            boolean
+	 */
+	public Node cloneNode(boolean deep) {
+		CommentImpl cloned = new CommentImpl(this);
+		notifyUserDataHandlers(UserDataHandler.NODE_CLONED, cloned);
+		return cloned;
+	}
+
+	/**
+	 * getData method
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getData() throws DOMException {
+		char[] data = getCharacterData();
+		if (data == null) {
+			String sdata = getData(getStructuredDocumentRegion());
+			if (sdata != null)
+				return sdata;
+			return NodeImpl.EMPTY_STRING;
+		}
+		return new String(data);
+	}
+
+	/**
+	 */
+	private String getData(IStructuredDocumentRegion flatNode) {
+		if (flatNode == null)
+			return null;
+		ITextRegionList regions = flatNode.getRegions();
+		if (regions == null)
+			return null;
+
+		ITextRegion contentRegion = null;
+		StringBuffer buffer = null;
+		Iterator e = regions.iterator();
+		while (e.hasNext()) {
+			ITextRegion region = (ITextRegion) e.next();
+			String regionType = region.getType();
+			if (regionType == DOMRegionContext.XML_COMMENT_OPEN || regionType == DOMRegionContext.XML_COMMENT_CLOSE || isNestedCommentOpenClose(regionType)) {
+				continue;
+			}
+			if (contentRegion == null) { // first content
+				contentRegion = region;
+			}
+			else { // multiple contents
+				if (buffer == null) {
+					buffer = new StringBuffer(flatNode.getText(contentRegion));
+				}
+				buffer.append(flatNode.getText(region));
+			}
+		}
+
+		if (buffer != null)
+			return buffer.toString();
+		if (contentRegion != null)
+			return flatNode.getText(contentRegion);
+		return null;
+	}
+
+	/**
+	 * getNodeName method
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getNodeName() {
+		return "#comment";//$NON-NLS-1$
+	}
+
+	/**
+	 * getNodeType method
+	 * 
+	 * @return short
+	 */
+	public short getNodeType() {
+		return COMMENT_NODE;
+	}
+
+	/**
+	 */
+	public boolean isClosed() {
+		IStructuredDocumentRegion flatNode = getStructuredDocumentRegion();
+		if (flatNode == null)
+			return true; // will be generated
+		String regionType = StructuredDocumentRegionUtil.getLastRegionType(flatNode);
+		return (regionType == DOMRegionContext.XML_COMMENT_CLOSE || isNestedCommentClose(regionType));
+	}
+
+	/**
+	 * Subclasses must override
+	 * @param regionType
+	 * @return
+	 */
+	protected boolean isNestedCommentClose(String regionType) {
+		boolean result = false;
+		return result; 
+	}
+	/**
+	 * Subclasses must override
+	 * @param regionType
+	 * @return
+	 */
+	protected boolean isNestedCommentOpenClose(String regionType) {
+		boolean result = false;
+		return result; 
+	}
+																											
+	public boolean isJSPTag() {
+		return this.isJSPTag;
+	}
+
+	/**
+	 * setJSPTag method
+	 * 
+	 * @param isJSPTag
+	 *            boolean
+	 */
+	public void setJSPTag(boolean isJSPTag) {
+		if (isJSPTag == this.isJSPTag)
+			return;
+
+		if (!isDataEditable()) {
+			throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, DOMMessages.NO_MODIFICATION_ALLOWED_ERR);
+		}
+
+		DocumentImpl document = (DocumentImpl) getOwnerDocument();
+		if (isJSPTag) {
+			if (document == null || !document.isJSPType())
+				return;
+		}
+
+		this.isJSPTag = isJSPTag;
+
+		if (getContainerDocument() != null) {
+			// already in the tree, update IStructuredDocument
+			setData(getData()); // calls notifyValueChanged();
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/DOMMessages.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/DOMMessages.java
new file mode 100644
index 0000000..562f4b1
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/DOMMessages.java
@@ -0,0 +1,43 @@
+/*******************************************************************************

+ * Copyright (c) 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

+ *     

+ *******************************************************************************/

+package org.eclipse.wst.xml.core.internal.document;

+

+import org.eclipse.osgi.util.NLS;

+

+class DOMMessages extends NLS {

+	private static String BUNDLE_NAME = "org.eclipse.wst.xml.core.internal.document.DOMMessages"; //$NON-NLS-1$

+

+	static {

+		NLS.initializeMessages(BUNDLE_NAME, DOMMessages.class);

+	}

+

+	private DOMMessages() {

+	}

+

+	static String DOMSTRING_SIZE_ERR;

+	static String HIERARCHY_REQUEST_ERR;

+	static String INDEX_SIZE_ERR;

+	static String INUSE_ATTRIBUTE_ERR;

+	static String INVALID_ACCESS_ERR;

+	static String INVALID_CHARACTER_ERR;

+	static String INVALID_MODIFICATION_ERR;

+	static String INVALID_STATE_ERR;

+	static String NAMESPACE_ERR;

+	static String NO_DATA_ALLOWED_ERR;

+	static String NO_MODIFICATION_ALLOWED_ERR;

+	static String NOT_FOUND_ERR;

+	static String NOT_SUPPORTED_ERR;

+	static String SYNTAX_ERR;

+	static String TYPE_MISMATCH_ERR;

+	static String VALIDATION_ERR;

+	static String WRONG_DOCUMENT_ERR;

+}

diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/DOMMessages.properties b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/DOMMessages.properties
new file mode 100644
index 0000000..d0eac25
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/DOMMessages.properties
@@ -0,0 +1,17 @@
+DOMSTRING_SIZE_ERR=DOMString Size Error

+HIERARCHY_REQUEST_ERR=Invalid Hierarchy Request

+INDEX_SIZE_ERR=Incorrect Index Error

+INUSE_ATTRIBUTE_ERR=Attribute Node In Use Error

+INVALID_ACCESS_ERR=Invalid Access Error

+INVALID_CHARACTER_ERR=Invalid Characer Error

+INVALID_MODIFICATION_ERR=Invalid Modification Error

+INVALID_STATE_ERR=Invalid State Error

+NAMESPACE_ERR=Namespace Error

+NO_DATA_ALLOWED_ERR=No Data Allowed

+NO_MODIFICATION_ALLOWED_ERR=No Modification Allowed

+NOT_FOUND_ERR=Not Found

+NOT_SUPPORTED_ERR=Not Supported

+SYNTAX_ERR=Syntax Error

+TYPE_MISMATCH_ERR=Type Mismatch Error

+VALIDATION_ERR=Validation Error

+WRONG_DOCUMENT_ERR=Wrong Document

diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/DOMModelImpl.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/DOMModelImpl.java
new file mode 100644
index 0000000..367050e
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/DOMModelImpl.java
@@ -0,0 +1,915 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2011 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+import org.eclipse.wst.sse.core.internal.model.AbstractStructuredModel;
+import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
+import org.eclipse.wst.sse.core.internal.provisional.events.IStructuredDocumentListener;
+import org.eclipse.wst.sse.core.internal.provisional.events.NewDocumentEvent;
+import org.eclipse.wst.sse.core.internal.provisional.events.NoChangeEvent;
+import org.eclipse.wst.sse.core.internal.provisional.events.RegionChangedEvent;
+import org.eclipse.wst.sse.core.internal.provisional.events.RegionsReplacedEvent;
+import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentRegionsReplacedEvent;
+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.IStructuredDocumentRegionList;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList;
+import org.eclipse.wst.xml.core.internal.Logger;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
+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.provisional.document.ISourceGenerator;
+import org.w3c.dom.Attr;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+
+/**
+ * XMLModelImpl class
+ */
+public class DOMModelImpl extends AbstractStructuredModel implements IStructuredDocumentListener, IDOMModel, DOMImplementation {
+	private static String TRACE_PARSER_MANAGEMENT_EXCEPTION = "parserManagement"; //$NON-NLS-1$
+	private Object active = null;
+	private DocumentImpl document = null;
+	private ISourceGenerator generator = null;
+	private XMLModelNotifier notifier = null;
+	private XMLModelParser parser = null;
+	private boolean refresh = false;
+	private XMLModelUpdater updater = null;
+
+	/**
+	 * XMLModelImpl constructor
+	 */
+	public DOMModelImpl() {
+		super();
+		this.document = (DocumentImpl) internalCreateDocument();
+	}
+
+	/**
+	 * This API allows clients to declare that they are about to make a
+	 * "large" change to the model. This change might be in terms of content
+	 * or it might be in terms of the model id or base location.
+	 * 
+	 * Note that in the case of embedded calls, notification to listners is
+	 * sent only once.
+	 * 
+	 * Note that the client who is making these changes has the responsibility
+	 * to restore the models state once finished with the changes. See
+	 * getMemento and restoreState.
+	 * 
+	 * The method isModelStateChanging can be used by a client to determine if
+	 * the model is already in a change sequence.
+	 */
+	public void aboutToChangeModel() {
+		super.aboutToChangeModel();
+		// technically, no need to call beginChanging so often,
+		// since aboutToChangeModel can be nested.
+		// but will leave as is for this release.
+		// see modelChanged, and be sure stays coordinated there.
+		getModelNotifier().beginChanging();
+	}
+
+	public void aboutToReinitializeModel() {
+		XMLModelNotifier notifier = getModelNotifier();
+		notifier.cancelPending();
+		super.aboutToReinitializeModel();
+	}
+
+	/**
+	 * attrReplaced method
+	 * 
+	 * @param element
+	 *            org.w3c.dom.Element
+	 * @param newAttr
+	 *            org.w3c.dom.Attr
+	 * @param oldAttr
+	 *            org.w3c.dom.Attr
+	 */
+	protected void attrReplaced(Element element, Attr newAttr, Attr oldAttr) {
+		if (element == null)
+			return;
+		if (getActiveParser() == null) {
+			XMLModelUpdater updater = getModelUpdater();
+			setActive(updater);
+			updater.initialize();
+			updater.replaceAttr(element, newAttr, oldAttr);
+			setActive(null);
+		}
+		getModelNotifier().attrReplaced(element, newAttr, oldAttr);
+	}
+
+	/**
+	 * This API allows a client controlled way of notifying all ModelEvent
+	 * listners that the model has been changed. This method is a matched pair
+	 * to aboutToChangeModel, and must be called after aboutToChangeModel ...
+	 * or some listeners could be left waiting indefinitely for the changed
+	 * event. So, its suggested that changedModel always be in a finally
+	 * clause. Likewise, a client should never call changedModel without
+	 * calling aboutToChangeModel first.
+	 * 
+	 * In the case of embedded calls, the notification is just sent once.
+	 * 
+	 */
+	public void changedModel() {
+		// NOTE: the order of 'changedModel' and 'endChanging' is significant.
+		// By calling changedModel first, this basically decrements the
+		// "isChanging" counter
+		// in super class and when zero all listeners to model state events
+		// will be notified
+		// that the model has been changed. 'endChanging' will notify all
+		// deferred adapters.
+		// So, the significance of order is that adapters (and methods they
+		// call)
+		// can count on the state of model "isChanging" to be accurate.
+		// But, remember, that this means the "modelChanged" event can be
+		// received before all
+		// adapters have finished their processing.
+		// NOTE NOTE: The above note is obsolete in fact (though still states
+		// issue correctly).
+		// Due to popular demand, the order of these calls were reversed and
+		// behavior
+		// changed on 07/22/2004.
+		// 
+		// see also
+		// https://w3.opensource.ibm.com/bugzilla/show_bug.cgi?id=4302
+		// for motivation for this 'on verge of' call.
+		// this could be improved in future if notifier also used counting
+		// flag to avoid nested calls. If/when changed be sure to check if
+		// aboutToChangeModel needs any changes too.
+		if (isModelChangeStateOnVergeOfEnding()) {
+			// end lock before noticiation loop, since directly or indirectly
+			// we may be "called from foriegn code" during notification.
+			endLock();
+			// we null out here to avoid spurious"warning" message while debug
+			// tracing is enabled
+			fLockObject = null;
+			// the notifier is what controls adaper notification, which
+			// should be sent out before the 'modelChanged' event.
+			getModelNotifier().endChanging();
+		}
+		// changedModel handles 'nesting', so only one event sent out
+		// when mulitple calls to 'aboutToChange/Changed'.
+		super.changedModel();
+		handleRefresh();
+	}
+
+	/**
+	 * childReplaced method
+	 * 
+	 * @param parentNode
+	 *            org.w3c.dom.Node
+	 * @param newChild
+	 *            org.w3c.dom.Node
+	 * @param oldChild
+	 *            org.w3c.dom.Node
+	 */
+	protected void childReplaced(Node parentNode, Node newChild, Node oldChild) {
+		if (parentNode == null)
+			return;
+		if (getActiveParser() == null) {
+			XMLModelUpdater updater = getModelUpdater();
+			setActive(updater);
+			updater.initialize();
+			updater.replaceChild(parentNode, newChild, oldChild);
+			setActive(null);
+		}
+		getModelNotifier().childReplaced(parentNode, newChild, oldChild);
+	}
+
+	/**
+	 * Creates an XML <code>Document</code> object of the specified type
+	 * with its document element. HTML-only DOM implementations do not need to
+	 * implement this method.
+	 * 
+	 * @param namespaceURIThe
+	 *            namespace URI of the document element to create.
+	 * @param qualifiedNameThe
+	 *            qualified name of the document element to be created.
+	 * @param doctypeThe
+	 *            type of document to be created or <code>null</code>. When
+	 *            <code>doctype</code> is not <code>null</code>, its
+	 *            <code>Node.ownerDocument</code> attribute is set to the
+	 *            document being created.
+	 * @return A new <code>Document</code> object.
+	 * @exception DOMException
+	 *                INVALID_CHARACTER_ERR: Raised if the specified qualified
+	 *                name contains an illegal character. <br>
+	 *                NAMESPACE_ERR: Raised if the <code>qualifiedName</code>
+	 *                is malformed, if the <code>qualifiedName</code> has a
+	 *                prefix and the <code>namespaceURI</code> is
+	 *                <code>null</code>, or if the
+	 *                <code>qualifiedName</code> has a prefix that is "xml"
+	 *                and the <code>namespaceURI</code> is different from "
+	 *                http://www.w3.org/XML/1998/namespace" .<br>
+	 *                WRONG_DOCUMENT_ERR: Raised if <code>doctype</code> has
+	 *                already been used with a different document or was
+	 *                created from a different implementation.
+	 * @see DOM Level 2
+	 */
+	public Document createDocument(String namespaceURI, String qualifiedName, DocumentType doctype) throws DOMException {
+		return null;
+	}
+
+	/**
+	 * Creates an empty <code>DocumentType</code> node. Entity declarations
+	 * and notations are not made available. Entity reference expansions and
+	 * default attribute additions do not occur. It is expected that a future
+	 * version of the DOM will provide a way for populating a
+	 * <code>DocumentType</code>.<br>
+	 * HTML-only DOM implementations do not need to implement this method.
+	 * 
+	 * @param qualifiedNameThe
+	 *            qualified name of the document type to be created.
+	 * @param publicIdThe
+	 *            external subset public identifier.
+	 * @param systemIdThe
+	 *            external subset system identifier.
+	 * @return A new <code>DocumentType</code> node with
+	 *         <code>Node.ownerDocument</code> set to <code>null</code>.
+	 * @exception DOMException
+	 *                INVALID_CHARACTER_ERR: Raised if the specified qualified
+	 *                name contains an illegal character. <br>
+	 *                NAMESPACE_ERR: Raised if the <code>qualifiedName</code>
+	 *                is malformed.
+	 * @see DOM Level 2
+	 */
+	public DocumentType createDocumentType(String qualifiedName, String publicId, String systemId) throws DOMException {
+		DocumentTypeImpl documentType = new DocumentTypeImpl();
+		documentType.setName(qualifiedName);
+		documentType.setPublicId(publicId);
+		documentType.setSystemId(systemId);
+		return documentType;
+	}
+
+	/**
+	 */
+	protected void documentTypeChanged() {
+		if (this.refresh)
+			return;
+		// unlike 'resfresh', 'reinitialize' finishes loop
+		// and flushes remaining notification que before
+		// actually reinitializing.
+		// ISSUE: should reinit be used instead of handlerefresh?
+		// this.setReinitializeNeeded(true);
+		if (this.active != null || getModelNotifier().isChanging())
+			return; // defer
+		handleRefresh();
+	}
+
+	protected void editableChanged(Node node) {
+		if (node != null) {
+			getModelNotifier().editableChanged(node);
+		}
+	}
+
+	/**
+	 */
+	protected void endTagChanged(Element element) {
+		if (element == null)
+			return;
+		if (getActiveParser() == null) {
+			XMLModelUpdater updater = getModelUpdater();
+			setActive(updater);
+			updater.initialize();
+			updater.changeEndTag(element);
+			setActive(null);
+		}
+		getModelNotifier().endTagChanged(element);
+	}
+
+	/**
+	 */
+	private XMLModelParser getActiveParser() {
+		if (this.parser == null)
+			return null;
+		if (this.parser != this.active)
+			return null;
+		return this.parser;
+	}
+
+	/**
+	 */
+	private XMLModelUpdater getActiveUpdater() {
+		if (this.updater == null)
+			return null;
+		if (this.updater != this.active)
+			return null;
+		return this.updater;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class)
+	 */
+	public Object getAdapter(Class adapter) {
+		if (Document.class.equals(adapter))
+			return getDocument();
+		return super.getAdapter(adapter);
+	}
+
+	/**
+	 * getDocument method
+	 * 
+	 * @return XMLDocument
+	 */
+	public IDOMDocument getDocument() {
+		return this.document;
+	}
+
+	public ISourceGenerator getGenerator() {
+		if (this.generator == null) {
+			this.generator = XMLGeneratorImpl.getInstance();
+		}
+		return this.generator;
+	}
+
+	/**
+	 * getNode method
+	 * 
+	 * @param offset
+	 *            int
+	 */
+	public IndexedRegion getIndexedRegion(int offset) {
+		if (this.document == null)
+			return null;
+		// search in document children
+		IDOMNode parent = null;
+		int length = this.document.getEndOffset();
+		if (offset * 2 < length) {
+			// search from the first
+			IDOMNode child = (IDOMNode) this.document.getFirstChild();
+			while (child != null) {
+				if (child.getEndOffset() <= offset) {
+					child = (IDOMNode) child.getNextSibling();
+					continue;
+				}
+				if (child.getStartOffset() > offset) {
+					break;
+				}
+				IStructuredDocumentRegion startStructuredDocumentRegion = child.getStartStructuredDocumentRegion();
+				if (startStructuredDocumentRegion != null) {
+					if (startStructuredDocumentRegion.getEnd() > offset)
+						return child;
+				}
+				IStructuredDocumentRegion endStructuredDocumentRegion = child.getEndStructuredDocumentRegion();
+				if (endStructuredDocumentRegion != null) {
+					if (endStructuredDocumentRegion.getStart() <= offset)
+						return child;
+				}
+				// dig more
+				parent = child;
+				child = (IDOMNode) parent.getFirstChild();
+			}
+		}
+		else {
+			// search from the last
+			IDOMNode child = (IDOMNode) this.document.getLastChild();
+			while (child != null) {
+				if (child.getStartOffset() > offset) {
+					child = (IDOMNode) child.getPreviousSibling();
+					continue;
+				}
+				if (child.getEndOffset() <= offset) {
+					break;
+				}
+				IStructuredDocumentRegion startStructuredDocumentRegion = child.getStartStructuredDocumentRegion();
+				if (startStructuredDocumentRegion != null) {
+					if (startStructuredDocumentRegion.getEnd() > offset)
+						return child;
+				}
+				IStructuredDocumentRegion endStructuredDocumentRegion = child.getEndStructuredDocumentRegion();
+				if (endStructuredDocumentRegion != null) {
+					if (endStructuredDocumentRegion.getStart() <= offset)
+						return child;
+				}
+				// dig more
+				parent = child;
+				child = (IDOMNode) parent.getLastChild();
+			}
+		}
+		return parent;
+	}
+
+	/**
+	 */
+	public XMLModelNotifier getModelNotifier() {
+		if (this.notifier == null) {
+			this.notifier = new XMLModelNotifierImpl();
+		}
+		return this.notifier;
+	}
+
+	/**
+	 */
+	private XMLModelParser getModelParser() {
+		if (this.parser == null) {
+			this.parser = createModelParser();
+		}
+		return this.parser;
+	}
+
+	protected XMLModelParser createModelParser() {
+		return new XMLModelParser(this);
+	}
+
+	/**
+	 */
+	private XMLModelUpdater getModelUpdater() {
+		if (this.updater == null) {
+			this.updater = createModelUpdater();
+		}
+		return this.updater;
+	}
+
+	protected XMLModelUpdater createModelUpdater() {
+		return new XMLModelUpdater(this);
+	}
+
+	/**
+	 */
+	private void handleRefresh() {
+		if (!this.refresh)
+			return;
+		XMLModelNotifier notifier = getModelNotifier();
+		boolean isChanging = notifier.isChanging();
+		if (!isChanging)
+			notifier.beginChanging(true);
+		XMLModelParser parser = getModelParser();
+		setActive(parser);
+		this.document.removeChildNodes();
+		try {
+			this.refresh = false;
+			parser.replaceStructuredDocumentRegions(getStructuredDocument().getRegionList(), null);
+		}
+		catch (Exception ex) {
+			Logger.logException(ex);
+		}
+		finally {
+			setActive(null);
+			if (!isChanging)
+				notifier.endChanging();
+		}
+	}
+
+	/**
+	 * Test if the DOM implementation implements a specific feature.
+	 * 
+	 * @param featureThe
+	 *            name of the feature to test (case-insensitive). The values
+	 *            used by DOM features are defined throughout the DOM Level 2
+	 *            specifications and listed in the section. The name must be
+	 *            an XML name. To avoid possible conflicts, as a convention,
+	 *            names referring to features defined outside the DOM
+	 *            specification should be made unique by reversing the name of
+	 *            the Internet domain name of the person (or the organization
+	 *            that the person belongs to) who defines the feature,
+	 *            component by component, and using this as a prefix. For
+	 *            instance, the W3C SVG Working Group defines the feature
+	 *            "org.w3c.dom.svg".
+	 * @param versionThis
+	 *            is the version number of the feature to test. In Level 2,
+	 *            the string can be either "2.0" or "1.0". If the version is
+	 *            not specified, supporting any version of the feature causes
+	 *            the method to return <code>true</code>.
+	 * @return <code>true</code> if the feature is implemented in the
+	 *         specified version, <code>false</code> otherwise.
+	 */
+	public boolean hasFeature(String feature, String version) {
+		if (feature == null)
+			return false;
+		if (version != null) {
+			if (!version.equals("1.0") && !version.equals("2.0")) { //$NON-NLS-2$//$NON-NLS-1$
+				return false;
+			}
+		}
+		if (feature.equalsIgnoreCase("Core")) //$NON-NLS-1$
+			return true; //$NON-NLS-1$
+		if (feature.equalsIgnoreCase("XML")) //$NON-NLS-1$
+			return true; //$NON-NLS-1$
+		return false;
+	}
+
+	/**
+	 * createDocument method
+	 * 
+	 * @return org.w3c.dom.Document
+	 */
+	protected Document internalCreateDocument() {
+		DocumentImpl document = new DocumentImpl();
+		document.setModel(this);
+		return document;
+	}
+
+	boolean isReparsing() {
+		return (active != null);
+	}
+
+	/**
+	 * nameChanged method
+	 * 
+	 * @param node
+	 *            org.w3c.dom.Node
+	 */
+	protected void nameChanged(Node node) {
+		if (node == null)
+			return;
+		if (getActiveParser() == null) {
+			XMLModelUpdater updater = getModelUpdater();
+			setActive(updater);
+			updater.initialize();
+			updater.changeName(node);
+			setActive(null);
+		}
+		// notification is already sent
+	}
+
+	/**
+	 * newModel method
+	 * 
+	 */
+	public void newModel(NewDocumentEvent structuredDocumentEvent) {
+		if (structuredDocumentEvent == null)
+			return;
+		IStructuredDocument structuredDocument = structuredDocumentEvent.getStructuredDocument();
+		if (structuredDocument == null)
+			return;
+		// this should not happen, but for the case
+		if (fStructuredDocument != null && fStructuredDocument != structuredDocument)
+			setStructuredDocument(structuredDocument);
+
+		internalSetNewDocument(structuredDocument);
+	}
+
+	private void internalSetNewDocument(IStructuredDocument structuredDocument) {
+		if (structuredDocument == null)
+			return;
+		IStructuredDocumentRegionList flatNodes = structuredDocument.getRegionList();
+		if ((flatNodes == null) || (flatNodes.getLength() == 0)) {
+			return;
+		}
+		if (this.document == null)
+			return; // being constructed
+		XMLModelUpdater updater = getActiveUpdater();
+		if (updater != null) { // being updated
+			try {
+				updater.replaceStructuredDocumentRegions(flatNodes, null);
+			}
+			catch (Exception ex) {
+				Logger.logException(ex);
+				this.refresh = true;
+				handleRefresh();
+			}
+			finally {
+				setActive(null);
+			}
+			// // for new model, we might need to
+			// // re-init, e.g. if someone calls setText
+			// // on an existing model
+			// checkForReinit();
+			return;
+		}
+		XMLModelNotifier notifier = getModelNotifier();
+		boolean isChanging = notifier.isChanging();
+		// call even if changing to notify doing new model
+		getModelNotifier().beginChanging(true);
+		XMLModelParser parser = getModelParser();
+		setActive(parser);
+		this.document.removeChildNodes();
+		try {
+			parser.replaceStructuredDocumentRegions(flatNodes, null);
+		}
+		catch (Exception ex) {
+			Logger.logException(ex);
+			// meaningless to refresh, because the result might be the same
+		}
+		finally {
+			setActive(null);
+			if (!isChanging) {
+				getModelNotifier().endChanging();
+			}
+			// ignore refresh
+			this.refresh = false;
+		}
+	}
+
+	/**
+	 */
+	public void noChange(NoChangeEvent event) {
+		XMLModelUpdater updater = getActiveUpdater();
+		if (updater != null) { // being updated
+			// cleanup updater staffs
+			try {
+				updater.replaceStructuredDocumentRegions(null, null);
+			}
+			catch (Exception ex) {
+				Logger.logException(ex);
+				this.refresh = true;
+				handleRefresh();
+			}
+			finally {
+				setActive(null);
+			}
+			// I guess no chanage means the model could not need re-init
+			// checkForReinit();
+			return;
+		}
+	}
+
+	/**
+	 * nodesReplaced method
+	 * 
+	 */
+	public void nodesReplaced(StructuredDocumentRegionsReplacedEvent event) {
+		if (event == null)
+			return;
+		IStructuredDocumentRegionList oldStructuredDocumentRegions = event.getOldStructuredDocumentRegions();
+		IStructuredDocumentRegionList newStructuredDocumentRegions = event.getNewStructuredDocumentRegions();
+		XMLModelUpdater updater = getActiveUpdater();
+		if (updater != null) { // being updated
+			try {
+				updater.replaceStructuredDocumentRegions(newStructuredDocumentRegions, oldStructuredDocumentRegions);
+			}
+			catch (Exception ex) {
+				if (ex.getClass().equals(StructuredDocumentRegionManagementException.class)) {
+					Logger.traceException(TRACE_PARSER_MANAGEMENT_EXCEPTION, ex);
+				}
+				else {
+					Logger.logException(ex);
+				}
+				this.refresh = true;
+				handleRefresh();
+			}
+			finally {
+				setActive(null);
+			}
+			// checkForReinit();
+			return;
+		}
+		XMLModelNotifier notifier = getModelNotifier();
+		boolean isChanging = notifier.isChanging();
+		if (!isChanging)
+			notifier.beginChanging();
+		XMLModelParser parser = getModelParser();
+		setActive(parser);
+		try {
+			parser.replaceStructuredDocumentRegions(newStructuredDocumentRegions, oldStructuredDocumentRegions);
+		}
+		catch (Exception ex) {
+			Logger.logException(ex);
+			this.refresh = true;
+			handleRefresh();
+		}
+		finally {
+			setActive(null);
+			if (!isChanging) {
+				notifier.endChanging();
+				handleRefresh();
+			}
+		}
+
+	}
+
+	/**
+	 * regionChanged method
+	 * 
+	 * @param structuredDocumentEvent
+	 */
+	public void regionChanged(RegionChangedEvent event) {
+		if (event == null)
+			return;
+		IStructuredDocumentRegion flatNode = event.getStructuredDocumentRegion();
+		if (flatNode == null)
+			return;
+		ITextRegion region = event.getRegion();
+		if (region == null)
+			return;
+		XMLModelUpdater updater = getActiveUpdater();
+		if (updater != null) { // being updated
+			try {
+				updater.changeRegion(event, flatNode, region);
+			}
+			catch (Exception ex) {
+				Logger.logException(ex);
+				this.refresh = true;
+				handleRefresh();
+			}
+			finally {
+				setActive(null);
+			}
+			// checkForReinit();
+			return;
+		}
+		XMLModelNotifier notifier = getModelNotifier();
+		boolean isChanging = notifier.isChanging();
+		if (!isChanging)
+			notifier.beginChanging();
+		XMLModelParser parser = getModelParser();
+		setActive(parser);
+		try {
+			parser.changeRegion(event, flatNode, region);
+		}
+		catch (Exception ex) {
+			Logger.logException(ex);
+			this.refresh = true;
+			handleRefresh();
+		}
+		finally {
+			setActive(null);
+			if (!isChanging) {
+				notifier.endChanging();
+				handleRefresh();
+			}
+		}
+		// checkForReinit();
+	}
+
+	/**
+	 * regionsReplaced method
+	 * 
+	 * @param event
+	 */
+	public void regionsReplaced(RegionsReplacedEvent event) {
+		if (event == null)
+			return;
+		IStructuredDocumentRegion flatNode = event.getStructuredDocumentRegion();
+		if (flatNode == null)
+			return;
+		ITextRegionList oldRegions = event.getOldRegions();
+		ITextRegionList newRegions = event.getNewRegions();
+		if (oldRegions == null && newRegions == null)
+			return;
+		XMLModelUpdater updater = getActiveUpdater();
+		if (updater != null) { // being updated
+			try {
+				updater.replaceRegions(flatNode, newRegions, oldRegions);
+			}
+			catch (Exception ex) {
+				Logger.logException(ex);
+				this.refresh = true;
+				handleRefresh();
+			}
+			finally {
+				setActive(null);
+			}
+			// checkForReinit();
+			return;
+		}
+		XMLModelNotifier notifier = getModelNotifier();
+		boolean isChanging = notifier.isChanging();
+		if (!isChanging)
+			notifier.beginChanging();
+		XMLModelParser parser = getModelParser();
+		setActive(parser);
+		try {
+			parser.replaceRegions(flatNode, newRegions, oldRegions);
+		}
+		catch (Exception ex) {
+			Logger.logException(ex);
+			this.refresh = true;
+			handleRefresh();
+		}
+		finally {
+			setActive(null);
+			if (!isChanging) {
+				notifier.endChanging();
+				handleRefresh();
+			}
+		}
+		// checkForReinit();
+	}
+
+	/**
+	 */
+	public void releaseFromEdit() {
+		if (!isShared()) {
+			// this.document.releaseStyleSheets();
+			// this.document.releaseDocumentType();
+		}
+		super.releaseFromEdit();
+	}
+
+	/**
+	 */
+	public void releaseFromRead() {
+		if (!isShared()) {
+			// this.document.releaseStyleSheets();
+			// this.document.releaseDocumentType();
+		}
+		super.releaseFromRead();
+	}
+
+	/**
+	 */
+	private void setActive(Object active) {
+		this.active = active;
+		// side effect
+		// when ever becomes active, besure tagNameCache is cleared
+		// (and not used)
+		if (active == null) {
+			document.activateTagNameCache(true);
+		}
+		else {
+			document.activateTagNameCache(false);
+		}
+
+	}
+
+	/**
+	 */
+	public void setGenerator(ISourceGenerator generator) {
+		this.generator = generator;
+	}
+
+	/**
+	 */
+	public void setModelNotifier(XMLModelNotifier notifier) {
+		this.notifier = notifier;
+	}
+
+	/**
+	 */
+	public void setModelParser(XMLModelParser parser) {
+		this.parser = parser;
+	}
+
+	/**
+	 */
+	public void setModelUpdater(XMLModelUpdater updater) {
+		this.updater = updater;
+	}
+
+	/**
+	 * setStructuredDocument method
+	 * 
+	 * @param structuredDocument
+	 */
+	public void setStructuredDocument(IStructuredDocument structuredDocument) {
+		IStructuredDocument oldStructuredDocument = super.getStructuredDocument();
+		if (structuredDocument == oldStructuredDocument)
+			return; // nothing to do
+		if (oldStructuredDocument != null)
+			oldStructuredDocument.removeDocumentChangingListener(this);
+		super.setStructuredDocument(structuredDocument);
+		if (structuredDocument != null) {
+			internalSetNewDocument(structuredDocument);
+			structuredDocument.addDocumentChangingListener(this);
+		}
+	}
+
+	/**
+	 */
+	protected void startTagChanged(Element element) {
+		if (element == null)
+			return;
+		if (getActiveParser() == null) {
+			XMLModelUpdater updater = getModelUpdater();
+			setActive(updater);
+			updater.initialize();
+			updater.changeStartTag(element);
+			setActive(null);
+		}
+		getModelNotifier().startTagChanged(element);
+	}
+
+	/**
+	 * valueChanged method
+	 * 
+	 * @param node
+	 *            org.w3c.dom.Node
+	 */
+	protected void valueChanged(Node node) {
+		if (node == null)
+			return;
+		if (getActiveParser() == null) {
+			XMLModelUpdater updater = getModelUpdater();
+			setActive(updater);
+			updater.initialize();
+			updater.changeValue(node);
+			setActive(null);
+		}
+		getModelNotifier().valueChanged(node);
+	}
+
+	/**
+	 * NOT IMPLEMENTED. Is defined here in preparation of DOM 3.
+	 */
+	public Object getFeature(String feature, String version) {
+		throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Not implemented in this version."); //$NON-NLS-1$
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/DocumentFragmentImpl.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/DocumentFragmentImpl.java
new file mode 100644
index 0000000..cde882c
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/DocumentFragmentImpl.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 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
+ *     
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *     Balazs Banfai: Bug 154737 getUserData/setUserData support for Node
+ *     https://bugs.eclipse.org/bugs/show_bug.cgi?id=154737
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import org.w3c.dom.DocumentFragment;
+import org.w3c.dom.Node;
+import org.w3c.dom.UserDataHandler;
+
+
+/**
+ * DocumentFragmentImpl class
+ */
+public class DocumentFragmentImpl extends NodeContainer implements DocumentFragment {
+
+	/**
+	 * DocumentFragmentImpl constructor
+	 */
+	protected DocumentFragmentImpl() {
+		super();
+	}
+
+	/**
+	 * DocumentFragmentImpl constructor
+	 * 
+	 * @param that
+	 *            DocumentFragmentImpl
+	 */
+	protected DocumentFragmentImpl(DocumentFragmentImpl that) {
+		super(that);
+	}
+
+	/**
+	 * cloneNode method
+	 * 
+	 * @return org.w3c.dom.Node
+	 * @param deep
+	 *            boolean
+	 */
+	public Node cloneNode(boolean deep) {
+		DocumentFragmentImpl cloned = new DocumentFragmentImpl(this);
+		if (deep)
+			cloneChildNodes(cloned, deep);
+		
+		notifyUserDataHandlers(UserDataHandler.NODE_CLONED, cloned);
+		return cloned;
+	}
+
+	/**
+	 * getNodeName method
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getNodeName() {
+		return "#document-fragment";//$NON-NLS-1$
+	}
+
+	/**
+	 * getNodeType method
+	 * 
+	 * @return short
+	 */
+	public short getNodeType() {
+		return DOCUMENT_FRAGMENT_NODE;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/DocumentImpl.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/DocumentImpl.java
new file mode 100644
index 0000000..4082ff7
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/DocumentImpl.java
@@ -0,0 +1,1207 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *     Balazs Banfai: Bug 154737 getUserData/setUserData support for Node
+ *     https://bugs.eclipse.org/bugs/show_bug.cgi?id=154737
+ *     David Carver (STAR) - bug 296999 - Inefficient use of new String()
+ *     David Carver (Intalio) - bug 273004 - add check for valid xml characters in createAttribute
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+// for org.apache.xerces 3.2.1
+// import org.apache.xerces.utils.XMLCharacterProperties;
+// DMW modified for XML4J 4.0.1
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.apache.xerces.dom.TreeWalkerImpl;
+import org.eclipse.wst.sse.core.internal.ltk.modelhandler.IModelHandler;
+import org.eclipse.wst.xml.core.internal.commentelement.impl.CommentElementRegistry;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMEntityDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.modelquery.ModelQueryUtil;
+import org.eclipse.wst.xml.core.internal.provisional.IXMLCharEntity;
+import org.eclipse.wst.xml.core.internal.provisional.NameValidator;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
+import org.w3c.dom.Attr;
+import org.w3c.dom.CDATASection;
+import org.w3c.dom.Comment;
+import org.w3c.dom.DOMConfiguration;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.DocumentFragment;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Element;
+import org.w3c.dom.Entity;
+import org.w3c.dom.EntityReference;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Notation;
+import org.w3c.dom.ProcessingInstruction;
+import org.w3c.dom.Text;
+import org.w3c.dom.UserDataHandler;
+import org.w3c.dom.ranges.DocumentRange;
+import org.w3c.dom.ranges.Range;
+import org.w3c.dom.traversal.DocumentTraversal;
+import org.w3c.dom.traversal.NodeFilter;
+import org.w3c.dom.traversal.NodeIterator;
+import org.w3c.dom.traversal.TreeWalker;
+
+
+/**
+ * DocumentImpl class
+ */
+public class DocumentImpl extends NodeContainer implements IDOMDocument, DocumentRange, DocumentTraversal {
+
+	private static int maxDocTypeSearch = 500;
+	private static int noMaxSearch = -1;
+	/**
+	 * Internal-use only class. This class was added to better able to handle
+	 * repetetive request for getElementsByTagName. The cache is cleared when
+	 * ever the document changes at all, so still not real efficient,
+	 */
+	class TagNameCache {
+
+		private boolean active = true;
+
+		private Map cache;
+
+		public TagNameCache() {
+			super();
+			cache = new HashMap();
+		}
+
+		/**
+		 * @param b
+		 */
+		public void activate(boolean b) {
+			active = b;
+			if (!b)
+				clear();
+		}
+
+		public void addItem(String tagname, NodeListImpl nodelist) {
+			if (tagname == null || nodelist == null)
+				return;
+			cache.put(tagname, nodelist);
+		}
+
+		public void clear() {
+			cache.clear();
+		}
+
+		public NodeListImpl getItem(String tagName) {
+			NodeListImpl result = null;
+			if (active) {
+				result = (NodeListImpl) cache.get(tagName);
+				// if (result != null) {
+				// System.out.println("getElementsByTagname from cache: " +
+				// tagName);
+				// }
+			}
+			return result;
+		}
+
+	}
+
+	private class LimitedCache extends LinkedHashMap {
+		private static final long serialVersionUID = 1L;
+		private static final int MAX_SIZE = 10;
+		public LimitedCache() {
+			super(0, 0.75f, true);
+		}
+
+		protected boolean removeEldestEntry(java.util.Map.Entry entry) {
+			return size() > MAX_SIZE;
+		}
+	}
+
+	// this is a constant just to give compile-time control over
+	// whether or not to use the cache. If, in future, its found that
+	// there are no (or few) "duplicate requests" ... then this cache
+	// is not needed.
+	private static final boolean usetagnamecache = true;
+
+	// private DocumentTypeAdapter documentTypeAdapter = null;
+
+	private DOMModelImpl model = null;
+	private TagNameCache tagNameCache;
+
+	private Map fCMCache;
+	/**
+	 * DocumentImpl constructor
+	 */
+	protected DocumentImpl() {
+		super();
+		if (usetagnamecache) {
+			tagNameCache = new TagNameCache();
+		}
+		fCMCache = Collections.synchronizedMap(new LimitedCache());
+	}
+
+	/**
+	 * DocumentImpl constructor
+	 * 
+	 * @param that
+	 *            DocumentImpl
+	 */
+	protected DocumentImpl(DocumentImpl that) {
+		super(that);
+		if (usetagnamecache) {
+			tagNameCache = new TagNameCache();
+		}
+		fCMCache = Collections.synchronizedMap(new LimitedCache());
+	}
+
+	/**
+	 * @param b
+	 */
+	void activateTagNameCache(boolean b) {
+		tagNameCache.activate(b);
+	}
+
+	/**
+	 * <p>
+	 * EXPERIMENTAL! Based on the <a
+	 * href='http://www.w3.org/TR/2001/WD-DOM-Level-3-Core-20010605'>Document
+	 * Object Model (DOM) Level 3 Core Working Draft of 5 June 2001. </a>.
+	 * <p>
+	 * Changes the <code>ownerDocument</code> of a node, its children, as
+	 * well as the attached attribute nodes if there are any. If the node has
+	 * a parent it is first removed from its parent child list. This
+	 * effectively allows moving a subtree from one document to another. The
+	 * following list describes the specifics for each type of node.
+	 * <dl>
+	 * <dt>ATTRIBUTE_NODE</dt>
+	 * <dd>The <code>ownerElement</code> attribute is set to
+	 * <code>null</code> and the <code>specified</code> flag is set to
+	 * <code>true</code> on the adopted <code>Attr</code>. The
+	 * descendants of the source <code>Attr</code> are recursively adopted.
+	 * </dd>
+	 * <dt>DOCUMENT_FRAGMENT_NODE</dt>
+	 * <dd>The descendants of the source node are recursively adopted.</dd>
+	 * <dt>DOCUMENT_NODE</dt>
+	 * <dd><code>Document</code> nodes cannot be adopted.</dd>
+	 * <dt>DOCUMENT_TYPE_NODE</dt>
+	 * <dd><code>DocumentType</code> nodes cannot be adopted.</dd>
+	 * <dt>ELEMENT_NODE</dt>
+	 * <dd>Specified attribute nodes of the source element are adopted, and
+	 * the generated <code>Attr</code> nodes. Default attributes are
+	 * discarded, though if the document being adopted into defines default
+	 * attributes for this element name, those are assigned. The descendants
+	 * of the source element are recursively adopted.</dd>
+	 * <dt>ENTITY_NODE</dt>
+	 * <dd><code>Entity</code> nodes cannot be adopted.</dd>
+	 * <dt>ENTITY_REFERENCE_NODE</dt>
+	 * <dd>Only the <code>EntityReference</code> node itself is adopted,
+	 * the descendants are discarded, since the source and destination
+	 * documents might have defined the entity differently. If the document
+	 * being imported into provides a definition for this entity name, its
+	 * value is assigned.</dd>
+	 * <dt>NOTATION_NODE</dt>
+	 * <dd><code>Notation</code> nodes cannot be adopted.</dd>
+	 * <dt>PROCESSING_INSTRUCTION_NODE, TEXT_NODE, CDATA_SECTION_NODE,
+	 * COMMENT_NODE</dt>
+	 * <dd>These nodes can all be adopted. No specifics.</dd>
+	 * Should this method simply return null when it fails? How "exceptional"
+	 * is failure for this method?Stick with raising exceptions only in
+	 * exceptional circumstances, return null on failure (F2F 19 Jun 2000).Can
+	 * an entity node really be adopted?No, neither can Notation nodes (Telcon
+	 * 13 Dec 2000).Does this affect keys and hashCode's of the adopted
+	 * subtree nodes?If so, what about readonly-ness of key and hashCode?if
+	 * not, would appendChild affect keys/hashCodes or would it generate
+	 * exceptions if key's are duplicate? Update: Hashcodes have been dropped.
+	 * Given that the key is only unique within a document an adopted node
+	 * needs to be given a new key, but what does it mean for the application?
+	 * 
+	 * TODO: Needs to notify UserDataHandlers for the node if any
+	 * 
+	 * @param source
+	 *            The node to move into this document.
+	 * @return The adopted node, or <code>null</code> if this operation
+	 *         fails, such as when the source node comes from a different
+	 *         implementation.
+	 * @exception DOMException
+	 *                NOT_SUPPORTED_ERR: Raised if the source node is of type
+	 *                <code>DOCUMENT</code>,<code>DOCUMENT_TYPE</code>.
+	 *                <br>
+	 *                NO_MODIFICATION_ALLOWED_ERR: Raised when the source node
+	 *                is readonly.
+	 * @see DOM Level 3
+	 */
+	public org.w3c.dom.Node adoptNode(org.w3c.dom.Node source) throws org.w3c.dom.DOMException {
+		return null;
+	}
+
+	/**
+	 * @param tagName
+	 */
+	protected void checkTagNameValidity(String tagName) {
+		if (!isValidName(tagName)) {
+			throw new DOMException(DOMException.INVALID_CHARACTER_ERR, createDOMExceptionMessage(DOMException.INVALID_CHARACTER_ERR, tagName));
+		}
+	}
+
+	/**
+	 * cloneNode method
+	 * 
+	 * @return org.w3c.dom.Node
+	 * @param deep
+	 *            boolean
+	 */
+	public Node cloneNode(boolean deep) {
+		DocumentImpl cloned = new DocumentImpl(this);
+		if (deep)
+			cloned.importChildNodes(this, true);
+		return cloned;
+	}
+
+	/**
+	 * createAttribute method
+	 * 
+	 * @return org.w3c.dom.Attr
+	 * @param name
+	 *            java.lang.String
+	 */
+	public Attr createAttribute(String name) throws DOMException {
+		checkTagNameValidity(name);
+		AttrImpl attr = new AttrImpl();
+		attr.setOwnerDocument(this);
+		attr.setName(name);
+		return attr;
+	}
+
+	/**
+	 */
+	public Attr createAttributeNS(String uri, String name) throws DOMException {
+		checkTagNameValidity(name);
+		AttrImpl attr = new AttrImpl();
+		attr.setOwnerDocument(this);
+		attr.setName(name);
+		attr.setNamespaceURI(uri);
+		return attr;
+	}
+
+	/**
+	 * createCDATASection method
+	 * 
+	 * @return org.w3c.dom.CDATASection
+	 * @param data
+	 *            java.lang.String
+	 */
+	public CDATASection createCDATASection(String data) throws DOMException {
+		// allow CDATA section
+		// if (!isXMLType()) {
+		// throw new DOMException(DOMException.NOT_SUPPORTED_ERR, new
+		// String());
+		// }
+		CDATASectionImpl cdata = new CDATASectionImpl();
+		cdata.setOwnerDocument(this);
+		if (data != null)
+			cdata.setData(data);
+		return cdata;
+	}
+
+	/**
+	 * createComment method
+	 * 
+	 * @return org.w3c.dom.Comment
+	 * @param data
+	 *            java.lang.String
+	 */
+	public Comment createComment(String data) {
+		CommentImpl comment = new CommentImpl();
+		comment.setOwnerDocument(this);
+		if (data != null)
+			comment.setData(data);
+		return comment;
+	}
+
+	public Element createCommentElement(String tagName, boolean isJSPTag) throws DOMException {
+		Element result = null;
+		if (!isJSPType() && isJSPTag) {
+			throw new DOMException(DOMException.INVALID_MODIFICATION_ERR, DOMMessages.INVALID_MODIFICATION_ERR);
+		}
+		ElementImpl element = (ElementImpl) createElement(tagName);
+		element.setJSPTag(isJSPTag);
+		CommentElementRegistry registry = CommentElementRegistry.getInstance();
+		if (registry.setupCommentElement(element)) {
+			result = element;
+		}
+		else {
+			throw new DOMException(DOMException.INVALID_CHARACTER_ERR, DOMMessages.INVALID_CHARACTER_ERR);
+		}
+		return result;
+	}
+
+	/**
+	 * createDoctype method
+	 * 
+	 * @return org.w3c.dom.DocumentType
+	 * @param name
+	 *            java.lang.String
+	 */
+	public DocumentType createDoctype(String name) {
+		DocumentTypeImpl docType = new DocumentTypeImpl();
+		docType.setOwnerDocument(this);
+		docType.setName(name);
+		return docType;
+	}
+
+	/**
+	 * createDocumentFragment method
+	 * 
+	 * @return org.w3c.dom.DocumentFragment
+	 */
+	public DocumentFragment createDocumentFragment() {
+		DocumentFragmentImpl fragment = new DocumentFragmentImpl();
+		fragment.setOwnerDocument(this);
+		return fragment;
+	}
+
+	/**
+	 * createElement method
+	 * 
+	 * @return org.w3c.dom.Element
+	 * @param tagName
+	 *            java.lang.String
+	 */
+	public Element createElement(String tagName) throws DOMException {
+		checkTagNameValidity(tagName);
+
+		ElementImpl element = new ElementImpl();
+		element.setOwnerDocument(this);
+		element.setTagName(tagName);
+		return element;
+	}
+
+	/**
+	 */
+	public Element createElementNS(String uri, String tagName) throws DOMException {
+		if (!isValidName(tagName)) {
+			throw new DOMException(DOMException.INVALID_CHARACTER_ERR, DOMMessages.INVALID_CHARACTER_ERR);
+		}
+
+		ElementImpl element = (ElementImpl) createElement(tagName);
+		element.setNamespaceURI(uri);
+		return element;
+	}
+
+	/**
+	 * createEntity method
+	 * 
+	 * @return org.w3c.dom.Entity
+	 * @param name
+	 *            java.lang.String
+	 */
+	public Entity createEntity(String name) {
+		EntityImpl entity = new EntityImpl();
+		entity.setOwnerDocument(this);
+		entity.setName(name);
+		return entity;
+	}
+
+	/**
+	 * createEntityReference method
+	 * 
+	 * @return org.w3c.dom.EntityReference
+	 * @param name
+	 *            java.lang.String
+	 */
+	public EntityReference createEntityReference(String name) throws DOMException {
+		if (!isXMLType()) {
+			throw new DOMException(DOMException.NOT_SUPPORTED_ERR, DOMMessages.NOT_SUPPORTED_ERR);
+		}
+
+		EntityReferenceImpl ref = new EntityReferenceImpl();
+		ref.setOwnerDocument(this);
+		ref.setName(name);
+		return ref;
+	}
+
+	/**
+	 */
+	public NodeIterator createNodeIterator(Node root, int whatToShow, NodeFilter filter, boolean entityReferenceExpansion) {
+		if (root == null)
+			root = this;
+		return new NodeIteratorImpl(root, whatToShow, filter);
+	}
+
+	/**
+	 * createNotation method
+	 * 
+	 * @return org.w3c.dom.Notation
+	 * @param name
+	 *            java.lang.String
+	 */
+	public Notation createNotation(String name) {
+		NotationImpl notation = new NotationImpl();
+		notation.setOwnerDocument(this);
+		notation.setName(name);
+		return notation;
+	}
+
+	/**
+	 * createProcessingInstruction method
+	 * 
+	 * @return org.w3c.dom.ProcessingInstruction
+	 * @param target
+	 *            java.lang.String
+	 * @param data
+	 *            java.lang.String
+	 */
+	public ProcessingInstruction createProcessingInstruction(String target, String data) throws DOMException {
+		ProcessingInstructionImpl pi = new ProcessingInstructionImpl();
+		pi.setOwnerDocument(this);
+		pi.setTarget(target);
+		if (data != null)
+			pi.setData(data);
+		return pi;
+	}
+
+	/**
+	 */
+	public Range createRange() {
+		return new RangeImpl();
+	}
+
+	/**
+	 * createTextNode method
+	 * 
+	 * @return org.w3c.dom.Text
+	 * @param data
+	 *            java.lang.String
+	 */
+	public Text createTextNode(String data) {
+		TextImpl text = new TextImpl();
+		text.setOwnerDocument(this);
+		text.setData(data);
+		return text;
+	}
+
+	/**
+	 * Return an instance of tree walk
+	 */
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.w3c.dom.traversal.DocumentTraversal#createTreeWalker(org.w3c.dom.Node,
+	 *      int, org.w3c.dom.traversal.NodeFilter, boolean)
+	 */
+	public TreeWalker createTreeWalker(Node root, int whatToShow, NodeFilter filter, boolean entityReferenceExpansion) {
+		if (root == null) {
+			String msg = DOMMessages.NOT_SUPPORTED_ERR + " - Program Error: root node can not be null for TreeWalker";
+			throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
+		}
+		// ISSUE: we just use Xerces implementation for now, but longer term,
+		// we should make a
+		// thread/job safe version (as well as not rely on Xerces "impl"
+		// class.
+		return new TreeWalkerImpl(root, whatToShow, filter, entityReferenceExpansion);
+
+	}
+
+	private DocumentType findDoctype(Node node) {
+		
+		int countSearch = 0;
+		for (Node child = node.getFirstChild(); child != null; child = child.getNextSibling()) {
+			if (countSearch++ > maxDocTypeSearch) {
+				break;
+			}
+			if (child.getNodeType() == DOCUMENT_TYPE_NODE && child instanceof DocumentType) {
+				return (DocumentType) child;
+			}
+			else if (child.getNodeType() == ELEMENT_NODE && ((IDOMElement) child).isCommentTag()) {
+				// search DOCTYPE inside of generic comment element
+				DocumentType docType = findDoctype(child);
+				if (docType != null) {
+					return docType;
+				}
+			}
+		}
+
+		return null;
+	}
+
+	private Element findDocumentElement(String docName, Node node, Node[] firstFound, int max) {
+		int countSearch = 0;
+		for (Node child = node.getFirstChild(); child != null; child = child.getNextSibling()) {
+			
+			/* 
+			 * maxDocTypeSearch limits added via bug 151929
+			 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=151929
+			 * but, in other contexts, 
+			 * if noMaxSearch is specified, then do not "break out" of long searches 
+			 * */
+			if (max != noMaxSearch && countSearch++ > max) {
+				break;
+			}
+			if (child.getNodeType() != ELEMENT_NODE)
+				continue;
+			ElementImpl element = (ElementImpl) child;
+			if (element.isCommentTag()) {
+				Element docElement = findDocumentElement(docName, element, firstFound, max);
+				if (docElement != null) {
+					return docElement;
+				}
+				else {
+					// added 'else continue' to better handle cases where
+					// there is "more than one root" element
+					// especially complicated by CommentElements, which are
+					// sometimes treated as elements, but should
+					// be treated as comments in this context.
+					continue;
+				}
+			}
+			// note: the "name" won't match in the event of a jsp tag ... but
+			// incase
+			// the name is null, we do not want the jsp element returned as
+			// documentElement
+			if (element.isJSPTag())
+				continue;
+			if (docName == null)
+				return element;
+			// use local name for namespace
+			String localName = element.getLocalName();
+			if (localName == null)
+				continue;
+			if (isXMLType()) {
+				if (localName.equals(docName))
+					return element;
+			}
+			else {
+				if (localName.equalsIgnoreCase(docName))
+					return element;
+			}
+			if (firstFound[0] == null)
+				firstFound[0] = element;
+		}
+		return null;
+	}
+
+	/**
+	 * getCharValue method
+	 * 
+	 * @return java.lang.String
+	 * @param name
+	 *            java.lang.String
+	 */
+	protected String getCharValue(String name) {
+		if (name == null)
+			return null;
+		int length = name.length();
+		if (length == 0)
+			return null;
+
+		if (name.charAt(0) == '#') { // character reference
+			if (length == 1)
+				return null;
+			int radix = 10;
+			String s = null;
+			// now allow hexadecimal also for non XML document
+			if (name.charAt(1) == 'x') { // hexadecimal
+				radix = 16;
+				s = name.substring(2);
+			}
+			else { // decimal
+				s = name.substring(1);
+			}
+			if (s == null || s.length() == 0)
+				return null;
+			if (s.charAt(0) == '-')
+				return null; // no minus accepted
+			char c = 0;
+			try {
+				c = (char) Integer.parseInt(s, radix);
+			}
+			catch (NumberFormatException ex) {
+			}
+			if (c == 0)
+				return null;
+			return String.valueOf(c);
+		}
+
+		// implicit character entities for XML
+		if (name.equals(IXMLCharEntity.LT_NAME))
+			return IXMLCharEntity.LT_VALUE;
+		if (name.equals(IXMLCharEntity.GT_NAME))
+			return IXMLCharEntity.GT_VALUE;
+		if (name.equals(IXMLCharEntity.AMP_NAME))
+			return IXMLCharEntity.AMP_VALUE;
+		if (name.equals(IXMLCharEntity.QUOT_NAME))
+			return IXMLCharEntity.QUOT_VALUE;
+		if (isXMLType()) {
+			if (name.equals(IXMLCharEntity.APOS_NAME))
+				return IXMLCharEntity.APOS_VALUE;
+		}
+
+		CMDocument cm = getCMDocument();
+		if (cm != null) {
+			CMNamedNodeMap map = cm.getEntities();
+			if (map != null) {
+				CMEntityDeclaration decl = (CMEntityDeclaration) map.getNamedItem(name);
+				if (decl != null) {
+					String value = decl.getValue();
+					if (value == null)
+						return null;
+					int valueLength = value.length();
+					if (valueLength > 1 && value.charAt(0) == '&' && value.charAt(1) == '#' && value.charAt(valueLength - 1) == ';') {
+						// character reference
+						return getCharValue(value.substring(1, valueLength - 1));
+					}
+					return value;
+				}
+			}
+		}
+
+		return null;
+	}
+
+	/**
+	 */
+	protected CMDocument getCMDocument() {
+		ModelQuery modelQuery = ModelQueryUtil.getModelQuery(this);
+		if (modelQuery == null)
+			return null;
+		return modelQuery.getCorrespondingCMDocument(this);
+	}
+
+	/**
+	 * getDoctype method
+	 * 
+	 * @return org.w3c.dom.DocumentType
+	 */
+	public DocumentType getDoctype() {
+		return findDoctype(this);
+	}
+
+	/**
+	 * getDocumentElement
+	 * 
+	 * @return org.w3c.dom.Element From DOM 2 Spec: documentElement of type
+	 *         Element [p.62] , readonly This is a convenience [p.119]
+	 *         attribute that allows direct access to the child node that is
+	 *         the root element of the document. For HTML documents, this is
+	 *         the element with the tagName "HTML". Note: we differ from this
+	 *         definition a little in that we don't necessarily take the first
+	 *         child but also look to match the name. In a well formed
+	 *         document, of course, the result is the same, but not
+	 *         necessarily the same in an ill-formed document.
+	 */
+	public Element getDocumentElement() {
+		String name = null;
+		DocumentType docType = getDocumentType();
+		if (docType != null) {
+			name = docType.getName();
+		}
+
+		Element first[] = new Element[1];
+		Element docElement = findDocumentElement(name, this, first, noMaxSearch);
+		if (docElement == null) {
+			docElement = first[0];
+		}
+
+		return docElement;
+	}
+
+	/**
+	 */
+	protected DocumentType getDocumentType() {
+		DocumentTypeAdapter adapter = (DocumentTypeAdapter) getAdapterFor(DocumentTypeAdapter.class);
+		if (adapter == null)
+			return getDoctype();
+		return adapter.getDocumentType();
+	}
+
+
+	public String getDocumentTypeId() {
+		DocumentType docType = getDocumentType();
+		if (docType == null)
+			return null;
+		String id = docType.getPublicId();
+		if (id == null)
+			id = docType.getSystemId();
+		return id;
+	}
+
+	public Element getElementById(String id) {
+		if (id == null)
+			return null;
+		NodeIterator it = createNodeIterator(this, NodeFilter.SHOW_ALL, null, false);
+		if (it == null)
+			return null;
+
+		for (Node node = it.nextNode(); node != null; node = it.nextNode()) {
+			if (node.getNodeType() != ELEMENT_NODE)
+				continue;
+			ElementImpl element = (ElementImpl) node;
+			if (element.hasAttribute("id") && id.equals(element.getAttribute("id"))) //$NON-NLS-1$ //$NON-NLS-2$
+				return element;
+		}
+
+		return null;
+	}
+
+	public NodeList getElementsByTagName(String tagName) {
+		if (tagName == null)
+			return new NodeListImpl();
+
+		NodeListImpl elements = null;
+
+		if (usetagnamecache) {
+			elements = tagNameCache.getItem(tagName);
+		}
+
+		if (elements == null) {
+			elements = internalGetElementsByTagName(tagName);
+
+		}
+
+		return elements;
+	}
+
+	/**
+	 */
+	public NodeList getElementsByTagNameNS(String uri, String tagName) {
+		if (tagName == null)
+			return new NodeListImpl();
+
+		NodeIterator it = createNodeIterator(this, NodeFilter.SHOW_ALL, null, false);
+		if (it == null)
+			return new NodeListImpl();
+		NodeListImpl elements = new NodeListImpl();
+
+		if (uri != null && uri.length() == 1 && uri.charAt(0) == '*') {
+			uri = null; // do not care
+		}
+		if (tagName.length() == 1 && tagName.charAt(0) == '*') {
+			tagName = null; // do not care
+		}
+
+		for (Node node = it.nextNode(); node != null; node = it.nextNode()) {
+			if (node.getNodeType() != ELEMENT_NODE)
+				continue;
+			ElementImpl element = (ElementImpl) node;
+			if (tagName != null) {
+				String localName = element.getLocalName();
+				if (localName == null || !localName.equals(tagName))
+					continue;
+			}
+			if (uri != null) {
+				String nsURI = element.getNamespaceURI();
+				if (nsURI == null || !nsURI.equals(uri))
+					continue;
+			}
+			elements.appendNode(element);
+		}
+
+		return elements;
+	}
+
+	/**
+	 * <p>
+	 * EXPERIMENTAL! Based on the <a
+	 * href='http://www.w3.org/TR/2001/WD-DOM-Level-3-Core-20010605'>Document
+	 * Object Model (DOM) Level 3 Core Working Draft of 5 June 2001. </a>.
+	 * <p>
+	 * An attribute specifying, as part of the XML declaration, the encoding
+	 * of this document. This is <code>null</code> when unspecified.
+	 * 
+	 * @see DOM Level 3
+	 */
+	public java.lang.String getEncoding() {
+		return null;
+	}
+
+	/**
+	 */
+	public DOMImplementation getImplementation() {
+		return model;
+	}
+
+	/**
+	 * other nodes will be referring to this one to get the owning model
+	 */
+	public IDOMModel getModel() {
+		return model;
+	}
+
+	/**
+	 * getNodeName method
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getNodeName() {
+		return "#document";//$NON-NLS-1$
+	}
+
+	/**
+	 * getNodeType method
+	 * 
+	 * @return short
+	 */
+	public short getNodeType() {
+		return DOCUMENT_NODE;
+	}
+
+	/**
+	 * <p>
+	 * EXPERIMENTAL! Based on the <a
+	 * href='http://www.w3.org/TR/2001/WD-DOM-Level-3-Core-20010605'>Document
+	 * Object Model (DOM) Level 3 Core Working Draft of 5 June 2001. </a>.
+	 * <p>
+	 * An attribute specifying, as part of the XML declaration, whether this
+	 * document is standalone.
+	 * 
+	 * @see DOM Level 3
+	 */
+	public boolean getStandalone() {
+		return false;
+	}
+
+	/**
+	 * <p>
+	 * EXPERIMENTAL! Based on the <a
+	 * href='http://www.w3.org/TR/2001/WD-DOM-Level-3-Core-20010605'>Document
+	 * Object Model (DOM) Level 3 Core Working Draft of 5 June 2001. </a>.
+	 * <p>
+	 * An attribute specifying whether errors checking is enforced or not.
+	 * When set to <code>false</code>, the implementation is free to not
+	 * test every possible error case normally defined on DOM operations, and
+	 * not raise any <code>DOMException</code>. In case of error, the
+	 * behavior is undefined. This attribute is <code>true</code> by
+	 * defaults.
+	 * 
+	 * @see DOM Level 3
+	 */
+	public boolean getStrictErrorChecking() {
+		return false;
+	}
+
+	/**
+	 * <p>
+	 * EXPERIMENTAL! Based on the <a
+	 * href='http://www.w3.org/TR/2001/WD-DOM-Level-3-Core-20010605'>Document
+	 * Object Model (DOM) Level 3 Core Working Draft of 5 June 2001. </a>.
+	 * <p>
+	 * An attribute specifying, as part of the XML declaration, the version
+	 * number of this document. This is <code>null</code> when unspecified.
+	 * 
+	 * @see DOM Level 3
+	 */
+	public String getVersion() {
+		return null;
+	}
+
+	/**
+	 */
+	protected boolean ignoreCase() {
+		DocumentTypeAdapter adapter = (DocumentTypeAdapter) getAdapterFor(DocumentTypeAdapter.class);
+		if (adapter == null)
+			return false;
+		return (adapter.getTagNameCase() != DocumentTypeAdapter.STRICT_CASE);
+	}
+
+	/**
+	 */
+	protected void importChildNodes(Node parent, boolean deep) {
+		if (parent == null)
+			return;
+
+		removeChildNodes();
+
+		for (Node child = parent.getFirstChild(); child != null; child = child.getNextSibling()) {
+			Node imported = importNode(child, deep);
+			if (imported == null)
+				continue;
+			appendChild(imported);
+		}
+	}
+
+	/**
+	 */
+	public Node importNode(Node node, boolean deep) throws DOMException {
+		if (node == null)
+			return null;
+		NodeImpl imported = (NodeImpl) node.cloneNode(deep);
+		if (imported == null)
+			return null;
+		//successful import, notify UserDataHandlers if any
+		NodeImpl nodeToNotify=(NodeImpl) node;
+		nodeToNotify.notifyUserDataHandlers(UserDataHandler.NODE_IMPORTED, null);
+		imported.setOwnerDocument(this, deep);
+		return imported;
+	}
+
+	private NodeListImpl internalGetElementsByTagName(String tagName) {
+		// System.out.println("getElementsByTagname: " + tagName);
+		NodeIterator it = createNodeIterator(this, NodeFilter.SHOW_ALL, null, false);
+		if (it == null)
+			return new NodeListImpl();
+		NodeListImpl elements = new NodeListImpl();
+
+		if (tagName.length() == 1 && tagName.charAt(0) == '*') {
+			tagName = null; // do not care
+		}
+
+		for (Node node = it.nextNode(); node != null; node = it.nextNode()) {
+			if (node.getNodeType() != ELEMENT_NODE)
+				continue;
+			if (tagName != null) {
+				ElementImpl element = (ElementImpl) node;
+				if (!element.matchTagName(tagName))
+					continue;
+			}
+			elements.appendNode(node);
+		}
+		if (usetagnamecache) {
+			tagNameCache.addItem(tagName, elements);
+		}
+		return elements;
+	}
+
+	/**
+	 */
+	public boolean isJSPDocument() {
+		Element element = getDocumentElement();
+		if (element == null)
+			return false;
+		String tagName = element.getTagName();
+		if (tagName == null)
+			return false;
+		return tagName.equals(JSPTag.JSP_ROOT);
+	}
+
+	/**
+	 */
+	public boolean isJSPType() {
+		if (this.model == null)
+			return false;
+		IModelHandler handler = this.model.getModelHandler();
+		if (handler == null)
+			return false;
+		String id = handler.getAssociatedContentTypeId();
+		if (id == null)
+			return false;
+		// ISSUE: -- avoid this hardcoded string
+		return id.equals("org.eclipse.jst.jsp.core.jspsource"); //$NON-NLS-1$
+	}
+
+	/**
+	 */
+	protected boolean isValidName(String name) {
+		if (name == null || name.length() == 0)
+			return false;
+		// // DMW: modified for XML4J 4.0.1
+		// if (XMLChar.isValidName(name)) return true;
+		if (NameValidator.isValid(name))
+			return true;
+		// special for invalid declaration
+		if (name.length() == 1 && name.charAt(0) == '!')
+			return true;
+		// special for JSP tag in tag name
+		if (name.startsWith(JSPTag.TAG_OPEN))
+			return true;
+		return false;
+	}
+
+	/**
+	 */
+	public boolean isXMLType() {
+		DocumentTypeAdapter adapter = (DocumentTypeAdapter) getAdapterFor(DocumentTypeAdapter.class);
+		if (adapter == null)
+			return true;
+		return adapter.isXMLType();
+	}
+
+	/**
+	 */
+	// protected void releaseDocumentType() {
+	// if (this.documentTypeAdapter == null)
+	// return;
+	// this.documentTypeAdapter.release();
+	// this.documentTypeAdapter = null;
+	// }
+	/**
+	 * <p>
+	 * EXPERIMENTAL! Based on the <a
+	 * href='http://www.w3.org/TR/2001/WD-DOM-Level-3-Core-20010605'>Document
+	 * Object Model (DOM) Level 3 Core Working Draft of 5 June 2001. </a>.
+	 * <p>
+	 * An attribute specifying, as part of the XML declaration, the encoding
+	 * of this document. This is <code>null</code> when unspecified.
+	 * 
+	 * @see DOM Level 3
+	 */
+	public void setEncoding(java.lang.String encoding) {
+	}
+
+	/**
+	 * setModel method
+	 * 
+	 * @param model
+	 *            XMLModel
+	 */
+
+	protected void setModel(IDOMModel model) {
+		this.model = (DOMModelImpl) model;
+	}
+
+	/**
+	 * Provides an element's attribute declarations
+	 * @param element the element to retrieve the attribute map of
+	 * @return a <code>CMNamedNodeMap</code> of attributes if the declaration exists; null otherwise.
+	 */
+	CMNamedNodeMap getCMAttributes(Element element) {
+		CMNamedNodeMap map = (CMNamedNodeMap) fCMCache.get(element);
+		if (map == null) {
+			CMElementDeclaration decl = ModelQueryUtil.getModelQuery(this).getCMElementDeclaration(element);
+			if (decl != null) {
+				map = decl.getAttributes();
+				fCMCache.put(element, map);
+			}
+		}
+		return map;
+	}
+
+	/**
+	 * <p>
+	 * EXPERIMENTAL! Based on the <a
+	 * href='http://www.w3.org/TR/2001/WD-DOM-Level-3-Core-20010605'>Document
+	 * Object Model (DOM) Level 3 Core Working Draft of 5 June 2001. </a>.
+	 * <p>
+	 * An attribute specifying, as part of the XML declaration, whether this
+	 * document is standalone.
+	 * 
+	 * @see DOM Level 3
+	 */
+	public void setStandalone(boolean standalone) {
+	}
+
+	/**
+	 * <p>
+	 * EXPERIMENTAL! Based on the <a
+	 * href='http://www.w3.org/TR/2001/WD-DOM-Level-3-Core-20010605'>Document
+	 * Object Model (DOM) Level 3 Core Working Draft of 5 June 2001. </a>.
+	 * <p>
+	 * An attribute specifying whether errors checking is enforced or not.
+	 * When set to <code>false</code>, the implementation is free to not
+	 * test every possible error case normally defined on DOM operations, and
+	 * not raise any <code>DOMException</code>. In case of error, the
+	 * behavior is undefined. This attribute is <code>true</code> by
+	 * defaults.
+	 * 
+	 * @see DOM Level 3
+	 */
+	public void setStrictErrorChecking(boolean strictErrorChecking) {
+	}
+
+	/**
+	 * <p>
+	 * EXPERIMENTAL! Based on the <a
+	 * href='http://www.w3.org/TR/2001/WD-DOM-Level-3-Core-20010605'>Document
+	 * Object Model (DOM) Level 3 Core Working Draft of 5 June 2001. </a>.
+	 * <p>
+	 * An attribute specifying, as part of the XML declaration, the version
+	 * number of this document. This is <code>null</code> when unspecified.
+	 * 
+	 * @see DOM Level 3
+	 */
+	public void setVersion(java.lang.String version) {
+	}
+
+	/**
+	 * NOT IMPLEMENTED. Is defined here in preparation for DOM 3.
+	 */
+	public String getInputEncoding() {
+		throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Not implemented in this version"); //$NON-NLS-1$
+	}
+
+	/**
+	 * NOT IMPLEMENTED. Is defined here in preparation for DOM 3.
+	 */
+	public String getXmlEncoding() {
+		throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Not implemented in this version"); //$NON-NLS-1$
+	}
+
+	/**
+	 * NOT IMPLEMENTED. Is defined here in preparation for DOM 3.
+	 */
+	public boolean getXmlStandalone() {
+		throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Not implemented in this version"); //$NON-NLS-1$
+	}
+
+	/**
+	 * NOT IMPLEMENTED. Is defined here in preparation for DOM 3.
+	 */
+	public void setXmlStandalone(boolean xmlStandalone) throws DOMException {
+		throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Not implemented in this version"); //$NON-NLS-1$
+	}
+
+	/**
+	 * NOT IMPLEMENTED. Is defined here in preparation for DOM 3.
+	 */
+	public String getXmlVersion() {
+		throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Not implemented in this version"); //$NON-NLS-1$
+	}
+
+	/**
+	 * NOT IMPLEMENTED. Is defined here in preparation for DOM 3.
+	 */
+	public void setXmlVersion(String xmlVersion) throws DOMException {
+		throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Not implemented in this version"); //$NON-NLS-1$
+	}
+
+	/**
+	 * NOT IMPLEMENTED. Is defined here in preparation for DOM 3.
+	 */
+	public String getDocumentURI() {
+		throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Not implemented in this version"); //$NON-NLS-1$
+	}
+
+	/**
+	 * NOT IMPLEMENTED. Is defined here in preparation for DOM 3.
+	 */
+	public void setDocumentURI(String documentURI) {
+		throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Not implemented in this version"); //$NON-NLS-1$
+	}
+
+	/**
+	 * NOT IMPLEMENTED. Is defined here in preparation for DOM 3.
+	 */
+	public DOMConfiguration getDomConfig() {
+		throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Not implemented in this version"); //$NON-NLS-1$
+	}
+
+	/**
+	 * NOT IMPLEMENTED. Is defined here in preparation for DOM 3.
+	 */
+	public void normalizeDocument() {
+		throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Not implemented in this version"); //$NON-NLS-1$
+	}
+
+	/**
+	 * NOT IMPLEMENTED. Is defined here in preparation for DOM 3.
+	 */
+	public Node renameNode(Node n, String namespaceURI, String qualifiedName) throws DOMException {
+		throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Not implemented in this version"); //$NON-NLS-1$
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/DocumentTypeAdapter.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/DocumentTypeAdapter.java
new file mode 100644
index 0000000..d216704
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/DocumentTypeAdapter.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapter;
+import org.w3c.dom.DocumentType;
+
+
+/**
+ */
+public interface DocumentTypeAdapter extends INodeAdapter {
+	static final int LOWER_CASE = 2;
+	static final int STRICT_CASE = 0;
+	static final int UPPER_CASE = 1;
+
+	/**
+	 */
+	int getAttrNameCase();
+
+	/**
+	 */
+	DocumentType getDocumentType();
+
+	/**
+	 */
+	int getTagNameCase();
+
+	/**
+	 */
+	boolean hasFeature(String feature);
+
+	/**
+	 */
+	boolean isXMLType();
+
+	/**
+	 */
+	void release();
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/DocumentTypeAdapterImpl.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/DocumentTypeAdapterImpl.java
new file mode 100644
index 0000000..29c3e95
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/DocumentTypeAdapterImpl.java
@@ -0,0 +1,119 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
+import org.w3c.dom.DocumentType;
+
+
+/**
+ */
+public class DocumentTypeAdapterImpl implements DocumentTypeAdapter {
+
+	private IDOMDocument document = null;
+	private DocumentType documentType = null;
+
+	/**
+	 */
+	protected DocumentTypeAdapterImpl() {
+		super();
+	}
+
+	/**
+	 */
+	protected DocumentTypeAdapterImpl(IDOMDocument document) {
+		this.document = document;
+		if (document != null) {
+			this.documentType = document.getDoctype();
+		}
+	}
+
+	/**
+	 */
+	public int getAttrNameCase() {
+		return STRICT_CASE;
+	}
+
+	/**
+	 */
+	protected IDOMDocument getDocument() {
+		return this.document;
+	}
+
+	/**
+	 */
+	public DocumentType getDocumentType() {
+		return this.documentType;
+	}
+
+	/**
+	 */
+	public int getTagNameCase() {
+		return STRICT_CASE;
+	}
+
+	/**
+	 */
+	public boolean hasFeature(String feature) {
+		return false;
+	}
+
+	/**
+	 */
+	public boolean isAdapterForType(Object type) {
+		return (type == DocumentTypeAdapter.class);
+	}
+
+	/**
+	 */
+	public boolean isXMLType() {
+		return true;
+	}
+
+	/**
+	 */
+	public void notifyChanged(INodeNotifier notifier, int eventType, Object changedFeature, Object oldValue, Object newValue, int pos) {
+		if (eventType != INodeNotifier.STRUCTURE_CHANGED)
+			return;
+		if (notifier == null || !(notifier instanceof IDOMDocument))
+			return;
+		this.documentType = ((IDOMDocument) notifier).getDoctype();
+	}
+
+	/**
+	 */
+	protected void notifyDocumentTypeChanged() {
+		if (this.document == null)
+			return;
+		IDOMModel model = this.document.getModel();
+		if (model == null)
+			return;
+		((DOMModelImpl) model).documentTypeChanged();
+	}
+
+	/**
+	 */
+	public void release() {
+		// nothing to do
+	}
+
+	/**
+	 */
+	protected void setDocumentType(DocumentType documentType) {
+		this.documentType = documentType;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/DocumentTypeImpl.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/DocumentTypeImpl.java
new file mode 100644
index 0000000..5ff86bf
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/DocumentTypeImpl.java
@@ -0,0 +1,228 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *     Balazs Banfai: Bug 154737 getUserData/setUserData support for Node
+ *     https://bugs.eclipse.org/bugs/show_bug.cgi?id=154737
+ *     David Carver (STAR) - bug 296999 - Inefficient use of new String()
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocumentType;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.UserDataHandler;
+
+
+/**
+ * DocumentType class
+ */
+public class DocumentTypeImpl extends NodeImpl implements IDOMDocumentType {
+	private String internalSubset = null;
+
+	private String name = null;
+	private String publicId = null;
+	private String systemId = null;
+
+	/**
+	 * DocumentTypeImpl constructor
+	 */
+	protected DocumentTypeImpl() {
+		super();
+	}
+
+	/**
+	 * DocumentTypeImpl constructor
+	 * 
+	 * @param that
+	 *            DocumentTypeImpl
+	 */
+	protected DocumentTypeImpl(DocumentTypeImpl that) {
+		super(that);
+
+		if (that != null) {
+			this.name = that.name;
+		}
+	}
+
+	/**
+	 * cloneNode method
+	 * 
+	 * @return org.w3c.dom.Node
+	 * @param deep
+	 *            boolean
+	 */
+	public Node cloneNode(boolean deep) {
+		DocumentTypeImpl cloned = new DocumentTypeImpl(this);
+		notifyUserDataHandlers(UserDataHandler.NODE_CLONED, cloned);
+		return cloned;
+	}
+
+	/**
+	 * getEntities method
+	 * 
+	 * @return org.w3c.dom.NamedNodeMap
+	 */
+	public NamedNodeMap getEntities() {
+		return null;
+	}
+
+	/**
+	 */
+	public String getInternalSubset() {
+		return this.internalSubset;
+	}
+
+	/**
+	 * getName method
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getName() {
+		if (this.name == null)
+			return NodeImpl.EMPTY_STRING;
+		return this.name;
+	}
+
+	/**
+	 * getNodeName
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getNodeName() {
+		return getName();
+	}
+
+	/**
+	 * getNodeType method
+	 * 
+	 * @return short
+	 */
+	public short getNodeType() {
+		return DOCUMENT_TYPE_NODE;
+	}
+
+	/**
+	 * getNotations method
+	 * 
+	 * @return org.w3c.dom.NamedNodeMap
+	 */
+	public NamedNodeMap getNotations() {
+		return null;
+	}
+
+	/**
+	 * getPublicId method
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getPublicId() {
+		return this.publicId;
+	}
+
+	/**
+	 * getSystemId method
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getSystemId() {
+		return this.systemId;
+	}
+
+	/**
+	 */
+	public boolean isClosed() {
+		IStructuredDocumentRegion flatNode = getStructuredDocumentRegion();
+		if (flatNode == null)
+			return true; // will be generated
+		String regionType = StructuredDocumentRegionUtil.getLastRegionType(flatNode);
+		return (regionType == DOMRegionContext.XML_DOCTYPE_DECLARATION_CLOSE || regionType == DOMRegionContext.XML_DECLARATION_CLOSE);
+	}
+
+	/**
+	 */
+	public void setInternalSubset(String internalSubset) {
+		if (!isDataEditable()) {
+			throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, DOMMessages.NO_MODIFICATION_ALLOWED_ERR);
+		}
+
+		this.internalSubset = internalSubset;
+	}
+
+	/**
+	 * setName method
+	 * 
+	 * @param name
+	 *            java.lang.String
+	 */
+	protected void setName(String name) {
+		this.name = name;
+	}
+
+	/**
+	 * setPublicId method
+	 * 
+	 * @param publicId
+	 *            java.lang.String
+	 */
+	public void setPublicId(String publicId) {
+		if (!isDataEditable()) {
+			throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, DOMMessages.NO_MODIFICATION_ALLOWED_ERR);
+		}
+
+		this.publicId = publicId;
+
+		notifyValueChanged();
+	}
+
+	/**
+	 * setSystemId method
+	 * 
+	 * @param systemId
+	 *            java.lang.String
+	 */
+	public void setSystemId(String systemId) {
+		if (!isDataEditable()) {
+			throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, DOMMessages.NO_MODIFICATION_ALLOWED_ERR);
+		}
+
+		this.systemId = systemId;
+
+		notifyValueChanged();
+	}
+
+	/**
+	 * toString method
+	 * 
+	 * @return java.lang.String
+	 */
+	public String toString() {
+		StringBuffer buffer = new StringBuffer();
+		buffer.append(getName());
+		buffer.append('(');
+		buffer.append(getPublicId());
+		buffer.append(')');
+		buffer.append('(');
+		buffer.append(getSystemId());
+		buffer.append(')');
+		IStructuredDocumentRegion flatNode = getStructuredDocumentRegion();
+		if (flatNode != null) {
+			buffer.append('@');
+			buffer.append(flatNode.toString());
+		}
+		return buffer.toString();
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/ElementImpl.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/ElementImpl.java
new file mode 100644
index 0000000..74cafdd
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/ElementImpl.java
@@ -0,0 +1,1516 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2011 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
+ *     
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *    
+ *     Valentin Baciu - https://bugs.eclipse.org/bugs/show_bug.cgi?id=139552
+ *     
+ *     Balazs Banfai: Bug 154737 getUserData/setUserData support for Node
+ *     https://bugs.eclipse.org/bugs/show_bug.cgi?id=154737
+ *     David Carver (STAR) - bug 296999 - Inefficient use of new String()
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import java.util.Iterator;
+
+import org.eclipse.wst.sse.core.internal.ltk.parser.RegionParser;
+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.ITextRegionList;
+import org.eclipse.wst.xml.core.internal.commentelement.CommentElementAdapter;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.modelquery.ModelQueryUtil;
+import org.eclipse.wst.xml.core.internal.parser.XMLSourceParser;
+import org.eclipse.wst.xml.core.internal.provisional.IXMLNamespace;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
+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 org.w3c.dom.Attr;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.UserDataHandler;
+import org.w3c.dom.traversal.NodeFilter;
+import org.w3c.dom.traversal.NodeIterator;
+
+
+/**
+ * ElementImpl class
+ */
+public class ElementImpl extends NodeContainer implements IDOMElement {
+
+	private class Attributes implements NamedNodeMap {
+		Attributes() {
+			super();
+		}
+
+		public int getLength() {
+			if (attrNodes == null)
+				return 0;
+			return attrNodes.getLength();
+		}
+
+		public Node getNamedItem(String name) {
+			return getAttributeNode(name);
+		}
+
+		public Node getNamedItemNS(String uri, String name) {
+			return getAttributeNodeNS(uri, name);
+		}
+
+		public Node item(int index) {
+			if (attrNodes == null)
+				return null;
+			return attrNodes.item(index);
+		}
+
+		public Node removeNamedItem(String name) throws DOMException {
+			return removeAttributeNode(name);
+		}
+
+		public Node removeNamedItemNS(String uri, String name) throws DOMException {
+			return removeAttributeNodeNS(uri, name);
+		}
+
+		public Node setNamedItem(Node arg) throws DOMException {
+			return setAttributeNode((AttrImpl) arg);
+		}
+
+		public Node setNamedItemNS(Node arg) throws DOMException {
+			return setAttributeNodeNS((AttrImpl) arg);
+		}
+	}
+
+//	private static final char[] XMLNS_PREFIX = IXMLNamespace.XMLNS_PREFIX.toCharArray();
+	private static final byte FLAG_COMMENT = 0x1;
+	private static final byte FLAG_EMPTY = 0x2;
+	private static final byte FLAG_JSP = 0x4;
+	
+	private byte fTagFlags = 0;
+	
+	NodeListImpl attrNodes = null;
+	private IStructuredDocumentRegion endStructuredDocumentRegion = null;
+	
+	private char[] fTagName = null;
+
+	private char[] fNamespaceURI = null;
+
+	/**
+	 * ElementImpl constructor
+	 */
+	protected ElementImpl() {
+		super();
+	}
+
+	/**
+	 * ElementImpl constructor
+	 * 
+	 * @param that
+	 *            ElementImpl
+	 */
+	protected ElementImpl(ElementImpl that) {
+		super(that);
+
+		if (that != null) {
+			this.fTagName = that.fTagName;
+			this.fTagFlags = that.fTagFlags;
+
+			// clone attributes
+			that.cloneAttributes(this);
+		}
+	}
+
+	/**
+	 * addEndTag method
+	 * 
+	 * @param end
+	 *            org.w3c.dom.Element
+	 */
+	protected void addEndTag(Element endTag) {
+		if (endTag == null)
+			return;
+		if (hasEndTag())
+			return;
+		ElementImpl end = (ElementImpl) endTag;
+
+		// move the end flat node from the end tag
+		IStructuredDocumentRegion flatNode = end.getEndStructuredDocumentRegion();
+		if (flatNode == null)
+			return;
+		end.setEndStructuredDocumentRegion(null);
+		setEndStructuredDocumentRegion(flatNode);
+	}
+
+	/**
+	 * appendAttibuteNode method
+	 * 
+	 * @return org.w3c.dom.Attr
+	 * @param newAttr
+	 *            org.w3c.dom.Attr
+	 */
+	public Attr appendAttributeNode(Attr newAttr) {
+		if (newAttr == null)
+			return null;
+		AttrImpl attr = (AttrImpl) newAttr;
+		if (attr.getOwnerElement() != null)
+			return null;
+
+		if (!isDataEditable()) {
+			throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, DOMMessages.NO_MODIFICATION_ALLOWED_ERR);
+		}
+
+		if (this.attrNodes == null)
+			this.attrNodes = new NodeListImpl();
+		this.attrNodes.appendNode(attr);
+		attr.setOwnerElement(this);
+
+		notifyAttrReplaced(attr, null);
+		return attr;
+	}
+
+	/**
+	 * cloneAttributes method
+	 * 
+	 * @param newOwner
+	 *            org.w3c.dom.Element
+	 */
+	protected void cloneAttributes(Element newOwner) {
+		if (newOwner == null || newOwner == this)
+			return;
+
+		ElementImpl element = (ElementImpl) newOwner;
+		element.removeAttributes();
+
+		if (this.attrNodes == null)
+			return;
+
+		int length = this.attrNodes.getLength();
+		for (int i = 0; i < length; i++) {
+			Node node = this.attrNodes.item(i);
+			if (node == null)
+				continue;
+			Attr cloned = (Attr) node.cloneNode(false);
+			if (cloned != null)
+				element.appendAttributeNode(cloned);
+		}
+	}
+
+	/**
+	 * cloneNode method
+	 * 
+	 * @return org.w3c.dom.Node
+	 * @param deep
+	 *            boolean
+	 */
+	public Node cloneNode(boolean deep) {
+		ElementImpl cloned = newInstance();
+		if (deep)
+			cloneChildNodes(cloned, deep);
+		
+		notifyUserDataHandlers(UserDataHandler.NODE_CLONED, cloned);
+		return cloned;
+	}
+
+	protected ElementImpl newInstance() {
+		return new ElementImpl(this);
+	}
+
+	/**
+	 * getAttribute method
+	 * 
+	 * @return java.lang.String
+	 * @param name
+	 *            java.lang.String
+	 */
+	public String getAttribute(String name) {
+		Attr attr = getAttributeNode(name);
+		// In the absence of the attribute, get the default value
+		if (attr == null) {
+			String defaultValue = getDefaultValue(name);
+			return (defaultValue != null) ? defaultValue : NodeImpl.EMPTY_STRING;
+		}
+		return attr.getValue();
+	}
+
+	/**
+	 * get the default value for attribute <code>name</code>. Returns an empty string
+	 * @param name
+	 * @return
+	 */
+	private String getDefaultValue(String name) {
+		CMNamedNodeMap map = ((DocumentImpl) getOwnerDocument()).getCMAttributes(this);
+		if (map != null) {
+			CMNode attribute = map.getNamedItem(name);
+			if (attribute instanceof CMAttributeDeclaration)
+				return ((CMAttributeDeclaration) attribute).getAttrType().getImpliedValue();
+		}
+		return NodeImpl.EMPTY_STRING;
+	}
+
+	/**
+	 * getAttributeNode method
+	 * 
+	 * @return org.w3c.dom.Attr
+	 * @param name
+	 *            java.lang.String
+	 */
+	public Attr getAttributeNode(String name) {
+		if (name == null)
+			return null; // invalid parameter
+		if (this.attrNodes == null)
+			return null; // no attribute
+
+		int length = this.attrNodes.getLength();
+		char[] nameChars = name.toCharArray();
+		for (int i = 0; i < length; i++) {
+			AttrImpl attr = (AttrImpl) this.attrNodes.item(i);
+			if (attr == null)
+				continue;
+			if (attr.matchName(nameChars))
+				return attr; // found
+		}
+
+		return null; // not found
+	}
+
+	/**
+	 */
+	public Attr getAttributeNodeNS(String uri, String name) {
+		if (name == null)
+			return null; // invalid parameter
+		if (this.attrNodes == null)
+			return null; // no attribute
+
+		int length = this.attrNodes.getLength();
+		for (int i = 0; i < length; i++) {
+			AttrImpl attr = (AttrImpl) this.attrNodes.item(i);
+			if (attr == null)
+				continue;
+			String localName = attr.getLocalName();
+			if (localName == null || !localName.equals(name))
+				continue;
+			String nsURI = attr.getNamespaceURI();
+			if (uri == null) {
+				if (nsURI != null)
+					continue;
+			}
+			else {
+				if (nsURI == null || !nsURI.equals(uri))
+					continue;
+			}
+
+			// found
+			return attr;
+		}
+
+		return null; // not found
+	}
+
+	/**
+	 */
+	public String getAttributeNS(String uri, String name) {
+		Attr attr = getAttributeNodeNS(uri, name);
+		// In the absence of the attribute, get the default value
+		if (attr == null) {
+			String defaultValue = getDefaultValue(name);
+			return (defaultValue != null) ? defaultValue : NodeImpl.EMPTY_STRING;
+		}
+		return attr.getValue();
+	}
+
+	/**
+	 * getAttributes method
+	 * 
+	 * @return org.w3c.dom.NamedNodeMap
+	 */
+	public NamedNodeMap getAttributes() {
+		return new Attributes();
+	}
+
+	/**
+	 */
+	protected CMElementDeclaration getDeclaration() {
+		Document document = getOwnerDocument();
+		if (document == null)
+			return null;
+		ModelQuery modelQuery = ModelQueryUtil.getModelQuery(document);
+		if (modelQuery == null)
+			return null;
+		return modelQuery.getCMElementDeclaration(this);
+	}
+
+	/**
+	 * getElementsByTagName method
+	 * 
+	 * @return org.w3c.dom.NodeList
+	 * @param tagName
+	 *            java.lang.String
+	 */
+	public NodeList getElementsByTagName(String tagName) {
+		if (tagName == null)
+			return new NodeListImpl();
+
+		DocumentImpl document = (DocumentImpl) getOwnerDocument();
+		if (document == null)
+			return new NodeListImpl();
+		NodeIterator it = document.createNodeIterator(this, NodeFilter.SHOW_ALL, null, false);
+		if (it == null)
+			return new NodeListImpl();
+		NodeListImpl elements = new NodeListImpl();
+
+		if (tagName.length() == 1 && tagName.charAt(0) == '*') {
+			tagName = null; // do not care
+		}
+
+		it.nextNode(); // skip the first node since it is the root from createNodeIterator
+		for (Node node = it.nextNode(); node != null; node = it.nextNode()) {
+			if (node.getNodeType() != ELEMENT_NODE)
+				continue;
+			if (tagName != null) {
+				ElementImpl element = (ElementImpl) node;
+				if (!element.matchTagName(tagName))
+					continue;
+			}
+			elements.appendNode(node);
+		}
+
+		return elements;
+	}
+
+	/**
+	 */
+	public NodeList getElementsByTagNameNS(String uri, String tagName) {
+		if (tagName == null)
+			return new NodeListImpl();
+
+		DocumentImpl document = (DocumentImpl) getOwnerDocument();
+		if (document == null)
+			return new NodeListImpl();
+		NodeIterator it = document.createNodeIterator(this, NodeFilter.SHOW_ALL, null, false);
+		if (it == null)
+			return new NodeListImpl();
+		NodeListImpl elements = new NodeListImpl();
+
+		if (uri != null && uri.length() == 1 && uri.charAt(0) == '*') {
+			uri = null; // do not care
+		}
+		if (tagName.length() == 1 && tagName.charAt(0) == '*') {
+			tagName = null; // do not care
+		}
+
+		it.nextNode(); // skip the first node since it is the root from createNodeIterator
+		for (Node node = it.nextNode(); node != null; node = it.nextNode()) {
+			if (node.getNodeType() != ELEMENT_NODE)
+				continue;
+			ElementImpl element = (ElementImpl) node;
+			if (tagName != null) {
+				String localName = element.getLocalName();
+				if (localName == null || !localName.equals(tagName))
+					continue;
+			}
+			if (uri != null) {
+				String nsURI = element.getNamespaceURI();
+				if (nsURI == null || !nsURI.equals(uri))
+					continue;
+			}
+			elements.appendNode(element);
+		}
+
+		return elements;
+	}
+
+	/**
+	 * getEndOffset method
+	 * 
+	 * @return int
+	 */
+	public int getEndOffset() {
+		if (this.endStructuredDocumentRegion != null)
+			return this.endStructuredDocumentRegion.getEnd();
+		return super.getEndOffset();
+	}
+
+	/**
+	 * getEndStartOffset method
+	 * 
+	 * @return int
+	 */
+	public int getEndStartOffset() {
+		if (this.endStructuredDocumentRegion != null)
+			return this.endStructuredDocumentRegion.getStart();
+		return super.getEndOffset();
+	}
+
+	/**
+	 * getEndStructuredDocumentRegion method
+	 * 
+	 */
+	public IStructuredDocumentRegion getEndStructuredDocumentRegion() {
+		return this.endStructuredDocumentRegion;
+	}
+
+	public String getEndTagName() {
+		if (this.endStructuredDocumentRegion == null)
+			return null;
+
+		ITextRegionList regions = this.endStructuredDocumentRegion.getRegions();
+		if (regions == null)
+			return null;
+		Iterator e = regions.iterator();
+		while (e.hasNext()) {
+			ITextRegion region = (ITextRegion) e.next();
+			String regionType = region.getType();
+			if (regionType == DOMRegionContext.XML_TAG_NAME || isNestedEndTag(regionType)) {
+				return this.endStructuredDocumentRegion.getText(region);
+			}
+		}
+
+		return null;
+	}
+
+	protected boolean isNestedEndTag(String regionType) {
+		boolean result = false;
+		return result;
+	}
+
+	/**
+	 * getFirstStructuredDocumentRegion method
+	 * 
+	 */
+	public IStructuredDocumentRegion getFirstStructuredDocumentRegion() {
+		IStructuredDocumentRegion flatNode = getStructuredDocumentRegion();
+		if (flatNode != null)
+			return StructuredDocumentRegionUtil.getStructuredDocumentRegion(flatNode);
+		return StructuredDocumentRegionUtil.getStructuredDocumentRegion(this.endStructuredDocumentRegion);
+	}
+
+	/**
+	 * getLastStructuredDocumentRegion method
+	 * 
+	 */
+	public IStructuredDocumentRegion getLastStructuredDocumentRegion() {
+		if (this.endStructuredDocumentRegion != null)
+			return StructuredDocumentRegionUtil.getStructuredDocumentRegion(this.endStructuredDocumentRegion);
+		return StructuredDocumentRegionUtil.getStructuredDocumentRegion(getStructuredDocumentRegion());
+	}
+
+	/**
+	 */
+	public String getLocalName() {
+		if (this.fTagName == null)
+			return null;
+		int index = CharOperation.indexOf(this.fTagName, ':');
+		if (index < 0)
+			return new String(this.fTagName);
+		return new String(this.fTagName, index + 1, this.fTagName.length - index - 1);
+	}
+
+	public String getNamespaceURI() {
+		String nsAttrName = null;
+		String prefix = getPrefix();
+		if (prefix != null && prefix.length() > 0) {
+			nsAttrName = IXMLNamespace.XMLNS_PREFIX + prefix;
+		}
+		else {
+			nsAttrName = IXMLNamespace.XMLNS;
+		}
+
+		for (Node node = this; node != null; node = node.getParentNode()) {
+			if (node.getNodeType() != ELEMENT_NODE)
+				break;
+			Element element = (Element) node;
+			Attr attr = element.getAttributeNode(nsAttrName);
+			if (attr != null)
+				return attr.getValue();
+		}
+
+		if (this.fNamespaceURI == null)
+			return null;
+		return new String(this.fNamespaceURI);
+	}
+
+	/**
+	 * getNodeName method
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getNodeName() {
+		return getTagName();
+	}
+
+	/**
+	 * getNodeType method
+	 * 
+	 * @return short
+	 */
+	public short getNodeType() {
+		return ELEMENT_NODE;
+	}
+
+	/**
+	 */
+	public String getPrefix() {
+		if (this.fTagName == null)
+			return null;
+		int index = CharOperation.indexOf(this.fTagName, ':');
+		if (index <= 0)
+			return null;
+		// exclude JSP tag in name
+		if (this.fTagName[0] == '<')
+			return null;
+		return new String(this.fTagName, 0, index);
+	}
+
+	/**
+	 * getStartEndOffset method
+	 * 
+	 * @return int
+	 */
+	public int getStartEndOffset() {
+		IStructuredDocumentRegion flatNode = getStructuredDocumentRegion();
+		if (flatNode != null)
+			return flatNode.getEnd();
+		return super.getStartOffset();
+	}
+
+	/**
+	 * getStartOffset method
+	 * 
+	 * @return int
+	 */
+	public int getStartOffset() {
+		if (getStartStructuredDocumentRegion() == null && this.endStructuredDocumentRegion != null && !hasChildNodes()) {
+			return this.endStructuredDocumentRegion.getStart();
+		}
+		return super.getStartOffset();
+	}
+
+	/**
+	 * getStartStructuredDocumentRegion method
+	 * 
+	 */
+	public IStructuredDocumentRegion getStartStructuredDocumentRegion() {
+		return getStructuredDocumentRegion();
+	}
+
+	/**
+	 * getTagName method
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getTagName() {
+		if (this.fTagName == null)
+			return NodeImpl.EMPTY_STRING;
+		return new String(fTagName);
+	}
+
+	/**
+	 */
+	public boolean hasAttribute(String name) {
+		return (getAttributeNode(name) != null);
+	}
+
+	/**
+	 */
+	public boolean hasAttributeNS(String uri, String name) {
+		return (getAttributeNodeNS(uri, name) != null);
+	}
+
+	/**
+	 */
+	public boolean hasAttributes() {
+		return (this.attrNodes != null && this.attrNodes.getLength() > 0);
+	}
+
+	/**
+	 * hasEndTag method
+	 * 
+	 * @return boolean
+	 */
+	public boolean hasEndTag() {
+		return (this.endStructuredDocumentRegion != null);
+	}
+
+	/**
+	 */
+	protected final boolean hasPrefix() {
+		if (this.fTagName == null || this.fTagName.length == 0)
+			return false;
+		return CharOperation.indexOf(this.fTagName, ':') > 0 && this.fTagName[0] != '<';
+	}
+
+	/**
+	 * hasStartTag method
+	 * 
+	 * @return boolean
+	 */
+	public boolean hasStartTag() {
+		return (getStructuredDocumentRegion() != null);
+	}
+
+	/**
+	 */
+	protected final boolean ignoreCase() {
+		DocumentImpl document = (DocumentImpl) getOwnerDocument();
+		if (document != null && document.ignoreCase()) {
+			// even in case insensitive document, if having prefix, it's case
+			// sensitive tag
+			return !hasPrefix();
+		}
+		return false;
+	}
+
+	/**
+	 */
+	protected Attr insertAttributeNode(Attr newAttr, int index) {
+		if (newAttr == null)
+			return null;
+		AttrImpl attr = (AttrImpl) newAttr;
+		if (attr.getOwnerElement() != null)
+			return null;
+
+		if (this.attrNodes == null)
+			this.attrNodes = new NodeListImpl();
+		this.attrNodes.insertNode(attr, index);
+		attr.setOwnerElement(this);
+
+		notifyAttrReplaced(attr, null);
+		return attr;
+	}
+
+	/**
+	 * insertBefore method
+	 * 
+	 * @return org.w3c.dom.Node
+	 * @param newChild
+	 *            org.w3c.dom.Node
+	 * @param refChild
+	 *            org.w3c.dom.Node
+	 */
+	public Node insertBefore(Node newChild, Node refChild) throws DOMException {
+		// should throw DOMException instead of return null?
+		if (newChild == null)
+			return null;
+		if (!isContainer()) { // never be container
+			throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, DOMMessages.HIERARCHY_REQUEST_ERR);
+		}
+		if (newChild.getNodeType() != TEXT_NODE && newChild.getNodeType() != CDATA_SECTION_NODE) {
+			if (isJSPContainer() || isCDATAContainer()) { // accepts only
+				// Text
+				// child
+				throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, DOMMessages.HIERARCHY_REQUEST_ERR);
+			}
+		}
+		return super.insertBefore(newChild, refChild);
+	}
+
+	/**
+	 */
+	protected boolean isCDATAContainer() {
+		// use BlockMaker instead of CMElementDeclaration
+		// because <style> and <script> in XHTML is not CDATA content type
+		IDOMModel model = getModel();
+		if (model == null)
+			return false; // error
+		IStructuredDocument structuredDocument = model.getStructuredDocument();
+		if (structuredDocument == null || fTagName == null)
+			return false; // eror
+		RegionParser parser = structuredDocument.getParser();
+		if (parser == null || !(parser instanceof XMLSourceParser))
+			return false;
+		return (((XMLSourceParser) parser).getBlockMarker(new String(this.fTagName)) != null);
+		/*
+		 * CMElementDeclaration decl = getDeclaration(); if (decl == null)
+		 * return false; if (decl instanceof CMNodeWrapper) { decl =
+		 * (CMElementDeclaration)((CMNodeWrapper)decl).getOriginNode(); if
+		 * (decl == null) return false; } if (decl instanceof
+		 * TLDElementDeclaration) { String content =
+		 * ((TLDElementDeclaration)decl).getBodycontent(); if (content ==
+		 * null) return false; return
+		 * content.equals(JSP11TLDNames.CONTENT_TAGDEPENDENT); } if
+		 * (!isGlobalTag()) return false; return (decl.getContentType() ==
+		 * CMElementDeclaration.CDATA);
+		 */
+	}
+
+	/**
+	 */
+	public boolean isClosed() {
+		IStructuredDocumentRegion flatNode = null;
+		if (isEmptyTag() || !isContainer()) {
+			flatNode = getStructuredDocumentRegion();
+			if (flatNode == null)
+				return true; // will be generated
+		}
+		else {
+			flatNode = getEndStructuredDocumentRegion();
+			if (flatNode == null)
+				return false; // must be generated
+		}
+		String regionType = StructuredDocumentRegionUtil.getLastRegionType(flatNode);
+		if (isCommentTag()) {
+			return (isNestedClosedComment(regionType) || regionType == DOMRegionContext.XML_COMMENT_CLOSE);
+		}
+		if (isJSPTag()) {
+			return isNestedClosed(regionType);
+		}
+		return (regionType == DOMRegionContext.XML_TAG_CLOSE || regionType == DOMRegionContext.XML_EMPTY_TAG_CLOSE || regionType == DOMRegionContext.XML_DECLARATION_CLOSE);
+	}
+
+	protected boolean isNestedClosed(String regionType) {
+		boolean result = false;
+		return result;
+	}
+
+	protected boolean isNestedClosedComment(String regionType) {
+		boolean result = false;
+		return result;
+	}
+
+	/**
+	 */
+	public final boolean isCommentTag() {
+		return (fTagFlags & FLAG_COMMENT) != 0;
+	}
+
+	/**
+	 * isContainer method
+	 * 
+	 * @return boolean
+	 */
+	public boolean isContainer() {
+		if (isCommentTag()) {
+			CommentElementAdapter adapter = (CommentElementAdapter) getAdapterFor(CommentElementAdapter.class);
+			if (adapter != null) {
+				return (adapter.isContainer());
+			}
+			return (getDeclaration() == null);
+		}
+		if (isJSPTag()) {
+			// exclude JSP directive
+			return (matchTagName(JSPTag.JSP_SCRIPTLET) || matchTagName(JSPTag.JSP_DECLARATION) || matchTagName(JSPTag.JSP_EXPRESSION));
+		}
+		if (!isXMLTag()) { // non-XML tag
+			CMElementDeclaration decl = getDeclaration();
+			if (decl == null)
+				return true; // undefined tag
+			return (decl.getContentType() != CMElementDeclaration.EMPTY);
+		}
+		return true;
+	}
+
+	/**
+	 * isEmptyTag method
+	 * 
+	 * @return boolean
+	 */
+	public boolean isEmptyTag() {
+		if (isJSPTag())
+			return false;
+		if (isCommentTag())
+			return false;
+		if (!isXMLTag())
+			return false;
+		return (fTagFlags & FLAG_EMPTY) != 0;
+	}
+
+	/**
+	 */
+	public boolean isEndTag() {
+		return (hasEndTag() && !hasStartTag() && !hasChildNodes());
+	}
+
+	/**
+	 */
+	public boolean isGlobalTag() {
+		return !hasPrefix();
+	}
+
+	/**
+	 */
+	public boolean isImplicitTag() {
+		if (hasStartTag() || hasEndTag())
+			return false;
+		// make sure this is in the document tree
+		// because if not in the document tree, no tags are generated yet
+		return (getContainerDocument() != null);
+	}
+
+	/**
+	 */
+	public boolean isJSPContainer() {
+		return (isJSPTag() && !isCommentTag() && isContainer());
+	}
+
+	/**
+	 * isJSPTag method
+	 * 
+	 * @return boolean
+	 */
+	public final boolean isJSPTag() {
+		return (fTagFlags & FLAG_JSP) != 0;
+	}
+
+	/**
+	 */
+	public boolean isStartTagClosed() {
+		IStructuredDocumentRegion flatNode = getStructuredDocumentRegion();
+		if (flatNode == null)
+			return true; // will be generated
+		String regionType = StructuredDocumentRegionUtil.getLastRegionType(flatNode);
+		if (isCommentTag()) {
+			return (isNestedClosedComment(regionType) || regionType == DOMRegionContext.XML_COMMENT_CLOSE);
+		}
+		if (isJSPTag()) {
+			if (isContainer())
+				return true; // start tag always has a single region
+			return isClosedNestedDirective(regionType);
+		}
+		return (regionType == DOMRegionContext.XML_TAG_CLOSE || regionType == DOMRegionContext.XML_EMPTY_TAG_CLOSE || regionType == DOMRegionContext.XML_DECLARATION_CLOSE);
+	}
+
+	protected boolean isClosedNestedDirective(String regionType) {
+		boolean result = false;
+		return result;
+	}
+
+	/**
+	 */
+	public final boolean isXMLTag() {
+		if (isJSPTag())
+			return false;
+		if (isCommentTag())
+			return false;
+		DocumentImpl document = (DocumentImpl) getOwnerDocument();
+		if (document != null && !document.isXMLType()) {
+			// even in non-XML document, if having prefix, it's XML tag
+			return hasPrefix();
+		}
+		return true;
+	}
+
+	/**
+	 */
+	protected boolean matchEndTag(Element element) {
+		if (element == null)
+			return false;
+		ElementImpl impl = (ElementImpl) element;
+		if (isJSPTag() && !isCommentTag()) {
+			return (impl.isJSPTag() && !impl.isCommentTag());
+		}
+		return matchTagName(element.getTagName());
+	}
+
+	/**
+	 * matchTagName method
+	 * 
+	 * @return boolean
+	 * @param tagName
+	 *            java.lang.String
+	 */
+	public boolean matchTagName(String tagName) {
+		if (tagName == null)
+			return (this.fTagName == null);
+		if (this.fTagName == null)
+			return false;
+		if (this.fTagName.length != tagName.length())
+			return false;
+		String stringName = new String(this.fTagName);
+		if (!ignoreCase())
+			return stringName.equals(tagName);
+		return stringName.equalsIgnoreCase(tagName);
+	}
+
+	/**
+	 * notifyAttrReplaced method
+	 * 
+	 * @param newAttr
+	 *            org.w3c.dom.Attr
+	 * @param oldAttr
+	 *            org.w3c.dom.Attr
+	 */
+	protected void notifyAttrReplaced(Attr newAttr, Attr oldAttr) {
+		DocumentImpl document = (DocumentImpl) getContainerDocument();
+		if (document == null)
+			return;
+		DOMModelImpl model = (DOMModelImpl) document.getModel();
+		if (model == null)
+			return;
+		model.attrReplaced(this, newAttr, oldAttr);
+	}
+
+	/**
+	 * notifyValueChanged method
+	 */
+	public void notifyEndTagChanged() {
+		DocumentImpl document = (DocumentImpl) getContainerDocument();
+		if (document == null)
+			return;
+		DOMModelImpl model = (DOMModelImpl) document.getModel();
+		if (model == null)
+			return;
+		model.endTagChanged(this);
+	}
+
+	/**
+	 */
+	public void notifyStartTagChanged() {
+		DocumentImpl document = (DocumentImpl) getContainerDocument();
+		if (document == null)
+			return;
+		DOMModelImpl model = (DOMModelImpl) document.getModel();
+		if (model == null)
+			return;
+		model.startTagChanged(this);
+	}
+
+	/**
+	 */
+	public boolean preferEmptyTag() {
+		if (hasChildNodes())
+			return false;
+		if (isJSPTag())
+			return false;
+		if (isCommentTag())
+			return false;
+		if (!isXMLTag())
+			return false;
+		CMElementDeclaration decl = getDeclaration();
+		if (decl == null)
+			return false;
+		return (decl.getContentType() == CMElementDeclaration.EMPTY);
+	}
+
+	/**
+	 * removeAttribute method
+	 * 
+	 * @param name
+	 *            java.lang.String
+	 */
+	public void removeAttribute(String name) throws DOMException {
+		removeAttributeNode(name);
+	}
+
+	/**
+	 * removeAttributeNode method
+	 * 
+	 * @return org.w3c.dom.Attr
+	 * @param oldAttr
+	 *            org.w3c.dom.Attr
+	 */
+	public Attr removeAttributeNode(Attr oldAttr) throws DOMException {
+		if (oldAttr == null)
+			return null; // invalid parameter
+
+		if (!isDataEditable()) {
+			throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, DOMMessages.NO_MODIFICATION_ALLOWED_ERR);
+		}
+
+		if (this.attrNodes == null) { // no attribute
+			throw new DOMException(DOMException.NOT_FOUND_ERR, DOMMessages.NOT_FOUND_ERR);
+		}
+
+		int length = this.attrNodes.getLength();
+		for (int i = 0; i < length; i++) {
+			AttrImpl attr = (AttrImpl) this.attrNodes.item(i);
+			if (attr != oldAttr)
+				continue;
+
+			// found
+			this.attrNodes.removeNode(i);
+			attr.setOwnerElement(null);
+
+			notifyAttrReplaced(null, attr);
+			return attr;
+		}
+
+		// not found
+		throw new DOMException(DOMException.NOT_FOUND_ERR, DOMMessages.NOT_FOUND_ERR);
+	}
+
+	/**
+	 * removeAttributeNode method
+	 * 
+	 * @return org.w3c.dom.Attr
+	 * @param name
+	 *            java.lang.String
+	 */
+	public Attr removeAttributeNode(String name) {
+		if (name == null)
+			return null; // invalid parameter
+		if (this.attrNodes == null)
+			return null; // no attribute
+
+		if (!isDataEditable()) {
+			throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, DOMMessages.NO_MODIFICATION_ALLOWED_ERR);
+		}
+
+		int length = this.attrNodes.getLength();
+		for (int i = 0; i < length; i++) {
+			AttrImpl attr = (AttrImpl) this.attrNodes.item(i);
+			if (attr == null)
+				continue;
+			if (!attr.matchName(name))
+				continue;
+
+			// found
+			this.attrNodes.removeNode(i);
+			attr.setOwnerElement(null);
+
+			notifyAttrReplaced(null, attr);
+			return attr;
+		}
+
+		return null; // not found
+	}
+
+	/**
+	 */
+	public Attr removeAttributeNodeNS(String uri, String name) {
+		if (name == null)
+			return null; // invalid parameter
+		if (this.attrNodes == null)
+			return null; // no attribute
+
+		if (!isDataEditable()) {
+			throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, DOMMessages.NO_MODIFICATION_ALLOWED_ERR);
+		}
+
+		int length = this.attrNodes.getLength();
+		for (int i = 0; i < length; i++) {
+			AttrImpl attr = (AttrImpl) this.attrNodes.item(i);
+			if (attr == null)
+				continue;
+			String localName = attr.getLocalName();
+			if (localName == null || !localName.equals(name))
+				continue;
+			String nsURI = attr.getNamespaceURI();
+			if (uri == null) {
+				if (nsURI != null)
+					continue;
+			}
+			else {
+				if (nsURI == null || !nsURI.equals(uri))
+					continue;
+			}
+
+			// found
+			this.attrNodes.removeNode(i);
+			attr.setOwnerElement(null);
+
+			notifyAttrReplaced(null, attr);
+			return attr;
+		}
+
+		return null; // not found
+	}
+
+	/**
+	 */
+	public void removeAttributeNS(String uri, String name) throws DOMException {
+		removeAttributeNodeNS(uri, name);
+	}
+
+	/**
+	 * removeAttributes method
+	 */
+	public void removeAttributes() {
+		if (this.attrNodes == null)
+			return;
+
+		if (!isDataEditable()) {
+			throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, DOMMessages.NO_MODIFICATION_ALLOWED_ERR);
+		}
+
+		int length = this.attrNodes.getLength();
+		for (int i = 0; i < length; i++) {
+			AttrImpl attr = (AttrImpl) this.attrNodes.item(i);
+			if (attr != null) {
+				attr.setOwnerElement(null);
+				notifyAttrReplaced(null, attr);
+			}
+		}
+
+		this.attrNodes = null;
+	}
+
+	/**
+	 * removeEndTag method
+	 * 
+	 * @return org.w3c.dom.Element
+	 */
+	protected Element removeEndTag() {
+		if (!hasEndTag())
+			return null;
+		NodeListImpl attrNodes = this.attrNodes;
+		this.attrNodes = null; // not to copy attributes
+		ElementImpl end = (ElementImpl) cloneNode(false);
+		this.attrNodes = attrNodes;
+		if (end == null)
+			return null;
+
+		// move the end flat node to the end tag
+		IStructuredDocumentRegion flatNode = getEndStructuredDocumentRegion();
+		if (flatNode == null)
+			return null;
+		setEndStructuredDocumentRegion(null);
+		end.setEndStructuredDocumentRegion(flatNode);
+		return end;
+	}
+
+	/**
+	 */
+	protected void removeStartTag() {
+		removeAttributes();
+	}
+
+	/**
+	 * Resets attribute values from IStructuredDocumentRegion.
+	 */
+	void resetStructuredDocumentRegions() {
+		if (this.attrNodes != null) {
+			int length = this.attrNodes.getLength();
+			for (int i = 0; i < length; i++) {
+				AttrImpl attr = (AttrImpl) this.attrNodes.item(i);
+				if (attr == null)
+					continue;
+				attr.resetRegions();
+			}
+		}
+
+		super.resetStructuredDocumentRegions(); // for children
+
+		this.endStructuredDocumentRegion = null;
+	}
+
+	/**
+	 * setAttribute method
+	 * 
+	 * @param name
+	 *            java.lang.String
+	 * @param value
+	 *            java.lang.String
+	 */
+	public void setAttribute(String name, String value) throws DOMException {
+		if (name == null)
+			return;
+
+		if (!isDataEditable()) {
+			throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, DOMMessages.NO_MODIFICATION_ALLOWED_ERR);
+		}
+
+		Attr attr = getAttributeNode(name);
+		if (attr != null) {
+			attr.setValue(value); // change value
+			return;
+		}
+
+		// new attribute
+		Document doc = getOwnerDocument();
+		if (doc == null)
+			return;
+		attr = doc.createAttribute(name);
+		if (attr == null)
+			return;
+		attr.setValue(value);
+		appendAttributeNode(attr);
+	}
+
+	/**
+	 * setAttributeNode method
+	 * 
+	 * @return org.w3c.dom.Attr
+	 * @param newAttr
+	 *            org.w3c.dom.Attr
+	 */
+	public Attr setAttributeNode(Attr newAttr) throws DOMException {
+		if (newAttr == null)
+			return null; // nothing to do
+
+		if (!isDataEditable()) {
+			throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, DOMMessages.NO_MODIFICATION_ALLOWED_ERR);
+		}
+
+		AttrImpl attr = (AttrImpl) newAttr;
+		Element owner = attr.getOwnerElement();
+		if (owner != null) {
+			if (owner == this)
+				return null; // nothing to do
+			throw new DOMException(DOMException.INUSE_ATTRIBUTE_ERR, DOMMessages.INUSE_ATTRIBUTE_ERR);
+		}
+
+		Attr oldAttr = removeAttributeNode(newAttr.getName());
+		appendAttributeNode(attr);
+		return oldAttr;
+	}
+
+	/**
+	 */
+	public Attr setAttributeNodeNS(Attr newAttr) throws DOMException {
+		if (newAttr == null)
+			return null; // nothing to do
+
+		if (!isDataEditable()) {
+			throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, DOMMessages.NO_MODIFICATION_ALLOWED_ERR);
+		}
+
+		AttrImpl attr = (AttrImpl) newAttr;
+		Element owner = attr.getOwnerElement();
+		if (owner != null) {
+			if (owner == this)
+				return null; // nothing to do
+			throw new DOMException(DOMException.INUSE_ATTRIBUTE_ERR, DOMMessages.INUSE_ATTRIBUTE_ERR);
+		}
+
+		String name = newAttr.getLocalName();
+		String uri = newAttr.getNamespaceURI();
+		Attr oldAttr = removeAttributeNodeNS(uri, name);
+		appendAttributeNode(attr);
+		return oldAttr;
+	}
+
+	/**
+	 * ISSUE: we should check for and throw NAMESPACE_ERR, according to spec. 
+	 */
+	public void setAttributeNS(String uri, String qualifiedName, String value) throws DOMException {
+		if (qualifiedName == null)
+			return;
+
+		if (!isDataEditable()) {
+			throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, DOMMessages.NO_MODIFICATION_ALLOWED_ERR);
+		}
+
+		// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=139552
+		// fix provided by Valentin Baciu
+		int index = qualifiedName.indexOf(':');
+		String localName = index != -1 ? qualifiedName.substring(index + 1) : qualifiedName;
+
+		Attr attr = getAttributeNodeNS(uri, localName);
+		if (attr != null) {
+			attr.setValue(value); // change value
+		}
+		else {
+
+			// new attribute
+			Document doc = getOwnerDocument();
+			if (doc != null) {
+				attr = doc.createAttributeNS(uri, qualifiedName);
+				if (attr != null) {
+					attr.setValue(value);
+					appendAttributeNode(attr);
+				}
+			}
+		}
+	}
+
+	/**
+	 */
+	public void setCommentTag(boolean isCommentTag) {
+		IDOMNode parent = (IDOMNode) getParentNode();
+		if (parent != null && !parent.isChildEditable()) {
+			throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, DOMMessages.NO_MODIFICATION_ALLOWED_ERR);
+		}
+
+		if (isCommentTag)
+			fTagFlags |= FLAG_COMMENT;
+		else
+			fTagFlags &= ~FLAG_COMMENT;
+	}
+
+	/**
+	 * setEmptyTag method
+	 * 
+	 * @param isEmptyTag
+	 *            boolean
+	 */
+	public void setEmptyTag(boolean isEmptyTag) {
+		IDOMNode parent = (IDOMNode) getParentNode();
+		if (parent != null && !parent.isChildEditable()) {
+			throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, DOMMessages.NO_MODIFICATION_ALLOWED_ERR);
+		}
+
+		if (isEmptyTag)
+			fTagFlags |= FLAG_EMPTY;
+		else
+			fTagFlags &= ~FLAG_EMPTY;
+	}
+
+	/**
+	 * setEndStructuredDocumentRegion method
+	 * 
+	 * @param flatNode
+	 */
+	void setEndStructuredDocumentRegion(IStructuredDocumentRegion flatNode) {
+		this.endStructuredDocumentRegion = flatNode;
+
+		NodeContainer parent = (NodeContainer) getParentNode();
+		if (parent != null) {
+			parent.syncChildEditableState(this);
+		}
+	}
+
+	/**
+	 * setJSPTag method
+	 * 
+	 * @param isJSPTag
+	 *            boolean
+	 */
+	public void setJSPTag(boolean isJSPTag) {
+		IDOMNode parent = (IDOMNode) getParentNode();
+		if (parent != null && !parent.isChildEditable()) {
+			throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, NodeImpl.EMPTY_STRING);
+		}
+
+		if (isJSPTag)
+			fTagFlags |= FLAG_JSP;
+		else
+			fTagFlags &= ~FLAG_JSP;
+	}
+
+	protected void setNamespaceURI(String namespaceURI) {
+		if (namespaceURI == null)
+			this.fNamespaceURI = null;
+		else
+			this.fNamespaceURI = namespaceURI.toCharArray();
+	}
+
+	/**
+	 */
+	protected void setOwnerDocument(Document ownerDocument, boolean deep) {
+		super.setOwnerDocument(ownerDocument, deep);
+
+		if (this.attrNodes == null)
+			return;
+
+		int length = this.attrNodes.getLength();
+		for (int i = 0; i < length; i++) {
+			AttrImpl attr = (AttrImpl) this.attrNodes.item(i);
+			if (attr == null)
+				continue;
+			attr.setOwnerDocument(ownerDocument);
+		}
+	}
+
+	/**
+	 */
+	public void setPrefix(String prefix) throws DOMException {
+		IDOMNode parent = (IDOMNode) getParentNode();
+		if (parent != null && !parent.isChildEditable()) {
+			throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, NodeImpl.EMPTY_STRING);
+		}
+
+		int prefixLength = (prefix != null ? prefix.length() : 0);
+		String localName = getLocalName();
+		if (prefixLength == 0) {
+			if (localName == null || localName.length() == 0) {
+				// invalid local name
+				return;
+			}
+			setTagName(localName);
+		}
+		else {
+			int localLength = (localName != null ? localName.length() : 0);
+			StringBuffer buffer = new StringBuffer(prefixLength + 1 + localLength);
+			buffer.append(prefix);
+			buffer.append(':');
+			if (localName != null)
+				buffer.append(localName);
+			setTagName(buffer.toString());
+		}
+
+		boolean changeEndTag = hasEndTag();
+		notifyStartTagChanged();
+		if (changeEndTag)
+			notifyEndTagChanged();
+	}
+
+	/**
+	 * setStartStructuredDocumentRegion method
+	 * 
+	 * @param flatNode
+	 */
+	void setStartStructuredDocumentRegion(IStructuredDocumentRegion flatNode) {
+		setStructuredDocumentRegion(flatNode);
+	}
+
+	/**
+	 * setTagName method
+	 * 
+	 * @param tagName
+	 *            java.lang.String
+	 */
+	protected void setTagName(String tagName) {
+		this.fTagName = CharacterStringPool.getCharString(tagName);
+	}
+
+	/**
+	 * toString method
+	 * 
+	 * @return java.lang.String
+	 */
+	public String toString() {
+		StringBuffer buffer = new StringBuffer();
+		String tagName = getTagName();
+		if (hasStartTag())
+			buffer.append(tagName);
+		if (isEmptyTag())
+			buffer.append('/');
+		if (hasEndTag()) {
+			buffer.append('/');
+			buffer.append(tagName);
+		}
+		if (buffer.length() == 0)
+			buffer.append(tagName);
+
+		IStructuredDocumentRegion startStructuredDocumentRegion = getStartStructuredDocumentRegion();
+		if (startStructuredDocumentRegion != null) {
+			buffer.append('@');
+			buffer.append(startStructuredDocumentRegion.toString());
+		}
+		IStructuredDocumentRegion endStructuredDocumentRegion = getEndStructuredDocumentRegion();
+		if (endStructuredDocumentRegion != null) {
+			buffer.append('@');
+			buffer.append(endStructuredDocumentRegion.toString());
+		}
+		return buffer.toString();
+	}
+
+	/**
+	 * NOT IMPLEMENTED. Is defined here in preparation for DOM 3.
+	 */
+	public void setIdAttribute(String name, boolean isId) throws DOMException {
+		throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Not supported in this version"); //$NON-NLS-1$
+	}
+
+	/**
+	 * NOT IMPLEMENTED. Is defined here in preparation for DOM 3.
+	 */
+	public void setIdAttributeNS(String namespaceURI, String localName, boolean isId) throws DOMException {
+		throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Not supported in this version"); //$NON-NLS-1$
+	}
+
+	/**
+	 * NOT IMPLEMENTED. Is defined here in preparation for DOM 3.
+	 */
+	public void setIdAttributeNode(Attr idAttr, boolean isId) throws DOMException {
+		throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Not supported in this version"); //$NON-NLS-1$
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/EntityImpl.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/EntityImpl.java
new file mode 100644
index 0000000..fae39ca
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/EntityImpl.java
@@ -0,0 +1,247 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *     Balazs Banfai: Bug 154737 getUserData/setUserData support for Node
+ *     https://bugs.eclipse.org/bugs/show_bug.cgi?id=154737
+ *     David Carver (STAR) - bug 296999 - Inefficient use of new String()
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Entity;
+import org.w3c.dom.Node;
+import org.w3c.dom.UserDataHandler;
+
+/**
+ * EntityImpl class
+ */
+public class EntityImpl extends NodeImpl implements Entity {
+
+	private String name = null;
+	private String notationName = null;
+	private String publicId = null;
+	private String systemId = null;
+
+	/**
+	 * EntityImpl constructor
+	 */
+	protected EntityImpl() {
+		super();
+	}
+
+	/**
+	 * EntityImpl constructor
+	 * 
+	 * @param that
+	 *            EntityImpl
+	 */
+	protected EntityImpl(EntityImpl that) {
+		super(that);
+
+		if (that != null) {
+			this.name = that.name;
+			this.publicId = that.publicId;
+			this.systemId = that.systemId;
+			this.notationName = that.notationName;
+		}
+	}
+
+	/**
+	 * cloneNode method
+	 * 
+	 * @return org.w3c.dom.Node
+	 * @param deep
+	 *            boolean
+	 */
+	public Node cloneNode(boolean deep) {
+		EntityImpl cloned = new EntityImpl(this);
+		notifyUserDataHandlers(UserDataHandler.NODE_CLONED, cloned);
+		return cloned;
+	}
+
+	/**
+	 * <p>
+	 * EXPERIMENTAL! Based on the <a
+	 * href='http://www.w3.org/TR/2001/WD-DOM-Level-3-Core-20010605'>Document
+	 * Object Model (DOM) Level 3 Core Working Draft of 5 June 2001. </a>.
+	 * <p>
+	 * An attribute specifying, as part of the text declaration, the encoding
+	 * of this entity, when it is an external parsed entity. This is
+	 * <code>null</code> otherwise.
+	 * 
+	 * @see DOM Level 3
+	 */
+	public java.lang.String getEncoding() {
+		return null;
+	}
+
+	/**
+	 * getNodeName method
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getNodeName() {
+		if (this.name == null)
+			return NodeImpl.EMPTY_STRING;
+		return this.name;
+	}
+
+	/**
+	 * getNodeType method
+	 * 
+	 * @return short
+	 */
+	public short getNodeType() {
+		return ENTITY_NODE;
+	}
+
+	/**
+	 * getNotationName method
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getNotationName() {
+		return this.notationName;
+	}
+
+	/**
+	 * getPublicId method
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getPublicId() {
+		return this.publicId;
+	}
+
+	/**
+	 * getSystemId method
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getSystemId() {
+		return this.systemId;
+	}
+
+	/**
+	 * <p>
+	 * EXPERIMENTAL! Based on the <a
+	 * href='http://www.w3.org/TR/2001/WD-DOM-Level-3-Core-20010605'>Document
+	 * Object Model (DOM) Level 3 Core Working Draft of 5 June 2001. </a>.
+	 * <p>
+	 * An attribute specifying, as part of the text declaration, the version
+	 * number of this entity, when it is an external parsed entity. This is
+	 * <code>null</code> otherwise.
+	 * 
+	 * @see DOM Level 3
+	 */
+	public java.lang.String getVersion() {
+		return null;
+	}
+
+	/**
+	 * <p>
+	 * EXPERIMENTAL! Based on the <a
+	 * href='http://www.w3.org/TR/2001/WD-DOM-Level-3-Core-20010605'>Document
+	 * Object Model (DOM) Level 3 Core Working Draft of 5 June 2001. </a>.
+	 * <p>
+	 * An attribute specifying, as part of the text declaration, the encoding
+	 * of this entity, when it is an external parsed entity. This is
+	 * <code>null</code> otherwise.
+	 * 
+	 * @see DOM Level 3
+	 */
+	public void setEncoding(java.lang.String encoding) {
+	}
+
+	/**
+	 * setName method
+	 * 
+	 * @param name
+	 *            java.lang.String
+	 */
+	protected void setName(String name) {
+		this.name = name;
+	}
+
+	/**
+	 * setNotationName method
+	 * 
+	 * @param notationName
+	 *            java.lang.String
+	 */
+	public void setNotationName(String notationName) {
+		if (!isDataEditable()) {
+			throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, DOMMessages.NO_MODIFICATION_ALLOWED_ERR);
+		}
+
+		this.notationName = notationName;
+	}
+
+	/**
+	 * setPublicId method
+	 * 
+	 * @param publicId
+	 *            java.lang.String
+	 */
+	public void setPublicId(String publicId) {
+		if (!isDataEditable()) {
+			throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, DOMMessages.NO_MODIFICATION_ALLOWED_ERR);
+		}
+
+		this.publicId = publicId;
+	}
+
+	/**
+	 * setSystemId method
+	 * 
+	 * @param systemId
+	 *            java.lang.String
+	 */
+	public void setSystemId(String systemId) {
+		if (!isDataEditable()) {
+			throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, DOMMessages.NO_MODIFICATION_ALLOWED_ERR);
+		}
+
+		this.systemId = systemId;
+	}
+
+	/**
+	 * <p>
+	 * EXPERIMENTAL! Based on the <a
+	 * href='http://www.w3.org/TR/2001/WD-DOM-Level-3-Core-20010605'>Document
+	 * Object Model (DOM) Level 3 Core Working Draft of 5 June 2001. </a>.
+	 * <p>
+	 * An attribute specifying, as part of the text declaration, the version
+	 * number of this entity, when it is an external parsed entity. This is
+	 * <code>null</code> otherwise.
+	 * 
+	 * @see DOM Level 3
+	 */
+	public void setVersion(java.lang.String version) {
+	}
+
+	public String getInputEncoding() {
+		throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Not implemented in this version"); //$NON-NLS-1$
+	}
+
+	public String getXmlEncoding() {
+		throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Not implemented in this version"); //$NON-NLS-1$
+	}
+
+
+	public String getXmlVersion() {
+		throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Not implemented in this version"); //$NON-NLS-1$
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/EntityReferenceImpl.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/EntityReferenceImpl.java
new file mode 100644
index 0000000..a4edb32
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/EntityReferenceImpl.java
@@ -0,0 +1,95 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 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
+ *     
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *     Balazs Banfai: Bug 154737 getUserData/setUserData support for Node
+ *     https://bugs.eclipse.org/bugs/show_bug.cgi?id=154737
+ *     David Carver (STAR) - bug 296999 - Inefficient use of new String()
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import org.w3c.dom.EntityReference;
+import org.w3c.dom.Node;
+import org.w3c.dom.UserDataHandler;
+
+/**
+ * EntityReference class
+ */
+public class EntityReferenceImpl extends NodeImpl implements EntityReference {
+
+	private String name = null;
+
+	/**
+	 * EntityReferenceImpl constructor
+	 */
+	protected EntityReferenceImpl() {
+		super();
+	}
+
+	/**
+	 * EntityReferenceImpl constructor
+	 * 
+	 * @param that
+	 *            EntityReferenceImpl
+	 */
+	protected EntityReferenceImpl(EntityReferenceImpl that) {
+		super(that);
+
+		if (that != null) {
+			this.name = that.name;
+		}
+	}
+
+	/**
+	 * cloneNode method
+	 * 
+	 * @return org.w3c.dom.Node
+	 * @param deep
+	 *            boolean
+	 */
+	public Node cloneNode(boolean deep) {
+		EntityReferenceImpl cloned = new EntityReferenceImpl(this);
+		notifyUserDataHandlers(UserDataHandler.NODE_CLONED, cloned);
+		return cloned;
+	}
+
+	/**
+	 * getNodeName method
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getNodeName() {
+		if (this.name == null)
+			return NodeImpl.EMPTY_STRING;
+		return this.name;
+	}
+
+	/**
+	 * getNodeType method
+	 * 
+	 * @return short
+	 */
+	public short getNodeType() {
+		return ENTITY_REFERENCE_NODE;
+	}
+
+	/**
+	 * setName method
+	 * 
+	 * @param name
+	 *            java.lang.String
+	 */
+	protected void setName(String name) {
+		this.name = name;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/InvalidCharacterException.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/InvalidCharacterException.java
new file mode 100644
index 0000000..1a3a079
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/InvalidCharacterException.java
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+/**
+ * Thrown an invalid character is specified in : XMLNode#setSource(String)
+ */
+public class InvalidCharacterException extends Exception {
+
+	/**
+	 * Default <code>serialVersionUID</code>
+	 */
+	private static final long serialVersionUID = 1L;
+	private char invalidChar = 0;
+	private int offset = -1;
+
+	/**
+	 */
+	public InvalidCharacterException() {
+		super();
+	}
+
+	/**
+	 */
+	public InvalidCharacterException(String s) {
+		super(s);
+	}
+
+	/**
+	 */
+	public InvalidCharacterException(String s, char c) {
+		super(s);
+		this.invalidChar = c;
+	}
+
+	/**
+	 */
+	public InvalidCharacterException(String s, char c, int offset) {
+		super(s);
+		this.invalidChar = c;
+		this.offset = offset;
+	}
+
+	/**
+	 */
+	public char getInvalidChar() {
+		return this.invalidChar;
+	}
+
+	/**
+	 */
+	public int getOffset() {
+		return this.offset;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/JSPTag.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/JSPTag.java
new file mode 100644
index 0000000..6f2de44
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/JSPTag.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+/**
+ * JSPTag interface
+ */
+public interface JSPTag {
+	static final String COMMENT_CLOSE = "--%>";//$NON-NLS-1$
+	static final String COMMENT_OPEN = "<%--";//$NON-NLS-1$
+	static final String DECLARATION_TOKEN = "!";//$NON-NLS-1$
+	static final String DIRECTIVE_TOKEN = "@";//$NON-NLS-1$
+	static final String EXPRESSION_TOKEN = "=";//$NON-NLS-1$
+	static final String JSP_DECLARATION = "jsp:declaration";//$NON-NLS-1$
+	static final String JSP_DIRECTIVE = "jsp:directive";//$NON-NLS-1$
+	static final String JSP_EXPRESSION = "jsp:expression";//$NON-NLS-1$
+	static final String JSP_ROOT = "jsp:root";//$NON-NLS-1$
+
+	static final String JSP_SCRIPTLET = "jsp:scriptlet";//$NON-NLS-1$
+	static final String TAG_CLOSE = "%>";//$NON-NLS-1$
+	static final String TAG_OPEN = "<%";//$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/ModelParserAdapter.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/ModelParserAdapter.java
new file mode 100644
index 0000000..e61907d
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/ModelParserAdapter.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapter;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+
+/**
+ */
+public interface ModelParserAdapter extends INodeAdapter {
+
+	/**
+	 */
+	public boolean canBeImplicitTag(Element element);
+
+	/**
+	 */
+	public boolean canBeImplicitTag(Element element, Node child);
+
+	/**
+	 */
+	public boolean canContain(Element element, Node child);
+
+	/**
+	 */
+	public Element createCommentElement(Document document, String data, boolean isJSPTag);
+
+	/**
+	 */
+	public Element createImplicitElement(Document document, Node parent, Node child);
+
+	/**
+	 */
+	public String getFindRootName(String tagName);
+
+	/**
+	 */
+	public boolean isEndTag(IDOMElement element);
+
+	boolean isEndTagOmissible(Element element);
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/NodeContainer.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/NodeContainer.java
new file mode 100644
index 0000000..b8f6d66
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/NodeContainer.java
@@ -0,0 +1,534 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     David Carver (STAR) - bug 296999 - Inefficient use of new String()
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentFragment;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+
+/**
+ * NodeContainer class
+ */
+public abstract class NodeContainer extends NodeImpl implements Node, NodeList {
+
+	/**
+	 */
+	private class ChildNodesCache implements NodeList {
+		private Node curChild = null;
+		private int curIndex = -1;
+		private int length = 0;
+
+		ChildNodesCache() {
+			initializeCache();
+		}
+
+		public int getLength() {
+			// atomic
+			return this.length;
+		}
+
+		private void initializeCache() {
+			// note we use the outter objects lockobject
+			// (since we are using their "children".
+			synchronized (lockObject) {
+				for (Node child = firstChild; child != null; child = child.getNextSibling()) {
+					this.length++;
+				}
+			}
+		}
+
+		public Node item(int index) {
+			synchronized (lockObject) {
+				if (this.length == 0)
+					return null;
+				if (index < 0)
+					return null;
+				if (index >= this.length)
+					return null;
+
+				if (this.curIndex < 0) { // first time
+					if (index * 2 >= this.length) { // search from the last
+						this.curIndex = this.length - 1;
+						this.curChild = lastChild;
+					} else { // search from the first
+						this.curIndex = 0;
+						this.curChild = firstChild;
+					}
+				}
+
+				if (index == this.curIndex)
+					return this.curChild;
+
+				if (index > this.curIndex) {
+					while (index > this.curIndex) {
+						this.curIndex++;
+						this.curChild = this.curChild.getNextSibling();
+					}
+				} else { // index < this.curIndex
+					while (index < this.curIndex) {
+						this.curIndex--;
+						this.curChild = this.curChild.getPreviousSibling();
+					}
+				}
+
+				return this.curChild;
+			}
+		}
+	}
+
+	private NodeList childNodesCache = null;
+
+	private boolean fChildEditable = true;
+	NodeImpl firstChild = null;
+	NodeImpl lastChild = null;
+
+	Object lockObject = new byte[0];
+
+	/**
+	 * NodeContainer constructor
+	 */
+	protected NodeContainer() {
+		super();
+	}
+
+	/**
+	 * NodeContainer constructor
+	 * 
+	 * @param that
+	 *            NodeContainer
+	 */
+	protected NodeContainer(NodeContainer that) {
+		super(that);
+	}
+
+	/**
+	 * appendChild method
+	 * 
+	 * @return org.w3c.dom.Node
+	 * @param newChild
+	 *            org.w3c.dom.Node
+	 */
+	public Node appendChild(Node newChild) throws DOMException {
+		return insertBefore(newChild, null);
+	}
+
+	/**
+	 * cloneChildNodes method
+	 * 
+	 * @param container
+	 *            org.w3c.dom.Node
+	 * @param deep
+	 *            boolean
+	 */
+	protected void cloneChildNodes(Node newParent, boolean deep) {
+		if (newParent == null || newParent == this)
+			return;
+		if (!(newParent instanceof NodeContainer))
+			return;
+
+		NodeContainer container = (NodeContainer) newParent;
+		container.removeChildNodes();
+
+		for (Node child = getFirstChild(); child != null; child = child.getNextSibling()) {
+			Node cloned = child.cloneNode(deep);
+			if (cloned != null)
+				container.appendChild(cloned);
+		}
+	}
+
+	/**
+	 * getChildNodes method
+	 * 
+	 * @return org.w3c.dom.NodeList
+	 */
+	public NodeList getChildNodes() {
+		return this;
+	}
+
+	/**
+	 * getFirstChild method
+	 * 
+	 * @return org.w3c.dom.Node
+	 */
+	public Node getFirstChild() {
+		return this.firstChild;
+	}
+
+	/**
+	 * getLastChild method
+	 * 
+	 * @return org.w3c.dom.Node
+	 */
+	public Node getLastChild() {
+		return this.lastChild;
+	}
+
+	/**
+	 * getLength method
+	 * 
+	 * @return int
+	 */
+	public int getLength() {
+		if (this.firstChild == null)
+			return 0;
+		synchronized (lockObject) {
+			if (this.childNodesCache == null)
+				this.childNodesCache = new ChildNodesCache();
+			return this.childNodesCache.getLength();
+		}
+	}
+
+	/**
+	 */
+	public String getSource() {
+		StringBuffer buffer = new StringBuffer();
+
+		IStructuredDocumentRegion startStructuredDocumentRegion = getStartStructuredDocumentRegion();
+		if (startStructuredDocumentRegion != null) {
+			String source = startStructuredDocumentRegion.getText();
+			if (source != null)
+				buffer.append(source);
+		}
+
+		for (NodeImpl child = firstChild; child != null; child = (NodeImpl) child.getNextSibling()) {
+			String source = child.getSource();
+			if (source != null)
+				buffer.append(source);
+		}
+
+		IStructuredDocumentRegion endStructuredDocumentRegion = getEndStructuredDocumentRegion();
+		if (endStructuredDocumentRegion != null) {
+			String source = endStructuredDocumentRegion.getText();
+			if (source != null)
+				buffer.append(source);
+		}
+
+		return buffer.toString();
+	}
+
+	/**
+	 * hasChildNodes method
+	 * 
+	 * @return boolean
+	 */
+	public boolean hasChildNodes() {
+		return (this.firstChild != null);
+	}
+
+	/**
+	 * insertBefore method
+	 * 
+	 * @return org.w3c.dom.Node
+	 * @param newChild
+	 *            org.w3c.dom.Node
+	 * @param refChild
+	 *            org.w3c.dom.Node
+	 */
+	public Node insertBefore(Node newChild, Node refChild) throws DOMException {
+		if (newChild == null)
+			return null; // nothing to do
+		if (refChild != null && refChild.getParentNode() != this) {
+			throw new DOMException(DOMException.NOT_FOUND_ERR, DOMMessages.NOT_FOUND_ERR);
+		}
+		if (!isChildEditable()) {
+			throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, DOMMessages.NO_MODIFICATION_ALLOWED_ERR);
+		}
+		if (newChild == refChild)
+			return newChild; // nothing to do
+		//new child can not be a parent of this, would cause cycle
+		if(isParent(newChild)) {
+			throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, DOMMessages.HIERARCHY_REQUEST_ERR);
+		}
+
+		if (newChild.getNodeType() == DOCUMENT_FRAGMENT_NODE) {
+			// insert child nodes instead
+			for (Node child = newChild.getFirstChild(); child != null; child = newChild.getFirstChild()) {
+				newChild.removeChild(child);
+				insertBefore(child, refChild);
+			}
+			return newChild;
+		}
+		// synchronized in case another thread is getting item, or length
+		synchronized (lockObject) {
+			this.childNodesCache = null; // invalidate child nodes cache
+		}
+
+		NodeImpl child = (NodeImpl) newChild;
+		NodeImpl next = (NodeImpl) refChild;
+		NodeImpl prev = null;
+		Node oldParent = child.getParentNode();
+		if (oldParent != null)
+			oldParent.removeChild(child);
+		if (next == null) {
+			prev = this.lastChild;
+			this.lastChild = child;
+		} else {
+			prev = (NodeImpl) next.getPreviousSibling();
+			next.setPreviousSibling(child);
+		}
+		if (prev == null)
+			this.firstChild = child;
+		else
+			prev.setNextSibling(child);
+		child.setPreviousSibling(prev);
+		child.setNextSibling(next);
+		child.setParentNode(this);
+		// make sure having the same owner document
+		if (child.getOwnerDocument() == null) {
+			if (getNodeType() == DOCUMENT_NODE) {
+				child.setOwnerDocument((Document) this);
+			} else {
+				child.setOwnerDocument(getOwnerDocument());
+			}
+		}
+
+		notifyChildReplaced(child, null);
+
+		return child;
+	}
+
+	public boolean isChildEditable() {
+		if (!fChildEditable) {
+			DOMModelImpl model = (DOMModelImpl) getModel();
+			if (model != null && model.isReparsing()) {
+				return true;
+			}
+		}
+		return fChildEditable;
+	}
+
+	/**
+	 * isContainer method
+	 * 
+	 * @return boolean
+	 */
+	public boolean isContainer() {
+		return true;
+	}
+
+	/**
+	 * item method
+	 * 
+	 * @return org.w3c.dom.Node
+	 * @param index
+	 *            int
+	 */
+	public Node item(int index) {
+		if (this.firstChild == null)
+			return null;
+		synchronized (lockObject) {
+			if (this.childNodesCache == null)
+				this.childNodesCache = new ChildNodesCache();
+			return this.childNodesCache.item(index);
+		}
+	}
+
+	/**
+	 * notifyChildReplaced method
+	 * 
+	 * @param newChild
+	 *            org.w3c.dom.Node
+	 * @param oldChild
+	 *            org.w3c.dom.Node
+	 */
+	protected void notifyChildReplaced(Node newChild, Node oldChild) {
+		DocumentImpl document = (DocumentImpl) getContainerDocument();
+		if (document == null)
+			return;
+
+		syncChildEditableState(newChild);
+
+		DOMModelImpl model = (DOMModelImpl) document.getModel();
+		if (model == null)
+			return;
+		model.childReplaced(this, newChild, oldChild);
+	}
+
+	/**
+	 * removeChild method
+	 * 
+	 * @return org.w3c.dom.Node
+	 * @param oldChild
+	 *            org.w3c.dom.Node
+	 */
+	public Node removeChild(Node oldChild) throws DOMException {
+		if (oldChild == null)
+			return null;
+		if (oldChild.getParentNode() != this) {
+			throw new DOMException(DOMException.NOT_FOUND_ERR, DOMMessages.NOT_FOUND_ERR);
+		}
+
+		if (!isChildEditable()) {
+			throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, DOMMessages.NO_MODIFICATION_ALLOWED_ERR);
+		}
+
+		// synchronized in case another thread is getting item, or length
+		synchronized (lockObject) {
+			this.childNodesCache = null; // invalidate child nodes cache
+		}
+
+		NodeImpl child = (NodeImpl) oldChild;
+		NodeImpl prev = (NodeImpl) child.getPreviousSibling();
+		NodeImpl next = (NodeImpl) child.getNextSibling();
+
+		child.setEditable(true, true); // clear ReadOnly flags
+
+		if (prev == null)
+			this.firstChild = next;
+		else
+			prev.setNextSibling(next);
+		if (next == null)
+			this.lastChild = prev;
+		else
+			next.setPreviousSibling(prev);
+		child.setPreviousSibling(null);
+		child.setNextSibling(null);
+		child.setParentNode(null);
+
+		notifyChildReplaced(null, child);
+
+		return child;
+	}
+
+	/**
+	 * removeChildNodes method
+	 */
+	public void removeChildNodes() {
+		if (!isChildEditable()) {
+			throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, DOMMessages.NO_MODIFICATION_ALLOWED_ERR);
+		}
+
+		Node nextChild = null;
+		for (Node child = getFirstChild(); child != null; child = nextChild) {
+			nextChild = child.getNextSibling();
+			removeChild(child);
+		}
+	}
+
+	/**
+	 * removeChildNodes method
+	 * 
+	 * @return org.w3c.dom.DocumentFragment
+	 * @param firstChild
+	 *            org.w3c.dom.Node
+	 * @param lastChild
+	 *            org.w3c.dom.Node
+	 */
+	public DocumentFragment removeChildNodes(Node firstChild, Node lastChild) {
+		if (!hasChildNodes())
+			return null;
+		if (!isChildEditable()) {
+			throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, DOMMessages.NO_MODIFICATION_ALLOWED_ERR);
+		}
+
+		Document document = null;
+		if (getNodeType() == DOCUMENT_NODE)
+			document = (Document) this;
+		else
+			document = getOwnerDocument();
+		if (document == null)
+			return null;
+		DocumentFragment fragment = document.createDocumentFragment();
+		if (fragment == null)
+			return null;
+
+		if (firstChild == null)
+			firstChild = getFirstChild();
+		if (lastChild == null)
+			lastChild = getLastChild();
+		Node nextChild = null;
+		for (Node child = firstChild; child != null; child = nextChild) {
+			nextChild = child.getNextSibling();
+			removeChild(child);
+			fragment.appendChild(child);
+			if (child == lastChild)
+				break;
+		}
+
+		return fragment;
+	}
+
+	/**
+	 * replaceChild method
+	 * 
+	 * @return org.w3c.dom.Node
+	 * @param newChild
+	 *            org.w3c.dom.Node
+	 * @param oldChild
+	 *            org.w3c.dom.Node
+	 */
+	public Node replaceChild(Node newChild, Node oldChild) throws DOMException {
+		if (!isChildEditable()) {
+			throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, DOMMessages.NO_MODIFICATION_ALLOWED_ERR);
+		}
+
+		if (oldChild == null)
+			return newChild;
+		if (newChild != null)
+			insertBefore(newChild, oldChild);
+		return removeChild(oldChild);
+	}
+
+	public void setChildEditable(boolean editable) {
+		if (fChildEditable == editable) {
+			return;
+		}
+
+		ReadOnlyController roc = ReadOnlyController.getInstance();
+		Node node;
+		if (editable) {
+			for (node = getFirstChild(); node != null; node = node.getNextSibling()) {
+				roc.unlockNode((IDOMNode) node);
+			}
+		} else {
+			for (node = getFirstChild(); node != null; node = node.getNextSibling()) {
+				roc.lockNode((IDOMNode) node);
+			}
+		}
+
+		fChildEditable = editable;
+		notifyEditableChanged();
+	}
+
+	protected void syncChildEditableState(Node child) {
+		ReadOnlyController roc = ReadOnlyController.getInstance();
+		if (fChildEditable) {
+			roc.unlockNode((NodeImpl) child);
+		} else {
+			roc.lockNode((NodeImpl) child);
+		}
+	}
+
+	/**
+	 * <p>Checks to see if the given <code>Node</code> is a parent of <code>this</code> node</p>
+	 * 
+	 * @param possibleParent the possible parent <code>Node</code> of <code>this</code> node
+	 * @return <code>true</code> if <code>possibleParent</code> is the parent of <code>this</code>,
+	 * <code>false</code> otherwise.
+	 */
+	private boolean isParent(Node possibleParent) {
+		Node parent = this.getParentNode();
+		while(parent != null && parent != possibleParent) {
+			parent = parent.getParentNode();
+		}
+
+		return parent == possibleParent;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/NodeImpl.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/NodeImpl.java
new file mode 100644
index 0000000..938deb8
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/NodeImpl.java
@@ -0,0 +1,1139 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *     Balazs Banfai: Bug 154737 getUserData/setUserData support for Node
+ *     https://bugs.eclipse.org/bugs/show_bug.cgi?id=154737
+ *     
+ *     David Carver (STAR) - bug 295127 - implement isSameNode and compareDocumentPosition methods.
+ *                                        Unit Tests covered in wst.xsl XPath 2.0 tests.
+ *     David Carver (STAR) - bug 296999 - Inefficient use of new String()
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import java.io.Serializable;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.eclipse.wst.sse.core.internal.model.FactoryRegistry;
+import org.eclipse.wst.sse.core.internal.provisional.AbstractNotifier;
+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.xml.core.internal.provisional.document.IDOMModel;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentFragment;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+import org.w3c.dom.TypeInfo;
+import org.w3c.dom.UserDataHandler;
+
+/**
+ * NodeImpl class
+ */
+public abstract class NodeImpl extends AbstractNotifier implements Node, IDOMNode {
+	// define one empty nodelist, for repeated use
+	private final static NodeList EMPTY_NODE_LIST = new NodeListImpl();
+	// DocumentPosition
+	//private final static short      DOCUMENT_POSITION_DISCONNECTED = 0x01;
+    private final static short      DOCUMENT_POSITION_PRECEDING    = 0x02;
+	private final static short      DOCUMENT_POSITION_FOLLOWING    = 0x04;
+    //private final static short      DOCUMENT_POSITION_CONTAINS     = 0x08;
+	//private final static short      DOCUMENT_POSITION_CONTAINED_BY = 0x10;
+	private final static short      DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0x20;
+
+
+	private boolean fDataEditable = true;
+	private IStructuredDocumentRegion flatNode = null;
+	private NodeImpl nextSibling = null;
+
+	private DocumentImpl ownerDocument = null;
+	private NodeImpl parentNode = null;
+	private NodeImpl previousSibling = null;
+	// define one empty String constant for repeated use
+	static final String EMPTY_STRING = "";
+	
+	/**
+	 * NodeImpl constructor
+	 */
+	protected NodeImpl() {
+		super();
+	}
+
+	/**
+	 * NodeImpl constructor
+	 * 
+	 * @param that
+	 *            NodeImpl
+	 */
+	protected NodeImpl(NodeImpl that) {
+		if (that != null) {
+			this.ownerDocument = that.ownerDocument;
+		}
+	}
+
+	/**
+	 * appendChild method
+	 * 
+	 * @return org.w3c.dom.Node
+	 * @param newChild
+	 *            org.w3c.dom.Node
+	 */
+	public Node appendChild(Node newChild) throws DOMException {
+		throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, DOMMessages.HIERARCHY_REQUEST_ERR);
+	}
+
+	/**
+	 * contains method
+	 * 
+	 * @return boolean
+	 * @param offset
+	 *            int
+	 */
+	public boolean contains(int offset) {
+		return (offset >= getStartOffset() && offset < getEndOffset());
+	}
+
+	/**
+	 * @param s
+	 * @param tagName
+	 * @return
+	 */
+	protected String createDOMExceptionMessage(short s, String tagName) {
+		String result = null;
+		// TODO: Should localize these messages, and provide /u escaped
+		// version of tagName
+		result = lookupMessage(s) + " " + tagName; //$NON-NLS-1$
+		return result;
+	}
+
+	/**
+	 * getAttributes method
+	 * 
+	 * @return org.w3c.dom.NamedNodeMap
+	 */
+	public NamedNodeMap getAttributes() {
+		return null;
+	}
+
+	/**
+	 */
+	protected String getCharValue(String name) {
+		DocumentImpl document = (DocumentImpl) getOwnerDocument();
+		if (document == null)
+			return null;
+		return document.getCharValue(name);
+	}
+
+	/**
+	 * getChildNodes method
+	 * 
+	 * @return org.w3c.dom.NodeList
+	 */
+	public NodeList getChildNodes() {
+		// As per DOM spec, correct behavior for getChildNodes is to return a
+		// zero length NodeList, not null, when there are no children.
+		// We'll use a common instance of an empty node list, just to prevent
+		// creating a trival object many many times.
+
+		return EMPTY_NODE_LIST;
+	}
+
+	/**
+	 * getCommonAncestor method
+	 * 
+	 * @return org.w3c.dom.Node
+	 * @param node
+	 *            org.w3c.dom.Node
+	 */
+	public Node getCommonAncestor(Node node) {
+		if (node == null)
+			return null;
+
+		for (Node na = node; na != null; na = na.getParentNode()) {
+			for (Node ta = this; ta != null; ta = ta.getParentNode()) {
+				if (ta == na)
+					return ta;
+			}
+		}
+
+		return null; // not found
+	}
+
+	/**
+	 * getContainerDocument method
+	 * 
+	 * @return org.w3c.dom.Document
+	 */
+	public Document getContainerDocument() {
+		Node parent = null;
+		for (Node node = this; node != null; node = parent) {
+			if (node.getNodeType() == Node.DOCUMENT_NODE) {
+				return (Document) node;
+			}
+			/* Break out of a bad hierarchy */
+			if ((parent = node.getParentNode()) == node)
+				break;
+		}
+		return null;
+	}
+
+	/**
+	 * getEndOffset method
+	 * 
+	 * @return int
+	 */
+	public int getEndOffset() {
+		Node node = this;
+		while (node != null) {
+			if (node.getNodeType() == Node.ELEMENT_NODE) {
+				ElementImpl element = (ElementImpl) node;
+				IStructuredDocumentRegion endStructuredDocumentRegion = element.getEndStructuredDocumentRegion();
+				if (endStructuredDocumentRegion != null)
+					return endStructuredDocumentRegion.getEnd();
+			}
+
+			Node last = node.getLastChild();
+			if (last != null) { // dig into the last
+				node = last;
+				continue;
+			}
+
+			IStructuredDocumentRegion lastStructuredDocumentRegion = ((NodeImpl) node).getStructuredDocumentRegion();
+			if (lastStructuredDocumentRegion != null)
+				return lastStructuredDocumentRegion.getEnd();
+
+			Node prev = node.getPreviousSibling();
+			if (prev != null) { // move to the previous
+				node = prev;
+				continue;
+			}
+
+			Node parent = node.getParentNode();
+			node = null;
+			while (parent != null) {
+				if (parent.getNodeType() == Node.ELEMENT_NODE) {
+					ElementImpl element = (ElementImpl) parent;
+					IStructuredDocumentRegion startStructuredDocumentRegion = element.getStartStructuredDocumentRegion();
+					if (startStructuredDocumentRegion != null)
+						return startStructuredDocumentRegion.getEnd();
+				}
+				Node parentPrev = parent.getPreviousSibling();
+				if (parentPrev != null) { // move to the previous
+					node = parentPrev;
+					break;
+				}
+				parent = parent.getParentNode();
+			}
+		}
+		return 0;
+	}
+
+	public IStructuredDocumentRegion getEndStructuredDocumentRegion() {
+		return null;
+	}
+
+	/**
+	 */
+	public FactoryRegistry getFactoryRegistry() {
+		IDOMModel model = getModel();
+		if (model != null) {
+			FactoryRegistry reg = model.getFactoryRegistry();
+			if (reg != null)
+				return reg;
+		}
+		return null;
+	}
+
+	/**
+	 * getFirstChild method
+	 * 
+	 * @return org.w3c.dom.Node
+	 */
+	public Node getFirstChild() {
+		return null;
+	}
+
+	/**
+	 * getFirstStructuredDocumentRegion method
+	 * 
+	 */
+	public IStructuredDocumentRegion getFirstStructuredDocumentRegion() {
+		return StructuredDocumentRegionUtil.getStructuredDocumentRegion(this.flatNode);
+	}
+
+	/**
+	 */
+	public int getIndex() {
+		Node parent = getParentNode();
+		if (parent == null)
+			return -1; // error
+		int index = 0;
+		for (Node child = parent.getFirstChild(); child != null; child = child.getNextSibling()) {
+			if (child == this)
+				return index;
+			index++;
+		}
+		return -1; // error
+	}
+
+	/**
+	 * getLastChild method
+	 * 
+	 * @return org.w3c.dom.Node
+	 */
+	public Node getLastChild() {
+		return null;
+	}
+
+	/**
+	 * getLastStructuredDocumentRegion method
+	 * 
+	 */
+	public IStructuredDocumentRegion getLastStructuredDocumentRegion() {
+		return StructuredDocumentRegionUtil.getStructuredDocumentRegion(this.flatNode);
+	}
+
+	/**
+	 */
+	public String getLocalName() {
+		return null;
+	}
+
+	/**
+	 * the default implementation can just refer to the owning document
+	 */
+	public IDOMModel getModel() {
+		if (this.ownerDocument == null)
+			return null;
+		return this.ownerDocument.getModel();
+	}
+
+	/**
+	 * all but attr return null
+	 */
+	public ITextRegion getNameRegion() {
+		return null;
+	}
+
+	/**
+	 */
+	public String getNamespaceURI() {
+		return null;
+	}
+
+	/**
+	 * getNextSibling method
+	 * 
+	 * @return org.w3c.dom.Node
+	 */
+	public Node getNextSibling() {
+		return this.nextSibling;
+	}
+
+	/**
+	 * getNodeAt method
+	 * 
+	 * @return org.w3c.dom.Node
+	 * @param offset
+	 *            int
+	 */
+	Node getNodeAt(int offset) {
+		IDOMNode parent = this;
+		IDOMNode child = (IDOMNode) getFirstChild();
+		while (child != null) {
+			if (child.getEndOffset() <= offset) {
+				child = (IDOMNode) child.getNextSibling();
+				continue;
+			}
+			if (child.getStartOffset() > offset) {
+				break;
+			}
+
+			IStructuredDocumentRegion startStructuredDocumentRegion = child.getStartStructuredDocumentRegion();
+			if (startStructuredDocumentRegion != null) {
+				if (startStructuredDocumentRegion.getEnd() > offset)
+					return child;
+			}
+
+			// dig more
+			parent = child;
+			child = (IDOMNode) parent.getFirstChild();
+		}
+
+		return parent;
+	}
+
+	/**
+	 * getNodeValue method
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getNodeValue() throws DOMException {
+		return null;
+	}
+
+	/**
+	 * getOwnerDocument method
+	 * 
+	 * @return org.w3c.dom.Document
+	 */
+	public Document getOwnerDocument() {
+		return this.ownerDocument;
+	}
+
+	/**
+	 * getParentNode method
+	 * 
+	 * @return org.w3c.dom.Node
+	 */
+	public Node getParentNode() {
+		return this.parentNode;
+	}
+
+	/**
+	 */
+	public String getPrefix() {
+		return null;
+	}
+
+	/**
+	 * getPreviousSibling method
+	 * 
+	 * @return org.w3c.dom.Node
+	 */
+	public Node getPreviousSibling() {
+		return this.previousSibling;
+	}
+
+	/**
+	 */
+	public String getSource() {
+		if (this.flatNode == null)
+			return NodeImpl.EMPTY_STRING;
+		return this.flatNode.getText();
+	}
+
+	/**
+	 * getStartOffset method
+	 * 
+	 * @return int
+	 */
+	public int getStartOffset() {
+		if (this.flatNode != null)
+			return this.flatNode.getStart();
+		NodeImpl prev = (NodeImpl) getPreviousSibling();
+		if (prev != null)
+			return prev.getEndOffset();
+		Node parent = getParentNode();
+		if (parent != null && parent.getNodeType() == Node.ELEMENT_NODE) {
+			ElementImpl element = (ElementImpl) parent;
+			if (element.hasStartTag())
+				return element.getStartEndOffset();
+			return element.getStartOffset();
+		}
+		// final fallback to look into first child
+		NodeImpl child = (NodeImpl) getFirstChild();
+		while (child != null) {
+			IStructuredDocumentRegion childStructuredDocumentRegion = child.getStructuredDocumentRegion();
+			if (childStructuredDocumentRegion != null)
+				return childStructuredDocumentRegion.getStart();
+			child = (NodeImpl) child.getFirstChild();
+		}
+		return 0;
+	}
+
+	public IStructuredDocumentRegion getStartStructuredDocumentRegion() {
+		return getFirstStructuredDocumentRegion();
+	}
+
+	/**
+	 * Every node (indirectly) knows its structuredDocument
+	 */
+	public IStructuredDocument getStructuredDocument() {
+		return getModel().getStructuredDocument();
+	}
+
+	/**
+	 */
+	IStructuredDocumentRegion getStructuredDocumentRegion() {
+		return this.flatNode;
+	}
+
+	/**
+	 * all but attr return null
+	 */
+	public ITextRegion getValueRegion() {
+		return null;
+	}
+
+	/**
+	 */
+	public String getValueSource() {
+		return getNodeValue();
+	}
+
+	/**
+	 */
+	public boolean hasAttributes() {
+		return false;
+	}
+
+	/**
+	 * hasChildNodes method
+	 * 
+	 * @return boolean
+	 */
+	public boolean hasChildNodes() {
+		return false;
+	}
+
+	/**
+	 * hasProperties method
+	 * 
+	 * @return boolean
+	 */
+	public boolean hasProperties() {
+		return false;
+	}
+
+	/**
+	 * insertBefore method
+	 * 
+	 * @return org.w3c.dom.Node
+	 * @param newChild
+	 *            org.w3c.dom.Node
+	 * @param refChild
+	 *            org.w3c.dom.Node
+	 */
+	public Node insertBefore(Node newChild, Node refChild) throws DOMException {
+		throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, DOMMessages.HIERARCHY_REQUEST_ERR);
+	}
+
+	public boolean isChildEditable() {
+		return false;
+	}
+
+	/**
+	 */
+	public boolean isClosed() {
+		return true;
+	}
+
+	/**
+	 * isContainer method
+	 * 
+	 * @return boolean
+	 */
+	public boolean isContainer() {
+		return false;
+	}
+
+	public boolean isDataEditable() {
+		if (!fDataEditable) {
+			DOMModelImpl model = (DOMModelImpl) getModel();
+			if (model != null && model.isReparsing()) {
+				return true;
+			}
+		}
+		return fDataEditable;
+	}
+
+	/**
+	 */
+	public boolean isSupported(String feature, String version) {
+		if (this.ownerDocument == null)
+			return false;
+		DOMImplementation impl = this.ownerDocument.getImplementation();
+		if (impl == null)
+			return false;
+		return impl.hasFeature(feature, version);
+	}
+
+	/**
+	 * @param s
+	 * @return
+	 */
+	private String lookupMessage(short s) {
+		// TODO: make localized version
+		String result = null;
+		switch (s) {
+			case DOMException.DOMSTRING_SIZE_ERR :
+				result = DOMMessages.DOMSTRING_SIZE_ERR;
+				break;
+			case DOMException.HIERARCHY_REQUEST_ERR :
+				result = DOMMessages.HIERARCHY_REQUEST_ERR;
+				break;
+			case DOMException.INDEX_SIZE_ERR :
+				result = DOMMessages.INDEX_SIZE_ERR;
+				break;
+			case DOMException.INUSE_ATTRIBUTE_ERR :
+				result = DOMMessages.INUSE_ATTRIBUTE_ERR;
+				break;
+			case DOMException.INVALID_ACCESS_ERR :
+				result = DOMMessages.INVALID_ACCESS_ERR;
+				break;
+			case DOMException.INVALID_CHARACTER_ERR :
+				result = DOMMessages.INVALID_CHARACTER_ERR;
+				break;
+			case DOMException.INVALID_MODIFICATION_ERR :
+				result = DOMMessages.INVALID_MODIFICATION_ERR;
+				break;
+			case DOMException.INVALID_STATE_ERR :
+				result = DOMMessages.INVALID_STATE_ERR;
+				break;
+			case DOMException.NAMESPACE_ERR :
+				result = DOMMessages.NAMESPACE_ERR;
+				break;
+			case DOMException.NO_DATA_ALLOWED_ERR :
+				result = DOMMessages.NO_DATA_ALLOWED_ERR;
+				break;
+			case DOMException.NO_MODIFICATION_ALLOWED_ERR :
+				result = DOMMessages.NO_MODIFICATION_ALLOWED_ERR;
+				break;
+			case DOMException.NOT_FOUND_ERR :
+				result = DOMMessages.NOT_FOUND_ERR;
+				break;
+			case DOMException.NOT_SUPPORTED_ERR :
+				result = DOMMessages.NOT_SUPPORTED_ERR;
+				break;
+			case DOMException.SYNTAX_ERR :
+				result = DOMMessages.SYNTAX_ERR;
+				break;
+			case 17:// DOMException.TYPE_MISMATCH_ERR :
+				result = DOMMessages.TYPE_MISMATCH_ERR;
+				break;
+			case 16:// DOMException.VALIDATION_ERR :
+				result = DOMMessages.VALIDATION_ERR;
+				break;
+			case DOMException.WRONG_DOCUMENT_ERR :
+				result = DOMMessages.WRONG_DOCUMENT_ERR;
+				break;
+			default :
+				result = NodeImpl.EMPTY_STRING;
+				break;
+		}
+		return result;
+	}
+
+	/**
+	 * normalize method
+	 */
+	public void normalize() {
+		TextImpl prevText = null;
+		for (Node child = getFirstChild(); child != null; child = child.getNextSibling()) {
+			switch (child.getNodeType()) {
+				case TEXT_NODE : {
+					if (prevText == null) {
+						prevText = (TextImpl) child;
+						break;
+					}
+					Text text = (Text) child;
+					removeChild(text);
+					prevText.appendText(text);
+					child = prevText;
+					break;
+				}
+				case ELEMENT_NODE : {
+					Element element = (Element) child;
+					element.normalize();
+					prevText = null;
+					break;
+				}
+				default :
+					prevText = null;
+					break;
+			}
+		}
+	}
+
+	protected void notifyEditableChanged() {
+		DocumentImpl document = (DocumentImpl) getContainerDocument();
+		if (document == null)
+			return;
+		DOMModelImpl model = (DOMModelImpl) document.getModel();
+		if (model == null)
+			return;
+		model.editableChanged(this);
+	}
+
+	/**
+	 * notifyValueChanged method
+	 */
+	protected void notifyValueChanged() {
+		DocumentImpl document = (DocumentImpl) getContainerDocument();
+		if (document == null)
+			return;
+
+		syncDataEditableState();
+
+		DOMModelImpl model = (DOMModelImpl) document.getModel();
+		if (model == null)
+			return;
+		model.valueChanged(this);
+	}
+
+	/**
+	 * removeChild method
+	 * 
+	 * @return org.w3c.dom.Node
+	 * @param oldChild
+	 *            org.w3c.dom.Node
+	 */
+	public Node removeChild(Node oldChild) throws DOMException {
+		throw new DOMException(DOMException.NOT_FOUND_ERR, DOMMessages.NOT_FOUND_ERR);
+	}
+
+	/**
+	 * removeChildNodes method
+	 */
+	public void removeChildNodes() {
+	}
+
+	/**
+	 * removeChildNodes method
+	 * 
+	 * @return org.w3c.dom.DocumentFragment
+	 * @param firstChild
+	 *            org.w3c.dom.Node
+	 * @param lastChild
+	 *            org.w3c.dom.Node
+	 */
+	public DocumentFragment removeChildNodes(Node firstChild, Node lastChild) {
+		return null;
+	}
+
+	/**
+	 * replaceChild method
+	 * 
+	 * @return org.w3c.dom.Node
+	 * @param newChild
+	 *            org.w3c.dom.Node
+	 * @param oldChild
+	 *            org.w3c.dom.Node
+	 */
+	public Node replaceChild(Node newChild, Node oldChild) throws DOMException {
+		throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, DOMMessages.HIERARCHY_REQUEST_ERR);
+	}
+
+	/**
+	 * Resets children values from IStructuredDocumentRegion.
+	 */
+	void resetStructuredDocumentRegions() {
+		for (NodeImpl child = (NodeImpl) getFirstChild(); child != null; child = (NodeImpl) child.getNextSibling()) {
+			child.resetStructuredDocumentRegions();
+		}
+		this.flatNode = null;
+	}
+
+	public void setChildEditable(boolean editable) {
+		// nop
+	}
+
+	public void setDataEditable(boolean editable) {
+		if (fDataEditable == editable) {
+			return;
+		}
+
+		ReadOnlyController roc = ReadOnlyController.getInstance();
+		if (editable) {
+			roc.unlockData(this);
+		}
+		else {
+			roc.lockData(this);
+		}
+
+		fDataEditable = editable;
+
+		notifyEditableChanged();
+	}
+
+	public void setEditable(boolean editable, boolean deep) {
+		if (deep) {
+			IDOMNode node = (IDOMNode) getFirstChild();
+			while (node != null) {
+				node.setEditable(editable, deep);
+				node = (IDOMNode) node.getNextSibling();
+			}
+		}
+		setChildEditable(editable);
+		setDataEditable(editable);
+	}
+
+	/**
+	 * setNextSibling method
+	 * 
+	 * @param nextSibling
+	 *            org.w3c.dom.Node
+	 */
+	protected void setNextSibling(Node nextSibling) {
+		this.nextSibling = (NodeImpl) nextSibling;
+	}
+
+	/**
+	 * setNodeValue method
+	 * 
+	 * @param nodeValue
+	 *            java.lang.String
+	 */
+	public void setNodeValue(String nodeValue) throws DOMException {
+	}
+
+	/**
+	 * setOwnerDocument method
+	 * 
+	 * @param ownerDocument
+	 *            org.w3c.dom.Document
+	 */
+	protected void setOwnerDocument(Document ownerDocument) {
+		this.ownerDocument = (DocumentImpl) ownerDocument;
+	}
+
+	/**
+	 */
+	protected void setOwnerDocument(Document ownerDocument, boolean deep) {
+		this.ownerDocument = (DocumentImpl) ownerDocument;
+
+		if (deep) {
+			for (NodeImpl child = (NodeImpl) getFirstChild(); child != null; child = (NodeImpl) child.getNextSibling()) {
+				child.setOwnerDocument(ownerDocument, deep);
+			}
+		}
+	}
+
+	/**
+	 * setParentNode method
+	 * 
+	 * @param parentNode
+	 *            org.w3c.dom.Node
+	 */
+	protected void setParentNode(Node parentNode) {
+		this.parentNode = (NodeImpl) parentNode;
+	}
+
+	/**
+	 */
+	public void setPrefix(String prefix) throws DOMException {
+	}
+
+	/**
+	 * setPreviousSibling method
+	 * 
+	 * @param previousSibling
+	 *            org.w3c.dom.Node
+	 */
+	protected void setPreviousSibling(Node previousSibling) {
+		this.previousSibling = (NodeImpl) previousSibling;
+	}
+
+	/**
+	 */
+	public void setSource(String source) throws InvalidCharacterException {
+		// not supported
+	}
+
+	/**
+	 */
+	void setStructuredDocumentRegion(IStructuredDocumentRegion flatNode) {
+		this.flatNode = flatNode;
+	}
+
+	/**
+	 */
+	public void setValueSource(String source) {
+		setNodeValue(source);
+	}
+
+	protected void syncDataEditableState() {
+		ReadOnlyController roc = ReadOnlyController.getInstance();
+		if (fDataEditable) {
+			roc.unlockData(this);
+		}
+		else {
+			roc.lockData(this);
+		}
+	}
+
+	/**
+	 * toString method
+	 * 
+	 * @return java.lang.String
+	 */
+	public String toString() {
+		return getNodeName();
+	}
+
+	public int getLength() {
+		int result = -1;
+		int start = getStartOffset();
+		if (start >= 0) {
+			int end = getEndOffset();
+			if (end >= 0) {
+				result = end - start;
+				if (result < -1) {
+					result = -1;
+				}
+			}
+		}
+		return result;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.w3c.dom.Node#compareDocumentPosition(org.w3c.dom.Node)
+	 */
+	public short compareDocumentPosition(Node other) throws DOMException {
+		if (!(other instanceof IDOMNode))
+			throw new DOMException(DOMException.NOT_SUPPORTED_ERR, DOMMessages.NOT_SUPPORTED_ERR);
+
+		int nodeStart = this.getStartOffset();
+		int otherStart = ((IDOMNode) other).getStartOffset();
+
+		if (otherStart > nodeStart) {
+			return DOCUMENT_POSITION_FOLLOWING;
+		}
+		else if (otherStart < nodeStart) {
+			return DOCUMENT_POSITION_PRECEDING;
+		}
+		return DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC;
+	}
+
+	/**
+	 * NOT IMPLEMENTED, is defined here in preparation of DOM Level 3
+	 */
+	public String getBaseURI() {
+		throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Not implemented in this version."); //$NON-NLS-1$
+	}
+
+	/**
+	 * NOT IMPLEMENTED, is defined here in preparation of DOM Level 3
+	 */
+	public Object getFeature(String feature, String version) {
+		throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Not implemented in this version."); //$NON-NLS-1$
+	}
+
+	/**
+	 * NOT IMPLEMENTED, is defined here in preparation of DOM Level 3
+	 */
+	public String getTextContent() throws DOMException {
+		throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Not implemented in this version."); //$NON-NLS-1$
+	}
+
+	/**
+	 * NOT IMPLEMENTED, is defined here in preparation of DOM Level 3
+	 */
+	public boolean isDefaultNamespace(String namespaceURI) {
+		throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Not implemented in this version."); //$NON-NLS-1$
+	}
+
+	/* (non-Javadoc)
+	 * @see org.w3c.dom.Node#isEqualNode(org.w3c.dom.Node)
+	 */
+	public boolean isEqualNode(Node arg) {
+		return this.equals(arg);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.w3c.dom.Node#isSameNode(org.w3c.dom.Node)
+	 */
+	public boolean isSameNode(Node other) {
+		return this == other;
+	}
+
+	/**
+	 * NOT IMPLEMENTED, is defined here in preparation of DOM Level 3
+	 */
+	public String lookupNamespaceURI(String prefix) {
+		throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Not implemented in this version."); //$NON-NLS-1$
+	}
+
+	/**
+	 * NOT IMPLEMENTED, is defined here in preparation of DOM Level 3
+	 */
+	public String lookupPrefix(String namespaceURI) {
+		throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Not implemented in this version."); //$NON-NLS-1$
+	}
+
+	/**
+	 * NOT IMPLEMENTED, is defined here in preparation of DOM Level 3
+	 */
+	public void setTextContent(String textContent) throws DOMException {
+		throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Not implemented in this version."); //$NON-NLS-1$
+	}
+
+	/**
+	 * NOT IMPLEMENTED, is defined here in preparation of DOM Level 3
+	 */
+	public TypeInfo getSchemaTypeInfo() {
+		throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Not implemented in this version."); //$NON-NLS-1$
+	}
+
+	/**
+	 * NOT IMPLEMENTED, is defined here in preparation of DOM Level 3
+	 */
+	public boolean isId() {
+		throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Not implemented in this version."); //$NON-NLS-1$
+	}
+	
+	/**
+	 * Retrieves the object for a node associated to a key.
+	 * 
+	 * @param key The key associated with the object.
+	 * @return object The object for this node, associated with the key passed
+	 * or null if there was none set.
+	 *
+	 * @since DOM Level 3
+	 */
+	public Object getUserData(String key) {
+		
+		if (key==null) return null;
+		Map userDataTable = UserData.getInstance().getUserDataTable(this);
+		if (userDataTable!=null) {
+			UserDataAndHandler userDataAndHandler = (UserDataAndHandler) userDataTable.get(key);
+			if (userDataAndHandler!=null) {
+				return userDataAndHandler.getData();
+			} 
+		}
+		return null;	
+	}
+	
+	/**
+	 * Sets the user data and handler for a key
+	 * 
+	 * @param key The key associated with the object.
+	 * @param object The object for this node, associated with the key passed.
+	 * Null passed removes the existing association to the key.
+	 * @param handler UserDataHandler for the userdata associated with this key
+	 * @return Object The previous userdata object if set, null if it was none.  
+	 * 
+	 * @since DOM Level 3
+	 */
+	public Object setUserData(String key, Object data, UserDataHandler handler) {
+
+		UserDataAndHandler previousDataAndHandler=null;
+		
+		//return immediately for null keys
+		if (key ==null) return null;
+		Map userDataTable = UserData.getInstance().getUserDataTable(this);
+		//remove association for the key if data is null
+		if (data==null) {
+			if (userDataTable==null) return null;
+			
+			//see if there is a previous value set
+			previousDataAndHandler = (UserDataAndHandler) userDataTable.get(key);
+			if (previousDataAndHandler!=null) {
+				userDataTable.remove(key);
+				return previousDataAndHandler.getData();
+			}
+			//there is no previous value found
+			return null;
+		}
+		
+		//if data passed is not null
+		//the first data in the hashtable
+		if (userDataTable==null) {
+			userDataTable=new Hashtable();
+			UserDataAndHandler userDataAndHandler=new UserDataAndHandler(data,handler);
+			userDataTable.put(key,userDataAndHandler);
+			return null;
+			//there is already data in the hashtable
+		} else {
+			UserDataAndHandler userDataAndHandler=new UserDataAndHandler(data,handler);
+			previousDataAndHandler=(UserDataAndHandler) userDataTable.put(key,userDataAndHandler);
+			
+			//if we replace a value
+			if (previousDataAndHandler!=null)
+				return previousDataAndHandler.getData();
+			else {
+				return null;
+			}
+		}
+	}
+	
+	/**
+	 * Notifies the UserDataHandlers of the node.
+	 * 
+	 * @param operation
+	 * @param destination
+	 */
+	protected void notifyUserDataHandlers(short operation, Node destination) {
+		
+		if (operation!=UserDataHandler.NODE_ADOPTED 
+				& operation!=UserDataHandler.NODE_CLONED
+				& operation!=UserDataHandler.NODE_DELETED
+				& operation!=UserDataHandler.NODE_IMPORTED
+				& operation!=UserDataHandler.NODE_RENAMED)
+			return; 
+		Map userDataTable = UserData.getInstance().getUserDataTable(this);	
+		if (userDataTable!=null) {
+			Iterator entries =userDataTable.entrySet().iterator();
+			while (entries.hasNext()) {
+				Map.Entry entry = (Map.Entry) entries.next();
+				String key = entry.getKey().toString(); //should always be a string
+				UserDataAndHandler dataAndHandler = (UserDataAndHandler) entry.getValue();
+				if (dataAndHandler!=null) {
+					UserDataHandler dataHandler=dataAndHandler.getHandler();
+					if (dataHandler!=null) {
+						dataHandler.handle(operation, key, dataAndHandler.getData(), this, destination);
+					}
+				}
+			}
+		}
+	}
+	
+	/**
+	 * 
+	 * Class for user data and UserDataHandler
+	 */
+	protected static class UserDataAndHandler implements Serializable {
+
+		/**
+		 * Generated Serial ID
+		 */
+		private static final long serialVersionUID = 4860521237315444841L;
+		/**
+		 * Generated serialization version
+		 */
+		
+		private Object data;
+		private UserDataHandler handler;
+		
+		public UserDataAndHandler(Object data, UserDataHandler handler)
+		{
+			this.data=data;
+			this.handler=handler;
+		}
+
+		public Object getData() {
+			return data;
+		}
+
+		public void setData(Object data) {
+			this.data = data;
+		}
+
+		public UserDataHandler getHandler() {
+			return handler;
+		}
+
+		public void setHandler(UserDataHandler handler) {
+			this.handler = handler;
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/NodeIteratorImpl.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/NodeIteratorImpl.java
new file mode 100644
index 0000000..c4a278b
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/NodeIteratorImpl.java
@@ -0,0 +1,257 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Node;
+import org.w3c.dom.traversal.NodeFilter;
+import org.w3c.dom.traversal.NodeIterator;
+
+/**
+ * NodeIteratorImpl class
+ */
+public class NodeIteratorImpl implements NodeIterator {
+	private NodeFilter filter = null;
+	private Node nextNode = null;
+
+	private Node rootNode = null;
+	private int whatToShow = NodeFilter.SHOW_ALL;
+
+	/**
+	 * NodeIteratorImpl constructor
+	 * 
+	 * @param rootNode
+	 *            org.w3c.dom.Node
+	 */
+	NodeIteratorImpl(Node rootNode, int whatToShow, NodeFilter filter) {
+		this.rootNode = rootNode;
+		this.nextNode = rootNode;
+		this.whatToShow = whatToShow;
+		this.filter = filter;
+	}
+
+	/**
+	 */
+	private final boolean acceptNode(Node node) {
+		if (this.whatToShow != NodeFilter.SHOW_ALL) {
+			if (node == null)
+				return false;
+			short nodeType = node.getNodeType();
+			switch (this.whatToShow) {
+				case NodeFilter.SHOW_ELEMENT :
+					if (nodeType != Node.ELEMENT_NODE)
+						return false;
+					break;
+				case NodeFilter.SHOW_ATTRIBUTE :
+					if (nodeType != Node.ATTRIBUTE_NODE)
+						return false;
+					break;
+				case NodeFilter.SHOW_TEXT :
+					if (nodeType != Node.TEXT_NODE)
+						return false;
+					break;
+				case NodeFilter.SHOW_CDATA_SECTION :
+					if (nodeType != Node.CDATA_SECTION_NODE)
+						return false;
+					break;
+				case NodeFilter.SHOW_ENTITY_REFERENCE :
+					if (nodeType != Node.ENTITY_REFERENCE_NODE)
+						return false;
+					break;
+				case NodeFilter.SHOW_ENTITY :
+					if (nodeType != Node.ENTITY_NODE)
+						return false;
+					break;
+				case NodeFilter.SHOW_PROCESSING_INSTRUCTION :
+					if (nodeType != Node.PROCESSING_INSTRUCTION_NODE)
+						return false;
+					break;
+				case NodeFilter.SHOW_COMMENT :
+					if (nodeType != Node.COMMENT_NODE)
+						return false;
+					break;
+				case NodeFilter.SHOW_DOCUMENT :
+					if (nodeType != Node.DOCUMENT_NODE)
+						return false;
+					break;
+				case NodeFilter.SHOW_DOCUMENT_TYPE :
+					if (nodeType != Node.DOCUMENT_TYPE_NODE)
+						return false;
+					break;
+				case NodeFilter.SHOW_DOCUMENT_FRAGMENT :
+					if (nodeType != Node.DOCUMENT_FRAGMENT_NODE)
+						return false;
+					break;
+				case NodeFilter.SHOW_NOTATION :
+					if (nodeType != Node.NOTATION_NODE)
+						return false;
+					break;
+				default :
+					return false;
+			}
+		}
+		if (this.filter != null) {
+			return (this.filter.acceptNode(node) == NodeFilter.FILTER_ACCEPT);
+		}
+		return true;
+	}
+
+	/**
+	 * Detaches the <code>NodeIterator</code> from the set which it iterated
+	 * over, releasing any computational resources and placing the iterator in
+	 * the INVALID state. After <code>detach</code> has been invoked, calls
+	 * to <code>nextNode</code> or <code>previousNode</code> will raise
+	 * the exception INVALID_STATE_ERR.
+	 */
+	public void detach() {
+		this.rootNode = null;
+		this.nextNode = null;
+		this.filter = null;
+	}
+
+	/**
+	 * The value of this flag determines whether the children of entity
+	 * reference nodes are visible to the iterator. If false, they and their
+	 * descendants will be rejected. Note that this rejection takes precedence
+	 * over <code>whatToShow</code> and the filter. Also note that this is
+	 * currently the only situation where <code>NodeIterators</code> may
+	 * reject a complete subtree rather than skipping individual nodes. <br>
+	 * <br>
+	 * To produce a view of the document that has entity references expanded
+	 * and does not expose the entity reference node itself, use the
+	 * <code>whatToShow</code> flags to hide the entity reference node and
+	 * set <code>expandEntityReferences</code> to true when creating the
+	 * iterator. To produce a view of the document that has entity reference
+	 * nodes but no entity expansion, use the <code>whatToShow</code> flags
+	 * to show the entity reference node and set
+	 * <code>expandEntityReferences</code> to false.
+	 */
+	public boolean getExpandEntityReferences() {
+		// not supported
+		return false;
+	}
+
+	/**
+	 * The <code>NodeFilter</code> used to screen nodes.
+	 */
+	public NodeFilter getFilter() {
+		return this.filter;
+	}
+
+	/**
+	 */
+	private final Node getNextNode() {
+		if (this.nextNode == null)
+			return null;
+		Node oldNext = this.nextNode;
+		Node child = this.nextNode.getFirstChild();
+		if (child != null) {
+			this.nextNode = child;
+			return oldNext;
+		}
+		for (Node node = this.nextNode; node != null && node != this.rootNode; node = node.getParentNode()) {
+			Node next = node.getNextSibling();
+			if (next != null) {
+				this.nextNode = next;
+				return oldNext;
+			}
+		}
+		this.nextNode = null;
+		return oldNext;
+	}
+
+	/**
+	 */
+	private final Node getPreviousNode() {
+		if (this.nextNode == this.rootNode)
+			return null;
+		Node prev = null;
+		if (this.nextNode == null) {
+			prev = this.rootNode; // never null
+		} else {
+			prev = this.nextNode.getPreviousSibling();
+			if (prev == null) {
+				this.nextNode = this.nextNode.getParentNode();
+				return this.nextNode;
+			}
+		}
+		Node last = prev.getLastChild();
+		while (last != null) {
+			prev = last;
+			last = prev.getLastChild();
+		}
+		this.nextNode = prev;
+		return this.nextNode;
+	}
+
+	/**
+	 * The root node of the <code>NodeIterator</code>, as specified when it
+	 * was created.
+	 */
+	public Node getRoot() {
+		return this.rootNode;
+	}
+
+	/**
+	 * This attribute determines which node types are presented via the
+	 * iterator. The available set of constants is defined in the
+	 * <code>NodeFilter</code> interface. Nodes not accepted by
+	 * <code>whatToShow</code> will be skipped, but their children may still
+	 * be considered. Note that this skip takes precedence over the filter, if
+	 * any.
+	 */
+	public int getWhatToShow() {
+		return this.whatToShow;
+	}
+
+	/**
+	 * Returns the next node in the set and advances the position of the
+	 * iterator in the set. After a <code>NodeIterator</code> is created,
+	 * the first call to <code>nextNode()</code> returns the first node in
+	 * the set.
+	 * 
+	 * @return The next <code>Node</code> in the set being iterated over, or
+	 *         <code>null</code> if there are no more members in that set.
+	 * @exception DOMException
+	 *                INVALID_STATE_ERR: Raised if this method is called after
+	 *                the <code>detach</code> method was invoked.
+	 */
+	public Node nextNode() throws DOMException {
+		for (Node node = getNextNode(); node != null; node = getNextNode()) {
+			if (acceptNode(node))
+				return node;
+		}
+		return null;
+	}
+
+	/**
+	 * Returns the previous node in the set and moves the position of the
+	 * <code>NodeIterator</code> backwards in the set.
+	 * 
+	 * @return The previous <code>Node</code> in the set being iterated
+	 *         over, or <code>null</code> if there are no more members in
+	 *         that set.
+	 * @exception DOMException
+	 *                INVALID_STATE_ERR: Raised if this method is called after
+	 *                the <code>detach</code> method was invoked.
+	 */
+	public Node previousNode() throws DOMException {
+		for (Node node = getPreviousNode(); node != null; node = getPreviousNode()) {
+			if (acceptNode(node))
+				return node;
+		}
+		return null;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/NodeListImpl.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/NodeListImpl.java
new file mode 100644
index 0000000..a620f32
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/NodeListImpl.java
@@ -0,0 +1,157 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2009 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * An array-backed NodeList, used to keep the array size down
+ */
+public class NodeListImpl implements NodeList {
+
+	private Object fLockObject = new byte[0];
+	private final static int growthConstant = 2;
+	private Node[] fNodes = null;
+	private int fNodeCount = 0;
+
+	/**
+	 * NodeListImpl constructor
+	 */
+	public NodeListImpl() {
+		super();
+	}
+
+	protected NodeListImpl(NodeListImpl list) {
+		super();
+		fNodeCount = list.fNodeCount;
+		fNodes = list.fNodes;
+	}
+
+	/**
+	 * appendNode method
+	 * 
+	 * @return org.w3c.dom.Node
+	 * @param node
+	 *            org.w3c.dom.Node
+	 */
+	protected Node appendNode(Node node) {
+		if (node == null)
+			return null;
+		synchronized (fLockObject) {
+			ensureCapacity(fNodeCount + 1);
+			fNodes[fNodeCount++] = node;
+		}
+		return node;
+	}
+
+	/**
+	 * Grow the node array to at least the given size while keeping the
+	 * contents the same
+	 * 
+	 * @param needed
+	 */
+	private void ensureCapacity(int needed) {
+		if (fNodes == null) {
+			// first time
+			fNodes = new Node[needed];
+			return;
+		}
+		int oldLength = fNodes.length;
+		if (oldLength < needed) {
+			Node[] oldNodes = fNodes;
+			Node[] newNodes = new Node[needed + growthConstant];
+			System.arraycopy(oldNodes, 0, newNodes, 0, fNodeCount);
+			fNodes = newNodes;
+		}
+	}
+
+	/* (non-Javadoc)
+	 * @see org.w3c.dom.NodeList#getLength()
+	 */
+	public int getLength() {
+		return fNodeCount;
+	}
+	
+	protected final Node[] getNodes() {
+		return fNodes;
+	}
+
+	/**
+	 */
+	protected Node insertNode(Node node, int index) {
+		if (node == null)
+			return null;
+		synchronized (fLockObject) {
+			if (fNodes == null) {
+				// first time, ignore index
+				fNodes = new Node[1];
+				fNodes[fNodeCount++] = node;
+				return node;
+			}
+
+			// gracefully handle out of bounds
+			if (index < 0 || index > fNodeCount + 1)
+				return appendNode(node);
+
+			/*
+			 * Grow a new Node array, copying the old contents around the new
+			 * Node
+			 */
+			Node[] newNodes = new Node[fNodeCount + growthConstant];
+			System.arraycopy(fNodes, 0, newNodes, 0, index);
+			newNodes[index] = node;
+			System.arraycopy(fNodes, index, newNodes, index + 1, fNodeCount - index);
+			fNodes = newNodes;
+			fNodeCount++;
+		}
+		return node;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.w3c.dom.NodeList#item(int)
+	 */
+	public Node item(int index) {
+		if (index < 0 || index >= fNodeCount)
+			return null; // invalid parameter
+		return fNodes[index];
+	}
+
+	/**
+	 * removeNode method
+	 * 
+	 * @return org.w3c.dom.Node
+	 * @param index
+	 *            int
+	 */
+	protected Node removeNode(int index) {
+		if (this.fNodes == null)
+			return null; // no node
+
+		synchronized (fLockObject) {
+			if (index < 0 || index >= fNodeCount)
+				return null; // invalid parameter
+
+			Node removed = fNodes[index];
+			Node[] newNodes = new Node[fNodeCount - 1];
+			// copy around node being removed
+			System.arraycopy(fNodes, 0, newNodes, 0, index);
+			System.arraycopy(fNodes, index + 1, newNodes, index, fNodeCount - index - 1);
+			fNodes = newNodes;
+			fNodeCount--;
+			return removed;
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/NotationImpl.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/NotationImpl.java
new file mode 100644
index 0000000..186eea2
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/NotationImpl.java
@@ -0,0 +1,144 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *     Balazs Banfai: Bug 154737 getUserData/setUserData support for Node
+ *     https://bugs.eclipse.org/bugs/show_bug.cgi?id=154737
+ *     David Carver (STAR) - bug 296999 - Inefficient use of new String()
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Node;
+import org.w3c.dom.Notation;
+import org.w3c.dom.UserDataHandler;
+
+/**
+ * NotationImpl class
+ */
+public class NotationImpl extends NodeImpl implements Notation {
+
+	private String name = null;
+	private String publicId = null;
+	private String systemId = null;
+
+	/**
+	 * NotationImpl constructor
+	 */
+	protected NotationImpl() {
+		super();
+	}
+
+	/**
+	 * NotationImpl constructor
+	 * 
+	 * @param that
+	 *            NotationImpl
+	 */
+	protected NotationImpl(NotationImpl that) {
+		super(that);
+
+		if (that != null) {
+			this.name = that.name;
+			this.publicId = that.publicId;
+			this.systemId = that.systemId;
+		}
+	}
+
+	/**
+	 * cloneNode method
+	 * 
+	 * @return org.w3c.dom.Node
+	 * @param deep
+	 *            boolean
+	 */
+	public Node cloneNode(boolean deep) {
+		NotationImpl cloned = new NotationImpl(this);
+		notifyUserDataHandlers(UserDataHandler.NODE_CLONED, cloned);
+		return cloned;
+	}
+
+	/**
+	 * getNodeName method
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getNodeName() {
+		if (this.name == null)
+			return NodeImpl.EMPTY_STRING;
+		return this.name;
+	}
+
+	/**
+	 * getNodeType method
+	 * 
+	 * @return short
+	 */
+	public short getNodeType() {
+		return NOTATION_NODE;
+	}
+
+	/**
+	 * getPublicId method
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getPublicId() {
+		return this.publicId;
+	}
+
+	/**
+	 * getSystemId method
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getSystemId() {
+		return this.systemId;
+	}
+
+	/**
+	 * setName method
+	 * 
+	 * @param name
+	 *            java.lang.String
+	 */
+	protected void setName(String name) {
+		this.name = name;
+	}
+
+	/**
+	 * setPublicId method
+	 * 
+	 * @param publicId
+	 *            java.lang.String
+	 */
+	public void setPublicId(String publicId) {
+		if (!isDataEditable()) {
+			throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, DOMMessages.NO_MODIFICATION_ALLOWED_ERR);
+		}
+		this.publicId = publicId;
+	}
+
+	/**
+	 * setSystemId method
+	 * 
+	 * @param systemId
+	 *            java.lang.String
+	 */
+	public void setSystemId(String systemId) {
+		if (!isDataEditable()) {
+			throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, DOMMessages.NO_MODIFICATION_ALLOWED_ERR);
+		}
+		this.systemId = systemId;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/ProcessingInstructionImpl.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/ProcessingInstructionImpl.java
new file mode 100644
index 0000000..044eb53
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/ProcessingInstructionImpl.java
@@ -0,0 +1,233 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *     Balazs Banfai: Bug 154737 getUserData/setUserData support for Node
+ *     https://bugs.eclipse.org/bugs/show_bug.cgi?id=154737
+ *     David Carver (STAR) - bug 296999 - Inefficient use of new String()
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import java.util.Iterator;
+
+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.ITextRegionList;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Node;
+import org.w3c.dom.ProcessingInstruction;
+import org.w3c.dom.UserDataHandler;
+
+
+/**
+ * ProcessingInstructionImpl class
+ */
+public class ProcessingInstructionImpl extends NodeImpl implements ProcessingInstruction {
+	private String data = null;
+
+	private String target = null;
+
+	/**
+	 * ProcessingInstructionImpl constructor
+	 */
+	protected ProcessingInstructionImpl() {
+		super();
+	}
+
+	/**
+	 * ProcessingInstructionImpl constructor
+	 * 
+	 * @param that
+	 *            ProcessingInstructionImpl
+	 */
+	protected ProcessingInstructionImpl(ProcessingInstructionImpl that) {
+		super(that);
+
+		if (that != null) {
+			this.target = that.target;
+			this.data = that.getData();
+		}
+	}
+
+	/**
+	 * cloneNode method
+	 * 
+	 * @return org.w3c.dom.Node
+	 * @param deep
+	 *            boolean
+	 */
+	public Node cloneNode(boolean deep) {
+		ProcessingInstructionImpl cloned = new ProcessingInstructionImpl(this);
+		notifyUserDataHandlers(UserDataHandler.NODE_CLONED, cloned);
+		return cloned;
+	}
+
+	/**
+	 * getData method
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getData() {
+		if (this.data != null)
+			return this.data;
+
+		IStructuredDocumentRegion flatNode = getFirstStructuredDocumentRegion();
+		if (flatNode == null)
+			return NodeImpl.EMPTY_STRING;
+		ITextRegionList regions = flatNode.getRegions();
+		if (regions == null)
+			return NodeImpl.EMPTY_STRING;
+
+		ITextRegion targetRegion = null;
+		ITextRegion dataRegion = null;
+		ITextRegion closeRegion = null;
+		Iterator e = regions.iterator();
+		while (e.hasNext()) {
+			ITextRegion region = (ITextRegion) e.next();
+			String regionType = region.getType();
+			if (regionType == DOMRegionContext.XML_PI_OPEN)
+				continue;
+			if (regionType == DOMRegionContext.XML_PI_CLOSE) {
+				closeRegion = region;
+			}
+			else {
+				if (targetRegion == null)
+					targetRegion = region;
+				else if (dataRegion == null)
+					dataRegion = region;
+			}
+		}
+		if (dataRegion == null)
+			return NodeImpl.EMPTY_STRING;
+		int offset = dataRegion.getStart();
+		int end = flatNode.getLength();
+		if (closeRegion != null)
+			end = closeRegion.getStart();
+		String source = flatNode.getText();
+		return source.substring(offset, end);
+	}
+
+	/**
+	 * getNodeName method
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getNodeName() {
+		return getTarget();
+	}
+
+	/**
+	 * getNodeType method
+	 * 
+	 * @return short
+	 */
+	public short getNodeType() {
+		return PROCESSING_INSTRUCTION_NODE;
+	}
+
+	/**
+	 * getNodeValue method
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getNodeValue() {
+		return getData();
+	}
+
+	/**
+	 * getTarget method
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getTarget() {
+		if (this.target == null)
+			return NodeImpl.EMPTY_STRING;
+		return this.target;
+	}
+
+	/**
+	 */
+	public boolean isClosed() {
+		IStructuredDocumentRegion flatNode = getStructuredDocumentRegion();
+		if (flatNode == null)
+			return true; // will be generated
+		String regionType = StructuredDocumentRegionUtil.getLastRegionType(flatNode);
+		return (regionType == DOMRegionContext.XML_PI_CLOSE);
+	}
+
+	/**
+	 */
+	void resetStructuredDocumentRegions() {
+		this.data = getData();
+		setStructuredDocumentRegion(null);
+	}
+
+	/**
+	 * setData method
+	 * 
+	 * @param data
+	 *            java.lang.String
+	 */
+	public void setData(String data) throws DOMException {
+		if (!isDataEditable()) {
+			throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, DOMMessages.NO_MODIFICATION_ALLOWED_ERR);
+		}
+
+		this.data = data;
+
+		notifyValueChanged();
+	}
+
+	/**
+	 * setNodeValue method
+	 * 
+	 * @param nodeValue
+	 *            java.lang.String
+	 */
+	public void setNodeValue(String nodeValue) throws DOMException {
+		setData(nodeValue);
+	}
+
+	/**
+	 */
+	void setStructuredDocumentRegion(IStructuredDocumentRegion flatNode) {
+		super.setStructuredDocumentRegion(flatNode);
+		if (flatNode != null)
+			this.data = null;
+	}
+
+	/**
+	 * setTarget method
+	 * 
+	 * @param target
+	 *            java.lang.String
+	 */
+	protected void setTarget(String target) {
+		this.target = target;
+	}
+
+	/**
+	 * toString method
+	 * 
+	 * @return java.lang.String
+	 */
+	public String toString() {
+		StringBuffer buffer = new StringBuffer();
+		buffer.append(getTarget());
+		buffer.append('(');
+		buffer.append(getData());
+		buffer.append(')');
+		return buffer.toString();
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/RangeImpl.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/RangeImpl.java
new file mode 100644
index 0000000..ad30e28
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/RangeImpl.java
@@ -0,0 +1,630 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.DocumentFragment;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+import org.w3c.dom.ranges.Range;
+import org.w3c.dom.ranges.RangeException;
+
+
+/**
+ */
+public class RangeImpl implements Range {
+	private Node endContainer = null;
+	private int endOffset = 0;
+
+	private Node startContainer = null;
+	private int startOffset = 0;
+
+	/**
+	 */
+	protected RangeImpl() {
+		super();
+	}
+
+	/**
+	 */
+	protected RangeImpl(RangeImpl that) {
+		super();
+
+		if (that != null) {
+			this.startContainer = that.startContainer;
+			this.startOffset = that.startOffset;
+			this.endContainer = that.endContainer;
+			this.endOffset = that.endOffset;
+		}
+	}
+
+	/**
+	 * Duplicates the contents of a Range
+	 * 
+	 * @return A DocumentFragment that contains content equivalent to this
+	 *         Range.
+	 * @exception DOMException
+	 *                HIERARCHY_REQUEST_ERR: Raised if a DocumentType node
+	 *                would be extracted into the new DocumentFragment. <br>
+	 *                INVALID_STATE_ERR: Raised if <code>detach()</code> has
+	 *                already been invoked on this object.
+	 */
+	public DocumentFragment cloneContents() throws DOMException {
+		// not supported
+		return null;
+	}
+
+	/**
+	 * Produces a new Range whose boundary-points are equal to the
+	 * boundary-points of the Range.
+	 * 
+	 * @return The duplicated Range.
+	 * @exception DOMException
+	 *                INVALID_STATE_ERR: Raised if <code>detach()</code> has
+	 *                already been invoked on this object.
+	 */
+	public Range cloneRange() throws DOMException {
+		return new RangeImpl(this);
+	}
+
+	/**
+	 * Collapse a Range onto one of its boundary-points
+	 * 
+	 * @param toStartIf
+	 *            TRUE, collapses the Range onto its start; if FALSE,
+	 *            collapses it onto its end.
+	 * @exception DOMException
+	 *                INVALID_STATE_ERR: Raised if <code>detach()</code> has
+	 *                already been invoked on this object.
+	 */
+	public void collapse(boolean toStart) throws DOMException {
+		if (toStart) {
+			this.endContainer = this.startContainer;
+			this.endOffset = this.startOffset;
+		} else {
+			this.startContainer = this.endContainer;
+			this.startOffset = this.endOffset;
+		}
+	}
+
+	/**
+	 * Compare the boundary-points of two Ranges in a document.
+	 * 
+	 * @param howA
+	 *            code representing the type of comparison, as defined above.
+	 * @param sourceRangeThe
+	 *            <code>Range</code> on which this current
+	 *            <code>Range</code> is compared to.
+	 * @return -1, 0 or 1 depending on whether the corresponding
+	 *         boundary-point of the Range is respectively before, equal to,
+	 *         or after the corresponding boundary-point of
+	 *         <code>sourceRange</code>.
+	 * @exception DOMException
+	 *                WRONG_DOCUMENT_ERR: Raised if the two Ranges are not in
+	 *                the same Document or DocumentFragment. <br>
+	 *                INVALID_STATE_ERR: Raised if <code>detach()</code> has
+	 *                already been invoked on this object.
+	 */
+	public short compareBoundaryPoints(short how, Range sourceRange) throws DOMException {
+		if (sourceRange == null)
+			return (short) 0; // error
+
+		Node container1 = null;
+		int offset1 = 0;
+		Node container2 = null;
+		int offset2 = 0;
+
+		switch (how) {
+			case START_TO_START :
+				container1 = this.startContainer;
+				offset1 = this.startOffset;
+				container2 = sourceRange.getStartContainer();
+				offset2 = sourceRange.getStartOffset();
+				break;
+			case START_TO_END :
+				container1 = this.startContainer;
+				offset1 = this.startOffset;
+				container2 = sourceRange.getEndContainer();
+				offset2 = sourceRange.getEndOffset();
+				break;
+			case END_TO_END :
+				container1 = this.endContainer;
+				offset1 = this.endOffset;
+				container2 = sourceRange.getEndContainer();
+				offset2 = sourceRange.getEndOffset();
+				break;
+			case END_TO_START :
+				container1 = this.endContainer;
+				offset1 = this.endOffset;
+				container2 = sourceRange.getStartContainer();
+				offset2 = sourceRange.getStartOffset();
+				break;
+			default :
+				return (short) 0; // error
+		}
+
+		return comparePoints(container1, offset1, container2, offset2);
+	}
+
+	/*
+	 */
+	protected short comparePoints(Node container1, int offset1, Node container2, int offset2) {
+		if (container1 == null || container2 == null)
+			return (short) 0; // error
+
+		if (container1 == container2) {
+			if (offset1 > offset2)
+				return (short) 1;
+			if (offset1 < offset2)
+				return (short) -1;
+			return 0;
+		}
+
+		// get node offsets
+		IDOMNode node1 = null;
+		if (container1.hasChildNodes()) {
+			Node child = container1.getFirstChild();
+			for (int i = 0; i < offset1; i++) {
+				Node next = child.getNextSibling();
+				if (next == null)
+					break;
+				child = next;
+			}
+			node1 = (IDOMNode) child;
+			offset1 = 0;
+		} else {
+			node1 = (IDOMNode) container1;
+		}
+		int nodeOffset1 = node1.getStartOffset();
+		IDOMNode node2 = null;
+		if (container2.hasChildNodes()) {
+			Node child = container2.getFirstChild();
+			for (int i = 0; i < offset2; i++) {
+				Node next = child.getNextSibling();
+				if (next == null)
+					break;
+				child = next;
+			}
+			node2 = (IDOMNode) child;
+			offset2 = 0;
+		} else {
+			node2 = (IDOMNode) container2;
+		}
+		int nodeOffset2 = node2.getStartOffset();
+
+		if (nodeOffset1 > nodeOffset2)
+			return (short) 1;
+		if (nodeOffset1 < nodeOffset2)
+			return (short) -1;
+		if (offset1 > offset2)
+			return (short) 1;
+		if (offset1 < offset2)
+			return (short) -1;
+		return (short) 0;
+	}
+
+	/**
+	 * Removes the contents of a Range from the containing document or
+	 * document fragment without returning a reference to the removed content.
+	 * 
+	 * @exception DOMException
+	 *                NO_MODIFICATION_ALLOWED_ERR: Raised if any portion of
+	 *                the content of the Range is read-only or any of the
+	 *                nodes that contain any of the content of the Range are
+	 *                read-only. <br>
+	 *                INVALID_STATE_ERR: Raised if <code>detach()</code> has
+	 *                already been invoked on this object.
+	 */
+	public void deleteContents() throws DOMException {
+		// not supported
+	}
+
+	/**
+	 * Called to indicate that the Range is no longer in use and that the
+	 * implementation may relinquish any resources associated with this Range.
+	 * Subsequent calls to any methods or attribute getters on this Range will
+	 * result in a <code>DOMException</code> being thrown with an error code
+	 * of <code>INVALID_STATE_ERR</code>.
+	 * 
+	 * @exception DOMException
+	 *                INVALID_STATE_ERR: Raised if <code>detach()</code> has
+	 *                already been invoked on this object.
+	 */
+	public void detach() throws DOMException {
+		this.startContainer = null;
+		this.startOffset = 0;
+		this.endContainer = null;
+		this.endOffset = 0;
+	}
+
+	/**
+	 * Moves the contents of a Range from the containing document or document
+	 * fragment to a new DocumentFragment.
+	 * 
+	 * @return A DocumentFragment containing the extracted contents.
+	 * @exception DOMException
+	 *                NO_MODIFICATION_ALLOWED_ERR: Raised if any portion of
+	 *                the content of the Range is read-only or any of the
+	 *                nodes which contain any of the content of the Range are
+	 *                read-only. <br>
+	 *                HIERARCHY_REQUEST_ERR: Raised if a DocumentType node
+	 *                would be extracted into the new DocumentFragment. <br>
+	 *                INVALID_STATE_ERR: Raised if <code>detach()</code> has
+	 *                already been invoked on this object.
+	 */
+	public DocumentFragment extractContents() throws DOMException {
+		// not supported
+		return null;
+	}
+
+	/**
+	 * TRUE if the Range is collapsed
+	 * 
+	 * @exception DOMException
+	 *                INVALID_STATE_ERR: Raised if <code>detach()</code> has
+	 *                already been invoked on this object.
+	 */
+	public boolean getCollapsed() throws DOMException {
+		if (this.startContainer == this.endContainer && this.startOffset == this.endOffset)
+			return true;
+		return false;
+	}
+
+	/**
+	 * The deepest common ancestor container of the Range's two
+	 * boundary-points.
+	 * 
+	 * @exception DOMException
+	 *                INVALID_STATE_ERR: Raised if <code>detach()</code> has
+	 *                already been invoked on this object.
+	 */
+	public Node getCommonAncestorContainer() throws DOMException {
+		if (this.startContainer == null)
+			return null;
+		return ((NodeImpl) this.startContainer).getCommonAncestor(this.endContainer);
+	}
+
+	/**
+	 * Node within which the Range ends
+	 * 
+	 * @exception DOMException
+	 *                INVALID_STATE_ERR: Raised if <code>detach()</code> has
+	 *                already been invoked on this object.
+	 */
+	public Node getEndContainer() throws DOMException {
+		return this.endContainer;
+	}
+
+	/**
+	 * Offset within the ending node of the Range.
+	 * 
+	 * @exception DOMException
+	 *                INVALID_STATE_ERR: Raised if <code>detach()</code> has
+	 *                already been invoked on this object.
+	 */
+	public int getEndOffset() throws DOMException {
+		return this.endOffset;
+	}
+
+	/**
+	 * Node within which the Range begins
+	 * 
+	 * @exception DOMException
+	 *                INVALID_STATE_ERR: Raised if <code>detach()</code> has
+	 *                already been invoked on this object.
+	 */
+	public Node getStartContainer() throws DOMException {
+		return this.startContainer;
+	}
+
+	/**
+	 * Offset within the starting node of the Range.
+	 * 
+	 * @exception DOMException
+	 *                INVALID_STATE_ERR: Raised if <code>detach()</code> has
+	 *                already been invoked on this object.
+	 */
+	public int getStartOffset() throws DOMException {
+		return this.startOffset;
+	}
+
+	/**
+	 * Inserts a node into the Document or DocumentFragment at the start of
+	 * the Range. If the container is a Text node, this will be split at the
+	 * start of the Range (as if the Text node's splitText method was
+	 * performed at the insertion point) and the insertion will occur between
+	 * the two resulting Text nodes. Adjacent Text nodes will not be
+	 * automatically merged. If the node to be inserted is a DocumentFragment
+	 * node, the children will be inserted rather than the DocumentFragment
+	 * node itself.
+	 * 
+	 * @param newNodeThe
+	 *            node to insert at the start of the Range
+	 * @exception DOMException
+	 *                NO_MODIFICATION_ALLOWED_ERR: Raised if an ancestor
+	 *                container of the start of the Range is read-only. <br>
+	 *                WRONG_DOCUMENT_ERR: Raised if <code>newNode</code> and
+	 *                the container of the start of the Range were not created
+	 *                from the same document. <br>
+	 *                HIERARCHY_REQUEST_ERR: Raised if the container of the
+	 *                start of the Range is of a type that does not allow
+	 *                children of the type of <code>newNode</code> or if
+	 *                <code>newNode</code> is an ancestor of the container.
+	 *                <br>
+	 *                INVALID_STATE_ERR: Raised if <code>detach()</code> has
+	 *                already been invoked on this object.
+	 * @exception RangeException
+	 *                INVALID_NODE_TYPE_ERR: Raised if <code>newNode</code>
+	 *                is an Attr, Entity, Notation, or Document node.
+	 */
+	public void insertNode(Node newNode) throws RangeException, DOMException {
+		// not supported
+	}
+
+	/**
+	 * Select a node and its contents
+	 * 
+	 * @param refNodeThe
+	 *            node to select.
+	 * @exception RangeException
+	 *                INVALID_NODE_TYPE_ERR: Raised if an ancestor of
+	 *                <code>refNode</code> is an Entity, Notation or
+	 *                DocumentType node or if <code>refNode</code> is a
+	 *                Document, DocumentFragment, Attr, Entity, or Notation
+	 *                node.
+	 * @exception DOMException
+	 *                INVALID_STATE_ERR: Raised if <code>detach()</code> has
+	 *                already been invoked on this object.
+	 */
+	public void selectNode(Node refNode) throws RangeException, DOMException {
+		if (refNode == null)
+			return;
+		Node parent = refNode.getParentNode();
+		if (parent == null)
+			return;
+		int index = ((NodeImpl) refNode).getIndex();
+		if (index < 0)
+			return;
+		setStart(parent, index);
+		setEnd(parent, index + 1);
+	}
+
+	/**
+	 * Select the contents within a node
+	 * 
+	 * @param refNodeNode
+	 *            to select from
+	 * @exception RangeException
+	 *                INVALID_NODE_TYPE_ERR: Raised if <code>refNode</code>
+	 *                or an ancestor of <code>refNode</code> is an Entity,
+	 *                Notation or DocumentType node.
+	 * @exception DOMException
+	 *                INVALID_STATE_ERR: Raised if <code>detach()</code> has
+	 *                already been invoked on this object.
+	 */
+	public void selectNodeContents(Node refNode) throws RangeException, DOMException {
+		if (refNode == null)
+			return;
+		if (refNode.getNodeType() == Node.TEXT_NODE) {
+			Text text = (Text) refNode;
+			setStart(refNode, 0);
+			setEnd(refNode, text.getLength());
+		} else {
+			NodeList childNodes = refNode.getChildNodes();
+			int length = (childNodes != null ? childNodes.getLength() : 0);
+			setStart(refNode, 0);
+			setEnd(refNode, length);
+		}
+	}
+
+	/**
+	 * Sets the attributes describing the end of a Range.
+	 * 
+	 * @param refNodeThe
+	 *            <code>refNode</code> value. This parameter must be
+	 *            different from <code>null</code>.
+	 * @param offsetThe
+	 *            <code>endOffset</code> value.
+	 * @exception RangeException
+	 *                INVALID_NODE_TYPE_ERR: Raised if <code>refNode</code>
+	 *                or an ancestor of <code>refNode</code> is an Entity,
+	 *                Notation, or DocumentType node.
+	 * @exception DOMException
+	 *                INDEX_SIZE_ERR: Raised if <code>offset</code> is
+	 *                negative or greater than the number of child units in
+	 *                <code>refNode</code>. Child units are 16-bit units if
+	 *                <code>refNode</code> is a type of CharacterData node
+	 *                (e.g., a Text or Comment node) or a
+	 *                ProcessingInstruction node. Child units are Nodes in all
+	 *                other cases. <br>
+	 *                INVALID_STATE_ERR: Raised if <code>detach()</code> has
+	 *                already been invoked on this object.
+	 */
+	public void setEnd(Node refNode, int offset) throws RangeException, DOMException {
+		this.endContainer = refNode;
+		this.endOffset = offset;
+	}
+
+	/**
+	 * Sets the end of a Range to be after a node
+	 * 
+	 * @param refNodeRange
+	 *            ends after <code>refNode</code>.
+	 * @exception RangeException
+	 *                INVALID_NODE_TYPE_ERR: Raised if the root container of
+	 *                <code>refNode</code> is not an Attr, Document or
+	 *                DocumentFragment node or if <code>refNode</code> is a
+	 *                Document, DocumentFragment, Attr, Entity, or Notation
+	 *                node.
+	 * @exception DOMException
+	 *                INVALID_STATE_ERR: Raised if <code>detach()</code> has
+	 *                already been invoked on this object.
+	 */
+	public void setEndAfter(Node refNode) throws RangeException, DOMException {
+		if (refNode == null)
+			return;
+		Node parent = refNode.getParentNode();
+		if (parent == null)
+			return;
+		int index = ((NodeImpl) refNode).getIndex();
+		if (index < 0)
+			return;
+		setEnd(parent, index + 1);
+	}
+
+	/**
+	 * Sets the end position to be before a node.
+	 * 
+	 * @param refNodeRange
+	 *            ends before <code>refNode</code>
+	 * @exception RangeException
+	 *                INVALID_NODE_TYPE_ERR: Raised if the root container of
+	 *                <code>refNode</code> is not an Attr, Document, or
+	 *                DocumentFragment node or if <code>refNode</code> is a
+	 *                Document, DocumentFragment, Attr, Entity, or Notation
+	 *                node.
+	 * @exception DOMException
+	 *                INVALID_STATE_ERR: Raised if <code>detach()</code> has
+	 *                already been invoked on this object.
+	 */
+	public void setEndBefore(Node refNode) throws RangeException, DOMException {
+		if (refNode == null)
+			return;
+		Node parent = refNode.getParentNode();
+		if (parent == null)
+			return;
+		int index = ((NodeImpl) refNode).getIndex();
+		if (index < 0)
+			return;
+		setEnd(parent, index);
+	}
+
+	/**
+	 * Sets the attributes describing the start of the Range.
+	 * 
+	 * @param refNodeThe
+	 *            <code>refNode</code> value. This parameter must be
+	 *            different from <code>null</code>.
+	 * @param offsetThe
+	 *            <code>startOffset</code> value.
+	 * @exception RangeException
+	 *                INVALID_NODE_TYPE_ERR: Raised if <code>refNode</code>
+	 *                or an ancestor of <code>refNode</code> is an Entity,
+	 *                Notation, or DocumentType node.
+	 * @exception DOMException
+	 *                INDEX_SIZE_ERR: Raised if <code>offset</code> is
+	 *                negative or greater than the number of child units in
+	 *                <code>refNode</code>. Child units are 16-bit units if
+	 *                <code>refNode</code> is a type of CharacterData node
+	 *                (e.g., a Text or Comment node) or a
+	 *                ProcessingInstruction node. Child units are Nodes in all
+	 *                other cases. <br>
+	 *                INVALID_STATE_ERR: Raised if <code>detach()</code> has
+	 *                already been invoked on this object.
+	 */
+	public void setStart(Node refNode, int offset) throws RangeException, DOMException {
+		this.startContainer = refNode;
+		this.startOffset = offset;
+	}
+
+	/**
+	 * Sets the start position to be after a node
+	 * 
+	 * @param refNodeRange
+	 *            starts after <code>refNode</code>
+	 * @exception RangeException
+	 *                INVALID_NODE_TYPE_ERR: Raised if the root container of
+	 *                <code>refNode</code> is not an Attr, Document, or
+	 *                DocumentFragment node or if <code>refNode</code> is a
+	 *                Document, DocumentFragment, Attr, Entity, or Notation
+	 *                node.
+	 * @exception DOMException
+	 *                INVALID_STATE_ERR: Raised if <code>detach()</code> has
+	 *                already been invoked on this object.
+	 */
+	public void setStartAfter(Node refNode) throws RangeException, DOMException {
+		if (refNode == null)
+			return;
+		Node parent = refNode.getParentNode();
+		if (parent == null)
+			return;
+		int index = ((NodeImpl) refNode).getIndex();
+		if (index < 0)
+			return;
+		setStart(parent, index + 1);
+	}
+
+	/**
+	 * Sets the start position to be before a node
+	 * 
+	 * @param refNodeRange
+	 *            starts before <code>refNode</code>
+	 * @exception RangeException
+	 *                INVALID_NODE_TYPE_ERR: Raised if the root container of
+	 *                <code>refNode</code> is not an Attr, Document, or
+	 *                DocumentFragment node or if <code>refNode</code> is a
+	 *                Document, DocumentFragment, Attr, Entity, or Notation
+	 *                node.
+	 * @exception DOMException
+	 *                INVALID_STATE_ERR: Raised if <code>detach()</code> has
+	 *                already been invoked on this object.
+	 */
+	public void setStartBefore(Node refNode) throws RangeException, DOMException {
+		if (refNode == null)
+			return;
+		Node parent = refNode.getParentNode();
+		if (parent == null)
+			return;
+		int index = ((NodeImpl) refNode).getIndex();
+		if (index < 0)
+			return;
+		setStart(parent, index);
+	}
+
+	/**
+	 * Reparents the contents of the Range to the given node and inserts the
+	 * node at the position of the start of the Range.
+	 * 
+	 * @param newParentThe
+	 *            node to surround the contents with.
+	 * @exception DOMException
+	 *                NO_MODIFICATION_ALLOWED_ERR: Raised if an ancestor
+	 *                container of either boundary-point of the Range is
+	 *                read-only. <br>
+	 *                WRONG_DOCUMENT_ERR: Raised if <code> newParent</code>
+	 *                and the container of the start of the Range were not
+	 *                created from the same document. <br>
+	 *                HIERARCHY_REQUEST_ERR: Raised if the container of the
+	 *                start of the Range is of a type that does not allow
+	 *                children of the type of <code>newParent</code> or if
+	 *                <code>newParent</code> is an ancestor of the container
+	 *                or if <code>node</code> would end up with a child node
+	 *                of a type not allowed by the type of <code>node</code>.
+	 *                <br>
+	 *                INVALID_STATE_ERR: Raised if <code>detach()</code> has
+	 *                already been invoked on this object.
+	 * @exception RangeException
+	 *                BAD_BOUNDARYPOINTS_ERR: Raised if the Range partially
+	 *                selects a non-text node. <br>
+	 *                INVALID_NODE_TYPE_ERR: Raised if <code> node</code> is
+	 *                an Attr, Entity, DocumentType, Notation, Document, or
+	 *                DocumentFragment node.
+	 */
+	public void surroundContents(Node newParent) throws RangeException, DOMException {
+		// not supported
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/ReadOnlyController.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/ReadOnlyController.java
new file mode 100644
index 0000000..57c2375
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/ReadOnlyController.java
@@ -0,0 +1,343 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+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.ITextRegionList;
+import org.eclipse.wst.sse.core.internal.text.BasicStructuredDocument;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMText;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+import org.w3c.dom.Node;
+
+
+class ReadOnlyController {
+
+	class Span {
+		int length;
+		int offset;
+
+		Span(int offset, int length) {
+			this.offset = offset;
+			this.length = length;
+		}
+	}
+
+	private static ReadOnlyController fInstance;
+
+	static synchronized ReadOnlyController getInstance() {
+		if (fInstance == null) {
+			fInstance = new ReadOnlyController();
+		}
+		return fInstance;
+	}
+
+	static private void lock(IStructuredDocument doc, int offset, int length, boolean canInsertBefore, boolean canInsertAfter) {
+		if (doc == null) {
+			return;
+		}
+		if (doc instanceof BasicStructuredDocument) {
+			((BasicStructuredDocument)doc).makeReadOnly(offset, length, canInsertBefore, canInsertAfter);
+		} else {
+			doc.makeReadOnly(offset, length);
+		}
+	}
+
+	static private void lock(IStructuredDocumentRegion node, boolean canInsertBefore, boolean canInsertAfter) {
+		if (node == null) {
+			return;
+		}
+		IStructuredDocument doc = node.getParentDocument();
+		if (doc == null) {
+			return;
+		}
+		if (doc instanceof BasicStructuredDocument) {
+			((BasicStructuredDocument)doc).makeReadOnly(node.getStart(), node.getLength(), canInsertBefore, canInsertAfter);
+		} else {
+			doc.makeReadOnly(node.getStart(), node.getLength());
+		}
+	}
+
+	static private void unlock(IStructuredDocumentRegion node) {
+		if (node == null) {
+			return;
+		}
+		IStructuredDocument doc = node.getParentDocument();
+		if (doc == null) {
+			return;
+		}
+		doc.clearReadOnly(node.getStart(), node.getLength());
+	}
+
+	private ReadOnlyController() {
+		super();
+	}
+
+	private Span getDataSpan(IDOMNode node) {
+		switch (node.getNodeType()) {
+			case Node.ELEMENT_NODE :
+				return getDataSpanForElement((IDOMElement) node);
+			case Node.TEXT_NODE :
+				return getDataSpanForText((IDOMText) node);
+			default :
+				return new Span(0, -1);
+		}
+	}
+
+	private Span getDataSpanForElement(IDOMElement node) {
+		IStructuredDocumentRegion docRegion = node.getStartStructuredDocumentRegion();
+		if (docRegion == null) {
+			return new Span(0, -1);
+		}
+
+		ITextRegionList regions = docRegion.getRegions();
+		if (regions == null) {
+			return new Span(0, -1);
+		}
+
+		String startType;
+		String endType;
+		if (node.isCommentTag()) {
+			startType = DOMRegionContext.XML_COMMENT_OPEN;
+			endType = DOMRegionContext.XML_COMMENT_CLOSE;
+		} else {
+			startType = DOMRegionContext.XML_TAG_NAME;
+			endType = DOMRegionContext.XML_TAG_CLOSE;
+		}
+
+		int startOffset = -1;
+		int endOffset = -1;
+		ITextRegion prevRegion = null;
+		ITextRegion region;
+		for (int i = 0; i < regions.size(); i++) {
+			region = regions.get(i);
+			String type = region.getType();
+			if (type == startType) {
+				startOffset = region.getEnd();
+			} else if (type == endType && prevRegion != null) {
+				endOffset = prevRegion.getTextEnd();
+			}
+			prevRegion = region;
+		}
+
+		if (0 <= startOffset && 0 <= endOffset) {
+			return new Span(startOffset, endOffset - startOffset);
+		} else {
+			return new Span(0, -1);
+		}
+	}
+
+	private Span getDataSpanForText(IDOMText node) {
+		IStructuredDocumentRegion docRegion = ((NodeImpl) node).getStructuredDocumentRegion();
+		if (docRegion == null) {
+			return new Span(0, -1);
+		}
+		return new Span(0, docRegion.getLength());
+	}
+
+	/**
+	 * This method is used from parent's setChildEditable()
+	 * 
+	 * case 1:<parent><node attr="value"/> <node2></parent>
+	 * x####################x case 2:<parent><node attr="value"> <child>
+	 * </child> </node> </parent> x###################? ?#######x (? :
+	 * editable if node.isEditable() == true)
+	 */
+	void lockBoth(IDOMNode node) {
+		if (node == null) {
+			return;
+		}
+
+		IStructuredDocumentRegion flatNode;
+		boolean canInsert = false;
+
+		// end node (element)
+		if (node.getNodeType() == Node.ELEMENT_NODE) {
+			flatNode = node.getEndStructuredDocumentRegion();
+			if (flatNode != null) {
+				canInsert = node.isChildEditable();
+				lock(flatNode, canInsert, false);
+			}
+		}
+		// start node
+		flatNode = node.getStartStructuredDocumentRegion();
+		if (flatNode != null) {
+			lock(flatNode, false, canInsert);
+		}
+	}
+
+	void lockData(IDOMNode node) {
+		if (node == null) {
+			return;
+		}
+
+		Span span = getDataSpan(node);
+		if (0 <= span.length) {
+			lock(node.getModel().getStructuredDocument(), node.getStartOffset() + span.offset, span.length, false, false);
+		}
+	}
+
+	/**
+	 * lock itself and all descendants
+	 */
+	void lockDeep(IDOMNode node) {
+		if (node == null) {
+			return;
+		}
+
+		int offset = node.getStartOffset();
+		int length = node.getEndOffset() - offset;
+
+		boolean canInsert = true;
+		IDOMNode parent = (IDOMNode) node.getParentNode();
+		if (parent != null && !parent.isChildEditable()) {
+			canInsert = false;
+		}
+		lock(node.getStructuredDocument(), offset, length, canInsert, canInsert);
+	}
+
+	/**
+	 * This method is used from parent's setChildEditable()
+	 * 
+	 * case 1:<parent><node attr="value"/> <node2></parent> x######x x##x
+	 * case 2:<parent><node attr="value"> <child></child> </node> </parent>
+	 * x######x x#? ?#######x (? : editable if node.isEditable() == true)
+	 */
+	void lockNode(IDOMNode node) {
+		if (node == null) {
+			return;
+		}
+		if (!node.isDataEditable()) {
+			lockBoth(node);
+			return;
+		}
+
+		IStructuredDocumentRegion flatNode;
+		boolean canInsert = false;
+
+		// end node (element)
+		if (node.getNodeType() == Node.ELEMENT_NODE) {
+			flatNode = node.getEndStructuredDocumentRegion();
+			if (flatNode != null) {
+				canInsert = node.isChildEditable();
+				lock(flatNode, canInsert, false);
+			}
+		}
+		// start node
+		flatNode = node.getStartStructuredDocumentRegion();
+		if (flatNode != null) {
+			Span span = getDataSpan(node);
+			if (0 <= span.length) {
+				IStructuredDocument structuredDocument = flatNode.getParentDocument();
+				int offset, length;
+				offset = flatNode.getStart();
+				length = span.offset;
+				lock(structuredDocument, offset, length, false, false);
+				offset = offset + span.offset + span.length;
+				length = flatNode.getEnd() - offset;
+				lock(structuredDocument, offset, length, false, canInsert);
+			} else {
+				lock(flatNode, false, canInsert);
+			}
+		}
+	}
+
+	private void unlock(IStructuredDocument doc, int offset, int length) {
+		if (doc == null) {
+			return;
+		}
+		doc.clearReadOnly(offset, length);
+	}
+
+	void unlockBoth(IDOMNode node) {
+		if (node == null) {
+			return;
+		}
+
+		IStructuredDocumentRegion flatNode;
+		// start node
+		flatNode = node.getStartStructuredDocumentRegion();
+		if (flatNode != null) {
+			unlock(flatNode);
+		}
+		// end node
+		flatNode = node.getEndStructuredDocumentRegion();
+		if (flatNode != null) {
+			unlock(flatNode);
+		}
+	}
+
+	void unlockData(IDOMNode node) {
+		if (node == null) {
+			return;
+		}
+
+		Span span = getDataSpan(node);
+		if (0 <= span.length) {
+			unlock(node.getModel().getStructuredDocument(), span.offset, span.length);
+		}
+	}
+
+	void unlockDeep(IDOMNode node) {
+		if (node == null) {
+			return;
+		}
+
+		int offset = node.getStartOffset();
+		int length = node.getEndOffset() - offset;
+
+		unlock(node.getStructuredDocument(), offset, length);
+	}
+
+	void unlockNode(IDOMNode node) {
+		if (node == null) {
+			return;
+		}
+
+		IStructuredDocumentRegion flatNode;
+		// end node
+		if (node.getNodeType() == Node.ELEMENT_NODE) {
+			flatNode = node.getEndStructuredDocumentRegion();
+			if (flatNode != null) {
+				unlock(flatNode);
+			}
+		}
+
+		// start node
+		flatNode = node.getStartStructuredDocumentRegion();
+		if (flatNode != null) {
+			if (node.isDataEditable()) {
+				unlock(flatNode);
+			} else {
+				Span span = getDataSpan(node);
+				if (span.length <= 0) {
+					unlock(flatNode);
+				} else {
+					IStructuredDocument structuredDocument = flatNode.getParentDocument();
+					int offset, length;
+					offset = flatNode.getStart();
+					length = span.offset - offset;
+					unlock(structuredDocument, offset, length);
+					offset = span.offset + span.length;
+					length = flatNode.getEnd() - span.offset;
+					unlock(structuredDocument, offset, length);
+				}
+			}
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/SourceValidator.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/SourceValidator.java
new file mode 100644
index 0000000..2051222
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/SourceValidator.java
@@ -0,0 +1,388 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+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.ITextRegionContainer;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList;
+import org.eclipse.wst.xml.core.internal.XMLCoreMessages;
+import org.eclipse.wst.xml.core.internal.provisional.IXMLCharEntity;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Node;
+
+/**
+ */
+public class SourceValidator {
+
+	private NodeImpl node = null;
+
+	/**
+	 */
+	public SourceValidator(Node node) {
+		super();
+
+		if (node != null) {
+			this.node = (NodeImpl) node;
+		}
+	}
+
+	/**
+	 */
+	public String convertSource(String source) {
+		if (source == null)
+			return null;
+		if (this.node == null)
+			return null; // error
+
+		// setup conversion conditions
+		boolean acceptTag = false;
+		boolean acceptClose = false;
+		boolean acceptQuote = false;
+		boolean acceptAmpersand = false;
+		boolean acceptEntityRef = true;
+		boolean acceptJSPEnd = true;
+		String endTagName = null;
+		if (this.node.getNodeType() == Node.ATTRIBUTE_NODE) {
+			IDOMDocument document = (IDOMDocument) this.node.getOwnerDocument();
+			if (document != null && document.isJSPType())
+				acceptTag = true;
+			if (acceptTag) {
+				Attr attr = (Attr) this.node;
+				ElementImpl element = (ElementImpl) attr.getOwnerElement();
+				if (element != null && element.isJSPTag())
+					acceptTag = false;
+			}
+			// if the source does not include single quote,
+			// double quote is valid
+			acceptQuote = (source.indexOf('\'') < 0);
+		} else if (this.node.getNodeType() == Node.TEXT_NODE) {
+			TextImpl text = (TextImpl) this.node;
+			if (text.isJSPContent()) {
+				int index = source.indexOf(JSPTag.TAG_CLOSE);
+				if (index < 0)
+					return source;
+				acceptTag = true;
+				acceptClose = true;
+				acceptQuote = true;
+				acceptAmpersand = true;
+				acceptJSPEnd = false;
+			} else if (text.isCDATAContent()) {
+				endTagName = text.getParentNode().getNodeName();
+				if (endTagName == null)
+					return null; // error
+				acceptTag = true;
+				acceptClose = true;
+				acceptQuote = true;
+				acceptAmpersand = true;
+			}
+		} else {
+			IDOMDocument document = null;
+			if (this.node.getNodeType() == Node.DOCUMENT_NODE) {
+				document = (IDOMDocument) this.node;
+			} else {
+				document = (IDOMDocument) this.node.getOwnerDocument();
+			}
+			if (document != null && document.isJSPType())
+				acceptTag = true;
+		}
+
+		StringBuffer buffer = null;
+		int copiedLength = 0;
+		int length = source.length();
+		for (int i = 0; i < length; i++) {
+			String ref = null;
+			char c = source.charAt(i);
+			switch (c) {
+				case '<' :
+					if (acceptTag) {
+						if (endTagName != null) {
+							if (!matchEndTag(source, i + 1, endTagName))
+								continue;
+						} else {
+							int skip = skipTag(source, i + 1);
+							if (skip >= 0) {
+								i += skip;
+								continue;
+							}
+						}
+						// invalid JSP tag
+					}
+					ref = IXMLCharEntity.LT_REF;
+					break;
+				case '>' :
+					if (acceptClose)
+						continue;
+					ref = IXMLCharEntity.GT_REF;
+					break;
+				case '&' :
+					if (acceptAmpersand)
+						continue;
+					if (acceptEntityRef) {
+						int skip = skipEntityRef(source, i + 1);
+						if (skip >= 0) {
+							i += skip;
+							continue;
+						}
+					}
+					ref = IXMLCharEntity.AMP_REF;
+					break;
+				case '"' :
+					if (acceptQuote)
+						continue;
+					ref = IXMLCharEntity.QUOT_REF;
+					break;
+				case '%' :
+					if (acceptJSPEnd)
+						continue;
+					if (source.charAt(i + 1) != '>')
+						continue;
+					i++;
+					ref = IXMLCharEntity.GT_REF;
+					break;
+				default :
+					continue;
+			}
+
+			if (ref != null) {
+				if (buffer == null) {
+					buffer = new StringBuffer(length + 8);
+				}
+				if (i > copiedLength) {
+					buffer.append(source.substring(copiedLength, i));
+				}
+				buffer.append(ref);
+				copiedLength = i + 1; // skip this character
+			}
+		}
+
+		if (buffer != null) {
+			if (copiedLength < length) {
+				buffer.append(source.substring(copiedLength, length));
+			}
+			return buffer.toString();
+		}
+		return source;
+	}
+
+	/**
+	 */
+	private final boolean matchEndTag(String source, int offset, String endTagName) {
+		if (source == null || endTagName == null)
+			return false;
+		int length = source.length();
+		if (offset < 0 || offset >= length)
+			return false;
+		if (source.charAt(offset) != '/')
+			return false;
+		offset++;
+		int end = offset + endTagName.length();
+		if (end > length)
+			return false;
+		return endTagName.equalsIgnoreCase(source.substring(offset, end));
+	}
+
+	/**
+	 */
+	private final int skipEntityRef(String source, int offset) {
+		if (source == null)
+			return -1;
+		if (offset < 0 || offset >= source.length())
+			return -1;
+		DocumentImpl document = (DocumentImpl) this.node.getOwnerDocument();
+		if (document == null)
+			return -1; // error
+
+		int end = source.indexOf(';', offset);
+		if (end < 0 || end == offset)
+			return -1;
+		String name = source.substring(offset, end);
+		if (name == null || document.getCharValue(name) == null)
+			return -1;
+		return (end + 1 - offset);
+	}
+
+	/**
+	 */
+	private final int skipTag(String source, int offset) {
+		if (source == null)
+			return -1;
+		if (offset < 0 || offset >= source.length())
+			return -1;
+
+		int end = offset;
+		if (source.charAt(offset) == '%') {
+			// JSP tag
+			int found = source.indexOf(JSPTag.TAG_CLOSE, offset + 1);
+			if (found < 0)
+				return -1; // invalid JSP tag
+			end = found + 2;
+		} else {
+			// normal tag
+			int found = source.lastIndexOf('>');
+			if (found < offset)
+				return -1; // invalid tag
+			end = found + 1;
+		}
+		return (end - offset);
+	}
+
+	/**
+	 */
+	public boolean validateSource(String source) throws InvalidCharacterException {
+		if (source == null)
+			return true;
+		if (this.node == null)
+			return false; // error
+		String message = null;
+
+
+		// setup validation conditions
+		boolean acceptTag = false;
+		boolean acceptClose = false;
+		boolean acceptQuote = true;
+		boolean acceptEntityRef = true;
+		String endTagName = null;
+		if (this.node.getNodeType() == Node.ATTRIBUTE_NODE) {
+			IDOMDocument document = (IDOMDocument) this.node.getOwnerDocument();
+			if (document != null && document.isJSPType())
+				acceptTag = true;
+			if (acceptTag) {
+				Attr attr = (Attr) this.node;
+				ElementImpl element = (ElementImpl) attr.getOwnerElement();
+				if (element != null && element.isJSPTag())
+					acceptTag = false;
+			}
+			// if the source does not include single quote,
+			// double quote is valid
+			acceptQuote = (source.indexOf('\'') < 0);
+		} else if (this.node.getNodeType() == Node.TEXT_NODE) {
+			TextImpl text = (TextImpl) this.node;
+			if (text.isJSPContent()) {
+				int index = source.indexOf(JSPTag.TAG_CLOSE);
+				if (index < 0)
+					return true;
+				message = XMLCoreMessages.Invalid_character_gt_fo_ERROR_;
+				throw new InvalidCharacterException(message, '>', index + 1);
+			} else if (text.isCDATAContent()) {
+				endTagName = text.getParentNode().getNodeName();
+				if (endTagName == null)
+					return false; // error
+				acceptTag = true;
+				acceptClose = true;
+			} else if(hasNestedRegion(text)) {
+				//there are cases (such as with EL) that the text is to complicated
+				//	to be verified by this validator
+				return true;
+			}
+		} else {
+			IDOMDocument document = null;
+			if (this.node.getNodeType() == Node.DOCUMENT_NODE) {
+				document = (IDOMDocument) this.node;
+			} else {
+				document = (IDOMDocument) this.node.getOwnerDocument();
+			}
+			if (document != null && document.isJSPType())
+				acceptTag = true;
+		}
+
+		char c = 0;
+		int length = source.length();
+		for (int i = 0; i < length; i++) {
+			c = source.charAt(i);
+			switch (c) {
+				case '<' :
+					if (acceptTag) {
+						if (endTagName != null) {
+							if (!matchEndTag(source, i + 1, endTagName))
+								continue;
+						} else {
+							int skip = skipTag(source, i + 1);
+							if (skip >= 0) {
+								i += skip;
+								continue;
+							}
+						}
+						// invalid tag
+					}
+					message = XMLCoreMessages.Invalid_character_lt_fo_ERROR_;
+					break;
+				case '>' :
+					if (acceptClose)
+						continue;
+					message = XMLCoreMessages.Invalid_character_gt_fo_ERROR_;
+					break;
+				case '&' :
+					if (acceptEntityRef) {
+						if (endTagName != null)
+							continue;
+						int skip = skipEntityRef(source, i + 1);
+						if (skip >= 0) {
+							i += skip;
+							continue;
+						}
+						// invalid entity reference
+					}
+					message = XMLCoreMessages.Invalid_character_amp_fo_ERROR_;
+					break;
+				case '"' :
+					if (acceptQuote)
+						continue;
+					message = XMLCoreMessages.Invalid_character__f_EXC_;
+					break;
+				default :
+					continue;
+			}
+
+			if (message != null) {
+				throw new InvalidCharacterException(message, c, i);
+			}
+		}
+
+		return true;
+	}
+	
+	/**
+	 * True if the text has nested regions, meaning container is probably too
+	 * complicated (like EL regions) to validate with this validator.
+	 *
+	 * @param text
+	 * @return
+	 */
+	private boolean hasNestedRegion(TextImpl text) {
+		boolean done = false;
+
+		IStructuredDocumentRegion currRegion = text.getFirstStructuredDocumentRegion();
+		IStructuredDocumentRegion lastRegion = text.getLastStructuredDocumentRegion();
+
+		while(currRegion != null && !done) {
+			
+			ITextRegionList regions = currRegion.getRegions();
+			for(int i = 0; i < regions.size(); ++i) {
+				ITextRegion container = regions.get(i);
+				if ((container instanceof ITextRegionContainer)) {
+					ITextRegionList regions2 = ((ITextRegionContainer) container).getRegions();
+					if (regions2 != null) {
+						return true;
+					}
+				}
+			}
+
+			done = currRegion == lastRegion;
+			currRegion = currRegion.getNext();
+		}
+
+		return false;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/StructuredDocumentRegionChecker.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/StructuredDocumentRegionChecker.java
new file mode 100644
index 0000000..547c8f3
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/StructuredDocumentRegionChecker.java
@@ -0,0 +1,143 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import java.io.IOException;
+import java.io.Writer;
+
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
+import org.w3c.dom.Node;
+
+
+/**
+ * This class is only for debug purpose.
+ */
+public class StructuredDocumentRegionChecker {
+	String EOL = System.getProperty("line.separator"); //$NON-NLS-1$
+
+	private int offset = 0;
+	Writer testWriter = null;
+
+	/**
+	 */
+	public StructuredDocumentRegionChecker() {
+		super();
+	}
+
+	public StructuredDocumentRegionChecker(Writer writer) {
+		super();
+		testWriter = writer;
+	}
+
+	/**
+	 */
+	private void checkChildNodes(Node node) {
+		for (Node child = node.getFirstChild(); child != null; child = child.getNextSibling()) {
+			checkNode(child);
+		}
+	}
+
+	/**
+	 */
+	public void checkModel(IDOMModel model) {
+		checkChildNodes(model.getDocument());
+	}
+
+	/**
+	 */
+	private void checkNode(Node node) {
+		checkStructuredDocumentRegion(((NodeImpl) node).getStructuredDocumentRegion());
+		if (node.getNodeType() == Node.ELEMENT_NODE) {
+			checkChildNodes(node);
+			checkStructuredDocumentRegion(((ElementImpl) node).getEndStructuredDocumentRegion());
+		}
+	}
+
+	/**
+	 */
+	private void checkStructuredDocumentRegion(IStructuredDocumentRegion flatNode) {
+		if (flatNode == null)
+			return;
+
+		if (flatNode instanceof StructuredDocumentRegionContainer) {
+			StructuredDocumentRegionContainer container = (StructuredDocumentRegionContainer) flatNode;
+			int n = container.getStructuredDocumentRegionCount();
+			for (int i = 0; i < n; i++) {
+				IStructuredDocumentRegion c = container.getStructuredDocumentRegion(i);
+				if (c == null) {
+					reportError("null"); //$NON-NLS-1$
+					continue;
+				}
+				checkStructuredDocumentRegion(c);
+			}
+			return;
+		}
+
+		int start = flatNode.getStart();
+		if (start < this.offset)
+			reportError("overwrap"); //$NON-NLS-1$
+		if (start > this.offset)
+			reportError("gap"); //$NON-NLS-1$
+		int end = flatNode.getEnd();
+		this.offset = end;
+
+		if (flatNode instanceof StructuredDocumentRegionProxy) {
+			StructuredDocumentRegionProxy proxy = (StructuredDocumentRegionProxy) flatNode;
+			IStructuredDocumentRegion p = proxy.getStructuredDocumentRegion();
+			if (p == null) {
+				reportError("null"); //$NON-NLS-1$
+				return;
+			}
+			int s = p.getStart();
+			int e = p.getEnd();
+			if (s > start || e < end)
+				reportError("out"); //$NON-NLS-1$
+			if (s == start && e == end)
+				reportWarning("vain"); //$NON-NLS-1$
+		}
+	}
+
+	/**
+	 */
+	private void reportError(String message) {
+		String msg = "StructuredDocumentRegionChecker : error : " + message; //$NON-NLS-1$
+		if (testWriter != null) {
+			try {
+				testWriter.write(msg + EOL);
+			} catch (IOException e) {
+				e.printStackTrace();
+			}
+		} else {
+			System.out.println(msg);
+		}
+		throw new StructuredDocumentRegionManagementException();
+	}
+
+	/**
+	 */
+	private void reportWarning(String message) {
+		String msg = "StructuredDocumentRegionChecker : warning : " + message; //$NON-NLS-1$
+		if (testWriter != null) {
+			try {
+				testWriter.write(msg + EOL);
+			} catch (IOException e) {
+				e.printStackTrace();
+			}
+		} else {
+			System.out.println(msg);
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/StructuredDocumentRegionContainer.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/StructuredDocumentRegionContainer.java
new file mode 100644
index 0000000..245211d
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/StructuredDocumentRegionContainer.java
@@ -0,0 +1,435 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     David Carver (STAR) - bug 296999 - Inefficient use of new String()
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import java.util.Vector;
+
+import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentEvent;
+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.ITextRegionContainer;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList;
+
+
+class StructuredDocumentRegionContainer implements IStructuredDocumentRegion {
+
+	private Vector flatNodes = new Vector(2);
+
+	/**
+	 */
+	StructuredDocumentRegionContainer() {
+		super();
+	}
+
+
+	public void addRegion(ITextRegion aRegion) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+
+	}
+
+	public void adjust(int i) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+
+	}
+
+	public void adjustLength(int i) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+
+	}
+
+	public void adjustStart(int i) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+
+	}
+
+	public void adjustTextLength(int i) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+
+	}
+
+	/**
+	 */
+	void appendStructuredDocumentRegion(IStructuredDocumentRegion flatNode) {
+		if (flatNode == null)
+			return;
+		if (flatNode instanceof StructuredDocumentRegionContainer) {
+			StructuredDocumentRegionContainer container = (StructuredDocumentRegionContainer) flatNode;
+			if (container.getStructuredDocumentRegionCount() > 0) {
+				this.flatNodes.addAll(container.flatNodes);
+			}
+		}
+		else {
+			this.flatNodes.addElement(flatNode);
+		}
+	}
+
+	public boolean containsOffset(int i) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	public boolean containsOffset(ITextRegion region, int i) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	public void equatePositions(ITextRegion region) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+
+	}
+
+	public ITextRegion getDeepestRegionAtCharacterOffset(int offset) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	/**
+	 */
+	public int getEnd() {
+		IStructuredDocumentRegion last = getLastStructuredDocumentRegion();
+		if (last == null)
+			return 0;
+		return last.getEnd();
+	}
+
+	/**
+	 */
+	public int getEndOffset() {
+		return getEnd();
+	}
+
+	public int getEndOffset(ITextRegion containedRegion) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	public ITextRegion getFirstRegion() {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	/**
+	 */
+	IStructuredDocumentRegion getFirstStructuredDocumentRegion() {
+		if (this.flatNodes.isEmpty())
+			return null;
+		return (IStructuredDocumentRegion) this.flatNodes.elementAt(0);
+	}
+
+	/**
+	 */
+	public String getFullText() {
+		return getText();
+	}
+
+	/**
+	 */
+	public String getFullText(ITextRegion aRegion) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	/**
+	 */
+	public String getFullText(String context) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	public ITextRegion getLastRegion() {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	IStructuredDocumentRegion getLastStructuredDocumentRegion() {
+		int size = this.flatNodes.size();
+		if (size == 0)
+			return null;
+		return (IStructuredDocumentRegion) this.flatNodes.elementAt(size - 1);
+	}
+
+	/** 
+	 */
+	public int getLength() {
+		return (getEnd() - getStart());
+	}
+
+	public IStructuredDocumentRegion getNext() {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	public int getNumberOfRegions() {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	public ITextRegionContainer getParent() {
+		return null;
+	}
+
+	public IStructuredDocument getParentDocument() {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	public IStructuredDocumentRegion getPrevious() {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	/**
+	 */
+	public ITextRegion getRegionAtCharacterOffset(int offset) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	/**
+	 */
+	public ITextRegionList getRegions() {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	/**
+	 */
+	public int getStart() {
+		IStructuredDocumentRegion first = getFirstStructuredDocumentRegion();
+		if (first == null)
+			return 0;
+		return first.getStart();
+	}
+
+	/**
+	 */
+	public int getStartOffset() {
+		return getStart();
+	}
+
+	public int getStartOffset(ITextRegion containedRegion) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	/**
+	 */
+	public IStructuredDocument getStructuredDocument() {
+		IStructuredDocumentRegion first = getFirstStructuredDocumentRegion();
+		if (first == null)
+			return null;
+		return first.getParentDocument();
+	}
+
+	/**
+	 */
+	IStructuredDocumentRegion getStructuredDocumentRegion(int index) {
+		if (index < 0 || index >= this.flatNodes.size())
+			return null;
+		return (IStructuredDocumentRegion) this.flatNodes.elementAt(index);
+	}
+
+	/**
+	 */
+	int getStructuredDocumentRegionCount() {
+		return this.flatNodes.size();
+	}
+
+	/**
+	 */
+	public String getText() {
+		int size = this.flatNodes.size();
+		if (size == 0)
+			return NodeImpl.EMPTY_STRING;
+		StringBuffer buffer = new StringBuffer();
+		for (int i = 0; i < size; i++) {
+			IStructuredDocumentRegion flatNode = (IStructuredDocumentRegion) this.flatNodes.elementAt(i);
+			if (flatNode == null)
+				continue;
+			buffer.append(flatNode.getText());
+		}
+		return buffer.toString();
+	}
+
+	/**
+	 */
+	public String getText(ITextRegion aRegion) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	/**
+	 */
+	public String getText(String context) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	/**
+	 */
+	public int getTextEnd() {
+		return getEnd();
+	}
+
+	/**
+	 */
+	public int getTextEndOffset() {
+		return getTextEnd();
+	}
+
+	public int getTextEndOffset(ITextRegion containedRegion) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	/**
+	 * The text length is equal to length if there is no white space at the
+	 * end of a region. Otherwise it is smaller than length.
+	 */
+	public int getTextLength() {
+		return (getTextEnd() - getStart());
+	}
+
+	/**
+	 */
+	public String getType() {
+		return "StructuredDocumentRegionContainer";//$NON-NLS-1$
+	}
+
+	/**
+	 */
+	void insertStructuredDocumentRegion(IStructuredDocumentRegion flatNode, int index) {
+		if (flatNode == null)
+			return;
+		if (index < 0)
+			return;
+		int size = this.flatNodes.size();
+		if (index > size)
+			return;
+		if (index == size) {
+			appendStructuredDocumentRegion(flatNode);
+			return;
+		}
+		this.flatNodes.insertElementAt(flatNode, index);
+	}
+
+	public boolean isEnded() {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	/**
+	 */
+	IStructuredDocumentRegion removeStructuredDocumentRegion(int index) {
+		if (index < 0 || index >= this.flatNodes.size())
+			return null;
+		IStructuredDocumentRegion flatNode = (IStructuredDocumentRegion) this.flatNodes.elementAt(index);
+		this.flatNodes.removeElementAt(index);
+		return flatNode;
+	}
+
+	/**
+	 */
+	IStructuredDocumentRegion removeStructuredDocumentRegion(IStructuredDocumentRegion oldStructuredDocumentRegion) {
+		if (oldStructuredDocumentRegion == null)
+			return null;
+		int size = this.flatNodes.size();
+		for (int i = 0; i < size; i++) {
+			IStructuredDocumentRegion flatNode = (IStructuredDocumentRegion) this.flatNodes.elementAt(i);
+			if (flatNode == oldStructuredDocumentRegion) {
+				this.flatNodes.removeElementAt(i);
+				return flatNode;
+			}
+		}
+		return null; // not found
+	}
+
+	/**
+	 */
+	IStructuredDocumentRegion replaceStructuredDocumentRegion(IStructuredDocumentRegion flatNode, int index) {
+		if (flatNode == null)
+			return removeStructuredDocumentRegion(index);
+		if (index < 0 || index >= this.flatNodes.size())
+			return null;
+		IStructuredDocumentRegion oldStructuredDocumentRegion = (IStructuredDocumentRegion) this.flatNodes.elementAt(index);
+		this.flatNodes.setElementAt(flatNode, index);
+		return oldStructuredDocumentRegion;
+	}
+
+	public boolean sameAs(IStructuredDocumentRegion region, int shift) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	/**
+	 */
+	public boolean sameAs(ITextRegion region, int shift) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	public boolean sameAs(ITextRegion oldRegion, IStructuredDocumentRegion documentRegion, ITextRegion newRegion, int shift) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	public void setEnded(boolean hasEnd) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	public void setLength(int newLength) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	public void setNext(IStructuredDocumentRegion newNext) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	public void setParentDocument(IStructuredDocument document) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	public void setPrevious(IStructuredDocumentRegion newPrevious) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	/**
+	 */
+	public void setRegions(ITextRegionList embeddedRegions) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	public void setStart(int newStart) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	/**
+	 * toString method
+	 * 
+	 * @return java.lang.String
+	 */
+	public String toString() {
+		StringBuffer buffer = new StringBuffer();
+		buffer.append('{');
+		int count = getStructuredDocumentRegionCount();
+		for (int i = 0; i < count; i++) {
+			if (i != 0)
+				buffer.append(',');
+			IStructuredDocumentRegion flatNode = getStructuredDocumentRegion(i);
+			if (flatNode == null)
+				buffer.append("null");//$NON-NLS-1$
+			else
+				buffer.append(flatNode.toString());
+		}
+		buffer.append('}');
+		return buffer.toString();
+	}
+
+	public StructuredDocumentEvent updateRegion(Object requester, IStructuredDocumentRegion flatnode, String changes, int start, int end) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+
+	public boolean isDeleted() {
+		// if someone "gets" these temp regions by
+		// accident, we'll always return "deleted".
+		return true;
+	}
+
+
+	public void setDeleted(boolean deleted) {
+		// do nothing
+
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/StructuredDocumentRegionManagementException.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/StructuredDocumentRegionManagementException.java
new file mode 100644
index 0000000..90fecbe
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/StructuredDocumentRegionManagementException.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+
+/**
+ */
+public class StructuredDocumentRegionManagementException extends RuntimeException {
+
+	/**
+	 * Default <code>serialVersionUID</code>
+	 */
+	private static final long serialVersionUID = 1L;
+
+	/**
+	 * StructuredDocumentRegionManagementException constructor
+	 */
+	public StructuredDocumentRegionManagementException() {
+		super("IStructuredDocumentRegion management failed.");//$NON-NLS-1$
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/StructuredDocumentRegionProxy.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/StructuredDocumentRegionProxy.java
new file mode 100644
index 0000000..5312260
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/StructuredDocumentRegionProxy.java
@@ -0,0 +1,369 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     David Carver (STAR) - bug 296999 - Inefficient use of new String()
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentEvent;
+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.ITextRegionContainer;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList;
+
+
+class StructuredDocumentRegionProxy implements IStructuredDocumentRegion {
+	private IStructuredDocumentRegion flatNode = null;
+	private int length = 0;
+
+	private int offset = 0;
+
+	/**
+	 */
+	StructuredDocumentRegionProxy() {
+		super();
+	}
+
+	/**
+	 */
+	StructuredDocumentRegionProxy(int offset, int length) {
+		super();
+
+		this.offset = offset;
+		this.length = length;
+	}
+
+	/**
+	 */
+	StructuredDocumentRegionProxy(int offset, int length, IStructuredDocumentRegion flatNode) {
+		super();
+
+		this.offset = offset;
+		this.length = length;
+		this.flatNode = flatNode;
+		if (this.flatNode != null)
+			this.offset -= this.flatNode.getStart();
+	}
+
+	public void addRegion(ITextRegion aRegion) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+
+	}
+
+	public void adjust(int i) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+
+	}
+
+	public void adjustLength(int i) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+
+	}
+
+	public void adjustStart(int i) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+
+	}
+
+	public void adjustTextLength(int i) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+
+	}
+
+	public boolean containsOffset(int i) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	public boolean containsOffset(ITextRegion region, int i) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	public void equatePositions(ITextRegion region) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+
+	}
+
+	public ITextRegion getDeepestRegionAtCharacterOffset(int offset) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	public int getEnd() {
+		int flatNodeOffset = 0;
+		if (this.flatNode != null)
+			flatNodeOffset = this.flatNode.getStart();
+		return flatNodeOffset + this.offset + this.length;
+	}
+
+	public int getEndOffset() {
+		return getEnd();
+	}
+
+	public int getEndOffset(ITextRegion containedRegion) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	public ITextRegion getFirstRegion() {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	public String getFullText() {
+		return getText();
+	}
+
+	public String getFullText(ITextRegion aRegion) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	/**
+	 */
+	public String getFullText(String context) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	public ITextRegion getLastRegion() {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	public int getLength() {
+		return this.length;
+	}
+
+	public IStructuredDocumentRegion getNext() {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	public int getNumberOfRegions() {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	int getOffset() {
+		int flatNodeOffset = 0;
+		if (this.flatNode != null)
+			flatNodeOffset = this.flatNode.getStart();
+		return flatNodeOffset + this.offset;
+	}
+
+	/**
+	 */
+	public ITextRegionContainer getParent() {
+		return null;
+	}
+
+	public IStructuredDocument getParentDocument() {
+		return null;
+		// throw new Error("intentionally not implemented since should never
+		// be called");
+	}
+
+	public IStructuredDocumentRegion getPrevious() {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	/**
+	 */
+	public ITextRegion getRegionAtCharacterOffset(int offset) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	/**
+	 */
+	public ITextRegionList getRegions() {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	/**
+	 */
+	public int getStart() {
+		int flatNodeOffset = 0;
+		if (this.flatNode != null)
+			flatNodeOffset = this.flatNode.getStart();
+		return flatNodeOffset + this.offset;
+	}
+
+	/**
+	 */
+	public int getStartOffset() {
+		return getStart();
+	}
+
+	public int getStartOffset(ITextRegion containedRegion) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	/**
+	 */
+	public IStructuredDocument getStructuredDocument() {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	/** 
+	 */
+	IStructuredDocumentRegion getStructuredDocumentRegion() {
+		return this.flatNode;
+	}
+
+	/**
+	 */
+	public String getText() {
+		if (this.flatNode == null)
+			return NodeImpl.EMPTY_STRING;
+		String text = this.flatNode.getText();
+		if (text == null)
+			return NodeImpl.EMPTY_STRING;
+		int end = this.offset + this.length;
+		return text.substring(this.offset, end);
+	}
+
+	/**
+	 */
+	public String getText(ITextRegion aRegion) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	/**
+	 */
+	public String getText(String context) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	/**
+	 */
+	public int getTextEnd() {
+		return getEnd();
+	}
+
+	/**
+	 */
+	public int getTextEndOffset() {
+		return getTextEnd();
+	}
+
+	public int getTextEndOffset(ITextRegion containedRegion) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	/**
+	 * The text length is equal to length if there is no white space at the
+	 * end of a region. Otherwise it is smaller than length.
+	 */
+	public int getTextLength() {
+		return getLength();
+	}
+
+	/**
+	 */
+	public String getType() {
+		return "StructuredDocumentRegionProxy";//$NON-NLS-1$
+	}
+
+	public boolean isDeleted() {
+		// I'll assume never really needed here
+		return true;
+	}
+
+	public boolean isEnded() {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	public boolean sameAs(IStructuredDocumentRegion region, int shift) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	/**
+	 */
+	public boolean sameAs(ITextRegion region, int shift) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	public boolean sameAs(ITextRegion oldRegion, IStructuredDocumentRegion documentRegion, ITextRegion newRegion, int shift) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	public void setDeleted(boolean deleted) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	public void setEnded(boolean hasEnd) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	/**
+	 * had to make public, due to API transition.
+	 */
+	public void setLength(int length) {
+		this.length = length;
+	}
+
+	public void setNext(IStructuredDocumentRegion newNext) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	/**
+	 */
+	void setOffset(int offset) {
+		this.offset = offset;
+		if (this.flatNode != null)
+			this.offset -= this.flatNode.getStart();
+	}
+
+	public void setParentDocument(IStructuredDocument document) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	public void setPrevious(IStructuredDocumentRegion newPrevious) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	public void setRegions(ITextRegionList embeddedRegions) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	public void setStart(int newStart) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+
+	/**
+	 */
+	void setStructuredDocumentRegion(IStructuredDocumentRegion flatNode) {
+		if (this.flatNode != null)
+			this.offset += this.flatNode.getStart();
+		this.flatNode = flatNode;
+		if (this.flatNode != null)
+			this.offset -= flatNode.getStart();
+	}
+
+	/**
+	 * toString method
+	 * 
+	 * @return java.lang.String
+	 */
+	public String toString() {
+		StringBuffer buffer = new StringBuffer();
+		buffer.append('[');
+		buffer.append(getStart());
+		buffer.append(',');
+		buffer.append(getEnd());
+		buffer.append(']');
+		buffer.append('(');
+		if (this.flatNode != null)
+			buffer.append(this.flatNode.toString());
+		else
+			buffer.append("null");//$NON-NLS-1$
+		buffer.append(')');
+		return buffer.toString();
+	}
+
+	public StructuredDocumentEvent updateRegion(Object requester, IStructuredDocumentRegion flatnode, String changes, int start, int end) {
+		throw new Error("intentionally not implemented since should never be called"); //$NON-NLS-1$
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/StructuredDocumentRegionUtil.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/StructuredDocumentRegionUtil.java
new file mode 100644
index 0000000..84a378b
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/StructuredDocumentRegionUtil.java
@@ -0,0 +1,178 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+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.ITextRegionList;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+
+
+/**
+ * Provides convenient functions to handle IStructuredDocumentRegion and
+ * ITextRegion.
+ */
+class StructuredDocumentRegionUtil {
+
+	/**
+	 * Extracts contents enclosed with quotes. Quotes may be double or single.
+	 */
+	static String getAttrValue(IStructuredDocumentRegion flatNode, ITextRegion region) {
+		if (region == null)
+			return null;
+		if (flatNode == null)
+			return null;
+		String value = flatNode.getText(region);
+		if (value == null)
+			return null;
+		int length = value.length();
+		if (length == 0)
+			return value;
+		char firstChar = value.charAt(0);
+		if (firstChar == '"' || firstChar == '\'') {
+			if (length == 1)
+				return null;
+			if (value.charAt(length - 1) == firstChar)
+				length--;
+			return value.substring(1, length);
+		}
+		return value;
+	}
+
+	/**
+	 * Extracts the name without heading '&' and tailing ';'.
+	 */
+	static String getEntityRefName(IStructuredDocumentRegion flatNode, ITextRegion region) {
+		if (region == null)
+			return null;
+		String ref = flatNode.getText(region);
+		int length = ref.length();
+		if (length == 0)
+			return ref;
+		int offset = 0;
+		if (ref.charAt(0) == '&')
+			offset = 1;
+		if (ref.charAt(length - 1) == ';')
+			length--;
+		if (offset >= length)
+			return null;
+		return ref.substring(offset, length);
+	}
+
+	/**
+	 * Returns the first region.
+	 */
+	static ITextRegion getFirstRegion(IStructuredDocumentRegion flatNode) {
+		if(flatNode instanceof StructuredDocumentRegionProxy) {
+			flatNode = ((StructuredDocumentRegionProxy)flatNode).getStructuredDocumentRegion();
+		}
+		if (flatNode == null)
+			return null;
+		ITextRegionList regions = flatNode.getRegions();
+		if (regions == null || regions.size() == 0)
+			return null;
+		return regions.get(0);
+	}
+
+	/**
+	 * Returns the type of the first region.
+	 */
+	static String getFirstRegionType(IStructuredDocumentRegion flatNode) {
+		if(flatNode instanceof StructuredDocumentRegionProxy) {
+			flatNode = ((StructuredDocumentRegionProxy)flatNode).getStructuredDocumentRegion();
+		}
+		if (flatNode == null)
+			return DOMRegionContext.UNDEFINED;
+		ITextRegionList regions = flatNode.getRegions();
+		if (regions == null || regions.size() == 0)
+			return DOMRegionContext.UNDEFINED;
+		ITextRegion region = regions.get(0);
+		return region.getType();
+	}
+
+	/**
+	 */
+	static IStructuredDocumentRegion getFirstStructuredDocumentRegion(IStructuredDocumentRegion flatNode) {
+		if (flatNode == null)
+			return null;
+		if (flatNode instanceof StructuredDocumentRegionContainer) {
+			flatNode = ((StructuredDocumentRegionContainer) flatNode).getFirstStructuredDocumentRegion();
+		}
+		if (flatNode instanceof StructuredDocumentRegionProxy) {
+			flatNode = ((StructuredDocumentRegionProxy) flatNode).getStructuredDocumentRegion();
+		}
+		return flatNode;
+	}
+
+	/**
+	 * Returns the last region.
+	 */
+	static ITextRegion getLastRegion(IStructuredDocumentRegion flatNode) {
+		if(flatNode instanceof StructuredDocumentRegionProxy) {
+			flatNode = ((StructuredDocumentRegionProxy)flatNode).getStructuredDocumentRegion();
+		}
+		if (flatNode == null)
+			return null;
+		ITextRegionList regions = flatNode.getRegions();
+		if (regions == null || regions.size() == 0)
+			return null;
+		return regions.get(regions.size() - 1);
+	}
+
+	/**
+	 * Returns the type of the first region.
+	 */
+	static String getLastRegionType(IStructuredDocumentRegion flatNode) {
+		if(flatNode instanceof StructuredDocumentRegionProxy) {
+			flatNode = ((StructuredDocumentRegionProxy)flatNode).getStructuredDocumentRegion();
+		}
+		if (flatNode == null)
+			return DOMRegionContext.UNDEFINED;
+		ITextRegionList regions = flatNode.getRegions();
+		if (regions == null || regions.size() == 0)
+			return DOMRegionContext.UNDEFINED;
+		ITextRegion region = regions.get(regions.size() - 1);
+		return region.getType();
+	}
+
+	/**
+	 */
+	static IStructuredDocumentRegion getLastStructuredDocumentRegion(IStructuredDocumentRegion flatNode) {
+		if (flatNode == null)
+			return null;
+		if (flatNode instanceof StructuredDocumentRegionContainer) {
+			flatNode = ((StructuredDocumentRegionContainer) flatNode).getLastStructuredDocumentRegion();
+		}
+		if (flatNode instanceof StructuredDocumentRegionProxy) {
+			flatNode = ((StructuredDocumentRegionProxy) flatNode).getStructuredDocumentRegion();
+		}
+		return flatNode;
+	}
+
+	/**
+	 */
+	static IStructuredDocumentRegion getStructuredDocumentRegion(IStructuredDocumentRegion flatNode) {
+		if (flatNode == null)
+			return null;
+		if (flatNode instanceof StructuredDocumentRegionProxy) {
+			flatNode = ((StructuredDocumentRegionProxy) flatNode).getStructuredDocumentRegion();
+		}
+		return flatNode;
+	}
+
+	StructuredDocumentRegionUtil() {
+		super();
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/TagAdapter.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/TagAdapter.java
new file mode 100644
index 0000000..f49ff7b
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/TagAdapter.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapter;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
+
+/**
+ */
+public interface TagAdapter extends INodeAdapter {
+
+	/**
+	 */
+	String getEndTag(IDOMElement element);
+
+	/**
+	 */
+	String getStartTag(IDOMElement element);
+
+	/**
+	 */
+	boolean isEndTag();
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/TextImpl.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/TextImpl.java
new file mode 100644
index 0000000..cad3207
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/TextImpl.java
@@ -0,0 +1,1179 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *     Balazs Banfai: Bug 154737 getUserData/setUserData support for Node
+ *     https://bugs.eclipse.org/bugs/show_bug.cgi?id=154737
+ *     David Carver (STAR) - bug 296999 - Inefficient use of new String()
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMText;
+import org.eclipse.wst.xml.core.internal.provisional.document.ISourceGenerator;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.Text;
+import org.w3c.dom.UserDataHandler;
+
+/**
+ * TextImpl class
+ */
+public class TextImpl extends CharacterDataImpl implements IDOMText {
+
+	/**
+	 */
+	private class StringPair {
+		private String fFirst = null;
+		private String fSecond = null;
+
+		StringPair(String first, String second) {
+			this.fFirst = first;
+			this.fSecond = second;
+		}
+
+		String getFirst() {
+			return this.fFirst;
+		}
+
+		String getSecond() {
+			return this.fSecond;
+		}
+	}
+
+	private String fSource = null;
+
+	/**
+	 * TextImpl constructor
+	 */
+	protected TextImpl() {
+		super();
+	}
+
+	/**
+	 * TextImpl constructor
+	 * 
+	 * @param that
+	 *            TextImpl
+	 */
+	protected TextImpl(TextImpl that) {
+		super(that);
+
+		if (that != null) {
+			this.fSource = that.getSource();
+		}
+	}
+
+	/**
+	 * appendData method
+	 * 
+	 * @param arg
+	 *            java.lang.String
+	 */
+	public void appendData(String arg) throws DOMException {
+		if (arg == null || arg.length() == 0)
+			return;
+
+		if (!isDataEditable()) {
+			throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, DOMMessages.NO_MODIFICATION_ALLOWED_ERR);
+		}
+
+		String newSource = getSource(arg);
+		if (newSource == null)
+			return;
+		String source = getSource();
+		if (source != null)
+			setTextSource(source + newSource);
+		else
+			setTextSource(newSource);
+	}
+
+	/**
+	 */
+	IStructuredDocumentRegion appendStructuredDocumentRegion(IStructuredDocumentRegion newStructuredDocumentRegion) {
+		if (newStructuredDocumentRegion == null)
+			return null;
+
+		IStructuredDocumentRegion flatNode = getStructuredDocumentRegion();
+		if (flatNode == null) {
+			setStructuredDocumentRegion(newStructuredDocumentRegion);
+			return newStructuredDocumentRegion;
+		}
+
+		if (flatNode instanceof StructuredDocumentRegionContainer) {
+			StructuredDocumentRegionContainer container = (StructuredDocumentRegionContainer) flatNode;
+			container.appendStructuredDocumentRegion(newStructuredDocumentRegion);
+		}
+		else {
+			StructuredDocumentRegionContainer container = new StructuredDocumentRegionContainer();
+			container.appendStructuredDocumentRegion(flatNode);
+			container.appendStructuredDocumentRegion(newStructuredDocumentRegion);
+			setStructuredDocumentRegion(container);
+		}
+
+		return newStructuredDocumentRegion;
+	}
+
+	/**
+	 * appendText method
+	 * 
+	 * @param text
+	 *            org.w3c.dom.Text
+	 */
+	public void appendText(Text newText) {
+		if (newText == null)
+			return;
+
+		if (!isDataEditable()) {
+			throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, DOMMessages.NO_MODIFICATION_ALLOWED_ERR);
+		}
+
+		TextImpl text = (TextImpl) newText;
+		String newSource = text.getSource();
+		if (newSource == null || newSource.length() == 0)
+			return;
+		String source = getSource();
+		if (source != null)
+			setTextSource(source + newSource);
+		else
+			setTextSource(newSource);
+	}
+
+	/**
+	 * cloneNode method
+	 * 
+	 * @return org.w3c.dom.Node
+	 * @param deep
+	 *            boolean
+	 */
+	public Node cloneNode(boolean deep) {
+		TextImpl cloned = new TextImpl(this);
+		notifyUserDataHandlers(UserDataHandler.NODE_CLONED, cloned);
+		return cloned;
+	}
+
+	/**
+	 * deleteData method
+	 * 
+	 * @param offset
+	 *            int
+	 * @param count
+	 *            int
+	 */
+	public void deleteData(int offset, int count) throws DOMException {
+		if (count == 0)
+			return;
+		if (!isDataEditable()) {
+			throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, DOMMessages.NO_MODIFICATION_ALLOWED_ERR);
+		}
+		if (count < 0 || offset < 0) {
+			throw new DOMException(DOMException.INDEX_SIZE_ERR, DOMMessages.INDEX_SIZE_ERR);
+		}
+
+		String source = getSource();
+		if (source == null || source.length() == 0) {
+			throw new DOMException(DOMException.INDEX_SIZE_ERR, DOMMessages.INDEX_SIZE_ERR);
+		}
+		StringPair pair = substringSourceExcluded(source, offset, count);
+		if (pair == null)
+			return;
+		source = null;
+		String first = pair.getFirst();
+		if (first != null)
+			source = first;
+		String second = pair.getSecond();
+		if (second != null) {
+			if (source != null)
+				source += second;
+			else
+				source = second;
+		}
+		if (source == null)
+			source = NodeImpl.EMPTY_STRING; // delete all
+		setTextSource(source);
+	}
+
+	/**
+	 * getData method
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getData() throws DOMException {
+		if (this.fSource != null)
+			return getData(this.fSource);
+		String data = super.getData();
+		if (data != null)
+			return data;
+		return getData(getStructuredDocumentRegion());
+	}
+
+	/**
+	 */
+	private String getData(IStructuredDocumentRegion flatNode) {
+		if (flatNode == null)
+			return NodeImpl.EMPTY_STRING;
+
+		if (flatNode instanceof StructuredDocumentRegionContainer) {
+			StructuredDocumentRegionContainer container = (StructuredDocumentRegionContainer) flatNode;
+			int length = container.getLength();
+			if (length < 16)
+				length = 16; // default
+			StringBuffer buffer = new StringBuffer(length);
+			int count = container.getStructuredDocumentRegionCount();
+			for (int i = 0; i < count; i++) {
+				IStructuredDocumentRegion content = container.getStructuredDocumentRegion(i);
+				String data = getData(content);
+				if (data == null)
+					continue;
+				buffer.append(data);
+			}
+			return buffer.toString();
+		}
+
+		if (flatNode instanceof StructuredDocumentRegionProxy) {
+			return flatNode.getText();
+		}
+
+		ITextRegion region = StructuredDocumentRegionUtil.getFirstRegion(flatNode);
+		if (region != null) {
+			String regionType = region.getType();
+			if (regionType == DOMRegionContext.XML_ENTITY_REFERENCE || regionType == DOMRegionContext.XML_CHAR_REFERENCE) {
+				String name = StructuredDocumentRegionUtil.getEntityRefName(flatNode, region);
+				if (name != null) {
+					DocumentImpl document = (DocumentImpl) getOwnerDocument();
+					if (document != null) {
+						String value = document.getCharValue(name);
+						if (value != null)
+							return value;
+					}
+				}
+			}
+		}
+
+		return flatNode.getText();
+	}
+
+	/**
+	 * Returns data for the source
+	 */
+	private String getData(String source) {
+		if (source == null)
+			return null;
+		StringBuffer buffer = null;
+		int offset = 0;
+		int length = source.length();
+		int ref = source.indexOf('&');
+		while (ref >= 0) {
+			int end = source.indexOf(';', ref + 1);
+			if (end > ref + 1) {
+				String name = source.substring(ref + 1, end);
+				String value = getCharValue(name);
+				if (value != null) {
+					if (buffer == null)
+						buffer = new StringBuffer(length);
+					if (ref > offset)
+						buffer.append(source.substring(offset, ref));
+					buffer.append(value);
+					offset = end + 1;
+					ref = end;
+				}
+			}
+			ref = source.indexOf('&', ref + 1);
+		}
+		if (buffer == null)
+			return source;
+		if (length > offset)
+			buffer.append(source.substring(offset));
+		return buffer.toString();
+	}
+
+	/**
+	 * getFirstStructuredDocumentRegion method
+	 * 
+	 */
+	public IStructuredDocumentRegion getFirstStructuredDocumentRegion() {
+		return StructuredDocumentRegionUtil.getFirstStructuredDocumentRegion(getStructuredDocumentRegion());
+	}
+
+	/**
+	 * getLastStructuredDocumentRegion method
+	 * 
+	 */
+	public IStructuredDocumentRegion getLastStructuredDocumentRegion() {
+		return StructuredDocumentRegionUtil.getLastStructuredDocumentRegion(getStructuredDocumentRegion());
+	}
+
+	/**
+	 * getNodeName method
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getNodeName() {
+		return "#text";//$NON-NLS-1$
+	}
+
+	/**
+	 * getNodeType method
+	 * 
+	 * @return short
+	 */
+	public short getNodeType() {
+		return TEXT_NODE;
+	}
+
+	/**
+	 */
+	public String getSource() {
+		if (this.fSource != null)
+			return this.fSource;
+		String data = super.getData();
+		if (data != null && data.length() > 0) {
+			String source = getSource(data);
+			if (source != null)
+				return source;
+		}
+		return super.getSource();
+	}
+
+	/**
+	 * Returns source for the data
+	 */
+	private String getSource(String data) {
+		if (data == null)
+			return null;
+		IDOMModel model = getModel();
+		if (model == null)
+			return null; // error
+		ISourceGenerator generator = model.getGenerator();
+		if (generator == null)
+			return null; // error
+		return generator.generateTextData(this, data);
+	}
+
+	/**
+	 */
+	String getTextSource() {
+		return this.fSource;
+	}
+
+	/**
+	 */
+	public String getValueSource() {
+		return getSource();
+	}
+
+	/**
+	 */
+	boolean hasStructuredDocumentRegion(IStructuredDocumentRegion askedStructuredDocumentRegion) {
+		if (askedStructuredDocumentRegion == null)
+			return false;
+
+		IStructuredDocumentRegion flatNode = getStructuredDocumentRegion();
+		if (flatNode == null)
+			return false;
+
+		if (flatNode == askedStructuredDocumentRegion)
+			return true;
+
+		if (flatNode instanceof StructuredDocumentRegionProxy) {
+			StructuredDocumentRegionProxy proxy = (StructuredDocumentRegionProxy) flatNode;
+			if (proxy.getStructuredDocumentRegion() == askedStructuredDocumentRegion)
+				return true;
+			return false;
+		}
+
+		if (flatNode instanceof StructuredDocumentRegionContainer) {
+			StructuredDocumentRegionContainer container = (StructuredDocumentRegionContainer) flatNode;
+			int count = container.getStructuredDocumentRegionCount();
+			for (int i = 0; i < count; i++) {
+				IStructuredDocumentRegion content = container.getStructuredDocumentRegion(i);
+				if (content == null)
+					continue;
+				if (content == askedStructuredDocumentRegion)
+					return true;
+				if (content instanceof StructuredDocumentRegionProxy) {
+					StructuredDocumentRegionProxy proxy = (StructuredDocumentRegionProxy) content;
+					if (proxy.getStructuredDocumentRegion() == askedStructuredDocumentRegion)
+						return true;
+				}
+			}
+			return false;
+		}
+
+		return false;
+	}
+
+	/**
+	 * insertData method
+	 * 
+	 * @param offset
+	 *            int
+	 * @param arg
+	 *            java.lang.String
+	 */
+	public void insertData(int offset, String arg) throws DOMException {
+		if (arg == null || arg.length() == 0)
+			return;
+		if (!isDataEditable()) {
+			throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, DOMMessages.NO_MODIFICATION_ALLOWED_ERR);
+		}
+		if (offset < 0) {
+			throw new DOMException(DOMException.INDEX_SIZE_ERR, DOMMessages.INDEX_SIZE_ERR);
+		}
+
+		String source = getSource();
+		if (source == null || source.length() == 0) {
+			if (offset > 0) {
+				throw new DOMException(DOMException.INDEX_SIZE_ERR, DOMMessages.INDEX_SIZE_ERR);
+			}
+			source = getSource(arg);
+			if (source != null)
+				setTextSource(source);
+			return;
+		}
+
+		StringPair pair = substringSourceExcluded(source, offset, 0);
+		if (pair == null)
+			return; // error
+		StringBuffer buffer = new StringBuffer(source.length() + arg.length());
+		String first = pair.getFirst();
+		if (first != null)
+			buffer.append(first);
+		source = getSource(arg);
+		if (source != null)
+			buffer.append(source);
+		String second = pair.getSecond();
+		if (second != null)
+			buffer.append(second);
+		setTextSource(buffer.toString());
+	}
+
+	/**
+	 */
+	IStructuredDocumentRegion insertStructuredDocumentRegion(IStructuredDocumentRegion newStructuredDocumentRegion, IStructuredDocumentRegion nextStructuredDocumentRegion) {
+		if (newStructuredDocumentRegion == null)
+			return null;
+		if (nextStructuredDocumentRegion == null)
+			return appendStructuredDocumentRegion(newStructuredDocumentRegion);
+
+		IStructuredDocumentRegion flatNode = getStructuredDocumentRegion();
+		if (flatNode == null)
+			return null; // error
+
+		if (flatNode == nextStructuredDocumentRegion) {
+			StructuredDocumentRegionContainer container = new StructuredDocumentRegionContainer();
+			container.appendStructuredDocumentRegion(newStructuredDocumentRegion);
+			container.appendStructuredDocumentRegion(flatNode);
+			setStructuredDocumentRegion(container);
+			return newStructuredDocumentRegion;
+		}
+
+		if (flatNode instanceof StructuredDocumentRegionContainer) {
+			StructuredDocumentRegionContainer container = (StructuredDocumentRegionContainer) flatNode;
+			int count = container.getStructuredDocumentRegionCount();
+			for (int i = 0; i < count; i++) {
+				IStructuredDocumentRegion content = container.getStructuredDocumentRegion(i);
+				if (content == nextStructuredDocumentRegion) {
+					container.insertStructuredDocumentRegion(newStructuredDocumentRegion, i);
+					return newStructuredDocumentRegion;
+				}
+			}
+			return null; // error
+		}
+
+		return null; // error
+	}
+
+	/**
+	 * insertText method
+	 * 
+	 * @param text
+	 *            org.w3c.dom.Text
+	 * @param offset
+	 *            int
+	 */
+	public void insertText(Text newText, int offset) throws DOMException {
+		if (newText == null)
+			return;
+		if (!isDataEditable()) {
+			throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, DOMMessages.NO_MODIFICATION_ALLOWED_ERR);
+		}
+		TextImpl text = (TextImpl) newText;
+		String newSource = text.getSource();
+		if (newSource == null || newSource.length() == 0)
+			return;
+		if (offset < 0) {
+			throw new DOMException(DOMException.INDEX_SIZE_ERR, DOMMessages.INDEX_SIZE_ERR);
+		}
+
+		String source = getSource();
+		if (source == null || source.length() == 0) {
+			if (offset > 0) {
+				throw new DOMException(DOMException.INDEX_SIZE_ERR, DOMMessages.INDEX_SIZE_ERR);
+			}
+			setTextSource(newSource);
+			return;
+		}
+
+		StringPair pair = substringSourceExcluded(source, offset, 0);
+		if (pair == null)
+			return; // error
+		StringBuffer buffer = new StringBuffer(source.length() + newSource.length());
+		String first = pair.getFirst();
+		if (first != null)
+			buffer.append(first);
+		buffer.append(newSource);
+		String second = pair.getSecond();
+		if (second != null)
+			buffer.append(second);
+		setTextSource(buffer.toString());
+	}
+
+	/**
+	 * isCDATAContent method
+	 * 
+	 * @return boolean
+	 */
+	public boolean isCDATAContent() {
+		Node parent = getParentNode();
+		if (parent == null || parent.getNodeType() != Node.ELEMENT_NODE)
+			return false;
+		ElementImpl element = (ElementImpl) parent;
+		return element.isCDATAContainer();
+	}
+
+	/**
+	 */
+	public boolean isInvalid() {
+		return isInvalid(getStructuredDocumentRegion());
+	}
+
+	/**
+	 */
+	private boolean isInvalid(IStructuredDocumentRegion flatNode) {
+		if (flatNode == null)
+			return false;
+
+		if (flatNode instanceof StructuredDocumentRegionContainer) {
+			StructuredDocumentRegionContainer container = (StructuredDocumentRegionContainer) flatNode;
+			int count = container.getStructuredDocumentRegionCount();
+			for (int i = 0; i < count; i++) {
+				IStructuredDocumentRegion content = container.getStructuredDocumentRegion(i);
+				if (isInvalid(content))
+					return true;
+			}
+			return false;
+		}
+
+		if (flatNode instanceof StructuredDocumentRegionProxy) {
+			StructuredDocumentRegionProxy proxy = (StructuredDocumentRegionProxy) flatNode;
+			return isInvalid(proxy.getStructuredDocumentRegion());
+		}
+
+		String regionType = StructuredDocumentRegionUtil.getFirstRegionType(flatNode);
+		if (regionType != DOMRegionContext.XML_CONTENT && isNotNestedContent(regionType) && regionType != DOMRegionContext.XML_ENTITY_REFERENCE && regionType != DOMRegionContext.XML_CHAR_REFERENCE && regionType != DOMRegionContext.BLOCK_TEXT && regionType != DOMRegionContext.WHITE_SPACE) {
+			return true;
+		}
+
+		return false;
+	}
+
+	protected boolean isNotNestedContent(String regionType) {
+		boolean result = true;
+		return result;
+	}
+
+	/**
+	 */
+	boolean isSharingStructuredDocumentRegion(IStructuredDocumentRegion sharedStructuredDocumentRegion) {
+		if (sharedStructuredDocumentRegion == null)
+			return false;
+
+		IStructuredDocumentRegion flatNode = getStructuredDocumentRegion();
+		if (flatNode == null)
+			return false;
+
+		if (flatNode == sharedStructuredDocumentRegion)
+			return false;
+
+		if (flatNode instanceof StructuredDocumentRegionProxy) {
+			StructuredDocumentRegionProxy proxy = (StructuredDocumentRegionProxy) flatNode;
+			if (proxy.getStructuredDocumentRegion() == sharedStructuredDocumentRegion)
+				return true;
+			return false;
+		}
+
+		if (flatNode instanceof StructuredDocumentRegionContainer) {
+			StructuredDocumentRegionContainer container = (StructuredDocumentRegionContainer) flatNode;
+			int count = container.getStructuredDocumentRegionCount();
+			for (int i = 0; i < count; i++) {
+				IStructuredDocumentRegion content = container.getStructuredDocumentRegion(i);
+				if (content == null)
+					continue;
+				if (content == sharedStructuredDocumentRegion)
+					return false;
+				if (content instanceof StructuredDocumentRegionProxy) {
+					StructuredDocumentRegionProxy proxy = (StructuredDocumentRegionProxy) content;
+					if (proxy.getStructuredDocumentRegion() == sharedStructuredDocumentRegion)
+						return true;
+				}
+			}
+			return false;
+		}
+
+		return false;
+	}
+
+	/**
+	 * Returns whether this text node contains <a
+	 * href='http://www.w3.org/TR/2004/REC-xml-infoset-20040204#infoitem.character'>
+	 * element content whitespace</a>, often abusively called "ignorable
+	 * whitespace". The text node is determined to contain whitespace in
+	 * element content during the load of the document or if validation occurs
+	 * while using <code>Document.normalizeDocument()</code>.
+	 * 
+	 * @see DOM Level 3
+	 */
+	public boolean isElementContentWhitespace() {
+		return isWhitespace();
+	}
+
+	/**
+	 */
+	public boolean isWhitespace() {
+		String data = getData();
+		if (data == null)
+			return true;
+		int length = data.length();
+		for (int i = 0; i < length; i++) {
+			if (!Character.isWhitespace(data.charAt(i)))
+				return false;
+		}
+		return true;
+	}
+
+	/**
+	 */
+	IStructuredDocumentRegion removeStructuredDocumentRegion(IStructuredDocumentRegion oldStructuredDocumentRegion) {
+		if (oldStructuredDocumentRegion == null)
+			return null;
+
+		IStructuredDocumentRegion flatNode = getStructuredDocumentRegion();
+		if (flatNode == null)
+			return null; // error
+
+		if (flatNode == oldStructuredDocumentRegion) {
+			setStructuredDocumentRegion(null);
+			return oldStructuredDocumentRegion;
+		}
+
+		if (flatNode instanceof StructuredDocumentRegionProxy) {
+			StructuredDocumentRegionProxy proxy = (StructuredDocumentRegionProxy) flatNode;
+			if (proxy.getStructuredDocumentRegion() == oldStructuredDocumentRegion) {
+				// removed with proxy
+				setStructuredDocumentRegion(null);
+				return oldStructuredDocumentRegion;
+			}
+			return null; // error
+		}
+
+		if (flatNode instanceof StructuredDocumentRegionContainer) {
+			StructuredDocumentRegionContainer container = (StructuredDocumentRegionContainer) flatNode;
+			int count = container.getStructuredDocumentRegionCount();
+			for (int i = 0; i < count; i++) {
+				IStructuredDocumentRegion content = container.getStructuredDocumentRegion(i);
+				if (content == oldStructuredDocumentRegion) {
+					container.removeStructuredDocumentRegion(i);
+					if (container.getStructuredDocumentRegionCount() == 1) {
+						// get back to single IStructuredDocumentRegion
+						setStructuredDocumentRegion(container.getStructuredDocumentRegion(0));
+					}
+					return oldStructuredDocumentRegion;
+				}
+
+				if (content instanceof StructuredDocumentRegionProxy) {
+					StructuredDocumentRegionProxy proxy = (StructuredDocumentRegionProxy) content;
+					if (proxy.getStructuredDocumentRegion() == oldStructuredDocumentRegion) {
+						// removed with proxy
+						container.removeStructuredDocumentRegion(i);
+						if (container.getStructuredDocumentRegionCount() == 1) {
+							// get back to single IStructuredDocumentRegion
+							setStructuredDocumentRegion(container.getStructuredDocumentRegion(0));
+						}
+						return oldStructuredDocumentRegion;
+					}
+				}
+			}
+			return null; // error
+		}
+
+		return null; // error
+	}
+
+	/**
+	 * replaceData method
+	 * 
+	 * @param offset
+	 *            int
+	 * @param count
+	 *            int
+	 * @param arg
+	 *            java.lang.String
+	 */
+	public void replaceData(int offset, int count, String arg) throws DOMException {
+		if (!isDataEditable()) {
+			throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, DOMMessages.NO_MODIFICATION_ALLOWED_ERR);
+		}
+		if (arg == null || arg.length() == 0) {
+			deleteData(offset, count);
+			return;
+		}
+		if (count == 0) {
+			insertData(offset, arg);
+			return;
+		}
+		if (offset < 0 || count < 0) {
+			throw new DOMException(DOMException.INDEX_SIZE_ERR, DOMMessages.INDEX_SIZE_ERR);
+		}
+
+		String source = getSource();
+		if (source == null || source.length() == 0) {
+			throw new DOMException(DOMException.INDEX_SIZE_ERR, DOMMessages.INDEX_SIZE_ERR);
+		}
+
+		StringPair pair = substringSourceExcluded(source, offset, count);
+		if (pair == null)
+			return; // error
+		StringBuffer buffer = new StringBuffer(source.length() + arg.length());
+		String first = pair.getFirst();
+		if (first != null)
+			buffer.append(first);
+		source = getSource(arg);
+		if (source != null)
+			buffer.append(source);
+		String second = pair.getSecond();
+		if (second != null)
+			buffer.append(second);
+		setTextSource(buffer.toString());
+	}
+
+	/**
+	 */
+	IStructuredDocumentRegion replaceStructuredDocumentRegion(IStructuredDocumentRegion newStructuredDocumentRegion, IStructuredDocumentRegion oldStructuredDocumentRegion) {
+		if (oldStructuredDocumentRegion == null)
+			return null;
+		if (newStructuredDocumentRegion == null)
+			return removeStructuredDocumentRegion(oldStructuredDocumentRegion);
+
+		IStructuredDocumentRegion flatNode = getStructuredDocumentRegion();
+		if (flatNode == null)
+			return null; // error
+
+		if (flatNode == oldStructuredDocumentRegion) {
+			setStructuredDocumentRegion(newStructuredDocumentRegion);
+			return oldStructuredDocumentRegion;
+		}
+
+		if (flatNode instanceof StructuredDocumentRegionProxy) {
+			StructuredDocumentRegionProxy proxy = (StructuredDocumentRegionProxy) flatNode;
+			if (proxy.getStructuredDocumentRegion() == oldStructuredDocumentRegion) {
+				if (newStructuredDocumentRegion instanceof StructuredDocumentRegionProxy) {
+					// proxy must not be nested
+					setStructuredDocumentRegion(newStructuredDocumentRegion);
+				}
+				else {
+					proxy.setStructuredDocumentRegion(newStructuredDocumentRegion);
+				}
+				return oldStructuredDocumentRegion;
+			}
+			return null; // error
+		}
+
+		if (flatNode instanceof StructuredDocumentRegionContainer) {
+			StructuredDocumentRegionContainer container = (StructuredDocumentRegionContainer) flatNode;
+			int count = container.getStructuredDocumentRegionCount();
+			for (int i = 0; i < count; i++) {
+				IStructuredDocumentRegion content = container.getStructuredDocumentRegion(i);
+				if (content == null)
+					continue; // error
+				if (content == oldStructuredDocumentRegion) {
+					container.replaceStructuredDocumentRegion(newStructuredDocumentRegion, i);
+					return oldStructuredDocumentRegion;
+				}
+
+				if (content instanceof StructuredDocumentRegionProxy) {
+					StructuredDocumentRegionProxy proxy = (StructuredDocumentRegionProxy) content;
+					if (proxy.getStructuredDocumentRegion() == oldStructuredDocumentRegion) {
+						if (newStructuredDocumentRegion instanceof StructuredDocumentRegionProxy) {
+							// proxy must not be nested
+							container.replaceStructuredDocumentRegion(newStructuredDocumentRegion, i);
+						}
+						else {
+							proxy.setStructuredDocumentRegion(newStructuredDocumentRegion);
+						}
+						return oldStructuredDocumentRegion;
+					}
+				}
+			}
+			return null; // error
+		}
+
+		return null; // error
+	}
+
+	/**
+	 */
+	void resetStructuredDocumentRegions() {
+		String source = getSource();
+		if (source != null && source.length() > 0)
+			this.fSource = source;
+		super.resetStructuredDocumentRegions();
+	}
+
+	/**
+	 * getData method
+	 * 
+	 * @return java.lang.String
+	 */
+	public void setData(String data) throws DOMException {
+		if (!isDataEditable()) {
+			throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, DOMMessages.NO_MODIFICATION_ALLOWED_ERR);
+		}
+
+		this.fSource = null;
+		super.setData(data);
+	}
+
+	/**
+	 */
+	public void setSource(String source) throws InvalidCharacterException {
+		if (!isDataEditable()) {
+			throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, DOMMessages.NO_MODIFICATION_ALLOWED_ERR);
+		}
+
+		SourceValidator validator = new SourceValidator(this);
+		if (validator.validateSource(source))
+			setTextSource(source);
+	}
+
+	/**
+	 */
+	void setStructuredDocumentRegion(IStructuredDocumentRegion flatNode) {
+		super.setStructuredDocumentRegion(flatNode);
+		if (flatNode != null)
+			this.fSource = null;
+	}
+
+	/**
+	 */
+	public void setTextSource(String source) {
+		if (!isDataEditable()) {
+			throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, DOMMessages.NO_MODIFICATION_ALLOWED_ERR);
+		}
+
+		this.fSource = source;
+
+		notifyValueChanged();
+	}
+
+	/**
+	 */
+	public void setValueSource(String source) {
+		if (!isDataEditable()) {
+			throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, DOMMessages.NO_MODIFICATION_ALLOWED_ERR);
+		}
+
+		SourceValidator validator = new SourceValidator(this);
+		setTextSource(validator.convertSource(source));
+	}
+
+	/**
+	 * splitText method
+	 * 
+	 * @return org.w3c.dom.Text
+	 * @param offset
+	 *            int
+	 */
+	public Text splitText(int offset) throws DOMException {
+		if (!isDataEditable()) {
+			throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, DOMMessages.NO_MODIFICATION_ALLOWED_ERR);
+		}
+		if (offset < 0) {
+			throw new DOMException(DOMException.INDEX_SIZE_ERR, DOMMessages.INDEX_SIZE_ERR);
+		}
+		int length = getLength();
+		if (offset > length) {
+			throw new DOMException(DOMException.INDEX_SIZE_ERR, DOMMessages.INDEX_SIZE_ERR);
+		}
+		Document document = getOwnerDocument();
+		if (document == null)
+			return null;
+
+		String source = null;
+		if (offset < length) {
+			int count = length - offset;
+			source = substringSource(offset, count);
+			deleteData(offset, count);
+		}
+		TextImpl text = (TextImpl) document.createTextNode(null);
+		if (source != null)
+			text.setTextSource(source);
+
+		Node parent = getParentNode();
+		if (parent != null)
+			parent.insertBefore(text, getNextSibling());
+
+		return text;
+	}
+
+	/**
+	 */
+	Text splitText(IStructuredDocumentRegion nextStructuredDocumentRegion) {
+		if (nextStructuredDocumentRegion == null)
+			return null;
+
+		IStructuredDocumentRegion flatNode = getStructuredDocumentRegion();
+		if (flatNode == null || !(flatNode instanceof StructuredDocumentRegionContainer))
+			return null; // error
+
+		StructuredDocumentRegionContainer container = (StructuredDocumentRegionContainer) flatNode;
+		int count = container.getStructuredDocumentRegionCount();
+		int index = 0;
+		for (; index < count; index++) {
+			if (container.getStructuredDocumentRegion(index) == nextStructuredDocumentRegion)
+				break;
+		}
+		if (index >= count) {
+			// this is the case nextStructuredDocumentRegion is a new
+			// IStructuredDocumentRegion
+			// search gap by offset
+			int offset = nextStructuredDocumentRegion.getStart();
+			for (index = 0; index < count; index++) {
+				IStructuredDocumentRegion content = container.getStructuredDocumentRegion(index);
+				if (content == null)
+					continue; // error
+				if (content.getStart() >= offset)
+					break;
+			}
+			if (index >= count)
+				return null; // error
+		}
+		if (index == 0)
+			return this; // nothing to do
+
+		Document document = getOwnerDocument();
+		if (document == null)
+			return null; // error
+		Node parent = getParentNode();
+		if (parent == null)
+			return null; // error
+		TextImpl nextText = (TextImpl) document.createTextNode(null);
+		if (nextText == null)
+			return null; // error
+
+		for (; index < count; count--) {
+			nextText.appendStructuredDocumentRegion(container.removeStructuredDocumentRegion(index));
+		}
+
+		// normalize IStructuredDocumentRegion
+		if (index == 1) {
+			setStructuredDocumentRegion(container.getStructuredDocumentRegion(0));
+		}
+
+		parent.insertBefore(nextText, getNextSibling());
+		return nextText;
+	}
+
+	/**
+	 * Retruns data for the range
+	 */
+	private String substringData(String data, int offset, int count) throws DOMException {
+		// sure offset and count are non-negative
+		if (count == 0)
+			return NodeImpl.EMPTY_STRING;
+		if (data == null) {
+			throw new DOMException(DOMException.INDEX_SIZE_ERR, DOMMessages.INDEX_SIZE_ERR);
+		}
+		int length = data.length();
+		if (offset > length) {
+			throw new DOMException(DOMException.INDEX_SIZE_ERR, DOMMessages.INDEX_SIZE_ERR);
+		}
+		int end = offset + count;
+		if (end > length) {
+			throw new DOMException(DOMException.INDEX_SIZE_ERR, DOMMessages.INDEX_SIZE_ERR);
+		}
+		return data.substring(offset, end);
+	}
+
+	/**
+	 * Returns source for the range specified by: offset: data offset count:
+	 * data count
+	 */
+	private String substringSource(int offset, int count) throws DOMException {
+		// sure offset and count are non-negative
+		if (this.fSource != null)
+			return substringSource(this.fSource, offset, count);
+
+		String data = super.getData();
+		if (data != null && data.length() > 0) {
+			data = substringData(data, offset, count);
+			if (data == null)
+				return NodeImpl.EMPTY_STRING;
+			String source = getSource(data);
+			if (source != null)
+				return source;
+		}
+
+		return substringSource(getSource(), offset, count);
+	}
+
+	/**
+	 * Returns source for the range specified by: offset: data offset count:
+	 * data count
+	 */
+	private String substringSource(String source, int offset, int count) throws DOMException {
+		// sure offset and count are non-negative
+		if (count == 0)
+			return NodeImpl.EMPTY_STRING;
+		if (source == null) {
+			throw new DOMException(DOMException.INDEX_SIZE_ERR, DOMMessages.INDEX_SIZE_ERR);
+		}
+
+		int length = source.length();
+		int end = offset + count;
+
+		// find character reference
+		int ref = source.indexOf('&');
+		while (ref >= 0) {
+			if (ref >= end)
+				break;
+			int refEnd = source.indexOf(';', ref + 1);
+			if (refEnd > ref + 1) {
+				String name = source.substring(ref + 1, refEnd);
+				if (getCharValue(name) != null) {
+					// found, shift for source offsets
+					int refCount = refEnd - ref;
+					if (ref < offset)
+						offset += refCount;
+					if (ref < end)
+						end += refCount;
+					ref = refEnd;
+				}
+			}
+			ref = source.indexOf('&', ref + 1);
+		}
+
+		if (offset > length || end > length) {
+			throw new DOMException(DOMException.INDEX_SIZE_ERR, DOMMessages.INDEX_SIZE_ERR);
+		}
+
+		return source.substring(offset, end);
+	}
+
+	/**
+	 * Returns sources before and after the range specified by: offset: data
+	 * offset count: data count
+	 */
+	private StringPair substringSourceExcluded(String source, int offset, int count) throws DOMException {
+		// sure offset and count are non-negative
+		if (source == null) {
+			if (offset == 0 && count == 0)
+				return new StringPair(null, null);
+			throw new DOMException(DOMException.INDEX_SIZE_ERR, DOMMessages.INDEX_SIZE_ERR);
+		}
+
+		int length = source.length();
+		int end = offset + count;
+
+		// find character reference
+		int ref = source.indexOf('&');
+		while (ref >= 0) {
+			if (ref >= end)
+				break;
+			int refEnd = source.indexOf(';', ref + 1);
+			if (refEnd > ref + 1) {
+				String name = source.substring(ref + 1, refEnd);
+				if (getCharValue(name) != null) {
+					// found, shift for source offsets
+					int refCount = refEnd - ref;
+					if (ref < offset)
+						offset += refCount;
+					if (ref < end)
+						end += refCount;
+					ref = refEnd;
+				}
+			}
+			ref = source.indexOf('&', ref + 1);
+		}
+
+		if (offset > length || end > length) {
+			throw new DOMException(DOMException.INDEX_SIZE_ERR, DOMMessages.INDEX_SIZE_ERR);
+		}
+
+		String first = (offset > 0 ? source.substring(0, offset) : null);
+		String second = (end < length ? source.substring(end, length) : null);
+		return new StringPair(first, second);
+	}
+
+	public String getWholeText() {
+		throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Not Implemented in this version."); //$NON-NLS-1$
+	}
+    /**
+	 * Replaces the text of the current node and all logically-adjacent text
+	 * nodes with the specified text. All logically-adjacent text nodes are
+	 * removed including the current node unless it was the recipient of the
+	 * replacement text. <br>
+	 * This method returns the node which received the replacement text. The
+	 * returned node is:
+	 * <ul>
+	 * <li><code>null</code>, when the replacement text is the empty
+	 * string; </li>
+	 * <li>the current node, except when the current node is read-only; </li>
+	 * <li> a new <code>Text</code> node of the same type (
+	 * <code>Text</code> or <code>CDATASection</code>) as the current
+	 * node inserted at the location of the replacement. </li>
+	 * </ul>
+	 * <br>
+	 * For instance, in the above example calling
+	 * <code>replaceWholeText</code> on the <code>Text</code> node that
+	 * contains "bar" with "yo" in argument results in the following: <br>
+	 * Where the nodes to be removed are read-only descendants of an
+	 * <code>EntityReference</code>, the <code>EntityReference</code>
+	 * must be removed instead of the read-only nodes. If any
+	 * <code>EntityReference</code> to be removed has descendants that are
+	 * not <code>EntityReference</code>, <code>Text</code>, or
+	 * <code>CDATASection</code> nodes, the <code>replaceWholeText</code>
+	 * method must fail before performing any modification of the document,
+	 * raising a <code>DOMException</code> with the code
+	 * <code>NO_MODIFICATION_ALLOWED_ERR</code>. <br>
+	 * For instance, in the example below calling
+	 * <code>replaceWholeText</code> on the <code>Text</code> node that
+	 * contains "bar" fails, because the <code>EntityReference</code> node
+	 * "ent" contains an <code>Element</code> node which cannot be removed.
+	 * 
+	 * @param content
+	 *            The content of the replacing <code>Text</code> node.
+	 * @return The <code>Text</code> node created with the specified
+	 *         content.
+	 * @exception DOMException
+	 *                NO_MODIFICATION_ALLOWED_ERR: Raised if one of the
+	 *                <code>Text</code> nodes being replaced is readonly.
+	 * @see DOM Level 3
+	 */
+    public Text replaceWholeText(String content)
+                                 throws DOMException {
+		throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Not implemented"); //$NON-NLS-1$
+    }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/UserData.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/UserData.java
new file mode 100644
index 0000000..695ff71
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/UserData.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.WeakHashMap;
+
+import org.w3c.dom.Node;
+
+/**
+ * Collects user data associated to a Node.
+ * 
+ */
+final class UserData {
+
+	private static UserData fInstance;
+
+	/**
+	 * Mapping of a Node to its User Data table (represented by a Map)
+	 */
+	private Map fData;
+
+	private UserData() {
+		fData = new WeakHashMap(0);
+	}
+
+	public static synchronized UserData getInstance() {
+		if (fInstance == null)
+			fInstance = new UserData();
+		return fInstance;
+	}
+
+	/**
+	 * Get the user data table associated with <code>node</code>.
+	 * 
+	 * @param node the node
+	 * @return the user data table associated with the <code>node</code>
+	 */
+	public synchronized Map getUserDataTable(Node node) {
+		if (fData.containsKey(node))
+			return (Map) fData.get(node);
+		Map table = new HashMap();
+		fData.put(node, table);
+		return table;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/XMLGeneratorImpl.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/XMLGeneratorImpl.java
new file mode 100644
index 0000000..17c7eb9
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/XMLGeneratorImpl.java
@@ -0,0 +1,735 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import org.eclipse.wst.xml.core.internal.commentelement.impl.CommentElementRegistry;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+import org.eclipse.wst.xml.core.internal.provisional.IXMLCharEntity;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMAttr;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.eclipse.wst.xml.core.internal.provisional.document.ISourceGenerator;
+import org.w3c.dom.Attr;
+import org.w3c.dom.CDATASection;
+import org.w3c.dom.Comment;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Element;
+import org.w3c.dom.EntityReference;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.ProcessingInstruction;
+import org.w3c.dom.Text;
+
+
+/** 
+ */
+public class XMLGeneratorImpl implements ISourceGenerator {
+	private static final String CDATA_CLOSE = "]]>";//$NON-NLS-1$
+	private static final String CDATA_OPEN = "<![CDATA[";//$NON-NLS-1$
+	private static final String COMMENT_CLOSE = "-->";//$NON-NLS-1$
+	private static final String COMMENT_OPEN = "<!--";//$NON-NLS-1$
+	private static final String DOCTYPE_OPEN = "<!DOCTYPE";//$NON-NLS-1$
+	private static final String EMPTY_CLOSE = " />";//$NON-NLS-1$
+	private static final String END_OPEN = "</";//$NON-NLS-1$
+
+	private static XMLGeneratorImpl instance = null;
+	private static final String PI_CLOSE = "?>";//$NON-NLS-1$
+	private static final String PI_OPEN = "<?";//$NON-NLS-1$
+	private static final String PUBLIC_ID = "PUBLIC";//$NON-NLS-1$
+	private static final String SSI_PREFIX = "ssi";//$NON-NLS-1$
+	//private static final String SSI_FEATURE = "SSI";//$NON-NLS-1$
+	private static final String SSI_TOKEN = "#";//$NON-NLS-1$
+	private static final String SYSTEM_ID = "SYSTEM";//$NON-NLS-1$
+	private static final String TAG_CLOSE = ">";//$NON-NLS-1$
+
+	/**
+	 */
+	public synchronized static ISourceGenerator getInstance() {
+		if (instance == null)
+			instance = new XMLGeneratorImpl();
+		return instance;
+	}
+
+	/**
+	 */
+	//private boolean isCommentTag(XMLElement element) {
+	//	if (element == null) return false;
+	//	DocumentImpl document = (DocumentImpl)element.getOwnerDocument();
+	//	if (document == null) return false;
+	//	DocumentTypeAdapter adapter = document.getDocumentTypeAdapter();
+	//	if (adapter == null) return false;
+	//	if (!adapter.hasFeature(SSI_FEATURE)) return false;
+	//	String prefix = element.getPrefix();
+	//	return (prefix != null && prefix.equals(SSI_PREFIX));
+	//}
+	/**
+	 * Helper to modify the tag name in sub-classes
+	 */
+	private static void setTagName(Element element, String tagName) {
+		if (element == null || tagName == null)
+			return;
+		((ElementImpl) element).setTagName(tagName);
+	}
+
+	/**
+	 * XMLModelGenerator constructor
+	 */
+	private XMLGeneratorImpl() {
+		super();
+	}
+
+	/**
+	 */
+	public String generateAttrName(Attr attr) {
+		if (attr == null)
+			return null;
+		String attrName = attr.getName();
+		if (attrName == null)
+			return null;
+		if (attrName.startsWith(JSPTag.TAG_OPEN)) {
+			if (!attrName.endsWith(JSPTag.TAG_CLOSE)) {
+				// close JSP
+				return (attrName + JSPTag.TAG_CLOSE);
+			}
+		}
+		if (((IDOMAttr) attr).isGlobalAttr() && CMNodeUtil.getAttributeDeclaration(attr) != null) {
+			switch (getAttrNameCase(attr)) {
+				case DocumentTypeAdapter.UPPER_CASE :
+					attrName = attrName.toUpperCase();
+					break;
+				case DocumentTypeAdapter.LOWER_CASE :
+					attrName = attrName.toLowerCase();
+					break;
+				default :
+					// ASIS_CASE
+					break;
+			}
+		}
+		return attrName;
+	}
+
+	/**
+	 */
+	public String generateAttrValue(Attr attr) {
+		return generateAttrValue(attr, (char) 0); // no quote preference
+	}
+
+	/**
+	 */
+	public String generateAttrValue(Attr attr, char quote) {
+		if (attr == null)
+			return null;
+		String name = attr.getName();
+		SourceValidator validator = new SourceValidator(attr);
+		String value = validator.convertSource(((IDOMNode) attr).getValueSource());
+		if (value == null || value.length() == 0) {
+			if (name != null && name.startsWith(JSPTag.TAG_OPEN))
+				return null;
+			if (isBooleanAttr(attr)) {
+				if (((AttrImpl) attr).isXMLAttr()) {
+					// generate the name as value
+					value = attr.getName();
+				} else {
+					// not to generate '=' and value for HTML boolean
+					return null;
+				}
+			}
+		}
+		return generateAttrValue(value, quote);
+	}
+
+	/**
+	 */
+	public String generateAttrValue(String value, char quote) {
+		// assume the valid is already validated not to include both quotes
+		if (quote == '"') {
+			if ((value != null) && (value.indexOf('"') >= 0))
+				quote = '\''; // force
+		} else if (quote == '\'') {
+			if ((value != null) && (value.indexOf('\'') >= 0))
+				quote = '"'; // force
+		} else { // no preference
+			if ((value != null) && (value.indexOf('"') < 0))
+				quote = '"';
+			else
+				quote = '\'';
+		}
+
+		int length = (value == null ? 0 : value.length());
+		StringBuffer buffer = new StringBuffer(length + 2);
+		buffer.append(quote);
+		if (value != null)
+			buffer.append(value);
+		buffer.append(quote);
+		return buffer.toString();
+	}
+
+	/**
+	 * generateCDATASection method
+	 * 
+	 * @return java.lang.String
+	 * @param comment
+	 *            org.w3c.dom.CDATASection
+	 */
+	public String generateCDATASection(CDATASection cdata) {
+		if (cdata == null)
+			return null;
+
+		String data = cdata.getData();
+		int length = (data != null ? data.length() : 0);
+		StringBuffer buffer = new StringBuffer(length + 16);
+		buffer.append(CDATA_OPEN);
+		if (data != null)
+			buffer.append(data);
+		buffer.append(CDATA_CLOSE);
+		return buffer.toString();
+	}
+
+	/**
+	 * generateChild method
+	 * 
+	 * @return java.lang.String
+	 * @param org.w3c.dom.Node
+	 */
+	public String generateChild(Node parentNode) {
+		if (parentNode == null)
+			return null;
+		if (!parentNode.hasChildNodes())
+			return null;
+
+		StringBuffer buffer = new StringBuffer();
+		for (Node child = parentNode.getFirstChild(); child != null; child = child.getNextSibling()) {
+			String childSource = generateSource(child);
+			if (childSource != null)
+				buffer.append(childSource);
+		}
+		return buffer.toString();
+	}
+
+	/**
+	 */
+	public String generateCloseTag(Node node) {
+		if (node == null)
+			return null;
+
+		switch (node.getNodeType()) {
+			case Node.ELEMENT_NODE : {
+				ElementImpl element = (ElementImpl) node;
+				if (element.isCommentTag()) {
+					if (element.isJSPTag())
+						return JSPTag.COMMENT_CLOSE;
+					return COMMENT_CLOSE;
+				}
+				if (element.isJSPTag())
+					return JSPTag.TAG_CLOSE;
+				if (element.isEmptyTag())
+					return EMPTY_CLOSE;
+				return TAG_CLOSE;
+			}
+			case Node.COMMENT_NODE : {
+				CommentImpl comment = (CommentImpl) node;
+				if (comment.isJSPTag())
+					return JSPTag.COMMENT_CLOSE;
+				return COMMENT_CLOSE;
+			}
+			case Node.DOCUMENT_TYPE_NODE :
+				return TAG_CLOSE;
+			case Node.PROCESSING_INSTRUCTION_NODE :
+				return PI_CLOSE;
+			case Node.CDATA_SECTION_NODE :
+				return CDATA_CLOSE;
+			default :
+				break;
+		}
+
+		return null;
+	}
+
+	/**
+	 * generateComment method
+	 * 
+	 * @return java.lang.String
+	 * @param comment
+	 *            org.w3c.dom.Comment
+	 */
+	public String generateComment(Comment comment) {
+		if (comment == null)
+			return null;
+
+		String data = comment.getData();
+		int length = (data != null ? data.length() : 0);
+		StringBuffer buffer = new StringBuffer(length + 8);
+		CommentImpl impl = (CommentImpl) comment;
+		if (!impl.isJSPTag())
+			buffer.append(COMMENT_OPEN);
+		else
+			buffer.append(JSPTag.COMMENT_OPEN);
+		if (data != null)
+			buffer.append(data);
+		if (!impl.isJSPTag())
+			buffer.append(COMMENT_CLOSE);
+		else
+			buffer.append(JSPTag.COMMENT_CLOSE);
+		return buffer.toString();
+	}
+
+	/**
+	 * generateDoctype method
+	 * 
+	 * @return java.lang.String
+	 * @param docType
+	 *            org.w3c.dom.DocumentType
+	 */
+	public String generateDoctype(DocumentType docType) {
+		if (docType == null)
+			return null;
+
+		String name = docType.getName();
+		int length = (name != null ? name.length() : 0);
+		StringBuffer buffer = new StringBuffer(length + 16);
+		buffer.append(DOCTYPE_OPEN);
+		buffer.append(' ');
+		if (name != null)
+			buffer.append(name);
+		DocumentTypeImpl dt = (DocumentTypeImpl) docType;
+		String publicID = dt.getPublicId();
+		String systemID = dt.getSystemId();
+		if (publicID != null) {
+			buffer.append(' ');
+			buffer.append(PUBLIC_ID);
+			buffer.append(' ');
+			buffer.append('"');
+			buffer.append(publicID);
+			buffer.append('"');
+			if (systemID != null) {
+				buffer.append(' ');
+				buffer.append('"');
+				buffer.append(systemID);
+				buffer.append('"');
+			}
+		} else {
+			if (systemID != null) {
+				buffer.append(' ');
+				buffer.append(SYSTEM_ID);
+				buffer.append(' ');
+				buffer.append('"');
+				buffer.append(systemID);
+				buffer.append('"');
+			}
+		}
+		buffer.append('>');
+		return buffer.toString();
+	}
+
+	/**
+	 * generateElement method
+	 * 
+	 * @return java.lang.String
+	 * @param element
+	 *            Element
+	 */
+	public String generateElement(Element element) {
+		if (element == null)
+			return null;
+
+		// if empty tag is preferrable, generate as empty tag
+		ElementImpl impl = (ElementImpl) element;
+		if (impl.preferEmptyTag())
+			impl.setEmptyTag(true);
+
+		StringBuffer buffer = new StringBuffer();
+		String startTag = generateStartTag(element);
+		if (startTag != null)
+			buffer.append(startTag);
+		String child = generateChild(element);
+		if (child != null)
+			buffer.append(child);
+		String endTag = generateEndTag(element);
+		if (endTag != null)
+			buffer.append(endTag);
+		return buffer.toString();
+	}
+
+	/**
+	 * generateEndTag method
+	 * 
+	 * @return java.lang.String
+	 * @param element
+	 *            org.w3c.dom.Element
+	 */
+	public String generateEndTag(Element element) {
+		if (element == null)
+			return null;
+
+		ElementImpl impl = (ElementImpl) element;
+
+		// first check if tag adapter exists
+		TagAdapter adapter = (TagAdapter) impl.getExistingAdapter(TagAdapter.class);
+		if (adapter != null) {
+			String endTag = adapter.getEndTag(impl);
+			if (endTag != null)
+				return endTag;
+		}
+
+		if (impl.isEmptyTag())
+			return null;
+		if (!impl.isContainer())
+			return null;
+		if (impl.isJSPTag())
+			return JSPTag.TAG_CLOSE;
+
+		String tagName = generateTagName(element);
+		int length = (tagName != null ? tagName.length() : 0);
+		StringBuffer buffer = new StringBuffer(length + 4);
+		buffer.append(END_OPEN);
+		if (tagName != null)
+			buffer.append(tagName);
+		buffer.append('>');
+		return buffer.toString();
+	}
+
+	/**
+	 * generateEntityRef method
+	 * 
+	 * @return java.lang.String
+	 * @param entityRef
+	 *            org.w3c.dom.EntityReference
+	 */
+	public String generateEntityRef(EntityReference entityRef) {
+		if (entityRef == null)
+			return null;
+
+		String name = entityRef.getNodeName();
+		int length = (name != null ? name.length() : 0);
+		StringBuffer buffer = new StringBuffer(length + 4);
+		buffer.append('&');
+		if (name != null)
+			buffer.append(name);
+		buffer.append(';');
+		return buffer.toString();
+	}
+
+	/**
+	 * generatePI method
+	 * 
+	 * @return java.lang.String
+	 * @param pi
+	 *            org.w3c.dom.ProcessingInstruction
+	 */
+	public String generatePI(ProcessingInstruction pi) {
+		if (pi == null)
+			return null;
+
+		String target = pi.getTarget();
+		String data = pi.getData();
+		int length = (target != null ? target.length() : 0);
+		if (data != null)
+			length += data.length();
+		StringBuffer buffer = new StringBuffer(length + 8);
+		buffer.append(PI_OPEN);
+		if (target != null)
+			buffer.append(target);
+		buffer.append(' ');
+		if (data != null)
+			buffer.append(data);
+		buffer.append(PI_CLOSE);
+		return buffer.toString();
+	}
+
+	/**
+	 * generateSource method
+	 * 
+	 * @return java.lang.String
+	 * @param node
+	 *            org.w3c.dom.Node
+	 */
+	public String generateSource(Node node) {
+		switch (node.getNodeType()) {
+			case Node.ELEMENT_NODE :
+				return generateElement((Element) node);
+			case Node.TEXT_NODE :
+				return generateText((Text) node);
+			case Node.COMMENT_NODE :
+				return generateComment((Comment) node);
+			case Node.DOCUMENT_TYPE_NODE :
+				return generateDoctype((DocumentType) node);
+			case Node.PROCESSING_INSTRUCTION_NODE :
+				return generatePI((ProcessingInstruction) node);
+			case Node.CDATA_SECTION_NODE :
+				return generateCDATASection((CDATASection) node);
+			case Node.ENTITY_REFERENCE_NODE :
+				return generateEntityRef((EntityReference) node);
+			default :
+				// DOCUMENT
+				break;
+		}
+		return generateChild(node);
+	}
+
+	/**
+	 * generateStartTag method
+	 * 
+	 * @return java.lang.String
+	 * @param element
+	 *            Element
+	 */
+	public String generateStartTag(Element element) {
+		if (element == null)
+			return null;
+
+		ElementImpl impl = (ElementImpl) element;
+
+		if (impl.isJSPTag()) {
+			// check if JSP content type and JSP Document
+			IDOMDocument document = (IDOMDocument) element.getOwnerDocument();
+			if (document != null && document.isJSPType()) {
+				if (document.isJSPDocument() && !impl.hasChildNodes()) {
+					impl.setJSPTag(false);
+				}
+			} else {
+				impl.setJSPTag(false);
+			}
+		}
+		if (impl.isCommentTag() && impl.getExistingAdapter(TagAdapter.class) == null) {
+			CommentElementRegistry registry = CommentElementRegistry.getInstance();
+			registry.setupCommentElement(impl);
+		}
+
+		// first check if tag adapter exists
+		TagAdapter adapter = (TagAdapter) impl.getExistingAdapter(TagAdapter.class);
+		if (adapter != null) {
+			String startTag = adapter.getStartTag(impl);
+			if (startTag != null)
+				return startTag;
+		}
+
+		StringBuffer buffer = new StringBuffer();
+
+		if (impl.isCommentTag()) {
+			if (impl.isJSPTag())
+				buffer.append(JSPTag.COMMENT_OPEN);
+			else
+				buffer.append(COMMENT_OPEN);
+			String tagName = generateTagName(element);
+			if (tagName != null)
+				buffer.append(tagName);
+		} else if (impl.isJSPTag()) {
+			buffer.append(JSPTag.TAG_OPEN);
+			String tagName = generateTagName(element);
+			if (tagName != null)
+				buffer.append(tagName);
+			if (impl.isContainer())
+				return buffer.toString(); // JSP container
+		} else {
+			buffer.append('<');
+			String tagName = generateTagName(element);
+			if (tagName != null)
+				buffer.append(tagName);
+		}
+
+		NamedNodeMap attributes = element.getAttributes();
+		int length = attributes.getLength();
+		for (int i = 0; i < length; i++) {
+			AttrImpl attr = (AttrImpl) attributes.item(i);
+			if (attr == null)
+				continue;
+			buffer.append(' ');
+			String attrName = generateAttrName(attr);
+			if (attrName != null)
+				buffer.append(attrName);
+			String attrValue = generateAttrValue(attr);
+			if (attrValue != null) {
+				// attr name only for HTML boolean and JSP
+				buffer.append('=');
+				buffer.append(attrValue);
+			}
+		}
+
+		String closeTag = generateCloseTag(element);
+		if (closeTag != null)
+			buffer.append(closeTag);
+
+		return buffer.toString();
+	}
+
+	/**
+	 */
+	public String generateTagName(Element element) {
+		if (element == null)
+			return null;
+		IDOMElement xe = (IDOMElement) element;
+		String tagName = element.getTagName();
+		if (tagName == null)
+			return null;
+		if (xe.isJSPTag()) {
+			if (tagName.equals(JSPTag.JSP_EXPRESSION))
+				return JSPTag.EXPRESSION_TOKEN;
+			if (tagName.equals(JSPTag.JSP_DECLARATION))
+				return JSPTag.DECLARATION_TOKEN;
+			if (tagName.equals(JSPTag.JSP_DIRECTIVE))
+				return JSPTag.DIRECTIVE_TOKEN;
+			if (tagName.startsWith(JSPTag.JSP_DIRECTIVE)) {
+				int offset = JSPTag.JSP_DIRECTIVE.length() + 1; // after '.'
+				return (JSPTag.DIRECTIVE_TOKEN + tagName.substring(offset));
+			}
+			return (xe.isCommentTag()) ? tagName : null;
+		} else if (tagName.startsWith(JSPTag.TAG_OPEN)) {
+			if (!tagName.endsWith(JSPTag.TAG_CLOSE)) {
+				// close JSP
+				return (tagName + JSPTag.TAG_CLOSE);
+			}
+		} else if (xe.isCommentTag()) {
+			String prefix = element.getPrefix();
+			if (prefix.equals(SSI_PREFIX)) {
+				return (SSI_TOKEN + element.getLocalName());
+			}
+		} else {
+			if (!xe.isJSPTag() && xe.isGlobalTag() && // global tag
+						CMNodeUtil.getElementDeclaration(xe) != null) {
+				String newName = tagName;
+				switch (getTagNameCase(xe)) {
+					case DocumentTypeAdapter.UPPER_CASE :
+						newName = tagName.toUpperCase();
+						break;
+					case DocumentTypeAdapter.LOWER_CASE :
+						newName = tagName.toLowerCase();
+						break;
+				}
+				if (newName != tagName) {
+					tagName = newName;
+					setTagName(element, tagName);
+				}
+			}
+		}
+		return tagName;
+	}
+
+	/**
+	 * generateText method
+	 * 
+	 * @return java.lang.String
+	 * @param text
+	 *            org.w3c.dom.Text
+	 */
+	public String generateText(Text text) {
+		if (text == null)
+			return null;
+		TextImpl impl = (TextImpl) text;
+		String source = impl.getTextSource();
+		if (source != null)
+			return source;
+		return generateTextData(text, impl.getData());
+	}
+
+	/**
+	 */
+	public String generateTextData(Text text, String data) {
+		if (data == null)
+			return null;
+		if (text == null)
+			return null;
+		TextImpl impl = (TextImpl) text;
+		if (impl.isJSPContent() || impl.isCDATAContent()) {
+			return new SourceValidator(impl).convertSource(data);
+		}
+		String source = data;
+
+		// convert special characters to character entities
+		StringBuffer buffer = null;
+		int offset = 0;
+		int length = data.length();
+		for (int i = 0; i < length; i++) {
+			String name = getCharName(data.charAt(i));
+			if (name == null)
+				continue;
+			if (buffer == null)
+				buffer = new StringBuffer(length + 8);
+			if (i > offset)
+				buffer.append(data.substring(offset, i));
+			buffer.append('&');
+			buffer.append(name);
+			buffer.append(';');
+			offset = i + 1;
+		}
+		if (buffer != null) {
+			if (length > offset)
+				buffer.append(data.substring(offset));
+			source = buffer.toString();
+		}
+
+		if (source == null || source.length() == 0)
+			return null;
+		return source;
+	}
+
+	/**
+	 */
+	private int getAttrNameCase(Attr attr) {
+		DocumentImpl document = (DocumentImpl) attr.getOwnerDocument();
+		if (document == null)
+			return DocumentTypeAdapter.STRICT_CASE;
+		DocumentTypeAdapter adapter = (DocumentTypeAdapter) document.getAdapterFor(DocumentTypeAdapter.class);
+		if (adapter == null)
+			return DocumentTypeAdapter.STRICT_CASE;
+		return adapter.getAttrNameCase();
+	}
+
+	/**
+	 */
+	private String getCharName(char c) {
+		switch (c) {
+			case '<' :
+				return IXMLCharEntity.LT_NAME;
+			case '>' :
+				return IXMLCharEntity.GT_NAME;
+			case '&' :
+				return IXMLCharEntity.AMP_NAME;
+			case '"' :
+				return IXMLCharEntity.QUOT_NAME;
+		}
+		return null;
+	}
+
+	/**
+	 */
+	private int getTagNameCase(Element element) {
+		DocumentImpl document = (DocumentImpl) element.getOwnerDocument();
+		if (document == null)
+			return DocumentTypeAdapter.STRICT_CASE;
+		DocumentTypeAdapter adapter = (DocumentTypeAdapter) document.getAdapterFor(DocumentTypeAdapter.class);
+		if (adapter == null)
+			return DocumentTypeAdapter.STRICT_CASE;
+		return adapter.getTagNameCase();
+	}
+
+	/**
+	 */
+	private boolean isBooleanAttr(Attr attr) {
+		if (attr == null)
+			return false;
+		CMAttributeDeclaration decl = CMNodeUtil.getAttributeDeclaration(attr);
+		if (decl == null)
+			return false;
+		CMDataType type = decl.getAttrType();
+		if (type == null)
+			return false;
+		String values[] = type.getEnumeratedValues();
+		if (values == null)
+			return false;
+		return (values.length == 1 && values[0].equals(decl.getAttrName()));
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/XMLModelContext.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/XMLModelContext.java
new file mode 100644
index 0000000..6a799f7
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/XMLModelContext.java
@@ -0,0 +1,237 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.Text;
+
+/**
+ * XMLModelContext class
+ */
+class XMLModelContext {
+	private Node nextNode = null;
+	private Node parentNode = null;
+
+	//	private XMLModelImpl model = null;
+	private Node rootNode = null;
+
+	/**
+	 * XMLModelContext constructor
+	 * 
+	 * @param rootNode
+	 *            org.w3c.dom.Node
+	 */
+	XMLModelContext(Node rootNode) {
+		super();
+
+		this.rootNode = rootNode;
+	}
+
+	/**
+	 * findEndTag method
+	 * 
+	 * @return org.w3c.dom.Element
+	 * @param tagName
+	 *            java.lang.String
+	 */
+	Element findEndTag(String tagName) {
+		if (tagName == null)
+			return null;
+		if (this.parentNode == null)
+			return null;
+
+		for (Node parent = this.parentNode.getParentNode(); parent != null; parent = parent.getParentNode()) {
+			if (parent.getNodeType() != Node.ELEMENT_NODE)
+				break;
+			ElementImpl element = (ElementImpl) parent;
+			if (element.hasEndTag()) {
+				if (element.matchTagName(tagName))
+					return element;
+				// if ancestor element has end tag stop search
+				break;
+			}
+			if (element.getNextSibling() != null)
+				break;
+		}
+
+		return null;
+	}
+
+	/**
+	 */
+	Text findNextText() {
+		Node node = this.nextNode;
+		while (node != null) {
+			if (node != this.nextNode && node.getNodeType() == Node.TEXT_NODE) {
+				TextImpl text = (TextImpl) node;
+				// skip empty text
+				if (text.getStructuredDocumentRegion() != null)
+					return text;
+			}
+			Node child = node.getFirstChild();
+			if (child != null) {
+				node = child;
+				continue;
+			}
+			while (node != null) {
+				Node next = node.getNextSibling();
+				if (next != null) {
+					node = next;
+					break;
+				}
+				node = node.getParentNode();
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * findPreviousText method
+	 * 
+	 * @return org.w3c.dom.Text
+	 */
+	Text findPreviousText() {
+		if (this.parentNode == null)
+			return null;
+		Node node = null;
+		if (this.nextNode != null)
+			node = this.nextNode.getPreviousSibling();
+		else
+			node = this.parentNode.getLastChild();
+		if (node == null || node.getNodeType() != Node.TEXT_NODE)
+			return null;
+		return (Text) node;
+	}
+
+	/**
+	 * findStartTag method
+	 * 
+	 * @return org.w3c.dom.Element
+	 * @param tagName
+	 *            java.lang.String
+	 */
+	Element findStartTag(String tagName, String rootName) {
+		if (tagName == null)
+			return null;
+
+		// check previous for empty content element
+		Node prev = null;
+		if (this.nextNode != null)
+			prev = this.nextNode.getPreviousSibling();
+		else if (this.parentNode != null)
+			prev = this.parentNode.getLastChild();
+		if (prev != null && prev.getNodeType() == Node.ELEMENT_NODE) {
+			ElementImpl element = (ElementImpl) prev;
+			if (!element.hasEndTag() && !element.isEmptyTag() && element.matchTagName(tagName))
+				return element;
+		}
+
+		for (Node parent = this.parentNode; parent != null; parent = parent.getParentNode()) {
+			if (parent.getNodeType() != Node.ELEMENT_NODE)
+				break;
+			ElementImpl element = (ElementImpl) parent;
+			if (element.matchTagName(tagName))
+				return element;
+			if (rootName != null && element.matchTagName(rootName))
+				break;
+		}
+
+		return null;
+	}
+
+	/**
+	 * getNextNode method
+	 * 
+	 * @return org.w3c.dom.Node
+	 */
+	Node getNextNode() {
+		return this.nextNode;
+	}
+
+	/**
+	 * getParentNode method
+	 * 
+	 * @return org.w3c.dom.Node
+	 */
+	Node getParentNode() {
+		return this.parentNode;
+	}
+
+	/**
+	 * getRootNode method
+	 * 
+	 * @return org.w3c.dom.Node
+	 */
+	Node getRootNode() {
+		return this.rootNode;
+	}
+
+	/**
+	 * setLast method
+	 */
+	void setLast() {
+		if (this.parentNode == null)
+			return;
+		if (this.nextNode != null) {
+			Node prev = this.nextNode.getPreviousSibling();
+			if (prev == null || prev.getNodeType() != Node.ELEMENT_NODE)
+				return;
+			ElementImpl element = (ElementImpl) prev;
+			if (element.hasEndTag() || !element.isContainer() || element.isEmptyTag())
+				return;
+			setParentNode(prev);
+		}
+
+		// find last open parent
+		Node parent = this.parentNode;
+		Node last = parent.getLastChild();
+		while (last != null) {
+			if (last.getNodeType() != Node.ELEMENT_NODE)
+				break;
+			ElementImpl element = (ElementImpl) last;
+			if (element.hasEndTag() || !element.isContainer() || element.isEmptyTag())
+				break;
+			parent = element;
+			last = parent.getLastChild();
+		}
+		if (parent != this.parentNode)
+			setParentNode(parent);
+	}
+
+	/**
+	 * setNextNode method
+	 * 
+	 * @param nextNode
+	 *            org.w3c.dom.Node
+	 */
+	void setNextNode(Node nextNode) {
+		this.nextNode = nextNode;
+		if (nextNode == null)
+			return;
+		this.parentNode = nextNode.getParentNode();
+	}
+
+	/**
+	 * setParentNode method
+	 * 
+	 * @param parentNode
+	 *            org.w3c.dom.Node
+	 */
+	void setParentNode(Node parentNode) {
+		this.parentNode = parentNode;
+		this.nextNode = null;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/XMLModelNotifier.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/XMLModelNotifier.java
new file mode 100644
index 0000000..9a3e255
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/XMLModelNotifier.java
@@ -0,0 +1,139 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+/**
+ * 
+ * XMLModelNotifier manages the notification process. Clients should not use
+ * extend or reference.
+ * 
+ * ISSUE: should be internalized.
+ */
+
+public interface XMLModelNotifier {
+
+	/**
+	 * attrReplaced method
+	 * 
+	 * @param element
+	 *            org.w3c.dom.Element
+	 * @param newAttr
+	 *            org.w3c.dom.Attr
+	 * @param oldAttr
+	 *            org.w3c.dom.Attr
+	 */
+	void attrReplaced(Element element, Attr newAttr, Attr oldAttr);
+
+	/**
+	 * Signal that changing is starting.
+	 * 
+	 */
+	void beginChanging();
+
+	/**
+	 * Signal that changing is starting with a brand new model.
+	 * 
+	 */
+	void beginChanging(boolean newModel);
+
+	/**
+	 * Cancel pending notifications. This is called in the context of
+	 * "reinitialization" so is assumed ALL notifications can be safely
+	 * canceled, assuming that once factories and adapters are re-initialized
+	 * they will be re-notified as text is set in model, if still appropriate.
+	 */
+	void cancelPending();
+
+	/**
+	 * childReplaced method
+	 * 
+	 * @param parentNode
+	 *            org.w3c.dom.Node
+	 * @param newChild
+	 *            org.w3c.dom.Node
+	 * @param oldChild
+	 *            org.w3c.dom.Node
+	 */
+	void childReplaced(Node parentNode, Node newChild, Node oldChild);
+
+	/**
+	 * Editable state changed for node.
+	 * 
+	 */
+	void editableChanged(Node node);
+
+	/**
+	 * Signal changing is finished.
+	 * 
+	 */
+	void endChanging();
+
+	/**
+	 * Signal end tag changed.
+	 * 
+	 * @param element
+	 * 
+	 */
+	void endTagChanged(Element element);
+
+	/**
+	 * Used to reflect state of model.
+	 * 
+	 * @return true if model had changed.
+	 * 
+	 */
+	boolean hasChanged();
+
+	/**
+	 * Used to reflect state of parsing process.
+	 * 
+	 * @return true if model is currently changing.
+	 */
+	boolean isChanging();
+
+	/**
+	 * signal property changed
+	 * 
+	 * @param node
+	 */
+	void propertyChanged(Node node);
+
+	/**
+	 * signal start tag changed
+	 * 
+	 * @param element
+	 */
+	void startTagChanged(Element element);
+
+	/**
+	 * signal structured changed.
+	 * 
+	 * @param node
+	 */
+	void structureChanged(Node node);
+
+	/**
+	 * valueChanged method
+	 * 
+	 * @param node
+	 *            org.w3c.dom.Node
+	 */
+	void valueChanged(Node node);
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/XMLModelNotifierImpl.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/XMLModelNotifierImpl.java
new file mode 100644
index 0000000..75f89a0
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/XMLModelNotifierImpl.java
@@ -0,0 +1,496 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2008 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.sse.core.internal.util.Debug;
+import org.eclipse.wst.xml.core.internal.Logger;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+
+public class XMLModelNotifierImpl implements XMLModelNotifier {
+
+	private static class NotifyEvent {
+		Object changedFeature;
+		boolean discarded;
+		Object newValue;
+		// note: don't initialize instance variables, since
+		// that causes double assignments, and lots of these are created.
+		INodeNotifier notifier;
+		Object oldValue;
+		int pos;
+		String reason;
+		int type;
+		int index;
+
+		NotifyEvent(INodeNotifier notifier, int type, Object changedFeature, Object oldValue, Object newValue, int pos) {
+			this.notifier = notifier;
+			this.type = type;
+			this.changedFeature = changedFeature;
+			this.oldValue = oldValue;
+			this.newValue = newValue;
+			this.pos = pos;
+			this.reason = ""; //$NON-NLS-1$
+		}
+	}
+
+	private final static String ADDED_THEN_REMOVED = "Discard: Added then removed rule"; //$NON-NLS-1$
+	private final static boolean fOptimizeDeferred = true;
+	private final static boolean fOptimizeDeferredAccordingToParentAdded = true;
+	private final static boolean fOptimizeDeferredAccordingToParentRemoved = true;
+	private final static String PARENT_IS_ADDED = "Disarded: Parent has just been added"; //$NON-NLS-1$
+	/* start: for debugging only */
+	private final static String PARENT_IS_REMOVED_TOO = "Discard: Parent was removed too"; //$NON-NLS-1$
+	private final static String PARENT_IS_REPARENTED = "Not Discard: Parent was removed so this implies reparenting"; //$NON-NLS-1$
+	private Node changedRoot = null;
+
+	private boolean changing = false;
+	private boolean doingNewModel = false;
+	private List fEvents = null;
+	private boolean flushing = false;
+
+	/**
+	 */
+	public XMLModelNotifierImpl() {
+		super();
+	}
+
+	/**
+	 * attrReplaced method
+	 * 
+	 * @param element
+	 *            org.w3c.dom.Element
+	 * @param newAttr
+	 *            org.w3c.dom.Attr
+	 * @param oldAttr
+	 *            org.w3c.dom.Attr
+	 */
+	public void attrReplaced(Element element, Attr newAttr, Attr oldAttr) {
+		if (element == null)
+			return;
+		Attr attr = null;
+		String oldValue = null;
+		String newValue = null;
+		if (oldAttr != null) {
+			attr = oldAttr;
+			oldValue = oldAttr.getValue();
+		}
+		if (newAttr != null) {
+			attr = newAttr;
+			newValue = newAttr.getValue();
+		}
+		IDOMNode notifier = (IDOMNode) element;
+		int offset = notifier.getStartOffset();
+		notify(notifier, INodeNotifier.CHANGE, attr, oldValue, newValue, offset);
+		propertyChanged(notifier);
+	}
+
+	/**
+	 */
+	public void beginChanging() {
+		this.changing = true;
+	}
+
+	/**
+	 */
+	public void beginChanging(boolean newModel) {
+		beginChanging();
+		this.doingNewModel = newModel;
+	}
+
+	public void cancelPending() {
+		// we don't want to change the size of this array, since
+		// the array may be being processed, in the deferred notification
+		// loop, but we can signal that all
+		// should be discarded, so any remaining ones will be ignored.
+		if (this.fEvents != null) {
+			int size = fEvents.size();
+			for (int i = 0; i < size; i++) {
+				NotifyEvent event = (NotifyEvent) fEvents.get(i);
+				event.discarded = true;
+			}
+		}
+		// this cancel is presumably being called as a function of
+		// "reinitiailization" so we can ignore changes to the
+		// old root, and changes to the new one will be triggered during
+		// reinitialization.
+		changedRoot = null;
+	}
+
+	/**
+	 * childReplaced method
+	 * 
+	 * @param parentNode
+	 *            org.w3c.dom.Node
+	 * @param newChild
+	 *            org.w3c.dom.Node
+	 * @param oldChild
+	 *            org.w3c.dom.Node
+	 */
+	public void childReplaced(Node parentNode, Node newChild, Node oldChild) {
+		if (parentNode == null)
+			return;
+		IDOMNode notifier = (IDOMNode) parentNode;
+		int type = INodeNotifier.CHANGE;
+		if (newChild == null)
+			type = INodeNotifier.REMOVE;
+		else if (oldChild == null)
+			type = INodeNotifier.ADD;
+		int offset = notifier.getStartOffset();
+		notify(notifier, type, oldChild, oldChild, newChild, offset);
+		structureChanged(notifier);
+	}
+
+	public void editableChanged(Node node) {
+		if (node == null)
+			return;
+		IDOMNode notifier = (IDOMNode) node;
+		int offset = notifier.getStartOffset();
+		notify(notifier, INodeNotifier.CHANGE, null, null, null, offset);
+		propertyChanged(notifier);
+	}
+
+	/**
+	 */
+	public void endChanging() {
+		this.doingNewModel = false;
+		if (!this.changing)
+			return; // avoid nesting calls
+		notifyDeferred();
+		if (this.changedRoot != null) {
+			notifyStructureChanged(this.changedRoot);
+			if (Debug.debugNotifyDeferred) {
+				String p = this.changedRoot.getNodeName();
+				System.out.println("Deferred STRUCTURE_CHANGED: " + p); //$NON-NLS-1$
+			}
+			this.changedRoot = null;
+		}
+		this.changing = false;
+	}
+
+	/**
+	 */
+	public void endTagChanged(Element element) {
+		if (element == null)
+			return;
+		IDOMNode notifier = (IDOMNode) element;
+		int offset = notifier.getStartOffset();
+		notify(notifier, INodeNotifier.CHANGE, null, null, null, offset);
+		propertyChanged(element);
+	}
+
+	/**
+	 */
+	public boolean hasChanged() {
+		return (this.fEvents != null);
+	}
+
+	/**
+	 */
+	public boolean isChanging() {
+		return this.changing;
+	}
+
+	/**
+	 */
+	private void notify(INodeNotifier notifier, int eventType, Object changedFeature, Object oldValue, Object newValue, int pos) {
+		if (notifier == null)
+			return;
+		if (this.changing && !this.flushing) {
+			// defer notification
+			if (this.fEvents == null)
+				this.fEvents = new ArrayList();
+			// we do not defer anything if we are doing a new Model,
+			// except for the document event, since all others are
+			// trivial and not needed at that initial point.
+			// But even for that one document event, in the new model case,
+			// it is still important to defer it.
+			if ((!doingNewModel) || (((Node) notifier).getNodeType() == Node.DOCUMENT_NODE)) {
+				this.fEvents.add(new NotifyEvent(notifier, eventType, changedFeature, oldValue, newValue, pos));
+			}
+			return;
+		}
+		try {
+			// Its important to "keep going" if exception occurs, since this
+			// notification
+			// comes in between "about to change" and "changed" events. We do
+			// log, however,
+			// since would indicate a program error.
+			notifier.notify(eventType, changedFeature, oldValue, newValue, pos);
+		} catch (Exception e) {
+			Logger.logException("A structured model client threw following exception during adapter notification (" + INodeNotifier.EVENT_TYPE_STRINGS[eventType] + " )", e); //$NON-NLS-1$ //$NON-NLS-2$
+		}
+	}
+
+	/**
+	 */
+	private void notifyDeferred() {
+		if (this.fEvents == null)
+			return;
+		if (this.flushing)
+			return;
+		this.flushing = true; // force notification
+		int count = this.fEvents.size();
+		
+		if (!doingNewModel && fOptimizeDeferred) {
+			Map notifyEvents = new HashMap();
+			for (int i = 0; i < count; i++) {
+				NotifyEvent event = (NotifyEvent) this.fEvents.get(i);
+				if (event == null)
+					continue; // error
+				event.index = i;
+				if(event.type == INodeNotifier.REMOVE) {
+					addToMap(event.oldValue, event, notifyEvents);
+				}
+				if(event.type == INodeNotifier.ADD) {
+					addToMap(event.newValue, event, notifyEvents);
+				}
+			}
+			Iterator it = notifyEvents.values().iterator();
+			while (it.hasNext()) {
+				NotifyEvent[] es = (NotifyEvent[]) it.next();
+				for (int i = 0; i < es.length - 1; i++) {
+					NotifyEvent event = es[i];
+					if(es[i].discarded) continue;
+					NotifyEvent next = es[i + 1];
+					if(es[i].type == INodeNotifier.ADD && next.type == INodeNotifier.REMOVE) {
+						// Added then removed later, discard both
+						event.discarded = true;
+						next.discarded = true;
+						if (Debug.debugNotifyDeferred) {
+							event.reason = event.reason + ADDED_THEN_REMOVED + "(see " + next.index + ")"; //$NON-NLS-1$ //$NON-NLS-2$
+							next.reason = next.reason + ADDED_THEN_REMOVED + "(see " + event.index + ")"; //$NON-NLS-1$ //$NON-NLS-2$
+						}
+					}
+				}
+			}
+			for (int i = 0; i < count; i++) {
+				NotifyEvent event = (NotifyEvent) this.fEvents.get(i);
+				if (event == null)
+					continue; // error
+				if(event.discarded) continue;
+				if (event.notifier != null && fOptimizeDeferredAccordingToParentAdded) {
+					if (event.type == INodeNotifier.ADD) {
+						NotifyEvent[] es = (NotifyEvent[])notifyEvents.get(event.notifier);
+						if(es != null) for (int p = 0; p < es.length && es[p].index < event.index; p++) {
+							NotifyEvent prev = es[p];
+							if (prev.type == INodeNotifier.REMOVE && prev.oldValue == event.notifier) {
+								// parent is reparented, do not discard
+								if (Debug.debugNotifyDeferred) {
+									event.reason = event.reason + PARENT_IS_REPARENTED + "(see " + prev.index + ")"; //$NON-NLS-1$ //$NON-NLS-2$
+								}
+								break;
+							} else if (prev.type == INodeNotifier.ADD && prev.newValue == event.notifier) {
+								// parent has been added, discard this
+								event.discarded = true;
+								if (Debug.debugNotifyDeferred) {
+									event.reason = event.reason + PARENT_IS_ADDED + "(see " + prev.index + ")"; //$NON-NLS-1$ //$NON-NLS-2$
+								}
+								break;
+							}
+						}							
+					}						
+				}
+				if(event.discarded) continue;
+				if (event.notifier != null && fOptimizeDeferredAccordingToParentRemoved) {
+					if (event.type == INodeNotifier.REMOVE) {
+						NotifyEvent[] es = (NotifyEvent[])notifyEvents.get(event.notifier);
+						if(es != null) for (int n = 0; n < es.length; n++) {
+							NotifyEvent next = es[n];
+							if(next.index > event.index && next.type == INodeNotifier.REMOVE) {
+								if (next.oldValue == event.notifier) {
+									// parent will be removed, discard this
+									event.discarded = true;
+									if (Debug.debugNotifyDeferred) {
+										event.reason = event.reason + PARENT_IS_REMOVED_TOO + "(see " + next.index + ")"; //$NON-NLS-1$ //$NON-NLS-2$
+									}
+									break;
+								}
+							}
+						}
+					}						
+				}
+				if(event.discarded) continue;
+			}
+		}
+		for (int i = 0; i < count; i++) {
+			NotifyEvent event = (NotifyEvent) this.fEvents.get(i);
+			if (event == null)
+				continue; // error
+			if(event.discarded) continue;
+			notify(event.notifier, event.type, event.changedFeature, event.oldValue, event.newValue, event.pos);
+		}
+		if (Debug.debugNotifyDeferred) {
+			for (int l = 0; l < count; l++) {
+				NotifyEvent event = (NotifyEvent) this.fEvents.get(l);
+				Object o = null;
+				String t = null;
+				if (event.type == INodeNotifier.ADD) {
+					o = event.newValue;
+					t = " + "; //$NON-NLS-1$
+				} else if (event.type == INodeNotifier.REMOVE) {
+					o = event.oldValue;
+					t = " - "; //$NON-NLS-1$
+				}
+				if (o instanceof Element) {
+					String p = ((Node) event.notifier).getNodeName();
+					String c = ((Node) o).getNodeName();
+					String d = (event.discarded ? "! " : "  "); //$NON-NLS-1$ //$NON-NLS-2$
+					System.out.println(d + p + t + c);
+				}
+			}
+		}
+		this.flushing = false;
+		this.fEvents = null;
+	}
+
+	void addToMap(Object o, NotifyEvent event, Map map) {
+		if(o == null) return;
+		Object x = map.get(o);
+		if(x == null) {
+			map.put(o, new NotifyEvent[]{event});
+		} else {
+			NotifyEvent[] es = (NotifyEvent[])x;
+			NotifyEvent[] es2 = new NotifyEvent[es.length + 1];
+			System.arraycopy(es, 0, es2, 0, es.length);
+			es2[es.length] = event;
+			map.put(o, es2);
+		}
+	}
+
+	/**
+	 */
+	private void notifyStructureChanged(Node root) {
+		if (root == null)
+			return;
+		INodeNotifier notifier = (INodeNotifier) root;
+		try {
+			// Its important to "keep going" if exception occurs, since this
+			// notification
+			// comes in between "about to change" and "changed" events. We do
+			// log, however,
+			// since would indicate a program error.
+			notifier.notify(INodeNotifier.STRUCTURE_CHANGED, null, null, null, -1);
+		} catch (Exception e) {
+			Logger.logException("A structured model client threw following exception during adapter notification (" + INodeNotifier.EVENT_TYPE_STRINGS[INodeNotifier.STRUCTURE_CHANGED] + " )", e); //$NON-NLS-1$ //$NON-NLS-2$
+		}
+
+	}
+
+	/**
+	 */
+	public void propertyChanged(Node node) {
+	}
+
+	/**
+	 * @param node
+	 */
+	private void setCommonRootIfNeeded(Node node) {
+		// defer notification
+		if (this.changedRoot == null) {
+			this.changedRoot = node;
+		} else {
+			// tiny optimization: if previous commonAncestor (changedRoot) is
+			// already 'document',
+			// or if already equal to this 'node',
+			// then no need to re-calculate
+			if (changedRoot.getNodeType() != Node.DOCUMENT_NODE && changedRoot != node) {
+				Node common = ((NodeImpl) this.changedRoot).getCommonAncestor(node);
+				if (common != null)
+					this.changedRoot = common;
+				else
+					this.changedRoot = node;
+			}
+		}
+	}
+
+	/**
+	 */
+	public void startTagChanged(Element element) {
+		if (element == null)
+			return;
+		IDOMNode notifier = (IDOMNode) element;
+		int offset = notifier.getStartOffset();
+		notify(notifier, INodeNotifier.CHANGE, null, null, null, offset);
+		propertyChanged(element);
+	}
+
+	/**
+	 */
+	public void structureChanged(Node node) {
+		if (node == null)
+			return;
+		if (isChanging()) {
+			setCommonRootIfNeeded(node);
+			if (Debug.debugNotifyDeferred) {
+				String p = this.changedRoot.getNodeName();
+				System.out.println("requested STRUCTURE_CHANGED: " + p); //$NON-NLS-1$
+			}
+			return;
+		}
+		if (Debug.debugNotifyDeferred) {
+			String p = node.getNodeName();
+			System.out.println("STRUCTURE_CHANGED: " + p); //$NON-NLS-1$
+		}
+		notifyStructureChanged(node);
+	}
+
+	/**
+	 * valueChanged method
+	 * 
+	 * @param node
+	 *            org.w3c.dom.Node
+	 */
+	public void valueChanged(Node node) {
+		if (node == null)
+			return;
+		IDOMNode notifier = null;
+		if (node.getNodeType() == Node.ATTRIBUTE_NODE) {
+			Attr attr = (Attr) node;
+			notifier = (IDOMNode) attr.getOwnerElement();
+			// TODO_dmw: experimental: changed 06/29/2004 to send "structuure
+			// changed" even for attribute value changes
+			// there are pros and cons to considering attribute value
+			// "structure changed". Will (re)consider
+			// setCommonRootIfNeeded(notifier);
+			if (notifier == null)
+				return;
+			String value = attr.getValue();
+			int offset = notifier.getStartOffset();
+			notify(notifier, INodeNotifier.CHANGE, attr, null, value, offset);
+		} else {
+			// note: we do not send structured changed event for content
+			// changed
+			notifier = (IDOMNode) node;
+			String value = node.getNodeValue();
+			int offset = notifier.getStartOffset();
+			notify(notifier, INodeNotifier.CHANGE, null, null, value, offset);
+			if (node.getNodeType() != Node.ELEMENT_NODE) {
+				IDOMNode parent = (IDOMNode) node.getParentNode();
+				if (parent != null) {
+					notify(parent, INodeNotifier.CONTENT_CHANGED, node, null, value, offset);
+				}
+			}
+		}
+		propertyChanged(notifier);
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/XMLModelParser.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/XMLModelParser.java
new file mode 100644
index 0000000..9f893bb
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/XMLModelParser.java
@@ -0,0 +1,2422 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.wst.sse.core.internal.provisional.events.RegionChangedEvent;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegionList;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList;
+import org.eclipse.wst.xml.core.internal.commentelement.impl.CommentElementConfiguration;
+import org.eclipse.wst.xml.core.internal.commentelement.impl.CommentElementRegistry;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+import org.w3c.dom.Attr;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.Text;
+
+
+/**
+ * XMLModelParser
+ */
+public class XMLModelParser {
+	private XMLModelContext context = null;
+	private DOMModelImpl model = null;
+	private TextImpl lastTextNode = null;
+
+	/**
+	 */
+	protected XMLModelParser(DOMModelImpl model) {
+		super();
+
+		if (model != null) {
+			this.model = model;
+		}
+	}
+
+	/**
+	 */
+	protected boolean canBeImplicitTag(Element element) {
+		ModelParserAdapter adapter = getParserAdapter();
+		if (adapter != null) {
+			return adapter.canBeImplicitTag(element);
+		}
+		return false;
+	}
+
+	/**
+	 */
+	protected boolean canBeImplicitTag(Element element, Node child) {
+		ModelParserAdapter adapter = getParserAdapter();
+		if (adapter != null) {
+			return adapter.canBeImplicitTag(element, child);
+		}
+		return false;
+	}
+
+	/**
+	 */
+	protected boolean canContain(Element element, Node child) {
+		if (element == null || child == null)
+			return false;
+		ElementImpl impl = (ElementImpl) element;
+		if (impl.isEndTag())
+			return false; // invalid (floating) end tag
+		if (!impl.isContainer())
+			return false;
+		if (child.getNodeType() != Node.TEXT_NODE) {
+			if (impl.isJSPContainer() || impl.isCDATAContainer()) {
+				// accepts only Text child
+				return false;
+			}
+		}
+		ModelParserAdapter adapter = getParserAdapter();
+		if (adapter != null) {
+			return adapter.canContain(element, child);
+		}
+		return true;
+	}
+
+	/**
+	 */
+	private void changeAttrEqual(IStructuredDocumentRegion flatNode, ITextRegion region) {
+		int offset = flatNode.getStart();
+		if (offset < 0)
+			return;
+		NodeImpl root = (NodeImpl) this.context.getRootNode();
+		if (root == null)
+			return;
+		Node node = root.getNodeAt(offset);
+		if (node == null)
+			return;
+		if (node.getNodeType() != Node.ELEMENT_NODE) {
+			if (node.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE) {
+				// just notify the change instead of setting data
+				ProcessingInstructionImpl pi = (ProcessingInstructionImpl) node;
+				pi.notifyValueChanged();
+			}
+			return;
+		}
+		// actually, do nothing
+	}
+
+	/**
+	 * changeAttrName method
+	 * 
+	 */
+	private void changeAttrName(IStructuredDocumentRegion flatNode, ITextRegion region) {
+		int offset = flatNode.getStart();
+		if (offset < 0)
+			return;
+		NodeImpl root = (NodeImpl) this.context.getRootNode();
+		if (root == null)
+			return;
+		Node node = root.getNodeAt(offset);
+		if (node == null)
+			return;
+		if (node.getNodeType() != Node.ELEMENT_NODE) {
+			if (node.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE) {
+				// just notify the change instead of setting data
+				ProcessingInstructionImpl pi = (ProcessingInstructionImpl) node;
+				pi.notifyValueChanged();
+			}
+			return;
+		}
+
+		ElementImpl element = (ElementImpl) node;
+		NamedNodeMap attributes = element.getAttributes();
+		if (attributes == null)
+			return;
+		int length = attributes.getLength();
+		for (int i = 0; i < length; i++) {
+			AttrImpl attr = (AttrImpl) attributes.item(i);
+			if (attr == null)
+				continue;
+			if (attr.getNameRegion() != region)
+				continue;
+
+			String name = flatNode.getText(region);
+			attr.setName(name);
+			break;
+		}
+	}
+
+	/**
+	 * changeAttrValue method
+	 * 
+	 */
+	private void changeAttrValue(IStructuredDocumentRegion flatNode, ITextRegion region) {
+		int offset = flatNode.getStart();
+		if (offset < 0)
+			return;
+		NodeImpl root = (NodeImpl) this.context.getRootNode();
+		if (root == null)
+			return;
+		Node node = root.getNodeAt(offset);
+		if (node == null)
+			return;
+		if (node.getNodeType() != Node.ELEMENT_NODE) {
+			if (node.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE) {
+				// just notify the change instead of setting data
+				ProcessingInstructionImpl pi = (ProcessingInstructionImpl) node;
+				pi.notifyValueChanged();
+			}
+			return;
+		}
+
+		ElementImpl element = (ElementImpl) node;
+		NamedNodeMap attributes = element.getAttributes();
+		if (attributes == null)
+			return;
+		int length = attributes.getLength();
+		for (int i = 0; i < length; i++) {
+			AttrImpl attr = (AttrImpl) attributes.item(i);
+			if (attr == null)
+				continue;
+			if (attr.getValueRegion() != region)
+				continue;
+			// just notify the change instead of setting value
+			attr.notifyValueChanged();
+			break;
+		}
+	}
+
+	/**
+	 * changeData method
+	 * 
+	 */
+	private void changeData(IStructuredDocumentRegion flatNode, ITextRegion region) {
+		int offset = flatNode.getStart();
+		if (offset < 0)
+			return;
+		NodeImpl root = (NodeImpl) this.context.getRootNode();
+		if (root == null)
+			return;
+		Node node = root.getNodeAt(offset);
+		if (node == null)
+			return;
+		switch (node.getNodeType()) {
+			case Node.TEXT_NODE : {
+				TextImpl text = (TextImpl) node;
+				if (text.isSharingStructuredDocumentRegion(flatNode)) {
+					// has consecutive text sharing IStructuredDocumentRegion
+					changeStructuredDocumentRegion(flatNode);
+					return;
+				}
+				this.context.setNextNode(node);
+				cleanupText();
+				break;
+			}
+			case Node.CDATA_SECTION_NODE :
+			case Node.PROCESSING_INSTRUCTION_NODE :
+				break;
+			case Node.COMMENT_NODE :
+			case Node.ELEMENT_NODE :
+				// comment tag
+				changeStructuredDocumentRegion(flatNode);
+				return;
+			default :
+				return;
+		}
+
+		// just notify the change instead of setting data
+		NodeImpl impl = (NodeImpl) node;
+		impl.notifyValueChanged();
+	}
+
+	/**
+	 */
+	private void changeEndTag(IStructuredDocumentRegion flatNode, ITextRegionList newRegions, ITextRegionList oldRegions) {
+		int offset = flatNode.getStart();
+		if (offset < 0)
+			return; // error
+		NodeImpl root = (NodeImpl) this.context.getRootNode();
+		if (root == null)
+			return; // error
+		Node node = root.getNodeAt(offset);
+		if (node == null)
+			return; // error
+
+		if (node.getNodeType() != Node.ELEMENT_NODE) {
+			changeStructuredDocumentRegion(flatNode);
+			return;
+		}
+
+		// check if change is only for close tag
+		if (newRegions != null) {
+			Iterator e = newRegions.iterator();
+			while (e.hasNext()) {
+				ITextRegion region = (ITextRegion) e.next();
+				String regionType = region.getType();
+				if (regionType == DOMRegionContext.XML_TAG_CLOSE)
+					continue;
+
+				// other region has changed
+				changeStructuredDocumentRegion(flatNode);
+				return;
+			}
+		}
+		if (oldRegions != null) {
+			Iterator e = oldRegions.iterator();
+			while (e.hasNext()) {
+				ITextRegion region = (ITextRegion) e.next();
+				String regionType = region.getType();
+				if (regionType == DOMRegionContext.XML_TAG_CLOSE)
+					continue;
+
+				// other region has changed
+				changeStructuredDocumentRegion(flatNode);
+				return;
+			}
+		}
+
+		// change for close tag has no impact
+		// do nothing
+	}
+
+	/**
+	 * changeRegion method
+	 * 
+	 */
+	void changeRegion(RegionChangedEvent change, IStructuredDocumentRegion flatNode, ITextRegion region) {
+		if (flatNode == null || region == null)
+			return;
+		if (this.model.getDocument() == null)
+			return;
+		this.context = new XMLModelContext(this.model.getDocument());
+		
+		//determine if change was whitespace only change
+		boolean isWhitespaceChange = false;
+		if(change.getText() != null && change.getText().length() > 0) {
+			isWhitespaceChange = Character.isWhitespace(change.getText().charAt(0));
+		} else if(change.getDeletedText() != null && change.getDeletedText().length() > 0) {
+			isWhitespaceChange = Character.isWhitespace(change.getDeletedText().charAt(0));
+		}
+
+		// optimize typical cases
+		String regionType = region.getType();
+		if (regionType == DOMRegionContext.XML_CONTENT || regionType == DOMRegionContext.XML_COMMENT_TEXT || regionType == DOMRegionContext.XML_CDATA_TEXT || regionType == DOMRegionContext.BLOCK_TEXT || isNestedContent(regionType)) {
+			changeData(flatNode, region);
+		}
+		else if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) {
+			if (isWhitespaceChange && (change.getOffset() >= flatNode.getStartOffset() + region.getTextEnd())) {
+				// change is entirely in white-space
+				return;
+			}
+			changeAttrName(flatNode, region);
+		}
+		else if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
+			if (isWhitespaceChange && (change.getOffset() >= flatNode.getStartOffset() + region.getTextEnd())) {
+				// change is entirely in white-space
+				return;
+			}
+			changeAttrValue(flatNode, region);
+		}
+		else if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_EQUALS) {
+			if (isWhitespaceChange && (change.getOffset() >= flatNode.getStartOffset() + region.getTextEnd())) {
+				// change is entirely in white-space
+				return;
+			}
+			changeAttrEqual(flatNode, region);
+		}
+		else if (regionType == DOMRegionContext.XML_TAG_NAME || isNestedTagName(regionType)) {
+			if (isWhitespaceChange && (change.getOffset() >= flatNode.getStartOffset() + region.getTextEnd())) {
+				// change is entirely in white-space
+				return;
+			}
+			changeTagName(flatNode, region);
+		}
+		else {
+			changeStructuredDocumentRegion(flatNode);
+		}
+	}
+
+
+
+	/**
+	 */
+	private void changeStartTag(IStructuredDocumentRegion flatNode, ITextRegionList newRegions, ITextRegionList oldRegions) {
+		int offset = flatNode.getStart();
+		if (offset < 0)
+			return; // error
+		NodeImpl root = (NodeImpl) this.context.getRootNode();
+		if (root == null)
+			return; // error
+		Node node = root.getNodeAt(offset);
+		if (node == null)
+			return; // error
+
+		if (node.getNodeType() != Node.ELEMENT_NODE) {
+			changeStructuredDocumentRegion(flatNode);
+			return;
+		}
+		ElementImpl element = (ElementImpl) node;
+
+		// check if changes are only for attributes and close tag
+		boolean tagNameUnchanged = false;
+		if (newRegions != null) {
+			Iterator e = newRegions.iterator();
+			while (e.hasNext()) {
+				ITextRegion region = (ITextRegion) e.next();
+				String regionType = region.getType();
+				if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME || regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_EQUALS || regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE)
+					continue;
+				if (regionType == DOMRegionContext.XML_TAG_CLOSE) {
+					// change from empty tag may have impact on structure
+					if (!element.isEmptyTag())
+						continue;
+				}
+				else if (regionType == DOMRegionContext.XML_TAG_NAME || isNestedTagName(regionType)) {
+					String oldTagName = element.getTagName();
+					String newTagName = flatNode.getText(region);
+					if (oldTagName != null && newTagName != null && oldTagName.equals(newTagName)) {
+						// the tag name is unchanged
+						tagNameUnchanged = true;
+						continue;
+					}
+				}
+
+				// other region has changed
+				changeStructuredDocumentRegion(flatNode);
+				return;
+			}
+		}
+		if (oldRegions != null) {
+			Iterator e = oldRegions.iterator();
+			while (e.hasNext()) {
+				ITextRegion region = (ITextRegion) e.next();
+				String regionType = region.getType();
+				if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME || regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_EQUALS || regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE)
+					continue;
+				if (regionType == DOMRegionContext.XML_TAG_CLOSE) {
+					// change from empty tag may have impact on structure
+					if (!element.isEmptyTag())
+						continue;
+				}
+				else if (regionType == DOMRegionContext.XML_TAG_NAME || isNestedTagName(regionType)) {
+					// if new tag name is unchanged, it's OK
+					if (tagNameUnchanged)
+						continue;
+				}
+
+				// other region has changed
+				changeStructuredDocumentRegion(flatNode);
+				return;
+			}
+		}
+
+		// update attributes
+		ITextRegionList regions = flatNode.getRegions();
+		if (regions == null)
+			return; // error
+		NamedNodeMap attributes = element.getAttributes();
+		if (attributes == null)
+			return; // error
+
+		// first remove attributes
+		int regionIndex = 0;
+		int attrIndex = 0;
+		AttrImpl attr = null;
+		while (attrIndex < attributes.getLength()) {
+			attr = (AttrImpl) attributes.item(attrIndex);
+			if (attr == null) { // error
+				attrIndex++;
+				continue;
+			}
+			ITextRegion nameRegion = attr.getNameRegion();
+			if (nameRegion == null) { // error
+				element.removeAttributeNode(attr);
+				continue;
+			}
+			boolean found = false;
+			for (int i = regionIndex; i < regions.size(); i++) {
+				ITextRegion region = regions.get(i);
+				if (region == nameRegion) {
+					regionIndex = i + 1; // next region
+					found = true;
+					break;
+				}
+			}
+			if (found) {
+				attrIndex++;
+			}
+			else {
+				element.removeAttributeNode(attr);
+			}
+		}
+
+		// insert or update attributes
+		attrIndex = 0; // reset to first
+		AttrImpl newAttr = null;
+		ITextRegion oldValueRegion = null;
+		Iterator e = regions.iterator();
+		while (e.hasNext()) {
+			ITextRegion region = (ITextRegion) e.next();
+			String regionType = region.getType();
+			if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) {
+				if (newAttr != null) {
+					// insert deferred new attribute
+					element.insertAttributeNode(newAttr, attrIndex++);
+					newAttr = null;
+				}
+				else if (attr != null && oldValueRegion != null) {
+					// notify existing attribute value removal
+					attr.notifyValueChanged();
+				}
+
+				oldValueRegion = null;
+				attr = (AttrImpl) attributes.item(attrIndex);
+				if (attr != null && attr.getNameRegion() == region) {
+					// existing attribute
+					attrIndex++;
+					// clear other regions
+					oldValueRegion = attr.getValueRegion();
+					attr.setEqualRegion(null);
+					attr.setValueRegion(null);
+				}
+				else {
+					String name = flatNode.getText(region);
+					attr = (AttrImpl) this.model.getDocument().createAttribute(name);
+					if (attr != null)
+						attr.setNameRegion(region);
+					// defer insertion of new attribute
+					newAttr = attr;
+				}
+			}
+			else if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_EQUALS) {
+				if (attr != null) {
+					attr.setEqualRegion(region);
+				}
+			}
+			else if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
+				if (attr != null) {
+					attr.setValueRegion(region);
+					if (attr != newAttr && oldValueRegion != region) {
+						// notify existing attribute value changed
+						attr.notifyValueChanged();
+					}
+					oldValueRegion = null;
+					attr = null;
+				}
+			}
+		}
+
+		if (newAttr != null) {
+			// insert deferred new attribute
+			element.appendAttributeNode(newAttr);
+		}
+		else if (attr != null && oldValueRegion != null) {
+			// notify existing attribute value removal
+			attr.notifyValueChanged();
+		}
+	}
+
+	/**
+	 * changeStructuredDocumentRegion method
+	 * 
+	 */
+	private void changeStructuredDocumentRegion(IStructuredDocumentRegion flatNode) {
+		if (flatNode == null)
+			return;
+		if (this.model.getDocument() == null)
+			return;
+
+		setupContext(flatNode);
+
+		removeStructuredDocumentRegion(flatNode);
+		// make sure the parent is set to deepest level
+		// when end tag has been removed
+		this.context.setLast();
+		insertStructuredDocumentRegion(flatNode);
+
+		cleanupText();
+		cleanupEndTag();
+	}
+
+	/**
+	 */
+	private void changeTagName(IStructuredDocumentRegion flatNode, ITextRegion region) {
+		int offset = flatNode.getStart();
+		if (offset < 0)
+			return; // error
+		NodeImpl root = (NodeImpl) this.context.getRootNode();
+		if (root == null)
+			return; // error
+		Node node = root.getNodeAt(offset);
+		if (node == null)
+			return; // error
+
+		if (node.getNodeType() != Node.ELEMENT_NODE) {
+			changeStructuredDocumentRegion(flatNode);
+			return;
+		}
+
+		ElementImpl element = (ElementImpl) node;
+		String newTagName = flatNode.getText(region);
+		if (newTagName == null || !element.matchTagName(newTagName)) {
+			// the tag name is changed
+			changeStructuredDocumentRegion(flatNode);
+			return;
+		}
+
+		// the tag name is unchanged
+		// this happens when typing spaces after the tag name
+		// do nothing, but...
+		// if it's not a change in the end tag of an element with the start
+		// tag,
+		// and case has been changed, set to element and notify
+		if (!element.hasStartTag() || StructuredDocumentRegionUtil.getFirstRegionType(flatNode) != DOMRegionContext.XML_END_TAG_OPEN) {
+			String tagName = element.getTagName();
+			if (tagName == null || !tagName.equals(newTagName)) {
+				element.setTagName(newTagName);
+				element.notifyValueChanged();
+			}
+		}
+	}
+
+	/**
+	 * cleanupContext method
+	 */
+	private void cleanupEndTag() {
+		Node parent = this.context.getParentNode();
+		Node next = this.context.getNextNode();
+		while (parent != null) {
+			while (next != null) {
+				if (next.getNodeType() == Node.ELEMENT_NODE) {
+					ElementImpl element = (ElementImpl) next;
+					if (element.isEndTag()) {
+						// floating end tag
+						String tagName = element.getTagName();
+						String rootName = getFindRootName(tagName);
+						ElementImpl start = (ElementImpl) this.context.findStartTag(tagName, rootName);
+						if (start != null) {
+							insertEndTag(start);
+							// move the end tag from 'element' to 'start'
+							start.addEndTag(element);
+							removeNode(element);
+							parent = this.context.getParentNode();
+							next = this.context.getNextNode();
+							continue;
+						}
+					}
+				}
+
+				Node first = next.getFirstChild();
+				if (first != null) {
+					parent = next;
+					next = first;
+					this.context.setNextNode(next);
+				}
+				else {
+					next = next.getNextSibling();
+					this.context.setNextNode(next);
+				}
+			}
+
+			if (parent.getNodeType() == Node.ELEMENT_NODE) {
+				ElementImpl element = (ElementImpl) parent;
+				if (!element.hasEndTag() && element.hasStartTag() && element.getNextSibling() == null) {
+					String tagName = element.getTagName();
+					ElementImpl end = (ElementImpl) this.context.findEndTag(tagName);
+					if (end != null) {
+						// move the end tag from 'end' to 'element'
+						element.addEndTag(end);
+						removeEndTag(end);
+						this.context.setParentNode(parent); // reset context
+						continue;
+					}
+				}
+			}
+
+			next = parent.getNextSibling();
+			parent = parent.getParentNode();
+			if (next != null) {
+				this.context.setNextNode(next);
+			}
+			else {
+				this.context.setParentNode(parent);
+			}
+		}
+	}
+
+	/**
+	 */
+	private void cleanupText() {
+		if (lastTextNode != null) {
+			lastTextNode.notifyValueChanged();
+			lastTextNode = null;
+		}
+		Node parent = this.context.getParentNode();
+		if (parent == null)
+			return; // error
+		Node next = this.context.getNextNode();
+		Node prev = (next == null ? parent.getLastChild() : next.getPreviousSibling());
+
+		TextImpl nextText = null;
+		TextImpl prevText = null;
+		if (next != null && next.getNodeType() == Node.TEXT_NODE) {
+			nextText = (TextImpl) next;
+		}
+		if (prev != null && prev.getNodeType() == Node.TEXT_NODE) {
+			prevText = (TextImpl) prev;
+		}
+		if (nextText == null && prevText == null)
+			return;
+		if (nextText != null && prevText != null) {
+			// consecutive Text nodes created by setupContext(),
+			// concat them
+			IStructuredDocumentRegion flatNode = nextText.getStructuredDocumentRegion();
+			if (flatNode != null)
+				prevText.appendStructuredDocumentRegion(flatNode);
+			Node newNext = next.getNextSibling();
+			parent.removeChild(next);
+			next = null;
+			this.context.setNextNode(newNext);
+		}
+
+		TextImpl childText = (prevText != null ? prevText : nextText);
+		if (childText.getNextSibling() == null && childText.getPreviousSibling() == null) {
+			if (parent.getNodeType() == Node.ELEMENT_NODE) {
+				ElementImpl parentElement = (ElementImpl) parent;
+				if (!parentElement.hasStartTag() && !parentElement.hasEndTag()) {
+					if (childText.isWhitespace() || childText.isInvalid()) {
+						// implicit parent is not required
+						Node newParent = parent.getParentNode();
+						if (newParent != null) {
+							Node newNext = parent.getNextSibling();
+							newParent.removeChild(parent);
+							parent.removeChild(childText);
+							newParent.insertBefore(childText, newNext);
+							if (childText == next) {
+								this.context.setNextNode(childText);
+							}
+							else if (newNext != null) {
+								this.context.setNextNode(newNext);
+							}
+							else {
+								this.context.setParentNode(newParent);
+							}
+							// try again
+							cleanupText();
+						}
+					}
+				}
+			}
+		}
+	}
+
+	/**
+	 * This routine create an Element from comment data for comment style
+	 * elements, such as SSI and METADATA
+	 */
+	protected Element createCommentElement(String data, boolean isJSPTag) {
+		String trimmedData = data.trim();
+		CommentElementConfiguration[] configs = CommentElementRegistry.getInstance().getConfigurations();
+		for (int iConfig = 0; iConfig < configs.length; iConfig++) {
+			CommentElementConfiguration config = configs[iConfig];
+			if ((isJSPTag && !config.acceptJSPComment()) || (!isJSPTag && !config.acceptXMLComment())) {
+				continue;
+			}
+			String[] prefixes = config.getPrefix();
+			for (int iPrefix = 0; iPrefix < prefixes.length; iPrefix++) {
+				if (trimmedData.startsWith(prefixes[iPrefix])) {
+					return config.createElement(this.model.getDocument(), data, isJSPTag);
+				}
+			}
+		}
+		ModelParserAdapter adapter = getParserAdapter();
+		if (adapter != null) {
+			return adapter.createCommentElement(this.model.getDocument(), data, isJSPTag);
+		}
+		return null;
+	}
+
+	/**
+	 * This routine create an implicit Element for given parent and child,
+	 * such as HTML, BODY, HEAD, and TBODY for HTML document.
+	 */
+	protected Element createImplicitElement(Node parent, Node child) {
+		ModelParserAdapter adapter = getParserAdapter();
+		if (adapter != null) {
+			return adapter.createImplicitElement(this.model.getDocument(), parent, child);
+		}
+		return null;
+	}
+
+	/**
+	 */
+	private void demoteNodes(Node root, Node newParent, Node oldParent, Node next) {
+		if (newParent.getNodeType() != Node.ELEMENT_NODE)
+			return;
+		ElementImpl newElement = (ElementImpl) newParent;
+
+		// find next
+		while (next == null) {
+			if (oldParent.getNodeType() != Node.ELEMENT_NODE)
+				return;
+			ElementImpl oldElement = (ElementImpl) oldParent;
+			if (oldElement.hasEndTag())
+				return;
+			oldParent = oldElement.getParentNode();
+			if (oldParent == null)
+				return; // error
+			next = oldElement.getNextSibling();
+		}
+
+		while (next != null) {
+			boolean done = false;
+			if (next.getNodeType() == Node.ELEMENT_NODE) {
+				ElementImpl nextElement = (ElementImpl) next;
+				if (!nextElement.hasStartTag()) {
+					Node nextChild = nextElement.getFirstChild();
+					if (nextChild != null) {
+						// demote children
+						next = nextChild;
+						oldParent = nextElement;
+						continue;
+					}
+
+					if (nextElement.hasEndTag()) {
+						if (nextElement.matchEndTag(newElement)) {
+							// stop at the matched invalid end tag
+							next = nextElement.getNextSibling();
+							oldParent.removeChild(nextElement);
+							newElement.addEndTag(nextElement);
+
+							if (newElement == root)
+								return;
+							Node p = newElement.getParentNode();
+							// check if reached to top
+							if (p == null || p == oldParent || p.getNodeType() != Node.ELEMENT_NODE)
+								return;
+							newElement = (ElementImpl) p;
+							done = true;
+						}
+					}
+					else {
+						// remove implicit element
+						next = nextElement.getNextSibling();
+						oldParent.removeChild(nextElement);
+						done = true;
+					}
+				}
+			}
+
+			if (!done) {
+				if (!canContain(newElement, next)) {
+					if (newElement == root)
+						return;
+					Node p = newElement.getParentNode();
+					// check if reached to top
+					if (p == null || p == oldParent || p.getNodeType() != Node.ELEMENT_NODE)
+						return;
+					newElement = (ElementImpl) p;
+					continue;
+				}
+
+				Node child = next;
+				next = next.getNextSibling();
+				oldParent.removeChild(child);
+				insertNode(newElement, child, null);
+				Node childParent = child.getParentNode();
+				if (childParent != newElement) {
+					newElement = (ElementImpl) childParent;
+				}
+			}
+
+			// find next parent and sibling
+			while (next == null) {
+				if (oldParent.getNodeType() != Node.ELEMENT_NODE)
+					return;
+				ElementImpl oldElement = (ElementImpl) oldParent;
+
+				// dug parent must not have children at this point
+				if (!oldElement.hasChildNodes() && !oldElement.hasStartTag()) {
+					oldParent = oldElement.getParentNode();
+					if (oldParent == null)
+						return; // error
+					next = oldElement;
+					break;
+				}
+
+				if (oldElement.hasEndTag())
+					return;
+				oldParent = oldElement.getParentNode();
+				if (oldParent == null)
+					return; // error
+				next = oldElement.getNextSibling();
+			}
+		}
+	}
+
+	private ModelParserAdapter getParserAdapter() {
+		return (ModelParserAdapter) this.model.getDocument().getAdapterFor(ModelParserAdapter.class);
+	}
+	
+	/**
+	 */
+	protected String getFindRootName(String tagName) {
+		ModelParserAdapter adapter = getParserAdapter();
+		if (adapter != null) {
+			return adapter.getFindRootName(tagName);
+		}
+		return null;
+	}
+
+	/**
+	 */
+	protected final IDOMModel getModel() {
+		return this.model;
+	}
+
+	/**
+	 * insertCDATASection method
+	 * 
+	 */
+	private void insertCDATASection(IStructuredDocumentRegion flatNode) {
+		ITextRegionList regions = flatNode.getRegions();
+		if (regions == null)
+			return;
+
+		CDATASectionImpl cdata = null;
+		try {
+			cdata = (CDATASectionImpl) this.model.getDocument().createCDATASection(null);
+		}
+		catch (DOMException ex) {
+		}
+		if (cdata == null) { // CDATA section might not be supported
+			insertInvalidDecl(flatNode); // regard as invalid decl
+			return;
+		}
+
+		cdata.setStructuredDocumentRegion(flatNode);
+		insertNode(cdata);
+	}
+
+	/**
+	 * insertComment method
+	 * 
+	 */
+	private void insertComment(IStructuredDocumentRegion flatNode) {
+		ITextRegionList regions = flatNode.getRegions();
+		if (regions == null)
+			return;
+
+		StringBuffer data = null;
+		boolean isJSPTag = false;
+		Iterator e = regions.iterator();
+		while (e.hasNext()) {
+			ITextRegion region = (ITextRegion) e.next();
+			String regionType = region.getType();
+			if (isNestedCommentOpen(regionType)) {
+				isJSPTag = true;
+			}
+			else if (regionType == DOMRegionContext.XML_COMMENT_TEXT || isNestedCommentText(regionType)) {
+				if (data == null) {
+					data = new StringBuffer(flatNode.getText(region));
+				}
+				else {
+					data.append(flatNode.getText(region));
+				}
+			}
+		}
+
+		if (data != null) {
+			ElementImpl element = (ElementImpl) createCommentElement(data.toString(), isJSPTag);
+			if (element != null) {
+				if (!isEndTag(element)) {
+					element.setStartStructuredDocumentRegion(flatNode);
+					insertStartTag(element);
+					return;
+				}
+
+				// end tag
+				element.setEndStructuredDocumentRegion(flatNode);
+
+				String tagName = element.getTagName();
+				String rootName = getFindRootName(tagName);
+				ElementImpl start = (ElementImpl) this.context.findStartTag(tagName, rootName);
+				if (start != null) { // start tag found
+					insertEndTag(start);
+					start.addEndTag(element);
+					return;
+				}
+
+				// invalid end tag
+				insertNode(element);
+				return;
+			}
+		}
+
+		CommentImpl comment = (CommentImpl) this.model.getDocument().createComment(null);
+		if (comment == null)
+			return;
+		if (isJSPTag)
+			comment.setJSPTag(true);
+		comment.setStructuredDocumentRegion(flatNode);
+		insertNode(comment);
+	}
+
+	/**
+	 * insertDecl method
+	 * 
+	 */
+	private void insertDecl(IStructuredDocumentRegion flatNode) {
+		ITextRegionList regions = flatNode.getRegions();
+		if (regions == null)
+			return;
+
+		boolean isDocType = false;
+		String name = null;
+		String publicId = null;
+		String systemId = null;
+		Iterator e = regions.iterator();
+		while (e.hasNext()) {
+			ITextRegion region = (ITextRegion) e.next();
+			String regionType = region.getType();
+			if (regionType == DOMRegionContext.XML_DOCTYPE_DECLARATION) {
+				isDocType = true;
+			}
+			else if (regionType == DOMRegionContext.XML_DOCTYPE_NAME) {
+				if (name == null)
+					name = flatNode.getText(region);
+			}
+			else if (regionType == DOMRegionContext.XML_DOCTYPE_EXTERNAL_ID_PUBREF) {
+				if (publicId == null)
+					publicId = StructuredDocumentRegionUtil.getAttrValue(flatNode, region);
+			}
+			else if (regionType == DOMRegionContext.XML_DOCTYPE_EXTERNAL_ID_SYSREF) {
+				if (systemId == null)
+					systemId = StructuredDocumentRegionUtil.getAttrValue(flatNode, region);
+			}
+		}
+
+		// invalid declaration
+		if (!isDocType) {
+			insertInvalidDecl(flatNode);
+			return;
+		}
+
+		DocumentTypeImpl docType = (DocumentTypeImpl) this.model.getDocument().createDoctype(name);
+		if (docType == null)
+			return;
+		if (publicId != null)
+			docType.setPublicId(publicId);
+		if (systemId != null)
+			docType.setSystemId(systemId);
+		docType.setStructuredDocumentRegion(flatNode);
+		insertNode(docType);
+	}
+
+	/**
+	 * insertEndTag method can be used by subclasses, but not overrided.
+	 * 
+	 * @param element
+	 *            org.w3c.dom.Element
+	 */
+	protected void insertEndTag(Element element) {
+		if (element == null)
+			return;
+
+		Node newParent = element.getParentNode();
+		if (newParent == null)
+			return; // error
+
+		if (!((ElementImpl) element).isContainer()) {
+			// just update context
+			Node elementNext = element.getNextSibling();
+			if (elementNext != null)
+				this.context.setNextNode(elementNext);
+			else
+				this.context.setParentNode(newParent);
+			return;
+		}
+
+		// promote children
+		Node newNext = element.getNextSibling();
+		Node oldParent = this.context.getParentNode();
+		if (oldParent == null)
+			return; // error
+		Node oldNext = this.context.getNextNode();
+		promoteNodes(element, newParent, newNext, oldParent, oldNext);
+
+		// update context
+		// re-check the next sibling
+		newNext = element.getNextSibling();
+		if (newNext != null)
+			this.context.setNextNode(newNext);
+		else
+			this.context.setParentNode(newParent);
+	}
+
+	/**
+	 * insertEndTag method
+	 * 
+	 */
+	private void insertEndTag(IStructuredDocumentRegion flatNode) {
+		ITextRegionList regions = flatNode.getRegions();
+		if (regions == null)
+			return;
+
+		String tagName = null;
+		Iterator e = regions.iterator();
+		while (e.hasNext()) {
+			ITextRegion region = (ITextRegion) e.next();
+			String regionType = region.getType();
+			if (regionType == DOMRegionContext.XML_TAG_NAME || isNestedTagName(regionType)) {
+				if (tagName == null)
+					tagName = flatNode.getText(region);
+			}
+		}
+
+		if (tagName == null) { // invalid end tag
+			insertText(flatNode); // regard as invalid text
+			return;
+		}
+
+		String rootName = getFindRootName(tagName);
+		ElementImpl start = (ElementImpl) this.context.findStartTag(tagName, rootName);
+		if (start != null) { // start tag found
+			insertEndTag(start);
+			start.setEndStructuredDocumentRegion(flatNode);
+			return;
+		}
+
+		// invalid end tag
+		ElementImpl end = null;
+		try {
+			end = (ElementImpl) this.model.getDocument().createElement(tagName);
+		}
+		catch (DOMException ex) {
+		}
+		if (end == null) { // invalid end tag
+			insertText(flatNode); // regard as invalid text
+			return;
+		}
+		end.setEndStructuredDocumentRegion(flatNode);
+		insertNode(end);
+	}
+
+	/**
+	 * insertEntityRef method
+	 * 
+	 */
+	private void insertEntityRef(IStructuredDocumentRegion flatNode) {
+		ITextRegionList regions = flatNode.getRegions();
+		if (regions == null)
+			return;
+
+		String name = null;
+		Iterator e = regions.iterator();
+		while (e.hasNext()) {
+			ITextRegion region = (ITextRegion) e.next();
+			String regionType = region.getType();
+			if (regionType == DOMRegionContext.XML_ENTITY_REFERENCE || regionType == DOMRegionContext.XML_CHAR_REFERENCE) {
+				if (name == null)
+					name = StructuredDocumentRegionUtil.getEntityRefName(flatNode, region);
+			}
+		}
+
+		if (name == null) { // invalid entity
+			insertText(flatNode);
+			return;
+		}
+
+		// ISSUE: avoid this cast
+		String value = ((DocumentImpl)this.model.getDocument()).getCharValue(name);
+		if (value != null) { // character entity
+			TextImpl text = (TextImpl) this.context.findPreviousText();
+			if (text != null) { // existing text found
+				// do not append data
+				text.appendStructuredDocumentRegion(flatNode);
+				// Adjacent text nodes, where changes were queued
+				if (lastTextNode != null && lastTextNode != text)
+					lastTextNode.notifyValueChanged();
+				lastTextNode = text;
+				return;
+			}
+
+			// new text
+			text = (TextImpl) this.model.getDocument().createTextNode(null);
+			if (text == null)
+				return;
+			text.setStructuredDocumentRegion(flatNode);
+			insertNode(text);
+			return;
+		}
+
+		// general entity reference
+		EntityReferenceImpl ref = null;
+		try {
+			ref = (EntityReferenceImpl) this.model.getDocument().createEntityReference(name);
+		}
+		catch (DOMException ex) {
+		}
+		if (ref == null) { // entity reference might not be supported
+			insertText(flatNode); // regard as invalid text
+			return;
+		}
+
+		ref.setStructuredDocumentRegion(flatNode);
+		insertNode(ref);
+	}
+
+	/**
+	 * insertInvalidDecl method
+	 * 
+	 */
+	private void insertInvalidDecl(IStructuredDocumentRegion flatNode) {
+		ITextRegionList regions = flatNode.getRegions();
+		if (regions == null)
+			return;
+
+		ElementImpl element = null;
+		try {
+			element = (ElementImpl) this.model.getDocument().createElement("!");//$NON-NLS-1$
+		}
+		catch (DOMException ex) {
+		}
+		if (element == null) { // invalid tag
+			insertText(flatNode); // regard as invalid text
+			return;
+		}
+		element.setEmptyTag(true);
+		element.setStartStructuredDocumentRegion(flatNode);
+		insertNode(element);
+	}
+
+	/**
+	 * insertJSPTag method
+	 * 
+	 */
+	private void insertNestedTag(IStructuredDocumentRegion flatNode) {
+		ITextRegionList regions = flatNode.getRegions();
+		if (regions == null)
+			return;
+
+		String tagName = null;
+		AttrImpl attr = null;
+		List attrNodes = null;
+		boolean isCloseTag = false;
+		Iterator e = regions.iterator();
+		while (e.hasNext()) {
+			ITextRegion region = (ITextRegion) e.next();
+			String regionType = region.getType();
+			if (isNestedTagOpen(regionType) || isNestedTagName(regionType)) {
+				tagName = computeNestedTag(regionType, tagName, flatNode, region);
+			}
+			else if (isNestedTagClose(regionType)) {
+				isCloseTag = true;
+			}
+			else if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) {
+				String name = flatNode.getText(region);
+				attr = (AttrImpl) this.model.getDocument().createAttribute(name);
+				if (attr != null) {
+					attr.setNameRegion(region);
+					if (attrNodes == null)
+						attrNodes = new ArrayList();
+					attrNodes.add(attr);
+				}
+			}
+			else if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_EQUALS) {
+				if (attr != null) {
+					attr.setEqualRegion(region);
+				}
+			}
+			else if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
+				if (attr != null) {
+					attr.setValueRegion(region);
+					attr = null;
+				}
+			}
+		}
+
+		if (tagName == null) {
+			if (isCloseTag) {
+				// close JSP tag
+				Node parent = this.context.getParentNode();
+				if (parent != null && parent.getNodeType() == Node.ELEMENT_NODE) {
+					ElementImpl start = (ElementImpl) parent;
+					if (start.isJSPContainer()) {
+						insertEndTag(start);
+						start.setEndStructuredDocumentRegion(flatNode);
+						return;
+					}
+				}
+			}
+			// invalid JSP tag
+			insertText(flatNode); // regard as invalid text
+			return;
+		}
+
+		ElementImpl element = null;
+		try {
+			element = (ElementImpl) this.model.getDocument().createElement(tagName);
+		}
+		catch (DOMException ex) {
+		}
+		if (element == null) { // invalid tag
+			insertText(flatNode); // regard as invalid text
+			return;
+		}
+		if (attrNodes != null) {
+			for (int i = 0; i < attrNodes.size(); i++) {
+				element.appendAttributeNode((Attr) attrNodes.get(i));
+			}
+		}
+		element.setJSPTag(true);
+		element.setStartStructuredDocumentRegion(flatNode);
+		insertStartTag(element);
+	}
+
+	protected boolean isNestedTagClose(String regionType) {
+		boolean result = false;
+		return result;
+	}
+
+	protected boolean isNestedTagOpen(String regionType) {
+		boolean result = false;
+		return result;
+	}
+
+	protected String computeNestedTag(String regionType, String tagName, IStructuredDocumentRegion structuredDocumentRegion, ITextRegion region) {
+		return tagName;
+	}
+
+	/**
+	 * insertNode method
+	 * 
+	 * @param child
+	 *            org.w3c.dom.Node
+	 */
+	private void insertNode(Node node) {
+		if(node != null && this.context != null) {
+			Node parent = this.context.getParentNode();
+			if(parent != null) {
+				Node next = this.context.getNextNode();
+				// Reset parents which are closed container elements; should not be parents
+				if(parent.getNodeType() == Node.ELEMENT_NODE) {
+					String type = ((ElementImpl)parent).getStartStructuredDocumentRegion().getLastRegion().getType();
+					if(((ElementImpl)parent).isContainer() && type == DOMRegionContext.XML_EMPTY_TAG_CLOSE) {
+						next = parent.getNextSibling();
+						parent = parent.getParentNode();
+					}
+					else {
+						ModelParserAdapter adapter = getParserAdapter();
+						if (adapter != null) {
+							while (parent.getNodeType() == Node.ELEMENT_NODE && !adapter.canContain( (Element) parent, node) && adapter.isEndTagOmissible((Element) parent)) {
+								next = parent.getNextSibling();
+								parent = parent.getParentNode();
+							}
+						}
+					}
+				}	
+				insertNode(parent, node, next);
+				next = node.getNextSibling();
+				if (next != null) {
+					this.context.setNextNode(next);
+				} else {
+					this.context.setParentNode(node.getParentNode());
+				}
+			}
+		}
+	}
+
+	/**
+	 */
+	private void insertNode(Node parent, Node node, Node next) {
+		while (next != null && next.getNodeType() == Node.ELEMENT_NODE) {
+			ElementImpl nextElement = (ElementImpl) next;
+			if (nextElement.hasStartTag())
+				break;
+			if (!canBeImplicitTag(nextElement, node))
+				break;
+			parent = nextElement;
+			next = nextElement.getFirstChild();
+		}
+		Element implicitElement = createImplicitElement(parent, node);
+		if (implicitElement != null)
+			node = implicitElement;
+		parent.insertBefore(node, next);
+	}
+
+	/**
+	 * insertPI method
+	 * 
+	 */
+	private void insertPI(IStructuredDocumentRegion flatNode) {
+		ITextRegionList regions = flatNode.getRegions();
+		if (regions == null)
+			return;
+
+		String target = null;
+		Iterator e = regions.iterator();
+		while (e.hasNext()) {
+			ITextRegion region = (ITextRegion) e.next();
+			String regionType = region.getType();
+			if (regionType == DOMRegionContext.XML_PI_OPEN || regionType == DOMRegionContext.XML_PI_CLOSE)
+				continue;
+			if (target == null)
+				target = flatNode.getText(region);
+		}
+
+		ProcessingInstructionImpl pi = (ProcessingInstructionImpl) this.model.getDocument().createProcessingInstruction(target, null);
+		if (pi == null)
+			return;
+		pi.setStructuredDocumentRegion(flatNode);
+		insertNode(pi);
+	}
+
+	/**
+	 * insertStartTag method can be used by subclasses, but not overridden.
+	 * 
+	 * @param element
+	 *            org.w3c.dom.Element
+	 */
+	protected void insertStartTag(Element element) {
+		if (element == null)
+			return;
+		if (this.context == null)
+			return;
+
+		insertNode(element);
+
+		ElementImpl newElement = (ElementImpl) element;
+		if (newElement.isEmptyTag() || !newElement.isContainer())
+			return;
+
+		// Ignore container tags that have been closed
+		String type = newElement.getStartStructuredDocumentRegion().getLastRegion().getType();
+		if(newElement.isContainer() && type == DOMRegionContext.XML_EMPTY_TAG_CLOSE)
+			return;
+
+		// demote siblings
+		Node parent = this.context.getParentNode();
+		if (parent == null)
+			return; // error
+		Node next = this.context.getNextNode();
+		demoteNodes(element, element, parent, next);
+
+		// update context
+		Node firstChild = element.getFirstChild();
+		if (firstChild != null)
+			this.context.setNextNode(firstChild);
+		else
+			this.context.setParentNode(element);
+	}
+
+	/**
+	 * insertStartTag method
+	 * 
+	 */
+	private void insertStartTag(IStructuredDocumentRegion flatNode) {
+		ITextRegionList regions = flatNode.getRegions();
+		if (regions == null)
+			return;
+
+		String tagName = null;
+		boolean isEmptyTag = false;
+		AttrImpl attr = null;
+		List attrNodes = null;
+		Iterator e = regions.iterator();
+		while (e.hasNext()) {
+			ITextRegion region = (ITextRegion) e.next();
+			String regionType = region.getType();
+			if (regionType == DOMRegionContext.XML_TAG_NAME || isNestedTagName(regionType)) {
+				if (tagName == null)
+					tagName = flatNode.getText(region);
+			}
+			else if (regionType == DOMRegionContext.XML_EMPTY_TAG_CLOSE) {
+				isEmptyTag = true;
+			}
+			else if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) {
+				String name = flatNode.getText(region);
+				attr = (AttrImpl) this.model.getDocument().createAttribute(name);
+				if (attr != null) {
+					attr.setNameRegion(region);
+					if (attrNodes == null)
+						attrNodes = new ArrayList();
+					attrNodes.add(attr);
+				}
+			}
+			else if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_EQUALS) {
+				if (attr != null) {
+					attr.setEqualRegion(region);
+				}
+			}
+			else if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
+				if (attr != null) {
+					attr.setValueRegion(region);
+					attr = null;
+				}
+			}
+		}
+
+		if (tagName == null) { // invalid start tag
+			insertText(flatNode); // regard as invalid text
+			return;
+		}
+
+		ElementImpl element = null;
+		try {
+			element = (ElementImpl) this.model.getDocument().createElement(tagName);
+		}
+		catch (DOMException ex) {
+			// typically invalid name
+		}
+		if (element == null) { // invalid tag
+			insertText(flatNode); // regard as invalid text
+			return;
+		}
+		if (attrNodes != null) {
+			for (int i = 0; i < attrNodes.size(); i++) {
+				element.appendAttributeNode((Attr) attrNodes.get(i));
+			}
+		}
+		if (isEmptyTag)
+			element.setEmptyTag(true);
+		element.setStartStructuredDocumentRegion(flatNode);
+		insertStartTag(element);
+	}
+
+	/**
+	 * insertStructuredDocumentRegion method
+	 * 
+	 */
+	protected void insertStructuredDocumentRegion(IStructuredDocumentRegion flatNode) {
+		String regionType = StructuredDocumentRegionUtil.getFirstRegionType(flatNode);
+		boolean isTextNode = false;
+		if (regionType == DOMRegionContext.XML_TAG_OPEN) {
+			insertStartTag(flatNode);
+		}
+		else if (regionType == DOMRegionContext.XML_END_TAG_OPEN) {
+			insertEndTag(flatNode);
+		}
+		else if (regionType == DOMRegionContext.XML_COMMENT_OPEN || isNestedCommentOpen(regionType)) {
+			insertComment(flatNode);
+		}
+		else if (regionType == DOMRegionContext.XML_ENTITY_REFERENCE || regionType == DOMRegionContext.XML_CHAR_REFERENCE) {
+			insertEntityRef(flatNode);
+			isTextNode = true;
+		}
+		else if (regionType == DOMRegionContext.XML_DECLARATION_OPEN) {
+			insertDecl(flatNode);
+		}
+		else if (regionType == DOMRegionContext.XML_PI_OPEN) {
+			insertPI(flatNode);
+		}
+		else if (regionType == DOMRegionContext.XML_CDATA_OPEN) {
+			insertCDATASection(flatNode);
+		}
+		else if (isNestedTag(regionType)) {
+			insertNestedTag(flatNode);
+		}
+		else {
+			insertText(flatNode);
+			isTextNode = true;
+		}
+
+		// Changes to text regions are queued up, and once the value is done changing a notification is sent
+		if (!isTextNode && lastTextNode != null) {
+			lastTextNode.notifyValueChanged();
+			lastTextNode = null;
+		}
+	}
+
+	protected boolean isNestedTag(String regionType) {
+		boolean result = false;
+		return result;
+	}
+
+	protected boolean isNestedCommentText(String regionType) {
+		boolean result = false;
+		return result;
+	}
+
+
+	protected boolean isNestedCommentOpen(String regionType) {
+		boolean result = false;
+		return result;
+	}
+
+	protected boolean isNestedTagName(String regionType) {
+		boolean result = false;
+		return result;
+	}
+
+	protected boolean isNestedContent(String regionType) {
+		boolean result = false;
+		return result;
+	}
+
+	/**
+	 * insertText method Can be called from subclasses, not to be overrided or
+	 * re-implemented.
+	 * 
+	 */
+	protected void insertText(IStructuredDocumentRegion flatNode) {
+		TextImpl text = (TextImpl) this.context.findPreviousText();
+		if (text != null) { // existing text found
+			text.appendStructuredDocumentRegion(flatNode);
+			// Adjacent text nodes, where changes were queued
+			if (lastTextNode != null && lastTextNode != text)
+				lastTextNode.notifyValueChanged();
+			lastTextNode = text;
+			return;
+		}
+
+		// new text
+		text = (TextImpl) this.model.getDocument().createTextNode(null);
+		if (text == null)
+			return;
+		text.setStructuredDocumentRegion(flatNode);
+		insertNode(text);
+	}
+
+	/**
+	 */
+	protected boolean isEndTag(IDOMElement element) {
+		ModelParserAdapter adapter = getParserAdapter();
+		if (adapter != null) {
+			return adapter.isEndTag(element);
+		}
+		return element.isEndTag();
+	}
+
+	/**
+	 */
+	private void promoteNodes(Node root, Node newParent, Node newNext, Node oldParent, Node next) {
+		ElementImpl newElement = null;
+		if (newParent.getNodeType() == Node.ELEMENT_NODE) {
+			newElement = (ElementImpl) newParent;
+		}
+
+		Node rootParent = root.getParentNode();
+		while (oldParent != rootParent) {
+			while (next != null) {
+				boolean done = false;
+				boolean endTag = false;
+				if (next.getNodeType() == Node.ELEMENT_NODE) {
+					ElementImpl nextElement = (ElementImpl) next;
+					if (!nextElement.hasStartTag()) {
+						Node nextChild = nextElement.getFirstChild();
+						if (nextChild != null) {
+							// promote children
+							next = nextChild;
+							oldParent = nextElement;
+							continue;
+						}
+
+						if (nextElement.hasEndTag()) {
+							if (nextElement.matchEndTag(newElement)) {
+								endTag = true;
+							}
+						}
+						else {
+							// remove implicit element
+							next = nextElement.getNextSibling();
+							oldParent.removeChild(nextElement);
+							done = true;
+						}
+					}
+				}
+
+				if (!done) {
+					if (!endTag && newElement != null && !canContain(newElement, next)) {
+						newParent = newElement.getParentNode();
+						if (newParent == null)
+							return; // error
+						Node elementNext = newElement.getNextSibling();
+						// promote siblings
+						promoteNodes(newElement, newParent, elementNext, newElement, newNext);
+						newNext = newElement.getNextSibling();
+						if (newParent.getNodeType() == Node.ELEMENT_NODE) {
+							newElement = (ElementImpl) newParent;
+						}
+						else {
+							newElement = null;
+						}
+						continue;
+					}
+
+					Node child = next;
+					next = next.getNextSibling();
+					oldParent.removeChild(child);
+					insertNode(newParent, child, newNext);
+					Node childParent = child.getParentNode();
+					if (childParent != newParent) {
+						newParent = childParent;
+						newElement = (ElementImpl) newParent;
+						newNext = child.getNextSibling();
+					}
+				}
+			}
+
+			if (oldParent.getNodeType() != Node.ELEMENT_NODE)
+				return;
+			ElementImpl oldElement = (ElementImpl) oldParent;
+			oldParent = oldElement.getParentNode();
+			if (oldParent == null)
+				return; // error
+			next = oldElement.getNextSibling();
+
+			if (oldElement.hasEndTag()) {
+				Element end = null;
+				if (!oldElement.hasChildNodes() && !oldElement.hasStartTag()) {
+					oldParent.removeChild(oldElement);
+					end = oldElement;
+				}
+				else {
+					end = oldElement.removeEndTag();
+				}
+				if (end != null) {
+					insertNode(newParent, end, newNext);
+					Node endParent = end.getParentNode();
+					if (endParent != newParent) {
+						newParent = endParent;
+						newElement = (ElementImpl) newParent;
+						newNext = end.getNextSibling();
+					}
+				}
+			}
+		}
+	}
+
+	/**
+	 * removeEndTag method
+	 * 
+	 * @param element
+	 *            org.w3c.dom.Element
+	 */
+	private void removeEndTag(Element element) {
+		if (element == null)
+			return;
+		if (this.context == null)
+			return;
+
+		Node parent = element.getParentNode();
+		if (parent == null)
+			return; // error
+
+		if (!((ElementImpl) element).isContainer()) {
+			// just update context
+			Node elementNext = element.getNextSibling();
+			if (elementNext != null)
+				this.context.setNextNode(elementNext);
+			else
+				this.context.setParentNode(parent);
+			return;
+		}
+
+		// demote siblings
+		Node next = element.getNextSibling();
+		ElementImpl newElement = (ElementImpl) element;
+		// find new parent
+		for (Node last = newElement.getLastChild(); last != null; last = last.getLastChild()) {
+			if (last.getNodeType() != Node.ELEMENT_NODE)
+				break;
+			ElementImpl lastElement = (ElementImpl) last;
+			if (lastElement.hasEndTag() || lastElement.isEmptyTag() || !lastElement.isContainer())
+				break;
+			newElement = lastElement;
+		}
+		Node lastChild = newElement.getLastChild();
+		demoteNodes(element, newElement, parent, next);
+
+		// update context
+		Node newNext = null;
+		if (lastChild != null)
+			newNext = lastChild.getNextSibling();
+		else
+			newNext = newElement.getFirstChild();
+		if (newNext != null)
+			this.context.setNextNode(newNext);
+		else
+			this.context.setParentNode(newElement);
+	}
+
+	/**
+	 * Remove the specified node if it is no longer required implicit tag with
+	 * remaining child nodes promoted.
+	 */
+	private Element removeImplicitElement(Node parent) {
+		if (parent == null)
+			return null;
+		if (parent.getNodeType() != Node.ELEMENT_NODE)
+			return null;
+		ElementImpl element = (ElementImpl) parent;
+		if (!element.isImplicitTag())
+			return null;
+		if (canBeImplicitTag(element))
+			return null;
+
+		Node elementParent = element.getParentNode();
+		if (elementParent == null)
+			return null; // error
+		Node firstChild = element.getFirstChild();
+		Node child = firstChild;
+		Node elementNext = element.getNextSibling();
+		while (child != null) {
+			Node nextChild = child.getNextSibling();
+			element.removeChild(child);
+			elementParent.insertBefore(child, elementNext);
+			child = nextChild;
+		}
+
+		// reset context
+		if (this.context.getParentNode() == element) {
+			Node oldNext = this.context.getNextNode();
+			if (oldNext != null) {
+				this.context.setNextNode(oldNext);
+			}
+			else {
+				if (elementNext != null) {
+					this.context.setNextNode(elementNext);
+				}
+				else {
+					this.context.setParentNode(elementParent);
+				}
+			}
+		}
+		else if (this.context.getNextNode() == element) {
+			if (firstChild != null) {
+				this.context.setNextNode(firstChild);
+			}
+			else {
+				if (elementNext != null) {
+					this.context.setNextNode(elementNext);
+				}
+				else {
+					this.context.setParentNode(elementParent);
+				}
+			}
+		}
+
+		removeNode(element);
+		return element;
+	}
+
+	/**
+	 * removeNode method
+	 * 
+	 * @param node
+	 *            org.w3c.dom.Node
+	 */
+	private void removeNode(Node node) {
+		if (node == null)
+			return;
+		if (this.context == null)
+			return;
+
+		Node parent = node.getParentNode();
+		if (parent == null)
+			return;
+		Node next = node.getNextSibling();
+		Node prev = node.getPreviousSibling();
+
+		// update context
+		Node oldParent = this.context.getParentNode();
+		if (node == oldParent) {
+			if (next != null)
+				this.context.setNextNode(next);
+			else
+				this.context.setParentNode(parent);
+		}
+		else {
+			Node oldNext = this.context.getNextNode();
+			if (node == oldNext) {
+				this.context.setNextNode(next);
+			}
+		}
+
+		parent.removeChild(node);
+
+		if (removeImplicitElement(parent) != null)
+			return;
+
+		// demote sibling
+		if (prev != null && prev.getNodeType() == Node.ELEMENT_NODE) {
+			ElementImpl newElement = (ElementImpl) prev;
+			if (!newElement.hasEndTag() && !newElement.isEmptyTag() && newElement.isContainer()) {
+				// find new parent
+				for (Node last = newElement.getLastChild(); last != null; last = last.getLastChild()) {
+					if (last.getNodeType() != Node.ELEMENT_NODE)
+						break;
+					ElementImpl lastElement = (ElementImpl) last;
+					if (lastElement.hasEndTag() || lastElement.isEmptyTag() || !lastElement.isContainer())
+						break;
+					newElement = lastElement;
+				}
+				Node lastChild = newElement.getLastChild();
+				demoteNodes(prev, newElement, parent, next);
+
+				// update context
+				Node newNext = null;
+				if (lastChild != null)
+					newNext = lastChild.getNextSibling();
+				else
+					newNext = newElement.getFirstChild();
+				if (newNext != null)
+					this.context.setNextNode(newNext);
+				else
+					this.context.setParentNode(newElement);
+			}
+		}
+	}
+
+	/**
+	 * removeStartTag method
+	 * 
+	 * @param element
+	 *            org.w3c.dom.Element
+	 */
+	private void removeStartTag(Element element) {
+		if (element == null)
+			return;
+		if (this.context == null)
+			return;
+
+		// for implicit tag
+		ElementImpl oldElement = (ElementImpl) element;
+		if (canBeImplicitTag(oldElement)) {
+			Node newParent = null;
+			Node prev = oldElement.getPreviousSibling();
+			if (prev != null && prev.getNodeType() == Node.ELEMENT_NODE) {
+				ElementImpl prevElement = (ElementImpl) prev;
+				if (!prevElement.hasEndTag()) {
+					if (prevElement.hasStartTag() || prevElement.matchTagName(oldElement.getTagName())) {
+						newParent = prevElement;
+					}
+				}
+			}
+			if (newParent == null) {
+				// this element should stay as implicit tag
+				// just remove all attributes
+				oldElement.removeStartTag();
+
+				// update context
+				Node child = oldElement.getFirstChild();
+				if (child != null) {
+					this.context.setNextNode(child);
+				}
+				else if (oldElement.hasEndTag()) {
+					this.context.setParentNode(oldElement);
+				}
+				return;
+			}
+		}
+		// for comment tag
+		if (oldElement.isCommentTag())
+			oldElement.removeStartTag();
+
+		// promote children
+		Node elementParent = element.getParentNode();
+		Node parent = elementParent;
+		if (parent == null)
+			return;
+		Node first = element.getFirstChild();
+		Node firstElement = null; // for the case first is removed as end
+		// tag
+		if (first != null) {
+			// find new parent for children
+			ElementImpl newElement = null;
+			for (Node last = element.getPreviousSibling(); last != null; last = last.getLastChild()) {
+				if (last.getNodeType() != Node.ELEMENT_NODE)
+					break;
+				ElementImpl lastElement = (ElementImpl) last;
+				if (lastElement.hasEndTag() || lastElement.isEmptyTag() || !lastElement.isContainer())
+					break;
+				newElement = lastElement;
+			}
+			Node next = first;
+			if (newElement != null) {
+				while (next != null) {
+					if (!newElement.hasEndTag() && newElement.hasStartTag() && next.getNodeType() == Node.ELEMENT_NODE) {
+						ElementImpl nextElement = (ElementImpl) next;
+						if (!nextElement.hasStartTag() && nextElement.hasEndTag() && nextElement.matchEndTag(newElement)) {
+							// stop at the matched invalid end tag
+							Node elementChild = nextElement.getFirstChild();
+							while (elementChild != null) {
+								Node nextChild = elementChild.getNextSibling();
+								nextElement.removeChild(elementChild);
+								newElement.appendChild(elementChild);
+								elementChild = nextChild;
+							}
+
+							next = nextElement.getNextSibling();
+							element.removeChild(nextElement);
+							newElement.addEndTag(nextElement);
+							if (nextElement == first)
+								firstElement = newElement;
+
+							Node newParent = newElement.getParentNode();
+							if (newParent == parent)
+								break;
+							if (newParent == null || newParent.getNodeType() != Node.ELEMENT_NODE)
+								break; // error
+							newElement = (ElementImpl) newParent;
+							continue;
+						}
+					}
+					if (!canContain(newElement, next)) {
+						Node newParent = newElement.getParentNode();
+						if (newParent == parent)
+							break;
+						if (newParent == null || newParent.getNodeType() != Node.ELEMENT_NODE)
+							break; // error
+						newElement = (ElementImpl) newParent;
+						continue;
+					}
+					Node child = next;
+					next = next.getNextSibling();
+					element.removeChild(child);
+					newElement.appendChild(child);
+				}
+				newElement = null;
+			}
+			if (parent.getNodeType() == Node.ELEMENT_NODE) {
+				newElement = (ElementImpl) parent;
+			}
+			while (next != null) {
+				if (newElement == null || canContain(newElement, next)) {
+					Node child = next;
+					next = next.getNextSibling();
+					element.removeChild(child);
+					parent.insertBefore(child, element);
+					continue;
+				}
+
+				parent = newElement.getParentNode();
+				if (parent == null)
+					return;
+
+				// promote siblings
+				Node newNext = newElement.getNextSibling();
+				Node child = element;
+				while (child != null) {
+					Node nextChild = child.getNextSibling();
+					newElement.removeChild(child);
+					parent.insertBefore(child, newNext);
+					child = nextChild;
+				}
+
+				// leave the old end tag where it is
+				if (newElement.hasEndTag()) {
+					Element end = newElement.removeEndTag();
+					if (end != null) {
+						parent.insertBefore(end, newNext);
+					}
+				}
+				if (!newElement.hasStartTag()) {
+					// implicit element
+					if (!newElement.hasChildNodes()) {
+						parent.removeChild(newElement);
+					}
+				}
+
+				if (parent.getNodeType() == Node.ELEMENT_NODE) {
+					newElement = (ElementImpl) parent;
+				}
+				else {
+					newElement = null;
+				}
+			}
+		}
+
+		Node newNext = element;
+		Node startElement = null; // for the case element is removed as end
+		// tag
+		if (oldElement.hasEndTag()) {
+			// find new parent for invalid end tag and siblings
+			ElementImpl newElement = null;
+			for (Node last = element.getPreviousSibling(); last != null; last = last.getLastChild()) {
+				if (last.getNodeType() != Node.ELEMENT_NODE)
+					break;
+				ElementImpl lastElement = (ElementImpl) last;
+				if (lastElement.hasEndTag() || lastElement.isEmptyTag() || !lastElement.isContainer())
+					break;
+				newElement = lastElement;
+			}
+			if (newElement != null) {
+				// demote invalid end tag and sibling
+				Node next = element;
+				while (next != null) {
+					if (!newElement.hasEndTag() && newElement.hasStartTag() && next.getNodeType() == Node.ELEMENT_NODE) {
+						ElementImpl nextElement = (ElementImpl) next;
+						if (!nextElement.hasStartTag() && nextElement.hasEndTag() && nextElement.matchEndTag(newElement)) {
+							// stop at the matched invalid end tag
+							Node elementChild = nextElement.getFirstChild();
+							while (elementChild != null) {
+								Node nextChild = elementChild.getNextSibling();
+								nextElement.removeChild(elementChild);
+								newElement.appendChild(elementChild);
+								elementChild = nextChild;
+							}
+
+							next = nextElement.getNextSibling();
+							parent.removeChild(nextElement);
+							newElement.addEndTag(nextElement);
+							if (nextElement == newNext)
+								startElement = newElement;
+
+							Node newParent = newElement.getParentNode();
+							if (newParent == parent)
+								break;
+							if (newParent == null || newParent.getNodeType() != Node.ELEMENT_NODE)
+								break; // error
+							newElement = (ElementImpl) newParent;
+							continue;
+						}
+					}
+					if (!canContain(newElement, next)) {
+						Node newParent = newElement.getParentNode();
+						if (newParent == parent)
+							break;
+						if (newParent == null || newParent.getNodeType() != Node.ELEMENT_NODE)
+							break; // error
+						newElement = (ElementImpl) newParent;
+						continue;
+					}
+					Node child = next;
+					next = next.getNextSibling();
+					parent.removeChild(child);
+					if (child == oldElement) {
+						if (!oldElement.isCommentTag()) {
+							// clone (re-create) end tag
+							Element end = oldElement.removeEndTag();
+							if (end != null) {
+								child = end;
+								newNext = end;
+							}
+						}
+					}
+					newElement.appendChild(child);
+				}
+			}
+			else {
+				if (!oldElement.isCommentTag()) {
+					// clone (re-create) end tag
+					Element end = oldElement.removeEndTag();
+					if (end != null) {
+						parent.insertBefore(end, oldElement);
+						parent.removeChild(oldElement);
+						newNext = end;
+					}
+				}
+			}
+		}
+		else {
+			newNext = oldElement.getNextSibling();
+			parent.removeChild(oldElement);
+		}
+
+		// update context
+		Node oldParent = this.context.getParentNode();
+		Node oldNext = this.context.getNextNode();
+		if (element == oldParent) {
+			if (oldNext != null) {
+				this.context.setNextNode(oldNext); // reset for new parent
+			}
+			else if (newNext != null) {
+				this.context.setNextNode(newNext);
+			}
+			else {
+				this.context.setParentNode(parent);
+			}
+		}
+		else if (element == oldNext) {
+			if (firstElement != null) {
+				this.context.setParentNode(firstElement);
+			}
+			else if (first != null) {
+				this.context.setNextNode(first);
+			}
+			else if (startElement != null) {
+				this.context.setParentNode(startElement);
+			}
+			else {
+				this.context.setNextNode(newNext);
+			}
+		}
+
+		removeImplicitElement(elementParent);
+	}
+
+	/**
+	 * removeStructuredDocumentRegion method
+	 * 
+	 */
+	private void removeStructuredDocumentRegion(IStructuredDocumentRegion oldStructuredDocumentRegion) {
+		NodeImpl next = (NodeImpl) this.context.getNextNode();
+		if (next != null) {
+			short nodeType = next.getNodeType();
+			if (nodeType != Node.ELEMENT_NODE) {
+				IStructuredDocumentRegion flatNode = next.getStructuredDocumentRegion();
+				if (flatNode == oldStructuredDocumentRegion) {
+					removeNode(next);
+					return;
+				}
+				if (nodeType != Node.TEXT_NODE) {
+					throw new StructuredDocumentRegionManagementException();
+				}
+				if (flatNode == null) {
+					// this is the case for empty Text
+					// remove and continue
+					removeNode(next);
+					removeStructuredDocumentRegion(oldStructuredDocumentRegion);
+					return;
+				}
+				TextImpl text = (TextImpl) next;
+				boolean isShared = text.isSharingStructuredDocumentRegion(oldStructuredDocumentRegion);
+				if (isShared) {
+					// make sure there is next Text node sharing this
+					TextImpl nextText = (TextImpl) this.context.findNextText();
+					if (nextText == null || !nextText.hasStructuredDocumentRegion(oldStructuredDocumentRegion)) {
+						isShared = false;
+					}
+				}
+				oldStructuredDocumentRegion = text.removeStructuredDocumentRegion(oldStructuredDocumentRegion);
+				if (oldStructuredDocumentRegion == null) {
+					throw new StructuredDocumentRegionManagementException();
+				}
+				if (text.getStructuredDocumentRegion() == null) {
+					// this is the case partial IStructuredDocumentRegion is
+					// removed
+					removeNode(text);
+				}
+				else {
+					// notify the change
+					text.notifyValueChanged();
+				}
+				// if shared, continue to remove IStructuredDocumentRegion
+				// from them
+				if (isShared)
+					removeStructuredDocumentRegion(oldStructuredDocumentRegion);
+				return;
+			}
+
+			ElementImpl element = (ElementImpl) next;
+			if (element.hasStartTag()) {
+				IStructuredDocumentRegion flatNode = element.getStartStructuredDocumentRegion();
+				if (flatNode != oldStructuredDocumentRegion) {
+					throw new StructuredDocumentRegionManagementException();
+				}
+				if (element.hasEndTag() || element.hasChildNodes()) {
+					element.setStartStructuredDocumentRegion(null);
+					removeStartTag(element);
+				}
+				else {
+					removeNode(element);
+				}
+			}
+			else {
+				Node child = element.getFirstChild();
+				if (child != null) {
+					this.context.setNextNode(child);
+					removeStructuredDocumentRegion(oldStructuredDocumentRegion);
+					return;
+				}
+
+				if (!element.hasEndTag()) {
+					// implicit element
+					removeNode(element);
+					removeStructuredDocumentRegion(oldStructuredDocumentRegion);
+					return;
+				}
+
+				IStructuredDocumentRegion flatNode = element.getEndStructuredDocumentRegion();
+				if (flatNode != oldStructuredDocumentRegion) {
+					throw new StructuredDocumentRegionManagementException();
+				}
+				removeNode(element);
+			}
+			return;
+		}
+
+		Node parent = this.context.getParentNode();
+		if (parent == null || parent.getNodeType() != Node.ELEMENT_NODE) {
+			throw new StructuredDocumentRegionManagementException();
+		}
+
+		ElementImpl end = (ElementImpl) parent;
+		if (end.hasEndTag()) {
+			IStructuredDocumentRegion flatNode = end.getEndStructuredDocumentRegion();
+			if (flatNode != oldStructuredDocumentRegion) {
+				throw new StructuredDocumentRegionManagementException();
+			}
+			if (!end.hasStartTag() && !end.hasChildNodes()) {
+				this.context.setNextNode(end);
+				removeNode(end);
+			}
+			else {
+				end.setEndStructuredDocumentRegion(null);
+				removeEndTag(end);
+			}
+			return;
+		}
+
+		next = (NodeImpl) end.getNextSibling();
+		if (next != null) {
+			this.context.setNextNode(next);
+			removeStructuredDocumentRegion(oldStructuredDocumentRegion);
+			return;
+		}
+
+		parent = end.getParentNode();
+		if (parent != null) {
+			this.context.setParentNode(parent);
+			removeStructuredDocumentRegion(oldStructuredDocumentRegion);
+			return;
+		}
+	}
+
+	/**
+	 * replaceRegions method
+	 * 
+	 * @param newRegions
+	 *            java.util.Vector
+	 * @param oldRegions
+	 *            java.util.Vector
+	 */
+	void replaceRegions(IStructuredDocumentRegion flatNode, ITextRegionList newRegions, ITextRegionList oldRegions) {
+		if (flatNode == null)
+			return;
+		if (this.model.getDocument() == null)
+			return;
+		this.context = new XMLModelContext(this.model.getDocument());
+
+		// optimize typical cases
+		String regionType = StructuredDocumentRegionUtil.getFirstRegionType(flatNode);
+		if (regionType == DOMRegionContext.XML_TAG_OPEN) {
+			changeStartTag(flatNode, newRegions, oldRegions);
+		}
+		else if (regionType == DOMRegionContext.XML_END_TAG_OPEN) {
+			changeEndTag(flatNode, newRegions, oldRegions);
+		}
+		else {
+			changeStructuredDocumentRegion(flatNode);
+		}
+	}
+
+	/**
+	 * replaceStructuredDocumentRegions method
+	 * 
+	 */
+	void replaceStructuredDocumentRegions(IStructuredDocumentRegionList newStructuredDocumentRegions, IStructuredDocumentRegionList oldStructuredDocumentRegions) {
+		if (this.model.getDocument() == null)
+			return;
+		this.context = new XMLModelContext(this.model.getDocument());
+
+		int newCount = (newStructuredDocumentRegions != null ? newStructuredDocumentRegions.getLength() : 0);
+		int oldCount = (oldStructuredDocumentRegions != null ? oldStructuredDocumentRegions.getLength() : 0);
+
+		if (oldCount > 0) {
+			setupContext(oldStructuredDocumentRegions.item(0));
+			// Node startParent = this.context.getParentNode();
+
+			for (int i = 0; i < oldCount; i++) {
+				IStructuredDocumentRegion documentRegion = oldStructuredDocumentRegions.item(i);
+				removeStructuredDocumentRegion(documentRegion);
+			}
+		}
+		else {
+			if (newCount == 0)
+				return;
+			setupContext(newStructuredDocumentRegions.item(0));
+		}
+		// make sure the parent is set to deepest level
+		// when end tag has been removed
+		this.context.setLast();
+
+		if (newCount > 0) {
+			for (int i = 0; i < newCount; i++) {
+				IStructuredDocumentRegion documentRegion = newStructuredDocumentRegions.item(i);
+				insertStructuredDocumentRegion(documentRegion);
+			}
+		}
+
+		cleanupText();
+		cleanupEndTag();
+	}
+
+	/**
+	 * setupContext method
+	 * 
+	 */
+	private void setupContext(IStructuredDocumentRegion startStructuredDocumentRegion) {
+		int offset = startStructuredDocumentRegion.getStart();
+		if (offset < 0)
+			return;
+		NodeImpl root = (NodeImpl) this.context.getRootNode();
+		if (root == null)
+			return;
+
+		if (offset == 0) {
+			// at the beginning of document
+			Node child = root.getFirstChild();
+			if (child != null)
+				this.context.setNextNode(child);
+			else
+				this.context.setParentNode(root);
+			return;
+		}
+
+		NodeImpl node = (NodeImpl) root.getNodeAt(offset);
+		if (node == null) {
+			// might be at the end of document
+			this.context.setParentNode(root);
+			this.context.setLast();
+			return;
+		}
+
+		if (offset == node.getStartOffset()) {
+			this.context.setNextNode(node);
+			return;
+		}
+
+		if (node.getNodeType() == Node.TEXT_NODE) {
+			TextImpl text = (TextImpl) node;
+			Text nextText = text.splitText(startStructuredDocumentRegion);
+			// notify the change
+			text.notifyValueChanged();
+			if (nextText == null)
+				return; // error
+			this.context.setNextNode(nextText);
+			return;
+		}
+
+		for (Node child = node.getFirstChild(); child != null; child = child.getNextSibling()) {
+			if (offset >= ((NodeImpl) child).getEndOffset())
+				continue;
+			this.context.setNextNode(child);
+			return;
+		}
+		this.context.setParentNode(node);
+		this.context.setLast();
+	}
+
+	protected XMLModelContext getContext() {
+		return context;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/XMLModelUpdater.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/XMLModelUpdater.java
new file mode 100644
index 0000000..a92b233
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/XMLModelUpdater.java
@@ -0,0 +1,1704 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2009 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     David Carver (STAR) - bug 296999 - Inefficient use of new String()
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import java.util.Enumeration;
+import java.util.Iterator;
+
+import org.eclipse.wst.sse.core.internal.provisional.events.RegionChangedEvent;
+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.IStructuredDocumentRegionList;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.eclipse.wst.xml.core.internal.provisional.document.ISourceGenerator;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.Text;
+
+
+/**
+ * XMLModelUpdater class
+ */
+public class XMLModelUpdater {
+	private int diff = 0;
+	private int gapLength = 0;
+	private int gapOffset = 0;
+	private IStructuredDocumentRegion gapStructuredDocumentRegion = null;
+	private ISourceGenerator generator = null;
+	private DOMModelImpl model = null;
+	private NodeImpl nextNode = null;
+	private NodeImpl parentNode = null;
+
+	protected XMLModelUpdater(DOMModelImpl model) {
+		super();
+
+		if (model != null) {
+			this.model = model;
+			this.generator = model.getGenerator();
+		}
+	}
+
+	/**
+	 * changeAttrValue method
+	 * 
+	 * @param attrNode
+	 *            org.w3c.dom.Attr
+	 */
+	private void changeAttrName(Attr attrNode) {
+		if (attrNode == null)
+			return;
+
+		AttrImpl attr = (AttrImpl) attrNode;
+		ElementImpl element = (ElementImpl) attr.getOwnerElement();
+		if (element == null)
+			return;
+
+		if (element.isCommentTag()) {
+			changeStartTag(element);
+			return;
+		}
+
+		int offset = element.getStartOffset();
+		int start = offset;
+		int end = offset;
+
+		String name = attr.getName();
+		if (name == null)
+			name = NodeImpl.EMPTY_STRING;
+		ITextRegion nameRegion = attr.getNameRegion();
+		if (nameRegion == null)
+			return; // error
+		start += nameRegion.getStart();
+		// use getTextEnd() because getEnd() may include the tailing spaces
+		end += nameRegion.getTextEnd();
+
+		replaceSource(name, start, end);
+	}
+
+	/**
+	 * changeAttrValue method
+	 * 
+	 * @param attrNode
+	 *            org.w3c.dom.Attr
+	 */
+	private void changeAttrValue(Attr attrNode) {
+		if (attrNode == null)
+			return;
+
+		AttrImpl attr = (AttrImpl) attrNode;
+		ElementImpl element = (ElementImpl) attr.getOwnerElement();
+		if (element == null)
+			return;
+
+		if (element.isCommentTag()) {
+			changeStartTag(element);
+			return;
+		}
+
+		int offset = element.getStartOffset();
+		int start = offset;
+		int end = offset;
+
+		String value = null;
+		ITextRegion valueRegion = attr.getValueRegion();
+		if (valueRegion != null) {
+			char quote = 0; // no quote preference
+			// DW: 4/16/2003 due to change in structuredDocument ... we need a
+			// flatnode to
+			// get at region values. For now I'll assume this is always the
+			// first
+			// flatnode .. may need to make smarter later (e.g. to search for
+			// the flatnode that this.valueRegion belongs to.
+			IStructuredDocumentRegion documentRegion = element.getFirstStructuredDocumentRegion();
+			String oldValue = documentRegion.getText(valueRegion);
+			if (oldValue != null && oldValue.length() > 0) {
+				char firstChar = oldValue.charAt(0);
+				if (firstChar == '"' || firstChar == '\'') {
+					quote = firstChar;
+				}
+			}
+
+			ITextRegion startRegion = valueRegion;
+
+			value = this.generator.generateAttrValue(attr, quote);
+			if (value == null) {
+				value = NodeImpl.EMPTY_STRING;
+				// remove equal too
+				ITextRegion equalRegion = attr.getEqualRegion();
+				if (equalRegion != null)
+					startRegion = equalRegion;
+			}
+			attr.setValueRegion(valueRegion); // reset value
+
+			start += startRegion.getStart();
+			// use getTextEnd() because getEnd() may include the tailing
+			// spaces
+			end += valueRegion.getTextEnd();
+		}
+		else {
+			ITextRegion equalRegion = attr.getEqualRegion();
+
+			value = this.generator.generateAttrValue(attr);
+			if (value == null) {
+				if (equalRegion == null)
+					return; // nothng to do
+				value = NodeImpl.EMPTY_STRING;
+				// remove equal
+				start += equalRegion.getStart();
+				end += equalRegion.getTextEnd();
+			}
+			else {
+				if (equalRegion != null) {
+					// use getTextEnd() because getEnd() may include the
+					// tailing spaces
+					start += equalRegion.getTextEnd();
+				}
+				else {
+					ITextRegion nameRegion = attr.getNameRegion();
+					if (nameRegion == null)
+						return; // must never happen
+					// use getTextEnd() because getEnd() may include the
+					// tailing spaces
+					start += nameRegion.getTextEnd();
+					value = '=' + value;
+				}
+				end = start;
+			}
+		}
+
+		replaceSource(value, start, end);
+	}
+
+	/**
+	 */
+	void changeEndTag(Element element) {
+		String source = this.generator.generateEndTag(element);
+		if (source == null)
+			return;
+		int length = source.length();
+		if (length == 0)
+			return;
+
+		ElementImpl impl = (ElementImpl) element;
+		int offset = impl.getEndStartOffset();
+		int start = offset;
+		int end = offset;
+		if (impl.hasEndTag()) {
+			end = impl.getEndOffset();
+			this.gapStructuredDocumentRegion = impl.getEndStructuredDocumentRegion();
+			impl.setEndStructuredDocumentRegion(new StructuredDocumentRegionProxy(offset, length));
+		}
+
+		replaceSource(source, start, end);
+	}
+
+	/**
+	 * changeName method
+	 * 
+	 * @param node
+	 *            org.w3c.dom.Node
+	 */
+	void changeName(Node node) {
+		if (node == null)
+			return;
+		if (getStructuredDocument() == null)
+			return;
+
+		// support changing name of attribute for setPrefix()
+		short nodeType = node.getNodeType();
+		if (nodeType == Node.ATTRIBUTE_NODE) {
+			changeAttrName((Attr) node);
+			return;
+		}
+
+		// not supported
+		return;
+	}
+
+	void changeRegion(RegionChangedEvent change, IStructuredDocumentRegion flatNode, ITextRegion region) {
+		if (change.getOffset() >= flatNode.getStartOffset() + region.getTextEnd()) {
+			// change is entirely in white-space
+			return;
+		}
+
+		NodeImpl root = (NodeImpl) this.model.getDocument();
+		this.parentNode = root;
+		this.nextNode = (NodeImpl) root.getFirstChild();
+
+		removeGapStructuredDocumentRegion(flatNode);
+		insertGapStructuredDocumentRegionBefore(flatNode.getStart());
+		changeStructuredDocumentRegion(flatNode);
+		insertGapStructuredDocumentRegionAfter(flatNode.getEnd());
+	}
+
+	/**
+	 * This is a fallback method to regenerate the start tag.
+	 */
+	void changeStartTag(Element element) {
+		if (element == null)
+			return;
+		ElementImpl impl = (ElementImpl) element;
+
+		if (!impl.hasStartTag() && !impl.hasEndTag()) {
+			// need to generate the start and the end tags
+			Node parent = element.getParentNode();
+			if (parent != null) {
+				replaceChild(parent, element, element);
+				return;
+			}
+			// else error
+		}
+
+		String source = this.generator.generateStartTag(element);
+		if (source == null)
+			return;
+		int length = source.length();
+		if (length == 0)
+			return;
+
+		int offset = impl.getStartOffset();
+		int start = offset;
+		int end = offset;
+		if (impl.hasStartTag()) {
+			end = impl.getStartEndOffset();
+			this.gapStructuredDocumentRegion = impl.getStartStructuredDocumentRegion();
+		}
+		impl.setStartStructuredDocumentRegion(new StructuredDocumentRegionProxy(offset, length));
+
+		replaceSource(source, start, end);
+	}
+
+	private void changeStructuredDocumentRegion(IStructuredDocumentRegion oldStructuredDocumentRegion) {
+		if (oldStructuredDocumentRegion == null)
+			return; // error
+		if (this.parentNode == null)
+			return; // error
+
+		int oldOffset = oldStructuredDocumentRegion.getStart();
+		int oldEnd = oldStructuredDocumentRegion.getEnd();
+		boolean isEndTag = false;
+
+		// find owner node
+		NodeImpl ownerNode = null;
+		while (this.parentNode != null) {
+			if (this.nextNode != null) {
+				IStructuredDocumentRegion nextStructuredDocumentRegion = this.nextNode.getStructuredDocumentRegion();
+				if (nextStructuredDocumentRegion != null) {
+					if (nextStructuredDocumentRegion == oldStructuredDocumentRegion) {
+						ownerNode = this.nextNode;
+						break;
+					}
+					int nextOffset = nextStructuredDocumentRegion.getStart();
+					if (nextOffset == oldOffset) { // found
+						ownerNode = this.nextNode;
+						break;
+					}
+					if (this.nextNode.getNodeType() == Node.TEXT_NODE) {
+						TextImpl text = (TextImpl) this.nextNode;
+						if (text.hasStructuredDocumentRegion(oldStructuredDocumentRegion)) {
+							ownerNode = this.nextNode;
+							break;
+						}
+						int nextEnd = nextStructuredDocumentRegion.getEnd();
+						if (nextOffset < oldEnd && nextEnd > oldOffset) {
+							ownerNode = this.nextNode;
+							break;
+						}
+					}
+				}
+
+				Node child = this.nextNode.getFirstChild();
+				if (child != null) {
+					this.parentNode = this.nextNode;
+					this.nextNode = (NodeImpl) child;
+					continue;
+				}
+
+				if (this.nextNode.getNodeType() == Node.ELEMENT_NODE) {
+					this.parentNode = this.nextNode;
+					this.nextNode = null;
+					continue;
+				}
+
+				this.nextNode = (NodeImpl) this.nextNode.getNextSibling();
+				if (this.nextNode != null)
+					continue;
+			}
+
+			if (this.parentNode.getNodeType() == Node.ELEMENT_NODE) {
+				ElementImpl element = (ElementImpl) this.parentNode;
+				IStructuredDocumentRegion endStructuredDocumentRegion = element.getEndStructuredDocumentRegion();
+				if (endStructuredDocumentRegion != null) {
+					if (endStructuredDocumentRegion == oldStructuredDocumentRegion) {
+						ownerNode = this.parentNode;
+						isEndTag = true;
+						break;
+					}
+					int endOffset = endStructuredDocumentRegion.getStart();
+					if (endOffset == oldOffset) { // found
+						ownerNode = this.parentNode;
+						isEndTag = true;
+						break;
+					}
+				}
+			}
+
+			this.nextNode = (NodeImpl) this.parentNode.getNextSibling();
+			this.parentNode = (NodeImpl) this.parentNode.getParentNode();
+		}
+		if (ownerNode == null)
+			throw new StructuredDocumentRegionManagementException();
+
+		short nodeType = ownerNode.getNodeType();
+		if (nodeType == Node.ELEMENT_NODE) {
+			ElementImpl element = (ElementImpl) ownerNode;
+			if (isEndTag) {
+				element.setEndStructuredDocumentRegion(oldStructuredDocumentRegion);
+			}
+			else {
+				element.setStartStructuredDocumentRegion(oldStructuredDocumentRegion);
+				updateAttrRegions(element, oldStructuredDocumentRegion);
+			}
+		}
+		else if (nodeType == Node.TEXT_NODE) {
+			TextImpl text = (TextImpl) ownerNode;
+
+			IStructuredDocumentRegion flatNode = text.getStructuredDocumentRegion();
+			if (flatNode == oldStructuredDocumentRegion) {
+				int newOffset = oldOffset;
+				int newEnd = oldEnd;
+				if (oldOffset == this.gapOffset) {
+					newOffset += this.diff;
+				}
+				else {
+					newEnd = this.gapOffset;
+				}
+				int newLength = newEnd - newOffset;
+				IStructuredDocumentRegion newStructuredDocumentRegion = new StructuredDocumentRegionProxy(newOffset, newLength, oldStructuredDocumentRegion);
+				text.setStructuredDocumentRegion(newStructuredDocumentRegion);
+
+				if (oldEnd > newEnd) {
+					this.nextNode = (NodeImpl) text.getNextSibling();
+					changeStructuredDocumentRegion(oldStructuredDocumentRegion);
+				}
+				return;
+			}
+
+			if (flatNode instanceof StructuredDocumentRegionProxy) {
+				StructuredDocumentRegionProxy proxy = (StructuredDocumentRegionProxy) flatNode;
+				int offset = proxy.getOffset();
+				int end = offset + proxy.getLength();
+				if (proxy.getStructuredDocumentRegion() == null) {
+					if (offset == oldOffset && end == oldEnd) {
+						text.setStructuredDocumentRegion(oldStructuredDocumentRegion);
+					}
+					else {
+						if (end > oldEnd) {
+							StructuredDocumentRegionContainer container = new StructuredDocumentRegionContainer();
+							container.appendStructuredDocumentRegion(oldStructuredDocumentRegion);
+							proxy.setOffset(oldEnd);
+							proxy.setLength(end - oldEnd);
+							container.appendStructuredDocumentRegion(proxy);
+							text.setStructuredDocumentRegion(container);
+						}
+						else {
+							proxy.setStructuredDocumentRegion(oldStructuredDocumentRegion);
+
+							if (end < oldEnd) { // to be shared
+								this.nextNode = (NodeImpl) text.getNextSibling();
+								changeStructuredDocumentRegion(oldStructuredDocumentRegion);
+							}
+						}
+					}
+					return;
+				}
+
+				if (offset >= this.gapOffset) {
+					proxy.setOffset(offset + this.diff);
+					end += this.diff;
+				}
+				if (end < oldEnd) { // to be shared
+					this.nextNode = (NodeImpl) text.getNextSibling();
+					changeStructuredDocumentRegion(oldStructuredDocumentRegion);
+					return;
+				}
+			}
+			else if (flatNode instanceof StructuredDocumentRegionContainer) {
+				StructuredDocumentRegionContainer container = (StructuredDocumentRegionContainer) flatNode;
+				int count = container.getStructuredDocumentRegionCount();
+				for (int i = 0; i < count; i++) {
+					IStructuredDocumentRegion content = container.getStructuredDocumentRegion(i);
+					if (content == null)
+						continue; // error
+					if (content == oldStructuredDocumentRegion) {
+						int newOffset = oldOffset;
+						int newEnd = oldEnd;
+						if (oldOffset == this.gapOffset) {
+							newOffset += this.diff;
+						}
+						else {
+							newEnd = this.gapOffset;
+						}
+						int newLength = newEnd - newOffset;
+						IStructuredDocumentRegion newStructuredDocumentRegion = new StructuredDocumentRegionProxy(newOffset, newLength, oldStructuredDocumentRegion);
+						container.replaceStructuredDocumentRegion(newStructuredDocumentRegion, i);
+
+						if (oldEnd > newEnd) { // to be shared
+							this.nextNode = (NodeImpl) text.getNextSibling();
+							changeStructuredDocumentRegion(oldStructuredDocumentRegion);
+						}
+						return;
+					}
+
+					if (content instanceof StructuredDocumentRegionProxy) {
+						StructuredDocumentRegionProxy proxy = (StructuredDocumentRegionProxy) content;
+						int offset = proxy.getOffset();
+						int end = offset + proxy.getLength();
+						if (end <= oldOffset)
+							continue;
+						if (proxy.getStructuredDocumentRegion() == null) {
+							if (offset == oldOffset && end == oldEnd) {
+								container.replaceStructuredDocumentRegion(oldStructuredDocumentRegion, i);
+							}
+							else {
+								if (end > oldEnd) {
+									container.insertStructuredDocumentRegion(oldStructuredDocumentRegion, i);
+									proxy.setOffset(oldEnd);
+									proxy.setLength(end - oldEnd);
+								}
+								else {
+									proxy.setStructuredDocumentRegion(oldStructuredDocumentRegion);
+
+									if (end < oldEnd) { // to be shared
+										this.nextNode = (NodeImpl) text.getNextSibling();
+										changeStructuredDocumentRegion(oldStructuredDocumentRegion);
+									}
+								}
+							}
+							return;
+						}
+
+						if (offset >= this.gapOffset) {
+							proxy.setOffset(offset + this.diff);
+							end += this.diff;
+						}
+						if (end < oldEnd) { // to be shared
+							this.nextNode = (NodeImpl) text.getNextSibling();
+							changeStructuredDocumentRegion(oldStructuredDocumentRegion);
+							return;
+						}
+					}
+				}
+			}
+			else {
+				throw new StructuredDocumentRegionManagementException();
+			}
+		}
+		else {
+			ownerNode.setStructuredDocumentRegion(oldStructuredDocumentRegion);
+		}
+	}
+
+	/**
+	 */
+	private void changeTextData(Text text) {
+		if (text == null)
+			return;
+
+		String source = this.generator.generateSource(text);
+		if (source == null)
+			source = NodeImpl.EMPTY_STRING;
+		int length = source.length();
+
+		TextImpl impl = (TextImpl) text;
+		int start = impl.getStartOffset();
+		int end = impl.getEndOffset();
+		int offset = start;
+
+		// make sure previous tag is closed
+		Node prev = text.getPreviousSibling();
+		if (prev != null) {
+			String preTag = getCloseTag((IDOMNode) prev);
+			if (preTag != null && preTag.length() > 0) {
+				offset += preTag.length();
+				source = preTag + source;
+			}
+		}
+		else {
+			Node parent = text.getParentNode();
+			if (parent != null && parent.getNodeType() == Node.ELEMENT_NODE) {
+				ElementImpl element = (ElementImpl) parent;
+				String preTag = getStartCloseTag(element);
+				if (preTag != null && preTag.length() > 0) {
+					offset += preTag.length();
+					StringBuffer buffer = new StringBuffer();
+					buffer.append(preTag);
+					buffer.append(source);
+					if (text.getNextSibling() == null && !element.hasEndTag() && (element.isJSPContainer() || element.isCDATAContainer())) {
+						// need to generate the end tag
+						String postTag = this.generator.generateEndTag(element);
+						if (postTag != null) {
+							int postLength = postTag.length();
+							if (postLength > 0) {
+								buffer.append(postTag);
+								int postOffset = offset + length;
+								IStructuredDocumentRegion flatNode = new StructuredDocumentRegionProxy(postOffset, postLength);
+								element.setEndStructuredDocumentRegion(flatNode);
+							}
+						}
+					}
+					source = buffer.toString();
+				}
+			}
+		}
+
+		this.gapStructuredDocumentRegion = impl.getStructuredDocumentRegion();
+		IStructuredDocumentRegion newStructuredDocumentRegion = null;
+		if (length > 0)
+			newStructuredDocumentRegion = new StructuredDocumentRegionProxy(offset, length);
+		impl.setStructuredDocumentRegion(newStructuredDocumentRegion);
+
+		replaceSource(source, start, end);
+	}
+
+	/**
+	 * changeValue method
+	 * 
+	 * @param node
+	 *            org.w3c.dom.Node
+	 */
+	void changeValue(Node node) {
+		if (node == null)
+			return;
+		if (getStructuredDocument() == null)
+			return;
+
+		short nodeType = node.getNodeType();
+		if (nodeType == Node.TEXT_NODE) {
+			changeTextData((Text) node);
+			return;
+		}
+		if (nodeType == Node.ATTRIBUTE_NODE) {
+			changeAttrValue((Attr) node);
+			return;
+		}
+		if (nodeType == Node.ELEMENT_NODE) {
+			changeStartTag((Element) node);
+			return;
+		}
+
+		String source = this.generator.generateSource(node);
+		if (source == null)
+			source = NodeImpl.EMPTY_STRING;
+		int length = source.length();
+
+		NodeImpl impl = (NodeImpl) node;
+		int start = impl.getStartOffset();
+		int end = impl.getEndOffset();
+
+		this.gapStructuredDocumentRegion = impl.getStructuredDocumentRegion();
+		IStructuredDocumentRegion flatNode = null;
+		if (length > 0)
+			flatNode = new StructuredDocumentRegionProxy(start, length);
+		impl.setStructuredDocumentRegion(flatNode);
+
+		replaceSource(source, start, end);
+	}
+
+	/**
+	 */
+	private String getAttrValueClose(IDOMElement element) {
+		if (element == null)
+			return null;
+
+		IStructuredDocumentRegion flatNode = element.getStartStructuredDocumentRegion();
+		if (flatNode == null)
+			return null;
+		ITextRegion region = StructuredDocumentRegionUtil.getLastRegion(flatNode);
+		if (region == null || region.getType() != DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE)
+			return null;
+		String value = flatNode.getText(region);
+		if (value == null)
+			return null;
+		int length = value.length();
+		if (length == 0)
+			return null;
+
+		// check open JSP tag
+		boolean closeJSPTag = false;
+		int offset = value.indexOf(JSPTag.TAG_OPEN);
+		while (offset >= 0) {
+			offset = value.indexOf(JSPTag.TAG_CLOSE, offset + 2);
+			if (offset < 0) {
+				closeJSPTag = true;
+				break;
+			}
+			offset = value.indexOf(JSPTag.TAG_OPEN, offset + 2);
+		}
+
+		// check quote
+		boolean closeQuote = false;
+		char firstChar = value.charAt(0);
+		if (firstChar == '"' || firstChar == '\'') {
+			if (closeJSPTag || length == 1 || value.charAt(length - 1) != firstChar) {
+				closeQuote = true;
+			}
+		}
+
+		if (!closeJSPTag && !closeQuote)
+			return null;
+
+		StringBuffer buffer = new StringBuffer();
+		if (closeJSPTag)
+			buffer.append(JSPTag.TAG_CLOSE);
+		if (closeQuote)
+			buffer.append(firstChar);
+		return buffer.toString();
+	}
+
+	/**
+	 * Gather close tags recursively.
+	 */
+	private String getCloseTag(IDOMNode node) {
+		if (node == null || node.isClosed())
+			return null;
+
+		if (node.getNodeType() != Node.ELEMENT_NODE) {
+			return this.generator.generateCloseTag(node);
+		}
+
+		ElementImpl element = (ElementImpl) node;
+		if (element.hasEndTag()) {
+			// end tag is not closed
+			return this.generator.generateCloseTag(element);
+		}
+
+		// no end tag
+		int offset = element.getEndOffset();
+		StringBuffer buffer = new StringBuffer();
+
+		IDOMNode lastChild = (IDOMNode) element.getLastChild();
+		if (lastChild == null) {
+			if (!element.isStartTagClosed()) {
+				if (element.preferEmptyTag())
+					element.setEmptyTag(true);
+				String closeTag = getStartCloseTag(element);
+				if (closeTag != null) {
+					int length = closeTag.length();
+					if (length > 0) {
+						buffer.append(closeTag);
+						offset += length;
+					}
+				}
+			}
+		}
+		else {
+			String closeTag = getCloseTag(lastChild);
+			if (closeTag != null) {
+				int length = closeTag.length();
+				if (length > 0) {
+					buffer.append(closeTag);
+					offset += length;
+				}
+			}
+		}
+
+		String endTag = this.generator.generateEndTag(element);
+		if (endTag != null) {
+			int length = endTag.length();
+			if (length > 0) {
+				buffer.append(endTag);
+				IStructuredDocumentRegion flatNode = new StructuredDocumentRegionProxy(offset, length);
+				element.setEndStructuredDocumentRegion(flatNode);
+			}
+		}
+
+		return buffer.toString();
+	}
+
+	/**
+	 */
+	private String getStartCloseTag(IDOMElement element) {
+		if (element == null || element.isStartTagClosed())
+			return null;
+
+		StringBuffer buffer = new StringBuffer();
+		String attrValueClose = getAttrValueClose(element);
+		if (attrValueClose != null)
+			buffer.append(attrValueClose);
+		String closeTag = this.generator.generateCloseTag(element);
+		if (closeTag != null)
+			buffer.append(closeTag);
+		return buffer.toString();
+	}
+
+	private IStructuredDocument getStructuredDocument() {
+		if (model == null)
+			return null;
+		return model.getStructuredDocument();
+	}
+
+	/**
+	 */
+	void initialize() {
+		this.gapStructuredDocumentRegion = null;
+		this.gapOffset = 0;
+		this.gapLength = 0;
+		this.diff = 0;
+		this.parentNode = null;
+		this.nextNode = null;
+	}
+
+	private void insertGapStructuredDocumentRegionAfter(int endOffset) {
+		if (this.gapStructuredDocumentRegion == null)
+			return;
+
+		if (this.gapStructuredDocumentRegion instanceof StructuredDocumentRegionProxy) {
+			StructuredDocumentRegionProxy proxy = (StructuredDocumentRegionProxy) this.gapStructuredDocumentRegion;
+			IStructuredDocumentRegion flatNode = proxy.getStructuredDocumentRegion();
+			if (flatNode != null)
+				insertStructuredDocumentRegion(flatNode);
+		}
+		else if (this.gapStructuredDocumentRegion instanceof StructuredDocumentRegionContainer) {
+			StructuredDocumentRegionContainer container = (StructuredDocumentRegionContainer) this.gapStructuredDocumentRegion;
+			int count = container.getStructuredDocumentRegionCount();
+			for (int i = 0; i < count; i++) {
+				IStructuredDocumentRegion content = container.getStructuredDocumentRegion(i);
+				if (content == null)
+					continue;
+				if (content.getStart() < endOffset)
+					continue;
+				if (content instanceof StructuredDocumentRegionProxy) {
+					StructuredDocumentRegionProxy proxy = (StructuredDocumentRegionProxy) content;
+					IStructuredDocumentRegion flatNode = proxy.getStructuredDocumentRegion();
+					if (flatNode != null)
+						insertStructuredDocumentRegion(flatNode);
+				}
+				else {
+					insertStructuredDocumentRegion(content);
+				}
+			}
+		}
+		else {
+			insertStructuredDocumentRegion(this.gapStructuredDocumentRegion);
+		}
+	}
+
+	private void insertGapStructuredDocumentRegionBefore(int startOffset) {
+		if (this.gapStructuredDocumentRegion == null)
+			return;
+
+		if (this.gapStructuredDocumentRegion instanceof StructuredDocumentRegionProxy) {
+			StructuredDocumentRegionProxy proxy = (StructuredDocumentRegionProxy) this.gapStructuredDocumentRegion;
+			IStructuredDocumentRegion flatNode = proxy.getStructuredDocumentRegion();
+			if (flatNode != null)
+				insertStructuredDocumentRegion(flatNode);
+		}
+		else if (this.gapStructuredDocumentRegion instanceof StructuredDocumentRegionContainer) {
+			StructuredDocumentRegionContainer container = (StructuredDocumentRegionContainer) this.gapStructuredDocumentRegion;
+			int count = container.getStructuredDocumentRegionCount();
+			for (int i = 0; i < count; i++) {
+				IStructuredDocumentRegion content = container.getStructuredDocumentRegion(i);
+				if (content == null)
+					continue;
+				if (content.getStart() >= startOffset)
+					return;
+				if (content instanceof StructuredDocumentRegionProxy) {
+					StructuredDocumentRegionProxy proxy = (StructuredDocumentRegionProxy) content;
+					IStructuredDocumentRegion flatNode = proxy.getStructuredDocumentRegion();
+					if (flatNode != null)
+						insertStructuredDocumentRegion(flatNode);
+				}
+				else {
+					insertStructuredDocumentRegion(content);
+				}
+			}
+		}
+		else {
+			insertStructuredDocumentRegion(this.gapStructuredDocumentRegion);
+		}
+	}
+
+	/**
+	 */
+	private void insertStructuredDocumentRegion(IStructuredDocumentRegion newStructuredDocumentRegion) {
+		if (newStructuredDocumentRegion == null)
+			return; // error
+		if (this.parentNode == null)
+			return; // error
+
+		int newOffset = newStructuredDocumentRegion.getStart();
+		int newEnd = newStructuredDocumentRegion.getEnd();
+		boolean isEndTag = false;
+
+		// find owner node
+		NodeImpl ownerNode = null;
+		while (this.parentNode != null) {
+			if (this.nextNode != null) {
+				IStructuredDocumentRegion nextStructuredDocumentRegion = this.nextNode.getStructuredDocumentRegion();
+				if (nextStructuredDocumentRegion != null) {
+					int nextOffset = nextStructuredDocumentRegion.getStart();
+					if (nextOffset == newOffset) { // found
+						ownerNode = this.nextNode;
+						break;
+					}
+					if (this.nextNode.getNodeType() == Node.TEXT_NODE) {
+						int nextEnd = nextStructuredDocumentRegion.getEnd();
+						if (nextOffset < newEnd && nextEnd > newOffset) {
+							ownerNode = this.nextNode;
+							break;
+						}
+					}
+				}
+
+				Node child = this.nextNode.getFirstChild();
+				if (child != null) {
+					this.parentNode = this.nextNode;
+					this.nextNode = (NodeImpl) child;
+					continue;
+				}
+
+				if (this.nextNode.getNodeType() == Node.ELEMENT_NODE) {
+					this.parentNode = this.nextNode;
+					this.nextNode = null;
+					continue;
+				}
+
+				this.nextNode = (NodeImpl) this.nextNode.getNextSibling();
+				if (this.nextNode != null)
+					continue;
+			}
+
+			if (this.parentNode.getNodeType() == Node.ELEMENT_NODE) {
+				ElementImpl element = (ElementImpl) this.parentNode;
+				IStructuredDocumentRegion endStructuredDocumentRegion = element.getEndStructuredDocumentRegion();
+				if (endStructuredDocumentRegion != null) {
+					int endOffset = endStructuredDocumentRegion.getStart();
+					if (endOffset == newOffset) { // found
+						ownerNode = this.parentNode;
+						isEndTag = true;
+						break;
+					}
+				}
+			}
+
+			this.nextNode = (NodeImpl) this.parentNode.getNextSibling();
+			this.parentNode = (NodeImpl) this.parentNode.getParentNode();
+		}
+		if (ownerNode == null)
+			throw new StructuredDocumentRegionManagementException();
+
+		short nodeType = ownerNode.getNodeType();
+		if (nodeType == Node.ELEMENT_NODE) {
+			ElementImpl element = (ElementImpl) ownerNode;
+			if (isEndTag) {
+				element.setEndStructuredDocumentRegion(newStructuredDocumentRegion);
+			}
+			else {
+				element.setStartStructuredDocumentRegion(newStructuredDocumentRegion);
+				updateAttrRegions(element, newStructuredDocumentRegion);
+			}
+		}
+		else if (nodeType == Node.TEXT_NODE) {
+			TextImpl text = (TextImpl) ownerNode;
+			IStructuredDocumentRegion oldStructuredDocumentRegion = text.getStructuredDocumentRegion();
+			if (oldStructuredDocumentRegion == null) {
+				throw new StructuredDocumentRegionManagementException();
+			}
+			int oldOffset = oldStructuredDocumentRegion.getStart();
+			int oldEnd = oldStructuredDocumentRegion.getEnd();
+			if (oldOffset == newOffset && oldEnd == newEnd) {
+				text.setStructuredDocumentRegion(newStructuredDocumentRegion);
+				return;
+			}
+
+			if (oldStructuredDocumentRegion instanceof StructuredDocumentRegionProxy) {
+				StructuredDocumentRegionProxy proxy = (StructuredDocumentRegionProxy) oldStructuredDocumentRegion;
+				if (oldEnd > newEnd) {
+					StructuredDocumentRegionContainer container = new StructuredDocumentRegionContainer();
+					if (oldOffset == newOffset) {
+						container.appendStructuredDocumentRegion(newStructuredDocumentRegion);
+					}
+					else {
+						StructuredDocumentRegionProxy newProxy = new StructuredDocumentRegionProxy();
+						newProxy.setOffset(oldOffset);
+						newProxy.setLength(newEnd - oldOffset);
+						newProxy.setStructuredDocumentRegion(newStructuredDocumentRegion);
+						container.appendStructuredDocumentRegion(newProxy);
+					}
+					proxy.setOffset(newEnd);
+					proxy.setLength(oldEnd - newEnd);
+					container.appendStructuredDocumentRegion(proxy);
+					text.setStructuredDocumentRegion(container);
+				}
+				else {
+					proxy.setStructuredDocumentRegion(newStructuredDocumentRegion);
+
+					if (oldEnd < newEnd) { // to be shared
+						this.nextNode = (NodeImpl) text.getNextSibling();
+						insertStructuredDocumentRegion(newStructuredDocumentRegion);
+					}
+				}
+				return;
+			}
+
+			if (oldStructuredDocumentRegion instanceof StructuredDocumentRegionContainer) {
+				StructuredDocumentRegionContainer container = (StructuredDocumentRegionContainer) oldStructuredDocumentRegion;
+				int count = container.getStructuredDocumentRegionCount();
+				for (int i = 0; i < count; i++) {
+					IStructuredDocumentRegion content = container.getStructuredDocumentRegion(i);
+					if (content == null)
+						continue; // error
+					int offset = content.getStart();
+					int end = content.getEnd();
+					if (end <= newOffset)
+						continue;
+					if (offset == newOffset && end == newEnd) {
+						container.replaceStructuredDocumentRegion(newStructuredDocumentRegion, i);
+						return;
+					}
+
+					if (content instanceof StructuredDocumentRegionProxy) {
+						StructuredDocumentRegionProxy proxy = (StructuredDocumentRegionProxy) content;
+						if (end > newEnd) {
+							if (offset == newOffset) {
+								container.insertStructuredDocumentRegion(newStructuredDocumentRegion, i);
+							}
+							else {
+								StructuredDocumentRegionProxy newProxy = new StructuredDocumentRegionProxy();
+								newProxy.setOffset(offset);
+								newProxy.setLength(newEnd - offset);
+								newProxy.setStructuredDocumentRegion(newStructuredDocumentRegion);
+								container.insertStructuredDocumentRegion(newProxy, i);
+							}
+							proxy.setOffset(newEnd);
+							proxy.setLength(end - newEnd);
+							return;
+						}
+						else {
+							proxy.setStructuredDocumentRegion(newStructuredDocumentRegion);
+							if (end == newEnd)
+								return;
+						}
+					}
+				}
+
+				if (oldEnd < newEnd) { // to be shared
+					this.nextNode = (NodeImpl) text.getNextSibling();
+					insertStructuredDocumentRegion(newStructuredDocumentRegion);
+				}
+				return;
+			}
+			else {
+				throw new StructuredDocumentRegionManagementException();
+			}
+		}
+		else {
+			ownerNode.setStructuredDocumentRegion(newStructuredDocumentRegion);
+		}
+	}
+
+	private void removeGapStructuredDocumentRegion(IStructuredDocumentRegion oldStructuredDocumentRegion) {
+		if (this.gapStructuredDocumentRegion == null)
+			return;
+
+		if (this.gapStructuredDocumentRegion == oldStructuredDocumentRegion) {
+			this.gapStructuredDocumentRegion = null;
+			return;
+		}
+
+		if (this.gapStructuredDocumentRegion instanceof StructuredDocumentRegionProxy) {
+			StructuredDocumentRegionProxy proxy = (StructuredDocumentRegionProxy) this.gapStructuredDocumentRegion;
+			IStructuredDocumentRegion flatNode = proxy.getStructuredDocumentRegion();
+			if (flatNode == oldStructuredDocumentRegion)
+				this.gapStructuredDocumentRegion = null;
+		}
+		else if (this.gapStructuredDocumentRegion instanceof StructuredDocumentRegionContainer) {
+			StructuredDocumentRegionContainer container = (StructuredDocumentRegionContainer) this.gapStructuredDocumentRegion;
+			int count = container.getStructuredDocumentRegionCount();
+			for (int i = 0; i < count; i++) {
+				IStructuredDocumentRegion content = container.getStructuredDocumentRegion(i);
+				if (content == null)
+					continue;
+				if (content == oldStructuredDocumentRegion) {
+					if (count > 1)
+						container.removeStructuredDocumentRegion(i);
+					else
+						this.gapStructuredDocumentRegion = null;
+					return;
+				}
+				if (content instanceof StructuredDocumentRegionProxy) {
+					StructuredDocumentRegionProxy proxy = (StructuredDocumentRegionProxy) content;
+					if (proxy.getStructuredDocumentRegion() == oldStructuredDocumentRegion) {
+						if (count > 1)
+							container.removeStructuredDocumentRegion(i);
+						else
+							this.gapStructuredDocumentRegion = null;
+						return;
+					}
+				}
+			}
+		}
+	}
+
+	private void removeStructuredDocumentRegion(IStructuredDocumentRegion oldStructuredDocumentRegion) {
+		if (oldStructuredDocumentRegion == null)
+			return; // error
+		if (this.parentNode == null)
+			return; // error
+
+		int gapEnd = this.gapOffset + this.gapLength;
+		int oldOffset = oldStructuredDocumentRegion.getStart();
+		int oldEnd = oldStructuredDocumentRegion.getEnd();
+		if (oldOffset >= this.gapOffset && oldEnd <= gapEnd)
+			return; // do nothing
+		int oldLength = oldEnd - oldOffset;
+		if (oldOffset >= gapEnd)
+			oldOffset += this.diff;
+
+		// find owner node
+		NodeImpl ownerNode = null;
+		ElementImpl ownerEndTag = null;
+		TextImpl ownerText = null;
+		while (this.parentNode != null) {
+			if (this.nextNode != null) {
+				if (this.nextNode.getStructuredDocumentRegion() == oldStructuredDocumentRegion) {
+					ownerNode = this.nextNode;
+					break;
+				}
+				if (this.nextNode.getNodeType() == Node.TEXT_NODE) {
+					TextImpl text = (TextImpl) this.nextNode;
+					if (text.hasStructuredDocumentRegion(oldStructuredDocumentRegion)) {
+						ownerNode = this.nextNode;
+						ownerText = text;
+						break;
+					}
+				}
+
+				Node child = this.nextNode.getFirstChild();
+				if (child != null) {
+					this.parentNode = this.nextNode;
+					this.nextNode = (NodeImpl) child;
+					continue;
+				}
+
+				if (this.nextNode.getNodeType() == Node.ELEMENT_NODE) {
+					this.parentNode = this.nextNode;
+					this.nextNode = null;
+					continue;
+				}
+
+				this.nextNode = (NodeImpl) this.nextNode.getNextSibling();
+				if (this.nextNode != null)
+					continue;
+			}
+
+			if (this.parentNode.getNodeType() == Node.ELEMENT_NODE) {
+				ElementImpl element = (ElementImpl) this.parentNode;
+				if (element.getEndStructuredDocumentRegion() == oldStructuredDocumentRegion) {
+					ownerNode = this.parentNode;
+					ownerEndTag = element;
+					break;
+				}
+			}
+
+			this.nextNode = (NodeImpl) this.parentNode.getNextSibling();
+			this.parentNode = (NodeImpl) this.parentNode.getParentNode();
+		}
+		if (ownerNode == null)
+			throw new StructuredDocumentRegionManagementException();
+
+		if (ownerText != null) {
+			IStructuredDocumentRegion flatNode = ownerText.getStructuredDocumentRegion();
+			if (flatNode == oldStructuredDocumentRegion) {
+				IStructuredDocumentRegion newStructuredDocumentRegion = new StructuredDocumentRegionProxy(oldOffset, oldLength);
+				ownerText.setStructuredDocumentRegion(newStructuredDocumentRegion);
+				return;
+			}
+
+			if (flatNode instanceof StructuredDocumentRegionProxy) {
+				StructuredDocumentRegionProxy proxy = (StructuredDocumentRegionProxy) flatNode;
+				if (proxy.getStructuredDocumentRegion() != oldStructuredDocumentRegion) {
+					throw new StructuredDocumentRegionManagementException();
+				}
+				int offset = proxy.getOffset();
+				int end = offset + proxy.getLength();
+				if (offset >= this.gapOffset) {
+					proxy.setOffset(offset + this.diff);
+				}
+				proxy.setStructuredDocumentRegion(null);
+				if (end < oldEnd && (end < this.gapOffset || oldEnd > gapEnd)) { // has
+					// shared
+					removeStructuredDocumentRegion(oldStructuredDocumentRegion);
+					return;
+				}
+			}
+			else if (flatNode instanceof StructuredDocumentRegionContainer) {
+				StructuredDocumentRegionContainer container = (StructuredDocumentRegionContainer) flatNode;
+				int count = container.getStructuredDocumentRegionCount();
+				for (int i = 0; i < count; i++) {
+					IStructuredDocumentRegion content = container.getStructuredDocumentRegion(i);
+					if (content == null)
+						continue; // error
+					if (content == oldStructuredDocumentRegion) {
+						IStructuredDocumentRegion newStructuredDocumentRegion = new StructuredDocumentRegionProxy(oldOffset, oldLength);
+						container.replaceStructuredDocumentRegion(newStructuredDocumentRegion, i);
+						return;
+					}
+
+					if (content instanceof StructuredDocumentRegionProxy) {
+						StructuredDocumentRegionProxy proxy = (StructuredDocumentRegionProxy) content;
+						if (proxy.getStructuredDocumentRegion() == oldStructuredDocumentRegion) {
+							int offset = proxy.getOffset();
+							int end = offset + proxy.getLength();
+							if (offset >= this.gapOffset) {
+								proxy.setOffset(offset + this.diff);
+							}
+							proxy.setStructuredDocumentRegion(null);
+							if (end < oldEnd && (end < this.gapOffset || oldEnd > gapEnd)) { // has
+								// shared
+								removeStructuredDocumentRegion(oldStructuredDocumentRegion);
+								return;
+							}
+						}
+					}
+				}
+			}
+			else {
+				throw new StructuredDocumentRegionManagementException();
+			}
+		}
+		else {
+			IStructuredDocumentRegion newStructuredDocumentRegion = new StructuredDocumentRegionProxy(oldOffset, oldLength);
+			if (ownerEndTag != null) {
+				ownerEndTag.setEndStructuredDocumentRegion(newStructuredDocumentRegion);
+			}
+			else {
+				ownerNode.setStructuredDocumentRegion(newStructuredDocumentRegion);
+			}
+		}
+	}
+
+	/**
+	 * replaceAttr method
+	 * 
+	 * @param ownerElement
+	 *            org.w3c.dom.Element
+	 * @param newAttr
+	 *            org.w3c.dom.Attr
+	 * @param oldAttr
+	 *            org.w3c.dom.Attr
+	 */
+	void replaceAttr(Element ownerElement, Attr newAttr, Attr oldAttr) {
+		if (ownerElement == null)
+			return;
+		if (getStructuredDocument() == null)
+			return;
+
+		ElementImpl element = (ElementImpl) ownerElement;
+		if (!element.hasStartTag()) {
+			changeStartTag(element);
+			return;
+		}
+		if (element.isCommentTag()) {
+			changeStartTag(element);
+			return;
+		}
+
+		int offset = element.getStartOffset();
+		int start = offset;
+		int end = offset;
+
+		boolean insertSpace = false;
+		String attrValueClose = null;
+		if (oldAttr != null) {
+			AttrImpl impl = (AttrImpl) oldAttr;
+			ITextRegion nameRegion = impl.getNameRegion();
+			if (nameRegion == null)
+				return; // must never happen
+			ITextRegion lastRegion = impl.getValueRegion();
+			if (lastRegion != null) {
+				end += lastRegion.getEnd();
+			}
+			else {
+				lastRegion = impl.getEqualRegion();
+				if (lastRegion != null) {
+					end += lastRegion.getEnd();
+				}
+				else {
+					end += nameRegion.getEnd();
+					lastRegion = nameRegion;
+				}
+			}
+			// check there are extra space before the last attribute
+			IStructuredDocumentRegion flatNode = element.getStartStructuredDocumentRegion();
+			if (flatNode == null)
+				return; // must never happen
+			ITextRegionList regions = flatNode.getRegions();
+			if (regions == null)
+				return; // must never happen
+			ITextRegion prevRegion = null;
+			ITextRegion nextRegion = null;
+			for (int i = 0; i < regions.size(); i++) {
+				ITextRegion region = regions.get(i);
+				if (region == nameRegion) {
+					if (i > 0) {
+						prevRegion = regions.get(i - 1);
+					}
+				}
+				if (region == lastRegion) {
+					if (i + 1 < regions.size()) {
+						nextRegion = regions.get(i + 1);
+					}
+					break;
+				}
+			}
+			boolean isLastAttr = false;
+			if (nextRegion != null) {
+				String regionType = nextRegion.getType();
+				if (regionType == DOMRegionContext.XML_TAG_CLOSE || regionType == DOMRegionContext.XML_EMPTY_TAG_CLOSE || isNestedTagClose(regionType)) {
+					isLastAttr = true;
+				}
+			}
+			if (isLastAttr && prevRegion != null) {
+				start += prevRegion.getTextEnd();
+			}
+			else {
+				start += nameRegion.getStart();
+			}
+
+			// impl.resetRegions(ownerElement);
+			impl.resetRegions(element);
+		}
+		else { // append attribute
+			IStructuredDocumentRegion flatNode = element.getStartStructuredDocumentRegion();
+			if (flatNode == null)
+				return; // must never happen
+
+			attrValueClose = getAttrValueClose(element);
+			if (attrValueClose != null && attrValueClose.length() > 0) {
+				insertSpace = true;
+				start = flatNode.getEndOffset();
+				end = start;
+			}
+			else {
+				ITextRegionList regions = flatNode.getRegions();
+				if (regions == null)
+					return; // must never happen
+				int attrStart = 0;
+				for (int i = regions.size() - 1; i >= 0; i--) {
+					ITextRegion region = regions.get(i);
+					String regionType = region.getType();
+					if (regionType == DOMRegionContext.XML_TAG_CLOSE || regionType == DOMRegionContext.XML_EMPTY_TAG_CLOSE || isNestedTagClose(regionType))
+						continue;
+					int regionEnd = region.getEnd();
+					if (regionEnd == region.getTextEnd())
+						insertSpace = true;
+					attrStart = regionEnd;
+					break;
+				}
+				if (attrStart == 0)
+					return; // not found, must never happen
+				start += attrStart;
+				end = start;
+			}
+		}
+
+		String source = null;
+		if (newAttr != null) {
+			int size = 2;
+			if (attrValueClose != null)
+				size += attrValueClose.length();
+			String name = this.generator.generateAttrName(newAttr);
+			if (name != null)
+				size += name.length();
+			String value = this.generator.generateAttrValue(newAttr);
+			if (value != null)
+				size += value.length();
+			StringBuffer buffer = new StringBuffer(size);
+			if (attrValueClose != null)
+				buffer.append(attrValueClose);
+			if (insertSpace)
+				buffer.append(' ');
+			buffer.append(name);
+			if (value != null) {
+				buffer.append('=');
+				buffer.append(value);
+			}
+			source = buffer.toString();
+		}
+
+		replaceSource(source, start, end);
+	}
+
+	protected boolean isNestedTagClose(String regionType) {
+		boolean result = false;
+		return result;
+	}
+
+	/**
+	 * replaceChild method
+	 * 
+	 * @param parentNode
+	 *            org.w3c.dom.Node
+	 * @param newChild
+	 *            org.w3c.dom.Node
+	 * @param oldChild
+	 *            org.w3c.dom.Node
+	 */
+	void replaceChild(Node parentNode, Node newChild, Node oldChild) {
+		if (parentNode == null)
+			return;
+		if (newChild == null && oldChild == null)
+			return;
+		if (getStructuredDocument() == null)
+			return;
+
+		int start = 0;
+		int end = 0;
+		String preTag = null;
+		String postTag = null;
+		ElementImpl postElement = null;
+		if (oldChild != null) {
+			NodeImpl node = (NodeImpl) oldChild;
+			start = node.getStartOffset();
+			end = node.getEndOffset();
+			if (oldChild.getNodeType() == Node.TEXT_NODE) {
+				this.gapStructuredDocumentRegion = node.getStructuredDocumentRegion();
+			}
+			node.resetStructuredDocumentRegions(); // reset values from
+			// IStructuredDocumentRegion
+		}
+		else {
+			NodeImpl prev = (NodeImpl) newChild.getPreviousSibling();
+			if (prev != null) {
+				start = prev.getEndOffset();
+				end = start;
+				preTag = getCloseTag(prev);
+			}
+			else {
+				// first child
+				NodeImpl next = (NodeImpl) newChild.getNextSibling();
+				if (next != null) {
+					start = next.getStartOffset();
+					end = start;
+					if (parentNode.getNodeType() == Node.ELEMENT_NODE) {
+						preTag = getStartCloseTag((IDOMElement) parentNode);
+					}
+				}
+				else {
+					// newly having a child
+					if (parentNode.getNodeType() == Node.ELEMENT_NODE) {
+						ElementImpl element = (ElementImpl) parentNode;
+						if (element.isEmptyTag()) { // empty tag format
+							// need to generate the start and the end tags
+							end = element.getEndOffset();
+							start = end - 2; // for "/>"
+							element.setEmptyTag(false);
+							preTag = this.generator.generateCloseTag(element);
+							postTag = this.generator.generateEndTag(element);
+							postElement = element;
+						}
+						else if (!element.hasStartTag()) {
+							start = element.getStartOffset();
+							end = start;
+							// invalid end tag or implicit tag
+							// need to generate the start tag
+							preTag = this.generator.generateStartTag(element);
+							if (preTag != null) {
+								int length = preTag.length();
+								if (length > 0) {
+									IStructuredDocumentRegion flatNode = new StructuredDocumentRegionProxy(start, length);
+									element.setStartStructuredDocumentRegion(flatNode);
+								}
+							}
+							if (!element.hasEndTag()) {
+								// implicit tag
+								// need to generate the end tags
+								postTag = this.generator.generateEndTag(element);
+								postElement = element;
+							}
+						}
+						else {
+							start = element.getStartEndOffset();
+							end = start;
+							preTag = getStartCloseTag(element);
+							if (preTag != null && preTag.length() > 0) {
+								if (!element.hasEndTag() && (element.isJSPContainer() || element.isCDATAContainer())) {
+									// need to generate the end tag
+									postTag = this.generator.generateEndTag(element);
+									postElement = element;
+								}
+							}
+						}
+					}
+					// else might DOCUMENT_NODE, start and end are 0
+				}
+			}
+		}
+
+		String source = null;
+		if (newChild != null) {
+			StringBuffer buffer = new StringBuffer();
+			int offset = start;
+			if (preTag != null) {
+				int length = preTag.length();
+				if (length > 0) {
+					offset += length;
+					buffer.append(preTag);
+				}
+			}
+
+			NodeImpl node = (NodeImpl) newChild;
+			while (node != null) {
+				if (node.getNodeType() == Node.ELEMENT_NODE) {
+					ElementImpl element = (ElementImpl) node;
+					if (element.preferEmptyTag())
+						element.setEmptyTag(true);
+					IStructuredDocumentRegion flatNode = null;
+					String startTag = this.generator.generateStartTag(element);
+					if (startTag != null) {
+						int length = startTag.length();
+						if (length > 0) {
+							buffer.append(startTag);
+							flatNode = new StructuredDocumentRegionProxy(offset, length);
+							offset += length;
+						}
+					}
+					element.setStartStructuredDocumentRegion(flatNode);
+				}
+				else {
+					String content = this.generator.generateSource(node);
+					if (content == null)
+						content = NodeImpl.EMPTY_STRING;
+					int length = content.length();
+					IStructuredDocumentRegion flatNode = null;
+					if (length > 0) {
+						buffer.append(content);
+						flatNode = new StructuredDocumentRegionProxy(offset, length);
+						offset += length;
+					}
+					node.setStructuredDocumentRegion(flatNode);
+				}
+
+				NodeImpl child = (NodeImpl) node.getFirstChild();
+				if (child != null) {
+					node = child;
+					continue;
+				}
+
+				if (node.getNodeType() == Node.ELEMENT_NODE) {
+					ElementImpl element = (ElementImpl) node;
+					IStructuredDocumentRegion flatNode = null;
+					String endTag = this.generator.generateEndTag(element);
+					if (endTag != null) {
+						int length = endTag.length();
+						if (length > 0) {
+							buffer.append(endTag);
+							flatNode = new StructuredDocumentRegionProxy(offset, length);
+							offset += length;
+						}
+					}
+					element.setEndStructuredDocumentRegion(flatNode);
+				}
+
+				while (node != null) {
+					if (node == newChild) {
+						node = null;
+						break;
+					}
+					NodeImpl next = (NodeImpl) node.getNextSibling();
+					if (next != null) {
+						node = next;
+						break;
+					}
+
+					node = (NodeImpl) node.getParentNode();
+					if (node.getNodeType() != Node.ELEMENT_NODE)
+						continue;
+					ElementImpl element = (ElementImpl) node;
+					IStructuredDocumentRegion flatNode = null;
+					String endTag = this.generator.generateEndTag(element);
+					if (endTag != null) {
+						int length = endTag.length();
+						if (length > 0) {
+							buffer.append(endTag);
+							flatNode = new StructuredDocumentRegionProxy(offset, length);
+							offset += length;
+						}
+					}
+					element.setEndStructuredDocumentRegion(flatNode);
+				}
+			}
+
+			if (postTag != null) {
+				int length = postTag.length();
+				if (length > 0) {
+					buffer.append(postTag);
+					if (postElement != null) {
+						IStructuredDocumentRegion flatNode = new StructuredDocumentRegionProxy(offset, length);
+						postElement.setEndStructuredDocumentRegion(flatNode);
+					}
+				}
+			}
+			source = buffer.toString();
+		}
+
+		if (start == end && (source == null || source.length() == 0)) {
+			// no thing changed
+			return;
+		}
+
+		replaceSource(source, start, end);
+	}
+
+	void replaceRegions(IStructuredDocumentRegion flatNode, ITextRegionList newRegions, ITextRegionList oldRegions) {
+		// future_TODO: optimize
+
+		NodeImpl root = (NodeImpl) this.model.getDocument();
+		this.parentNode = root;
+		this.nextNode = (NodeImpl) root.getFirstChild();
+
+		removeGapStructuredDocumentRegion(flatNode);
+		insertGapStructuredDocumentRegionBefore(flatNode.getStart());
+		changeStructuredDocumentRegion(flatNode);
+		insertGapStructuredDocumentRegionAfter(flatNode.getEnd());
+	}
+
+	/**
+	 * Wraps IStructuredDocumentRegion.replaceText() and sets contextual
+	 * information.
+	 */
+	private void replaceSource(String source, int start, int end) {
+		int inserted = 0;
+		if (source == null)
+			source = NodeImpl.EMPTY_STRING;
+		else
+			inserted = source.length();
+		int removed = end - start;
+		if (inserted == 0 && removed == 0)
+			return;
+
+		this.gapOffset = start;
+		this.gapLength = removed;
+		this.diff = inserted - removed;
+		// Note: due to bug
+		// https://w3.opensource.ibm.com/bugzilla/show_bug.cgi?id=3619
+		// for now assume "ignore readonly" region is ok -- assume DOM itself
+		// checks if
+		// ok to insert or not. In reality, we may have to make or "contains"
+		// method more
+		// better. Or, we may have to "perculate up" the parameter for clients
+		// to tell us programatically
+		// that its ok to insert/format in a read-only region.
+		getStructuredDocument().replaceText(this.model, this.gapOffset, this.gapLength, source, true);
+	}
+
+	void replaceStructuredDocumentRegions(IStructuredDocumentRegionList newStructuredDocumentRegions, IStructuredDocumentRegionList oldStructuredDocumentRegions) {
+		NodeImpl root = (NodeImpl) this.model.getDocument();
+
+		if (oldStructuredDocumentRegions != null) {
+			this.parentNode = root;
+			this.nextNode = (NodeImpl) root.getFirstChild();
+
+			Enumeration e = oldStructuredDocumentRegions.elements();
+			while (e.hasMoreElements()) {
+				IStructuredDocumentRegion flatNode = (IStructuredDocumentRegion) e.nextElement();
+				if (flatNode == null)
+					continue;
+				removeStructuredDocumentRegion(flatNode);
+				removeGapStructuredDocumentRegion(flatNode);
+			}
+		}
+
+		if (newStructuredDocumentRegions != null) {
+			this.parentNode = root;
+			this.nextNode = (NodeImpl) root.getFirstChild();
+
+			IStructuredDocumentRegion lastStructuredDocumentRegion = null;
+			Enumeration e = newStructuredDocumentRegions.elements();
+			while (e.hasMoreElements()) {
+				IStructuredDocumentRegion flatNode = (IStructuredDocumentRegion) e.nextElement();
+				if (flatNode == null)
+					continue;
+				if (lastStructuredDocumentRegion == null)
+					insertGapStructuredDocumentRegionBefore(flatNode.getStart());
+				insertStructuredDocumentRegion(flatNode);
+				lastStructuredDocumentRegion = flatNode;
+			}
+			if (lastStructuredDocumentRegion != null) {
+				insertGapStructuredDocumentRegionAfter(lastStructuredDocumentRegion.getEnd());
+			}
+			else {
+				insertGapStructuredDocumentRegionBefore(this.gapOffset);
+				// make sure to restore all backuped StructuredDocumentRegions
+				insertGapStructuredDocumentRegionAfter(this.gapOffset);
+			}
+		}
+		else {
+			this.parentNode = root;
+			this.nextNode = (NodeImpl) root.getFirstChild();
+
+			insertGapStructuredDocumentRegionBefore(this.gapOffset);
+			// make sure to restore all backuped StructuredDocumentRegions
+			insertGapStructuredDocumentRegionAfter(this.gapOffset);
+		}
+	}
+
+	/**
+	 */
+	private void updateAttrRegions(Element element, IStructuredDocumentRegion flatNode) {
+
+		// update attributes
+		ITextRegionList regions = flatNode.getRegions();
+		if (regions == null)
+			return;
+		NamedNodeMap attributes = element.getAttributes();
+		if (attributes == null)
+			return;
+		int index = -1;
+		AttrImpl attr = null;
+		Iterator e = regions.iterator();
+		while (e.hasNext()) {
+			ITextRegion region = (ITextRegion) e.next();
+			String regionType = region.getType();
+			if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) {
+				attr = (AttrImpl) attributes.item(++index);
+				if (attr != null) {
+					attr.setNameRegion(region);
+					// reset other regions
+					attr.setEqualRegion(null);
+					attr.setValueRegion(null);
+				}
+			}
+			else if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_EQUALS) {
+				if (attr != null)
+					attr.setEqualRegion(region);
+			}
+			else if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
+				if (attr != null) {
+					attr.setValueRegion(region);
+					attr = null;
+				}
+			}
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/encoding/XMLDocumentCharsetDetector.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/encoding/XMLDocumentCharsetDetector.java
new file mode 100644
index 0000000..697f649
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/encoding/XMLDocumentCharsetDetector.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.encoding;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.wst.sse.core.internal.document.DocumentReader;
+import org.eclipse.wst.sse.core.internal.document.IDocumentCharsetDetector;
+import org.eclipse.wst.xml.core.internal.contenttype.XMLResourceEncodingDetector;
+
+
+/**
+ * This class reads and parses first of XML file to get encoding.
+ *  
+ */
+public class XMLDocumentCharsetDetector extends XMLResourceEncodingDetector implements IDocumentCharsetDetector {
+
+	/**
+	 * XMLLoader constructor comment.
+	 */
+	public XMLDocumentCharsetDetector() {
+		super();
+	}
+
+	public void set(IDocument document) {
+		set(new DocumentReader(document, 0));
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/encoding/XMLDocumentLoader.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/encoding/XMLDocumentLoader.java
new file mode 100644
index 0000000..2316b34
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/encoding/XMLDocumentLoader.java
@@ -0,0 +1,82 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.encoding;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.jface.text.IDocumentPartitioner;
+import org.eclipse.wst.sse.core.internal.document.AbstractDocumentLoader;
+import org.eclipse.wst.sse.core.internal.document.IDocumentCharsetDetector;
+import org.eclipse.wst.sse.core.internal.document.IDocumentLoader;
+import org.eclipse.wst.sse.core.internal.document.StructuredDocumentFactory;
+import org.eclipse.wst.sse.core.internal.encoding.ContentTypeEncodingPreferences;
+import org.eclipse.wst.sse.core.internal.ltk.parser.RegionParser;
+import org.eclipse.wst.sse.core.internal.provisional.document.IEncodedDocument;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+import org.eclipse.wst.sse.core.internal.text.BasicStructuredDocument;
+import org.eclipse.wst.xml.core.internal.parser.XMLSourceParser;
+import org.eclipse.wst.xml.core.internal.parser.XMLStructuredDocumentReParser;
+import org.eclipse.wst.xml.core.internal.provisional.contenttype.ContentTypeIdForXML;
+import org.eclipse.wst.xml.core.internal.text.rules.StructuredTextPartitionerForXML;
+
+
+/**
+ * This class reads an XML file and creates an XML Structured Model.
+ * 
+ */
+public class XMLDocumentLoader extends AbstractDocumentLoader {
+
+	public XMLDocumentLoader() {
+		super();
+	}
+
+	public IDocumentPartitioner getDefaultDocumentPartitioner() {
+		return new StructuredTextPartitionerForXML();
+	}
+
+	public IDocumentCharsetDetector getDocumentEncodingDetector() {
+		if (fDocumentEncodingDetector == null) {
+			fDocumentEncodingDetector = new XMLDocumentCharsetDetector();
+		}
+		return fDocumentEncodingDetector;
+	}
+
+	public RegionParser getParser() {
+		return new XMLSourceParser();
+	}
+
+	protected String getPreferredNewLineDelimiter(IFile file) {
+		String delimiter = ContentTypeEncodingPreferences.getPreferredNewLineDelimiter(ContentTypeIdForXML.ContentTypeID_XML);
+		if (delimiter == null)
+			delimiter = super.getPreferredNewLineDelimiter(file);
+		return delimiter;
+	}
+
+	protected String getSpecDefaultEncoding() {
+		// by default, UTF-8 as per XML spec
+		final String enc = "UTF-8"; //$NON-NLS-1$
+		return enc;
+	}
+
+	protected IEncodedDocument newEncodedDocument() {
+		IStructuredDocument structuredDocument = StructuredDocumentFactory.getNewStructuredDocumentInstance(getParser());
+		if (structuredDocument instanceof BasicStructuredDocument) {
+			((BasicStructuredDocument) structuredDocument).setReParser(new XMLStructuredDocumentReParser());
+		}
+		return structuredDocument;
+	}
+
+	public IDocumentLoader newInstance() {
+		return new XMLDocumentLoader();
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/formatter/DefaultXMLPartitionFormatter.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/formatter/DefaultXMLPartitionFormatter.java
new file mode 100644
index 0000000..66b4b8d
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/formatter/DefaultXMLPartitionFormatter.java
@@ -0,0 +1,1684 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 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
+ *     David Carver (STAR) - bug 297006 - String Comparison
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.formatter;
+
+import java.util.Iterator;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.Position;
+import org.eclipse.text.edits.DeleteEdit;
+import org.eclipse.text.edits.InsertEdit;
+import org.eclipse.text.edits.MultiTextEdit;
+import org.eclipse.text.edits.ReplaceEdit;
+import org.eclipse.text.edits.TextEdit;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
+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.ITextRegionList;
+import org.eclipse.wst.xml.core.internal.Logger;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMText;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+import org.eclipse.wst.xml.core.internal.ssemodelquery.ModelQueryAdapter;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+public class DefaultXMLPartitionFormatter {
+	/**
+	 * Just a small container class that holds a DOMNode & documentRegion that
+	 * should represent each other.
+	 */
+	protected class DOMRegion {
+		public IDOMNode domNode;
+		public IStructuredDocumentRegion documentRegion;
+	}
+
+	static private final String PRESERVE = "preserve";//$NON-NLS-1$
+	static private final String COLLAPSE = "collapse";//$NON-NLS-1$
+	static private final String REPLACE = "replace";//$NON-NLS-1$
+	static private final String PRESERVE_QUOTED = "\"preserve\"";//$NON-NLS-1$
+	static private final String XML_SPACE = "xml:space";//$NON-NLS-1$
+	static private final String XSL_NAMESPACE = "http://www.w3.org/1999/XSL/Transform"; //$NON-NLS-1$
+	static private final String XSL_ATTRIBUTE = "attribute"; //$NON-NLS-1$
+	static private final String XSL_TEXT = "text"; //$NON-NLS-1$
+	static private final String SPACE = " "; //$NON-NLS-1$
+	static private final String EMPTY = ""; //$NON-NLS-1$
+	static private final String PROPERTY_WHITESPACE_FACET = "org.eclipse.wst.xsd.cm.properties/whitespace"; //$NON-NLS-1$
+
+	private XMLFormattingPreferences fPreferences = null;
+	private IProgressMonitor fProgressMonitor;
+
+	private int replaceSpaces(TextEdit textEdit, int spaceStartOffset, int availableLineWidth, String whitespaceRun) {
+		StringBuffer buff = new StringBuffer(whitespaceRun);
+		for(int i = 0; i < buff.length(); i++) {
+			buff.setCharAt(i, ' '); //$NON-NLS-1$
+		}
+		String replacementString = buff.toString();
+		if (!replacementString.equals(whitespaceRun)) {
+			ReplaceEdit replaceEdit = new ReplaceEdit(spaceStartOffset, whitespaceRun.length(), replacementString);
+			textEdit.addChild(replaceEdit);
+		}
+		return availableLineWidth;
+	}
+	
+	private int collapseSpaces(TextEdit textEdit, int spaceStartOffset, int availableLineWidth, String whitespaceRun) {
+		// prefer to use use existing whitespace
+		int existingWhitespaceOffset = whitespaceRun.indexOf(' ');
+		if (existingWhitespaceOffset > -1) {
+			// delete whitespaces before and after existing whitespace
+			if (existingWhitespaceOffset > 0) {
+				DeleteEdit deleteEdit = new DeleteEdit(spaceStartOffset, existingWhitespaceOffset);
+				textEdit.addChild(deleteEdit);
+			}
+			if (existingWhitespaceOffset < whitespaceRun.length() - 1) {
+				int nextOffset = existingWhitespaceOffset + 1;
+				DeleteEdit deleteEdit = new DeleteEdit(spaceStartOffset + nextOffset, whitespaceRun.length() - nextOffset);
+				textEdit.addChild(deleteEdit);
+			}
+		}
+		else {
+			// delete all whitespace and insert new one
+			// collapse whitespace by deleting whitespace
+			DeleteEdit deleteEdit = new DeleteEdit(spaceStartOffset, whitespaceRun.length());
+			textEdit.addChild(deleteEdit);
+			// then insert one space
+			InsertEdit insertEdit = new InsertEdit(spaceStartOffset, SPACE);
+			textEdit.addChild(insertEdit);
+		}
+		// remember to account for space added
+		--availableLineWidth;
+		return availableLineWidth;
+	}
+	
+	private int collapseAndIndent(TextEdit textEdit, int spaceStartOffset, int availableLineWidth, int indentLevel, String whitespaceRun, IStructuredDocumentRegion currentRegion) {
+		// Need to keep blank lines, but still collapse the whitespace
+		String lineDelimiters = null;
+		if (!getFormattingPreferences().getClearAllBlankLines()) {
+			lineDelimiters = extractLineDelimiters(whitespaceRun, currentRegion);
+			String formattedLine = lineDelimiters + getIndentString(indentLevel);
+			if(lineDelimiters.length() > 0 && !formattedLine.equals(whitespaceRun)) {
+				textEdit.addChild(new ReplaceEdit(spaceStartOffset, whitespaceRun.length(), formattedLine));
+				availableLineWidth = getFormattingPreferences().getMaxLineWidth() - indentLevel;
+			}
+		}
+		if (lineDelimiters == null || lineDelimiters.length() == 0) {
+			availableLineWidth = collapseSpaces(textEdit, spaceStartOffset, availableLineWidth, whitespaceRun);
+		}
+		return availableLineWidth;
+	}
+
+	private void deleteTrailingSpaces(TextEdit textEdit, ITextRegion currentTextRegion, IStructuredDocumentRegion currentDocumentRegion) {
+		int textEnd = currentTextRegion.getTextEnd();
+		int textEndOffset = currentDocumentRegion.getStartOffset() + textEnd;
+		int difference = currentTextRegion.getEnd() - textEnd;
+		DeleteEdit deleteEdit = new DeleteEdit(textEndOffset, difference);
+		textEdit.addChild(deleteEdit);
+	}
+
+	public TextEdit format(IDocument document, int start, int length) {
+		return format(document, start, length, new XMLFormattingPreferences());
+	}
+
+	public TextEdit format(IDocument document, int start, int length, XMLFormattingPreferences preferences) {
+		TextEdit edit = null;
+		if (document instanceof IStructuredDocument) {
+			IStructuredModel model = StructuredModelManager.getModelManager().getModelForEdit((IStructuredDocument) document);
+			if (model != null) {
+				try {
+					edit = format(model, start, length, preferences);
+				}
+				finally {
+					model.releaseFromEdit();
+				}
+			}
+		}
+		return edit;
+	}
+
+	public TextEdit format(IStructuredModel model, int start, int length) {
+		return format(model, start, length, new XMLFormattingPreferences());
+	}
+
+	public TextEdit format(IStructuredModel model, int start, int length, XMLFormattingPreferences preferences) {
+		setFormattingPreferences(preferences);
+
+		TextEdit edit = new MultiTextEdit();
+		IStructuredDocument document = model.getStructuredDocument();
+		// get initial document region
+		IStructuredDocumentRegion currentRegion = document.getRegionAtCharacterOffset(start);
+		if (currentRegion != null) {
+			int startOffset = currentRegion.getStartOffset();
+
+			// get initial dom node
+			IndexedRegion currentIndexedRegion = model.getIndexedRegion(startOffset);
+			if (currentIndexedRegion instanceof IDOMNode) {
+				// set up domRegion which will contain current region to be
+				// formatted
+				IDOMNode currentDOMNode = (IDOMNode) currentIndexedRegion;
+				DOMRegion domRegion = new DOMRegion();
+				domRegion.documentRegion = currentRegion;
+				domRegion.domNode = currentDOMNode;
+				
+				XMLFormattingConstraints parentConstraints = getRegionConstraints(currentDOMNode);
+				
+				/* if the whitespace strategy is declared as default, get it from the preferences */
+				if(XMLFormattingConstraints.DEFAULT.equals(parentConstraints.getWhitespaceStrategy()))
+					parentConstraints.setWhitespaceStrategy(preferences.getElementWhitespaceStrategy());
+				
+				// TODO: initialize indentLevel
+				// initialize available line width
+				int lineWidth = getFormattingPreferences().getMaxLineWidth();
+				try {
+					IRegion lineInfo = document.getLineInformationOfOffset(startOffset);
+					lineWidth = lineWidth - (startOffset - lineInfo.getOffset());
+				}
+				catch (BadLocationException e) {
+					Logger.log(Logger.WARNING_DEBUG, e.getMessage(), e);
+				}
+				parentConstraints.setAvailableLineWidth(lineWidth);
+
+				// format all siblings (and their children) as long they
+				// overlap with start/length
+				Position formatRange = new Position(start, length);
+				formatSiblings(edit, domRegion, parentConstraints, formatRange);
+			}
+		}
+		return edit;
+	}
+
+	/**
+	 * Determines the formatting constraints for a specified node based on
+	 * its ancestors' formatting. In particular, if any ancestor node either
+	 * explicitly defines whitespace preservation or ignorance, that
+	 * whitespace strategy should be used for <code>currentNode</code> and 
+	 * all of its descendants.
+	 * 
+	 * @param currentNode the node to investigate the ancestry of to determine
+	 * formatting constraints
+	 * 
+	 * @return formatting constraints defined by an ancestor
+	 */
+	private XMLFormattingConstraints getRegionConstraints(IDOMNode currentNode) {
+		IDOMNode iterator = currentNode;
+		XMLFormattingConstraints result = new XMLFormattingConstraints();
+		DOMRegion region = new DOMRegion();
+		XMLFormattingConstraints parentConstraints = new XMLFormattingConstraints();
+		boolean parent = true;
+		
+		/* Iterate through the ancestry to find if any explicit whitespace strategy has
+		 * been defined
+		 */
+		while(iterator != null && iterator.getNodeType() != Node.DOCUMENT_NODE) {
+			iterator = (IDOMNode) iterator.getParentNode();
+			region.domNode = iterator;
+			region.documentRegion = iterator.getFirstStructuredDocumentRegion();
+			
+			updateFormattingConstraints(null, null, result, region);
+			
+			/* If this is the parent of the current node, keep the constraints
+			 * in case no other constraints are identified
+			 */
+			if(parent) {
+				parentConstraints.copyConstraints(result);
+				parent = false;
+			}
+			
+			/* A parent who has defined a specific whitespace strategy was found */
+			if(XMLFormattingConstraints.PRESERVE.equals(result.getWhitespaceStrategy()) || XMLFormattingConstraints.DEFAULT.equals(result.getWhitespaceStrategy()))
+				return result;
+		}
+		
+		return parentConstraints;
+	}
+//	private XMLFormattingConstraints getRegionConstraints(IDOMNode currentNode) {
+//		IDOMNode iterator = (IDOMNode) currentNode.getParentNode();
+//		XMLFormattingConstraints result = new XMLFormattingConstraints();
+//		DOMRegion region = new DOMRegion();
+//		
+//		/* Iterate through the ancestry to find if any explicit whitespace strategy has
+//		 * been defined
+//		 */
+//		while(iterator != null && iterator.getNodeType() != Node.DOCUMENT_NODE) {
+
+//			region.domNode = iterator;
+//			region.documentRegion = iterator.getFirstStructuredDocumentRegion();
+//			
+//			updateFormattingConstraints(null, null, result, region);
+//			
+//			/* A parent who has defined a specific whitespace strategy was found */
+//			if(XMLFormattingConstraints.PRESERVE == result.getWhitespaceStrategy() || XMLFormattingConstraints.DEFAULT == result.getWhitespaceStrategy())
+//				return result;
+//			
+//			iterator = (IDOMNode) iterator.getParentNode();
+//		}
+//		
+//		return null;
+//	}
+	
+	/**
+	 * Formats the given xml content region
+	 * 
+	 * @param textEdit
+	 * @param formatRange
+	 * @param parentConstraints
+	 * @param currentDOMRegion
+	 * @param previousRegion
+	 */
+	private void formatContent(TextEdit textEdit, Position formatRange, XMLFormattingConstraints parentConstraints, DOMRegion currentDOMRegion, IStructuredDocumentRegion previousRegion) {
+		IStructuredDocumentRegion currentRegion = currentDOMRegion.documentRegion;
+		String fullText = currentDOMRegion.domNode.getSource();
+
+		// check if in preserve space mode, if so, don't touch anything but
+		// make sure to update available line width
+		String whitespaceMode = parentConstraints.getWhitespaceStrategy();
+		if (XMLFormattingConstraints.PRESERVE.equals(whitespaceMode)) {
+			int availableLineWidth = parentConstraints.getAvailableLineWidth();
+			availableLineWidth = updateLineWidthWithLastLine(fullText, availableLineWidth);
+
+			// update available line width in constraints
+			parentConstraints.setAvailableLineWidth(availableLineWidth);
+			// A text node can contain multiple structured document regions - sync the documentRegion
+			// with the last region of the node since the text from all regions was formatted
+			currentDOMRegion.documentRegion = currentDOMRegion.domNode.getLastStructuredDocumentRegion();
+			return;
+		}
+
+		// if content is just whitespace and there's something after it
+		// just skip over this region because region will take care of it
+		boolean isAllWhitespace = ((IDOMText) currentDOMRegion.domNode).isElementContentWhitespace();
+		IStructuredDocumentRegion nextDocumentRegion = null;
+		if (isAllWhitespace) {
+			parentConstraints.setAvailableLineWidth(fPreferences.getMaxLineWidth());
+			nextDocumentRegion = currentRegion.getNext();
+			if (nextDocumentRegion != null)
+				return;
+		}
+
+		// special handling if text follows an entity or cdata region
+		if (!XMLFormattingConstraints.COLLAPSE.equals(whitespaceMode) && previousRegion != null) {
+			String previouRegionType = previousRegion.getType();
+			if (DOMRegionContext.XML_ENTITY_REFERENCE.equals(previouRegionType) || DOMRegionContext.XML_CDATA_TEXT.equals(previouRegionType))
+				whitespaceMode = XMLFormattingConstraints.COLLAPSE;
+		}
+		// also, special handling if text is before an entity or cdata region
+		if (!XMLFormattingConstraints.COLLAPSE.equals(whitespaceMode)) {
+			// get next document region if dont already have it
+			if (nextDocumentRegion == null)
+				nextDocumentRegion = currentRegion.getNext();
+			if (nextDocumentRegion != null) {
+				String nextRegionType = nextDocumentRegion.getType();
+				if (DOMRegionContext.XML_ENTITY_REFERENCE.equals(nextRegionType) || DOMRegionContext.XML_CDATA_TEXT.equals(nextRegionType))
+					whitespaceMode = XMLFormattingConstraints.COLLAPSE;
+			}
+		}
+		formatTextInContent(textEdit, parentConstraints, currentRegion, fullText, whitespaceMode);
+		// A text node can contain multiple structured document regions - sync the documentRegion
+		// with the last region of the node since the text from all regions was formatted
+		currentDOMRegion.documentRegion = currentDOMRegion.domNode.getLastStructuredDocumentRegion();
+	}
+
+	private void formatEmptyStartTagWithNoAttr(TextEdit textEdit, XMLFormattingConstraints constraints, IStructuredDocumentRegion currentDocumentRegion, IStructuredDocumentRegion previousDocumentRegion, int availableLineWidth, String indentStrategy, String whitespaceStrategy, ITextRegion currentTextRegion) {
+		// get preference if there should be a space or not between tag
+		// name and empty tag close
+		// <tagName />
+		boolean oneSpaceInTagName = getFormattingPreferences().getSpaceBeforeEmptyCloseTag();
+
+		// calculate available line width
+		int tagNameLineWidth = currentTextRegion.getTextLength() + 3;
+		if (oneSpaceInTagName) {
+			// add one more to account for space before empty tag close
+			++tagNameLineWidth;
+		}
+		availableLineWidth -= tagNameLineWidth;
+
+		if (XMLFormattingConstraints.INLINE.equals(indentStrategy)) {
+			// if was inlining, need to check if out of available line
+			// width
+			if (availableLineWidth < 0) {
+				// need to indent if possible
+				int lineWidth = indentIfPossible(textEdit, constraints, currentDocumentRegion, previousDocumentRegion, whitespaceStrategy, indentStrategy, true);
+				// update available line width
+				if (lineWidth > 0)
+					availableLineWidth = lineWidth - tagNameLineWidth;
+				else
+					availableLineWidth -= tagNameLineWidth;
+			}
+			else {
+				// no need to indent
+				// just make sure to delete previous whitespace if
+				// needed
+				if ((DOMRegionContext.XML_CONTENT.equals(previousDocumentRegion.getType())) && (previousDocumentRegion.getFullText().trim().length() == 0)) {
+					availableLineWidth = collapseSpaces(textEdit, previousDocumentRegion.getStartOffset(), availableLineWidth, previousDocumentRegion.getFullText());
+				}
+			}
+		}
+
+		// delete any trail spaces after tag name
+		int textLength = currentTextRegion.getTextLength();
+		int regionLength = currentTextRegion.getLength();
+
+		boolean thereAreSpaces = textLength < regionLength;
+		if (!oneSpaceInTagName && thereAreSpaces) {
+			deleteTrailingSpaces(textEdit, currentTextRegion, currentDocumentRegion);
+		}
+		else if(oneSpaceInTagName) {
+			insertSpaceAndCollapse(textEdit, currentDocumentRegion, availableLineWidth, currentTextRegion);
+		}
+		constraints.setAvailableLineWidth(availableLineWidth);
+	}
+
+	/**
+	 * Formats an end tag
+	 * 
+	 * @param textEdit
+	 * @param currentRegion
+	 * @param textRegions
+	 */
+	private void formatEndTag(TextEdit textEdit, Position formatRange, XMLFormattingConstraints constraints, DOMRegion currentDOMRegion, IStructuredDocumentRegion previousDocumentRegion) {
+		IStructuredDocumentRegion currentDocumentRegion = currentDOMRegion.documentRegion;
+
+		String whitespaceStrategy = constraints.getWhitespaceStrategy();
+		String indentStrategy = constraints.getIndentStrategy();
+
+		// do not format space before start tag if preserving spaces
+		if (whitespaceStrategy != XMLFormattingConstraints.PRESERVE) {
+			// format like indent strategy says
+			if (XMLFormattingConstraints.INDENT.equals(indentStrategy) || XMLFormattingConstraints.NEW_LINE.equals(indentStrategy)) {
+				int availableLineWidth = indentIfPossible(textEdit, constraints, currentDocumentRegion, previousDocumentRegion, whitespaceStrategy, indentStrategy, false);
+				constraints.setAvailableLineWidth(availableLineWidth);
+			}
+		}
+		// format the end tag itself
+		formatWithinEndTag(textEdit, constraints, currentDocumentRegion, previousDocumentRegion);
+	}
+
+	/**
+	 * Formats the given region (and all its children) contained in domRegion.
+	 * 
+	 * @param edit
+	 *            edits required to format
+	 * @param formatRange
+	 *            document range to format (only format content within this
+	 *            range)
+	 * @param parentConstraints
+	 * @param domRegion
+	 *            assumes dom node & region are not null
+	 * @param previousRegion
+	 *            could be null
+	 * @return Returns the last region formatted
+	 */
+	private DOMRegion formatRegion(TextEdit edit, Position formatRange, XMLFormattingConstraints parentConstraints, DOMRegion domRegion, IStructuredDocumentRegion previousRegion) {
+		IStructuredDocumentRegion currentRegion = domRegion.documentRegion;
+		String regionType = currentRegion.getType();
+		if (DOMRegionContext.XML_TAG_NAME.equals(regionType)) {
+			ITextRegion textRegion = currentRegion.getFirstRegion();
+			String textRegionType = textRegion.getType();
+			if (DOMRegionContext.XML_TAG_OPEN.equals(textRegionType)) {
+				domRegion = formatStartTag(edit, formatRange, parentConstraints, domRegion, previousRegion);
+			}
+			else if (DOMRegionContext.XML_END_TAG_OPEN.equals(textRegionType)) {
+				formatEndTag(edit, formatRange, parentConstraints, domRegion, previousRegion);
+			}
+		}
+		else if (DOMRegionContext.XML_CONTENT.equals(regionType) || domRegion.domNode.getNodeType() == Node.TEXT_NODE) {
+			formatContent(edit, formatRange, parentConstraints, domRegion, previousRegion);
+		}
+		else if (DOMRegionContext.XML_COMMENT_TEXT.equals(regionType)) {
+			formatComment(edit, formatRange, parentConstraints, domRegion, previousRegion);
+		}
+		else {
+			// unknown, so just leave alone for now but make sure to update
+			// available line width
+			String fullText = currentRegion.getFullText();
+			int width = updateLineWidthWithLastLine(fullText, parentConstraints.getAvailableLineWidth());
+			parentConstraints.setAvailableLineWidth(width);
+		}
+		return domRegion;
+	}
+
+	/**
+	 * Formats the domRegion and all of its children and siblings
+	 * 
+	 * @param edit
+	 * @param domRegion
+	 * @param parentConstraints
+	 * @param formatRange
+	 */
+	private void formatSiblings(TextEdit edit, DOMRegion domRegion, XMLFormattingConstraints parentConstraints, Position formatRange) {
+		IStructuredDocumentRegion previousRegion = null;
+		IStructuredDocumentRegion currentRegion = domRegion.documentRegion;
+		IDOMNode currentDOMNode = domRegion.domNode;
+		while (currentDOMNode != null && currentRegion != null && formatRange.overlapsWith(currentRegion.getStartOffset(), currentRegion.getLength()) && (fProgressMonitor == null || !fProgressMonitor.isCanceled())) {
+			domRegion.documentRegion = currentRegion;
+			domRegion.domNode = currentDOMNode;
+
+			// need to make sure current document region and current
+			// dom node match up
+			if (currentDOMNode.getFirstStructuredDocumentRegion().equals(currentRegion)) {
+				// format this document region/node, formatRegion will
+				// return the last node/region formatted
+				domRegion = formatRegion(edit, formatRange, parentConstraints, domRegion, previousRegion);
+			}
+			else {
+				// TODO: need to figure out what to do if they don't
+				// match up
+			}
+			previousRegion = domRegion.documentRegion;
+			// get the next sibling information
+			if (domRegion.domNode != null)
+				currentDOMNode = (IDOMNode) domRegion.domNode.getNextSibling();
+			else
+				currentDOMNode = null;
+			currentRegion = previousRegion.getNext();
+		}
+	}
+
+	/**
+	 * Formats a start tag
+	 * 
+	 * @param textEdit
+	 * @param currentRegion
+	 * @param textRegions
+	 */
+	private DOMRegion formatStartTag(TextEdit textEdit, Position formatRange, XMLFormattingConstraints parentConstraints, DOMRegion currentDOMRegion, IStructuredDocumentRegion previousDocumentRegion) {
+		// determine proper indent by referring to parent constraints,
+		// previous node, and current node
+		IStructuredDocumentRegion currentDocumentRegion = currentDOMRegion.documentRegion;
+		IDOMNode currentDOMNode = currentDOMRegion.domNode;
+
+		// create a constraint for this tag
+		XMLFormattingConstraints thisConstraints = new XMLFormattingConstraints();
+		XMLFormattingConstraints childrenConstraints = new XMLFormattingConstraints();
+		updateFormattingConstraints(parentConstraints, thisConstraints, childrenConstraints, currentDOMRegion);
+
+		if(XMLFormattingConstraints.DEFAULT.equals(childrenConstraints.getWhitespaceStrategy()))
+			childrenConstraints.setWhitespaceStrategy((new XMLFormattingPreferences()).getElementWhitespaceStrategy());
+			
+		String whitespaceStrategy = thisConstraints.getWhitespaceStrategy();
+		String indentStrategy = thisConstraints.getIndentStrategy();
+		int availableLineWidth = thisConstraints.getAvailableLineWidth();
+
+		// format space before start tag
+		// do not format space before start tag if preserving spaces
+		if (!XMLFormattingConstraints.PRESERVE.equals(whitespaceStrategy)) {
+			// format like indent strategy says
+			if (XMLFormattingConstraints.INDENT.equals(indentStrategy) || XMLFormattingConstraints.NEW_LINE.equals(indentStrategy)) {
+				availableLineWidth = indentIfPossible(textEdit, thisConstraints, currentDocumentRegion, previousDocumentRegion, whitespaceStrategy, indentStrategy, true);
+				if (availableLineWidth > 0)
+					thisConstraints.setAvailableLineWidth(availableLineWidth);
+			}
+		}
+		// format the start tag itself
+		boolean tagEnded = formatWithinTag(textEdit, thisConstraints, currentDocumentRegion, previousDocumentRegion);
+
+		// format children
+		if (!tagEnded) {
+			// update childConstraints with thisConstraint's indentLevel &
+			// availableLineWidth
+			childrenConstraints.setIndentLevel(thisConstraints.getIndentLevel());
+			childrenConstraints.setAvailableLineWidth(thisConstraints.getAvailableLineWidth());
+
+			previousDocumentRegion = currentDocumentRegion;
+			IDOMNode childDOMNode = (IDOMNode) currentDOMNode.getFirstChild();
+			IStructuredDocumentRegion nextRegion = currentDocumentRegion.getNext();
+			boolean passedFormatRange = false;
+			// as long as there is one child
+			if (childDOMNode != null && nextRegion != null) {
+				while (childDOMNode != null && nextRegion != null && !passedFormatRange && (fProgressMonitor == null || !fProgressMonitor.isCanceled())) {
+					DOMRegion childDOMRegion = new DOMRegion();
+					childDOMRegion.documentRegion = nextRegion;
+					childDOMRegion.domNode = childDOMNode;
+					if (nextRegion.equals(childDOMNode.getFirstStructuredDocumentRegion())) {
+						// format children. pass in child constraints
+						childDOMRegion = formatRegion(textEdit, formatRange, childrenConstraints, childDOMRegion, previousDocumentRegion);
+					}
+					else {
+						// TODO: what happens if they dont match up?
+					}
+
+					// update childDOMRegion with next dom/region node
+					if (childDOMRegion.domNode != null) {
+						childDOMNode = (IDOMNode) childDOMRegion.domNode.getNextSibling();
+					}
+					else {
+						childDOMNode = null;
+					}
+					previousDocumentRegion = childDOMRegion.documentRegion;
+					nextRegion = previousDocumentRegion.getNext();
+					if (nextRegion != null)
+						passedFormatRange = !formatRange.overlapsWith(nextRegion.getStartOffset(), nextRegion.getLength());
+				}
+			}
+			else {
+				// there were no children, so keep end tag inlined
+				childrenConstraints.setWhitespaceStrategy(XMLFormattingConstraints.COLLAPSE);
+				childrenConstraints.setIndentStrategy(XMLFormattingConstraints.INLINE);
+			}
+
+			if (!passedFormatRange) {
+				// update the dom region with the last formatted region/dom
+				// node should be end tag and this tag's DOMNode
+				currentDOMRegion.documentRegion = nextRegion;
+				currentDOMRegion.domNode = currentDOMNode;
+
+				// end tag's indent level should be same as start tag's
+				childrenConstraints.setIndentLevel(thisConstraints.getIndentLevel());
+				// format end tag
+				boolean formatEndTag = false;
+				if (nextRegion != null && currentDOMNode != null) {
+					ITextRegionList rs = nextRegion.getRegions();
+					if (rs.size() > 1) {
+						ITextRegion r = rs.get(0);
+						if (r != null && DOMRegionContext.XML_END_TAG_OPEN.equals(r.getType())) {
+							r = rs.get(1);
+							if (r != null && DOMRegionContext.XML_TAG_NAME.equals(r.getType())) {
+								String tagName = nextRegion.getText(r);
+								if (tagName != null && tagName.equals(currentDOMNode.getNodeName()))
+									formatEndTag = true;
+							}
+						}
+
+					}
+				}
+				if (formatEndTag)
+					formatEndTag(textEdit, formatRange, childrenConstraints, currentDOMRegion, previousDocumentRegion);
+				else {
+					// missing end tag so return last formatted document
+					// region
+					currentDOMRegion.documentRegion = previousDocumentRegion;
+				}
+			}
+			else {
+				// passed format range before could finish, so update dom
+				// region to last known formatted region
+				currentDOMRegion.documentRegion = nextRegion;
+				currentDOMRegion.domNode = childDOMNode;
+			}
+
+			// update parent constraint since this is what is passed back
+			parentConstraints.setAvailableLineWidth(childrenConstraints.getAvailableLineWidth());
+		}
+		else {
+			// update available line width
+			parentConstraints.setAvailableLineWidth(thisConstraints.getAvailableLineWidth());
+		}
+		return currentDOMRegion;
+	}
+
+	private void formatStartTagWithNoAttr(TextEdit textEdit, XMLFormattingConstraints constraints, IStructuredDocumentRegion currentDocumentRegion, IStructuredDocumentRegion previousDocumentRegion, int availableLineWidth, String indentStrategy, String whitespaceStrategy, ITextRegion currentTextRegion) {
+		// calculate available line width
+		int tagNameLineWidth = currentTextRegion.getTextLength() + 2;
+		availableLineWidth -= tagNameLineWidth;
+
+		if (XMLFormattingConstraints.INLINE.equals(indentStrategy)) {
+			// if was inlining, need to check if out of available line
+			// width
+			if (availableLineWidth < 0) {
+				// need to indent if possible
+				int lineWidth = indentIfPossible(textEdit, constraints, currentDocumentRegion, previousDocumentRegion, whitespaceStrategy, indentStrategy, true);
+				// update available line width
+				if (lineWidth > 0)
+					availableLineWidth = lineWidth - tagNameLineWidth;
+				else
+					availableLineWidth -= tagNameLineWidth;
+			}
+			else {
+				// no need to indent
+				// just make sure to delete previous whitespace if
+				// needed
+				if (previousDocumentRegion != null) {
+					if (DOMRegionContext.XML_CONTENT.equals(previousDocumentRegion.getType())) {
+						String previousDocumentRegionText = previousDocumentRegion.getFullText();
+						if (previousDocumentRegionText.trim().length() == 0) {
+							availableLineWidth = collapseSpaces(textEdit, previousDocumentRegion.getStartOffset(), availableLineWidth, previousDocumentRegionText);
+						}
+					}
+				}
+			}
+		}
+
+		// delete any trail spaces after tag name
+		if (currentTextRegion.getTextLength() < currentTextRegion.getLength()) {
+			deleteTrailingSpaces(textEdit, currentTextRegion, currentDocumentRegion);
+		}
+		constraints.setAvailableLineWidth(availableLineWidth);
+	}
+
+	/**
+	 * Format the text in xml content
+	 * 
+	 * @param textEdit
+	 * @param parentConstraints
+	 * @param currentRegion
+	 * @param fullText
+	 * @param whitespaceMode
+	 */
+	private void formatTextInContent(TextEdit textEdit, XMLFormattingConstraints parentConstraints, IStructuredDocumentRegion currentRegion, String fullText, String whitespaceMode) {
+		int availableLineWidth = parentConstraints.getAvailableLineWidth();
+
+		// determine indentation
+		boolean forceInitialIndent = false;
+		int indentLevel = parentConstraints.getIndentLevel() + 1;
+		String indentMode = parentConstraints.getIndentStrategy();
+		if (XMLFormattingConstraints.INDENT.equals(indentMode)) {
+			forceInitialIndent = true;
+		}
+		if (XMLFormattingConstraints.NEW_LINE.equals(indentMode)) {
+			indentLevel = parentConstraints.getIndentLevel();
+			forceInitialIndent = true;
+		}
+
+		int fullTextOffset = 0;
+		char[] fullTextArray = fullText.toCharArray();
+		while (fullTextOffset < fullTextArray.length) {
+			// gather all whitespaces
+			String whitespaceRun = getCharacterRun(fullTextArray, fullTextOffset, true);
+			if (whitespaceRun.length() > 0) {
+				// offset where whitespace starts
+				int whitespaceStart = fullTextOffset;
+				// update current offset in fullText
+				fullTextOffset += whitespaceRun.length();
+
+				// gather following word
+				String characterRun = getCharacterRun(fullTextArray, fullTextOffset, false);
+				int characterRunLength = characterRun.length();
+				if (characterRunLength > 0) {
+					// indent if word is too long or forcing initial
+					// indent
+					availableLineWidth -= characterRunLength;
+					// offset where indent/collapse will happen
+					int startOffset = currentRegion.getStartOffset() + whitespaceStart;
+					if (forceInitialIndent || (availableLineWidth <= 0)) {
+						// indent if not already indented
+						availableLineWidth = indentIfNotAlreadyIndented(textEdit, currentRegion, indentLevel, startOffset, whitespaceRun);
+						// remember to subtract word length
+						availableLineWidth -= characterRunLength;
+						forceInitialIndent = false; // initial indent done
+					}
+					else {
+						// just collapse spaces, but adjust for any indenting that may result from preserving line delimiters
+						if (whitespaceStart == 0 && XMLFormattingConstraints.IGNOREANDTRIM.equals(whitespaceMode)) {
+							// if ignore, trim
+							DeleteEdit deleteTrailing = new DeleteEdit(startOffset, whitespaceRun.length());
+							textEdit.addChild(deleteTrailing);
+						}
+						else if(XMLFormattingConstraints.REPLACE.equals(whitespaceMode))
+							availableLineWidth = replaceSpaces(textEdit, startOffset, availableLineWidth, whitespaceRun);
+						else
+							availableLineWidth = collapseAndIndent(textEdit, startOffset, availableLineWidth, indentLevel, whitespaceRun, currentRegion);
+					}
+
+					fullTextOffset += characterRunLength;
+				}
+				else {
+					// handle trailing whitespace
+					int whitespaceOffset = currentRegion.getStartOffset() + whitespaceStart;
+					if (XMLFormattingConstraints.REPLACE.equals(whitespaceMode))
+						availableLineWidth = replaceSpaces(textEdit, whitespaceOffset, availableLineWidth, whitespaceRun);
+					else if (XMLFormattingConstraints.IGNOREANDTRIM.equals(whitespaceMode)) {
+						// always trim
+						DeleteEdit deleteTrailing = new DeleteEdit(whitespaceOffset, whitespaceRun.length());
+						textEdit.addChild(deleteTrailing);
+					}
+					else if(getFormattingPreferences().getClearAllBlankLines()) {
+						if (XMLFormattingConstraints.IGNORE.equals(whitespaceMode)) {
+							// if ignore, trim
+							DeleteEdit deleteTrailing = new DeleteEdit(whitespaceOffset, whitespaceRun.length());
+							textEdit.addChild(deleteTrailing);
+						}
+						else {
+							// if collapse, leave a space. but what if end up
+							// wanting to add indent? then need to delete space
+							// added and add indent instead
+							availableLineWidth = collapseSpaces(textEdit, whitespaceOffset, availableLineWidth, whitespaceRun);
+						}
+					}
+				}
+			}
+			else {
+				// gather word
+				String characterRun = getCharacterRun(fullTextArray, fullTextOffset, false);
+				int characterRunLength = characterRun.length();
+				if (characterRunLength > 0) {
+					// indent if word is too long or forcing initial
+					// indent
+					// [243091] - characterRunLength should only be subtracted once or text formatting wraps prematurely
+					// availableLineWidth = availableLineWidth - characterRunLength;
+					if ((XMLFormattingConstraints.IGNORE.equals(whitespaceMode) || XMLFormattingConstraints.IGNOREANDTRIM.equals(whitespaceMode)) && (forceInitialIndent || (availableLineWidth <= 0))) {
+						// indent if not already indented
+						availableLineWidth = indentIfNotAlreadyIndented(textEdit, currentRegion, indentLevel, currentRegion.getStartOffset(), whitespaceRun);
+						// remember to subtract word length
+						availableLineWidth -= characterRunLength;
+						forceInitialIndent = false; // initial indent done
+					}
+					else {
+						// just collapse spaces
+						availableLineWidth -= characterRunLength;
+					}
+
+					fullTextOffset += characterRunLength;
+				}
+			}
+		}
+		// update available line width
+		parentConstraints.setAvailableLineWidth(availableLineWidth);
+	}
+
+	private void formatWithinEndTag(TextEdit textEdit, XMLFormattingConstraints constraints, IStructuredDocumentRegion currentDocumentRegion, IStructuredDocumentRegion previousDocumentRegion) {
+		String indentStrategy = constraints.getIndentStrategy();
+		String whitespaceStrategy = constraints.getWhitespaceStrategy();
+		int availableLineWidth = constraints.getAvailableLineWidth();
+		ITextRegionList textRegions = currentDocumentRegion.getRegions();
+		int currentNumberOfRegions = currentDocumentRegion.getNumberOfRegions();
+		int currentTextRegionIndex = 1;
+
+		ITextRegion currentTextRegion = textRegions.get(currentTextRegionIndex);
+		String currentType = currentTextRegion.getType();
+		// tag name should always be the first text region
+		if (DOMRegionContext.XML_TAG_NAME.equals(currentType) && currentTextRegionIndex < currentNumberOfRegions - 1) {
+			ITextRegion nextTextRegion = textRegions.get(currentTextRegionIndex + 1);
+			// Bug 221279 - Some non well-formed documents will not contribute a next region
+			if (nextTextRegion != null && DOMRegionContext.XML_TAG_CLOSE.equals(nextTextRegion.getType())) {
+				// calculate available line width
+				int tagNameLineWidth = currentTextRegion.getTextLength() + 3;
+				availableLineWidth -= tagNameLineWidth;
+
+				if (XMLFormattingConstraints.INLINE.equals(indentStrategy)) {
+					// if was inlining, need to check if out of available line
+					// width - Whitespace may have been corrected in the text content
+					if (availableLineWidth < 0 && XMLFormattingConstraints.IGNORE.equals(whitespaceStrategy)) {
+						// need to deindent if possible
+						int lineWidth = indentIfPossible(textEdit, constraints, currentDocumentRegion, previousDocumentRegion, whitespaceStrategy, indentStrategy, false);
+						// update available line width
+						if (lineWidth > 0)
+							availableLineWidth = lineWidth - tagNameLineWidth;
+					}
+					else {
+						// no need to indent
+						// just make sure to delete previous whitespace if
+						// needed
+						if (previousDocumentRegion != null) {
+							if (DOMRegionContext.XML_CONTENT.equals(previousDocumentRegion.getType())) {
+								String previousDocumentRegionText = previousDocumentRegion.getFullText();
+								if (previousDocumentRegionText.trim().length() == 0) {
+									availableLineWidth = collapseSpaces(textEdit, previousDocumentRegion.getStartOffset(), availableLineWidth, previousDocumentRegionText);
+								}
+							}
+						}
+					}
+				}
+				// delete any trail spaces after tag name
+				if (currentTextRegion.getTextLength() < currentTextRegion.getLength()) {
+					deleteTrailingSpaces(textEdit, currentTextRegion, currentDocumentRegion);
+				}
+			}
+		}
+		else {
+			// end tag has unexpected stuff, so just leave it alone
+		}
+		constraints.setAvailableLineWidth(availableLineWidth);
+	}
+
+	/**
+	 * Formats the contents within a tag like tag name and attributes
+	 * 
+	 * @param textEdit
+	 * @param currentDocumentRegion
+	 * @param textRegions
+	 *            contains at least 3 regions
+	 * @return true if tag was ended, false otherwise
+	 */
+	private boolean formatWithinTag(TextEdit textEdit, XMLFormattingConstraints constraints, IStructuredDocumentRegion currentDocumentRegion, IStructuredDocumentRegion previousDocumentRegion) {
+		int availableLineWidth = constraints.getAvailableLineWidth();
+		String indentStrategy = constraints.getIndentStrategy();
+		String whitespaceStrategy = constraints.getWhitespaceStrategy();
+		int indentLevel = constraints.getIndentLevel();
+		ITextRegionList textRegions = currentDocumentRegion.getRegions();
+		int currentTextRegionIndex = 1;
+
+		ITextRegion currentTextRegion = textRegions.get(currentTextRegionIndex);
+		String currentType = currentTextRegion.getType();
+		// tag name should always be the first text region
+		if (DOMRegionContext.XML_TAG_NAME.equals(currentType)) {
+			ITextRegion nextTextRegion = textRegions.get(currentTextRegionIndex + 1);
+			String nextType = (nextTextRegion != null) ? nextTextRegion.getType() : null;
+			if (DOMRegionContext.XML_TAG_CLOSE.equals(nextType)) {
+				// already at tag close
+				formatStartTagWithNoAttr(textEdit, constraints, currentDocumentRegion, previousDocumentRegion, availableLineWidth, indentStrategy, whitespaceStrategy, currentTextRegion);
+				return false;
+			}
+			else if (DOMRegionContext.XML_EMPTY_TAG_CLOSE.equals(nextType)) {
+				// already at empty tag close
+				formatEmptyStartTagWithNoAttr(textEdit, constraints, currentDocumentRegion, previousDocumentRegion, availableLineWidth, indentStrategy, whitespaceStrategy, currentTextRegion);
+				return true;
+			}
+			else {
+				availableLineWidth -= (currentTextRegion.getTextLength() + 2);
+				boolean alignFinalBracket = getFormattingPreferences().getAlignFinalBracket();
+				boolean oneSpaceInTagName = getFormattingPreferences().getSpaceBeforeEmptyCloseTag();
+				boolean indentMultipleAttribute = getFormattingPreferences().getIndentMultipleAttributes();
+				// indicates if tag spanned more than one line
+				boolean spanMoreThan1Line = false;
+				// indicates if all attributes should be indented
+				boolean indentAllAttributes = false;
+				if (indentMultipleAttribute) {
+					int attributesCount = 0;
+					int i = 2;
+					while (i < textRegions.size() && attributesCount < 2) {
+						if (DOMRegionContext.XML_TAG_ATTRIBUTE_NAME.equals(textRegions.get(i).getType()))
+							++attributesCount;
+					}
+					indentAllAttributes = (attributesCount > 1);
+				}
+
+				while ((currentTextRegionIndex + 1) < textRegions.size()) {
+					nextTextRegion = textRegions.get(currentTextRegionIndex + 1);
+					nextType = nextTextRegion.getType();
+					if (DOMRegionContext.XML_TAG_ATTRIBUTE_NAME.equals(nextType)) {
+						boolean indentAttribute = indentAllAttributes;
+						if (!indentAttribute)
+							indentAttribute = shouldIndentBeforeAttribute(constraints, textRegions, availableLineWidth, currentTextRegionIndex, currentTextRegion, nextTextRegion);
+						if (indentAttribute) {
+							availableLineWidth = indentIfNotAlreadyIndented(textEdit, indentLevel + 1, currentDocumentRegion, currentTextRegion);
+							spanMoreThan1Line = true;
+						}
+						else {
+							// otherwise, insertSpaceAndCollapse
+							insertSpaceAndCollapse(textEdit, currentDocumentRegion, availableLineWidth, currentTextRegion);
+							// update available line width
+							availableLineWidth -= (currentTextRegion.getTextLength() + 1);
+						}
+					}
+					else if (DOMRegionContext.XML_TAG_CLOSE.equals(nextType)) {
+						// if need to align bracket on next line, indent
+						if (alignFinalBracket && spanMoreThan1Line) {
+							availableLineWidth = indentIfNotAlreadyIndented(textEdit, indentLevel, currentDocumentRegion, currentTextRegion);
+							--availableLineWidth; // for tag close itself
+						}
+						else {
+							// otherwise, just delete space before tag close
+							if (currentTextRegion.getTextLength() < currentTextRegion.getLength()) {
+								deleteTrailingSpaces(textEdit, currentTextRegion, currentDocumentRegion);
+								availableLineWidth -= (currentTextRegion.getTextLength() + 1);
+							}
+						}
+						// update line width
+						constraints.setAvailableLineWidth(availableLineWidth);
+						return false;
+					}
+					else if (DOMRegionContext.XML_EMPTY_TAG_CLOSE.equals(nextType)) {
+						int textLength = currentTextRegion.getTextLength();
+						int regionLength = currentTextRegion.getLength();
+
+						boolean thereAreSpaces = textLength < regionLength;
+						if (!oneSpaceInTagName && thereAreSpaces) {
+							// delete any trail spaces after tag name
+							deleteTrailingSpaces(textEdit, currentTextRegion, currentDocumentRegion);
+							availableLineWidth -= (currentTextRegion.getTextLength() + 2);
+						}
+						// insert a space and collapse ONLY IF it's specified
+						else if (oneSpaceInTagName) {
+							insertSpaceAndCollapse(textEdit, currentDocumentRegion, availableLineWidth, currentTextRegion);
+							availableLineWidth -= (currentTextRegion.getTextLength() + 3);
+						}
+						// update line width
+						constraints.setAvailableLineWidth(availableLineWidth);
+						return true;
+					}
+					else {
+						if (DOMRegionContext.XML_TAG_ATTRIBUTE_NAME.equals(currentType) && DOMRegionContext.XML_TAG_ATTRIBUTE_EQUALS.equals(nextType)) {
+							if (currentTextRegion.getTextLength() < currentTextRegion.getLength()) {
+								deleteTrailingSpaces(textEdit, currentTextRegion, currentDocumentRegion);
+							}
+							// update available width
+							availableLineWidth -= currentTextRegion.getTextLength();
+						}
+						else if (DOMRegionContext.XML_TAG_ATTRIBUTE_EQUALS.equals(currentType) && DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE.equals(nextType)) {
+							if (currentTextRegion.getTextLength() < currentTextRegion.getLength()) {
+								deleteTrailingSpaces(textEdit, currentTextRegion, currentDocumentRegion);
+							}
+							// update available width
+							availableLineWidth -= currentTextRegion.getTextLength();
+						}
+						else {
+							// otherwise, insertSpaceAndCollapse
+							insertSpaceAndCollapse(textEdit, currentDocumentRegion, availableLineWidth, currentTextRegion);
+							// update available line width
+							availableLineWidth -= (currentTextRegion.getTextLength() + 1);
+						}
+					}
+					currentTextRegion = nextTextRegion;
+					currentType = nextType;
+					++currentTextRegionIndex;
+				}
+			}
+		}
+		// update line width
+		constraints.setAvailableLineWidth(availableLineWidth);
+		return false;
+	}
+	
+	/**
+	 * Format an XML comment structured document region.
+	 */
+	private void formatComment(TextEdit textEdit, Position formatRange, XMLFormattingConstraints parentConstraints, DOMRegion currentDOMRegion, IStructuredDocumentRegion previousRegion) {
+		IStructuredDocumentRegion currentRegion = currentDOMRegion.documentRegion;
+		int lineWidth = parentConstraints.getAvailableLineWidth() - currentRegion.getFullText().length();
+		// Don't format if we're not exceeding the available line width, or if the whitespace
+		// strategy is to preserve whitespace - But update line width.
+		if(currentRegion == null ||	XMLFormattingConstraints.PRESERVE.equals(parentConstraints.getWhitespaceStrategy()) || !fPreferences.getFormatCommentText()) {
+			parentConstraints.setAvailableLineWidth(lineWidth);
+			return;
+		}
+
+		Iterator it = currentRegion.getRegions().iterator();
+		ITextRegion previous = null;
+		if (previousRegion == null)
+			previousRegion = currentRegion.getPrevious();
+		// Iterate over each text region of the comment
+		Node parent = currentDOMRegion.domNode.getParentNode();
+		while(it.hasNext()) {
+			ITextRegion text = (ITextRegion) it.next();
+			String type = text.getType();
+			if (type == DOMRegionContext.XML_COMMENT_OPEN) {
+				int indentLevel = (parent != null && parent.getNodeType() == Node.DOCUMENT_NODE) ? 0 : 1;
+				int width = formatCommentStart(textEdit, parentConstraints, indentLevel, currentRegion, previousRegion, text);
+				parentConstraints.setAvailableLineWidth(width);
+			}
+			else if (type == DOMRegionContext.XML_COMMENT_TEXT) {
+				int indentLevel = (parent != null && parent.getNodeType() == Node.DOCUMENT_NODE) ? -1 : parentConstraints.getIndentLevel();
+				formatCommentContent(textEdit, parentConstraints, indentLevel, currentRegion, previous, text);
+			}
+			previous = text;
+		}
+	}
+
+	private void formatCommentContent(TextEdit textEdit, XMLFormattingConstraints parentConstraints, int indentLevel, IStructuredDocumentRegion currentRegion, ITextRegion previous, ITextRegion region) {
+		int lineWidth = parentConstraints.getAvailableLineWidth() - currentRegion.getFullText(previous).length();
+		// If there's more text than line width available, format
+		String text = currentRegion.getFullText(region);
+		compressContent(textEdit, currentRegion, currentRegion.getStartOffset(region), indentLevel + 1, lineWidth, text);
+	}
+
+	private void compressContent(TextEdit textEdit, IStructuredDocumentRegion region, int startOffset, int indentLevel, int lineWidth, String text) {
+		int length = text.length();
+		int start = 0, end = 0;
+		char c = 0;
+		int resultLength = 0;
+		boolean joinLines = fPreferences.getJoinCommentLines();
+		boolean onOwnLine = false;
+
+		String indent = getIndentString(indentLevel + 1);
+
+		for (int i = 0; i < length; i++) {
+			c = text.charAt(i);
+			// Compress whitespace unless its a line delimiter and formatting does not permit joining lines
+			if (Character.isWhitespace(c)) {
+				if ((c != '\r' && c!= '\n') || joinLines) {
+					// Just came off of a word
+					if (start == end) {
+						start = end = i;
+					}
+					end++;
+					resultLength++;
+				}
+				else {
+					// correct the indent of this line
+					lineWidth = fPreferences.getMaxLineWidth();
+					resultLength = 0;
+					onOwnLine = true;
+
+					// Compress any whitespace before the line delimiter
+					if (start != end) {
+						int replaceLength = end - start;
+						textEdit.addChild(new ReplaceEdit(start + startOffset, replaceLength, EMPTY));
+						start = end = i;
+					}
+				}
+			}
+			else {
+				// Transitioned to a new word
+				if (start != end) {
+					int replaceLength = end - start;
+					if (onOwnLine) {
+						// If content is on its own line, replace leading whitespace with proper indent
+						textEdit.addChild(new ReplaceEdit(start + startOffset, replaceLength, indent));
+						resultLength -= (replaceLength - indent.length());
+						onOwnLine = false;
+					}
+					else if (!(replaceLength == 1 && text.charAt(start) == ' ')) {
+						textEdit.addChild(new ReplaceEdit(start + startOffset, replaceLength, SPACE));
+						resultLength -= (replaceLength - 1);
+					}
+					start = end = i;
+					// Make sure the word starts on a new line
+					if (resultLength > lineWidth) {
+						lineWidth = fPreferences.getMaxLineWidth();
+						resultLength = 0;
+						textEdit.addChild(new InsertEdit(start + startOffset, getLineDelimiter(region) + indent));
+					}
+				}
+				// Word is immediately after line delimiters, indent appropriately
+				if (onOwnLine) {
+					textEdit.addChild(new InsertEdit(i + startOffset, indent));
+					onOwnLine = false;
+				}
+				resultLength++;
+			}
+		}
+
+		// Clean up any dangling whitespace
+		int replaceLength = end - start;
+		indent = getIndentString(indentLevel);
+		if (replaceLength == 0) { // No trailing whitespace
+			textEdit.addChild(new InsertEdit(length + startOffset, (onOwnLine) ? indent : SPACE));
+		}
+		else {
+			String whitespace = text.substring(start);
+			String replacement = (onOwnLine) ? indent : SPACE;
+			if (!whitespace.equals(replacement)) {
+				textEdit.addChild(new ReplaceEdit(start + startOffset, replaceLength, replacement));
+			}
+		}
+	}
+
+	private int formatCommentStart(TextEdit textEdit, XMLFormattingConstraints parentConstraints, int indentLevel, IStructuredDocumentRegion currentRegion, IStructuredDocumentRegion previousRegion, ITextRegion region) {
+		int lineWidth = parentConstraints.getAvailableLineWidth();
+		if (previousRegion!=null&&(DOMRegionContext.XML_CONTENT.equals(previousRegion.getType()))) {
+			String previousText = previousRegion.getFullText();
+			String trailingWhitespace = getTrailingWhitespace(previousText);
+			String delimiters = extractLineDelimiters(trailingWhitespace, previousRegion);
+			if (delimiters != null && delimiters.length() > 0){// && previousText.length() == trailingWhitespace.length()) {
+				// Format the comment if it's on a new line
+				int offset = previousRegion.getEnd() - trailingWhitespace.length();
+				lineWidth = indentIfNotAlreadyIndented(textEdit, currentRegion, parentConstraints.getIndentLevel() + indentLevel, offset, trailingWhitespace);
+			}
+		}
+		return lineWidth;
+	}
+
+	/**
+	 * Returns either a String of whitespace or characters depending on
+	 * forWhitespace
+	 * 
+	 * @param fullTextArray
+	 *            the text array to look in
+	 * @param textOffset
+	 *            the start offset to start searching
+	 * @param forWhitespace
+	 *            true if should return whitespaces, false otherwise
+	 * @return a String of either all whitespace or all characters. Never
+	 *         returns null
+	 */
+	private String getCharacterRun(char[] fullTextArray, int textOffset, boolean forWhitespace) {
+		StringBuffer characterRun = new StringBuffer();
+		boolean nonCharacterFound = false;
+		while (textOffset < fullTextArray.length && !nonCharacterFound) {
+			char c = fullTextArray[textOffset];
+			boolean isWhitespace = Character.isWhitespace(c);
+			if ((forWhitespace && isWhitespace) || (!forWhitespace && !isWhitespace))
+				characterRun.append(c);
+			else
+				nonCharacterFound = true;
+			++textOffset;
+		}
+		return characterRun.toString();
+	}
+	
+	private String getTrailingWhitespace(String text) {
+		StringBuffer whitespaceRun = new StringBuffer();
+		int index = text.length() - 1;
+		while(index >= 0) {
+			char c = text.charAt(index--);
+			if (Character.isWhitespace(c))
+				whitespaceRun.insert(0, c);
+			else
+				break;
+		}
+		return whitespaceRun.toString();
+	}
+
+	private String getIndentString(int indentLevel) {
+		StringBuffer indentString = new StringBuffer();
+		String indent = getFormattingPreferences().getOneIndent();
+		for (int i = 0; i < indentLevel; ++i) {
+			indentString.append(indent);
+		}
+		return indentString.toString();
+	}
+
+	protected XMLFormattingPreferences getFormattingPreferences() {
+		if (fPreferences == null)
+			fPreferences = new XMLFormattingPreferences();
+		return fPreferences;
+	}
+
+	protected void setFormattingPreferences(XMLFormattingPreferences preferences) {
+		fPreferences = preferences;
+	}
+
+	/**
+	 * Indent if whitespaceRun does not already contain an indent
+	 * 
+	 * @param textEdit
+	 * @param indentLevel
+	 * @param indentStartOffset
+	 * @param maxAvailableLineWidth
+	 * @param whitespaceRun
+	 * @return new available line width up to where indented
+	 */
+	private int indentIfNotAlreadyIndented(TextEdit textEdit, IStructuredDocumentRegion currentRegion, int indentLevel, int indentStartOffset, String whitespaceRun) {
+		int maxAvailableLineWidth = getFormattingPreferences().getMaxLineWidth();
+
+		int availableLineWidth;
+		String indentString = getIndentString(indentLevel);
+		String lineDelimiter = getLineDelimiter(currentRegion);
+		String newLineAndIndent = lineDelimiter + indentString;
+		
+		TextEdit indentation = null;
+		
+		// if not already correctly indented
+		if (!newLineAndIndent.equals(whitespaceRun)) {
+			if (getFormattingPreferences().getClearAllBlankLines()) {
+				if (whitespaceRun != null) {
+					// replace existing whitespace run
+					indentation = new ReplaceEdit(indentStartOffset, whitespaceRun.length(), newLineAndIndent);
+				}
+				else {
+					// just insert correct indent
+					indentation = new InsertEdit(indentStartOffset, newLineAndIndent);
+				}
+			}
+			// Keep the empty lines
+			else {
+				// just insert correct indent
+				if(whitespaceRun == null)
+					indentation = new InsertEdit(indentStartOffset, newLineAndIndent);
+				// Need to preserve the number of empty lines, but still indent on the current line properly
+				else {
+					String existingDelimiters = extractLineDelimiters(whitespaceRun, currentRegion);
+					if(existingDelimiters != null && existingDelimiters.length() > 0) {
+						String formatted = existingDelimiters + indentString;
+						// Don't perform a replace if the formatted string is the same as the existing whitespaceRun
+						if(!formatted.equals(whitespaceRun))
+							indentation = new ReplaceEdit(indentStartOffset, whitespaceRun.length(), formatted);
+					}
+					// No blank lines to preserve - correct the indent
+					else
+						indentation = new ReplaceEdit(indentStartOffset, whitespaceRun.length(), newLineAndIndent);
+				}
+			}
+		}
+		
+		if(indentation != null)
+			textEdit.addChild(indentation);
+		// update line width
+		availableLineWidth = maxAvailableLineWidth - indentString.length();
+		return availableLineWidth;
+	}
+
+	private int indentIfNotAlreadyIndented(TextEdit textEdit, int indentLevel, IStructuredDocumentRegion currentDocumentRegion, ITextRegion currentTextRegion) {
+		// indent if not already indented
+		int textLength = currentTextRegion.getTextLength();
+		int regionLength = currentTextRegion.getLength();
+		int indentStartOffset = currentDocumentRegion.getTextEndOffset(currentTextRegion);
+		String fullText = currentDocumentRegion.getFullText(currentTextRegion);
+		String whitespaceRun = fullText.substring(textLength, regionLength);
+
+		// update line width
+		int availableLineWidth = indentIfNotAlreadyIndented(textEdit, currentDocumentRegion, indentLevel, indentStartOffset, whitespaceRun);
+		return availableLineWidth;
+	}
+
+	private int indentIfPossible(TextEdit textEdit, XMLFormattingConstraints thisConstraints, IStructuredDocumentRegion currentDocumentRegion, IStructuredDocumentRegion previousDocumentRegion, String whitespaceStrategy, String indentStrategy, boolean addIndent) {
+		int availableLineWidth = -1;
+		// if there is no previous document region, there is no need to indent
+		// because we're at beginning of document
+		if (previousDocumentRegion == null)
+			return availableLineWidth;
+
+		// only indent if ignoring whitespace or if collapsing and
+		// there was a whitespace character before this region
+		boolean canIndent = false;
+		String previousRegionFullText = null;
+		String previousRegionType = null;
+
+		if ((XMLFormattingConstraints.IGNORE.equals(whitespaceStrategy)) || XMLFormattingConstraints.IGNOREANDTRIM.equals(whitespaceStrategy)) {
+			// if ignoring, need to check if previous region was cdata
+			previousRegionType = previousDocumentRegion.getType();
+			if (DOMRegionContext.XML_CDATA_TEXT.equals(previousRegionType))
+				canIndent = false;
+			else
+				canIndent = true;
+		}
+		else if (XMLFormattingConstraints.COLLAPSE.equals(whitespaceStrategy)) {
+			// if collapsing, need to check if previous region ended in a
+			// whitespace
+			previousRegionType = previousDocumentRegion.getType();
+			if (DOMRegionContext.XML_CONTENT.equals(previousRegionType)) {
+				previousRegionFullText = previousDocumentRegion.getFullText();
+				int length = previousRegionFullText.length();
+				if (length > 1)
+					canIndent = Character.isWhitespace(previousRegionFullText.charAt(length - 1));
+			}
+		}
+		if (canIndent) {
+			int indentStartOffset = currentDocumentRegion.getStartOffset();
+			String whitespaceRun = null;
+
+			// get previous region type if it was not previously retrieved
+			if (previousRegionType == null)
+				previousRegionType = previousDocumentRegion.getType();
+
+			// get previous region's text if it was not previously retrieved
+			if (previousRegionFullText == null && DOMRegionContext.XML_CONTENT.equals(previousRegionType))
+				previousRegionFullText = previousDocumentRegion.getFullText();
+
+			// if previous region was only whitespace, this may
+			// already be indented, so need to make sure
+			if ((previousRegionFullText != null) && (previousRegionFullText.trim().length() == 0)) {
+				indentStartOffset = previousDocumentRegion.getStartOffset();
+				whitespaceRun = previousRegionFullText;
+			}
+			if ((previousRegionFullText != null) && (whitespaceRun == null) && !getFormattingPreferences().getClearAllBlankLines()) {
+				whitespaceRun = getTrailingWhitespace(previousRegionFullText);
+				indentStartOffset = previousDocumentRegion.getEndOffset() - whitespaceRun.length();
+			}
+
+			int indentLevel = thisConstraints.getIndentLevel();
+			if (addIndent && XMLFormattingConstraints.INDENT.equals(indentStrategy)) {
+				++indentLevel;
+				thisConstraints.setIndentLevel(indentLevel);
+			}
+
+			// indent if not already indented
+			availableLineWidth = indentIfNotAlreadyIndented(textEdit, currentDocumentRegion, indentLevel, indentStartOffset, whitespaceRun);
+		}
+		return availableLineWidth;
+	}
+
+	/**
+	 * Allow exactly one whitespace in currentTextRegion. If there are more,
+	 * collapse to one. If there are none, insert one.
+	 * 
+	 * @param textEdit
+	 * @param currentDocumentRegion
+	 * @param availableLineWidth
+	 * @param currentTextRegion
+	 */
+	private void insertSpaceAndCollapse(TextEdit textEdit, IStructuredDocumentRegion currentDocumentRegion, int availableLineWidth, ITextRegion currentTextRegion) {
+		int textLength = currentTextRegion.getTextLength();
+		int regionLength = currentTextRegion.getLength();
+		boolean thereAreSpaces = textLength < regionLength;
+		int spacesStartOffset = currentDocumentRegion.getStartOffset(currentTextRegion) + textLength;
+
+		if (thereAreSpaces) {
+			String fullTagName = currentDocumentRegion.getFullText(currentTextRegion);
+			String whitespaceRun = fullTagName.substring(textLength, regionLength);
+			collapseSpaces(textEdit, spacesStartOffset, availableLineWidth, whitespaceRun);
+		}
+		else {
+			// insert a space
+			InsertEdit insertEdit = new InsertEdit(spacesStartOffset, SPACE);
+			textEdit.addChild(insertEdit);
+		}
+	}
+
+	private boolean shouldIndentBeforeAttribute(XMLFormattingConstraints constraints, ITextRegionList textRegions, int availableLineWidth, int currentTextRegionIndex, ITextRegion currentTextRegion, ITextRegion nextTextRegion) {
+		boolean indentAttribute = false;
+
+		// look ahead to see if going to hit max line width
+		// something attrName
+		int currentWidth = currentTextRegion.getTextLength() + nextTextRegion.getTextLength() + 1;
+		if (currentWidth > availableLineWidth)
+			indentAttribute = true;
+		else {
+			if ((currentTextRegionIndex + 2) < textRegions.size()) {
+				// still okay, so try next region
+				// something attrName=
+				ITextRegion textRegion = textRegions.get(currentTextRegionIndex + 2);
+				if (DOMRegionContext.XML_TAG_ATTRIBUTE_EQUALS.equals(textRegion.getType())) {
+					++currentWidth;
+					if (currentWidth > availableLineWidth)
+						indentAttribute = true;
+					else {
+						if ((currentTextRegionIndex + 3) < textRegions.size()) {
+							// still okay, so try next region
+							// something attrName=attrValue
+							textRegion = textRegions.get(currentTextRegionIndex + 3);
+							if (DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE.equals(textRegion.getType())) {
+								currentWidth = +textRegion.getTextLength();
+								if (currentWidth > availableLineWidth)
+									indentAttribute = true;
+							}
+						}
+					}
+				}
+			}
+		}
+		return indentAttribute;
+	}
+
+	/**
+	 * Given the provided information (parentConstraints & currentDOMRegion),
+	 * update the formatting constraints (for this & child)
+	 * 
+	 * @param parentConstraints
+	 *            can be null
+	 * @param thisConstraints
+	 *            can be null
+	 * @param childConstraints
+	 *            can be null
+	 * @param currentDOMRegion
+	 *            cannot be null
+	 */
+	protected void updateFormattingConstraints(XMLFormattingConstraints parentConstraints, XMLFormattingConstraints thisConstraints, XMLFormattingConstraints childConstraints, DOMRegion currentDOMRegion) {
+		IStructuredDocumentRegion currentRegion = currentDOMRegion.documentRegion;
+		IDOMNode currentNode = currentDOMRegion.domNode;
+
+		// default to whatever parent's constraint said to do
+		if (parentConstraints != null) {
+			if (thisConstraints != null) {
+				thisConstraints.copyConstraints(parentConstraints);
+			}
+			if (childConstraints != null) {
+				childConstraints.copyConstraints(parentConstraints);
+				// if whitespace strategy was only a hint, null it out so
+				// defaults are taken instead
+				if (parentConstraints.isWhitespaceStrategyAHint())
+					childConstraints.setWhitespaceStrategy(null);
+			}
+		}
+
+		// set up constraints for direct children of document root
+		Node parentNode = currentNode.getParentNode();
+		if (parentNode != null && parentNode.getNodeType() == Node.DOCUMENT_NODE) {
+			if (thisConstraints != null) {
+				thisConstraints.setWhitespaceStrategy(XMLFormattingConstraints.IGNORE);
+				thisConstraints.setIndentStrategy(XMLFormattingConstraints.NEW_LINE);
+				thisConstraints.setIndentLevel(0);
+			}
+			if (childConstraints != null) {
+				childConstraints.setWhitespaceStrategy(null);
+				childConstraints.setIndentStrategy(null);
+				childConstraints.setIndentLevel(0);
+			}
+		}
+
+		// other conditions to check when setting up child constraints
+		if (childConstraints != null) {
+			XMLFormattingPreferences preferences = getFormattingPreferences();
+
+			// if we're at document root, child tags should always just start
+			// on a new line and have an indent level of 0
+			if (currentNode.getNodeType() == Node.DOCUMENT_NODE) {
+				childConstraints.setWhitespaceStrategy(XMLFormattingConstraints.IGNORE);
+				childConstraints.setIndentStrategy(XMLFormattingConstraints.NEW_LINE);
+				childConstraints.setIndentLevel(0);
+			}
+			else {
+				// BUG108074 & BUG84688 - preserve whitespace in xsl:text &
+				// xsl:attribute
+				String nodeNamespaceURI = currentNode.getNamespaceURI();
+				if (XSL_NAMESPACE.equals(nodeNamespaceURI)) {
+					String nodeName = ((Element) currentNode).getLocalName();
+					if (XSL_ATTRIBUTE.equals(nodeName) || XSL_TEXT.equals(nodeName)) {
+						childConstraints.setWhitespaceStrategy(XMLFormattingConstraints.PRESERVE);
+					}
+				}
+				else {
+					// search within current tag for xml:space attribute
+					ITextRegionList textRegions = currentRegion.getRegions();
+					int i = 0;
+					boolean xmlSpaceFound = false;
+					boolean preserveFound = false;
+					while (i < textRegions.size() && !xmlSpaceFound) {
+						ITextRegion textRegion = textRegions.get(i);
+						if (DOMRegionContext.XML_TAG_ATTRIBUTE_NAME.equals(textRegion.getType())) {
+							String regionText = currentRegion.getText(textRegion);
+							if (XML_SPACE.equals(regionText)) {
+								if ((i + 1) < textRegions.size()) {
+									++i;
+									textRegion = textRegions.get(i);
+									if (DOMRegionContext.XML_TAG_ATTRIBUTE_EQUALS.equals(textRegion.getType()) && ((i + 1) < textRegions.size())) {
+										++i;
+										textRegion = textRegions.get(i);
+										regionText = currentRegion.getText(textRegion);
+										if (PRESERVE.equals(regionText) || PRESERVE_QUOTED.equals(regionText)) {
+											preserveFound = true;
+										}
+									}
+								}
+								xmlSpaceFound = true;
+							}
+						}
+						++i;
+					}
+					if (xmlSpaceFound) {
+						if (preserveFound) {
+							// preserve was found so set the strategy
+							childConstraints.setWhitespaceStrategy(XMLFormattingConstraints.PRESERVE);
+						}
+						else {
+							// xml:space was found but it was not collapse, so
+							// use default whitespace strategy
+							childConstraints.setWhitespaceStrategy(XMLFormattingConstraints.DEFAULT);
+						}
+					}
+					else {
+						// how to hande nodes that have nonwhitespace text
+						// content
+						NodeList nodeList = currentNode.getChildNodes();
+						int length = nodeList.getLength();
+						int index = 0;
+						boolean textNodeFound = false;
+						// BUG214516 - If the parent constraint is to preserve whitespace, child constraints should
+						// still reflect the parent constraints
+						while (index < length && !textNodeFound && parentConstraints != null && !XMLFormattingConstraints.PRESERVE.equals(parentConstraints.getWhitespaceStrategy())) {
+							Node childNode = nodeList.item(index);
+							if (childNode.getNodeType() == Node.TEXT_NODE) {
+								textNodeFound = !((IDOMText) childNode).isElementContentWhitespace();
+							}
+							++index;
+						}
+						if (textNodeFound) {
+							if (length > 1) {
+								// more in here than just text, so consider
+								// this mixed content
+								childConstraints.setWhitespaceStrategy(preferences.getMixedWhitespaceStrategy());
+								childConstraints.setIndentStrategy(preferences.getMixedIndentStrategy());
+							}
+							else {
+								// there's only text
+								childConstraints.setWhitespaceStrategy(preferences.getTextWhitespaceStrategy());
+								childConstraints.setIndentStrategy(preferences.getTextIndentStrategy());
+							}
+							childConstraints.setIsWhitespaceStrategyAHint(true);
+							childConstraints.setIsIndentStrategyAHint(true);
+						}
+
+						// try referring to content model for information on
+						// whitespace & indent strategy
+						ModelQueryAdapter adapter = (ModelQueryAdapter) ((IDOMDocument) currentNode.getOwnerDocument()).getAdapterFor(ModelQueryAdapter.class);
+						CMElementDeclaration elementDeclaration = (CMElementDeclaration) adapter.getModelQuery().getCMNode(currentNode);
+						if (elementDeclaration != null) {
+							// follow whitespace strategy preference for
+							// pcdata content
+							int contentType = elementDeclaration.getContentType();
+							
+							String facetValue = null;
+							if(elementDeclaration.getDataType() != null)
+								facetValue = (String) elementDeclaration.getDataType().getProperty(PROPERTY_WHITESPACE_FACET);
+							if(facetValue != null) {
+								if(PRESERVE.equals(facetValue))
+									childConstraints.setWhitespaceStrategy(XMLFormattingConstraints.PRESERVE);
+								// For XSD types, "collapse" corresponds to the IGNOREANDTRIM strategy
+								else if(COLLAPSE.equals(facetValue))
+									childConstraints.setWhitespaceStrategy(XMLFormattingConstraints.IGNOREANDTRIM);
+								else if(REPLACE.equals(facetValue))
+									childConstraints.setWhitespaceStrategy(XMLFormattingConstraints.REPLACE);
+							}
+							else if (contentType == CMElementDeclaration.PCDATA && parentConstraints != null && !XMLFormattingConstraints.PRESERVE.equals(parentConstraints.getWhitespaceStrategy())) {
+								childConstraints.setWhitespaceStrategy(preferences.getPCDataWhitespaceStrategy());
+							}
+							else if (contentType == CMElementDeclaration.ELEMENT && parentConstraints != null && !XMLFormattingConstraints.PRESERVE.equals(parentConstraints.getWhitespaceStrategy())) {
+								childConstraints.setWhitespaceStrategy(XMLFormattingConstraints.IGNORE);
+								childConstraints.setIndentStrategy(XMLFormattingConstraints.INDENT);
+								childConstraints.setIsWhitespaceStrategyAHint(true);
+								childConstraints.setIsIndentStrategyAHint(true);
+							}
+							else {
+								// look for xml:space in content model
+								CMNamedNodeMap cmAttributes = elementDeclaration.getAttributes();
+
+								// Not needed - we're looking for xml:space
+								//CMNamedNodeMapImpl allAttributes = new CMNamedNodeMapImpl(cmAttributes);
+								//List nodes = ModelQueryUtil.getModelQuery(currentNode.getOwnerDocument()).getAvailableContent((Element) currentNode, elementDeclaration, ModelQuery.INCLUDE_ATTRIBUTES);
+								//for (int k = 0; k < nodes.size(); k++) {
+								//	CMNode cmnode = (CMNode) nodes.get(k);
+								//	if (cmnode.getNodeType() == CMNode.ATTRIBUTE_DECLARATION) {
+								//		allAttributes.put(cmnode);
+								//	}
+								//}
+								//cmAttributes = allAttributes;
+
+								// Check implied values from the DTD way.
+								CMAttributeDeclaration attributeDeclaration = (CMAttributeDeclaration) cmAttributes.getNamedItem(XML_SPACE);
+								if (attributeDeclaration != null) {
+									// CMAttributeDeclaration found, check
+									// it
+									// out.
+
+									//BUG214516/196544 - Fixed NPE that was caused by an attr having
+									// a null attr type
+									String defaultValue = null;
+									CMDataType attrType = attributeDeclaration.getAttrType();
+									if (attrType != null) {
+										if ((attrType.getImpliedValueKind() != CMDataType.IMPLIED_VALUE_NONE) && attrType.getImpliedValue() != null)
+											defaultValue = attrType.getImpliedValue();
+										else if ((attrType.getEnumeratedValues() != null) && (attrType.getEnumeratedValues().length > 0)) {
+											defaultValue = attrType.getEnumeratedValues()[0];
+										}
+									}
+
+									// xml:space="preserve" means preserve
+									// space,
+									// everything else means back to
+									// default.
+									if (PRESERVE.equals(defaultValue))
+										childConstraints.setWhitespaceStrategy(XMLFormattingConstraints.PRESERVE);
+									else
+										childConstraints.setWhitespaceStrategy(XMLFormattingConstraints.DEFAULT);
+								}
+								// If the node has no attributes, inherit the parents whitespace strategy
+								else {
+									if (parentConstraints != null)
+										childConstraints.setWhitespaceStrategy(parentConstraints.getWhitespaceStrategy());
+									else
+										childConstraints.setWhitespaceStrategy(null);
+								}
+							}
+						}
+					}
+				}
+			}
+			// set default values according to preferences
+			if (childConstraints.getWhitespaceStrategy() == null) {
+				childConstraints.setWhitespaceStrategy(preferences.getElementWhitespaceStrategy());
+			}
+			if (childConstraints.getIndentStrategy() == null) {
+				childConstraints.setIndentStrategy(preferences.getElementIndentStrategy());
+			}
+		}
+	}
+
+	/**
+	 * Calculates the current available line width given fullText.
+	 * 
+	 * @param fullText
+	 * @param availableLineWidth
+	 * @param maxAvailableLineWidth
+	 * @return
+	 */
+	private int updateLineWidthWithLastLine(String fullText, int availableLineWidth) {
+		int maxAvailableLineWidth = getFormattingPreferences().getMaxLineWidth();
+		int lineWidth = availableLineWidth;
+		if (fullText != null) {
+			int textLength = fullText.length();
+			// update available line width
+			// find last newline
+			int lastLFOffset = fullText.lastIndexOf('\n');
+			int lastCROffset = fullText.lastIndexOf('\r');
+			// all text was on 1 line
+			if (lastLFOffset == -1 && lastCROffset == -1) {
+				// just subtract text length from current
+				// available line width
+				lineWidth -= fullText.length();
+			}
+			else {
+				// calculate available line width of last line
+				int lastNewLine = Math.max(lastLFOffset, lastCROffset);
+				lineWidth = maxAvailableLineWidth - (textLength - lastNewLine);
+			}
+		}
+		return lineWidth;
+	}
+
+	private String getLineDelimiter(IStructuredDocumentRegion currentRegion) {
+		IStructuredDocument doc = currentRegion.getParentDocument();
+		int line = doc.getLineOfOffset(currentRegion.getStartOffset());
+		String lineDelimiter = doc.getLineDelimiter();
+		try {
+			if (line > 0) {
+				lineDelimiter = doc.getLineDelimiter(line - 1);
+			}
+		}
+		catch (BadLocationException e) {
+			// log for now, unless we find reason not to
+			Logger.log(Logger.INFO, e.getMessage());
+		}
+		// BUG115716: if cannot get line delimiter from current line, just
+		// use default line delimiter
+		if (lineDelimiter == null)
+			lineDelimiter = doc.getLineDelimiter();
+		return lineDelimiter;
+	}
+	
+	private String extractLineDelimiters(String base, IStructuredDocumentRegion currentRegion) {
+		String lineDelimiter = getLineDelimiter(currentRegion);
+		StringBuffer sb = new StringBuffer();
+		for(int index = 0; index < base.length();) {
+			index = base.indexOf(lineDelimiter, index);
+			if(index++ >= 0)
+				sb.append(lineDelimiter);
+			else
+				break;
+		}
+		return sb.toString();
+	}
+
+	void setProgressMonitor(IProgressMonitor monitor) {
+		fProgressMonitor = monitor;
+	}
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/formatter/XMLFormatterFormatProcessor.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/formatter/XMLFormatterFormatProcessor.java
new file mode 100644
index 0000000..e02ee7e
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/formatter/XMLFormatterFormatProcessor.java
@@ -0,0 +1,146 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.formatter;
+
+import java.io.IOException;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.jface.text.DocumentRewriteSession;
+import org.eclipse.jface.text.DocumentRewriteSessionType;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentExtension4;
+import org.eclipse.text.edits.TextEdit;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.format.IStructuredFormatProcessor;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+import org.eclipse.wst.xml.core.internal.Logger;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.w3c.dom.Node;
+
+/**
+ * This is a wrapper for the new xml formatter so that it can be still
+ * considered an IStruturedFormatProcessor
+ */
+public class XMLFormatterFormatProcessor implements IStructuredFormatProcessor {
+	private DefaultXMLPartitionFormatter fFormatter = null;
+	private IProgressMonitor fProgressMonitor = null;
+
+	public void formatDocument(IDocument document, int start, int length) throws IOException, CoreException {
+		if (document instanceof IStructuredDocument) {
+			IStructuredModel model = StructuredModelManager.getModelManager().getModelForEdit((IStructuredDocument) document);
+			if (model != null) {
+				try {
+					formatModel(model, start, length);
+				}
+				finally {
+					model.releaseFromEdit();
+				}
+			}
+		}
+	}
+
+	public void formatFile(IFile file) throws IOException, CoreException {
+		if (file == null)
+			return;
+
+		IStructuredModel structuredModel = null;
+		// OutputStream outputStream = null;
+		try {
+			// setup structuredModel
+			// Note: We are getting model for edit. Will save model if model
+			// changed.
+			structuredModel = StructuredModelManager.getModelManager().getModelForEdit(file);
+
+			// format
+			formatModel(structuredModel);
+
+			// save model if needed
+			if (!structuredModel.isSharedForEdit() && structuredModel.isSaveNeeded())
+				structuredModel.save();
+		}
+		finally {
+			// ensureClosed(outputStream, null);
+			// release from model manager
+			if (structuredModel != null) {
+				structuredModel.releaseFromEdit();
+			}
+
+		}
+	}
+
+	public void formatModel(IStructuredModel structuredModel) {
+		int start = 0;
+		int length = structuredModel.getStructuredDocument().getLength();
+
+		formatModel(structuredModel, start, length);
+	}
+
+	public void formatModel(IStructuredModel structuredModel, int start, int length) {
+		if(fProgressMonitor != null)
+			fProgressMonitor.beginTask("", 2);
+		IStructuredDocument structuredDocument = structuredModel.getStructuredDocument();
+		DocumentRewriteSession activeRewriteSession = ((IDocumentExtension4) structuredDocument).getActiveRewriteSession();
+		boolean startedRewriteSession = false;
+		if (activeRewriteSession == null) {
+			activeRewriteSession = ((IDocumentExtension4) structuredDocument).startRewriteSession(DocumentRewriteSessionType.UNRESTRICTED);
+			startedRewriteSession = true;
+		}
+		getFormatter().setProgressMonitor(new NullProgressMonitor() {
+			public boolean isCanceled() {
+				return fProgressMonitor != null && fProgressMonitor.isCanceled();
+			}
+		});
+		TextEdit edit = getFormatter().format(structuredModel, start, length);
+		if(fProgressMonitor != null)
+			fProgressMonitor.worked(1);
+		
+		try {
+			structuredModel.aboutToChangeModel();
+			edit.apply(structuredDocument);
+			if(fProgressMonitor != null)
+				fProgressMonitor.worked(1);
+		}
+		catch (Exception e) {
+			Logger.log(Logger.WARNING_DEBUG, e.getMessage(), e);
+		}
+		finally {
+			if (startedRewriteSession && activeRewriteSession != null) {
+				((IDocumentExtension4) structuredDocument).stopRewriteSession(activeRewriteSession);
+			}
+			structuredModel.changedModel();
+			if(fProgressMonitor != null)
+				fProgressMonitor.done();
+		}
+	}
+
+	public void formatNode(Node node) {
+		if (node instanceof IDOMNode) {
+			IDOMNode domNode = (IDOMNode) node;
+			formatModel(domNode.getModel(), domNode.getStartOffset(), domNode.getLength());
+		}
+	}
+
+	public void setProgressMonitor(IProgressMonitor monitor) {
+		fProgressMonitor = monitor;
+	}
+
+	private DefaultXMLPartitionFormatter getFormatter() {
+		if (fFormatter == null) {
+			fFormatter = new DefaultXMLPartitionFormatter();
+		}
+		return fFormatter;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/formatter/XMLFormattingConstraints.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/formatter/XMLFormattingConstraints.java
new file mode 100644
index 0000000..fa2a53b
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/formatter/XMLFormattingConstraints.java
@@ -0,0 +1,94 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.formatter;
+
+
+public class XMLFormattingConstraints {
+	public final static String PRESERVE = "PRESERVE"; //$NON-NLS-1$
+	public final static String COLLAPSE = "COLLAPSE"; //$NON-NLS-1$
+	public final static String IGNORE = "IGNORE"; //$NON-NLS-1$
+	public final static String IGNOREANDTRIM = "IGNOREANDTRIM"; //$NON-NLS-1$
+	public final static String DEFAULT = "DEFAULT"; //$NON-NLS-1$
+	public final static String REPLACE = "REPLACE"; //$NON-NLS-1$
+	
+	public final static String INDENT = "INDENT"; //$NON-NLS-1$
+	public final static String NEW_LINE = "NEW_LINE"; //$NON-NLS-1$
+	public final static String INLINE = "INLINE"; //$NON-NLS-1$
+
+	private int fAvailableLineWidth = 0;
+	private int fIndentLevel = 0;
+	private String fIndentStrategy;
+	private String fWhitespaceStrategy;
+	private boolean fIsIndentStrategyAHint = false;
+	private boolean fIsWhitespaceStrategyAHint = false;
+
+	/**
+	 * Initializes the values in this formatting constraint with values from
+	 * constraints
+	 * 
+	 * @param constraints
+	 *            cannot be null
+	 */
+	public void copyConstraints(XMLFormattingConstraints constraints) {
+		setAvailableLineWidth(constraints.getAvailableLineWidth());
+		setIndentLevel(constraints.getIndentLevel());
+		setIndentStrategy(constraints.getIndentStrategy());
+		setWhitespaceStrategy(constraints.getWhitespaceStrategy());
+	}
+
+	public int getAvailableLineWidth() {
+		return fAvailableLineWidth;
+	}
+
+	public void setAvailableLineWidth(int lineWidth) {
+		fAvailableLineWidth = lineWidth;
+	}
+
+	public int getIndentLevel() {
+		return fIndentLevel;
+	}
+
+	public void setIndentLevel(int indentLevel) {
+		fIndentLevel = indentLevel;
+	}
+
+	public String getIndentStrategy() {
+		return fIndentStrategy;
+	}
+
+	public void setIndentStrategy(String indentStrategy) {
+		fIndentStrategy = indentStrategy;
+	}
+
+	public String getWhitespaceStrategy() {
+		return fWhitespaceStrategy;
+	}
+
+	public void setWhitespaceStrategy(String whitespaceStrategy) {
+		fWhitespaceStrategy = whitespaceStrategy;
+	}
+
+	public boolean isIndentStrategyAHint() {
+		return fIsIndentStrategyAHint;
+	}
+
+	public void setIsIndentStrategyAHint(boolean isIndentStrategyAHint) {
+		fIsIndentStrategyAHint = isIndentStrategyAHint;
+	}
+
+	public boolean isWhitespaceStrategyAHint() {
+		return fIsWhitespaceStrategyAHint;
+	}
+
+	public void setIsWhitespaceStrategyAHint(boolean isWhitespaceStrategyAHint) {
+		fIsWhitespaceStrategyAHint = isWhitespaceStrategyAHint;
+	}
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/formatter/XMLFormattingPreferences.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/formatter/XMLFormattingPreferences.java
new file mode 100644
index 0000000..61c1b46
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/formatter/XMLFormattingPreferences.java
@@ -0,0 +1,179 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.formatter;
+
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.wst.xml.core.internal.XMLCorePlugin;
+import org.eclipse.wst.xml.core.internal.preferences.XMLCorePreferenceNames;
+
+public class XMLFormattingPreferences {
+	public final static String PRESERVE = XMLFormattingConstraints.PRESERVE;
+	public final static String COLLAPSE = XMLFormattingConstraints.COLLAPSE;
+	public final static String IGNORE = XMLFormattingConstraints.IGNORE;
+
+	public final static String INDENT = XMLFormattingConstraints.INDENT;
+	public final static String NEW_LINE = XMLFormattingConstraints.NEW_LINE;
+	public final static String INLINE = XMLFormattingConstraints.INLINE;
+
+	private int fMaxLineWidth = 72;
+	private boolean fAlignFinalBracket = false;
+	private boolean fSpaceBeforeEmptyCloseTag = true;
+	private boolean fIndentMultipleAttributes = false;
+	private boolean fFormatCommentText = true;
+	private boolean fJoinCommentLines = false;
+
+	private String fPCDataWhitespaceStrategy = XMLFormattingConstraints.PRESERVE;
+	private String fTextIndentStrategy = XMLFormattingConstraints.INLINE;
+	private String fTextWhitespaceStrategy = XMLFormattingConstraints.COLLAPSE;
+	private String fElementIndentStrategy = XMLFormattingConstraints.INDENT;
+	private String fElementWhitespaceStrategy = XMLFormattingConstraints.IGNORE;
+	private String fMixedIndentStrategy = XMLFormattingConstraints.INDENT;
+	private String fMixedWhitespaceStrategy = XMLFormattingConstraints.IGNORE;
+	private String fOneIndent = "\t"; //$NON-NLS-1$
+	private boolean fClearAllBlankLines = false;
+
+	public XMLFormattingPreferences() {
+		Preferences preferences = XMLCorePlugin.getDefault().getPluginPreferences();
+		if (preferences != null) {
+			setFormatCommentText(preferences.getBoolean(XMLCorePreferenceNames.FORMAT_COMMENT_TEXT));
+			setJoinCommentLines(preferences.getBoolean(XMLCorePreferenceNames.FORMAT_COMMENT_JOIN_LINES));
+
+			setMaxLineWidth(preferences.getInt(XMLCorePreferenceNames.LINE_WIDTH));
+			setIndentMultipleAttributes(preferences.getBoolean(XMLCorePreferenceNames.SPLIT_MULTI_ATTRS));
+			setAlignFinalBracket(preferences.getBoolean(XMLCorePreferenceNames.ALIGN_END_BRACKET));
+			setSpaceBeforeEmptyCloseTag(preferences.getBoolean(XMLCorePreferenceNames.SPACE_BEFORE_EMPTY_CLOSE_TAG));
+			
+			boolean preservepcdata = preferences.getBoolean(XMLCorePreferenceNames.PRESERVE_CDATACONTENT);
+			if (preservepcdata)
+				fPCDataWhitespaceStrategy = XMLFormattingPreferences.PRESERVE;
+			else
+				fPCDataWhitespaceStrategy = XMLFormattingPreferences.COLLAPSE;
+
+			char indentChar = ' ';
+			String indentCharPref = preferences.getString(XMLCorePreferenceNames.INDENTATION_CHAR);
+			if (XMLCorePreferenceNames.TAB.equals(indentCharPref)) {
+				indentChar = '\t';
+			}
+			int indentationWidth = preferences.getInt(XMLCorePreferenceNames.INDENTATION_SIZE);
+
+			StringBuffer indent = new StringBuffer();
+			for (int i = 0; i < indentationWidth; i++) {
+				indent.append(indentChar);
+			}
+			setOneIndent(indent.toString());
+			setClearAllBlankLines(preferences.getBoolean(XMLCorePreferenceNames.CLEAR_ALL_BLANK_LINES));
+		}
+	}
+
+	public int getMaxLineWidth() {
+		return fMaxLineWidth;
+	}
+
+	public boolean getFormatCommentText() {
+		return fFormatCommentText;
+	}
+
+	public boolean getAlignFinalBracket() {
+		return fAlignFinalBracket;
+	}
+
+	public boolean getSpaceBeforeEmptyCloseTag() {
+		return fSpaceBeforeEmptyCloseTag;
+	}
+	
+	public boolean getIndentMultipleAttributes() {
+		return fIndentMultipleAttributes;
+	}
+
+	public String getPCDataWhitespaceStrategy() {
+		return fPCDataWhitespaceStrategy;
+	}
+
+	public String getTextIndentStrategy() {
+		return fTextIndentStrategy;
+	}
+
+	public String getTextWhitespaceStrategy() {
+		return fTextWhitespaceStrategy;
+	}
+
+	public String getElementIndentStrategy() {
+		return fElementIndentStrategy;
+	}
+
+	public String getElementWhitespaceStrategy() {
+		return fElementWhitespaceStrategy;
+	}
+	
+	public boolean getJoinCommentLines() {
+		return fJoinCommentLines;
+	}
+
+	public void setJoinCommentLines(boolean joinCommentLines) {
+		fJoinCommentLines = joinCommentLines;
+	}
+
+	public void setFormatCommentText(boolean formatCommentText) {
+		fFormatCommentText = formatCommentText;
+	}
+
+	public void setSpaceBeforeEmptyCloseTag(boolean spaceBeforeEmptyCloseTag) {
+		fSpaceBeforeEmptyCloseTag = spaceBeforeEmptyCloseTag;
+	}
+
+	public void setIndentMultipleAttributes(boolean indentMultipleAttributes) {
+		fIndentMultipleAttributes = indentMultipleAttributes;
+	}
+
+	public void setPCDataWhitespaceStrategy(String dataWhitespaceStrategy) {
+		fPCDataWhitespaceStrategy = dataWhitespaceStrategy;
+	}
+
+	public void setAlignFinalBracket(boolean alignFinalBracket) {
+		fAlignFinalBracket = alignFinalBracket;
+	}
+
+	public String getMixedIndentStrategy() {
+		return fMixedIndentStrategy;
+	}
+
+	public void setMixedIndentStrategy(String mixedIndentStrategy) {
+		fMixedIndentStrategy = mixedIndentStrategy;
+	}
+
+	public String getMixedWhitespaceStrategy() {
+		return fMixedWhitespaceStrategy;
+	}
+
+	public void setMixedWhitespaceStrategy(String mixedWhitespaceStrategy) {
+		fMixedWhitespaceStrategy = mixedWhitespaceStrategy;
+	}
+
+	public String getOneIndent() {
+		return fOneIndent;
+	}
+
+	protected void setMaxLineWidth(int maxLineWidth) {
+		fMaxLineWidth = maxLineWidth;
+	}
+
+	protected void setOneIndent(String oneIndent) {
+		fOneIndent = oneIndent;
+	}
+
+	public boolean getClearAllBlankLines() {
+		return fClearAllBlankLines;
+	}
+
+	public void setClearAllBlankLines(boolean clearAllBlankLines) {
+		fClearAllBlankLines = clearAllBlankLines;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/modelhandler/EmbeddedXML.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/modelhandler/EmbeddedXML.java
new file mode 100644
index 0000000..abff1a4
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/modelhandler/EmbeddedXML.java
@@ -0,0 +1,95 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2009 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.modelhandler;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.wst.sse.core.internal.ltk.modelhandler.EmbeddedTypeHandler;
+import org.eclipse.wst.sse.core.internal.ltk.parser.RegionParser;
+import org.eclipse.wst.sse.core.internal.model.FactoryRegistry;
+import org.eclipse.wst.xml.core.internal.modelquery.ModelQueryAdapterFactoryForEmbeddedXML;
+
+
+public class EmbeddedXML implements EmbeddedTypeHandler {
+
+	private static List supportedMimeTypes;
+	public String ContentTypeID_EmbeddedXML = "org.eclipse.wst.xml.core.contenttype.EmbeddedXML"; //$NON-NLS-1$
+
+	/**
+	 * Constructor for EmbeddedXML.
+	 */
+	public EmbeddedXML() {
+		super();
+	}
+
+	/*
+	 * @see EmbeddedContentType#getAdapterFactories()
+	 */
+	public List getAdapterFactories() {
+		List factories = new ArrayList();
+		factories.add(new ModelQueryAdapterFactoryForEmbeddedXML());
+		// factories.addAll(PluginContributedFactoryReader.getInstance().getFactories(this));
+		return factories;
+	}
+
+	/**
+	 * @see EmbeddedContentType#getFamilyId()
+	 */
+	public String getFamilyId() {
+		return ModelHandlerForXML.AssociatedContentTypeID;
+	}
+
+	public List getSupportedMimeTypes() {
+		if (supportedMimeTypes == null) {
+			supportedMimeTypes = new ArrayList();
+			supportedMimeTypes.add("application/xml"); //$NON-NLS-1$
+			supportedMimeTypes.add("text/xml"); //$NON-NLS-1$
+		}
+		return supportedMimeTypes;
+	}
+
+	public void initializeFactoryRegistry(FactoryRegistry registry) {
+		//TODO: initialize
+	}
+
+	public void initializeParser(RegionParser parser) {
+		// nothing to initialize for "pure" XML
+		// compare with XHTML
+	}
+
+	public boolean isDefault() {
+		return false;
+	}
+
+	public EmbeddedTypeHandler newInstance() {
+		return new EmbeddedXML();
+	}
+
+	public void uninitializeFactoryRegistry(FactoryRegistry registry) {
+		// TODO: need to undo anything we did in initialize
+
+	}
+
+	public void uninitializeParser(RegionParser parser) {
+		// need to undo anything we did in initialize
+	}
+
+	public boolean canHandleMimeType(String mimeType) {
+		boolean canHandle = getSupportedMimeTypes().contains(mimeType);
+		if(!canHandle) {
+			canHandle = mimeType.endsWith("+xml"); //$NON-NLS-1$
+		}
+		return canHandle;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/modelhandler/ModelHandlerForXML.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/modelhandler/ModelHandlerForXML.java
new file mode 100644
index 0000000..f4bdf3c
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/modelhandler/ModelHandlerForXML.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.modelhandler;
+
+import org.eclipse.wst.sse.core.internal.document.IDocumentCharsetDetector;
+import org.eclipse.wst.sse.core.internal.document.IDocumentLoader;
+import org.eclipse.wst.sse.core.internal.ltk.modelhandler.AbstractModelHandler;
+import org.eclipse.wst.sse.core.internal.ltk.modelhandler.IModelHandler;
+import org.eclipse.wst.sse.core.internal.provisional.IModelLoader;
+import org.eclipse.wst.xml.core.internal.encoding.XMLDocumentCharsetDetector;
+import org.eclipse.wst.xml.core.internal.encoding.XMLDocumentLoader;
+
+
+/**
+ * Provides generic XML model handling. It is also marked as the default
+ * content type handler. There should be only one implementation of the
+ * default.
+ */
+public class ModelHandlerForXML extends AbstractModelHandler implements IModelHandler {
+	/**
+	 * Needs to match what's in plugin registry. In fact, can be overwritten
+	 * at run time with what's in registry! (so should never be 'final')
+	 */
+	static String AssociatedContentTypeID = "org.eclipse.core.runtime.xml"; //$NON-NLS-1$
+	/**
+	 * Needs to match what's in plugin registry. In fact, can be overwritten
+	 * at run time with what's in registry! (so should never be 'final')
+	 */
+	private static String ModelHandlerID = "org.eclipse.wst.xml.core.modelhandler"; //$NON-NLS-1$
+
+	public ModelHandlerForXML() {
+		super();	
+		setId(ModelHandlerID);
+		setAssociatedContentTypeId(AssociatedContentTypeID);
+	}
+
+	public IDocumentLoader getDocumentLoader() {
+		return new XMLDocumentLoader();
+	}
+
+	public IDocumentCharsetDetector getEncodingDetector() {
+		return new XMLDocumentCharsetDetector();
+	}
+
+	public IModelLoader getModelLoader() {
+		return new XMLModelLoader();
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/modelhandler/XMLModelLoader.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/modelhandler/XMLModelLoader.java
new file mode 100644
index 0000000..ecf9223
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/modelhandler/XMLModelLoader.java
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.modelhandler;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.wst.sse.core.internal.PropagatingAdapter;
+import org.eclipse.wst.sse.core.internal.document.IDocumentLoader;
+import org.eclipse.wst.sse.core.internal.model.AbstractModelLoader;
+import org.eclipse.wst.sse.core.internal.provisional.IModelLoader;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapterFactory;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.util.Debug;
+import org.eclipse.wst.xml.core.internal.DebugAdapterFactory;
+import org.eclipse.wst.xml.core.internal.document.DOMModelImpl;
+import org.eclipse.wst.xml.core.internal.encoding.XMLDocumentLoader;
+import org.eclipse.wst.xml.core.internal.modelquery.ModelQueryAdapterFactoryForXML;
+import org.eclipse.wst.xml.core.internal.propagate.PropagatingAdapterFactoryImpl;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
+
+
+/**
+ * This class reads an XML file and creates an XML Structured Model.
+ *  
+ */
+public class XMLModelLoader extends AbstractModelLoader {
+
+	//	private static final String STR_ENCODING = "encoding"; //$NON-NLS-1$
+
+	/**
+	 * XMLLoader constructor comment.
+	 */
+	public XMLModelLoader() {
+		super();
+	}
+
+	public List getAdapterFactories() {
+		List result = new ArrayList();
+		INodeAdapterFactory factory = null;
+		factory = new ModelQueryAdapterFactoryForXML();
+		result.add(factory);
+		// Does XML need propagating adapter? Or just JSP?
+		factory = new PropagatingAdapterFactoryImpl();
+		result.add(factory);
+		return result;
+	}
+
+	public IDocumentLoader getDocumentLoader() {
+		if (documentLoaderInstance == null) {
+			documentLoaderInstance = new XMLDocumentLoader();
+		}
+		return documentLoaderInstance;
+	}
+
+	public IModelLoader newInstance() {
+		return new XMLModelLoader();
+	}
+
+	public IStructuredModel newModel() {
+		return new DOMModelImpl();
+	}
+
+	protected void preLoadAdapt(IStructuredModel structuredModel) {
+		super.preLoadAdapt(structuredModel);
+		IDOMModel domModel = (IDOMModel) structuredModel;
+		// if there is a model in the adapter, this will adapt it to
+		// first node. After that the PropagatingAdater spreads over the
+		// children being
+		// created. Each time that happends, a side effect is to
+		// also "spread" sprecific registered adapters,
+		// they two can propigate is needed.
+		((INodeNotifier) domModel.getDocument()).getAdapterFor(PropagatingAdapter.class);
+
+		if (Debug.debugNotificationAndEvents) {
+			PropagatingAdapter propagatingAdapter = (PropagatingAdapter) ((INodeNotifier) domModel.getDocument()).getAdapterFor(PropagatingAdapter.class);
+			propagatingAdapter.addAdaptOnCreateFactory(new DebugAdapterFactory());
+		}
+
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/modelquery/ModelQueryAdapterFactoryForEmbeddedXML.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/modelquery/ModelQueryAdapterFactoryForEmbeddedXML.java
new file mode 100644
index 0000000..805a9c1
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/modelquery/ModelQueryAdapterFactoryForEmbeddedXML.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.modelquery;
+
+
+
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapter;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.CMDocumentManager;
+import org.eclipse.wst.xml.core.internal.ssemodelquery.ModelQueryAdapter;
+
+
+public class ModelQueryAdapterFactoryForEmbeddedXML extends ModelQueryAdapterFactoryForXML {
+
+
+	/**
+	 * Constructor for ModelQueryAdapterFactoryForEmbeddedXML.
+	 */
+	public ModelQueryAdapterFactoryForEmbeddedXML() {
+		super(ModelQueryAdapter.class, false);
+	}
+
+	protected void configureDocumentManager(CMDocumentManager mgr) {
+		super.configureDocumentManager(mgr);
+		mgr.setPropertyEnabled(CMDocumentManager.PROPERTY_ASYNC_LOAD, true);
+	}
+	
+	/**
+	 * ISSUE: this "forces" a new one to always be created/returned, 
+	 * not "cached" on the node. That seems incorrect. 
+	 * Simply using shouldRegisterFalse should work, except, 
+	 * there might have been one there that someone else already 
+	 * explicitly put there, so this is only way I know to 
+	 * override that. Especially complicated here since a number
+	 * of adapters are for ModelQueryAdapter.class.
+	 */
+	public INodeAdapter adapt(INodeNotifier object) {
+		return adaptNew(object);
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/modelquery/ModelQueryAdapterFactoryForXML.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/modelquery/ModelQueryAdapterFactoryForXML.java
new file mode 100644
index 0000000..cbb4add
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/modelquery/ModelQueryAdapterFactoryForXML.java
@@ -0,0 +1,253 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.modelquery;
+
+
+
+import java.io.File;
+import java.net.URI;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.wst.common.uriresolver.internal.provisional.URIResolver;
+import org.eclipse.wst.sse.core.internal.provisional.AbstractAdapterFactory;
+import org.eclipse.wst.sse.core.internal.provisional.IModelStateListener;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapter;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapterFactory;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.util.Debug;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.CMDocumentManager;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.CMDocumentCache;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.eclipse.wst.xml.core.internal.ssemodelquery.ModelQueryAdapter;
+import org.eclipse.wst.xml.core.internal.ssemodelquery.ModelQueryAdapterImpl;
+
+
+public class ModelQueryAdapterFactoryForXML extends AbstractAdapterFactory {
+
+	protected ModelQueryAdapterImpl modelQueryAdapterImpl;
+	IStructuredModel stateNotifier = null;
+	private InternalModelStateListener internalModelStateListener;
+
+	/**
+	 * ModelQueryAdapterFactoryForXML constructor comment.
+	 */
+	public ModelQueryAdapterFactoryForXML() {
+		this(ModelQueryAdapter.class, true);
+	}
+
+	/**
+	 * ModelQueryAdapterFactoryForXML constructor comment.
+	 * 
+	 * @param adapterKey
+	 *            java.lang.Object
+	 * @param registerAdapters
+	 *            boolean
+	 */
+	protected ModelQueryAdapterFactoryForXML(Object adapterKey, boolean registerAdapters) {
+		super(adapterKey, registerAdapters);
+	}
+
+	class InternalModelStateListener implements IModelStateListener {
+
+		/**
+		 * @see IModelStateListener#modelAboutToBeChanged(IStructuredModel)
+		 */
+		public void modelAboutToBeChanged(IStructuredModel model) {
+		}
+
+		/**
+		 * @see IModelStateListener#modelChanged(IStructuredModel)
+		 */
+		public void modelChanged(IStructuredModel model) {
+		}
+
+		/**
+		 * @see IModelStateListener#modelDirtyStateChanged(IStructuredModel,
+		 *      boolean)
+		 */
+		public void modelDirtyStateChanged(IStructuredModel model, boolean isDirty) {
+		}
+
+		/**
+		 * @see IModelStateListener#modelResourceDeleted(IStructuredModel)
+		 */
+		public void modelResourceDeleted(IStructuredModel model) {
+		}
+
+		/**
+		 * @see IModelStateListener#modelResourceMoved(IStructuredModel,
+		 *      IStructuredModel)
+		 */
+		public void modelResourceMoved(IStructuredModel oldModel, IStructuredModel newModel) {
+			stateNotifier.removeModelStateListener(this);
+			stateNotifier = newModel;
+			updateResolver(stateNotifier);
+			stateNotifier.addModelStateListener(this);
+		}
+
+		public void modelAboutToBeReinitialized(IStructuredModel structuredModel) {
+			// TODO Auto-generated method stub
+
+		}
+
+		public void modelReinitialized(IStructuredModel structuredModel) {
+			updateResolver(structuredModel);
+
+		}
+
+
+	}
+
+	protected boolean autoLoadCM() {
+		// until the existence of a CMDocumentRequesterFactory to create the
+		// load requests,
+		// return true
+		return true;
+	}
+
+	protected void configureDocumentManager(CMDocumentManager mgr) {
+		// this depends on there being a CMDocumentRequesterFactory installed
+		mgr.setPropertyEnabled(CMDocumentManager.PROPERTY_AUTO_LOAD, autoLoadCM());
+	}
+
+	public INodeAdapterFactory copy() {
+
+		return new ModelQueryAdapterFactoryForXML(getAdapterKey(), isShouldRegisterAdapter());
+	}
+
+	/**
+	 * createAdapter method comment.
+	 */
+	protected INodeAdapter createAdapter(INodeNotifier target) {
+
+		if (org.eclipse.wst.sse.core.internal.util.Debug.displayInfo)
+			System.out.println("-----------------------ModelQueryAdapterFactoryForXML.createAdapter" + target); //$NON-NLS-1$
+		if (modelQueryAdapterImpl == null) {
+			if (target instanceof IDOMNode) {
+				IDOMNode xmlNode = (IDOMNode) target;
+				IStructuredModel model = xmlNode.getModel();
+				stateNotifier = xmlNode.getModel();
+				stateNotifier.addModelStateListener(getInternalModelStateListener());
+
+				org.eclipse.wst.sse.core.internal.util.URIResolver resolver = model.getResolver();
+				if (Debug.displayInfo)
+					System.out.println("----------------ModelQueryAdapterFactoryForXML... baseLocation : " + resolver.getFileBaseLocation()); //$NON-NLS-1$
+
+				/**
+				 * XMLCatalogIdResolver currently requires a filesystem
+				 * location string. Customarily this will be what is in the
+				 * deprecated SSE URIResolver and required by the Common URI
+				 * Resolver.
+				 */
+				URIResolver idResolver = null;
+				if (resolver != null) {
+					idResolver = new XMLCatalogIdResolver(resolver.getFileBaseLocation(), resolver);
+				}
+				else {
+					/*
+					 * 203649 - this block may be necessary due to ordering of
+					 * setting the resolver into the model
+					 */
+					String baseLocation = null;
+					String modelsBaseLocation = model.getBaseLocation();
+					if (modelsBaseLocation != null) {
+						File file = new Path(modelsBaseLocation).toFile();
+						if (file.exists()) {
+							baseLocation = file.getAbsolutePath();
+						}
+						else {
+							IPath basePath = new Path(model.getBaseLocation());
+							IResource derivedResource = null;
+							if (basePath.segmentCount() > 1)
+								derivedResource = ResourcesPlugin.getWorkspace().getRoot().getFile(basePath);
+							else
+								derivedResource = ResourcesPlugin.getWorkspace().getRoot().getProject(basePath.segment(0));
+							IPath derivedPath = derivedResource.getLocation();
+							if (derivedPath != null) {
+								baseLocation = derivedPath.toString();
+							}
+							else {
+								URI uri = derivedResource.getLocationURI();
+								if (uri != null) {
+									baseLocation = uri.toString();
+								}
+							}
+						}
+						if(baseLocation == null) {
+							baseLocation = modelsBaseLocation;
+						}
+					}
+					idResolver = new XMLCatalogIdResolver(baseLocation, null);
+				}
+
+				CMDocumentCache cmDocumentCache = new CMDocumentCache();
+				ModelQuery modelQuery = new XMLModelQueryImpl(cmDocumentCache, idResolver);
+
+				// cs todo...
+				// for now we create a CMDocumentCache on a 'per editor' basis
+				// in the future we need to support a CMDocumentCache that is
+				// shared between editors
+				// nsd comment: may not be appropriate depending on
+				CMDocumentManager documentManager = modelQuery.getCMDocumentManager();
+				if (documentManager != null) {
+					configureDocumentManager(documentManager);
+				}
+				modelQueryAdapterImpl = new ModelQueryAdapterImpl(cmDocumentCache, modelQuery, idResolver);
+			}
+		}
+		return modelQueryAdapterImpl;
+	}
+
+	public void release() {
+		super.release();
+		if (stateNotifier != null)
+			stateNotifier.removeModelStateListener(getInternalModelStateListener());
+		stateNotifier = null;
+		if (modelQueryAdapterImpl != null)
+			modelQueryAdapterImpl.release();
+	}
+
+	protected void updateResolver(IStructuredModel model) {
+
+		String baseLocation = model.getBaseLocation();
+		IFile baseFile = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(model.getBaseLocation()));
+		if (baseFile != null) {
+			if (baseFile.getLocation() != null) {
+				baseLocation = baseFile.getLocation().toString();
+			}
+			if (baseLocation == null && baseFile.getLocationURI() != null) {
+				baseLocation = baseFile.getLocationURI().toString();
+			}
+			if (baseLocation == null) {
+				baseLocation = baseFile.getFullPath().toString();
+			}
+		}
+		else {
+			baseLocation = model.getBaseLocation();
+		}
+		modelQueryAdapterImpl.setIdResolver(new XMLCatalogIdResolver(baseLocation, model.getResolver()));
+	}
+
+	private final InternalModelStateListener getInternalModelStateListener() {
+		if (internalModelStateListener == null) {
+			internalModelStateListener = new InternalModelStateListener();
+		}
+		return internalModelStateListener;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/modelquery/ModelQueryUtil.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/modelquery/ModelQueryUtil.java
new file mode 100644
index 0000000..eae3e89
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/modelquery/ModelQueryUtil.java
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.modelquery;
+
+
+
+import org.eclipse.wst.common.uriresolver.internal.provisional.URIResolver;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.CMDocumentCache;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
+import org.eclipse.wst.xml.core.internal.ssemodelquery.ModelQueryAdapter;
+import org.w3c.dom.Document;
+
+
+/**
+ * This class is used to associate ModelQuery (and related data) with a
+ * Document (or IStructuredModel).
+ */
+public class ModelQueryUtil {
+
+	public static CMDocumentCache getCMDocumentCache(Document node) {
+		ModelQueryAdapter modelQueryAdapter = getModelQueryAdapter(node);
+		return modelQueryAdapter != null ? modelQueryAdapter.getCMDocumentCache() : null;
+	}
+
+	public static URIResolver getIdResolver(Document node) {
+		ModelQueryAdapter modelQueryAdapter = getModelQueryAdapter(node);
+		return modelQueryAdapter != null ? modelQueryAdapter.getIdResolver() : null;
+	}
+
+	public static ModelQuery getModelQuery(Document node) {
+		ModelQueryAdapter modelQueryAdapter = getModelQueryAdapter(node);
+		return modelQueryAdapter != null ? modelQueryAdapter.getModelQuery() : null;
+	}
+
+	public static ModelQuery getModelQuery(IStructuredModel model) {
+		if ((!(model instanceof IDOMModel)) || model == null)
+			return null;
+		return getModelQuery(((IDOMModel) model).getDocument());
+	}
+
+	public static ModelQueryAdapter getModelQueryAdapter(Document node) {
+		ModelQueryAdapter result = null;
+
+		if (node instanceof INodeNotifier) {
+			INodeNotifier notifier = (INodeNotifier) node;
+			result = (ModelQueryAdapter) notifier.getAdapterFor(ModelQueryAdapter.class);
+		}
+
+		return result;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/modelquery/XMLCatalogIdResolver.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/modelquery/XMLCatalogIdResolver.java
new file mode 100644
index 0000000..61852f9
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/modelquery/XMLCatalogIdResolver.java
@@ -0,0 +1,102 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.modelquery;
+
+
+import org.eclipse.wst.common.uriresolver.internal.provisional.URIResolverPlugin;
+import org.eclipse.wst.common.uriresolver.internal.util.URIHelper;
+import org.eclipse.wst.sse.core.internal.util.URIResolver;
+import org.eclipse.wst.xml.core.internal.Logger;
+
+
+// TODO cs : remove this class and utilize the common URIResolver directly
+// We need to update some of the ModelQuery related code to pass the
+// 'baseLocation' thru
+// and then there'll be node need for this class.
+// 
+public class XMLCatalogIdResolver implements org.eclipse.wst.common.uriresolver.internal.provisional.URIResolver {
+	protected String resourceLocation;
+
+	protected URIResolver uriresolver;
+
+	private XMLCatalogIdResolver() {
+		super();
+	}
+
+	private XMLCatalogIdResolver(String resourceLocation) {
+		this();
+		this.resourceLocation = resourceLocation;
+	}
+
+	public XMLCatalogIdResolver(String resourceLocation, URIResolver uriresolver) {
+		this(resourceLocation);
+// this constructor should not be called with two null arguments.
+// If so, an assert will occur later when resolve is called. 
+// See 118371 XMLCatalogIdResolver#resolve throws AssertionFailedException
+//
+// but, I'm not enabling this check now due to lateness in cycle. 		
+//		if (resourceLocation == null && uriresolver == null) {
+//			throw new IllegalArgumentException("both location and resolver can not be null");
+//		}
+		this.uriresolver = uriresolver;
+	}
+
+
+	/**
+	 * Gets the resourceLocation.
+	 * 
+	 * @return Returns a String
+	 */
+	private String getResourceLocation() {
+		String location = resourceLocation;
+		if (location == null) {
+			if (uriresolver != null)
+				location = uriresolver.getFileBaseLocation();
+		}
+		return location;
+	}
+
+
+	public String resolve(String base, String publicId, String systemId) {
+
+		String result = systemId;
+		if (base == null) {
+			base = getResourceLocation();
+			// bug 117320, ensure base URI is 'protocal' qualified before
+			// passing it thru to URIResolver
+			// bug 117424, we should be able to assume that the base location
+			// is non-null
+
+			/**
+			 * We shouldn't assert a failure because the catalog does not
+			 * require a base location to operate and it will be called from
+			 * non-file-based scenarios.
+			 * 
+			 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=206176
+			 */
+			// Assert.isNotNull(base, "Base location is expected to be non null."); //$NON-NLS-1$
+			if (base != null) {
+				base = URIHelper.addImpliedFileProtocol(base);
+			}
+		}
+		result = URIResolverPlugin.createResolver().resolve(base, publicId, systemId);
+		return result;
+	}
+
+	public String resolvePhysicalLocation(String baseLocation, String publicId, String logicalLocation) {
+		// This class should never be called to perform physical resolution!
+		// If it does we should log it as an error
+		Logger.log(Logger.ERROR_DEBUG, "XMLCatalogIDResolver.resolvePhysicalLocation() called unexpectedly"); //$NON-NLS-1$
+		return logicalLocation;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/modelquery/XMLModelQueryAssociationProvider.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/modelquery/XMLModelQueryAssociationProvider.java
new file mode 100644
index 0000000..74d14ab
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/modelquery/XMLModelQueryAssociationProvider.java
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.modelquery;
+
+
+
+import org.eclipse.wst.common.uriresolver.internal.provisional.URIResolver;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelqueryimpl.XMLAssociationProvider;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.CMDocumentCache;
+import org.w3c.dom.Document;
+
+/**
+ * XMLModelQueryAssociationProvider
+ * 
+ * This added and/or made public specifically for experimentation. It will
+ * change as this functionality becomes API. See
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=119084
+ * 
+ */
+public class XMLModelQueryAssociationProvider extends XMLAssociationProvider {
+
+	protected URIResolver idResolver;
+
+	public XMLModelQueryAssociationProvider(CMDocumentCache cache, URIResolver idResolver) {
+		super(cache);
+		this.idResolver = idResolver;
+	}
+
+	protected String resolveGrammarURI(Document document, String publicId, String systemId) {
+
+		// CS : spooky code alert!
+		// this look really strange because we're passing null in as the first
+		// argument
+		// however we're assuming the use of a 'fudged' URIResolver that knows
+		// the
+		// correct baseLocation and will call to the URIResolver framework
+		// properly
+
+		// CS : note that we should never call resolvePhysical at this point.
+		// Physical resolution should only occur when we're interesting to
+		// opening the actual stream.
+		// The CMDocumentFactory implementation would be responsible for
+		// calling resolvePhysical.
+		// All we need to do here is return a 'logical' URI
+
+		if (idResolver == null)
+			return null;
+		return idResolver.resolve(null, publicId, systemId);
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/modelquery/XMLModelQueryImpl.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/modelquery/XMLModelQueryImpl.java
new file mode 100644
index 0000000..7bfa001
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/modelquery/XMLModelQueryImpl.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.modelquery;
+
+
+
+import org.eclipse.wst.common.uriresolver.internal.provisional.URIResolver;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelqueryimpl.ModelQueryImpl;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.CMDocumentCache;
+import org.eclipse.wst.xml.core.internal.ssemodelquery.MovableModelQuery;
+
+
+public class XMLModelQueryImpl extends ModelQueryImpl implements MovableModelQuery {
+
+	protected CMDocumentCache fCache = null;
+
+	public XMLModelQueryImpl(CMDocumentCache cache, URIResolver idResolver) {
+		super(new XMLModelQueryAssociationProvider(cache, idResolver));
+		fCache = cache;
+	}
+
+	/**
+	 * @see MovableModelQuery#setIdResolver(URIResolver)
+	 */
+	public void setIdResolver(URIResolver newIdResolver) {
+		modelQueryAssociationProvider = new XMLModelQueryAssociationProvider(fCache, newIdResolver);
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/BlockStructuredDocumentRegion.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/BlockStructuredDocumentRegion.java
new file mode 100644
index 0000000..7754a80
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/BlockStructuredDocumentRegion.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.parser;
+
+
+
+import org.eclipse.wst.sse.core.internal.ltk.parser.IBlockedStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.internal.text.BasicStructuredDocumentRegion;
+
+
+public class BlockStructuredDocumentRegion extends BasicStructuredDocumentRegion implements IBlockedStructuredDocumentRegion {
+
+	private String partitionType;
+
+	/**
+	 * A BlockStructuredDocumentRegion is like a IStructuredDocumentRegion,
+	 * but is the result of a "block scan".
+	 */
+	public BlockStructuredDocumentRegion() {
+		super();
+	}
+
+	public String getPartitionType() {
+		if (partitionType == null) {
+			// eventually can look up surroundingTag name
+			// but this field is primarily entended for future
+			// extensibility. This may change.
+			//partitionType = "org.eclipse.wst.sse.core." + tagname;
+		}
+		return partitionType;
+	}
+
+	public void setPartitionType(String partitionType) {
+		this.partitionType = partitionType;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/ContextRegionContainer.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/ContextRegionContainer.java
new file mode 100644
index 0000000..0de3302
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/ContextRegionContainer.java
@@ -0,0 +1,327 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2009 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.parser;
+
+
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentEvent;
+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.internal.text.TextRegionListImpl;
+import org.eclipse.wst.xml.core.internal.Logger;
+
+
+public class ContextRegionContainer implements ITextRegionContainer {
+	protected int length;
+	protected ITextRegionCollection parent;
+	protected ITextRegionList regions;
+	protected int start;
+	protected int textLength;
+	protected String type;
+
+	public ContextRegionContainer() {
+		super();
+		regions = new TextRegionListImpl();
+
+	}
+
+	/**
+	 * these "deep" parenting is not normal, but just in case.
+	 */
+	private IStructuredDocument _getParentDocument() {
+		// go up enough parents to get to document
+		ITextRegionCollection parent = getParent();
+		while (!(parent instanceof IStructuredDocumentRegion)) {
+			// would be an error not to be container, but
+			// won't check for it now
+			parent = ((ITextRegionContainer) parent).getParent();
+		}
+		return ((IStructuredDocumentRegion) parent).getParentDocument();
+	}
+
+
+	public void adjust(int i) {
+
+		start += i;
+		// I erroneously added length and textLength
+		// TODO: may want to rename this method to adjustStart
+		//length += i;
+		//textLength += i;
+
+	}
+
+	public void adjustLength(int i) {
+		length += i;
+	}
+
+	public void adjustStart(int i) {
+		start += i;
+	}
+
+
+	public void adjustTextLength(int i) {
+		textLength += i;
+
+	}
+
+	public boolean containsOffset(int i) {
+
+		return getStartOffset() <= i && i < getEndOffset();
+	}
+
+	public boolean containsOffset(ITextRegion containedRegion, int offset) {
+		return getStartOffset(containedRegion) <= offset && offset < getEndOffset(containedRegion);
+	}
+
+	/**
+	 * This method is just to equate positions. clients may (will probably)
+	 * still need to make calls to equate regions, parent, etc.
+	 */
+	public void equatePositions(ITextRegion region) {
+		start = region.getStart();
+		length = region.getLength();
+		textLength = region.getTextLength();
+	}
+
+	public int getEnd() {
+		return start + length;
+	}
+
+	public int getEndOffset() {
+		// our startOffset take into account our parent, and our start
+		return getStartOffset() + getLength();
+	}
+
+	public int getEndOffset(ITextRegion containedRegion) {
+		return getStartOffset(containedRegion) + containedRegion.getLength();
+	}
+
+	public ITextRegion getFirstRegion() {
+		return getRegions().get(0);
+	}
+
+	public String getFullText() {
+		return getParent().getFullText(this);
+	}
+
+	public String getFullText(org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion aRegion) {
+		// Must be proxied here since aRegion should always be a child of
+		// *this* container and indexed from
+		// this container's offset
+		return parent.getFullText().substring(start + aRegion.getStart(), start + aRegion.getEnd());
+	}
+
+	public ITextRegion getLastRegion() {
+		return getRegions().get(getRegions().size() - 1);
+	}
+
+	public int getLength() {
+		return length;
+	}
+
+
+	public int getNumberOfRegions() {
+		return getRegions().size();
+	}
+
+	public ITextRegionCollection getParent() {
+		return parent;
+	}
+
+	/**
+	 * The parameter offset refers to the overall offset in the document.
+	 */
+	public ITextRegion getRegionAtCharacterOffset(int offset) {
+		ITextRegion result = null;
+		if (regions != null) {
+			int thisStartOffset = getStartOffset();
+			if (offset < thisStartOffset)
+				return null;
+			int thisEndOffset = getStartOffset() + getLength();
+			if (offset > thisEndOffset)
+				return null;
+			// transform the requested offset to the "scale" that
+			// regions are stored in, which are all relative to the
+			// start point.
+			//int transformedOffset = offset - getStartOffset();
+			//
+			ITextRegionList regions = getRegions();
+			int length = regions.size();
+			int low = 0;
+			int high = length;
+			int mid = 0;
+			// Binary search for the region
+			while (low < high) {
+				mid = low + ((high - low) >> 1);
+				ITextRegion region = regions.get(mid);
+				if (org.eclipse.wst.sse.core.internal.util.Debug.debugStructuredDocument) {
+					System.out.println("region(s) in IStructuredDocumentRegion::getRegionAtCharacterOffset: " + region); //$NON-NLS-1$
+					System.out.println("       midpoint of search:" + mid); //$NON-NLS-1$
+					System.out.println("       requested offset: " + offset); //$NON-NLS-1$
+					//System.out.println(" transformedOffset: " +
+					// transformedOffset); //$NON-NLS-1$
+					System.out.println("       region start: " + region.getStart()); //$NON-NLS-1$
+					System.out.println("       region end: " + region.getEnd()); //$NON-NLS-1$
+					System.out.println("       region type: " + region.getType()); //$NON-NLS-1$
+					System.out.println("       region class: " + region.getClass()); //$NON-NLS-1$
+
+				}
+				// Region is before this one
+				if (offset < region.getStart() + thisStartOffset)
+					high = mid;
+				else if (offset > (region.getEnd() + thisStartOffset - 1))
+					low = mid + 1;
+				else
+					return region;
+			}
+			return null;
+		}
+		return result;
+	}
+
+	public ITextRegionList getRegions() {
+		return regions;
+	}
+
+	public int getStart() {
+		return start;
+	}
+
+	public int getStartOffset() {
+		return getParent().getStartOffset() + getStart();
+	}
+
+	public int getStartOffset(ITextRegion containedRegion) {
+		// it is an error to pass null to this method
+		// ISSUE: need better "spec" on error behavior: 
+		// for now will return zero as this will roughly 
+		// work for some cases (and avoid NPE).
+		if (containedRegion == null) {
+			return getStartOffset();
+		}
+		return getStartOffset() + containedRegion.getStart();
+	}
+
+	/**
+	 * same as getFullText for this region type ... do we need to take white
+	 * space off?
+	 */
+
+	public String getText() {
+		String result = null;
+		try {
+			IStructuredDocument parentDocument = _getParentDocument();
+			result = parentDocument.get(start, length);
+		} catch (BadLocationException e) {
+			Logger.logException("program error: unreachable exception", e); //$NON-NLS-1$
+		}
+		return result;
+	}
+
+	public String getText(org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion aRegion) {
+		// Must be proxied here since aRegion should always be a child of
+		// *this* container and indexed from
+		// this container's offset
+		return parent.getText().substring(start + aRegion.getStart(), start + aRegion.getTextEnd());
+	}
+
+	public int getTextEnd() {
+		return start + textLength;
+	}
+
+	public int getTextEndOffset() {
+		ITextRegion region = regions.get(regions.size() - 1);
+		// our startOffset take into account our parent, and our start
+		// (pa) 10/4 changed to be based on text end
+		//           it used to return incorrect value for embedded region containers
+		//
+
+		// TODO CRITICAL -- need to re-work this work around, so doesn't
+		// depend on XMLRegionContext
+		//		// this is a workaround for 226823///////////
+		//		for (int i = regions.size() - 1; i >= 0 && region.getType() ==
+		// XMLRegionContext.WHITE_SPACE; i--)
+		//			region = (ITextRegion) regions.get(i);
+		//		/////////////////////////////////////////////
+
+		return getStartOffset() + region.getTextEnd();
+	}
+
+	public int getTextEndOffset(ITextRegion containedRegion) {
+		int result = 0;
+		if (regions != null) {
+			int length = getRegions().size();
+			for (int i = 0; i < length; i++) {
+				ITextRegion region = getRegions().get(i);
+				if (region == containedRegion) {
+					result = getStartOffset(region) + region.getTextEnd();
+					break;
+				}
+			}
+		}
+		return result;
+	}
+
+	public int getTextLength() {
+		return textLength;
+	}
+
+	public String getType() {
+		return type;
+	}
+
+	public void setLength(int i) {
+		length = i;
+	}
+
+	public void setParent(ITextRegionCollection parentRegion) {
+		parent = parentRegion;
+	}
+
+	public void setRegions(ITextRegionList containedRegions) {
+		regions = containedRegions;
+	}
+
+	public void setStart(int i) {
+		start = i;
+	}
+
+	public void setTextLength(int i) {
+		textLength = i;
+	}
+
+	public void setType(String string) {
+		type = string;
+	}
+
+	public String toString() {
+		String className = getClass().getName();
+		String shortClassName = className.substring(className.lastIndexOf(".") + 1); //$NON-NLS-1$
+		String result = "Container!!! " + shortClassName + "--> " + getType() + ": " + getStart() + "-" + getTextEnd() + (getTextEnd() != getEnd() ? ("/" + getEnd()) : ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
+		return result;
+	}
+
+	public StructuredDocumentEvent updateRegion(Object requester, IStructuredDocumentRegion parent, String changes, int requestStart, int lengthToReplace) {
+		org.eclipse.wst.sse.core.internal.provisional.events.RegionChangedEvent result = null;
+		// FUTURE_TO_DO: need to implement region level parsing in
+		// ITextRegionContainer::updateModel
+		// never being called?
+		return result;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/IntStack.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/IntStack.java
new file mode 100644
index 0000000..5cb8d5a
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/IntStack.java
@@ -0,0 +1,112 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2009 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.parser;
+
+
+
+/*
+ * 
+ * A non-resizable class implementing the behavior of java.util.Stack, but
+ * directly for the <code> integer </code> primitive.
+ */
+import java.util.EmptyStackException;
+
+public class IntStack {
+	private int[] list = null;
+
+	private int size = 0;
+
+	public IntStack() {
+		this(100);
+	}
+
+	public IntStack(int maxdepth) {
+		super();
+		list = new int[maxdepth];
+		initialize();
+	}
+
+	public boolean empty() {
+		return size == 0;
+	}
+
+	public int get(int slot) {
+		return list[slot];
+	}
+
+	void initialize() {
+		for (int i = 0; i < list.length; i++)
+			list[i] = -1;
+	}
+
+	/**
+	 * Returns the int at the top of the stack without removing it
+	 * 
+	 * @return int at the top of this stack.
+	 * @exception EmptyStackException
+	 *                when empty.
+	 */
+	public int peek() {
+		if (size == 0)
+			throw new EmptyStackException();
+		return list[size - 1];
+	}
+
+	/**
+	 * Removes and returns the int at the top of the stack
+	 * 
+	 * @return int at the top of this stack.
+	 * @exception EmptyStackException
+	 *                when empty.
+	 */
+	public int pop() {
+		int value = peek();
+		list[size - 1] = -1;
+		size--;
+		return value;
+	}
+
+	/**
+	 * Pushes an item onto the top of this stack.
+	 * 
+	 * @param newValue -
+	 *            the int to be pushed onto this stack.
+	 * @return the <code>newValue</code> argument.
+	 */
+	public int push(int newValue) {
+		if (size == list.length) {
+			throw new StackOverflowError();
+		}
+		list[size++] = newValue;
+		return newValue;
+	}
+
+	public int size() {
+		return size;
+	}
+	
+	/* (non-Javadoc)
+	 * @see java.lang.Object#toString()
+	 */
+	public String toString() {
+		StringBuffer s = new StringBuffer(getClass().getName() + ":" +size + " [");
+		for (int i = 0; i < size; i++) {
+			s.append(list[i]);
+			if(i < size - 1) {
+				s.append(", ");
+			}
+		}
+		s.append("]");
+		return s.toString();
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/RegionFactory.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/RegionFactory.java
new file mode 100644
index 0000000..1315a77
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/RegionFactory.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.parser;
+
+
+
+import org.eclipse.wst.sse.core.internal.parser.ContextRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionContainer;
+
+
+public class RegionFactory {
+
+	public RegionFactory() {
+		super();
+	}
+
+	public ITextRegion createToken(ITextRegionContainer parent, String context, int start, int textLength, int length) {
+		return this.createToken(parent, context, start, textLength, length, null, null);
+	}
+
+	public ITextRegion createToken(ITextRegionContainer parent, String context, int start, int textLength, int length, String lang, String surroundingTag) {
+		ITextRegion newRegion = createToken(context, start, textLength, length);
+		// DW, 4/16/2003 token regions no longer have parents
+		//newRegion.setParent(parent);
+		return newRegion;
+	}
+
+	public ITextRegion createToken(String context, int start, int textLength, int length) {
+		return this.createToken(context, start, textLength, length, null, null);
+	}
+
+	public ITextRegion createToken(String context, int start, int textLength, int length, String lang, String surroundingTag) {
+		ITextRegion newRegion = new ContextRegion(context, start, textLength, length);
+		return newRegion;
+
+
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/XML10Names.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/XML10Names.java
new file mode 100644
index 0000000..af91c63
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/XML10Names.java
@@ -0,0 +1,595 @@
+/* The following code was generated by JFlex 1.4 on 2/25/08 10:25 AM */
+
+/*******************************************************************************
+ * Copyright (c) 2004,2008 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
+ *     kb.huang  - Bug 214416  Dot char is not escaped in XML10Names.jFlex
+ *******************************************************************************/
+/*nlsXXX*/
+package org.eclipse.wst.xml.core.internal.parser;
+
+
+
+
+/**
+ * This class is a scanner generated by 
+ * <a href="http://www.jflex.de/">JFlex</a> 1.4
+ * on 2/25/08 10:25 AM from the specification file
+ * <tt>XML10Names.jflex</tt>
+ */
+public final class XML10Names {
+
+  /** This character denotes the end of file */
+  private static final int YYEOF = -1;
+
+  /** initial size of the lookahead buffer */
+  private static final int ZZ_BUFFERSIZE = 2048;
+
+  /** lexical states */
+  private static final int YYINITIAL = 0;
+
+  /** 
+   * Translates characters to character classes
+   */
+  private static final String ZZ_CMAP_PACKED = 
+    "\12\0\1\3\42\0\1\2\1\2\1\0\12\2\1\1\6\0\32\1"+
+    "\4\0\1\1\1\0\32\1\74\0\1\2\10\0\27\1\1\0\37\1"+
+    "\1\0\72\1\2\0\13\1\2\0\10\1\1\0\65\1\1\0\104\1"+
+    "\11\0\44\1\3\0\2\1\4\0\36\1\70\0\131\1\22\0\7\1"+
+    "\16\0\2\2\56\0\106\2\32\0\2\2\44\0\1\1\1\2\3\1"+
+    "\1\0\1\1\1\0\24\1\1\0\54\1\1\0\7\1\3\0\1\1"+
+    "\1\0\1\1\1\0\1\1\1\0\1\1\1\0\22\1\15\0\14\1"+
+    "\1\0\102\1\1\0\14\1\1\0\44\1\1\0\4\2\11\0\65\1"+
+    "\2\0\2\1\2\0\2\1\3\0\34\1\2\0\10\1\2\0\2\1"+
+    "\67\0\46\1\2\0\1\1\7\0\46\1\12\0\21\2\1\0\27\2"+
+    "\1\0\3\2\1\0\1\2\1\0\2\2\1\0\1\2\13\0\33\1"+
+    "\5\0\3\1\56\0\32\1\5\0\1\2\12\1\10\2\15\0\12\2"+
+    "\6\0\1\2\107\1\2\0\5\1\1\0\17\1\1\0\4\1\1\0"+
+    "\1\1\17\2\2\1\2\2\1\0\4\2\2\0\12\2\u0207\0\3\2"+
+    "\1\0\65\1\2\0\1\2\1\1\20\2\3\0\4\2\3\0\12\1"+
+    "\2\2\2\0\12\2\21\0\3\2\1\0\10\1\2\0\2\1\2\0"+
+    "\26\1\1\0\7\1\1\0\1\1\3\0\4\1\2\0\1\2\1\0"+
+    "\7\2\2\0\2\2\2\0\3\2\11\0\1\2\4\0\2\1\1\0"+
+    "\3\1\2\2\2\0\12\2\2\1\20\0\1\2\2\0\6\1\4\0"+
+    "\2\1\2\0\26\1\1\0\7\1\1\0\2\1\1\0\2\1\1\0"+
+    "\2\1\2\0\1\2\1\0\5\2\4\0\2\2\2\0\3\2\13\0"+
+    "\4\1\1\0\1\1\7\0\12\2\2\2\3\1\14\0\3\2\1\0"+
+    "\7\1\1\0\1\1\1\0\3\1\1\0\26\1\1\0\7\1\1\0"+
+    "\2\1\1\0\5\1\2\0\1\2\1\1\10\2\1\0\3\2\1\0"+
+    "\3\2\22\0\1\1\5\0\12\2\21\0\3\2\1\0\10\1\2\0"+
+    "\2\1\2\0\26\1\1\0\7\1\1\0\2\1\2\0\4\1\2\0"+
+    "\1\2\1\1\6\2\3\0\2\2\2\0\3\2\10\0\2\2\4\0"+
+    "\2\1\1\0\3\1\4\0\12\2\22\0\2\2\1\0\6\1\3\0"+
+    "\3\1\1\0\4\1\3\0\2\1\1\0\1\1\1\0\2\1\3\0"+
+    "\2\1\3\0\3\1\3\0\10\1\1\0\3\1\4\0\5\2\3\0"+
+    "\3\2\1\0\4\2\11\0\1\2\17\0\11\2\21\0\3\2\1\0"+
+    "\10\1\1\0\3\1\1\0\27\1\1\0\12\1\1\0\5\1\4\0"+
+    "\7\2\1\0\3\2\1\0\4\2\7\0\2\2\11\0\2\1\4\0"+
+    "\12\2\22\0\2\2\1\0\10\1\1\0\3\1\1\0\27\1\1\0"+
+    "\12\1\1\0\5\1\4\0\7\2\1\0\3\2\1\0\4\2\7\0"+
+    "\2\2\7\0\1\1\1\0\2\1\4\0\12\2\22\0\2\2\1\0"+
+    "\10\1\1\0\3\1\1\0\27\1\1\0\20\1\4\0\6\2\2\0"+
+    "\3\2\1\0\4\2\11\0\1\2\10\0\2\1\4\0\12\2\221\0"+
+    "\56\1\1\0\1\1\1\2\2\1\7\2\5\0\6\1\1\2\10\2"+
+    "\1\0\12\2\47\0\2\1\1\0\1\1\2\0\2\1\1\0\1\1"+
+    "\2\0\1\1\6\0\4\1\1\0\7\1\1\0\3\1\1\0\1\1"+
+    "\1\0\1\1\2\0\2\1\1\0\2\1\1\0\1\1\1\2\2\1"+
+    "\6\2\1\0\2\2\1\1\2\0\5\1\1\0\1\2\1\0\6\2"+
+    "\2\0\12\2\76\0\2\2\6\0\12\2\13\0\1\2\1\0\1\2"+
+    "\1\0\1\2\4\0\2\2\10\1\1\0\41\1\7\0\24\2\1\0"+
+    "\6\2\4\0\6\2\1\0\1\2\1\0\25\2\3\0\7\2\1\0"+
+    "\1\2\346\0\46\1\12\0\47\1\11\0\1\1\1\0\2\1\1\0"+
+    "\3\1\1\0\1\1\1\0\2\1\1\0\5\1\51\0\1\1\1\0"+
+    "\1\1\1\0\1\1\13\0\1\1\1\0\1\1\1\0\1\1\3\0"+
+    "\2\1\3\0\1\1\5\0\3\1\1\0\1\1\1\0\1\1\1\0"+
+    "\1\1\1\0\1\1\3\0\2\1\3\0\2\1\1\0\1\1\50\0"+
+    "\1\1\11\0\1\1\2\0\1\1\2\0\2\1\7\0\2\1\1\0"+
+    "\1\1\1\0\7\1\50\0\1\1\4\0\1\1\10\0\1\1\u0c06\0"+
+    "\234\1\4\0\132\1\6\0\26\1\2\0\6\1\2\0\46\1\2\0"+
+    "\6\1\2\0\10\1\1\0\1\1\1\0\1\1\1\0\1\1\1\0"+
+    "\37\1\2\0\65\1\1\0\7\1\1\0\1\1\3\0\3\1\1\0"+
+    "\7\1\3\0\4\1\2\0\6\1\4\0\15\1\5\0\3\1\1\0"+
+    "\7\1\323\0\15\2\4\0\1\2\104\0\1\1\3\0\2\1\2\0"+
+    "\1\1\121\0\3\1\u0e82\0\1\2\1\0\1\1\31\0\11\1\6\2"+
+    "\1\0\5\2\13\0\124\1\4\0\2\2\2\0\2\2\2\0\132\1"+
+    "\1\0\3\2\6\0\50\1\u1cd3\0\u51a6\1\u0c5a\0\u2ba4\1\u285c\0";
+
+  /** 
+   * Translates characters to character classes
+   */
+  private static final char [] ZZ_CMAP = zzUnpackCMap(ZZ_CMAP_PACKED);
+
+  /** 
+   * Translates DFA states to action switch labels.
+   */
+  private static final int [] ZZ_ACTION = zzUnpackAction();
+
+  private static final String ZZ_ACTION_PACKED_0 =
+    "\1\0\1\1\1\2\1\3";
+
+  private static int [] zzUnpackAction() {
+    int [] result = new int[4];
+    int offset = 0;
+    offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result);
+    return result;
+  }
+
+  private static int zzUnpackAction(String packed, int offset, int [] result) {
+    int i = 0;       /* index in packed string  */
+    int j = offset;  /* index in unpacked array */
+    int l = packed.length();
+    while (i < l) {
+      int count = packed.charAt(i++);
+      int value = packed.charAt(i++);
+      do result[j++] = value; while (--count > 0);
+    }
+    return j;
+  }
+
+
+  /** 
+   * Translates a state to a row index in the transition table
+   */
+  private static final int [] ZZ_ROWMAP = zzUnpackRowMap();
+
+  private static final String ZZ_ROWMAP_PACKED_0 =
+    "\0\0\0\4\0\10\0\14";
+
+  private static int [] zzUnpackRowMap() {
+    int [] result = new int[4];
+    int offset = 0;
+    offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result);
+    return result;
+  }
+
+  private static int zzUnpackRowMap(String packed, int offset, int [] result) {
+    int i = 0;  /* index in packed string  */
+    int j = offset;  /* index in unpacked array */
+    int l = packed.length();
+    while (i < l) {
+      int high = packed.charAt(i++) << 16;
+      result[j++] = high | packed.charAt(i++);
+    }
+    return j;
+  }
+
+  /** 
+   * The transition table of the DFA
+   */
+  private static final int ZZ_TRANS [] = {
+    1, 2, 1, -1, -1, -1, -1, -1, 3, 2, 
+    2, -1, 3, 3, 3, -1
+  };
+
+  /* error codes */
+  private static final int ZZ_UNKNOWN_ERROR = 0;
+  private static final int ZZ_NO_MATCH = 1;
+//  private static final int ZZ_PUSHBACK_2BIG = 2;
+
+  /* error messages for the codes above */
+  private static final String ZZ_ERROR_MSG[] = {
+    "Unkown internal scanner error",
+    "Error: could not match input",
+    "Error: pushback value was too large"
+  };
+
+  /**
+   * ZZ_ATTRIBUTE[aState] contains the attributes of state <code>aState</code>
+   */
+  private static final int [] ZZ_ATTRIBUTE = zzUnpackAttribute();
+
+  private static final String ZZ_ATTRIBUTE_PACKED_0 =
+    "\1\0\1\11\2\1";
+
+  private static int [] zzUnpackAttribute() {
+    int [] result = new int[4];
+    int offset = 0;
+    offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result);
+    return result;
+  }
+
+  private static int zzUnpackAttribute(String packed, int offset, int [] result) {
+    int i = 0;       /* index in packed string  */
+    int j = offset;  /* index in unpacked array */
+    int l = packed.length();
+    while (i < l) {
+      int count = packed.charAt(i++);
+      int value = packed.charAt(i++);
+      do result[j++] = value; while (--count > 0);
+    }
+    return j;
+  }
+
+  /** the input device */
+  private java.io.Reader zzReader;
+
+  /** the current state of the DFA */
+  private int zzState;
+
+  /** the current lexical state */
+  private int zzLexicalState = YYINITIAL;
+
+  /** this buffer contains the current text to be matched and is
+      the source of the yytext() string */
+  private char zzBuffer[] = new char[ZZ_BUFFERSIZE];
+
+  /** the textposition at the last accepting state */
+  private int zzMarkedPos;
+
+  /** the textposition at the last state to be included in yytext */
+  private int zzPushbackPos;
+
+  /** the current text position in the buffer */
+  private int zzCurrentPos;
+
+  /** startRead marks the beginning of the yytext() string in the buffer */
+  private int zzStartRead;
+
+  /** endRead marks the last character in the buffer, that has been read
+      from input */
+  private int zzEndRead;
+
+  /** number of newlines encountered up to the start of the matched text */
+//  private int yyline;
+
+  /** the number of characters up to the start of the matched text */
+//  private int yychar;
+
+  /**
+   * the number of characters from the last newline up to the start of the 
+   * matched text
+   */
+//  private int yycolumn;
+
+  /** 
+   * zzAtBOL == true <=> the scanner is currently at the beginning of a line
+   */
+//  private boolean zzAtBOL = true;
+
+  /** zzAtEOF == true <=> the scanner is at the EOF */
+  private boolean zzAtEOF;
+
+  /* user code: */
+        boolean result;
+        /**
+         * Creates a new scanner
+         */
+        public XML10Names() {
+                this.zzReader = null;
+        }
+
+        public boolean isValidXML10Name(String stringToCheck) {
+                boolean result = false;
+                yyreset(new java.io.StringReader(stringToCheck));
+                try {
+                        result = isValidXML10Name();
+                }
+                catch (java.io.IOException e) {
+                        // should be impossible with strings, but if occurs, just means
+                        // "not"
+                        result = false;
+                }
+                return result;
+        }
+
+
+
+  /**
+   * Creates a new scanner
+   * There is also a java.io.InputStream version of this constructor.
+   *
+   * @param   in  the java.io.Reader to read input from.
+   */
+  public XML10Names(java.io.Reader in) {
+    this.zzReader = in;
+  }
+
+  /**
+   * Creates a new scanner.
+   * There is also java.io.Reader version of this constructor.
+   *
+   * @param   in  the java.io.Inputstream to read input from.
+   */
+  public XML10Names(java.io.InputStream in) {
+    this(new java.io.InputStreamReader(in));
+  }
+
+  /** 
+   * Unpacks the compressed character translation table.
+   *
+   * @param packed   the packed character translation table
+   * @return         the unpacked character translation table
+   */
+  private static char [] zzUnpackCMap(String packed) {
+    char [] map = new char[0x10000];
+    int i = 0;  /* index in packed string  */
+    int j = 0;  /* index in unpacked array */
+    while (i < 1218) {
+      int  count = packed.charAt(i++);
+      char value = packed.charAt(i++);
+      do map[j++] = value; while (--count > 0);
+    }
+    return map;
+  }
+
+
+  /**
+   * Refills the input buffer.
+   *
+   * @return      <code>false</code>, iff there was new input.
+   * 
+   * @exception   java.io.IOException  if any I/O-Error occurs
+   */
+  private boolean zzRefill() throws java.io.IOException {
+
+    /* first: make room (if you can) */
+    if (zzStartRead > 0) {
+      System.arraycopy(zzBuffer, zzStartRead,
+                       zzBuffer, 0,
+                       zzEndRead-zzStartRead);
+
+      /* translate stored positions */
+      zzEndRead-= zzStartRead;
+      zzCurrentPos-= zzStartRead;
+      zzMarkedPos-= zzStartRead;
+      zzPushbackPos-= zzStartRead;
+      zzStartRead = 0;
+    }
+
+    /* is the buffer big enough? */
+    if (zzCurrentPos >= zzBuffer.length) {
+      /* if not: blow it up */
+      char newBuffer[] = new char[zzCurrentPos*2];
+      System.arraycopy(zzBuffer, 0, newBuffer, 0, zzBuffer.length);
+      zzBuffer = newBuffer;
+    }
+
+    /* finally: fill the buffer with new input */
+    int numRead = zzReader.read(zzBuffer, zzEndRead,
+                                            zzBuffer.length-zzEndRead);
+
+    if (numRead < 0) {
+      return true;
+    }
+    else {
+      zzEndRead+= numRead;
+      return false;
+    }
+  }
+
+    
+  /**
+   * Closes the input stream.
+   */
+//  private final void yyclose() throws java.io.IOException {
+//    zzAtEOF = true;            /* indicate end of file */
+//    zzEndRead = zzStartRead;  /* invalidate buffer    */
+//
+//    if (zzReader != null)
+//      zzReader.close();
+//  }
+
+
+  /**
+   * Resets the scanner to read from a new input stream.
+   * Does not close the old reader.
+   *
+   * All internal variables are reset, the old input stream 
+   * <b>cannot</b> be reused (internal buffer is discarded and lost).
+   * Lexical state is set to <tt>ZZ_INITIAL</tt>.
+   *
+   * @param reader   the new input stream 
+   */
+  private final void yyreset(java.io.Reader reader) {
+    zzReader = reader;
+//    zzAtBOL  = true;
+    zzAtEOF  = false;
+    zzEndRead = zzStartRead = 0;
+    zzCurrentPos = zzMarkedPos = zzPushbackPos = 0;
+//    yyline = yychar = yycolumn = 0;
+    zzLexicalState = YYINITIAL;
+  }
+
+
+  /**
+   * Returns the current lexical state.
+   */
+//  private final int yystate() {
+//    return zzLexicalState;
+//  }
+
+
+  /**
+   * Enters a new lexical state
+   *
+   * @param newState the new lexical state
+   */
+//  private final void yybegin(int newState) {
+//    zzLexicalState = newState;
+//  }
+
+
+  /**
+   * Returns the text matched by the current regular expression.
+   */
+//  private final String yytext() {
+//    return new String( zzBuffer, zzStartRead, zzMarkedPos-zzStartRead );
+//  }
+
+
+  /**
+   * Returns the character at position <tt>pos</tt> from the 
+   * matched text. 
+   * 
+   * It is equivalent to yytext().charAt(pos), but faster
+   *
+   * @param pos the position of the character to fetch. 
+   *            A value from 0 to yylength()-1.
+   *
+   * @return the character at position pos
+   */
+//  private final char yycharat(int pos) {
+//    return zzBuffer[zzStartRead+pos];
+//  }
+
+
+  /**
+   * Returns the length of the matched text region.
+   */
+//  private final int yylength() {
+//    return zzMarkedPos-zzStartRead;
+//  }
+
+
+  /**
+   * Reports an error that occured while scanning.
+   *
+   * In a wellformed scanner (no or only correct usage of 
+   * yypushback(int) and a match-all fallback rule) this method 
+   * will only be called with things that "Can't Possibly Happen".
+   * If this method is called, something is seriously wrong
+   * (e.g. a JFlex bug producing a faulty scanner etc.).
+   *
+   * Usual syntax/scanner level error handling should be done
+   * in error fallback rules.
+   *
+   * @param   errorCode  the code of the errormessage to display
+   */
+  private void zzScanError(int errorCode) {
+    String message;
+    try {
+      message = ZZ_ERROR_MSG[errorCode];
+    }
+    catch (ArrayIndexOutOfBoundsException e) {
+      message = ZZ_ERROR_MSG[ZZ_UNKNOWN_ERROR];
+    }
+
+    throw new Error(message);
+  } 
+
+
+  /**
+   * Pushes the specified amount of characters back into the input stream.
+   *
+   * They will be read again by then next call of the scanning method
+   *
+   * @param number  the number of characters to be read again.
+   *                This number must not be greater than yylength()!
+   */
+//  private void yypushback(int number)  {
+//    if ( number > yylength() )
+//      zzScanError(ZZ_PUSHBACK_2BIG);
+//
+//    zzMarkedPos -= number;
+//  }
+
+
+  /**
+   * Resumes scanning until the next regular expression is matched,
+   * the end of input is encountered or an I/O-Error occurs.
+   *
+   * @return      the next token
+   * @exception   java.io.IOException  if any I/O-Error occurs
+   */
+  private boolean isValidXML10Name() throws java.io.IOException {
+    int zzInput;
+    int zzAction;
+
+    // cached fields:
+    int zzCurrentPosL;
+    int zzMarkedPosL;
+    int zzEndReadL = zzEndRead;
+    char [] zzBufferL = zzBuffer;
+    char [] zzCMapL = ZZ_CMAP;
+
+    int [] zzTransL = ZZ_TRANS;
+    int [] zzRowMapL = ZZ_ROWMAP;
+    int [] zzAttrL = ZZ_ATTRIBUTE;
+
+    while (true) {
+      zzMarkedPosL = zzMarkedPos;
+
+      zzAction = -1;
+
+      zzCurrentPosL = zzCurrentPos = zzStartRead = zzMarkedPosL;
+  
+      zzState = zzLexicalState;
+
+
+      zzForAction: {
+        while (true) {
+    
+          if (zzCurrentPosL < zzEndReadL)
+            zzInput = zzBufferL[zzCurrentPosL++];
+          else if (zzAtEOF) {
+            zzInput = YYEOF;
+            break zzForAction;
+          }
+          else {
+            // store back cached positions
+            zzCurrentPos  = zzCurrentPosL;
+            zzMarkedPos   = zzMarkedPosL;
+            boolean eof = zzRefill();
+            // get translated positions and possibly new buffer
+            zzCurrentPosL  = zzCurrentPos;
+            zzMarkedPosL   = zzMarkedPos;
+            zzBufferL      = zzBuffer;
+            zzEndReadL     = zzEndRead;
+            if (eof) {
+              zzInput = YYEOF;
+              break zzForAction;
+            }
+            else {
+              zzInput = zzBufferL[zzCurrentPosL++];
+            }
+          }
+          int zzNext = zzTransL[ zzRowMapL[zzState] + zzCMapL[zzInput] ];
+          if (zzNext == -1) break zzForAction;
+          zzState = zzNext;
+
+          int zzAttributes = zzAttrL[zzState];
+          if ( (zzAttributes & 1) == 1 ) {
+            zzAction = zzState;
+            zzMarkedPosL = zzCurrentPosL;
+            if ( (zzAttributes & 8) == 8 ) break zzForAction;
+          }
+
+        }
+      }
+
+      // store back cached position
+      zzMarkedPos = zzMarkedPosL;
+
+      switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) {
+        case 1: 
+          { return false; /* matched wild */
+          }
+        case 4: break;
+        case 2: 
+          { return true; /* exact name */
+          }
+        case 5: break;
+        case 3: 
+          { return false; /* more than name */
+          }
+        case 6: break;
+        default: 
+          if (zzInput == YYEOF && zzStartRead == zzCurrentPos) {
+            zzAtEOF = true;
+              { {return false; /* hit end with no match */} }
+          } 
+          else {
+            zzScanError(ZZ_NO_MATCH);
+          }
+      }
+    }
+  }
+
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/XMLSourceParser.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/XMLSourceParser.java
new file mode 100644
index 0000000..4a8791c
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/XMLSourceParser.java
@@ -0,0 +1,645 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.parser;
+
+
+
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.wst.sse.core.internal.document.DocumentReader;
+import org.eclipse.wst.sse.core.internal.ltk.parser.BlockMarker;
+import org.eclipse.wst.sse.core.internal.ltk.parser.BlockTagParser;
+import org.eclipse.wst.sse.core.internal.ltk.parser.BlockTokenizer;
+import org.eclipse.wst.sse.core.internal.ltk.parser.RegionParser;
+import org.eclipse.wst.sse.core.internal.ltk.parser.StructuredDocumentRegionHandler;
+import org.eclipse.wst.sse.core.internal.ltk.parser.StructuredDocumentRegionParser;
+import org.eclipse.wst.sse.core.internal.ltk.parser.StructuredDocumentRegionParserExtension;
+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.ITextRegionContainer;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList;
+import org.eclipse.wst.sse.core.internal.text.CharSequenceReader;
+import org.eclipse.wst.sse.core.internal.text.IRegionComparible;
+import org.eclipse.wst.sse.core.internal.util.Debug;
+import org.eclipse.wst.xml.core.internal.Logger;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+
+
+/**
+ * Takes input from the HTMLTokenizer and creates a tag list
+ */
+
+public class XMLSourceParser implements RegionParser, BlockTagParser, StructuredDocumentRegionParser, IRegionComparible, StructuredDocumentRegionParserExtension {
+	// made public to aid access from inner classes in hierarchy.
+	// TODO: in future, figure out how to solve without exposing data.
+	public CharSequence fCharSequenceSource = null;
+	private IDocument fDocumentInput;
+	protected int fOffset = 0;
+	// DMW: 2/12/03. Removed some state data, since not really needed,
+	// and since it added a lot to overhead (since so many regions are
+	// created.
+	// protected IStructuredDocumentRegion fCurrentNode = null;
+	// protected IStructuredDocumentRegion fNodes = null;
+	// protected List fRegions = null;
+	// protected Object fInput = null;
+	protected String fStringInput = null;
+	protected List fStructuredDocumentRegionHandlers;
+
+	protected BlockTokenizer fTokenizer = null;
+	protected long startTime;
+	protected long stopTime;
+
+	/**
+	 * HTMLSourceParser constructor comment.
+	 */
+	public XMLSourceParser() {
+		super();
+		fStructuredDocumentRegionHandlers = new ArrayList();
+	}
+
+	/**
+	 * This is a simple utility to count nodes. Used only for debug
+	 * statements.
+	 */
+	protected int _countNodes(IStructuredDocumentRegion nodes) {
+		int result = 0;
+		IStructuredDocumentRegion countNode = nodes;
+		while (countNode != null) {
+			result++;
+			countNode = countNode.getNext();
+		}
+		return result;
+	}
+
+	public void addBlockMarker(BlockMarker marker) {
+		getTokenizer().addBlockMarker(marker);
+	}
+
+	public synchronized void addStructuredDocumentRegionHandler(StructuredDocumentRegionHandler handler) {
+		if (fStructuredDocumentRegionHandlers == null)
+			fStructuredDocumentRegionHandlers = new ArrayList();
+		synchronized (fStructuredDocumentRegionHandlers) {
+			fStructuredDocumentRegionHandlers.add(handler);
+		}
+	}
+
+	public void beginBlockScan(String newTagName) {
+		getTokenizer().beginBlockTagScan(newTagName);
+	}
+
+	/**
+	 * @return IStructuredDocumentRegion
+	 */
+	protected IStructuredDocumentRegion createStructuredDocumentRegion(String type) {
+		IStructuredDocumentRegion newNode = null;
+		if (type == DOMRegionContext.BLOCK_TEXT)
+			newNode = XMLStructuredRegionFactory.createRegion(XMLStructuredRegionFactory.XML_BLOCK);
+		else
+			newNode = XMLStructuredRegionFactory.createRegion(XMLStructuredRegionFactory.XML);
+		return newNode;
+	}
+
+	protected void fireNodeParsed(IStructuredDocumentRegion fCurrentNode) {
+		/*
+		 * Never let an Exceptions from foreign code interfere with completion
+		 * of parsing. To get an exception here is definitely a program error
+		 * somewhere, but we can't afford to interrupt the flow of control. or
+		 * backwards typing can result!
+		 * 
+		 * Protect the user's data above everything.
+		 */
+		Object[] handlers = null;
+		synchronized (fStructuredDocumentRegionHandlers) {
+			if (fStructuredDocumentRegionHandlers == null)
+				return;
+
+			handlers = fStructuredDocumentRegionHandlers.toArray();
+		}
+		if (fCurrentNode != null && handlers != null) {
+			for (int i = 0; i < handlers.length; i++) {
+				try {
+					((StructuredDocumentRegionHandler) handlers[i]).nodeParsed(fCurrentNode);
+				}
+				catch (Exception e) {
+					Logger.log(Logger.ERROR, "Error occurred while firing Node Parsed event", e); //$NON-NLS-1$
+				}
+			}
+		}
+	}
+
+	public BlockMarker getBlockMarker(String tagName) {
+		List markers = getTokenizer().getBlockMarkers();
+		for (int i = 0; i < markers.size(); i++) {
+			BlockMarker marker = (BlockMarker) markers.get(i);
+			if (marker.isCaseSensitive()) {
+				if (marker.getTagName().equals(tagName))
+					return marker;
+			}
+			else {
+				if (marker.getTagName().equalsIgnoreCase(tagName))
+					return marker;
+			}
+		}
+		return null;
+	}
+
+	public List getBlockMarkers() {
+		return getTokenizer().getBlockMarkers();
+	}
+
+	/**
+	 * @return IStructuredDocumentRegion
+	 */
+	public IStructuredDocumentRegion getDocumentRegions() {
+		IStructuredDocumentRegion headnode = null;
+		if (headnode == null) {
+			if (Debug.perfTest) {
+				startTime = System.currentTimeMillis();
+			}
+			headnode = parseNodes();
+			if (Debug.perfTest) {
+				stopTime = System.currentTimeMillis();
+				System.out.println(" -- creating nodes of IStructuredDocument -- "); //$NON-NLS-1$
+				System.out.println(" Time parse and init all regions: " + (stopTime - startTime) + " (msecs)"); //$NON-NLS-2$//$NON-NLS-1$
+				// System.out.println(" for " + fRegions.size() + "
+				// Regions");//$NON-NLS-2$//$NON-NLS-1$
+				System.out.println("      and " + _countNodes(headnode) + " Nodes"); //$NON-NLS-2$//$NON-NLS-1$
+			}
+		}
+		return headnode;
+	}
+
+	protected ITextRegion getNextRegion() {
+		ITextRegion region = null;
+		try {
+			region = getTokenizer().getNextToken();
+			// DMW: 2/12/03 Removed state
+			// if (region != null) {
+			// fRegions.add(region);
+			// }
+			return region;
+		}
+		catch (StackOverflowError e) {
+			Logger.logException(getClass().getName() + ": input could not be parsed correctly at position " + getTokenizer().getOffset(), e); //$NON-NLS-1$
+			throw e;
+		}
+		catch (Exception e) {
+			Logger.logException(getClass().getName() + ": input could not be parsed correctly at position " + getTokenizer().getOffset() + " (" + e.getLocalizedMessage() + ")", e); //$NON-NLS-3$//$NON-NLS-2$//$NON-NLS-1$
+		}
+		return null;
+	}
+
+	/**
+	 * Return the full list of known regions. Typically getNodes should be
+	 * used instead of this method.
+	 */
+	public List getRegions() {
+		IStructuredDocumentRegion headNode = null;
+		if (!getTokenizer().isEOF()) {
+			headNode = getDocumentRegions();
+			// throw new IllegalStateException("parsing has not finished");
+		}
+		// for memory recovery, we assume if someone
+		// requests all regions, we can reset our big
+		// memory consuming objects
+		// but the new "getRegions" method is then more expensive.
+		// I don't think its used much, though.
+		List localRegionsList = getRegions(headNode);
+		primReset();
+		return localRegionsList;
+	}
+
+	/**
+	 * Method getRegions.
+	 * 
+	 * @param headNode
+	 * @return List
+	 */
+	protected List getRegions(IStructuredDocumentRegion headNode) {
+		List allRegions = new ArrayList();
+		IStructuredDocumentRegion currentNode = headNode;
+		while (currentNode != null) {
+			ITextRegionList nodeRegions = currentNode.getRegions();
+			for (int i = 0; i < nodeRegions.size(); i++) {
+				allRegions.add(nodeRegions.get(i));
+			}
+			currentNode = currentNode.getNext();
+		}
+		return allRegions;
+	}
+
+	/**
+	 * @deprecated - use the add/remove methods instead
+	 * @return java.util.List
+	 */
+	public List getStructuredDocumentRegionHandlers() {
+		if (fStructuredDocumentRegionHandlers == null) {
+			fStructuredDocumentRegionHandlers = new ArrayList(0);
+		}
+		return fStructuredDocumentRegionHandlers;
+	}
+
+	/**
+	 * Returns text from the current input. Text is only valid before
+	 * getNodes() has been called and only when a raw String or DocumentReader
+	 * is given as the input.
+	 */
+	public String getText(int offset, int length) {
+		String text = null;
+		if (fCharSequenceSource != null) {
+			int start = fOffset + offset;
+			int end = start + length;
+			text = fCharSequenceSource.subSequence(start, end).toString();
+		}
+		else if (fDocumentInput != null) {
+			try {
+				text = fDocumentInput.get(offset, length);
+			}
+			catch (BadLocationException e) {
+				text = ""; //$NON-NLS-1$
+			}
+		}
+		else {
+			if (fStringInput == null || fStringInput.length() == 0 || offset + length > fStringInput.length() || offset < 0) {
+				text = ""; //$NON-NLS-1$
+			}
+			else {
+				// offset is entirely valid during parsing as the parse
+				// numbers haven't been adjusted.
+				text = fStringInput.substring(offset, offset + length);
+			}
+		}
+		return text;
+	}
+
+	protected BlockTokenizer getTokenizer() {
+		if (fTokenizer == null) {
+			fTokenizer = new XMLTokenizer();
+		}
+		return fTokenizer;
+	}
+
+
+	public RegionParser newInstance() {
+		XMLSourceParser newInstance = new XMLSourceParser();
+		newInstance.setTokenizer(getTokenizer().newInstance());
+		return newInstance;
+	}
+
+	protected IStructuredDocumentRegion parseNodes() {
+		// regions are initially reported as complete offsets within the
+		// scanned input
+		// they are adjusted here to be indexes from the currentNode's start
+		// offset
+		IStructuredDocumentRegion headNode = null;
+		IStructuredDocumentRegion lastNode = null;
+		ITextRegion region = null;
+		IStructuredDocumentRegion currentNode = null;
+		String type = null;
+
+		while ((region = getNextRegion()) != null) {
+			type = region.getType();
+			// these types (might) demand a IStructuredDocumentRegion for each
+			// of them
+			if (type == DOMRegionContext.BLOCK_TEXT) {
+				if (currentNode != null && currentNode.getLastRegion().getType() == DOMRegionContext.BLOCK_TEXT) {
+					// multiple block texts indicated embedded containers; no
+					// new IStructuredDocumentRegion
+					currentNode.addRegion(region);
+					currentNode.setLength(region.getStart() + region.getLength() - currentNode.getStart());
+					region.adjustStart(-currentNode.getStart());
+					// DW 4/16/2003 regions no longer have parents
+					// region.setParent(currentNode);
+				}
+				else {
+					// not continuing a IStructuredDocumentRegion
+					if (currentNode != null) {
+						// ensure that any existing node is at least
+						// terminated
+						if (!currentNode.isEnded()) {
+							currentNode.setLength(region.getStart() - currentNode.getStart());
+							// fCurrentNode.setTextLength(region.getStart() -
+							// fCurrentNode.getStart());
+						}
+						lastNode = currentNode;
+					}
+					fireNodeParsed(currentNode);
+					currentNode = createStructuredDocumentRegion(type);
+					if (lastNode != null) {
+						lastNode.setNext(currentNode);
+					}
+					currentNode.setPrevious(lastNode);
+					currentNode.setStart(region.getStart());
+					currentNode.setLength(region.getStart() + region.getLength() - currentNode.getStart());
+					currentNode.setEnded(true);
+					region.adjustStart(-currentNode.getStart());
+					currentNode.addRegion(region);
+					// DW 4/16/2003 regions no longer have parents
+					// region.setParent(currentNode);
+				}
+			}
+			// the following contexts OPEN new StructuredDocumentRegions
+			else if ((currentNode != null && currentNode.isEnded()) || (type == DOMRegionContext.XML_CONTENT) || (type == DOMRegionContext.XML_CHAR_REFERENCE) || (type == DOMRegionContext.XML_ENTITY_REFERENCE) || (type == DOMRegionContext.XML_PI_OPEN) || (type == DOMRegionContext.XML_TAG_OPEN) || (type == DOMRegionContext.XML_END_TAG_OPEN) || (type == DOMRegionContext.XML_COMMENT_OPEN) || (type == DOMRegionContext.XML_CDATA_OPEN) || (type == DOMRegionContext.XML_DECLARATION_OPEN)) {
+				if (currentNode != null) {
+					// ensure that any existing node is at least terminated
+					if (!currentNode.isEnded()) {
+						currentNode.setLength(region.getStart() - currentNode.getStart());
+						// fCurrentNode.setTextLength(region.getStart() -
+						// fCurrentNode.getStart());
+					}
+					lastNode = currentNode;
+				}
+				fireNodeParsed(currentNode);
+				currentNode = createStructuredDocumentRegion(type);
+				if (lastNode != null) {
+					lastNode.setNext(currentNode);
+				}
+				currentNode.setPrevious(lastNode);
+				currentNode.setStart(region.getStart());
+				currentNode.addRegion(region);
+				currentNode.setLength(region.getStart() + region.getLength() - currentNode.getStart());
+				region.adjustStart(-currentNode.getStart());
+				// DW 4/16/2003 regions no longer have parents
+				// region.setParent(currentNode);
+			}
+			// the following contexts neither open nor close
+			// StructuredDocumentRegions; just add to them
+			else if ((type == DOMRegionContext.XML_TAG_NAME) || (type == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) || (type == DOMRegionContext.XML_TAG_ATTRIBUTE_EQUALS) || (type == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) || (type == DOMRegionContext.XML_COMMENT_TEXT) || (type == DOMRegionContext.XML_PI_CONTENT) || (type == DOMRegionContext.XML_DOCTYPE_INTERNAL_SUBSET)) {
+				currentNode.addRegion(region);
+				currentNode.setLength(region.getStart() + region.getLength() - currentNode.getStart());
+				region.adjustStart(-currentNode.getStart());
+				// DW 4/16/2003 regions no longer have parents
+				// region.setParent(currentNode);
+			}
+			// the following contexts close off StructuredDocumentRegions
+			// cleanly
+			else if ((type == DOMRegionContext.XML_PI_CLOSE) || (type == DOMRegionContext.XML_TAG_CLOSE) || (type == DOMRegionContext.XML_EMPTY_TAG_CLOSE) || (type == DOMRegionContext.XML_COMMENT_CLOSE) || (type == DOMRegionContext.XML_DECLARATION_CLOSE) || (type == DOMRegionContext.XML_CDATA_CLOSE)) {
+				currentNode.setEnded(true);
+				currentNode.setLength(region.getStart() + region.getLength() - currentNode.getStart());
+				currentNode.addRegion(region);
+				region.adjustStart(-currentNode.getStart());
+				// DW 4/16/2003 regions no longer have parents
+				// region.setParent(currentNode);
+			}
+			// this is extremely rare, but valid
+			else if (type == DOMRegionContext.WHITE_SPACE) {
+				ITextRegion lastRegion = currentNode.getLastRegion();
+				// pack the embedded container with this region
+				if (lastRegion instanceof ITextRegionContainer) {
+					ITextRegionContainer container = (ITextRegionContainer) lastRegion;
+					container.getRegions().add(region);
+					// containers must have parent set ...
+					// setting for EACH subregion is redundent, but not sure
+					// where else to do, so will do here for now.
+					container.setParent(currentNode);
+					// DW 4/16/2003 regions no longer have parents
+					// region.setParent(container);
+					region.adjustStart(container.getLength() - region.getStart());
+				}
+				currentNode.getLastRegion().adjustLength(region.getLength());
+				currentNode.adjustLength(region.getLength());
+			}
+			else if (type == DOMRegionContext.UNDEFINED && currentNode != null) {
+				// skip on a very-first region situation as the default
+				// behavior is good enough
+				// combine with previous if also undefined
+				if (currentNode.getLastRegion() != null && currentNode.getLastRegion().getType() == DOMRegionContext.UNDEFINED) {
+					currentNode.getLastRegion().adjustLength(region.getLength());
+					currentNode.adjustLength(region.getLength());
+				}
+				// previous wasn't undefined
+				else {
+					currentNode.addRegion(region);
+					currentNode.setLength(region.getStart() + region.getLength() - currentNode.getStart());
+					region.adjustStart(-currentNode.getStart());
+				}
+			}
+			else {
+				// if an unknown type is the first region in the document,
+				// ensure that a node exists
+				if (currentNode == null) {
+					currentNode = createStructuredDocumentRegion(type);
+					currentNode.setStart(region.getStart());
+				}
+				currentNode.addRegion(region);
+				currentNode.setLength(region.getStart() + region.getLength() - currentNode.getStart());
+				region.adjustStart(-currentNode.getStart());
+				// DW 4/16/2003 regions no longer have parents
+				// region.setParent(currentNode);
+				if (Debug.debugTokenizer)
+					System.out.println(getClass().getName() + " found region of not specifically handled type " + region.getType() + " @ " + region.getStart() + "[" + region.getLength() + "]"); //$NON-NLS-4$//$NON-NLS-3$//$NON-NLS-2$//$NON-NLS-1$
+				//$NON-NLS-3$//$NON-NLS-2$//$NON-NLS-1$
+			}
+
+			// these regions also get their own node, so close them cleanly
+			// NOTE: these regions have new StructuredDocumentRegions created
+			// for them above; it may
+			// be more readable if that is handled here as well, but the
+			// current layout
+			// ensures that they open StructuredDocumentRegions the same way
+			if ((type == DOMRegionContext.XML_CONTENT) || (type == DOMRegionContext.XML_CHAR_REFERENCE) || (type == DOMRegionContext.XML_ENTITY_REFERENCE)) {
+				currentNode.setEnded(true);
+			}
+			if (headNode == null && currentNode != null) {
+				headNode = currentNode;
+			}
+		}
+		if (currentNode != null) {
+			fireNodeParsed(currentNode);
+			currentNode.setPrevious(lastNode);
+		}
+		// fStringInput = null;
+		primReset();
+		return headNode;
+	}
+
+	protected void primReset() {
+		// fNodes = null;
+		// fRegions = null;
+		// fInput = null;
+		fStringInput = null;
+		fCharSequenceSource = null;
+		fDocumentInput = null;
+		fOffset = 0;
+		// fCurrentNode = null;
+		// DMW: also reset tokenizer so it doesn't hold on
+		// to large arrays
+		getTokenizer().reset(new char[0]);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.wst.sse.core.internal.text.IRegionComparible#regionMatches(int,
+	 *      int, java.lang.String)
+	 */
+	public boolean regionMatches(int offset, int length, String stringToCompare) {
+		// by definition
+		if (stringToCompare == null)
+			return false;
+
+		int ajustedOffset = fOffset + offset;
+		boolean result = false;
+		if (fCharSequenceSource != null && fCharSequenceSource instanceof IRegionComparible) {
+			result = ((IRegionComparible) fCharSequenceSource).regionMatches(ajustedOffset, length, stringToCompare);
+		}
+		else {
+			// old fashioned ways
+			String test = null;
+			if (fCharSequenceSource != null) {
+				test = fCharSequenceSource.subSequence(ajustedOffset, ajustedOffset + length).toString();
+			}
+			else if (fStringInput != null) {
+				test = fStringInput.substring(ajustedOffset, ajustedOffset + length);
+			}
+			result = stringToCompare.equals(test);
+		}
+		return result;
+	}
+
+	public boolean regionMatchesIgnoreCase(int offset, int length, String stringToCompare) {
+		// by definition
+		if (stringToCompare == null)
+			return false;
+
+		int ajustedOffset = fOffset + offset;
+		boolean result = false;
+		if (fCharSequenceSource != null && fCharSequenceSource instanceof IRegionComparible) {
+			result = ((IRegionComparible) fCharSequenceSource).regionMatchesIgnoreCase(ajustedOffset, length, stringToCompare);
+		}
+		else {
+			// old fashioned ways
+			String test = null;
+			if (fCharSequenceSource != null) {
+				test = fCharSequenceSource.subSequence(ajustedOffset, ajustedOffset + length).toString();
+			}
+			else if (fStringInput != null) {
+				test = fStringInput.substring(ajustedOffset, ajustedOffset + length);
+			}
+			result = stringToCompare.equalsIgnoreCase(test);
+		}
+		return result;
+	}
+
+	public void removeBlockMarker(BlockMarker marker) {
+		getTokenizer().removeBlockMarker(marker);
+	}
+
+	public void removeBlockMarker(String tagName) {
+		getTokenizer().removeBlockMarker(tagName);
+	}
+
+	public void removeStructuredDocumentRegionHandler(StructuredDocumentRegionHandler handler) {
+		if (fStructuredDocumentRegionHandlers == null)
+			return;
+		synchronized (fStructuredDocumentRegionHandlers) {
+			fStructuredDocumentRegionHandlers.remove(handler);
+		}
+	}
+
+	/**
+	 * Resets the input.
+	 */
+	public void reset(java.io.FileInputStream instream) {
+		primReset();
+		// fInput = instream;
+		getTokenizer().reset(instream);
+	}
+
+	/**
+	 * Resets the input.
+	 */
+	public void reset(java.io.Reader reader) {
+		reset(reader, 0);
+	}
+
+	/**
+	 * Resets the input.
+	 */
+	public void reset(java.io.Reader reader, int position) {
+		primReset();
+		fOffset = position;
+		getTokenizer().reset(reader, position);
+		if (reader instanceof DocumentReader) {
+			IDocument doc = ((DocumentReader) reader).getDocument();
+			if (doc instanceof CharSequence) {
+				fCharSequenceSource = (CharSequence) doc;
+			}
+			else {
+				// old fashioned IDocument
+				fDocumentInput = ((DocumentReader) reader).getDocument();
+			}
+
+		}
+		else if (reader instanceof CharSequenceReader) {
+			fCharSequenceSource = ((CharSequenceReader) reader).getOriginalSource();
+		}
+	}
+
+	/**
+	 * Resets the input. Use this version to allow text to be retrieved
+	 * <em>during</em> parsing, such as by the
+	 * StructuredDocumentRegionHandler.
+	 */
+	public void reset(String sourceString) {
+		reset(new StringReader(sourceString));
+		fStringInput = sourceString;
+	}
+
+	/**
+	 * Resets the input. Use this version to allow text to be retrieved
+	 * <em>during</em> parsing, such as by the
+	 * StructuredDocumentRegionHandler.
+	 */
+	public void reset(String sourceString, int position) {
+		StringReader reader = new StringReader(sourceString);
+		reset(reader, position);
+		fStringInput = sourceString;
+	}
+
+	public void resetHandlers() {
+		Object[] handlers = null;
+		synchronized (fStructuredDocumentRegionHandlers) {
+			if (fStructuredDocumentRegionHandlers == null)
+				return;
+
+			handlers = fStructuredDocumentRegionHandlers.toArray();
+		}
+		for (int i = 0; i < handlers.length; i++) {
+			try {
+				((StructuredDocumentRegionHandler) handlers[i]).resetNodes();
+			}
+			catch (Exception e) {
+				Logger.log(Logger.ERROR, "Error occurred while resetting handlers", e); //$NON-NLS-1$
+			}
+		}
+	}
+
+	/**
+	 * 
+	 * @param List
+	 */
+	public void setStructuredDocumentRegionHandlers(List newStructuredDocumentRegionHandlers) {
+		fStructuredDocumentRegionHandlers = newStructuredDocumentRegionHandlers;
+	}
+
+	protected void setTokenizer(BlockTokenizer newTokenizer) {
+		// DMW: changed from private to protected, so subclass could use in
+		// creation of 'newInstance'.
+		fTokenizer = newTokenizer;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/XMLStructuredDocumentReParser.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/XMLStructuredDocumentReParser.java
new file mode 100644
index 0000000..c185520
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/XMLStructuredDocumentReParser.java
@@ -0,0 +1,124 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.parser;
+
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredTextReParser;
+import org.eclipse.wst.sse.core.internal.text.StructuredDocumentReParser;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+
+
+public class XMLStructuredDocumentReParser extends StructuredDocumentReParser {
+
+	public XMLStructuredDocumentReParser() {
+		super();
+	}
+
+	protected IStructuredDocumentRegion findDirtyEnd(int end) {
+		// Caution: here's one place we have to cast
+		IStructuredDocumentRegion result = fStructuredDocument.getRegionAtCharacterOffset(end);
+		// if not well formed, get one past, if there is something there
+		if ((result != null) && (!result.isEnded())) {
+			if (result.getNext() != null) {
+				result = result.getNext();
+			}
+		}
+		// also, get one past if exactly equal to the end (this was needed
+		// as a simple fix to when a whole exact region is deleted.
+		// there's probably a better way.
+		if ((result != null) && (end == result.getEnd())) {
+			if (result.getNext() != null) {
+				result = result.getNext();
+			}
+		}
+
+		// 12/6/2001 - Since we've changed the parser/scanner to allow a lone
+		// '<' without
+		// always interpretting it as start of a tag name, we need to be a
+		// little fancier, in order
+		// to "skip" over any plain 'ol content between the lone '<' and any
+		// potential meating
+		// regions past plain 'ol content.
+		if (isLoneOpenFollowedByContent(result) && (result.getNext() != null)) {
+			result = result.getNext();
+		}
+
+		if (result != null)
+			fStructuredDocument.setCachedDocumentRegion(result);
+		dirtyEnd = result;
+
+		return dirtyEnd;
+	}
+
+	protected void findDirtyStart(int start) {
+		IStructuredDocumentRegion result = fStructuredDocument.getRegionAtCharacterOffset(start);
+		// heuristic: if the postion is exactly equal to the start, then
+		// go back one more, if it exists. This prevents problems with
+		// insertions
+		// of text that should be merged with the previous node instead of
+		// simply hung
+		// off of it as a separate node (ex.: XML content inserted right
+		// before an open
+		// bracket should become part of the previous content node)
+		if (result != null) {
+			IStructuredDocumentRegion previous = result.getPrevious();
+			if ((previous != null) && ((!(previous.isEnded())) || (start == result.getStart()))) {
+				result = previous;
+			}
+			// If we are now at the end of a "tag dependent" content area (or
+			// JSP area)
+			// then we need to back up all the way to the beginning of that.
+			IStructuredDocumentRegion potential = result;
+			while (isPartOfBlockRegion(potential)) {
+				potential = potential.getPrevious();
+			}
+			if (potential != null) {
+				result = potential;
+				fStructuredDocument.setCachedDocumentRegion(result);
+			}
+		}
+		dirtyStart = result;
+	}
+
+	/**
+	 * The rule is, that is we are content, preceded by lone <, then we need
+	 * to advance one more for dirty end.
+	 */
+	protected boolean isLoneOpenFollowedByContent(IStructuredDocumentRegion flatNode) {
+		boolean result = false;
+		String type = flatNode.getType();
+		if (type == DOMRegionContext.XML_CONTENT) {
+			IStructuredDocumentRegion previous = flatNode.getPrevious();
+			String previousType = null;
+			if (previous != null) {
+				previousType = previous.getType();
+			}
+			if (previousType != null) {
+				result = (previousType == DOMRegionContext.XML_TAG_OPEN);
+			}
+		}
+		return result;
+	}
+
+	protected boolean isPartOfBlockRegion(IStructuredDocumentRegion flatNode) {
+		boolean result = false;
+		String type = flatNode.getType();
+		result = (type == DOMRegionContext.BLOCK_TEXT);
+		return result;
+	}
+
+	public IStructuredTextReParser newInstance() {
+		return new XMLStructuredDocumentReParser();
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/XMLStructuredRegionFactory.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/XMLStructuredRegionFactory.java
new file mode 100644
index 0000000..8a98dc2
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/XMLStructuredRegionFactory.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.parser;
+
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.xml.core.internal.text.XMLStructuredDocumentRegion;
+
+
+/**
+ * A simple class to generate instances of StructuredRegions.
+ */
+public class XMLStructuredRegionFactory {
+	public final static int JSP_DIRECTIVE = 1003;
+	public final static int XML = 1001;
+	public final static int XML_BLOCK = 1002;
+
+	public static IStructuredDocumentRegion createRegion(int type) {
+		IStructuredDocumentRegion instance = null;
+		switch (type) {
+			case XML :
+				instance = new XMLStructuredDocumentRegion();
+				break;
+			case XML_BLOCK :
+				instance = new BlockStructuredDocumentRegion();
+				break;
+			default :
+				throw new IllegalArgumentException("AbstractRegion::createRegion. Invalid type."); //$NON-NLS-1$
+		}
+		return instance;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/XMLTokenizer.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/XMLTokenizer.java
new file mode 100644
index 0000000..09a3850
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/XMLTokenizer.java
@@ -0,0 +1,1931 @@
+/* The following code was generated by JFlex 1.2.2 on 6/29/10 1:04 PM */
+
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+
+package org.eclipse.wst.xml.core.internal.parser;
+
+import java.io.CharArrayReader;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.wst.sse.core.internal.ltk.parser.BlockMarker;
+import org.eclipse.wst.sse.core.internal.ltk.parser.BlockTokenizer;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+import org.eclipse.wst.sse.core.internal.util.Debug;
+import org.eclipse.wst.sse.core.utils.StringUtils;
+import org.eclipse.wst.xml.core.internal.Logger;
+import org.eclipse.wst.xml.core.internal.parser.regions.XMLParserRegionFactory;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+
+
+/**
+ * This class is a scanner generated by 
+ * <a href="http://www.informatik.tu-muenchen.de/~kleing/jflex/">JFlex</a> 1.2.2
+ * on 6/29/10 1:04 PM from the specification file
+ * <tt>file:/D:/eclipse.wtp/workspace/org.eclipse.wst.sse.core/DevTimeSupport/SedModel/HTMLTokenizer/devel/XMLTokenizer.jflex</tt>
+ */
+public class XMLTokenizer implements BlockTokenizer, DOMRegionContext {
+
+  /** this character denotes the end of file */
+  final public static int YYEOF = -1;
+
+  /** lexical states */
+  final public static int ST_XML_DOCTYPE_EXTERNAL_ID = 23;
+  final public static int ST_XML_ELEMENT_DECLARATION_CONTENT = 27;
+  final public static int ST_DHTML_ATTRIBUTE_NAME = 12;
+  final public static int ST_XML_PI_TAG_CLOSE = 11;
+  final public static int ST_XML_DECLARATION_CLOSE = 21;
+  final public static int ST_XML_PI_ATTRIBUTE_VALUE = 10;
+  final public static int ST_DHTML_EQUALS = 13;
+  final public static int ST_XML_TAG_NAME = 16;
+  final public static int ST_XML_ATTRIBUTE_VALUE = 19;
+  final public static int ST_DHTML_ATTRIBUTE_VALUE = 14;
+  final public static int ST_XML_DOCTYPE_ID_SYSTEM = 25;
+  final public static int ST_XML_ATTRIBUTE_NAME = 17;
+  final public static int ST_XML_ELEMENT_DECLARATION = 26;
+  final public static int ST_XML_DOCTYPE_DECLARATION = 22;
+  final public static int ST_XML_ATTLIST_DECLARATION = 28;
+  final public static int ST_XML_COMMENT_END = 4;
+  final public static int ST_CDATA_TEXT = 1;
+  final public static int ST_DHTML_TAG_CLOSE = 15;
+  final public static int ST_XML_COMMENT = 3;
+  final public static int ST_PI_CONTENT = 7;
+  final public static int ST_PI_WS = 6;
+  final public static int ST_CDATA_END = 2;
+  final public static int ST_XML_ATTLIST_DECLARATION_CONTENT = 29;
+  final public static int ST_BLOCK_TAG_SCAN = 30;
+  final public static int ST_XML_PI_EQUALS = 9;
+  final public static int ST_XML_DECLARATION = 20;
+  final public static int YYINITIAL = 0;
+  final public static int ST_XML_DOCTYPE_ID_PUBLIC = 24;
+  final public static int ST_XML_EQUALS = 18;
+  final public static int ST_PI = 5;
+  final public static int ST_XML_PI_ATTRIBUTE_NAME = 8;
+
+  /** 
+   * Translates characters to character classes
+   */
+  final private static String yycmap_packed = 
+    "\11\0\1\5\1\22\2\0\1\14\22\0\1\14\1\21\1\11\1\55"+
+    "\1\16\1\17\1\12\1\13\1\16\1\16\1\16\1\16\1\16\1\7"+
+    "\1\6\1\3\12\15\1\10\1\61\1\1\1\45\1\2\1\4\1\16"+
+    "\1\34\1\62\1\32\1\33\1\50\1\57\1\36\1\36\1\42\1\36"+
+    "\1\36\1\27\1\25\1\44\1\43\1\47\1\36\1\40\1\56\1\35"+
+    "\1\60\2\36\1\23\1\46\1\36\1\31\1\0\1\20\1\0\1\10"+
+    "\1\0\1\52\1\62\1\63\1\53\1\37\1\57\1\36\1\66\1\42"+
+    "\2\36\1\30\1\26\1\44\1\43\1\47\1\36\1\40\1\41\1\51"+
+    "\1\60\1\36\1\36\1\24\1\54\1\36\1\0\1\0\72\0\1\65"+
+    "\10\0\27\64\1\0\37\64\1\0\72\64\2\0\13\64\2\0\10\64"+
+    "\1\0\65\64\1\0\104\64\11\0\44\64\3\0\2\64\4\0\36\64"+
+    "\70\0\131\64\22\0\7\64\16\0\2\65\56\0\106\65\32\0\2\65"+
+    "\44\0\1\64\1\65\3\64\1\0\1\64\1\0\24\64\1\0\54\64"+
+    "\1\0\7\64\3\0\1\64\1\0\1\64\1\0\1\64\1\0\1\64"+
+    "\1\0\22\64\15\0\14\64\1\0\102\64\1\0\14\64\1\0\44\64"+
+    "\1\0\4\65\11\0\65\64\2\0\2\64\2\0\2\64\3\0\34\64"+
+    "\2\0\10\64\2\0\2\64\67\0\46\64\2\0\1\64\7\0\46\64"+
+    "\12\0\21\65\1\0\27\65\1\0\3\65\1\0\1\65\1\0\2\65"+
+    "\1\0\1\65\13\0\33\64\5\0\3\64\56\0\32\64\5\0\1\65"+
+    "\12\64\10\65\15\0\12\65\6\0\1\65\107\64\2\0\5\64\1\0"+
+    "\17\64\1\0\4\64\1\0\1\64\17\65\2\64\2\65\1\0\4\65"+
+    "\2\0\12\65\u0207\0\3\65\1\0\65\64\2\0\1\65\1\64\20\65"+
+    "\3\0\4\65\3\0\12\64\2\65\2\0\12\65\21\0\3\65\1\0"+
+    "\10\64\2\0\2\64\2\0\26\64\1\0\7\64\1\0\1\64\3\0"+
+    "\4\64\2\0\1\65\1\0\7\65\2\0\2\65\2\0\3\65\11\0"+
+    "\1\65\4\0\2\64\1\0\3\64\2\65\2\0\12\65\2\64\20\0"+
+    "\1\65\2\0\6\64\4\0\2\64\2\0\26\64\1\0\7\64\1\0"+
+    "\2\64\1\0\2\64\1\0\2\64\2\0\1\65\1\0\5\65\4\0"+
+    "\2\65\2\0\3\65\13\0\4\64\1\0\1\64\7\0\12\65\2\65"+
+    "\3\64\14\0\3\65\1\0\7\64\1\0\1\64\1\0\3\64\1\0"+
+    "\26\64\1\0\7\64\1\0\2\64\1\0\5\64\2\0\1\65\1\64"+
+    "\10\65\1\0\3\65\1\0\3\65\22\0\1\64\5\0\12\65\21\0"+
+    "\3\65\1\0\10\64\2\0\2\64\2\0\26\64\1\0\7\64\1\0"+
+    "\2\64\2\0\4\64\2\0\1\65\1\64\6\65\3\0\2\65\2\0"+
+    "\3\65\10\0\2\65\4\0\2\64\1\0\3\64\4\0\12\65\22\0"+
+    "\2\65\1\0\6\64\3\0\3\64\1\0\4\64\3\0\2\64\1\0"+
+    "\1\64\1\0\2\64\3\0\2\64\3\0\3\64\3\0\10\64\1\0"+
+    "\3\64\4\0\5\65\3\0\3\65\1\0\4\65\11\0\1\65\17\0"+
+    "\11\65\21\0\3\65\1\0\10\64\1\0\3\64\1\0\27\64\1\0"+
+    "\12\64\1\0\5\64\4\0\7\65\1\0\3\65\1\0\4\65\7\0"+
+    "\2\65\11\0\2\64\4\0\12\65\22\0\2\65\1\0\10\64\1\0"+
+    "\3\64\1\0\27\64\1\0\12\64\1\0\5\64\4\0\7\65\1\0"+
+    "\3\65\1\0\4\65\7\0\2\65\7\0\1\64\1\0\2\64\4\0"+
+    "\12\65\22\0\2\65\1\0\10\64\1\0\3\64\1\0\27\64\1\0"+
+    "\20\64\4\0\6\65\2\0\3\65\1\0\4\65\11\0\1\65\10\0"+
+    "\2\64\4\0\12\65\221\0\56\64\1\0\1\64\1\65\2\64\7\65"+
+    "\5\0\6\64\1\65\10\65\1\0\12\65\47\0\2\64\1\0\1\64"+
+    "\2\0\2\64\1\0\1\64\2\0\1\64\6\0\4\64\1\0\7\64"+
+    "\1\0\3\64\1\0\1\64\1\0\1\64\2\0\2\64\1\0\2\64"+
+    "\1\0\1\64\1\65\2\64\6\65\1\0\2\65\1\64\2\0\5\64"+
+    "\1\0\1\65\1\0\6\65\2\0\12\65\76\0\2\65\6\0\12\65"+
+    "\13\0\1\65\1\0\1\65\1\0\1\65\4\0\2\65\10\64\1\0"+
+    "\41\64\7\0\24\65\1\0\6\65\4\0\6\65\1\0\1\65\1\0"+
+    "\25\65\3\0\7\65\1\0\1\65\346\0\46\64\12\0\47\64\11\0"+
+    "\1\64\1\0\2\64\1\0\3\64\1\0\1\64\1\0\2\64\1\0"+
+    "\5\64\51\0\1\64\1\0\1\64\1\0\1\64\13\0\1\64\1\0"+
+    "\1\64\1\0\1\64\3\0\2\64\3\0\1\64\5\0\3\64\1\0"+
+    "\1\64\1\0\1\64\1\0\1\64\1\0\1\64\3\0\2\64\3\0"+
+    "\2\64\1\0\1\64\50\0\1\64\11\0\1\64\2\0\1\64\2\0"+
+    "\2\64\7\0\2\64\1\0\1\64\1\0\7\64\50\0\1\64\4\0"+
+    "\1\64\10\0\1\64\u0c06\0\234\64\4\0\132\64\6\0\26\64\2\0"+
+    "\6\64\2\0\46\64\2\0\6\64\2\0\10\64\1\0\1\64\1\0"+
+    "\1\64\1\0\1\64\1\0\37\64\2\0\65\64\1\0\7\64\1\0"+
+    "\1\64\3\0\3\64\1\0\7\64\3\0\4\64\2\0\6\64\4\0"+
+    "\15\64\5\0\3\64\1\0\7\64\323\0\15\65\4\0\1\65\104\0"+
+    "\1\64\3\0\2\64\2\0\1\64\121\0\3\64\u0e82\0\1\65\1\0"+
+    "\1\64\31\0\11\64\6\65\1\0\5\65\13\0\124\64\4\0\2\65"+
+    "\2\0\2\65\2\0\132\64\1\0\3\65\6\0\50\64\u1cd3\0\u51a6\64"+
+    "\u0c5a\0\u2ba4\64\134\0\u0800\0\u1ffe\0\2\0";
+
+  /** 
+   * Translates characters to character classes
+   */
+  final private static char [] yycmap = yy_unpack_cmap(yycmap_packed);
+
+  /** 
+   * Translates a state to a row index in the transition table
+   */
+  final private static int yy_rowMap [] = { 
+        0,    55,   110,   165,   220,   275,   330,   385,   440,   495, 
+      550,   605,   660,   715,   770,   825,   880,   935,   990,  1045, 
+     1100,  1155,  1210,  1265,  1320,  1375,  1430,  1485,  1540,  1595, 
+     1650,  1705,  1760,  1815,  1870,  1925,  1980,  1925,  1980,  2035, 
+     1925,  1925,  1980,  2090,  2145,  2200,  2255,  2310,  2365,  2420, 
+     2475,  1925,  1980,  2530,  2585,  2640,  1925,  2695,  2695,  2750, 
+     2805,  2860,  2530,  1925,  2915,  2970,  1925,  3025,  3080,  3135, 
+     3190,  3245,  3300,  1925,  3355,  3410,  3465,  3520,  1925,  3575, 
+     3630,  3685,  3740,  3795,  1925,  3850,  3905,  3960,  4015,  4070, 
+     4125,  4180,  4235,  4235,  4290,  4345,  4400,  4455,  4455,  4510, 
+     4565,  4620,  4675,  4675,  4730,  4785,  4840,  4895,  1925,  4950, 
+     4950,  5005,  5060,  5115,  5170,  1925,  1925,  1980,  1925,  1925, 
+     5225,  5280,  5335,  5390,  5445,  5500,  5555,  5610,  1925,  5665, 
+     5720,  5775,  1925,  1925,  2695,  5830,  2805,  1925,  5885,  2860, 
+     2915,  3025,  3080,  5940,  3135,  1925,  5995,  3190,  1925,  3575, 
+     6050,  3685,  1925,  6105,  3740,  5225,  6160,  6215,  6270,  4015, 
+     1925,  6325,  6380,  4235,  6435,  4290,  1925,  6490,  6545,  6600, 
+     6600,  6655,  6710,  4400,  4235,  4455,  6765,  4510,  1925,  6820, 
+     4565,  4620,  4455,  4675,  6875,  4730,  1925,  6930,  6985,  7040, 
+     7040,  7095,  7150,  7205,  4950,  7260,  5005,  1925,  7315,  7370, 
+     7425,  7425,  7480,  7535,  7590,  7645,  7700,  7755,  7810,  1925, 
+     7865,  7920,  1925,  1925,  1925,  2255,  7975,  8030,  8085,  8140, 
+     8195,  8250,  8305,  6490,  8360,  8360,  6930,  8415,  8415,  8470, 
+     7315,  8525,  8525,  8580,  1925,  8635,  8690,  1925,  8745,  8800, 
+     8855,  8910,  8965,  9020,  9075,  9130,  6655,  7095,  9185,  7480, 
+     9240,  9295,  9350,  9405,  9460,  9515,  9570,  9625,  9680,  9735, 
+     9790,  9845,  9900,  9955, 10010, 10065, 10120,  1925,  1925, 10175, 
+    10230, 10285, 10340, 10395,  1925,  1925,  1925, 10450, 10505, 10560, 
+    10615, 10670, 10725,  1925, 10780,  4840,  5115, 10835, 10890, 10945, 
+    11000,  2255
+  };
+
+  /** 
+   * The packed transition table of the DFA
+   */
+  final private static String yy_packed = 
+    "\1\40\1\41\10\40\1\42\4\40\1\43\47\40\1\44"+
+    "\1\45\65\44\1\46\1\47\16\46\1\50\1\46\1\51"+
+    "\44\46\1\52\1\53\65\52\1\46\1\47\5\46\1\54"+
+    "\12\46\1\51\45\46\1\47\2\46\1\55\1\56\2\46"+
+    "\1\57\3\46\1\56\5\46\1\56\1\60\1\61\4\57"+
+    "\1\46\10\57\1\62\2\57\1\46\7\57\1\46\3\57"+
+    "\1\46\3\57\1\46\1\57\1\46\1\47\2\46\1\55"+
+    "\1\63\6\46\1\63\5\46\1\63\44\46\1\64\1\65"+
+    "\2\64\1\66\15\64\1\51\44\64\1\46\1\47\2\46"+
+    "\1\67\1\56\2\46\1\70\3\46\1\56\5\46\1\56"+
+    "\6\70\1\46\13\70\1\46\7\70\1\46\3\70\1\46"+
+    "\3\70\1\46\1\70\1\46\1\47\2\46\1\67\1\56"+
+    "\2\46\1\70\3\46\1\56\5\46\1\56\6\70\1\46"+
+    "\13\70\1\71\7\70\1\46\3\70\1\46\3\70\1\46"+
+    "\1\70\1\72\1\47\1\46\1\73\1\74\1\56\3\72"+
+    "\1\75\1\72\1\76\1\56\5\72\1\56\44\72\1\46"+
+    "\1\47\2\46\1\77\15\46\1\51\45\46\1\47\1\100"+
+    "\1\101\1\46\1\56\2\46\1\102\3\46\1\56\5\46"+
+    "\1\56\6\102\1\46\13\102\1\46\7\102\1\46\3\102"+
+    "\1\46\3\102\1\46\1\102\1\46\1\47\1\100\1\101"+
+    "\1\46\1\56\2\46\1\102\3\46\1\56\5\46\1\56"+
+    "\6\102\1\46\13\102\1\103\7\102\1\46\3\102\1\46"+
+    "\3\102\1\46\1\102\1\104\1\47\1\100\1\105\1\104"+
+    "\1\56\3\104\1\106\1\104\1\107\1\56\5\104\1\56"+
+    "\44\104\1\46\1\47\3\46\1\56\6\46\1\56\5\46"+
+    "\1\56\44\46\1\110\1\111\1\112\1\113\4\110\1\114"+
+    "\12\110\6\115\1\110\13\115\1\110\7\115\1\110\3\115"+
+    "\1\110\3\115\1\110\1\115\1\46\1\111\1\112\1\113"+
+    "\1\46\1\56\2\46\1\116\3\46\1\56\5\46\1\56"+
+    "\6\116\1\46\13\116\1\46\7\116\1\46\3\116\1\46"+
+    "\3\116\1\46\1\116\1\46\1\111\1\112\1\113\1\46"+
+    "\1\56\2\46\1\116\3\46\1\56\5\46\1\56\6\116"+
+    "\1\46\13\116\1\117\7\116\1\46\3\116\1\46\3\116"+
+    "\1\46\1\116\1\120\1\111\1\112\1\121\1\120\1\56"+
+    "\3\120\1\122\1\120\1\123\1\56\5\120\1\56\44\120"+
+    "\1\46\1\124\1\125\2\46\1\56\6\46\1\56\5\46"+
+    "\1\56\10\46\1\126\1\127\2\46\1\130\10\46\1\130"+
+    "\1\46\1\127\1\126\14\46\1\47\1\125\2\46\1\56"+
+    "\6\46\1\56\5\46\1\56\6\46\1\131\36\46\1\47"+
+    "\1\125\2\46\1\56\2\46\1\132\3\46\1\56\5\46"+
+    "\1\56\6\132\1\131\13\132\1\46\7\132\1\46\3\132"+
+    "\1\46\3\132\1\46\1\132\1\46\1\47\1\125\2\46"+
+    "\1\56\6\46\1\56\5\46\1\56\6\46\1\131\7\46"+
+    "\1\133\5\46\1\134\6\46\1\133\10\46\1\135\1\47"+
+    "\1\125\1\136\1\135\1\56\3\135\1\137\1\135\1\140"+
+    "\1\56\5\135\1\56\6\135\1\141\35\135\1\142\1\47"+
+    "\1\125\1\143\1\142\1\56\3\142\1\144\1\142\1\145"+
+    "\1\56\5\142\1\56\6\142\1\146\35\142\1\147\1\47"+
+    "\1\125\1\150\1\147\1\56\3\147\1\151\1\147\1\152"+
+    "\1\56\5\147\1\56\44\147\1\153\1\154\1\155\64\153"+
+    "\1\156\1\47\1\125\1\157\1\156\1\56\3\156\1\160"+
+    "\1\156\1\161\1\56\5\156\1\56\44\156\1\162\1\163"+
+    "\1\164\64\162\1\165\1\166\65\165\1\40\1\0\10\40"+
+    "\1\0\4\40\1\0\47\40\3\0\1\167\1\170\14\0"+
+    "\1\171\52\0\1\172\2\0\1\173\3\0\1\172\5\0"+
+    "\1\172\6\173\1\0\13\173\1\0\7\173\1\174\3\173"+
+    "\1\0\3\173\1\0\1\173\5\0\1\172\2\0\1\175"+
+    "\3\0\1\172\5\0\1\172\6\175\1\0\13\175\1\0"+
+    "\7\175\1\0\3\175\1\0\3\175\1\0\1\175\110\0"+
+    "\1\176\65\0\1\177\55\0\1\200\61\0\1\201\71\0"+
+    "\1\56\6\0\1\56\5\0\1\56\52\0\3\57\4\0"+
+    "\1\57\5\0\6\57\1\0\13\57\1\0\7\57\1\0"+
+    "\3\57\1\0\5\57\6\0\3\57\4\0\1\57\5\0"+
+    "\2\57\2\202\2\57\1\0\13\57\1\0\7\57\1\0"+
+    "\3\57\1\0\5\57\6\0\3\57\4\0\1\57\5\0"+
+    "\2\57\1\202\1\203\2\57\1\0\13\57\1\0\7\57"+
+    "\1\0\3\57\1\0\5\57\6\0\3\57\4\0\1\57"+
+    "\5\0\2\57\2\204\2\57\1\0\13\57\1\0\7\57"+
+    "\1\0\3\57\1\0\5\57\5\0\1\63\6\0\1\63"+
+    "\5\0\1\63\46\0\1\205\66\0\1\206\72\0\3\70"+
+    "\4\0\1\70\5\0\6\70\1\0\13\70\1\0\7\70"+
+    "\1\0\3\70\1\0\5\70\1\72\2\0\1\207\1\72"+
+    "\1\0\3\72\1\0\1\72\2\0\5\72\1\0\45\72"+
+    "\1\0\1\206\1\207\1\72\1\0\3\72\1\0\1\72"+
+    "\2\0\5\72\1\0\44\72\1\75\2\210\1\211\1\75"+
+    "\1\210\3\75\1\212\1\75\2\210\5\75\1\210\44\75"+
+    "\1\76\2\213\1\214\1\76\1\213\3\76\1\213\1\76"+
+    "\1\212\1\213\5\76\1\213\44\76\2\0\1\100\1\215"+
+    "\71\0\3\102\4\0\1\102\5\0\6\102\1\0\13\102"+
+    "\1\0\7\102\1\0\3\102\1\0\5\102\1\104\2\0"+
+    "\1\216\1\104\1\0\3\104\1\0\1\104\2\0\5\104"+
+    "\1\0\45\104\1\0\1\100\1\217\1\104\1\0\3\104"+
+    "\1\0\1\104\2\0\5\104\1\0\44\104\1\106\2\220"+
+    "\1\221\1\106\1\220\3\106\1\222\1\106\2\220\5\106"+
+    "\1\220\44\106\1\107\2\223\1\224\1\107\1\223\3\107"+
+    "\1\223\1\107\1\222\1\223\5\107\1\223\44\107\1\110"+
+    "\3\0\17\110\6\0\1\110\13\0\1\110\7\0\1\110"+
+    "\3\0\1\110\3\0\1\110\4\0\1\167\15\0\1\171"+
+    "\47\0\1\225\64\0\1\110\3\0\2\110\3\114\4\110"+
+    "\1\114\5\110\6\115\1\110\13\115\1\110\7\115\1\110"+
+    "\3\115\1\110\3\115\1\114\1\115\6\0\3\115\4\0"+
+    "\1\115\5\0\6\115\1\0\13\115\1\0\7\115\1\0"+
+    "\3\115\1\0\5\115\6\0\3\116\4\0\1\116\5\0"+
+    "\6\116\1\0\13\116\1\0\7\116\1\0\3\116\1\0"+
+    "\5\116\1\120\2\0\1\226\1\120\1\0\3\120\1\0"+
+    "\1\120\2\0\5\120\1\0\45\120\1\0\1\225\1\226"+
+    "\1\120\1\0\3\120\1\0\1\120\2\0\5\120\1\0"+
+    "\44\120\1\122\2\227\1\230\1\122\1\227\3\122\1\231"+
+    "\1\122\2\227\5\122\1\227\44\122\1\123\2\232\1\233"+
+    "\1\123\1\232\3\123\1\232\1\123\1\231\1\232\5\123"+
+    "\1\232\44\123\3\0\1\167\15\0\1\234\110\0\1\235"+
+    "\60\0\1\236\13\0\1\236\44\0\2\237\36\0\20\240"+
+    "\1\241\46\240\6\0\3\132\4\0\1\132\5\0\6\132"+
+    "\1\0\13\132\1\0\7\132\1\0\3\132\1\0\5\132"+
+    "\46\0\1\242\5\0\1\242\72\0\1\243\6\0\1\135"+
+    "\2\0\1\244\1\135\1\0\3\135\1\0\1\135\2\0"+
+    "\5\135\1\0\44\135\1\137\2\245\1\246\1\137\1\245"+
+    "\3\137\1\247\1\137\2\245\5\137\1\245\44\137\1\250"+
+    "\2\251\1\252\1\253\1\251\3\253\1\251\1\250\1\254"+
+    "\1\255\3\253\1\250\1\253\1\255\6\253\1\250\32\253"+
+    "\2\250\1\253\1\141\2\240\1\256\1\141\1\240\3\141"+
+    "\1\240\1\141\2\240\3\141\1\257\1\141\1\240\44\141"+
+    "\1\142\2\0\1\260\1\142\1\0\3\142\1\0\1\142"+
+    "\2\0\5\142\1\0\44\142\1\144\2\261\1\262\1\144"+
+    "\1\261\3\144\1\263\1\144\2\261\5\144\1\261\44\144"+
+    "\1\145\2\264\1\265\1\145\1\264\3\145\1\264\1\145"+
+    "\1\263\1\264\5\145\1\264\44\145\1\146\2\240\1\266"+
+    "\1\146\1\240\3\146\1\240\1\146\2\240\3\146\1\267"+
+    "\1\146\1\240\44\146\1\147\2\0\1\270\1\147\1\0"+
+    "\3\147\1\0\1\147\2\0\5\147\1\0\44\147\1\151"+
+    "\2\271\1\272\1\151\1\271\3\151\1\273\1\151\2\271"+
+    "\5\151\1\271\44\151\1\274\2\275\1\276\1\277\1\275"+
+    "\3\277\1\275\1\274\1\300\1\301\3\277\1\274\1\277"+
+    "\1\301\6\277\1\274\32\277\2\274\1\277\2\153\1\0"+
+    "\66\153\1\0\16\153\1\302\45\153\1\156\2\0\1\303"+
+    "\1\156\1\0\3\156\1\0\1\156\2\0\5\156\1\0"+
+    "\44\156\1\160\2\304\1\305\1\160\1\304\3\160\1\306"+
+    "\1\160\2\304\5\160\1\304\44\160\1\307\2\310\1\311"+
+    "\1\312\1\310\3\312\1\310\1\307\1\313\1\314\3\312"+
+    "\1\307\1\312\1\314\6\312\1\307\32\312\2\307\1\312"+
+    "\2\162\1\0\66\162\1\0\16\162\1\315\45\162\7\0"+
+    "\1\316\21\0\1\317\42\0\1\172\2\0\1\40\3\0"+
+    "\1\172\5\0\1\172\6\40\1\0\13\40\1\0\7\40"+
+    "\1\0\3\40\1\0\3\40\1\0\1\40\1\320\1\0"+
+    "\3\320\1\321\3\173\1\320\1\0\1\320\1\321\1\173"+
+    "\1\320\1\0\2\320\1\321\6\173\1\320\13\173\1\320"+
+    "\7\173\1\320\3\173\1\322\5\173\15\0\1\323\6\0"+
+    "\1\324\42\0\1\320\1\0\3\320\1\321\3\175\1\320"+
+    "\1\0\1\320\1\321\1\175\1\320\1\0\2\320\1\321"+
+    "\6\175\1\320\13\175\1\320\7\175\1\320\3\175\1\325"+
+    "\5\175\31\0\1\317\37\0\1\326\66\0\1\327\72\0"+
+    "\3\57\4\0\1\57\5\0\4\57\2\330\1\0\13\57"+
+    "\1\0\7\57\1\0\3\57\1\0\5\57\6\0\3\57"+
+    "\4\0\1\57\5\0\4\57\1\330\1\331\1\0\13\57"+
+    "\1\0\7\57\1\0\3\57\1\0\5\57\6\0\3\57"+
+    "\4\0\1\57\5\0\6\57\1\0\13\57\1\0\1\57"+
+    "\1\332\5\57\1\0\3\57\1\0\5\57\11\210\1\212"+
+    "\55\210\13\213\1\212\53\213\11\220\1\222\55\220\13\223"+
+    "\1\222\53\223\11\227\1\231\55\227\13\232\1\231\53\232"+
+    "\32\0\1\333\30\0\1\333\40\0\1\334\13\0\1\334"+
+    "\54\0\1\335\10\0\1\335\57\0\1\336\14\0\1\336"+
+    "\72\0\1\337\4\0\11\245\1\247\55\245\1\250\2\251"+
+    "\1\340\1\250\1\251\3\250\1\251\1\250\1\247\1\251"+
+    "\5\250\1\251\44\250\13\251\1\247\53\251\1\250\2\251"+
+    "\1\340\1\250\1\251\3\250\1\251\1\250\1\341\1\251"+
+    "\5\250\1\251\44\250\13\0\1\342\53\0\13\251\1\341"+
+    "\53\251\11\261\1\263\55\261\13\264\1\263\53\264\11\271"+
+    "\1\273\55\271\1\274\2\275\1\343\1\274\1\275\3\274"+
+    "\1\275\1\274\1\273\1\275\5\274\1\275\44\274\13\275"+
+    "\1\273\53\275\1\274\2\275\1\343\1\274\1\275\3\274"+
+    "\1\275\1\274\1\344\1\275\5\274\1\275\44\274\13\0"+
+    "\1\345\53\0\13\275\1\344\53\275\2\153\1\0\26\153"+
+    "\1\346\35\153\11\304\1\306\55\304\1\307\2\310\1\347"+
+    "\1\307\1\310\3\307\1\310\1\307\1\306\1\310\5\307"+
+    "\1\310\44\307\13\310\1\306\53\310\1\307\2\310\1\347"+
+    "\1\307\1\310\3\307\1\310\1\307\1\350\1\310\5\307"+
+    "\1\310\44\307\13\0\1\351\53\0\13\310\1\350\53\310"+
+    "\2\162\1\0\26\162\1\352\35\162\7\0\1\353\111\0"+
+    "\1\354\34\0\1\320\1\0\10\320\1\0\4\320\1\0"+
+    "\41\320\1\0\6\320\1\0\3\320\1\321\4\320\1\0"+
+    "\1\320\1\321\2\320\1\0\2\320\1\321\36\320\1\355"+
+    "\5\320\15\0\1\323\43\0\1\356\22\0\1\357\14\0"+
+    "\3\357\2\0\1\357\10\0\1\357\1\0\2\357\3\0"+
+    "\1\357\2\0\2\357\11\0\1\57\1\360\1\57\4\0"+
+    "\1\57\5\0\6\57\1\0\13\57\1\0\7\57\1\0"+
+    "\3\57\1\0\5\57\6\0\3\57\4\0\1\57\5\0"+
+    "\6\57\1\0\11\57\1\361\1\57\1\0\7\57\1\0"+
+    "\3\57\1\0\5\57\35\0\1\362\13\0\1\362\44\0"+
+    "\2\363\63\0\2\364\75\0\1\365\13\0\1\365\44\0"+
+    "\2\366\41\0\2\367\1\0\3\367\2\0\1\254\4\367"+
+    "\1\0\10\367\1\0\32\367\2\0\1\367\3\0\2\370"+
+    "\1\0\3\370\2\0\1\300\4\370\1\0\10\370\1\0"+
+    "\32\370\2\0\1\370\2\153\1\0\27\153\1\371\34\153"+
+    "\3\0\2\372\1\0\3\372\2\0\1\313\4\372\1\0"+
+    "\10\372\1\0\32\372\2\0\1\372\2\162\1\0\27\162"+
+    "\1\373\34\162\33\0\1\374\114\0\1\355\22\0\1\357"+
+    "\14\0\3\357\2\0\1\357\10\0\1\357\1\0\2\357"+
+    "\3\0\1\357\1\0\1\356\2\357\11\0\3\57\4\0"+
+    "\1\57\5\0\6\57\1\0\7\57\1\375\3\57\1\0"+
+    "\7\57\1\0\3\57\1\0\5\57\6\0\3\57\4\0"+
+    "\1\57\5\0\6\57\1\0\6\57\1\376\4\57\1\0"+
+    "\7\57\1\0\3\57\1\0\5\57\46\0\1\377\5\0"+
+    "\1\377\54\0\1\u0100\63\0\1\u0101\10\0\1\u0101\55\0"+
+    "\1\u0102\10\0\1\u0102\60\0\1\u0103\24\0\2\153\1\0"+
+    "\30\153\1\u0104\33\153\2\162\1\0\30\162\1\u0105\33\162"+
+    "\34\0\1\u0106\40\0\3\57\4\0\1\57\5\0\6\57"+
+    "\1\0\13\57\1\0\3\57\1\u0107\3\57\1\0\3\57"+
+    "\1\0\5\57\6\0\3\57\4\0\1\57\5\0\6\57"+
+    "\1\0\3\57\1\u0108\7\57\1\0\3\57\1\u0108\3\57"+
+    "\1\0\3\57\1\0\5\57\47\0\1\u0109\60\0\1\u010a"+
+    "\14\0\1\u010a\54\0\1\u010b\47\0\2\u010c\72\0\1\u010d"+
+    "\30\0\1\u010d\3\0\2\153\1\0\31\153\1\u010e\32\153"+
+    "\2\162\1\0\31\162\1\u010f\32\162\35\0\1\u0110\37\0"+
+    "\3\57\4\0\1\57\5\0\6\57\1\0\13\57\1\0"+
+    "\6\57\1\u0111\1\0\3\57\1\0\5\57\5\0\1\u0112"+
+    "\3\57\3\0\1\u0112\1\57\4\0\1\u0112\6\57\1\0"+
+    "\13\57\1\0\7\57\1\0\3\57\1\0\5\57\37\0"+
+    "\1\u0113\10\0\1\u0113\53\0\1\u0114\13\0\1\u0114\52\0"+
+    "\1\u0115\13\0\1\u0115\15\0\2\153\1\0\32\153\1\u0116"+
+    "\31\153\2\162\1\0\32\162\1\u0117\31\162\34\0\1\u0118"+
+    "\40\0\3\57\4\0\1\57\5\0\5\57\1\u0119\1\0"+
+    "\13\57\1\0\7\57\1\0\3\57\1\0\5\57\5\0"+
+    "\1\u0112\6\0\1\u0112\5\0\1\u0112\44\0\2\153\1\0"+
+    "\31\153\1\u011a\32\153\2\162\1\0\31\162\1\u011b\32\162"+
+    "\31\0\1\u011c\43\0\3\57\4\0\1\57\5\0\6\57"+
+    "\1\0\5\57\1\u011d\5\57\1\0\7\57\1\0\3\57"+
+    "\1\0\5\57\2\153\1\0\26\153\1\u011e\35\153\2\162"+
+    "\1\0\26\162\1\u011f\35\162\6\0\3\57\4\0\1\57"+
+    "\5\0\6\57\1\0\7\57\1\u0120\3\57\1\0\7\57"+
+    "\1\0\3\57\1\0\5\57\6\0\3\57\4\0\1\57"+
+    "\5\0\6\57\1\0\13\57\1\0\7\57\1\0\3\57"+
+    "\1\0\4\57\1\u0121\6\0\3\57\4\0\1\57\5\0"+
+    "\6\57\1\0\5\57\1\u0122\5\57\1\0\7\57\1\0"+
+    "\3\57\1\0\5\57\6\0\3\57\4\0\1\57\5\0"+
+    "\6\57\1\0\5\57\1\u0123\5\57\1\0\7\57\1\0"+
+    "\3\57\1\0\5\57\6\0\3\57\4\0\1\57\5\0"+
+    "\6\57\1\0\13\57\1\0\3\57\1\u0124\3\57\1\0"+
+    "\3\57\1\0\5\57";
+
+  /** 
+   * The transition table of the DFA
+   */
+  final private static int yytrans [] = yy_unpack(yy_packed);
+
+
+  /* error codes */
+  final private static int YY_UNKNOWN_ERROR = 0;
+  // final private static int YY_ILLEGAL_STATE = 1;
+  final private static int YY_NO_MATCH = 2;
+  final private static int YY_PUSHBACK_2BIG = 3;
+
+  /* error messages for the codes above */
+  final private static String YY_ERROR_MSG[] = {
+    "Unkown internal scanner error",		//$NON-NLS-1$
+    "Internal error: unknown state",		//$NON-NLS-1$
+    "Error: could not match input",		//$NON-NLS-1$
+    "Error: pushback value was too large"	//$NON-NLS-1$
+  };
+
+  /**
+   * YY_ATTRIBUTE[aState] contains the attributes of state <code>aState</code>
+   */
+  private final static byte YY_ATTRIBUTE[] = {
+     1,  0,  0,  0,  0,  1,  0,  0,  1,  1,  1,  0,  1,  1,  1,  1, 
+     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  1, 
+     1,  1,  1,  9,  1,  9,  1,  1,  9,  9,  1,  1,  1,  1,  1,  1, 
+     1,  1,  1,  9,  1,  1,  1,  1,  9,  1,  1,  1,  1,  1,  1,  9, 
+     1,  1,  9,  1,  1,  1,  1,  1,  1,  9,  1,  1,  1,  1,  9,  1, 
+     1,  1,  1,  1,  9,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
+     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  9,  1,  1,  1, 
+     1,  1,  1,  9,  9,  1,  9,  9,  1,  0,  1,  0,  1,  0,  0,  0, 
+     9,  1,  1,  1,  9,  9,  0,  0,  0,  9,  0,  0,  0,  0,  0,  0, 
+     0,  9,  0,  0,  9,  0,  0,  0,  9,  0,  0,  0,  0,  0,  0,  0, 
+     9,  0,  0,  0,  0,  0,  9,  1,  0,  0,  1,  1,  0,  0,  1,  0, 
+     0,  0,  9,  0,  0,  0,  1,  0,  0,  0,  9,  1,  0,  0,  1,  1, 
+     0,  1,  0,  0,  0,  9,  1,  0,  0,  1,  1,  0,  1,  0,  0,  1, 
+     1,  9,  0,  0,  9,  9,  9,  1,  1,  1,  0,  0,  0,  0,  0,  0, 
+     1,  0,  0,  1,  0,  1,  0,  1,  0,  1,  9,  0,  1,  9,  0,  1, 
+     1,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  1,  0,  0, 
+     0,  0,  0,  1,  1,  0,  1,  1,  0,  0,  0,  9,  9,  1,  1,  0, 
+     1,  1,  9,  9,  9,  1,  1,  0,  1,  1,  1,  9,  1,  1,  1,  1, 
+     1,  1,  1,  1
+  };
+
+  /** the input device */
+  private java.io.Reader yy_reader;
+
+  /** the current state of the DFA */
+  private int yy_state;
+
+  /** the current lexical state */
+  private int yy_lexical_state = YYINITIAL;
+
+  /** this buffer contains the current text to be matched and is
+      the source of the yytext() string */
+  private char yy_buffer[] = new char[16384];
+
+  /** the textposition at the last accepting state */
+  private int yy_markedPos;
+
+  /** the textposition at the last state to be included in yytext */
+  private int yy_pushbackPos;
+
+  /** the current text position in the buffer */
+  private int yy_currentPos;
+
+  /** startRead marks the beginning of the yytext() string in the buffer */
+  private int yy_startRead;
+
+  /** endRead marks the last character in the buffer, that has been read
+      from input */
+  private int yy_endRead;
+
+  /** number of newlines encountered up to the start of the matched text */
+  private int yyline;
+
+  /** the number of characters up to the start of the matched text */
+  private int yychar;
+
+  /**
+   * the number of characters from the last newline up to the start of the 
+   * matched text
+   */
+  // private int yycolumn; 
+
+  /** 
+   * yy_atBOL == true <=> the scanner is currently at the beginning of a line
+   */
+  // private boolean yy_atBOL;
+
+  /** yy_atEOF == true <=> the scanner has returned a value for EOF */
+  private boolean yy_atEOF;
+
+  /** denotes if the user-EOF-code has already been executed */
+  private boolean yy_eof_done;
+
+  /* user code: */
+	private int fTokenCount = 0;
+ 
+	// required holders for white-space compacting
+	private boolean fShouldLoadBuffered = false;
+	private String fBufferedContext = null;
+	private int fBufferedStart = 1;
+	private int fBufferedLength = 0;
+	private String f_context = null;
+
+	// state stack for handling embedded regions
+	private IntStack fStateStack = new IntStack();
+
+	private String context = null;
+	private int start = 0;
+	private int textLength = 0;
+	private int length = 0;
+
+	// offset for tracking position specific block tags
+	private int fOffset = 0;
+	
+	// the name of the current tag being opened
+	private String fCurrentTagName = null;
+
+	// the list of tag name BlockMarkers
+	private List fBlockMarkers = new ArrayList();
+
+	// required to not seek text blocks on an end tag
+	private boolean fIsBlockingEnabled = false;
+	private boolean fIsCaseSensitiveBlocking = true;
+
+	private XMLParserRegionFactory fRegionFactory = new XMLParserRegionFactory();
+/**
+ * user method 
+ */
+public final void addBlockMarker(BlockMarker marker) {
+	if(containsTagName(marker.getTagName()))
+		return;
+	fBlockMarkers.add(marker);
+}
+/**
+ * user method 
+ */
+public final void removeBlockMarker(BlockMarker marker) {
+	fBlockMarkers.remove(marker);
+}
+/**
+ * user method 
+ */
+public final void removeBlockMarker(String tagname) {
+	if (fBlockMarkers != null) {
+		Iterator blocks = fBlockMarkers.iterator();
+		while (blocks.hasNext()) {
+			if (((BlockMarker) blocks.next()).getTagName().equals(tagname))
+				blocks.remove();
+		}
+	}
+}
+/* user method */
+public final boolean isCaseSensitiveBlocking() {
+	return fIsCaseSensitiveBlocking;
+}
+/* user method */
+public final void setCaseSensitiveBlocking(boolean newValue) {
+	fIsCaseSensitiveBlocking = newValue;
+}
+/* user method */
+public boolean getBlockMarkerCaseSensitivity() {
+        return getBlockMarkerCaseSensitivity(fCurrentTagName);
+}
+/* user method */
+public boolean getBlockMarkerCaseSensitivity(String name) {
+	Iterator iterator = fBlockMarkers.iterator();
+	while(iterator.hasNext()) {
+		BlockMarker marker = (BlockMarker)iterator.next();
+		boolean casesensitive = marker.isCaseSensitive();
+		if(casesensitive && marker.getTagName().equals(name))
+			return casesensitive;
+		else if(!casesensitive && marker.getTagName().equalsIgnoreCase(name))
+			return casesensitive;
+	}
+	return true;
+}
+/* user method */
+public String getBlockMarkerContext() {
+	return getBlockMarkerContext(fCurrentTagName);
+}
+/* user method */
+public String getBlockMarkerContext(String name) {
+	Iterator iterator = fBlockMarkers.iterator();
+	while(iterator.hasNext()) {
+		BlockMarker marker = (BlockMarker)iterator.next();
+		if(marker.getTagName().equals(name))
+			return marker.getContext();
+	}
+	return BLOCK_TEXT;
+}
+/* user method */
+public List getBlockMarkers() {
+	return fBlockMarkers;
+}
+/* user method */
+public final int getOffset() {
+	return fOffset + yychar;
+}
+private final boolean isBlockMarker() {
+	return isBlockMarker(fCurrentTagName);
+}
+private final boolean isBlockMarker(String tagName) {
+	if (!fIsBlockingEnabled)
+		return false;
+	return containsTagName(tagName);
+}
+/**
+ * user method
+ */
+public final void beginBlockTagScan(String newTagName) {
+	beginBlockMarkerScan(newTagName, BLOCK_TEXT);
+}
+/**
+ * user method
+ *
+ * Special tokenizer setup.  Allows tokenization to be initiated at the
+ * start of a text block within a "newTagName" tag.
+ *
+ * Example: 
+ *	Tokenizer toker = new Tokenizer();
+ *	toker.setCaseSensitiveBlocking(false);
+ *	toker.reset(new java.io.StringReader("afiuhqwkejhtasihgalkwhtq</scripter></scr></script>asgdasga"));
+ *	toker.beginBlockMarkerScan("script", BLOCK_TEXT);
+ *	toker.getRegions(); 
+ *
+ * Returns:
+ *	BLOCK_TEXT: 0-40
+ *	XML_END_TAG_OPEN: 41-42
+ *	XML_TAG_NAME: 43-48
+ *	XML_TAG_CLOSE: 49-49
+ *	XML_CONTENT: 50-57
+ *
+ */
+public final void beginBlockMarkerScan(String newTagName, String blockcontext) {
+	yybegin(ST_BLOCK_TAG_SCAN);
+	fCurrentTagName = newTagName;
+}
+/**
+ * Method doScan.
+ * 
+ * Returns a context region for all of the text from the current position upto the end of input or
+ * to right *before* the first occurence of searchString
+ * 
+ * @param searchString - target string to search for ex.: "-->", "</tagname"
+ * @param requireTailSeparator - whether the target must be immediately followed by whitespace or '>'
+ * @param context - the context of the scanned region if non-zero length
+ * @param exitState - the state to go to if the region was of non-zero length
+ * @param abortState - the state to go to if the searchString was found immediately
+ * @return String - the context found: the desired context on a non-zero length match, the abortContext on immediate success
+ * @throws IOException
+ */
+private final String doScan(String searchString, boolean requireTailSeparator, String searchContext, int exitState, int immediateFallbackState) throws IOException {
+	boolean stillSearching = true;
+	// Disable further block (probably)
+	fIsBlockingEnabled = false;
+	int searchStringLength = searchString.length();
+	int n = 0;
+	char lastCheckChar;
+	int i;
+	boolean same = false;
+	while (stillSearching) {
+		n = 0;
+		// Ensure that enough data from the input exists to compare against the search String.
+		n = yy_advance();
+		while(n != YYEOF && yy_currentPos < searchStringLength)
+			n = yy_advance();
+		// If the input was too short or we've exhausted the input, stop immediately.
+		if (n == YYEOF) {
+			stillSearching = false;
+		}
+		else {
+			same = true;
+			// Ensure that we've not encountered a complete block (<%%>) that was *shorter* than the closeTagString and
+			// thus found twice at current-targetLength [since the first scan would have come out this far anyway].
+			// Check the characters in the target versus the last targetLength characters read from the buffer
+			// and see if it matches
+			
+			// safety check for array accesses (yy_currentPos is the *last* character we can check against)
+			if(yy_currentPos >= searchStringLength && yy_currentPos <= yy_buffer.length) {
+				for(i = 0; i < searchStringLength; i++) {
+					if(same && fIsCaseSensitiveBlocking)
+						same = yy_buffer[i + yy_currentPos - searchStringLength] == searchString.charAt(i);
+					else if(same && !fIsCaseSensitiveBlocking)
+						same = Character.toLowerCase(yy_buffer[i + yy_currentPos - searchStringLength]) == Character.toLowerCase(searchString.charAt(i));
+				}
+			}
+			// safety check failed; no match is possible right now
+			else {
+				same = false;
+			}
+			if (same && requireTailSeparator && yy_currentPos < yy_buffer.length) {
+				// Additional check for close tags to ensure that targetString="</script" doesn't match
+				// "</scriptS"
+				lastCheckChar = yy_buffer[yy_currentPos];
+				// Succeed on "</script>" and "</script "
+				if(lastCheckChar == '>' || Character.isWhitespace(lastCheckChar))
+					stillSearching = false;
+			}
+			else {
+				stillSearching = !same || (yy_currentPos < yy_startRead + searchStringLength);
+			}
+		}
+	}
+	if (n != YYEOF || same) {
+		// We've stopped short of the end or definitely found a match
+		yy_markedPos = yy_currentPos - searchStringLength;
+		yy_currentPos = yy_markedPos + 1;
+		// If the searchString occurs at the very beginning of what would have
+		// been a Block, resume scanning normally immediately
+		if (yy_markedPos == yy_startRead) {
+			yybegin(immediateFallbackState);
+			return primGetNextToken();
+		}
+	}
+	else {
+		// We ran through the rest of the input
+		yy_markedPos = yy_currentPos;
+		yy_currentPos++;
+	}
+	yybegin(exitState);
+	// If the ending occurs at the very beginning of what would have
+	// been a Block, resume scanning normally immediately
+	if(yy_markedPos == yy_startRead)
+		return primGetNextToken();
+	return searchContext;
+}
+/**
+ * user method
+ *
+ * A generic lookahead-like operation
+ */
+private final String doBlockScan(String target, String targetContext, int immediateFallbackState) throws IOException {
+	return doScan(target, false, targetContext, immediateFallbackState, immediateFallbackState);
+}
+/**
+ * user method 
+ * does a lookahead for the current tag name
+ */
+private final String doBlockTagScan() throws IOException {
+        fIsCaseSensitiveBlocking = getBlockMarkerCaseSensitivity();
+	return doScan("</" + fCurrentTagName, true, getBlockMarkerContext(fCurrentTagName), YYINITIAL, YYINITIAL);
+}
+/**
+ * user method
+ *
+ * Converts the raw context String returned by the primGetNextToken()
+ * method into a full ITextRegion by pulling in values for the
+ * current offset within the scanning text.
+ *
+ * Returns null when EOF is encountered and attaches intermittently
+ * discovered whitespace onto the end of useful regions.
+ *
+ * Note that this algorithm caches the token following the one being returned
+ * so that whitespace can be collapsed.
+ */
+public final ITextRegion getNextToken() throws IOException {
+	// load the starting non-whitespace token (assume that it is so)
+	if (fShouldLoadBuffered) {
+		context = fBufferedContext;
+		start = fBufferedStart;
+		textLength = length = fBufferedLength;
+		fShouldLoadBuffered = false;
+	}
+	else {
+		context = primGetNextToken();
+		if (context == XML_TAG_NAME) {
+			if(containsTagName(yy_buffer, yy_startRead, yy_markedPos-yy_startRead))
+				fCurrentTagName = yytext();
+			else
+				fCurrentTagName = null;
+		}
+		else if (context == XML_TAG_OPEN) {
+			fIsBlockingEnabled = true;
+		}
+		else if (context == XML_END_TAG_OPEN) {
+			fIsBlockingEnabled = false;
+		}
+		start = yychar;
+		textLength = length = yylength();
+		if (yy_atEOF) {
+			fTokenCount++;
+			return null;
+		}
+	}
+	// store the next token
+	f_context = primGetNextToken();
+	if (f_context == XML_TAG_NAME) {
+		if(containsTagName(yy_buffer, yy_startRead, yy_markedPos-yy_startRead))
+			fCurrentTagName = yytext();
+		else
+			fCurrentTagName = null;
+	}
+	else if (f_context == XML_TAG_OPEN) {
+		fIsBlockingEnabled = true;
+	}
+	else if (f_context == XML_END_TAG_OPEN) {
+		fIsBlockingEnabled = false;
+	}
+	fBufferedContext = f_context;
+	fBufferedStart = yychar;
+	fBufferedLength = yylength();
+	fShouldLoadBuffered = true;
+	if (fBufferedContext == WHITE_SPACE) {
+		fShouldLoadBuffered = false;
+		length += fBufferedLength;
+	}
+	if (context == null) {
+		// EOF
+		if (Debug.debugTokenizer) {
+			System.out.println(getClass().getName() + " discovered " + fTokenCount + " tokens."); //$NON-NLS-2$//$NON-NLS-1$
+		}
+		return null;
+	}
+	fTokenCount++;
+	return fRegionFactory.createToken(context, start, textLength, length, null, fCurrentTagName);
+}
+/* user method */
+public XMLTokenizer(){
+	super();
+}
+/* user method */
+public XMLTokenizer(char[] charArray){
+		this(new CharArrayReader(charArray));
+}
+/* user method */
+public void reset(char[] charArray) {
+	reset(new CharArrayReader(charArray), 0);
+}
+/* user method */
+public void reset(char[] charArray, int newOffset) {
+	reset(new CharArrayReader(charArray), newOffset);
+}
+/* user method */
+public void reset(java.io.InputStream in) {
+	reset(new java.io.InputStreamReader(in), 0);
+}
+/* user method */
+public void reset(java.io.InputStream in, int newOffset) {
+	reset(new java.io.InputStreamReader(in), newOffset);
+}
+/* user method */
+public void reset(java.io.Reader in) {
+	reset(in, 0);
+}
+/**
+ * user method *
+ *
+ * Reset internal counters and vars to "newly created" values, in the hopes
+ * that resetting a pre-existing tokenizer is faster than creating a new one.
+ *
+ * This method contains code blocks that were essentially duplicated from the
+ * <em>generated</em> output of this specification before this method was
+ * added.  Those code blocks were under the above copyright.
+ */
+public void reset(java.io.Reader in, int newOffset) {
+	if (Debug.debugTokenizer) {
+		System.out.println("resetting tokenizer");//$NON-NLS-1$
+	}
+	fOffset = newOffset;
+
+	/* the input device */
+	yy_reader = in;
+
+	/* the current state of the DFA */
+	yy_state = 0;
+
+	/* the current lexical state */
+	yy_lexical_state = YYINITIAL;
+
+	/* this buffer contains the current text to be matched and is
+	the source of the yytext() string */
+	java.util.Arrays.fill(yy_buffer, (char)0);
+
+	/* the textposition at the last accepting state */
+	yy_markedPos = 0;
+
+	/* the textposition at the last state to be included in yytext */
+	yy_pushbackPos = 0;
+
+	/* the current text position in the buffer */
+	yy_currentPos = 0;
+
+	/* startRead marks the beginning of the yytext() string in the buffer */
+	yy_startRead = 0;
+
+	/** 
+	 * endRead marks the last character in the buffer, that has been read
+	 * from input 
+	 */
+	yy_endRead = 0;
+
+	/* number of newlines encountered up to the start of the matched text */
+	yyline = 0;
+
+	/* the number of characters up to the start of the matched text */
+	yychar = 0;
+
+	/* yy_atEOF == true <=> the scanner has returned a value for EOF */
+	yy_atEOF = false;
+
+	/* denotes if the user-EOF-code has already been executed */
+	yy_eof_done = false;
+
+
+	/* user vars: */
+	fTokenCount = 0;
+ 
+	fShouldLoadBuffered = false;
+	fBufferedContext = null;
+	fBufferedStart = 1;
+	fBufferedLength = 0;
+	fStateStack = new IntStack();
+
+	context = null;
+	start = 0;
+	textLength = 0;
+	length = 0;
+}
+
+	/**
+	 * user method
+	 *
+	 */
+	public BlockTokenizer newInstance() {
+		XMLTokenizer newInstance = new XMLTokenizer();
+		// global tagmarkers can be shared; they have no state and 
+		// are never destroyed (e.g. 'release')
+		for(int i = 0; i < fBlockMarkers.size(); i++) {
+			BlockMarker blockMarker = (BlockMarker) fBlockMarkers.get(i);
+			if(blockMarker.isGlobal())
+				newInstance.addBlockMarker(blockMarker);
+		}
+		return newInstance;
+	}
+/* user method */
+private final String scanXMLCommentText() throws IOException {
+	// Scan for '-->' and return the text up to that point as
+	//   XML_COMMENT_TEXT unless the string occurs IMMEDIATELY, in which
+	//  case change to the ST_XML_COMMENT_END state and return the next
+	//  context as usual.
+	return doScan("-->", false, XML_COMMENT_TEXT, ST_XML_COMMENT_END, ST_XML_COMMENT_END);
+}
+
+
+  /**
+   * Creates a new scanner
+   * There is also a java.io.InputStream version of this constructor.
+   *
+   * @param   in  the java.io.Reader to read input from.
+   */
+  public XMLTokenizer(java.io.Reader in) {
+    this.yy_reader = in;
+  }
+
+  /**
+   * Creates a new scanner.
+   * There is also java.io.Reader version of this constructor.
+   *
+   * @param   in  the java.io.Inputstream to read input from.
+   */
+  public XMLTokenizer(java.io.InputStream in) {
+    this(new java.io.InputStreamReader(in));
+  }
+
+  /** 
+   * Unpacks the compressed DFA transition table.
+   *
+   * @param packed   the packed transition table
+   * @return         the unpacked transition table
+   */
+  private static int [] yy_unpack(String packed) {
+    int [] trans = new int[11055];
+    int i = 0;  /* index in packed string  */
+    int j = 0;  /* index in unpacked array */
+    while (i < 3638) {
+      int count = packed.charAt(i++);
+      int value = packed.charAt(i++);
+      value--;
+      do trans[j++] = value; while (--count > 0);
+    }
+    return trans;
+  }
+
+  /** 
+   * Unpacks the compressed character translation table.
+   *
+   * @param packed   the packed character translation table
+   * @return         the unpacked character translation table
+   */
+  private static char [] yy_unpack_cmap(String packed) {
+    char [] map = new char[0x10000];
+    int i = 0;  /* index in packed string  */
+    int j = 0;  /* index in unpacked array */
+    while (i < 1372) {
+      int  count = packed.charAt(i++);
+      char value = packed.charAt(i++);
+      do map[j++] = value; while (--count > 0);
+    }
+    return map;
+  }
+
+
+  /**
+   * Gets the next input character.
+   *
+   * @return      the next character of the input stream, EOF if the
+   *              end of the stream is reached.
+   * @exception   IOException  if any I/O-Error occurs
+   */
+  private int yy_advance() throws java.io.IOException {
+
+    /* standard case */
+    if (yy_currentPos < yy_endRead) return yy_buffer[yy_currentPos++];
+
+    /* if the eof is reached, we don't need to work hard */ 
+    if (yy_atEOF) return YYEOF;
+
+    /* otherwise: need to refill the buffer */
+
+    /* first: make room (if you can) */
+    if (yy_startRead > 0) {
+      System.arraycopy(yy_buffer, yy_startRead, 
+                       yy_buffer, 0, 
+                       yy_endRead-yy_startRead);
+
+      /* translate stored positions */
+      yy_endRead-= yy_startRead;
+      yy_currentPos-= yy_startRead;
+      yy_markedPos-= yy_startRead;
+      yy_pushbackPos-= yy_startRead;
+      yy_startRead = 0;
+    }
+
+    /* is the buffer big enough? */
+    if (yy_currentPos >= yy_buffer.length) {
+      /* if not: blow it up */
+      char newBuffer[] = new char[yy_currentPos*2];
+      System.arraycopy(yy_buffer, 0, newBuffer, 0, yy_buffer.length);
+      yy_buffer = newBuffer;
+    }
+
+    /* finally: fill the buffer with new input */
+    int numRead = yy_reader.read(yy_buffer, yy_endRead, 
+                                            yy_buffer.length-yy_endRead);
+
+    if ( numRead == -1 ) return YYEOF;
+
+    yy_endRead+= numRead;
+
+    return yy_buffer[yy_currentPos++];
+  }
+
+    
+  /**
+   * Closes the input stream.
+   */
+  final public void yyclose() throws java.io.IOException {
+    yy_atEOF = true;            /* indicate end of file */
+    yy_endRead = yy_startRead;  /* invalidate buffer    */
+    yy_reader.close();
+  }
+
+
+  /**
+   * Returns the current lexical state.
+   */
+  final public int yystate() {
+    return yy_lexical_state;
+  }
+
+  /**
+   * Enters a new lexical state
+   *
+   * @param newState the new lexical state
+   */
+  final public void yybegin(int newState) {
+    yy_lexical_state = newState;
+  }
+
+
+  /**
+   * Returns the text matched by the current regular expression.
+   */
+  final public String yytext() {
+    return new String( yy_buffer, yy_startRead, yy_markedPos-yy_startRead );
+  }
+
+  /**
+   * Returns the length of the matched text region.
+   */
+  final public int yylength() {
+    return yy_markedPos-yy_startRead;
+  }
+
+
+  /**
+   * Reports an error that occured while scanning - from the SED JFlex skeleton
+   *
+   * @param   errorCode  the code of the errormessage to display
+   */
+  private void yy_ScanError(int errorCode) {
+    try {
+      Logger.log(Logger.ERROR, YY_ERROR_MSG[errorCode]);
+    }
+    catch (ArrayIndexOutOfBoundsException e) {
+      Logger.log(Logger.ERROR, YY_ERROR_MSG[YY_UNKNOWN_ERROR]);
+    }
+    // DO NOT EXIT the VM on an error
+    // System.exit(1);
+  } 
+
+
+  /**
+   * Pushes the specified amount of characters back into the input stream.
+   *
+   * They will be read again by then next call of the scanning method
+   *
+   * @param number  the number of characters to be read again.
+   *                This number must not be greater than yylength()!
+   */
+  void yypushback(int number) {
+    if ( number > yylength() )
+      yy_ScanError(YY_PUSHBACK_2BIG);
+
+    yy_markedPos -= number;
+  }
+
+	/**
+	 * user method - skeleton.sed
+	 */
+	protected final boolean containsTagName(char[] markerTagName, int offset, int tagnameLength) {
+		for(int j = 0; j < fBlockMarkers.size(); j++) {
+			BlockMarker marker = (BlockMarker)fBlockMarkers.get(j);
+			if(marker.getTagName().length() == tagnameLength) {
+				boolean matchesSoFar = true;
+				for(int i = 0; i < tagnameLength && matchesSoFar; i++) {
+					if(marker.isCaseSensitive()) {
+						if(marker.getTagName().charAt(i) != markerTagName[i + offset])
+							matchesSoFar = false;
+					}
+					else {
+						if(Character.toLowerCase(marker.getTagName().charAt(i)) != Character.toLowerCase(markerTagName[i + offset]))
+							matchesSoFar = false;
+					}
+				}
+				if(matchesSoFar)
+					return true;
+			}
+		}
+		return false;
+	}
+
+	/**
+	 * user method - skeleton.sed
+	 *
+	 * Return ALL of the regions scannable within the remaining text
+	 * Note: for verification use
+	 */
+	public final List getRegions() {
+		List tokens = new ArrayList();
+		ITextRegion region = null;
+		try {
+			region = getNextToken();
+			while(region != null) {
+				if (region != null) {
+					tokens.add(region);
+				}
+				region = getNextToken();
+			}
+		}
+		catch (StackOverflowError e) {
+			Logger.logException(getClass().getName()+": input could not be tokenized correctly at position " + getOffset(), e);//$NON-NLS-1$
+			throw e;
+		}
+		catch (Exception e) {
+			// Since this is convenience method and NOT the recommended 
+			// way of getting tokens, many errors are simply hidden
+			Logger.logException("Exception not handled retrieving regions: " + e.getLocalizedMessage(), e);//$NON-NLS-1$
+		}
+		return tokens;
+	}
+	/**
+	 * user method - skeleton.sed
+	 */
+	private final void dump(String s) {
+		if (Debug.debugTokenizer) {
+			System.out.println(s + " (" + yychar + "-" + //$NON-NLS-2$//$NON-NLS-1$
+				(yylength() + yychar) + "):\'" +//$NON-NLS-1$
+					StringUtils.escape(yytext()) + "\'");//$NON-NLS-1$
+		}
+	}
+	/* user method  - skeleton.sed */
+	public final boolean isEOF() {
+		return yy_atEOF;
+	}
+/* user method - skeleton.sed */
+protected final boolean containsTagName(String markerTagName) {
+	Iterator blocks = fBlockMarkers.iterator();
+	while(blocks.hasNext()) {
+		BlockMarker marker = (BlockMarker)blocks.next();
+		if(marker.isCaseSensitive()) {
+			if(marker.getTagName().equals(markerTagName))
+				return true;
+		}
+		else {
+			if(marker.getTagName().equalsIgnoreCase(markerTagName))
+				return true;
+		}
+	}
+	return false;
+}
+
+  /**
+   * Contains user EOF-code, which will be executed exactly once,
+   * when the end of file is reached
+   */
+  private void yy_do_eof() {
+    if (!yy_eof_done) {
+      yy_eof_done = true;
+    // do nothing, this is the downstream parser's job
+
+    }
+  }
+
+
+  /**
+   * Resumes scanning until the next regular expression is matched,
+   * the end of input is encountered or an I/O-Error occurs.
+   *
+   * @return      the next token
+   * @exception   IOException  if any I/O-Error occurs
+   */
+  public String primGetNextToken() throws java.io.IOException {
+    int yy_input;
+    int yy_action;
+
+
+    while (true) {
+
+      yychar+= yylength();
+
+      boolean yy_counted = false;
+      for (yy_currentPos = yy_startRead; yy_currentPos < yy_markedPos;
+                                                      yy_currentPos++) {
+        switch (yy_buffer[yy_currentPos]) {
+        case '\r':
+          yyline++;
+          yy_counted = true;
+          break;
+        case '\n':
+          if (yy_counted)
+            yy_counted = false;
+          else {
+            yyline++;
+          }
+          break;
+        default:
+          yy_counted = false;
+        }
+      }
+
+      if (yy_counted) {
+        if ( yy_advance() == '\n' ) yyline--;
+        if ( !yy_atEOF ) yy_currentPos--;
+      }
+
+      yy_action = -1;
+
+      yy_currentPos = yy_startRead = yy_markedPos;
+
+      yy_state = yy_lexical_state;
+
+
+      yy_forAction: {
+        while (true) {
+    
+          yy_input = yy_advance();
+
+          if ( yy_input == YYEOF ) break yy_forAction;
+
+          int yy_next = yytrans[ yy_rowMap[yy_state] + yycmap[yy_input] ];
+          if (yy_next == -1) break yy_forAction;
+          yy_state = yy_next;
+
+          int yy_attributes = YY_ATTRIBUTE[yy_state];
+          if ( (yy_attributes & 1) > 0 ) {
+            yy_action = yy_state; 
+            yy_markedPos = yy_currentPos; 
+            if ( (yy_attributes & 8) > 0 ) break yy_forAction;
+          }
+
+        }
+      }
+
+
+      switch (yy_action) {    
+
+        case 291: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("XSL processing instruction target");//$NON-NLS-1$
+        yybegin(ST_XML_PI_ATTRIBUTE_NAME);
+        return XML_TAG_NAME;
+ }
+        case 293: break;
+        case 283: 
+        case 285: 
+        case 286: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("\nCDATA start");//$NON-NLS-1$
+	fStateStack.push(yystate());
+	yybegin(ST_CDATA_TEXT);
+	return XML_CDATA_OPEN;
+ }
+        case 294: break;
+        case 276: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("element");//$NON-NLS-1$
+	yybegin(ST_XML_ELEMENT_DECLARATION);
+	return XML_ELEMENT_DECLARATION;
+ }
+        case 295: break;
+        case 275: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("attlist");//$NON-NLS-1$
+	yybegin(ST_XML_ATTLIST_DECLARATION);
+	return XML_ATTLIST_DECLARATION;
+ }
+        case 296: break;
+        case 274: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("doctype");//$NON-NLS-1$
+	yybegin(ST_XML_DOCTYPE_DECLARATION);
+	return XML_DOCTYPE_DECLARATION;
+ }
+        case 297: break;
+        case 268: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("doctype external id");//$NON-NLS-1$
+	yybegin(ST_XML_DOCTYPE_ID_PUBLIC);
+	return XML_DOCTYPE_EXTERNAL_ID_PUBLIC;
+ }
+        case 298: break;
+        case 267: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("doctype external id");//$NON-NLS-1$
+	yybegin(ST_XML_DOCTYPE_ID_SYSTEM);
+	return XML_DOCTYPE_EXTERNAL_ID_SYSTEM;
+ }
+        case 299: break;
+        case 263: 
+        case 273: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("DHTML processing instruction target");//$NON-NLS-1$
+        yybegin(ST_DHTML_ATTRIBUTE_NAME);
+        return XML_TAG_NAME;
+ }
+        case 300: break;
+        case 237: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("\nCharRef");//$NON-NLS-1$
+	return XML_CHAR_REFERENCE;
+ }
+        case 301: break;
+        case 234: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("\ncomment start");//$NON-NLS-1$
+	yybegin(ST_XML_COMMENT);
+	return XML_COMMENT_OPEN;
+ }
+        case 302: break;
+        case 215: 
+        case 216: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("XML processing instruction target");//$NON-NLS-1$
+        yybegin(ST_XML_PI_ATTRIBUTE_NAME);
+        return XML_TAG_NAME;
+ }
+        case 303: break;
+        case 214: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("comment end");//$NON-NLS-1$
+	yybegin(YYINITIAL);
+	return XML_COMMENT_CLOSE;
+ }
+        case 304: break;
+        case 213: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("CDATA end");//$NON-NLS-1$
+	yybegin(fStateStack.pop());
+	return XML_CDATA_CLOSE;
+ }
+        case 305: break;
+        case 212: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("\nPEReference");//$NON-NLS-1$
+	return XML_PE_REFERENCE;
+ }
+        case 306: break;
+        case 209: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("\nEntityRef");//$NON-NLS-1$
+	return XML_ENTITY_REFERENCE;
+ }
+        case 307: break;
+        case 160: 
+        case 174: 
+        case 182: 
+          { 
+	return XML_DOCTYPE_INTERNAL_SUBSET;
+ }
+        case 308: break;
+        case 148: 
+          { 
+        yybegin(YYINITIAL);
+	if(Debug.debugTokenizer)
+		dump("empty tag close");//$NON-NLS-1$
+        return XML_EMPTY_TAG_CLOSE;
+ }
+        case 309: break;
+        case 133: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("XML processing instruction end");//$NON-NLS-1$
+        yybegin(YYINITIAL);
+        return XML_PI_CLOSE;
+ }
+        case 310: break;
+        case 132: 
+          { 
+		// ended with nothing inside
+        yybegin(YYINITIAL);
+        return XML_PI_CLOSE;
+ }
+        case 311: break;
+        case 128: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("processing instruction end");//$NON-NLS-1$
+        yybegin(YYINITIAL);
+        return XML_PI_CLOSE;
+ }
+        case 312: break;
+        case 120: 
+          { 
+	fStateStack.push(yystate());
+	if(Debug.debugTokenizer)
+		dump("\ndeclaration start");//$NON-NLS-1$
+        yybegin(ST_XML_DECLARATION);
+	return XML_DECLARATION_OPEN;
+ }
+        case 313: break;
+        case 119: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("\nprocessing instruction start");//$NON-NLS-1$
+	yybegin(ST_PI);
+        return XML_PI_OPEN;
+ }
+        case 314: break;
+        case 63: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("DHTML processing instruction end");//$NON-NLS-1$
+        yybegin(YYINITIAL);
+        return XML_PI_CLOSE;
+ }
+        case 315: break;
+        case 57: 
+        case 59: 
+        case 60: 
+        case 61: 
+        case 137: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("XML processing instruction attribute value");//$NON-NLS-1$
+        yybegin(ST_XML_PI_ATTRIBUTE_NAME);
+        return XML_TAG_ATTRIBUTE_VALUE;
+ }
+        case 316: break;
+        case 56: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("XML processing instruction '='");//$NON-NLS-1$
+        yybegin(ST_XML_PI_ATTRIBUTE_VALUE);
+        return XML_TAG_ATTRIBUTE_EQUALS;
+ }
+        case 317: break;
+        case 55: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("XML processing instruction attribute name");//$NON-NLS-1$
+        yybegin(ST_XML_PI_EQUALS);
+        return XML_TAG_ATTRIBUTE_NAME;
+ }
+        case 318: break;
+        case 51: 
+        case 52: 
+        case 53: 
+          { 
+	// block scan until close is found
+	return doScan("?>", false, XML_PI_CONTENT, ST_XML_PI_TAG_CLOSE, ST_XML_PI_TAG_CLOSE);
+ }
+        case 319: break;
+        case 50: 
+          { 
+        yybegin(ST_PI_CONTENT);
+        return WHITE_SPACE;
+ }
+        case 320: break;
+        case 46: 
+        case 47: 
+        case 48: 
+        case 49: 
+        case 129: 
+        case 130: 
+        case 131: 
+        case 217: 
+        case 239: 
+        case 240: 
+        case 252: 
+        case 253: 
+        case 262: 
+        case 272: 
+        case 280: 
+        case 284: 
+        case 287: 
+        case 288: 
+        case 289: 
+        case 290: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("processing instruction target");//$NON-NLS-1$
+        yybegin(ST_PI_WS);
+        return XML_TAG_NAME;
+ }
+        case 321: break;
+        case 41: 
+        case 42: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("comment content");//$NON-NLS-1$
+	return scanXMLCommentText();
+ }
+        case 322: break;
+        case 40: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("LINE FEED");//$NON-NLS-1$
+	return WHITE_SPACE;
+ }
+        case 323: break;
+        case 0: 
+        case 31: 
+        case 122: 
+        case 124: 
+        case 207: 
+        case 208: 
+        case 236: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("\nXML content");//$NON-NLS-1$
+	return XML_CONTENT;
+ }
+        case 324: break;
+        case 5: 
+        case 8: 
+        case 9: 
+        case 10: 
+        case 12: 
+        case 13: 
+        case 14: 
+        case 15: 
+        case 17: 
+        case 18: 
+        case 19: 
+        case 20: 
+        case 21: 
+        case 22: 
+        case 23: 
+        case 24: 
+        case 25: 
+        case 26: 
+        case 28: 
+        case 45: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("white space");//$NON-NLS-1$
+        return WHITE_SPACE;
+ }
+        case 325: break;
+        case 16: 
+        case 71: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("inappropriate tag name");//$NON-NLS-1$
+	yybegin(YYINITIAL);
+        return XML_CONTENT;
+ }
+        case 326: break;
+        case 27: 
+        case 106: 
+        case 107: 
+        case 193: 
+        case 229: 
+        case 248: 
+        case 259: 
+        case 269: 
+        case 277: 
+        case 281: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("elementdecl contentspec");//$NON-NLS-1$
+	return XML_ELEMENT_DECL_CONTENT;
+ }
+        case 327: break;
+        case 29: 
+        case 113: 
+        case 114: 
+        case 204: 
+        case 233: 
+        case 250: 
+        case 260: 
+        case 270: 
+        case 278: 
+        case 282: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("attlist contentspec");//$NON-NLS-1$
+	return XML_ATTLIST_DECL_CONTENT;
+ }
+        case 328: break;
+        case 32: 
+        case 72: 
+        case 83: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("\nstart tag open");//$NON-NLS-1$
+        yybegin(ST_XML_TAG_NAME);
+        return XML_TAG_OPEN;
+ }
+        case 329: break;
+        case 33: 
+        case 34: 
+        case 37: 
+        case 38: 
+        case 39: 
+        case 43: 
+        case 44: 
+        case 54: 
+        case 58: 
+        case 62: 
+        case 64: 
+        case 68: 
+        case 74: 
+        case 80: 
+        case 85: 
+        case 86: 
+        case 87: 
+        case 88: 
+        case 90: 
+        case 91: 
+        case 93: 
+        case 98: 
+        case 103: 
+        case 110: 
+          { 
+	if (Debug.debugTokenizer)
+		System.out.println("!!!unexpected!!!: \"" + yytext() + "\":" + //$NON-NLS-2$//$NON-NLS-1$
+			yychar + "-" + (yychar + yylength()));//$NON-NLS-1$
+	return UNDEFINED;
+ }
+        case 330: break;
+        case 35: 
+        case 36: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("CDATA text");//$NON-NLS-1$
+	String blockContext = doBlockScan("]]>", XML_CDATA_TEXT, ST_CDATA_END);//$NON-NLS-1$
+	if(blockContext == XML_CDATA_TEXT)
+		yybegin(ST_CDATA_END);
+	return blockContext;
+ }
+        case 331: break;
+        case 65: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("DHTML processing instruction attribute name");//$NON-NLS-1$
+        yybegin(ST_DHTML_EQUALS);
+        return XML_TAG_ATTRIBUTE_NAME;
+ }
+        case 332: break;
+        case 66: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("DHTML processing instruction '='");//$NON-NLS-1$
+        yybegin(ST_DHTML_ATTRIBUTE_VALUE);
+        return XML_TAG_ATTRIBUTE_EQUALS;
+ }
+        case 333: break;
+        case 67: 
+        case 69: 
+        case 70: 
+        case 145: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("DHTML processing instruction attribute value");//$NON-NLS-1$
+        yybegin(ST_DHTML_ATTRIBUTE_NAME);
+        return XML_TAG_ATTRIBUTE_VALUE;
+ }
+        case 334: break;
+        case 73: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("tag close");//$NON-NLS-1$
+	if(isBlockMarker()) {
+        	yybegin(ST_BLOCK_TAG_SCAN);
+	}
+	else
+        	yybegin(YYINITIAL);
+        return XML_TAG_CLOSE;
+ }
+        case 335: break;
+        case 75: 
+        case 76: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("tag name");//$NON-NLS-1$
+        yybegin(ST_XML_ATTRIBUTE_NAME);
+        return XML_TAG_NAME;
+ }
+        case 336: break;
+        case 77: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("attr name");//$NON-NLS-1$
+        yybegin(ST_XML_EQUALS);
+        return XML_TAG_ATTRIBUTE_NAME;
+ }
+        case 337: break;
+        case 78: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("equals");//$NON-NLS-1$
+        yybegin(ST_XML_ATTRIBUTE_VALUE);
+        return XML_TAG_ATTRIBUTE_EQUALS;
+ }
+        case 338: break;
+        case 79: 
+        case 81: 
+        case 82: 
+        case 152: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("attr value");//$NON-NLS-1$
+        yybegin(ST_XML_ATTRIBUTE_NAME);
+        return XML_TAG_ATTRIBUTE_VALUE;
+ }
+        case 339: break;
+        case 84: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("declaration end");//$NON-NLS-1$
+	if (Debug.debugTokenizer) {
+		if(fStateStack.peek()!=YYINITIAL)
+			System.out.println("end embedded region");//$NON-NLS-1$
+	}
+	yybegin(fStateStack.pop());
+	return XML_DECLARATION_CLOSE;
+ }
+        case 340: break;
+        case 89: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("doctype type");//$NON-NLS-1$
+	yybegin(ST_XML_DOCTYPE_EXTERNAL_ID);
+	return XML_DOCTYPE_NAME;
+ }
+        case 341: break;
+        case 92: 
+        case 94: 
+        case 95: 
+        case 96: 
+        case 166: 
+        case 167: 
+        case 170: 
+        case 171: 
+        case 224: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("doctype public reference");//$NON-NLS-1$
+	yybegin(ST_XML_DOCTYPE_ID_SYSTEM);
+	return XML_DOCTYPE_EXTERNAL_ID_PUBREF;
+ }
+        case 342: break;
+        case 97: 
+        case 99: 
+        case 100: 
+        case 101: 
+        case 178: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("doctype system reference");//$NON-NLS-1$
+	yybegin(ST_XML_DECLARATION_CLOSE);
+	return XML_DOCTYPE_EXTERNAL_ID_SYSREF;
+ }
+        case 343: break;
+        case 102: 
+        case 104: 
+        case 105: 
+        case 186: 
+        case 187: 
+        case 190: 
+        case 191: 
+        case 227: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("elementdecl name");//$NON-NLS-1$
+	yybegin(ST_XML_ELEMENT_DECLARATION_CONTENT);
+	return XML_ELEMENT_DECL_NAME;
+ }
+        case 344: break;
+        case 108: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("elementdecl close");//$NON-NLS-1$
+	if (Debug.debugTokenizer) {
+		if(fStateStack.peek()!=YYINITIAL)
+			System.out.println("end embedded region");//$NON-NLS-1$
+	}
+	yybegin(fStateStack.pop());
+	return XML_DECLARATION_CLOSE;
+ }
+        case 345: break;
+        case 109: 
+        case 111: 
+        case 112: 
+        case 197: 
+        case 198: 
+        case 201: 
+        case 202: 
+        case 231: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("attlist name");//$NON-NLS-1$
+	yybegin(ST_XML_ATTLIST_DECLARATION_CONTENT);
+	return XML_ATTLIST_DECL_NAME;
+ }
+        case 346: break;
+        case 115: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("attlist close");//$NON-NLS-1$
+	if (Debug.debugTokenizer) {
+		if(fStateStack.peek()!=YYINITIAL)
+			System.out.println("end embedded region");//$NON-NLS-1$
+	}
+	yybegin(fStateStack.pop());
+	return XML_DECLARATION_CLOSE;
+ }
+        case 347: break;
+        case 118: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("\nend tag open");//$NON-NLS-1$
+        yybegin(ST_XML_TAG_NAME);
+        return XML_END_TAG_OPEN;
+ }
+        case 348: break;
+        case 116: 
+        case 117: 
+          { 
+		return doBlockTagScan();
+	 }
+        case 349: break;
+        default: 
+          if (yy_input == YYEOF && yy_startRead == yy_currentPos) {
+            yy_atEOF = true;
+            yy_do_eof();
+              return null;
+          } 
+          else {
+            yy_ScanError(YY_NO_MATCH);
+          }
+      }
+    }
+  }    
+
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/AttributeEqualsRegion.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/AttributeEqualsRegion.java
new file mode 100644
index 0000000..836dd41
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/AttributeEqualsRegion.java
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.parser.regions;
+
+import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentEvent;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+
+
+
+public class AttributeEqualsRegion implements ITextRegion {
+	static private final byte fTextLength = 1;
+	static private final String fType = DOMRegionContext.XML_TAG_ATTRIBUTE_EQUALS;
+	private short fLength;
+	private int fStart;
+
+
+	public AttributeEqualsRegion() {
+		super();
+	}
+
+	public AttributeEqualsRegion(int start, int textLength, int length) {
+		this();
+		fStart = start;
+		fLength = (short) length;
+	}
+
+
+	public void adjustLength(int i) {
+		fLength += i;
+
+	}
+
+	public void adjustStart(int i) {
+		fStart += i;
+
+	}
+
+	public void adjustTextLength(int i) {
+		// not supported
+
+	}
+
+	public void equatePositions(ITextRegion region) {
+		fStart = region.getStart();
+		fLength = (short) region.getLength();
+	}
+
+	public int getEnd() {
+		return fStart + fLength;
+	}
+
+	public int getLength() {
+		return fLength;
+	}
+
+	public int getStart() {
+		return fStart;
+	}
+
+	public int getTextEnd() {
+		return fStart + fTextLength;
+	}
+
+	public int getTextLength() {
+		return fTextLength;
+	}
+
+	public String getType() {
+		return fType;
+	}
+
+	public String toString() {
+		return RegionToStringUtil.toString(this);
+	}
+
+	public StructuredDocumentEvent updateRegion(Object requester, IStructuredDocumentRegion parent, String changes, int requestStart, int lengthToReplace) {
+		// can never be updated
+		return null;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/AttributeNameRegion.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/AttributeNameRegion.java
new file mode 100644
index 0000000..a2c4158
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/AttributeNameRegion.java
@@ -0,0 +1,165 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.parser.regions;
+
+import org.eclipse.wst.sse.core.internal.provisional.events.RegionChangedEvent;
+import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentEvent;
+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.util.Debug;
+import org.eclipse.wst.sse.core.internal.util.Utilities;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+
+
+public class AttributeNameRegion implements ITextRegion {
+	// specify correct type
+	static private final String fType = DOMRegionContext.XML_TAG_ATTRIBUTE_NAME;
+	private int fLength;
+	private int fStart;
+	private int fTextLength;
+
+	public AttributeNameRegion() {
+		super();
+	}
+
+	public AttributeNameRegion(int start, int textLength, int length) {
+		this();
+		fStart = start;
+		fTextLength = textLength;
+		fLength = length;
+	}
+
+	public void adjustLength(int i) {
+		fLength += i;
+
+	}
+
+	public void adjustStart(int i) {
+		fStart += i;
+
+	}
+
+	public void adjustTextLength(int i) {
+		fTextLength += 1;
+
+	}
+
+	public void equatePositions(ITextRegion region) {
+		fStart = region.getStart();
+		fLength = region.getLength();
+		fTextLength = region.getTextLength();
+	}
+
+	public int getEnd() {
+		return fStart + fLength;
+	}
+
+	public int getLength() {
+		return fLength;
+	}
+
+	public int getStart() {
+		return fStart;
+	}
+
+	public int getTextEnd() {
+		return fStart + fTextLength;
+	}
+
+	public int getTextLength() {
+		return fTextLength;
+	}
+
+	public String getType() {
+		return fType;
+	}
+
+	public String toString() {
+		return RegionToStringUtil.toString(this);
+	}
+
+	public StructuredDocumentEvent updateRegion(Object requester, IStructuredDocumentRegion parent, String changes, int requestStart, int lengthToReplace) {
+		RegionChangedEvent result = null;
+		// if the region is an easy type (e.g. attribute value),
+		// and the requested changes are all
+		// alphanumeric, then make the change here locally.
+		// (This can obviously be made more sophisticated as the need arises,
+		// but should
+		// always follow this pattern.)
+		if (Debug.debugStructuredDocument) {
+			System.out.println("\t\tContextRegion::updateModel"); //$NON-NLS-1$
+			System.out.println("\t\t\tregion type is " + fType); //$NON-NLS-1$
+		}
+		boolean canHandle = false;
+		// note: we'll always handle deletes from these
+		// regions ... if its already that region,
+		// deleting something from it won't change its
+		// type. (remember, the calling program needs
+		// to insure we are not called, if not all contained
+		// on one region.
+		if ((changes == null) || (changes.length() == 0)) {
+			// delete case
+			// We can not do the quick delete, if
+			// if all the text in a region is to be deleted.
+			// Or, if the delete starts in the white space region.
+			// In these cases, a reparse is needed.
+			// Minor note, we use textEnd-start since it always
+			// less than or equal to end-start. This might
+			// cause us to miss a few cases we could have handled,
+			// but will prevent us from trying to handle funning cases
+			// involving whitespace.
+			if ((fStart >= getTextEnd()) || (Math.abs(lengthToReplace) >= getTextEnd() - getStart())) {
+				canHandle = false;
+			} else {
+				canHandle = true;
+			}
+		} else {
+			if ((RegionUpdateRule.canHandleAsWhiteSpace(this, parent, changes, requestStart, lengthToReplace)) || RegionUpdateRule.canHandleAsLetterOrDigit(this, parent, changes, requestStart, lengthToReplace)) {
+				canHandle = true;
+			} else {
+				canHandle = false;
+			}
+
+		}
+		if (canHandle) {
+			// at this point, we still have the old region. We won't create a
+			// new instance, we'll just update the one we have, by changing
+			// its end postion,
+			// The parent flatnode, upon return, has responsibility
+			// for updating sibling regions.
+			// and in turn, the structuredDocument itself has responsibility
+			// for
+			// updating the text store and down stream flatnodes.
+			if (Debug.debugStructuredDocument) {
+				System.out.println("change handled by region"); //$NON-NLS-1$
+			}
+			int lengthDifference = Utilities.calculateLengthDifference(changes, lengthToReplace);
+			// Note: we adjust both end and text end, because for any change
+			// that is in only the trailing whitespace region, we should not
+			// do a quick change,
+			// so 'canHandle' should have been false for those case.
+			// TO_DO_FUTURE: cache value of canHandleAsWhiteSpace from above
+			// If we are handling as whitespace, there is no need to increase
+			// the text length, only
+			// the total length is changing.
+			if (!RegionUpdateRule.canHandleAsWhiteSpace(this, parent, changes, requestStart, lengthToReplace)) {
+				fTextLength += lengthDifference;
+			}
+			fLength += lengthDifference;
+			result = new RegionChangedEvent(parent.getParentDocument(), requester, parent, this, changes, requestStart, lengthToReplace);
+		}
+
+		return result;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/AttributeValueRegion.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/AttributeValueRegion.java
new file mode 100644
index 0000000..7fbbbbf
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/AttributeValueRegion.java
@@ -0,0 +1,162 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.parser.regions;
+
+import org.eclipse.wst.sse.core.internal.provisional.events.RegionChangedEvent;
+import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentEvent;
+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.util.Debug;
+import org.eclipse.wst.sse.core.internal.util.Utilities;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+
+
+public class AttributeValueRegion implements ITextRegion {
+	// specify correct type
+	static private final String fType = DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE;
+	private int fLength;
+	private int fStart;
+	private int fTextLength;
+
+	public AttributeValueRegion() {
+		super();
+	}
+
+	public AttributeValueRegion(int start, int textLength, int length) {
+		this();
+		fStart = start;
+		fTextLength = textLength;
+		fLength = length;
+	}
+
+	public void adjustLength(int i) {
+		fLength += i;
+	}
+
+	public void adjustStart(int i) {
+		fStart += i;
+	}
+
+	public void adjustTextLength(int i) {
+		fTextLength += 1;
+	}
+
+	public void equatePositions(ITextRegion region) {
+		fStart = region.getStart();
+		fLength = region.getLength();
+		fTextLength = region.getTextLength();
+	}
+
+	public int getEnd() {
+		return fStart + fLength;
+	}
+
+	public int getLength() {
+		return fLength;
+	}
+
+	public int getStart() {
+		return fStart;
+	}
+
+	public int getTextEnd() {
+		return fStart + fTextLength;
+	}
+
+	public int getTextLength() {
+		return fTextLength;
+	}
+
+	public String getType() {
+		return fType;
+	}
+
+	public String toString() {
+		return RegionToStringUtil.toString(this);
+	}
+
+	public StructuredDocumentEvent updateRegion(Object requester, IStructuredDocumentRegion parent, String changes, int requestStart, int lengthToReplace) {
+		RegionChangedEvent result = null;
+		// if the region is an easy type (e.g. attribute value),
+		// and the requested changes are all
+		// alphanumeric, then make the change here locally.
+		// (This can obviously be made more sophisticated as the need arises,
+		// but should
+		// always follow this pattern.)
+		if (Debug.debugStructuredDocument) {
+			System.out.println("\t\tContextRegion::updateModel"); //$NON-NLS-1$
+			System.out.println("\t\t\tregion type is " + fType); //$NON-NLS-1$
+		}
+		boolean canHandle = false;
+		// note: we'll always handle deletes from these
+		// regions ... if its already that region,
+		// deleting something from it won't change its
+		// type. (remember, the calling program needs
+		// to insure we are not called, if not all contained
+		// on one region.
+		if ((changes == null) || (changes.length() == 0)) {
+			// delete case
+			// We can not do the quick delete, if
+			// if all the text in a region is to be deleted.
+			// Or, if the delete starts in the white space region.
+			// In these cases, a reparse is needed.
+			// Minor note, we use textEnd-start since it always
+			// less than or equal to end-start. This might
+			// cause us to miss a few cases we could have handled,
+			// but will prevent us from trying to handle funning cases
+			// involving whitespace.
+			if ((fStart >= getTextEnd()) || (Math.abs(lengthToReplace) >= getTextEnd() - getStart())) {
+				canHandle = false;
+			} else {
+				canHandle = true;
+			}
+		} else {
+			if ((RegionUpdateRule.canHandleAsWhiteSpace(this, parent, changes, requestStart, lengthToReplace)) || RegionUpdateRule.canHandleAsLetterOrDigit(this, parent, changes, requestStart, lengthToReplace)) {
+				canHandle = true;
+			} else {
+				canHandle = false;
+			}
+		}
+		if (canHandle) {
+			// at this point, we still have the old region. We won't create a
+			// new instance, we'll just update the one we have, by changing
+			// its end postion,
+			// The parent flatnode, upon return, has responsibility
+			// for updating sibling regions.
+			// and in turn, the structuredDocument itself has responsibility
+			// for
+			// updating the text store and down stream flatnodes.
+			if (Debug.debugStructuredDocument) {
+				System.out.println("change handled by region"); //$NON-NLS-1$
+			}
+			int lengthDifference = Utilities.calculateLengthDifference(changes, lengthToReplace);
+			// Note: we adjust both end and text end, because for any change
+			// that is in only the trailing whitespace region, we should not
+			// do a quick change,
+			// so 'canHandle' should have been false for those case.
+			// TO_DO_FUTURE: cache value of canHandleAsWhiteSpace from above
+			// If we are handling as whitespace, there is no need to increase
+			// the text length, only
+			// the total length is changing.
+			if (!RegionUpdateRule.canHandleAsWhiteSpace(this, parent, changes, requestStart, lengthToReplace)) {
+				fTextLength += lengthDifference;
+			}
+			// update length (and end) after above check for white space,
+			// since
+			// it looks to determine if at end of region.
+			fLength += lengthDifference;
+			result = new RegionChangedEvent(parent.getParentDocument(), requester, parent, this, changes, requestStart, lengthToReplace);
+		}
+		return result;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/EmptyTagCloseRegion.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/EmptyTagCloseRegion.java
new file mode 100644
index 0000000..339d692
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/EmptyTagCloseRegion.java
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * Copyright (c) 2008 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.parser.regions;
+
+import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentEvent;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+
+
+public class EmptyTagCloseRegion implements ITextRegion {
+	private int fLength = 2;
+	static private final byte fTextLength = 2;
+	static private final String fType = DOMRegionContext.XML_EMPTY_TAG_CLOSE;
+	private int fStart;
+
+
+	public EmptyTagCloseRegion() {
+		super();
+	}
+
+	public EmptyTagCloseRegion(int start, int textLength, int length) {
+		super();
+		fStart = start;
+		fLength = length;
+		if (fTextLength != textLength)
+			throw new RuntimeException("invalid for this region type"); //$NON-NLS-1$
+	}
+
+	public void adjustLength(int i) {
+		fLength += i;
+	}
+
+	public void adjustStart(int i) {
+		fStart += i;
+
+	}
+
+	public void adjustTextLength(int i) {
+		throw new RuntimeException("invalid for this region type"); //$NON-NLS-1$
+	}
+
+	public void equatePositions(ITextRegion region) {
+		fStart = region.getStart();
+	}
+
+	public int getEnd() {
+		return fStart + fLength;
+	}
+
+	public int getLength() {
+		return fLength;
+	}
+
+	public int getStart() {
+		return fStart;
+	}
+
+	public int getTextEnd() {
+		return fStart + fTextLength;
+	}
+
+	public int getTextLength() {
+		return fTextLength;
+	}
+
+	public String getType() {
+		return fType;
+	}
+
+	public String toString() {
+		return RegionToStringUtil.toString(this);
+	}
+
+	public StructuredDocumentEvent updateRegion(Object requester, IStructuredDocumentRegion parent, String changes, int requestStart, int lengthToReplace) {
+		// can never be updated
+		return null;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/EndTagOpenRegion.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/EndTagOpenRegion.java
new file mode 100644
index 0000000..1ad5549
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/EndTagOpenRegion.java
@@ -0,0 +1,101 @@
+/*******************************************************************************
+ * Copyright (c) 2008 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.parser.regions;
+
+import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentEvent;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+
+
+public class EndTagOpenRegion implements ITextRegion {
+	static private final String fType = DOMRegionContext.XML_END_TAG_OPEN;
+	private int fLength;
+	private int fStart;
+	static private final byte fTextLength = 2;
+
+
+	public EndTagOpenRegion() {
+		super();
+	}
+
+	public EndTagOpenRegion(int start, int textLength, int length) {
+		this();
+		fStart = start;
+		if (fTextLength != textLength)
+			throw new RuntimeException("invalid for this region type"); //$NON-NLS-1$
+		fLength = length;
+	}
+
+	public EndTagOpenRegion(int start, int length) {
+		this();
+		fStart = start;
+		fLength = length;
+	}
+
+	public void adjustLength(int i) {
+		fLength += i;
+
+	}
+
+	public void adjustStart(int i) {
+		fStart += i;
+
+	}
+
+
+	public void adjustTextLength(int i) {
+//		fTextLength += 1;
+		throw new RuntimeException("invalid for this region type"); //$NON-NLS-1$
+	}
+
+	public void equatePositions(ITextRegion region) {
+		fStart = region.getStart();
+		fLength = region.getLength();
+//		fTextLength = region.getTextLength();
+	}
+
+	public int getEnd() {
+		return fStart + fLength;
+	}
+
+	public int getLength() {
+		return fLength;
+	}
+
+	public int getStart() {
+		return fStart;
+	}
+
+	public int getTextEnd() {
+		return fStart + fTextLength;
+	}
+
+	public int getTextLength() {
+		return fTextLength;
+	}
+
+	public String getType() {
+		return fType;
+	}
+
+	public String toString() {
+		return RegionToStringUtil.toString(this);
+	}
+
+	public StructuredDocumentEvent updateRegion(Object requester, IStructuredDocumentRegion parent, String changes, int requestStart, int lengthToReplace) {
+		// can never be updated
+		return null;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/GenericTemplateRegion.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/GenericTemplateRegion.java
new file mode 100644
index 0000000..e6064be
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/GenericTemplateRegion.java
@@ -0,0 +1,102 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.parser.regions;
+
+import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentEvent;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+
+
+/**
+ * 
+ * This class is not intended to be used, its just present to server as a
+ * generic starting point for adding new specific region types.
+ * 
+ */
+
+public class GenericTemplateRegion implements ITextRegion {
+	// specify correct type
+	static private final String fType = DOMRegionContext.UNDEFINED;
+	private int fLength;
+	private int fStart;
+	private int fTextLength;
+
+
+	public GenericTemplateRegion() {
+		super();
+	}
+
+	public GenericTemplateRegion(int start, int textLength, int length) {
+		this();
+		fStart = start;
+		fTextLength = textLength;
+		fLength = length;
+	}
+
+	public void adjustLength(int i) {
+		fLength += i;
+
+	}
+
+	public void adjustStart(int i) {
+		fStart += i;
+
+	}
+
+
+	public void adjustTextLength(int i) {
+		fTextLength += i;
+
+	}
+
+	public void equatePositions(ITextRegion region) {
+		fStart = region.getStart();
+		fLength = region.getLength();
+		fTextLength = region.getTextLength();
+	}
+
+	public int getEnd() {
+		return fStart + fLength;
+	}
+
+	public int getLength() {
+		return fLength;
+	}
+
+	public int getStart() {
+		return fStart;
+	}
+
+	public int getTextEnd() {
+		return fStart + fTextLength;
+	}
+
+	public int getTextLength() {
+		return fTextLength;
+	}
+
+	public String getType() {
+		return fType;
+	}
+
+	public String toString() {
+		return RegionToStringUtil.toString(this);
+	}
+
+	public StructuredDocumentEvent updateRegion(Object requester, IStructuredDocumentRegion parent, String changes, int requestStart, int lengthToReplace) {
+		// can never be updated
+		return null;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/RegionToStringUtil.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/RegionToStringUtil.java
new file mode 100644
index 0000000..af783f6
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/RegionToStringUtil.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.parser.regions;
+
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+
+
+public class RegionToStringUtil {
+	static public String toString(ITextRegion region) {
+		String className = region.getClass().getName();
+		String shortClassName = className.substring(className.lastIndexOf(".") + 1); //$NON-NLS-1$
+		String result = shortClassName + "--> " + region.getType() + ": " + region.getStart() + "-" + region.getTextEnd() + (region.getTextEnd() != region.getEnd() ? ("/" + region.getEnd()) : ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
+		// NOTE: if the document held by any region has been updated and the
+		// region offsets have not
+		// yet been updated, the output from this method invalid.
+		return result;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/RegionUpdateRule.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/RegionUpdateRule.java
new file mode 100644
index 0000000..567d093
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/RegionUpdateRule.java
@@ -0,0 +1,209 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.parser.regions;
+
+import org.eclipse.wst.sse.core.internal.provisional.events.RegionChangedEvent;
+import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentEvent;
+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.util.Debug;
+import org.eclipse.wst.sse.core.internal.util.Utilities;
+
+
+/**
+ * 
+ * This is a utility class to centralize 'region' update. Note: care must be
+ * taken that is is not used for StructuredDocumentRegions, or container
+ * regions, its only for "token regions"
+ *  
+ */
+public class RegionUpdateRule {
+
+	static public boolean allLetterOrDigit(String changes) {
+		boolean result = true;
+		for (int i = 0; i < changes.length(); i++) {
+			// TO_DO_FUTURE: check that a Java Letter or Digit is
+			// the same thing as an XML letter or digit
+			if (!(Character.isLetterOrDigit(changes.charAt(i)))) {
+				result = false;
+				break;
+			}
+		}
+		return result;
+	}
+
+	static public boolean allWhiteSpace(String changes) {
+		boolean result = true;
+		for (int i = 0; i < changes.length(); i++) {
+			if (!Character.isWhitespace(changes.charAt(i))) {
+				result = false;
+				break;
+			}
+		}
+		return result;
+	}
+
+	static public boolean canHandleAsLetterOrDigit(ITextRegion region, IStructuredDocumentRegion parent, String changes, int requestStart, int lengthToReplace) {
+		if (parent == null)
+			return canHandleAsLetterOrDigit(region, changes, requestStart, lengthToReplace);
+		boolean result = false;
+		// Make sure we are in a non-white space area
+		if ((requestStart <= (parent.getTextEndOffset(region))) && (allLetterOrDigit(changes))) {
+			result = true;
+		}
+		return result;
+	}
+
+	static public boolean canHandleAsLetterOrDigit(ITextRegion region, String changes, int requestStart, int lengthToReplace) {
+		boolean result = false;
+		// Make sure we are in a non-white space area
+		if ((requestStart <= (region.getTextEnd())) && (allLetterOrDigit(changes))) {
+			result = true;
+		}
+		return result;
+	}
+
+	static public boolean canHandleAsWhiteSpace(ITextRegion region, IStructuredDocumentRegion parent, String changes, int requestStart, int lengthToReplace) {
+		// we don't explect a null parent, but just in case!
+		// (in which case, we must be dealing with regions that are
+		// structuredDocumentRegions).
+		if (parent == null)
+			return canHandleAsWhiteSpace(region, changes, requestStart, lengthToReplace);
+		boolean result = false;
+		// if we are in the "white space" area of a region, then
+		// we don't want to handle, a reparse is needed.
+		// the white space region is consider anywhere that would
+		// leave whitespace between this character and the text part.
+		// and of course, we can insert whitespace in whitespace region
+		//
+		// if there is no whitespace in this region, no need to look further
+		if (region.getEnd() > region.getTextEnd()) {
+			// no need to add one to end of text, as we used to, since we
+			// change definition of length to equate to offset plus one.
+			// https://bugs.eclipse.org/bugs/show_bug.cgi?id=105866
+			// watch out for whitespace at end of text
+			if (requestStart >= parent.getTextEndOffset(region)) {
+				// ok, we are in the whitespace region, so we can't handle,
+				// unless
+				// we are just inserting whitespace.
+				if (allWhiteSpace(changes)) {
+					result = true;
+				} else {
+					result = false;
+				}
+			}
+		}
+		return result;
+	}
+
+	static public boolean canHandleAsWhiteSpace(ITextRegion region, String changes, int requestStart, int lengthToReplace) {
+		boolean result = false;
+		// if we are in the "white space" area of a region, then
+		// we don't want to handle, a reparse is needed.
+		// the white space region is consider anywhere that would
+		// leave whitespace between this character and the text part.
+		// and of course, we can insert whitespace in whitespace region
+		//
+		// if there is no whitespace in this region, no need to look further
+		if (region.getEnd() > region.getTextEnd()) {
+			// no need to add one to end of text, as we used to, since we
+			// change definition of length to equate to offset plus one.
+			// https://bugs.eclipse.org/bugs/show_bug.cgi?id=105866
+			// watch out for whitespace at end of text
+			if (requestStart >= region.getTextEnd()) {
+				// ok, we are in the whitespace region, so we can't handle,
+				// unless
+				// we are just inserting whitespace.
+				if (allWhiteSpace(changes)) {
+					result = true;
+				} else {
+					result = false;
+				}
+			}
+		}
+		return result;
+	}
+
+	// need an adjust text length API before this can be used
+	static public StructuredDocumentEvent updateModel(ITextRegion region, Object requester, IStructuredDocumentRegion parent, String changes, int requestStart, int lengthToReplace) {
+		RegionChangedEvent result = null;
+		// if the region is an easy type (e.g. attribute value),
+		// and the requested changes are all
+		// alphanumeric, then make the change here locally.
+		// (This can obviously be made more sophisticated as the need arises,
+		// but should
+		// always follow this pattern.)
+		if (Debug.debugStructuredDocument) {
+			System.out.println("\t\tContextRegion::updateModel"); //$NON-NLS-1$
+			System.out.println("\t\t\tregion type is " + region.getType()); //$NON-NLS-1$
+		}
+		boolean canHandle = false;
+		// note: we'll always handle deletes from these
+		// regions ... if its already that region,
+		// deleting something from it won't change its
+		// type. (remember, the calling program needs
+		// to insure we are not called, if not all contained
+		// on one region.
+		if ((changes == null) || (changes.length() == 0)) {
+			// delete case
+			// We can not do the quick delete, if
+			// if all the text in a region is to be deleted.
+			// Or, if the delete starts in the white space region.
+			// In these cases, a reparse is needed.
+			// Minor note, we use textEnd-start since it always
+			// less than or equal to end-start. This might
+			// cause us to miss a few cases we could have handled,
+			// but will prevent us from trying to handle funning cases
+			// involving whitespace.
+			if ((region.getStart() >= region.getTextEnd()) || (Math.abs(lengthToReplace) >= region.getTextEnd() - region.getStart())) {
+				canHandle = false;
+			} else {
+				canHandle = true;
+			}
+		} else {
+			if ((RegionUpdateRule.canHandleAsWhiteSpace(region, parent, changes, requestStart, lengthToReplace)) || RegionUpdateRule.canHandleAsLetterOrDigit(region, parent, changes, requestStart, lengthToReplace)) {
+				canHandle = true;
+			} else {
+				canHandle = false;
+			}
+		}
+		if (canHandle) {
+			// at this point, we still have the old region. We won't create a
+			// new instance, we'll just update the one we have, by changing
+			// its end postion,
+			// The parent flatnode, upon return, has responsibility
+			// for updating sibling regions.
+			// and in turn, the structuredDocument itself has responsibility
+			// for
+			// updating the text store and down stream flatnodes.
+			if (Debug.debugStructuredDocument) {
+				System.out.println("change handled by region"); //$NON-NLS-1$
+			}
+			int lengthDifference = Utilities.calculateLengthDifference(changes, lengthToReplace);
+			// Note: we adjust both end and text end, because for any change
+			// that is in only the trailing whitespace region, we should not
+			// do a quick change,
+			// so 'canHandle' should have been false for those case.
+			region.adjustLength(lengthDifference);
+			// TO_DO_FUTURE: cache value of canHandleAsWhiteSpace from above
+			// If we are handling as whitespace, there is no need to increase
+			// the text length, only
+			// the total length is changing.
+			if (!RegionUpdateRule.canHandleAsWhiteSpace(region, parent, changes, region.getStart(), lengthToReplace)) {
+				//				region.adjustTextLength(lengthDifference);
+			}
+			result = new RegionChangedEvent(parent.getParentDocument(), requester, parent, region, changes, requestStart, lengthToReplace);
+		}
+		return result;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/TagCloseRegion.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/TagCloseRegion.java
new file mode 100644
index 0000000..027ae4d
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/TagCloseRegion.java
@@ -0,0 +1,89 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.parser.regions;
+
+import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentEvent;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+
+
+public class TagCloseRegion implements ITextRegion {
+	static private final byte fLength = 1;
+	static private final byte fTextLength = 1;
+	static private final String fType = DOMRegionContext.XML_TAG_CLOSE;
+	private int fStart;
+
+
+	public TagCloseRegion() {
+		super();
+	}
+
+	public TagCloseRegion(int start) {
+		this();
+		fStart = start;
+	}
+
+	public void adjustLength(int i) {
+		throw new RuntimeException("invalid for this region type"); //$NON-NLS-1$
+
+	}
+
+	public void adjustStart(int i) {
+		fStart += i;
+
+	}
+
+	public void adjustTextLength(int i) {
+		// not supported
+
+	}
+
+	public void equatePositions(ITextRegion region) {
+		fStart = region.getStart();
+	}
+
+	public int getEnd() {
+		return fStart + fLength;
+	}
+
+	public int getLength() {
+		return fLength;
+	}
+
+	public int getStart() {
+		return fStart;
+	}
+
+	public int getTextEnd() {
+		return fStart + fTextLength;
+	}
+
+	public int getTextLength() {
+		return fTextLength;
+	}
+
+	public String getType() {
+		return fType;
+	}
+
+	public String toString() {
+		return RegionToStringUtil.toString(this);
+	}
+
+	public StructuredDocumentEvent updateRegion(Object requester, IStructuredDocumentRegion parent, String changes, int requestStart, int lengthToReplace) {
+		// can never be updated
+		return null;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/TagNameRegion.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/TagNameRegion.java
new file mode 100644
index 0000000..38b59c4
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/TagNameRegion.java
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.parser.regions;
+
+import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentEvent;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+
+
+public class TagNameRegion implements ITextRegion {
+	static private final String fType = DOMRegionContext.XML_TAG_NAME;
+	private short fLength;
+	private int fStart;
+	private short fTextLength;
+
+
+	public TagNameRegion() {
+		super();
+	}
+
+	public TagNameRegion(int start, int textLength, int length) {
+		this();
+		fStart = start;
+		fTextLength = (short) textLength;
+		fLength = (short) length;
+	}
+
+	public void adjustLength(int i) {
+		fLength += i;
+
+	}
+
+	public void adjustStart(int i) {
+		fStart += i;
+
+	}
+
+
+	public void adjustTextLength(int i) {
+		fTextLength += i;
+	}
+
+	public void equatePositions(ITextRegion region) {
+		fStart = region.getStart();
+		fLength = (short) region.getLength();
+		fTextLength = (short) region.getTextLength();
+	}
+
+	public int getEnd() {
+		return fStart + fLength;
+	}
+
+	public int getLength() {
+		return fLength;
+	}
+
+	public int getStart() {
+		return fStart;
+	}
+
+	public int getTextEnd() {
+		return fStart + fTextLength;
+	}
+
+	public int getTextLength() {
+		return fTextLength;
+	}
+
+	public String getType() {
+		return fType;
+	}
+
+	public String toString() {
+		return RegionToStringUtil.toString(this);
+	}
+
+	public StructuredDocumentEvent updateRegion(Object requester, IStructuredDocumentRegion parent, String changes, int requestStart, int lengthToReplace) {
+		// can never be updated
+		return null;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/TagOpenRegion.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/TagOpenRegion.java
new file mode 100644
index 0000000..e8cb85e
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/TagOpenRegion.java
@@ -0,0 +1,98 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2008 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.parser.regions;
+
+import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentEvent;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+
+
+public class TagOpenRegion implements ITextRegion {
+	static private final String fType = DOMRegionContext.XML_TAG_OPEN;
+	private int fLength;
+	private int fStart;
+	static private final byte fTextLength = 1;
+
+
+	public TagOpenRegion() {
+		super();
+	}
+
+	public TagOpenRegion(int start, int textLength, int length) {
+		this(start, length);
+		if (fTextLength != textLength)
+			throw new RuntimeException("invalid for this region type"); //$NON-NLS-1$
+	}
+
+	public TagOpenRegion(int start, int length) {
+		this();
+		fStart = start;
+		fLength = length;
+	}
+
+	public void adjustLength(int i) {
+		fLength += i;
+
+	}
+
+	public void adjustStart(int i) {
+		fStart += i;
+
+	}
+
+
+	public void adjustTextLength(int i) {
+//		fTextLength += 1;
+		throw new RuntimeException("invalid for this region type"); //$NON-NLS-1$
+	}
+
+	public void equatePositions(ITextRegion region) {
+		fStart = region.getStart();
+		fLength = region.getLength();
+	}
+
+	public int getEnd() {
+		return fStart + fLength;
+	}
+
+	public int getLength() {
+		return fLength;
+	}
+
+	public int getStart() {
+		return fStart;
+	}
+
+	public int getTextEnd() {
+		return fStart + fTextLength;
+	}
+
+	public int getTextLength() {
+		return fTextLength;
+	}
+
+	public String getType() {
+		return fType;
+	}
+
+	public String toString() {
+		return RegionToStringUtil.toString(this);
+	}
+
+	public StructuredDocumentEvent updateRegion(Object requester, IStructuredDocumentRegion parent, String changes, int requestStart, int lengthToReplace) {
+		// can never be updated
+		return null;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/WhiteSpaceOnlyRegion.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/WhiteSpaceOnlyRegion.java
new file mode 100644
index 0000000..bc0bcc1
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/WhiteSpaceOnlyRegion.java
@@ -0,0 +1,188 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.parser.regions;
+
+
+
+import org.eclipse.wst.sse.core.internal.provisional.events.RegionChangedEvent;
+import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentEvent;
+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.util.Debug;
+import org.eclipse.wst.sse.core.internal.util.Utilities;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+
+
+public class WhiteSpaceOnlyRegion implements ITextRegion {
+	static private final byte fTextLength = 0;
+
+	static private final String fType = DOMRegionContext.WHITE_SPACE;
+	protected int fLength;
+	protected int fStart;
+
+	public WhiteSpaceOnlyRegion(int start, int length) {
+		super();
+		fStart = start;
+		fLength = length;
+	}
+
+	public void adjust(int i) {
+		fStart += i;
+	}
+
+	public void adjustLength(int i) {
+		fLength += i;
+	}
+
+	public void adjustStart(int i) {
+		fStart += i;
+	}
+
+
+	public void adjustTextLength(int i) {
+		// not supported
+
+	}
+
+	public boolean contains(int position) {
+
+		return fStart <= position && position < fStart + fLength;
+	}
+
+	public void equatePositions(ITextRegion region) {
+		fStart = region.getStart();
+		fLength = region.getLength();
+	}
+
+	public int getEnd() {
+		return fStart + fLength;
+	}
+
+	public int getLength() {
+		return fLength;
+	}
+
+	public int getStart() {
+		return fStart;
+	}
+
+	public int getTextEnd() {
+		return fStart + fTextLength;
+	}
+
+	public int getTextLength() {
+		return fTextLength;
+	}
+
+	public String getType() {
+		return fType;
+	}
+
+	public void setLength(int i) {
+		fLength = i;
+	}
+
+	public void setStart(int i) {
+		fStart = i;
+	}
+
+	public void setTextLength(short i) {
+		throw new RuntimeException("invalid call"); //$NON-NLS-1$
+	}
+
+	public void setType(String string) {
+		throw new RuntimeException("invalid call"); //$NON-NLS-1$
+	}
+
+	public String toString() {
+		return RegionToStringUtil.toString(this);
+	}
+
+	/**
+	 * For this ITextRegion type, the start must in terms of what the region
+	 * expects ... that is, its not document offset, but start relative to
+	 * what ever contains it.
+	 */
+	public StructuredDocumentEvent updateRegion(Object requester, IStructuredDocumentRegion parent, String changes, int requestStart, int lengthToReplace) {
+		// if the region is an easy type (e.g. attribute value),
+		// and the requested changes are all
+		// alphanumeric, then make the change here locally.
+		// (This can obviously be made more sophisticated as the need arises,
+		// but should
+		// always follow this pattern.)
+		if (Debug.debugStructuredDocument) {
+			System.out.println("\t\tContextRegion::updateModel"); //$NON-NLS-1$
+			System.out.println("\t\t\tregion type is " + fType); //$NON-NLS-1$
+		}
+		boolean canHandle = false;
+		// note: we'll always handle deletes from these
+		// regions ... if its already that region,
+		// deleting something from it won't change its
+		// type. (remember, the calling program needs
+		// to insure we are not called, if not all contained
+		// on one region.
+		if ((changes == null) || (changes.length() == 0)) {
+			// delete case
+			// We can not do the quick delete, if
+			// if all the text in a region is to be deleted.
+			// Or, if the delete starts in the white space region.
+			// In these cases, a reparse is needed.
+			// Minor note, we use textEnd-start since it always
+			// less than or equal to end-start. This might
+			// cause us to miss a few cases we could have handled,
+			// but will prevent us from trying to handle funning cases
+			// involving whitespace.
+			if ((fStart >= getTextEnd()) || (Math.abs(lengthToReplace) >= getTextEnd() - getStart())) {
+				canHandle = false;
+			}
+			else {
+				canHandle = true;
+			}
+		}
+		else {
+			if (RegionUpdateRule.canHandleAsWhiteSpace(this, parent, changes, requestStart, lengthToReplace)) {
+				canHandle = true;
+			}
+			else {
+				canHandle = false;
+			}
+
+		}
+		RegionChangedEvent result = null;
+
+		if (canHandle) {
+			// at this point, we still have the old region. We won't create a
+			// new instance, we'll just update the one we have, by changing
+			// its end postion,
+			// The parent flatnode, upon return, has responsibility
+			// for updating sibling regions.
+			// and in turn, the structuredDocument itself has responsibility
+			// for
+			// updating the text store and down stream flatnodes.
+			if (Debug.debugStructuredDocument) {
+				System.out.println("change handled by region"); //$NON-NLS-1$
+			}
+			int lengthDifference = Utilities.calculateLengthDifference(changes, lengthToReplace);
+			// Note: we adjust both end and text end, because for any change
+			// that is in only the trailing whitespace region, we should not
+			// do a quick change,
+			// so 'canHandle' should have been false for those case.
+			fLength += lengthDifference;
+
+			result = new RegionChangedEvent(parent.getParentDocument(), requester, parent, this, changes, requestStart, lengthToReplace);
+		}
+
+		return result;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/XMLCDataTextRegion.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/XMLCDataTextRegion.java
new file mode 100644
index 0000000..23da980
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/XMLCDataTextRegion.java
@@ -0,0 +1,175 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.parser.regions;
+
+import org.eclipse.wst.sse.core.internal.provisional.events.RegionChangedEvent;
+import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentEvent;
+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.util.Debug;
+import org.eclipse.wst.sse.core.internal.util.Utilities;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+
+
+public class XMLCDataTextRegion implements ITextRegion {
+	static private final String fType = DOMRegionContext.XML_CDATA_TEXT;
+	private int fLength;
+	private int fStart;
+	private int fTextLength;
+
+
+	public XMLCDataTextRegion() {
+		super();
+	}
+
+	public XMLCDataTextRegion(int start, int textLength, int length) {
+		this();
+		fStart = start;
+		fTextLength = textLength;
+		fLength = length;
+	}
+
+	public void adjustLength(int i) {
+		fLength += i;
+
+	}
+
+	public void adjustStart(int i) {
+		fStart += i;
+
+	}
+
+
+	public void adjustTextLength(int i) {
+		fTextLength += i;
+
+	}
+
+	public void equatePositions(ITextRegion region) {
+		fStart = region.getStart();
+		fLength = region.getLength();
+		fTextLength = region.getTextLength();
+	}
+
+	public int getEnd() {
+		return fStart + fLength;
+	}
+
+	public int getLength() {
+		// TODO: shouldn't cdata be like XML Content ... length and text
+		// length
+		// always be the same, regardless of whitespace?
+		return fLength;
+	}
+
+	public int getStart() {
+		return fStart;
+	}
+
+	public int getTextEnd() {
+		return fStart + fTextLength;
+	}
+
+	public int getTextLength() {
+		return fTextLength;
+	}
+
+	public String getType() {
+		return fType;
+	}
+
+	public String toString() {
+		return RegionToStringUtil.toString(this);
+	}
+
+
+	public StructuredDocumentEvent updateRegion(Object requester, IStructuredDocumentRegion parent, String changes, int requestStart, int lengthToReplace) {
+		// TODO: this is a pretty lame method, since XML CData region can have
+		// a much
+		// better rule for region update, but this is what previous
+		// (unfactored)
+		// version had, so I'll carry it over, of now.
+		RegionChangedEvent result = null;
+		// if the region is an easy type (e.g. attribute value),
+		// and the requested changes are all
+		// alphanumeric, then make the change here locally.
+		// (This can obviously be made more sophisticated as the need arises,
+		// but should
+		// always follow this pattern.)
+		if (Debug.debugStructuredDocument) {
+			System.out.println("\t\tContextRegion::updateModel"); //$NON-NLS-1$
+			System.out.println("\t\t\tregion type is " + fType); //$NON-NLS-1$
+		}
+		boolean canHandle = false;
+		// note: we'll always handle deletes from these
+		// regions ... if its already that region,
+		// deleting something from it won't change its
+		// type. (remember, the calling program needs
+		// to insure we are not called, if not all contained
+		// on one region.
+		if ((changes == null) || (changes.length() == 0)) {
+			// delete case
+			// We can not do the quick delete, if
+			// if all the text in a region is to be deleted.
+			// Or, if the delete starts in the white space region.
+			// In these cases, a reparse is needed.
+			// Minor note, we use textEnd-start since it always
+			// less than or equal to end-start. This might
+			// cause us to miss a few cases we could have handled,
+			// but will prevent us from trying to handle funning cases
+			// involving whitespace.
+			if ((fStart >= getTextEnd()) || (Math.abs(lengthToReplace) >= getTextEnd() - getStart())) {
+				canHandle = false;
+			} else {
+				canHandle = true;
+			}
+		} else {
+			if ((RegionUpdateRule.canHandleAsWhiteSpace(this, parent, changes, requestStart, lengthToReplace)) || RegionUpdateRule.canHandleAsLetterOrDigit(this, parent, changes, requestStart, lengthToReplace)) {
+				canHandle = true;
+			} else {
+				canHandle = false;
+			}
+
+		}
+		if (canHandle) {
+			// at this point, we still have the old region. We won't create a
+			// new instance, we'll just update the one we have, by changing
+			// its end postion,
+			// The parent flatnode, upon return, has responsibility
+			// for updating sibling regions.
+			// and in turn, the structuredDocument itself has responsibility
+			// for
+			// updating the text store and down stream flatnodes.
+			if (Debug.debugStructuredDocument) {
+				System.out.println("change handled by region"); //$NON-NLS-1$
+			}
+			int lengthDifference = Utilities.calculateLengthDifference(changes, lengthToReplace);
+			// Note: we adjust both end and text end, because for any change
+			// that is in only the trailing whitespace region, we should not
+			// do a quick change,
+			// so 'canHandle' should have been false for those case.
+			// TO_DO_FUTURE: cache value of canHandleAsWhiteSpace from above
+			// If we are handling as whitespace, there is no need to increase
+			// the text length, only
+			// the total length is changing.
+			if (!RegionUpdateRule.canHandleAsWhiteSpace(this, parent, changes, requestStart, lengthToReplace)) {
+				fTextLength += lengthDifference;
+			}
+			fLength += lengthDifference;
+			result = new RegionChangedEvent(parent.getParentDocument(), requester, parent, this, changes, requestStart, lengthToReplace);
+		}
+
+		return result;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/XMLContentRegion.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/XMLContentRegion.java
new file mode 100644
index 0000000..e9088db
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/XMLContentRegion.java
@@ -0,0 +1,175 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.parser.regions;
+
+import org.eclipse.wst.sse.core.internal.provisional.events.RegionChangedEvent;
+import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentEvent;
+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.util.Debug;
+import org.eclipse.wst.sse.core.internal.util.Utilities;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+
+
+
+public class XMLContentRegion implements ITextRegion {
+	static private final String fType = DOMRegionContext.XML_CONTENT;
+	// length and textLength are always the same for content region
+	//private int fTextLength;
+	private int fLength;
+	private int fStart;
+
+
+	public XMLContentRegion() {
+		super();
+	}
+
+	public XMLContentRegion(int start, int length) {
+		this();
+		fStart = start;
+		fLength = length;
+	}
+
+
+	public void adjustLength(int i) {
+		fLength += i;
+
+	}
+
+	public void adjustStart(int i) {
+		fStart += i;
+
+	}
+
+
+	public void adjustTextLength(int i) {
+		// not supported
+
+	}
+
+	public void equatePositions(ITextRegion region) {
+		fStart = region.getStart();
+		fLength = region.getLength();
+	}
+
+	public int getEnd() {
+		return fStart + fLength;
+	}
+
+	public int getLength() {
+		return fLength;
+	}
+
+	public int getStart() {
+		return fStart;
+	}
+
+	public int getTextEnd() {
+		return fStart + fLength;
+	}
+
+	public int getTextLength() {
+		return fLength;
+	}
+
+	public String getType() {
+		return fType;
+	}
+
+	public String toString() {
+		return RegionToStringUtil.toString(this);
+	}
+
+
+	public StructuredDocumentEvent updateRegion(Object requester, IStructuredDocumentRegion parent, String changes, int requestStart, int lengthToReplace) {
+		// TODO: this is a pretty lame method, since XML Content can have a
+		// much
+		// better rule for region update, but this is what previous
+		// (unfactored)
+		// version had, so I'll carry it over, of now.
+		RegionChangedEvent result = null;
+		// if the region is an easy type (e.g. attribute value),
+		// and the requested changes are all
+		// alphanumeric, then make the change here locally.
+		// (This can obviously be made more sophisticated as the need arises,
+		// but should
+		// always follow this pattern.)
+		if (Debug.debugStructuredDocument) {
+			System.out.println("\t\tContextRegion::updateModel"); //$NON-NLS-1$
+			System.out.println("\t\t\tregion type is " + fType); //$NON-NLS-1$
+		}
+		boolean canHandle = false;
+		// note: we'll always handle deletes from these
+		// regions ... if its already that region,
+		// deleting something from it won't change its
+		// type. (remember, the calling program needs
+		// to insure we are not called, if not all contained
+		// on one region.
+		if ((changes == null) || (changes.length() == 0)) {
+			// delete case
+			// We can not do the quick delete, if
+			// if all the text in a region is to be deleted.
+			// Or, if the delete starts in the white space region.
+			// In these cases, a reparse is needed.
+			// Minor note, we use textEnd-start since it always
+			// less than or equal to end-start. This might
+			// cause us to miss a few cases we could have handled,
+			// but will prevent us from trying to handle funning cases
+			// involving whitespace.
+			if ((fStart >= getTextEnd()) || (Math.abs(lengthToReplace) >= getTextEnd() - getStart())) {
+				canHandle = false;
+			} else {
+				canHandle = true;
+			}
+		} else {
+			if ((RegionUpdateRule.canHandleAsWhiteSpace(this, parent, changes, requestStart, lengthToReplace)) || RegionUpdateRule.canHandleAsLetterOrDigit(this, parent, changes, requestStart, lengthToReplace)) {
+				canHandle = true;
+			} else {
+				canHandle = false;
+			}
+
+		}
+		if (canHandle) {
+			// at this point, we still have the old region. We won't create a
+			// new instance, we'll just update the one we have, by changing
+			// its end postion,
+			// The parent flatnode, upon return, has responsibility
+			// for updating sibling regions.
+			// and in turn, the structuredDocument itself has responsibility
+			// for
+			// updating the text store and down stream flatnodes.
+			if (Debug.debugStructuredDocument) {
+				System.out.println("change handled by region"); //$NON-NLS-1$
+			}
+			int lengthDifference = Utilities.calculateLengthDifference(changes, lengthToReplace);
+			// Note: we adjust both end and text end, because for any change
+			// that is in only the trailing whitespace region, we should not
+			// do a quick change,
+			// so 'canHandle' should have been false for those case.
+			fLength += lengthDifference;
+			// TO_DO_FUTURE: cache value of canHandleAsWhiteSpace from above
+			// If we are handling as whitespace, there is no need to increase
+			// the text length, only
+			// the total length is changing.
+			// don't need for content region
+			//			if (!RegionUpdateRule.canHandleAsWhiteSpace(this, changes,
+			// fStart, lengthToReplace)) {
+			//				fTextLength += lengthDifference;
+			//			}
+			result = new RegionChangedEvent(parent.getParentDocument(), requester, parent, this, changes, requestStart, lengthToReplace);
+		}
+
+		return result;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/XMLHeadParserFactory.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/XMLHeadParserFactory.java
new file mode 100644
index 0000000..38df3ea
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/XMLHeadParserFactory.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.parser.regions;
+
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+
+public class XMLHeadParserFactory {
+	public ITextRegion createToken(String context, int start, int textLength, int length, String text) {
+		ITextRegion newRegion = null;
+		//		if (context == XMLRegionContext.XML_CDATA_TEXT) {
+		newRegion = new XMLHeadParserRegion(context, start, textLength, length, text);
+		//		}
+		return newRegion;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/XMLHeadParserRegion.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/XMLHeadParserRegion.java
new file mode 100644
index 0000000..f3917b6
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/XMLHeadParserRegion.java
@@ -0,0 +1,107 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.parser.regions;
+
+import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentEvent;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+
+
+/**
+ * 
+ * This class is not intended to be used, its just present to server as a
+ * generic starting point for adding new specific region types.
+ */
+
+public class XMLHeadParserRegion implements ITextRegion {
+	private int fLength;
+	private int fStart;
+	private String fText;
+	private int fTextLength;
+	// specify correct type
+	private String fType = DOMRegionContext.UNDEFINED;
+
+	public XMLHeadParserRegion() {
+		super();
+	}
+
+	public XMLHeadParserRegion(String context, int start, int textLength, int length, String text) {
+		this();
+		fType = context;
+		fStart = start;
+		fTextLength = textLength;
+		fLength = length;
+		fText = text;
+	}
+
+	public void adjustLength(int i) {
+		fLength += i;
+
+	}
+
+	public void adjustStart(int i) {
+		fStart += i;
+
+	}
+
+
+	public void adjustTextLength(int i) {
+		fTextLength += 1;
+
+	}
+
+	public void equatePositions(ITextRegion region) {
+		fStart = region.getStart();
+		fLength = region.getLength();
+		fTextLength = region.getTextLength();
+	}
+
+	public int getEnd() {
+		return fStart + fLength;
+	}
+
+	public int getLength() {
+		return fLength;
+	}
+
+	public int getStart() {
+		return fStart;
+	}
+
+	public String getText() {
+		return fText;
+	}
+
+	public int getTextEnd() {
+		return fStart + fTextLength;
+	}
+
+	public int getTextLength() {
+		return fTextLength;
+	}
+
+	public String getType() {
+		return fType;
+	}
+
+	public String toString() {
+		return RegionToStringUtil.toString(this);
+	}
+
+	public StructuredDocumentEvent updateRegion(Object requester, IStructuredDocumentRegion parent, String changes, int requestStart, int lengthToReplace) {
+		// can never be updated
+		return null;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/XMLParserRegionFactory.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/XMLParserRegionFactory.java
new file mode 100644
index 0000000..581f447
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/XMLParserRegionFactory.java
@@ -0,0 +1,103 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.parser.regions;
+
+
+
+import org.eclipse.wst.sse.core.internal.parser.ContextRegion;
+import org.eclipse.wst.sse.core.internal.parser.ForeignRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionContainer;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+
+
+/**
+ * 
+ * This region factory is very specific to the parser output, and the specific
+ * implementation classes for various regions.
+ */
+
+public class XMLParserRegionFactory {
+
+	public XMLParserRegionFactory() {
+		super();
+	}
+
+	public ITextRegion createToken(ITextRegionContainer parent, String context, int start, int textLength, int length) {
+		return this.createToken(parent, context, start, textLength, length, null, null);
+	}
+
+	public ITextRegion createToken(ITextRegionContainer parent, String context, int start, int textLength, int length, String lang, String surroundingTag) {
+		ITextRegion newRegion = createToken(context, start, textLength, length);
+		// DW, 4/16/2003 token regions no longer have parents
+		// newRegion.setParent(parent);
+		return newRegion;
+	}
+
+	public ITextRegion createToken(String context, int start, int textLength, int length) {
+		return this.createToken(context, start, textLength, length, null, null);
+	}
+
+	public ITextRegion createToken(String context, int start, int textLength, int length, String lang, String surroundingTag) {
+		ITextRegion newRegion = null;
+		if (context == DOMRegionContext.XML_CDATA_TEXT) {
+			newRegion = new XMLCDataTextRegion(start, textLength, length);
+		}
+		else if (context == DOMRegionContext.XML_CONTENT) {
+			newRegion = new XMLContentRegion(start, length);
+		}
+		else if (context == DOMRegionContext.XML_TAG_NAME) {
+			newRegion = new TagNameRegion(start, textLength, length);
+		}
+		else if (context == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) {
+			newRegion = new AttributeNameRegion(start, textLength, length);
+		}
+		else if (context == DOMRegionContext.XML_TAG_ATTRIBUTE_EQUALS) {
+			newRegion = new AttributeEqualsRegion(start, textLength, length);
+		}
+		else if (context == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
+			newRegion = new AttributeValueRegion(start, textLength, length);
+		}
+		else if (context == DOMRegionContext.XML_TAG_OPEN) {
+			newRegion = new TagOpenRegion(start, textLength, length);
+		}
+		else if (context == DOMRegionContext.XML_END_TAG_OPEN) {
+			newRegion = new EndTagOpenRegion(start, textLength, length);
+		}
+		else if (context == DOMRegionContext.XML_TAG_CLOSE) {
+			newRegion = new TagCloseRegion(start);
+		}
+		else if (context == DOMRegionContext.XML_EMPTY_TAG_CLOSE) {
+			newRegion = new EmptyTagCloseRegion(start, textLength, length);
+		}
+		else if (context == DOMRegionContext.WHITE_SPACE) {
+			newRegion = new WhiteSpaceOnlyRegion(start, length);
+		}
+		else
+		// removed this condition during transition, and implemented in
+		// subclass
+		// if (context == XMLJSPRegionContexts.JSP_CONTENT) {
+		// newRegion = new JSPCodeRegion(context, start, textLength, length);
+		// } else
+		if (context == DOMRegionContext.BLOCK_TEXT) {
+			newRegion = new ForeignRegion(context, start, textLength, length);
+			((ForeignRegion) newRegion).setSurroundingTag(surroundingTag);
+		}
+		else {
+			newRegion = new ContextRegion(context, start, textLength, length);
+		}
+		return newRegion;
+	}
+
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/preferences/XMLCorePreferenceInitializer.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/preferences/XMLCorePreferenceInitializer.java
new file mode 100644
index 0000000..b050f9d
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/preferences/XMLCorePreferenceInitializer.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 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
+ *     David Carver - STAR - [205989] - [validation] validate XML after XInclude resolution
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.preferences;
+
+import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer;
+import org.eclipse.core.runtime.preferences.DefaultScope;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences;
+import org.eclipse.wst.sse.core.internal.encoding.CommonEncodingPreferenceNames;
+import org.eclipse.wst.xml.core.internal.XMLCorePlugin;
+
+/**
+ * Sets default values for XML Core preferences
+ */
+public class XMLCorePreferenceInitializer extends AbstractPreferenceInitializer {
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer#initializeDefaultPreferences()
+	 */
+	public void initializeDefaultPreferences() {
+		IEclipsePreferences node = new DefaultScope().getNode(XMLCorePlugin.getDefault().getBundle().getSymbolicName());
+
+		// formatting preferences
+		node.putInt(XMLCorePreferenceNames.LINE_WIDTH, 72);
+		node.putBoolean(XMLCorePreferenceNames.CLEAR_ALL_BLANK_LINES, false);
+		node.put(XMLCorePreferenceNames.INDENTATION_CHAR, XMLCorePreferenceNames.TAB);
+		node.putInt(XMLCorePreferenceNames.INDENTATION_SIZE, 1);
+		node.putBoolean(XMLCorePreferenceNames.SPLIT_MULTI_ATTRS, false);
+		node.putBoolean(XMLCorePreferenceNames.ALIGN_END_BRACKET, false);
+		node.putBoolean(XMLCorePreferenceNames.PRESERVE_CDATACONTENT, false);
+		node.putBoolean(XMLCorePreferenceNames.SPACE_BEFORE_EMPTY_CLOSE_TAG, true);
+		node.putBoolean(XMLCorePreferenceNames.FORMAT_COMMENT_TEXT, true);
+		node.putBoolean(XMLCorePreferenceNames.FORMAT_COMMENT_JOIN_LINES, true);
+		// cleanup preferences
+		node.putBoolean(XMLCorePreferenceNames.COMPRESS_EMPTY_ELEMENT_TAGS, true);
+		node.putBoolean(XMLCorePreferenceNames.INSERT_REQUIRED_ATTRS, true);
+		node.putBoolean(XMLCorePreferenceNames.INSERT_MISSING_TAGS, true);
+		node.putBoolean(XMLCorePreferenceNames.QUOTE_ATTR_VALUES, true);
+		node.putBoolean(XMLCorePreferenceNames.FORMAT_SOURCE, true);
+		node.putBoolean(XMLCorePreferenceNames.CONVERT_EOL_CODES, false);
+		node.putBoolean(XMLCorePreferenceNames.FIX_XML_DECLARATION, true);
+
+		node.put(CommonEncodingPreferenceNames.INPUT_CODESET, ""); //$NON-NLS-1$
+		node.put(CommonEncodingPreferenceNames.OUTPUT_CODESET, "UTF-8");//$NON-NLS-1$
+		node.put(CommonEncodingPreferenceNames.END_OF_LINE_CODE, ""); //$NON-NLS-1$
+
+		// this could be made smarter by actually looking up the content
+		// type's valid extensions
+		node.put(XMLCorePreferenceNames.DEFAULT_EXTENSION, "xml"); //$NON-NLS-1$
+
+		node.putBoolean(XMLCorePreferenceNames.WARN_NO_GRAMMAR, true);
+		// 1 = IMarker.SEVERITY_WARNING
+		node.putInt(XMLCorePreferenceNames.INDICATE_NO_GRAMMAR, 1);
+		node.putBoolean(XMLCorePreferenceNames.USE_XINCLUDE, false);
+		node.putBoolean(XMLCorePreferenceNames.HONOUR_ALL_SCHEMA_LOCATIONS, true);
+		node.putBoolean(XMLCorePreferenceNames.CMDOCUMENT_GLOBAL_CACHE_ENABLED, true);
+		
+		node.putBoolean(XMLCorePreferenceNames.MARKUP_VALIDATION, false);
+		node.putInt(XMLCorePreferenceNames.ATTRIBUTE_HAS_NO_VALUE, 2);
+		node.putInt(XMLCorePreferenceNames.END_TAG_WITH_ATTRIBUTES, 2);
+		node.putInt(XMLCorePreferenceNames.MISSING_START_TAG, 2);
+		node.putInt(XMLCorePreferenceNames.MISSING_END_TAG, 2);
+		node.putInt(XMLCorePreferenceNames.MISSING_TAG_NAME, 2);
+		node.putInt(XMLCorePreferenceNames.MISSING_QUOTES, 2);
+		node.putInt(XMLCorePreferenceNames.MISSING_CLOSING_BRACKET, 2);
+		node.putInt(XMLCorePreferenceNames.MISSING_CLOSING_QUOTE, 2);
+		node.putInt(XMLCorePreferenceNames.NAMESPACE_IN_PI_TARGET, 2);
+		node.putInt(XMLCorePreferenceNames.WHITESPACE_AT_START, 2);
+		node.putInt(XMLCorePreferenceNames.WHITESPACE_BEFORE_TAGNAME, 2);
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/preferences/XMLCorePreferenceNames.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/preferences/XMLCorePreferenceNames.java
new file mode 100644
index 0000000..00f597c
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/preferences/XMLCorePreferenceNames.java
@@ -0,0 +1,287 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 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
+ *     David Carver - STAR - [205989] - [validation] validate XML after XInclude resolution
+ *******************************************************************************/
+
+package org.eclipse.wst.xml.core.internal.preferences;
+
+
+/**
+ * Common preference keys used by XML core
+ * 
+ * @plannedfor 1.0
+ */
+public class XMLCorePreferenceNames {
+	private XMLCorePreferenceNames() {
+		// empty private constructor so users cannot instantiate class
+	}
+
+	/**
+	 * The default extension to use when none is specified in the New File
+	 * Wizard.
+	 * <p>
+	 * Value is of type <code>String</code>.
+	 * </p>
+	 */
+	public static final String DEFAULT_EXTENSION = "defaultExtension"; //$NON-NLS-1$
+
+
+	/**
+	 * The maximum width of a line before a line split is needed.
+	 * <p>
+	 * Value is of type <code>Integer</code>.
+	 * </p>
+	 */
+	public static final String LINE_WIDTH = "lineWidth";//$NON-NLS-1$
+
+	/**
+	 * Indicates if all blanks lines should be cleared during formatting.
+	 * Blank lines will be kept when false.
+	 * <p>
+	 * Value is of type <code>Boolean</code>.
+	 * </p>
+	 */
+	public static final String CLEAR_ALL_BLANK_LINES = "clearAllBlankLines";//$NON-NLS-1$
+
+	/**
+	 * The number of #INDENTATION_CHAR for 1 indentation.
+	 * <p>
+	 * Value is of type <code>Integer</code>.
+	 * </p>
+	 */
+	public static final String INDENTATION_SIZE = "indentationSize";//$NON-NLS-1$
+
+	/**
+	 * The character used for indentation.
+	 * <p>
+	 * Value is of type <code>String</code>.<br />
+	 * Possible values: {TAB, SPACE}
+	 * </p>
+	 */
+	public static final String INDENTATION_CHAR = "indentationChar";//$NON-NLS-1$
+
+	/**
+	 * Possible value for the preference #INDENTATION_CHAR. Indicates to use
+	 * tab character when formatting.
+	 * 
+	 * @see #SPACE
+	 * @see #INDENTATION_CHAR
+	 */
+	public static final String TAB = "tab"; //$NON-NLS-1$
+
+	/**
+	 * Possible value for the preference #INDENTATION_CHAR. Indicates to use
+	 * space character when formatting.
+	 * 
+	 * @see #TAB
+	 * @see #INDENTATION_CHAR
+	 */
+	public static final String SPACE = "space"; //$NON-NLS-1$
+
+	/**
+	 * Indicates if tags with multiple attributes should be formatted
+	 * (splitting each attr on a new line).
+	 * <p>
+	 * Value is of type <code>Boolean</code>.
+	 * </p>
+	 */
+	public static final String SPLIT_MULTI_ATTRS = "splitMultiAttrs";//$NON-NLS-1$
+
+	/**
+	 * Indicates whether or not cleanup processor should format source.
+	 * <p>
+	 * Value is of type <code>Boolean</code>.
+	 * </p>
+	 */
+	public static final String FORMAT_SOURCE = "formatSource";//$NON-NLS-1$
+
+	/**
+	 * Indicates whether or not empty elements should be compressed during
+	 * cleanup.
+	 * <p>
+	 * Value is of type <code>Boolean</code>.
+	 * </p>
+	 */
+	public static final String COMPRESS_EMPTY_ELEMENT_TAGS = "compressEmptyElementTags";//$NON-NLS-1$
+
+	/**
+	 * Indicates whether or not to insert required attributes during cleanup.
+	 * <p>
+	 * Value is of type <code>Boolean</code>.
+	 * </p>
+	 */
+	public static final String INSERT_REQUIRED_ATTRS = "insertRequiredAttrs";//$NON-NLS-1$
+
+	/**
+	 * Indicates whether or not to insert missing tags during cleanup.
+	 * <p>
+	 * Value is of type <code>Boolean</code>.
+	 * </p>
+	 */
+	public static final String INSERT_MISSING_TAGS = "insertMissingTags";//$NON-NLS-1$
+
+	/**
+	 * Indicates whether or not to quote all attribute values during cleanup.
+	 * <p>
+	 * Value is of type <code>Boolean</code>.
+	 * </p>
+	 */
+	public static final String QUOTE_ATTR_VALUES = "quoteAttrValues";//$NON-NLS-1$
+
+	/**
+	 * Indicates whether or not to insert missing XML declarations during cleanup.
+	 * <p>
+	 * Value is of type <code>Boolean</code>
+	 * </p>
+	 */
+	public static final String FIX_XML_DECLARATION = "fixXMLDeclaration"; //$NON-NLS-1$
+
+	/**
+	 * Indicates whether or not to convert all line delimiters during cleanup.
+	 * <p>
+	 * Value is of type <code>Boolean</code>.
+	 * </p>
+	 * @deprecated - no longer used
+	 */
+	public static final String CONVERT_EOL_CODES = "convertEOLCodes";//$NON-NLS-1$
+
+	/**
+	 * Indicates the line delimiter to use during cleanup if converting line
+	 * delimiters.
+	 * <p>
+	 * Value is of type <code>String</code>.<br />
+	 * Possible values: {CR, CRLF, LF, NO_TRANSLATION}
+	 * </p>
+	 * 
+	 */
+	public static final String CLEANUP_EOL_CODE = "cleanupEOLCode";//$NON-NLS-1$
+
+	/**
+	 * Indicates whether or not a warning should be produced when validating a
+	 * file that specifies not grammar.
+	 * <p>
+	 * Value is of type <code>boolean</code>.<br />
+	 * Possible values: {TRUE, FALSE}
+	 * </p>
+	 * @deprecated
+	 */
+	public static final String WARN_NO_GRAMMAR = "warnNoGrammar";//$NON-NLS-1$
+	
+	/**
+	 * Indicates whether or not a message should be produced when validating a
+	 * file that specifies not grammar.
+	 * <p>
+	 * Value is of type <code>integer</code>.<br />
+	 * Possible values: {0, 1, 2} (none, warning, error)
+	 * </p>
+	 */
+	public static final String INDICATE_NO_GRAMMAR = "indicateNoGrammar";//$NON-NLS-1$
+
+ 	/**
+	 * Indicates whether or not xincludes should be processed before
+	 * validation.
+	 * <p>
+	 * Value is of type <code>boolean</code>.<br />
+	 * Possible values: {TRUE, FALSE}
+	 * </p>
+	 * 
+	 */
+	public static final String USE_XINCLUDE = "xinclude";//$NON-NLS-1$
+
+	/**
+	 * Indicates if all whitespace in tags with CDATA content should be
+	 * preserved.
+	 * <p>
+	 * Value is of type <code>Boolean</code>.
+	 * </p>
+	 */
+	public static final String PRESERVE_CDATACONTENT = "preserveCDATAContent";//$NON-NLS-1$
+
+	/**
+	 * Indicates if end brackets of start tags should be placed on a new line
+	 * if the start tag spans more than one line.
+	 * <p>
+	 * Value is of type <code>Boolean</code>.
+	 * </p>
+	 */
+	public static final String ALIGN_END_BRACKET = "alignEndBracket";//$NON-NLS-1$
+	
+	/**
+	 * Indicates if an empty close tag should have a space inserted before
+	 * closing.
+	 * <p>
+	 * Value is of type <code>Boolean</code>
+	 * </p>
+	 */
+	public static final String SPACE_BEFORE_EMPTY_CLOSE_TAG = "spaceBeforeEmptyCloseTag";//$NON-NLS-1$
+	
+    /**
+     * Indicates whether or not all schema locations for XSD should be honoured
+     * during XSD validation of XML.
+     * <p>
+     * Value is of type <code>boolean</code>.<br />
+     * Possible values: {TRUE, FALSE}
+     * </p>
+     * 
+     */
+    public static final String HONOUR_ALL_SCHEMA_LOCATIONS = "honourAllSchemaLocations";//$NON-NLS-1$
+
+    /**
+     * Indicates whether or not the content of comments should be formatted
+     * <p>
+     * Value is of type <code>boolean</code><br />
+     * Possible values: {TRUE, FALSE}
+     * </p>
+     */
+    public static final String FORMAT_COMMENT_TEXT = "formatCommentText"; //$NON-NLS-1$
+
+    /**
+     * Indicates whether or not the lines of comments should be joined when formatting
+     * <p>
+     * Value is of type <code>boolean</code>
+     */
+    public static final String FORMAT_COMMENT_JOIN_LINES = "formatCommentJoinLines"; //$NON-NLS-1$
+    
+    /**
+     * Indicates whether or not CMDocuments should be globally cached
+     * <p>
+     * Value is of type <code>boolean</code>
+     */
+    public static final String CMDOCUMENT_GLOBAL_CACHE_ENABLED = "cmDocumentGlobalCacheEnabled"; //$NON-NLS-1$
+    
+    /**
+	 * Indicates whether or not MarkUpValidator should run as part of XMl Validation.
+	 * <p>
+	 * Value is of type <code>boolean</code>.<br />
+	 * Possible values: {TRUE, FALSE} 
+	 * </p>
+	 */
+    public static final String MARKUP_VALIDATION = "markupValidation"; //$NON-NLS-1$
+    
+    /**
+	 * Indicates whether or not a message should be produced when validating a
+	 * file that specifies following condition.
+	 * <p>
+	 * Value is of type <code>integer</code>.<br />
+	 * Possible values: {0, 1, 2} (none, warning, error)
+	 * </p>
+	 */
+    public static final String ATTRIBUTE_HAS_NO_VALUE = "attributeHasNoValue"; //$NON-NLS-1$
+    public static final String END_TAG_WITH_ATTRIBUTES = "endTagWithAttributes"; //$NON-NLS-1$
+    public static final String WHITESPACE_BEFORE_TAGNAME = "whitespaceBeforeTagName"; //$NON-NLS-1$
+    public static final String MISSING_CLOSING_BRACKET = "missingClosingBracket"; //$NON-NLS-1$
+    public static final String MISSING_CLOSING_QUOTE = "missingClosingQuote"; //$NON-NLS-1$
+    public static final String MISSING_END_TAG = "missingEndTag"; //$NON-NLS-1$
+    public static final String MISSING_START_TAG = "missingStartTag"; //$NON-NLS-1$
+    public static final String MISSING_QUOTES = "missingQuotes"; //$NON-NLS-1$
+    public static final String NAMESPACE_IN_PI_TARGET = "namespaceInPITarget"; //$NON-NLS-1$
+    public static final String MISSING_TAG_NAME = "missingTagName"; //$NON-NLS-1$
+    public static final String WHITESPACE_AT_START = "whitespaceAtStart"; //$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/propagate/PropagatingAdapterFactoryImpl.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/propagate/PropagatingAdapterFactoryImpl.java
new file mode 100644
index 0000000..7376d4e
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/propagate/PropagatingAdapterFactoryImpl.java
@@ -0,0 +1,113 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.propagate;
+
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.wst.sse.core.internal.PropagatingAdapter;
+import org.eclipse.wst.sse.core.internal.PropagatingAdapterFactory;
+import org.eclipse.wst.sse.core.internal.provisional.AbstractAdapterFactory;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapter;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapterFactory;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+
+
+/**
+ * The PropagatingAdapterFactory is part of the "adapt on create" mechanism. A
+ * PropagatingAdapter, once added to a node, will cause proagating adapters to
+ * be created for all child nodes. A side effect of creating a
+ * PropagatingAdapter for a node is that is is also creates adapters for and
+ * adapts the Node for all other registered 'create on adapt' Adapters. This
+ * other adapters are registered by registering their factories via plugin
+ * extension point.
+ */
+public class PropagatingAdapterFactoryImpl extends AbstractAdapterFactory implements PropagatingAdapterFactory {
+
+	private PropagatingAdapter fAdapterInstance;
+	private List fContributedFactories = null;
+
+	/**
+	 * PropagatingAdapterFactory constructor comment.
+	 */
+	public PropagatingAdapterFactoryImpl() {
+		this(PropagatingAdapter.class, true);
+	}
+
+	protected PropagatingAdapterFactoryImpl(Object adapterKey, boolean registerAdapters) { // ,
+		super(adapterKey, registerAdapters);
+	}
+
+	public void addContributedFactories(INodeAdapterFactory factory) {
+		if (fContributedFactories != null) {
+			fContributedFactories.add(factory);
+		}
+
+	}
+
+	/**
+	 * createAdapter method comment.
+	 */
+	protected INodeAdapter createAdapter(INodeNotifier target) {
+		// every notifier get's one of these
+		// (and the same instance of it)
+		return getAdapterInstance();
+	}
+
+	/**
+	 * Gets the adapterInstance.
+	 * 
+	 * @return Returns a PropagatingAdapter
+	 */
+	private PropagatingAdapter getAdapterInstance() {
+		if (fAdapterInstance == null) {
+			fAdapterInstance = new PropagatingAdapterImpl();
+			if (fContributedFactories != null) {
+				for (int i = 0; i < fContributedFactories.size(); i++)
+					fAdapterInstance.addAdaptOnCreateFactory((PropagatingAdapterFactory) fContributedFactories.get(i));
+			}
+		}
+		return fAdapterInstance;
+	}
+
+	public void release() {
+		// give the adapter instance a chance to release its factories
+		getAdapterInstance().release();
+
+	}
+
+	public void setContributedFactories(ArrayList list) {
+		fContributedFactories = list;
+
+	}
+
+	public INodeAdapterFactory copy() {
+		PropagatingAdapterFactory clonedInstance = new PropagatingAdapterFactoryImpl(getAdapterKey(), isShouldRegisterAdapter());
+		// clone this adapters specific list of adapter factories too
+		if (fContributedFactories != null) {
+			
+			Iterator iterator = fContributedFactories.iterator();
+			clonedInstance.setContributedFactories(new ArrayList());
+			while (iterator.hasNext()) {
+				INodeAdapterFactory existingFactory = (INodeAdapterFactory) iterator.next();
+				clonedInstance.addContributedFactories(existingFactory.copy());
+			}
+		}
+		return clonedInstance;
+	}
+
+	
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/propagate/PropagatingAdapterImpl.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/propagate/PropagatingAdapterImpl.java
new file mode 100644
index 0000000..f581590
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/propagate/PropagatingAdapterImpl.java
@@ -0,0 +1,144 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.propagate;
+
+
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.wst.sse.core.internal.PropagatingAdapter;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapterFactory;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+
+public class PropagatingAdapterImpl implements PropagatingAdapter {
+
+	private List adaptOnCreateFactories = null;
+
+	/**
+	 * AbstractPropagatingAdapterImpl constructor comment.
+	 */
+	public PropagatingAdapterImpl() {
+		super();
+	}
+
+	private void adaptOnCreate(IDOMNode node) {
+		// give each of the factories a chance to adapt the node, if it
+		// chooses to
+		if (adaptOnCreateFactories != null) {
+
+
+			synchronized (adaptOnCreateFactories) {
+				int length = adaptOnCreateFactories.size();
+				for (int i = 0; i < length; i++) {
+					INodeAdapterFactory factory = (INodeAdapterFactory) adaptOnCreateFactories.get(i);
+					factory.adapt(node);
+				}
+			}
+
+		}
+
+	}
+
+	/**
+	 * This mechanism can be made "easier to use" later.
+	 */
+	public void addAdaptOnCreateFactory(INodeAdapterFactory factory) {
+		getAdaptOnCreateFactories().add(factory);
+	}
+
+	/**
+	 * Gets the adaptOnCreateFactories.
+	 * 
+	 * @return Returns a List
+	 */
+	public List getAdaptOnCreateFactories() {
+		if (adaptOnCreateFactories == null)
+			adaptOnCreateFactories = new ArrayList();
+		return adaptOnCreateFactories;
+	}
+
+
+	/**
+	 * @see PropagatingAdapter#initializeForFactory(INodeAdapterFactory,
+	 *      INodeNotifier)
+	 */
+	public void initializeForFactory(INodeAdapterFactory factory, INodeNotifier node) {
+		// ISSUE: we are a DOM specific implimentation, 
+		// we should not be.
+		if (node instanceof IDOMNode) {
+			IDOMNode xmlNode = (IDOMNode) node;
+			propagateTo(xmlNode);
+		}
+	}
+
+	/**
+	 * Allowing the INodeAdapter to compare itself against the type allows it
+	 * to return true in more than one case.
+	 */
+	public boolean isAdapterForType(Object type) {
+		return type.equals(PropagatingAdapter.class);
+	}
+
+	private boolean isInteresting(Object newValue) {
+		return (newValue != null && (newValue instanceof Element || newValue instanceof Document || newValue instanceof DocumentType));
+	}
+
+	/**
+	 */
+	public void notifyChanged(INodeNotifier notifier, int eventType, Object changedFeature, Object oldValue, Object newValue, int pos) {
+		// Issue: We only propagate to Elements ...
+		// not attributes too! We should careful consider doning all when
+		// when we improve "adapt on create" design.
+		if (eventType == INodeNotifier.ADD && isInteresting(newValue)) {
+			propagateTo((IDOMNode) newValue);
+		}
+	}
+
+	private void propagateTo(IDOMNode node) {
+		// get adapter to ensure its created
+		node.getAdapterFor(PropagatingAdapter.class);
+		adaptOnCreate(node);
+		propagateToChildren(node);
+	}
+
+	private void propagateToChildren(IDOMNode parent) {
+		for (Node child = parent.getFirstChild(); child != null; child = child.getNextSibling()) {
+			propagateTo((IDOMNode) child);
+		}
+	}
+
+	/**
+	 * @see PropagatingAdapter#release()
+	 */
+	public void release() {
+		if (adaptOnCreateFactories != null) {
+
+			synchronized (adaptOnCreateFactories) {
+				int length = adaptOnCreateFactories.size();
+				for (int i = 0; i < length; i++) {
+					INodeAdapterFactory factory = (INodeAdapterFactory) adaptOnCreateFactories.get(i);
+					factory.release();
+				}
+			}
+
+		}
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/IXMLCharEntity.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/IXMLCharEntity.java
new file mode 100644
index 0000000..b1fb483
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/IXMLCharEntity.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.provisional;
+
+
+
+/**
+ * XML Namespace constants
+ * 
+ * @plannedfor 1.0
+ */
+public interface IXMLCharEntity {
+	static final String AMP_NAME = "amp";//$NON-NLS-1$
+	static final String AMP_REF = "&amp;";//$NON-NLS-1$
+	static final String AMP_VALUE = "&";//$NON-NLS-1$
+	static final String APOS_NAME = "apos";//$NON-NLS-1$
+	static final String APOS_REF = "&apos;";//$NON-NLS-1$
+	static final String APOS_VALUE = "'";//$NON-NLS-1$
+	static final String GT_NAME = "gt";//$NON-NLS-1$
+	static final String GT_REF = "&gt;";//$NON-NLS-1$
+	static final String GT_VALUE = ">";//$NON-NLS-1$
+
+	static final String LT_NAME = "lt";//$NON-NLS-1$
+	static final String LT_REF = "&lt;";//$NON-NLS-1$
+	static final String LT_VALUE = "<";//$NON-NLS-1$
+	static final String QUOT_NAME = "quot";//$NON-NLS-1$
+	static final String QUOT_REF = "&quot;";//$NON-NLS-1$
+	static final String QUOT_VALUE = "\"";//$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/IXMLNamespace.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/IXMLNamespace.java
new file mode 100644
index 0000000..10847db
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/IXMLNamespace.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.provisional;
+
+
+
+/**
+ * XML Namespace constants
+ * 
+ * @plannedfor 1.0
+ */
+public interface IXMLNamespace {
+
+	String XMLNS = "xmlns";//$NON-NLS-1$
+	String XMLNS_PREFIX = "xmlns:";//$NON-NLS-1$
+	String XMLNS_URI = "http://www.w3.org/2000/xmlns/";//$NON-NLS-1$
+	String XML = "xml";//$NON-NLS-1$
+	String XML_PREFIX = "xml:";//$NON-NLS-1$
+	String XML_URI = "http://www.w3.org/XML/1998/namespace";//$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/IXMLPreferenceNames.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/IXMLPreferenceNames.java
new file mode 100644
index 0000000..df49d48
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/IXMLPreferenceNames.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.provisional;
+
+/**
+ * Keys to use for preference settings.
+ * 
+ * @plannedfor 1.0
+ */
+
+public interface IXMLPreferenceNames {
+	String CLEANUP_ATTR_NAME_CASE = "cleanupAttrNameCase";//$NON-NLS-1$
+	String CLEANUP_EOL_CODE = "cleanupEOLCode";//$NON-NLS-1$
+	// cleanup preference names
+	String CLEANUP_TAG_NAME_CASE = "cleanupTagNameCase";//$NON-NLS-1$
+	String CONVERT_EOL_CODES = "convertEOLCodes";//$NON-NLS-1$
+	String FORMAT_SOURCE = "formatSource";//$NON-NLS-1$
+	String INSERT_MISSING_TAGS = "insertMissingTags";//$NON-NLS-1$
+
+	// others
+	String LAST_ACTIVE_PAGE = "lastActivePage";//$NON-NLS-1$
+	String QUOTE_ATTR_VALUES = "quoteAttrValues";//$NON-NLS-1$
+
+	/*
+	 * not used for now // highlighting types String COMMENT_BORDER =
+	 * "commentBorder";//$NON-NLS-1$ String COMMENT_TEXT =
+	 * "commentText";//$NON-NLS-1$ String CDATA_BORDER =
+	 * "cdataBorder";//$NON-NLS-1$ String CDATA_TEXT =
+	 * "cdataText";//$NON-NLS-1$ String PI_BORDER = "piBorder";//$NON-NLS-1$
+	 * String PI_CONTENT = "piContent";//$NON-NLS-1$ String TAG_BORDER =
+	 * "tagBorder";//$NON-NLS-1$ String TAG_NAME = "tagName";//$NON-NLS-1$
+	 * String TAG_ATTRIBUTE_NAME = "tagAttributeName";//$NON-NLS-1$ String
+	 * TAG_ATTRIBUTE_VALUE = "tagAttributeValue";//$NON-NLS-1$ String
+	 * DECL_BORDER = "declBoder";//$NON-NLS-1$ String DOCTYPE_NAME =
+	 * "doctypeName";//$NON-NLS-1$ String DOCTYPE_EXTERNAL_ID =
+	 * "doctypeExternalId";//$NON-NLS-1$ String DOCTYPE_EXTERNAL_ID_PUBREF =
+	 * "doctypeExternalPubref";//$NON-NLS-1$ String DOCTYPE_EXTERNAL_ID_SYSREF =
+	 * "doctypeExtrenalSysref";//$NON-NLS-1$ String XML_CONTENT =
+	 * "xmlContent";//$NON-NLS-1$ // highlighting preferences String COMMA =
+	 * ",";//$NON-NLS-1$ String COLOR = "color";//$NON-NLS-1$ String NAME =
+	 * "name";//$NON-NLS-1$ String FOREGROUND = "foreground";//$NON-NLS-1$
+	 * String BACKGROUND = "background";//$NON-NLS-1$ String BOLD =
+	 * "bold";//$NON-NLS-1$ String ITALIC = "italic";//$NON-NLS-1$
+	 */
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/NameValidator.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/NameValidator.java
new file mode 100644
index 0000000..496beb7
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/NameValidator.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.provisional;
+
+import java.io.Reader;
+
+import org.eclipse.wst.xml.core.internal.parser.XML10Names;
+
+/**
+ * This class provides consistent way to pre-check if a string is a valid XML
+ * name, before, for example, trying to actually create an Element with it.
+ * Attempting to create an Element with an invalid name will throw the appropriate
+ * DOM Exception, but often clients want to check the validiting of a name
+ * such as based on some user input, long in advance of actually making 
+ * the DOM call. And, natually, want to give the user feedback in a more 
+ * timely fashion.
+ * 
+ * ISSUE: is "endns:" really valid xml name? I think not, but this method
+ * (currently) says it is.
+ * 
+ * @plannedfor 1.0
+ */
+public final class NameValidator {
+
+	private static XML10Names xml10charChecker = null;
+
+	/**
+	 * Returns true if <code>name</code> is valid XML name according to XML
+	 * 1.0 rules, false otherwise.
+	 * 
+	 * @param name
+	 *            name is the string to test
+	 * @return true if valid name according to XML 1.0 rules, false otherwise.
+	 */
+	public synchronized static final boolean isValid(String name) {
+
+		if (xml10charChecker == null) {
+			xml10charChecker = inititailizeXML10Names();
+		}
+		return xml10charChecker.isValidXML10Name(name);
+	}
+
+	private static XML10Names inititailizeXML10Names() {
+		return new XML10Names((Reader) null);
+	}
+
+	/**
+	 * Not intenteded to be instantiated.
+	 */
+	private NameValidator() {
+		super();
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/contentmodel/CMDocType.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/contentmodel/CMDocType.java
new file mode 100644
index 0000000..679cefd
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/contentmodel/CMDocType.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.provisional.contentmodel;
+
+
+public interface CMDocType {
+	/**
+	 * CHTML files
+	 */
+	public final static String CHTML_DOC_TYPE = "CHTML";//$NON-NLS-1$
+	/**
+	 * HTML files
+	 */
+	public final static String HTML_DOC_TYPE = "HTML";//$NON-NLS-1$
+	/**
+	 * HTML5 files
+	 */
+	public final static String HTML5_DOC_TYPE = "HTML5";//$NON-NLS-1$
+	/**
+	 * JSP 1.1 files (currently includes 1.2 elements for backward behavioral compatibility)
+	 */
+	public final static String JSP11_DOC_TYPE = "JSP11";//$NON-NLS-1$
+	/**
+	 * JSP 1.2 files
+	 */
+	public final static String JSP12_DOC_TYPE = "JSP12";//$NON-NLS-1$
+	/**
+	 * JSP 2.0 JSP files
+	 */
+	public final static String JSP20_DOC_TYPE = "JSP20";//$NON-NLS-1$
+	/**
+	 * JSP 2.0 Tag files
+	 */
+	public final static String TAG20_DOC_TYPE = "JSP20.TAG";//$NON-NLS-1$
+	/**
+	 * JSP 2.1 JSP files
+	 */
+	public final static String JSP21_DOC_TYPE = "JSP21";//$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/contentmodel/CMDocumentTracker.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/contentmodel/CMDocumentTracker.java
new file mode 100644
index 0000000..19baa55
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/contentmodel/CMDocumentTracker.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.provisional.contentmodel;
+
+
+
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+
+
+/**
+ * Position dependent CMDocument tracker. A tracker matches a
+ * IStructuredDocumentRegion with a CMDocument that it enables allowing for
+ * position-dependent content models
+ */
+public interface CMDocumentTracker {
+
+	CMDocument getDocument();
+
+	IStructuredDocumentRegion getStructuredDocumentRegion();
+}
+
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/contentmodel/CMNodeWrapper.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/contentmodel/CMNodeWrapper.java
new file mode 100644
index 0000000..dbe75d6
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/contentmodel/CMNodeWrapper.java
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.provisional.contentmodel;
+
+
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+public interface CMNodeWrapper extends CMNode {
+	CMNode getOriginNode();
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/contentmodel/ContentModelAdapter.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/contentmodel/ContentModelAdapter.java
new file mode 100644
index 0000000..a66811e
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/contentmodel/ContentModelAdapter.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.provisional.contentmodel;
+
+
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ * ContentModelAdapter interface
+ */
+public interface ContentModelAdapter extends org.eclipse.wst.sse.core.internal.provisional.INodeAdapter {
+
+	/**
+	 * getCMDocument method
+	 * 
+	 * @return CMDocument
+	 * @param notifer
+	 * 
+	 * Returns CMDocument associated to the adapting node. For exampl : HTML
+	 * CMDocument is associated to HTML Document node, DTD CMDocument is
+	 * associated to DocumentType node, DTD/Schema CMDocument is associated to
+	 * Element node (sometime with namespace), and taglib CMDocument is
+	 * associated to taglib directive Element node.
+	 * 
+	 * INodeNotifier is passed for stateless (singleton) INodeAdapter
+	 * implementation.
+	 */
+	CMDocument getCMDocument(org.eclipse.wst.sse.core.internal.provisional.INodeNotifier notifier);
+
+	/**
+	 * getDeclaration method
+	 * 
+	 * @return CMNode
+	 * @param notifer
+	 * 
+	 * Returns ElementDefinition or AttributeDefinition for the adapting node.
+	 * 
+	 * INodeNotifier is passed for stateless (singleton) INodeAdapter
+	 * implementation.
+	 */
+	CMNode getDeclaration(org.eclipse.wst.sse.core.internal.provisional.INodeNotifier notifier);
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/contentmodel/NullContentModel.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/contentmodel/NullContentModel.java
new file mode 100644
index 0000000..0b2ee6b
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/contentmodel/NullContentModel.java
@@ -0,0 +1,101 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.provisional.contentmodel;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+
+/**
+ * This class can be used to intialize specific variables that need a content
+ * model, until the true content model is available. This prevents having to
+ * do lots of null checks.
+ */
+public class NullContentModel implements CMDocument {
+
+	private static class NullCMNamedNodeMap implements CMNamedNodeMap {
+		public int getLength() {
+			return 0;
+		}
+
+		public CMNode getNamedItem(String name) {
+			return null;
+		}
+
+		public CMNode item(int index) {
+			return null;
+		}
+
+		public Iterator iterator() {
+			return new NullIterator();
+		}
+
+	}
+
+	private static class NullIterator implements Iterator {
+		public NullIterator() {
+		}
+
+		public boolean hasNext() {
+			return false;
+		}
+
+		public Object next() {
+			throw new NoSuchElementException();
+		}
+
+		public void remove() {
+			throw new UnsupportedOperationException("can not remove regions via iterator"); //$NON-NLS-1$
+
+		}
+
+	}
+
+	public NullContentModel() {
+		super();
+	}
+
+	public CMNamedNodeMap getElements() {
+		return new NullCMNamedNodeMap();
+	}
+
+	public CMNamedNodeMap getEntities() {
+		return new NullCMNamedNodeMap();
+	}
+
+	public CMNamespace getNamespace() {
+		return null;
+	}
+
+	public String getNodeName() {
+		return null;
+	}
+
+	public int getNodeType() {
+		return 0;
+	}
+
+	public Object getProperty(String propertyName) {
+		return null;
+	}
+
+	public boolean supports(String propertyName) {
+		return false;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/contenttype/ContentTypeIdForXML.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/contenttype/ContentTypeIdForXML.java
new file mode 100644
index 0000000..67c3a90
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/contenttype/ContentTypeIdForXML.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+
+package org.eclipse.wst.xml.core.internal.provisional.contenttype;
+
+/**
+ * This class, with its few field, is a convience to provide compile-time
+ * safety when refering to a contentType ID. The value of the contenttype id
+ * field must match what is specified in plugin.xml file.
+ * 
+ * @plannedfor 1.0
+ */
+final public class ContentTypeIdForXML {
+	/**
+	 * This content type is actually supplied by base Eclipse. Its given here
+	 * just as documentation for WTP based clients. Typically, clients should
+	 * use the values/constants supplied by base Eclipse.
+	 */
+	public final static String ContentTypeID_XML = getConstantString2();
+	/**
+	 * This value is public only for testing and special infrastructure. The
+	 * constant nor is value should not be referenced by clients.
+	 * 
+	 * The value of the contenttype id field must match what is specified in
+	 * plugin.xml file. Note: this value is intentially set with default
+	 * protected method so it will not be inlined.
+	 */
+	public final static String ContentTypeID_SSEXML = getConstantString();
+
+	/**
+	 * Don't allow instantiation.
+	 */
+	private ContentTypeIdForXML() {
+		super();
+	}
+
+	static String getConstantString() {
+		return "org.eclipse.wst.xml.core.xmlsource"; //$NON-NLS-1$
+	}
+
+	static String getConstantString2() {
+		return "org.eclipse.core.runtime.xml"; //$NON-NLS-1$
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/document/IDOMAttr.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/document/IDOMAttr.java
new file mode 100644
index 0000000..ee16e15
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/document/IDOMAttr.java
@@ -0,0 +1,128 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.provisional.document;
+
+
+
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+import org.w3c.dom.Attr;
+
+
+/**
+ * This interface provides extensions to corresponding DOM interface to enable
+ * functions for source editing and incremental parsing.
+ * 
+ * @plannedfor 1.0
+ * 
+ */
+public interface IDOMAttr extends IDOMNode, Attr {
+
+	/**
+	 * Get's the region in attribute representing the '=' sign. May or may not
+	 * have whitespace surrounding it.
+	 * 
+	 * @deprecated - 
+	 * ISSUE: need to change/remove to avoid exposing 'ITextRegion'
+	 * change to offset pattern, as others.
+	 * 
+	 * @return ITextRegion - the region representing the equals sign, or null
+	 *         if their is no equals sign.
+	 */
+	ITextRegion getEqualRegion();
+
+	/**
+	 * Gets the source location of the end of the attribute name, including
+	 * whitespace.
+	 * 
+	 * @return int - the source location of the end of the attribute name,
+	 *         including whitespace.
+	 */
+	int getNameRegionEndOffset();
+
+	/**
+	 * Gets the source location of the start of the attribute name.
+	 * 
+	 * @return int - the source location of the start of the attribute name.
+	 */
+	int getNameRegionStartOffset();
+
+
+	/**
+	 * Gets the text associated with the attribute name.
+	 * 
+	 * @return String - the text associated with the attribute name.
+	 */
+	String getNameRegionText();
+
+	/**
+	 * Gets the source location of the end of the attribute name, excluding
+	 * whitespace.
+	 * 
+	 * @return int - returns the source location of the end of the attribute
+	 *         name, excluding whitespace.
+	 */
+	int getNameRegionTextEndOffset();
+
+	/**
+	 * Gets the source location of the start of the attribute value.
+	 * 
+	 * @return int - returns the source location of the start of the attribute
+	 *         value.
+	 * 
+	 * ISSUE: need to better spec interaction with quote marks
+	 */
+	int getValueRegionStartOffset();
+
+	/**
+	 * Gets the text associated with the attribute value.
+	 * 
+	 * @return String - returns the text associated with the attribute value.
+	 */
+	String getValueRegionText();
+
+	/**
+	 * Check if Attr has a nested value (such as a JSP expression).
+	 * 
+	 * @return true if contains a nested value, false otherwise.
+	 */
+	boolean hasNestedValue();
+
+	/**
+	 * Check if Attr has only name but not equal sign nor value.
+	 * 
+	 * @return true if has only name but not equal sign nor value.
+	 */
+	boolean hasNameOnly();
+
+	/**
+	 * Returns true if attribute is defined globally for document. Returns
+	 * false if attribute is preceeded by a prefix (whether valid name space
+	 * or not). Returns true if its owning element is a global element.
+	 * 
+	 * @return true if attribute is defined globally for document. Returns
+	 *         false if attribute is preceeded by a prefix (whether valid name
+	 *         space or not). Returns true if its owning element is a global
+	 *         element.
+	 */
+	boolean isGlobalAttr();
+
+	/**
+	 * Returns true if is xml attr
+	 * 
+	 * ISSUE: need to figure out how to specify this one in a meaningful way.
+	 * 
+	 * @return boolean - returns true if is xml attr
+	 */
+	boolean isXMLAttr();
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/document/IDOMDocument.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/document/IDOMDocument.java
new file mode 100644
index 0000000..4d69e58
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/document/IDOMDocument.java
@@ -0,0 +1,100 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.provisional.document;
+
+
+
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+/**
+ * This interface enables creation of DOCTYPE declaration and some DOM Level 2
+ * interfaces. May be referenced but not implemented by clients.
+ * 
+ * @plannedfor 1.0
+ */
+public interface IDOMDocument extends Node, Document, IDOMNode {
+
+	/**
+	 * create comment element. tagName must be registered as comment element
+	 * name in plugin.xml
+	 * 
+	 * @param tagName
+	 *            the element name
+	 * @param isJSPTag
+	 *            true if the element is JSP style comment (&lt;%-- ...
+	 *            --%&gt;)
+	 * @return Element element instance
+	 * @throws DOMException
+	 *             thrown if the element name is registered as comment element
+	 */
+	Element createCommentElement(String tagName, boolean isJSPTag) throws DOMException;
+
+	/**
+	 * Creates a DocumentType node
+	 * 
+	 * ISSUE: I believe this 'name' is the one specific in doctype extension,
+	 * need to verify.
+	 * 
+	 * @param name -
+	 *            name of the doctype
+	 * @return DocumentType - returns a document type node.
+	 */
+	DocumentType createDoctype(String name);
+
+	/**
+	 * Returns the DocumentType ID. Unlike the standard DOM approach of
+	 * "getDocumentType().getPublicId()", this method returns the id even if
+	 * implicit.
+	 * 
+	 * @return the DocumentType ID
+	 */
+	String getDocumentTypeId();
+
+	/**
+	 * NOT API ... needs to be removed/changed
+	 * 
+	 * ISSUE: need to specify
+	 * 
+	 * @deprecated
+	 * 
+	 * @return true if is JSPDocument
+	 * 
+	 */
+	boolean isJSPDocument();
+
+	/**
+	 * NOT API ... needs to be removed/changed
+	 * 
+	 * ISSUE: need to specify
+	 * 
+	 * @deprecated
+	 * 
+	 */
+	boolean isJSPType();
+
+	/**
+	 * NOT API ... may removed/changed
+	 * 
+	 * ISSUE: need to specify -- currently used to denote an HTML DOM document
+	 * is XHTML
+	 * 
+	 * @deprecated
+	 * 
+	 */
+	boolean isXMLType();
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/document/IDOMDocumentType.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/document/IDOMDocumentType.java
new file mode 100644
index 0000000..602c65e
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/document/IDOMDocumentType.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.provisional.document;
+
+
+
+import org.w3c.dom.DocumentType;
+
+/**
+ * This interface enables setting of Public and System ID for DOCTYPE
+ * declaration.
+ * 
+ * @plannedfor 1.0
+ */
+public interface IDOMDocumentType extends IDOMNode, DocumentType {
+
+
+	/**
+	 * Sets document type's public id, as source.
+	 * 
+	 * @param String -
+	 *            the publicId
+	 */
+	void setPublicId(String publicId);
+
+	/**
+	 * Sets docment type's system id, as source.
+	 * 
+	 * @param String -
+	 *            the systemId
+	 */
+	void setSystemId(String systemId);
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/document/IDOMElement.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/document/IDOMElement.java
new file mode 100644
index 0000000..fcd7763
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/document/IDOMElement.java
@@ -0,0 +1,196 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.provisional.document;
+
+
+
+import org.w3c.dom.Attr;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Element;
+
+/**
+ * This interface provides extensions to corresponding DOM interface to enable
+ * functions for source editing and incremental parsing.
+ * 
+ * @plannedfor 1.0
+ * 
+ */
+public interface IDOMElement extends IDOMNode, Element {
+
+	/**
+	 * Retuns the start offset of the end tag.
+	 * 
+	 * ISSUE: need to sort out need for this
+	 * 
+	 * @return int - the start offset of the end tag.
+	 */
+	int getEndStartOffset();
+
+	/**
+	 * Returns the end offset of the
+	 * 
+	 * ISSUE: need to sort out need for this
+	 * 
+	 * @return int - the end offset of the start tag.
+	 */
+	int getStartEndOffset();
+
+	/**
+	 * Returns true if has an end tag.
+	 * 
+	 * In our source-oriented DOM, sometimes Elements are "ended", even
+	 * without an explicit end tag in the source.
+	 * 
+	 * @return true if has an end tag.
+	 */
+	boolean hasEndTag();
+
+	/**
+	 * returns true if has a start tag.
+	 * 
+	 * In our source-oriented DOM, a lone end tag will cause a node to be
+	 * created in the tree, unlike well-formed-only DOMs.
+	 * 
+	 * @return true if has a start tag.
+	 */
+	boolean hasStartTag();
+
+	/**
+	 * returns true if this element is a comment element
+	 * 
+	 * @return true if this element is a comment element
+	 */
+	boolean isCommentTag();
+
+	/**
+	 * isEmptyTag method
+	 * 
+	 * @return boolean - true if is empty tag, false otherwise
+	 */
+	boolean isEmptyTag();
+
+	/**
+	 * Returns true if floating end tag.
+	 * 
+	 * @return true if floating end tag.
+	 */
+	boolean isEndTag();
+
+	/**
+	 * Returns true for "global tag" (basically, without prefix)
+	 * 
+	 * @return true for "global tag" (basically, without prefix)
+	 */
+	boolean isGlobalTag();
+
+	/**
+	 * Returns true for no start and the end tags in source.
+	 * 
+	 * Provided for some very special cases when, for example, and HTML tag is
+	 * assumed in an HTML document that does not have a literal HTML tag.
+	 * 
+	 * ISSUE: check with clients to see if still needed
+	 * 
+	 * @return true or no start and the end tags in source.
+	 */
+	boolean isImplicitTag();
+
+	/**
+	 * isJSPTag method
+	 * 
+	 * @return boolean
+	 * 
+	 * ISSUE: change to isContainerLanguageTag(String type);
+	 */
+	boolean isJSPTag();
+
+	/**
+	 * Returns true if start tag is closed.
+	 * 
+	 * @return true if start tag is closed.
+	 */
+	boolean isStartTagClosed();
+
+	/**
+	 * returns true if is xml tag
+	 * 
+	 * ISSUE: need to spec this better.
+	 * 
+	 * @return true if is xml tag
+	 */
+	boolean isXMLTag();
+
+	/**
+	 * NOT CLIENT API
+	 * 
+	 * notifyEndTagChanged
+	 * 
+	 */
+	void notifyEndTagChanged();
+
+	/**
+	 * NOT CLIENT API
+	 * 
+	 * notifyStartTagChanged
+	 * 
+	 */
+	void notifyStartTagChanged();
+
+	/**
+	 * NOT CLIENT API
+	 * 
+	 * Signify that this tag is a comment
+	 * 
+	 * For use only by parsers.
+	 * 
+	 */
+	void setCommentTag(boolean isCommentTag);
+
+	/**
+	 * NOT CLIENT API
+	 * 
+	 * Signify that this tag is an empty tag
+	 * 
+	 * For use only by parsers
+	 */
+	void setEmptyTag(boolean isEmptyTag);
+
+	/**
+	 * NOT CLIENT API
+	 * 
+	 * Signify that this tag is a JSP tag
+	 * 
+	 * For use only by parsers
+	 * 
+	 * ISSUE: I have had one non-parsing client who has had to use this ...
+	 * need to check
+	 * 
+	 */
+	void setJSPTag(boolean isJSPTag);
+
+	/**
+	 * NOT IMPLEMENTED. Is defined here in preparation for DOM 3.
+	 */
+	public void setIdAttribute(String name, boolean isId);
+
+	/**
+	 * NOT IMPLEMENTED. Is defined here in preparation for DOM 3.
+	 */
+	public void setIdAttributeNS(String namespaceURI, String localName, boolean isId);
+
+	/**
+	 * NOT IMPLEMENTED. Is defined here in preparation for DOM 3.
+	 */
+	public void setIdAttributeNode(Attr idAttr, boolean isId) throws DOMException;
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/document/IDOMEntity.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/document/IDOMEntity.java
new file mode 100644
index 0000000..3e22ec0
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/document/IDOMEntity.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+
+package org.eclipse.wst.xml.core.internal.provisional.document;
+
+import org.w3c.dom.Entity;
+
+public interface IDOMEntity extends Entity {
+
+	/**
+	 * NOT IMPLEMENTED. Is defined here in preparation of DOM 3.
+	 */
+	public String getInputEncoding();
+
+	/**
+	 * NOT IMPLEMENTED. Is defined here in preparation of DOM 3.
+	 */
+	public String getXmlEncoding();
+
+	/**
+	 * NOT IMPLEMENTED. Is defined here in preparation of DOM 3.
+	 */
+	public String getXmlVersion();
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/document/IDOMImplementation.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/document/IDOMImplementation.java
new file mode 100644
index 0000000..da73e24
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/document/IDOMImplementation.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+
+package org.eclipse.wst.xml.core.internal.provisional.document;
+
+public interface IDOMImplementation {
+
+	/**
+	 * NOT IMPLEMENTED. This is defined here in preparation of DOM 3.
+	 * 
+	 * This method returns a specialized object which implements the
+	 * specialized APIs of the specified feature and version, as specified in .
+	 * The specialized object may also be obtained by using binding-specific
+	 * casting methods but is not necessarily expected to, as discussed in .
+	 * This method also allow the implementation to provide specialized
+	 * objects which do not support the <code>DOMImplementation</code>
+	 * interface.
+	 * 
+	 * @param feature
+	 *            The name of the feature requested. Note that any plus sign
+	 *            "+" prepended to the name of the feature will be ignored
+	 *            since it is not significant in the context of this method.
+	 * @param version
+	 *            This is the version number of the feature to test.
+	 * @return Returns an object which implements the specialized APIs of the
+	 *         specified feature and version, if any, or <code>null</code>
+	 *         if there is no object which implements interfaces associated
+	 *         with that feature. If the <code>DOMObject</code> returned by
+	 *         this method implements the <code>DOMImplementation</code>
+	 *         interface, it must delegate to the primary core
+	 *         <code>DOMImplementation</code> and not return results
+	 *         inconsistent with the primary core
+	 *         <code>DOMImplementation</code> such as
+	 *         <code>hasFeature</code>, <code>getFeature</code>, etc.
+	 * @see DOM Level 3
+	 */
+	public Object getFeature(String feature, String version);
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/document/IDOMModel.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/document/IDOMModel.java
new file mode 100644
index 0000000..3effc7e
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/document/IDOMModel.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.provisional.document;
+
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.xml.core.internal.document.XMLModelNotifier;
+
+/**
+ * Provides means to get the XMLModel form of IStrucutredModel. Not to be
+ * implemented or extended by clients.
+ * 
+ * @plannedfor 1.0
+ */
+public interface IDOMModel extends IStructuredModel {
+
+	/**
+	 * Returns the DOM Document.
+	 * 
+	 * @return the DOM Document.
+	 */
+	IDOMDocument getDocument();
+
+	/**
+	 * 
+	 * Returns an source generator appropriate for this model.
+	 * 
+	 * @return the source generator
+	 */
+	ISourceGenerator getGenerator();
+
+	/**
+	 * NOT CLIENT API
+	 * 
+	 * Returns an XMLModelNotifier. Clients should not use.
+	 * 
+	 * ISSUE: should be "internalized".
+	 * 
+	 */
+	XMLModelNotifier getModelNotifier();
+
+	/**
+	 * NOT CLIENT API
+	 *
+	 * Sets the model notifier Clients should not use.
+	 * 
+	 * ISSUE: need to review with legacy clients.
+	 */
+	void setModelNotifier(XMLModelNotifier notifier);
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/document/IDOMNode.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/document/IDOMNode.java
new file mode 100644
index 0000000..ed8875f
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/document/IDOMNode.java
@@ -0,0 +1,272 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.provisional.document;
+
+
+
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
+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.xml.core.internal.document.InvalidCharacterException;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Node;
+
+/**
+ * This interface describes the extended functionality of our source-oriented
+ * DOM. First, our nodes extend the w3c Node interface, IndexedRegion, and
+ * INodeNotifier. Plus, has the extra methods called out here.
+ * 
+ * ISSUE: the 'read-only' API should be broken out in their own interface
+ * 
+ * @plannedfor 1.0
+ * 
+ */
+public interface IDOMNode extends IndexedRegion, INodeNotifier, Node {
+
+	/**
+	 * Gets the last structured document region of this node.
+	 * 
+	 * ISSUE: need to resolve getEnd/getLast confusion.
+	 * 
+	 * @return IStructuredDocumentRegion - returns the last structured
+	 *         document region associated with
+	 */
+	IStructuredDocumentRegion getEndStructuredDocumentRegion();
+
+	/**
+	 * Gets the first structured document region of this node.
+	 * 
+	 * ISSUE: need to resolve getFirst/getStart confusion
+	 * 
+	 * @return the first structured document region of this node.
+	 */
+	IStructuredDocumentRegion getFirstStructuredDocumentRegion();
+
+	/**
+	 * Gets the last structured document region of this node.
+	 * 
+	 * ISSUE: need to resolve getEnd/getLast confusion.
+	 * 
+	 * @return IStructuredDocumentRegion - returns the last structured
+	 *         document region associated with
+	 */
+	IStructuredDocumentRegion getLastStructuredDocumentRegion();
+
+	/**
+	 * Returns the model associated with this node. Returns null if not part
+	 * of an active model.
+	 * 
+	 * @return IDOMModel - returns the IDOMModel this node is part of.
+	 */
+	IDOMModel getModel();
+
+	/**
+	 * Get's the region representing the name of this node
+	 * 
+	 * ISSUE: only implemented/used at attribute and DTDNodes -- should move.
+	 * 
+	 * @return ITextRegion - returns the ITextRegion associated with this
+	 *         Node.
+	 * 
+	 * @deprecated
+	 */
+	ITextRegion getNameRegion();
+
+	/**
+	 * Returns the literal source representing this node in source document.
+	 * 
+	 * ISSUE: need to fix implementation to match.
+	 * 
+	 * @return the literal source representing this node in source document.
+	 */
+	String getSource();
+
+	/**
+	 * Gets the first structured document region of this node.
+	 * 
+	 * ISSUE: need to resolve getFirst/getStart confusion
+	 * 
+	 * @return the first structured document region of this node.
+	 */
+	IStructuredDocumentRegion getStartStructuredDocumentRegion();
+
+	/**
+	 * Returns the structured document that underlies this node's model.
+	 * 
+	 * Returns null if this node is not actively part of a source document. In
+	 * contrast, in the pure DOM world, "owning document" is not null even
+	 * after a node is deleted from the DOM.
+	 * 
+	 * ISSUE: we need to fix our implementation to match this spec.
+	 * 
+	 * @return the structured document.
+	 */
+	IStructuredDocument getStructuredDocument();
+
+	/**
+	 * Get's the region representing the value of this node if only one
+	 * ITextRegion, null otherwise.
+	 * 
+	 * ISSUE: only implemented/used at attribute level, move "down".
+	 * 
+	 * @return ITextRegion - returns the ITextRegion associated with this
+	 *         Node.
+	 * 
+	 * @deprecated
+	 */
+	ITextRegion getValueRegion();
+
+	/**
+	 * Returns a string representing the source of this node, but with
+	 * character enties converted (e.g. &lt; is converted to '<').
+	 * 
+	 * ISSUE: need to better spec extent of this conversion, we may not know
+	 * all character entities.
+	 * 
+	 * ISSUE: need to fix implementation to match spec.
+	 * 
+	 * @return String - get's the source of this Node.
+	 */
+	String getValueSource();
+
+	/**
+	 * Used to know read-only state of children.
+	 * 
+	 * @return boolean Whether children of the element can be appended or
+	 *         removed.
+	 */
+	boolean isChildEditable();
+
+	/**
+	 * Returns true if tag is closed in source.
+	 * 
+	 * In our source orient DOM we sometimes end a Node without it being
+	 * explicitly closed in source.
+	 * 
+	 * @return boolean - true if node is closed
+	 */
+	boolean isClosed();
+
+	/**
+	 * Returns true if this node can contain children.
+	 * 
+	 * @return boolean - true if this node can contain children.
+	 */
+	boolean isContainer();
+
+	/**
+	 * Used to know read-only state of data.
+	 * 
+	 */
+	boolean isDataEditable();
+
+	/**
+	 * Set's readonly state of children
+	 * 
+	 */
+	void setChildEditable(boolean editable);
+
+	/**
+	 * Set's readonly state of data
+	 * 
+	 */
+	void setDataEditable(boolean editable);
+
+	/**
+	 * Sets readonly state of data
+	 * 
+	 * faster approach to set read-only state.
+	 */
+	void setEditable(boolean editable, boolean deep);
+
+	/**
+	 * Sets the specified raw source to the Text node. Throws
+	 * InvalidCharacterException when the specified raw source includes
+	 * invalid characters, such as, ' <', '>' and '&'. Valid character
+	 * entities, such as, "&amp;lt;", are accepted.
+	 */
+	void setSource(String source) throws InvalidCharacterException;
+
+	/**
+	 * Sets the specified raw source to the Text or Attr node's value. When
+	 * the specified raw source includes invalid characters, such as, ' <',
+	 * '>' and '&', converts them. Valid character entities, such as,
+	 * "&amp;lt;", are accepted.
+	 */
+	void setValueSource(String source);
+	
+	
+
+	/**
+	 * NOT IMPLEMENTED, is defined here in preparation of DOM Level 3
+	 */
+	public short compareDocumentPosition(Node other) throws DOMException;
+
+	/**
+	 * NOT IMPLEMENTED, is defined here in preparation of DOM Level 3
+	 */
+	public String getBaseURI();
+
+	/**
+	 * NOT IMPLEMENTED, is defined here in preparation of DOM Level 3
+	 */
+	public Object getFeature(String feature, String version);
+
+	/**
+	 * NOT IMPLEMENTED, is defined here in preparation of DOM Level 3
+	 */
+	public String getTextContent() throws DOMException;
+
+	/**
+	 * NOT IMPLEMENTED, is defined here in preparation of DOM Level 3
+	 */
+	public Object getUserData(String key);
+
+	/**
+	 * NOT IMPLEMENTED, is defined here in preparation of DOM Level 3
+	 */
+	public boolean isDefaultNamespace(String namespaceURI);
+
+	/**
+	 * NOT IMPLEMENTED, is defined here in preparation of DOM Level 3
+	 */
+	public boolean isEqualNode(Node arg);
+	
+	/**
+	 * NOT IMPLEMENTED, is defined here in preparation of DOM Level 3
+	 */
+	public boolean isSameNode(Node other);
+
+	/**
+	 * NOT IMPLEMENTED, is defined here in preparation of DOM Level 3
+	 */
+	public String lookupNamespaceURI(String prefix);
+
+	/**
+	 * NOT IMPLEMENTED, is defined here in preparation of DOM Level 3
+	 */
+	public String lookupPrefix(String namespaceURI);
+	
+	/**
+	 * NOT IMPLEMENTED, is defined here in preparation of DOM Level 3
+	 */
+	public void setTextContent(String textContent) throws DOMException;
+	
+	
+	/**
+	 * NOT IMPLEMENTED, is defined here in preparation of DOM Level 3
+	 */
+	public boolean isId();
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/document/IDOMText.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/document/IDOMText.java
new file mode 100644
index 0000000..efb3a5f
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/document/IDOMText.java
@@ -0,0 +1,129 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.provisional.document;
+
+
+
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Text;
+
+/**
+ * This interface provides extensions to corresponding DOM interface to enable
+ * functions for source editing and incremental parsing.
+ * 
+ * @plannedfor 1.0
+ * 
+ */
+public interface IDOMText extends IDOMNode, Text {
+
+	/**
+	 * NOT API - can be eliminated or moved to ltk level
+	 * 
+	 * Appends the content of the text node
+	 * 
+	 * @param text -
+	 *            the Text to append.
+	 */
+	void appendText(Text text);
+
+	/**
+	 * NOT API - can be eliminated or moved to ltk level
+	 * 
+	 * Returns true if is not valid.
+	 */
+	boolean isInvalid();
+
+	/**
+	 * Returns true if is entirely white space.
+	 * 
+	 * This is intened to be better performing that all clients getting the
+	 * source, and checking themselves.
+	 * 
+	 * ISSUE: need to clarify if implementation is pure to "white space" as
+	 * per DOM spec? Here is the DOM spec:
+	 * 
+	 * Returns whether this text node contains <a
+	 * href='http://www.w3.org/TR/2004/REC-xml-infoset-20040204#infoitem.character'>
+	 * element content whitespace</a>, often abusively called "ignorable
+	 * whitespace". The text node is determined to contain whitespace in
+	 * element content during the load of the document or if validation occurs
+	 * while using <code>Document.normalizeDocument()</code>.
+	 * 
+	 * @see DOM Level 3
+	 * 
+	 * @return true if is entirely white space.
+	 */
+
+	public boolean isElementContentWhitespace();
+
+	/**
+	 * NOT YET IMPLEMTENTED but exists here interface in preparation for DOM3
+	 * 
+	 * Returns all text of <code>Text</code> nodes logically-adjacent text
+	 * nodes to this node, concatenated in document order. <br>
+	 * For instance, in the example below <code>wholeText</code> on the
+	 * <code>Text</code> node that contains "bar" returns "barfoo", while on
+	 * the <code>Text</code> node that contains "foo" it returns "barfoo".
+	 * 
+	 * @see DOM Level 3
+	 * 
+	 */
+	public String getWholeText();
+
+	/**
+	 * NOT YET IMPLEMTENTED but exists here interface in preparation for DOM3
+	 * 
+	 * Replaces the text of the current node and all logically-adjacent text
+	 * nodes with the specified text. All logically-adjacent text nodes are
+	 * removed including the current node unless it was the recipient of the
+	 * replacement text. <br>
+	 * This method returns the node which received the replacement text. The
+	 * returned node is:
+	 * <ul>
+	 * <li><code>null</code>, when the replacement text is the empty
+	 * string; </li>
+	 * <li>the current node, except when the current node is read-only; </li>
+	 * <li> a new <code>Text</code> node of the same type (
+	 * <code>Text</code> or <code>CDATASection</code>) as the current
+	 * node inserted at the location of the replacement. </li>
+	 * </ul>
+	 * <br>
+	 * For instance, in the above example calling
+	 * <code>replaceWholeText</code> on the <code>Text</code> node that
+	 * contains "bar" with "yo" in argument results in the following: <br>
+	 * Where the nodes to be removed are read-only descendants of an
+	 * <code>EntityReference</code>, the <code>EntityReference</code>
+	 * must be removed instead of the read-only nodes. If any
+	 * <code>EntityReference</code> to be removed has descendants that are
+	 * not <code>EntityReference</code>, <code>Text</code>, or
+	 * <code>CDATASection</code> nodes, the <code>replaceWholeText</code>
+	 * method must fail before performing any modification of the document,
+	 * raising a <code>DOMException</code> with the code
+	 * <code>NO_MODIFICATION_ALLOWED_ERR</code>. <br>
+	 * For instance, in the example below calling
+	 * <code>replaceWholeText</code> on the <code>Text</code> node that
+	 * contains "bar" fails, because the <code>EntityReference</code> node
+	 * "ent" contains an <code>Element</code> node which cannot be removed.
+	 * 
+	 * @param content
+	 *            The content of the replacing <code>Text</code> node.
+	 * @return The <code>Text</code> node created with the specified
+	 *         content.
+	 * @exception DOMException
+	 *                NO_MODIFICATION_ALLOWED_ERR: Raised if one of the
+	 *                <code>Text</code> nodes being replaced is readonly.
+	 * @see DOM Level 3
+	 */
+	public Text replaceWholeText(String content) throws DOMException;
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/document/ISourceGenerator.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/document/ISourceGenerator.java
new file mode 100644
index 0000000..473048c
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/document/ISourceGenerator.java
@@ -0,0 +1,201 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.provisional.document;
+
+import org.w3c.dom.Attr;
+import org.w3c.dom.CDATASection;
+import org.w3c.dom.Comment;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Element;
+import org.w3c.dom.EntityReference;
+import org.w3c.dom.Node;
+import org.w3c.dom.ProcessingInstruction;
+import org.w3c.dom.Text;
+
+/**
+ * 
+ * ISourceGenerator allows DOM models to generate source appropriate for their
+ * parameter, relative to the model that provides the source generator.
+ * 
+ */
+
+public interface ISourceGenerator {
+
+	/**
+	 * Generate attribute name.
+	 * 
+	 * @param attr -
+	 *            the Attr
+	 * @return String - the string generated
+	 */
+	String generateAttrName(Attr attr);
+
+	/**
+	 * generateAttrValue
+	 * 
+	 * @param attr -
+	 *            the Attr
+	 * @return String - the string generated
+	 */
+	String generateAttrValue(Attr attr);
+
+	/**
+	 * generateAttrValue
+	 * 
+	 * @param attr -
+	 *            the Attr
+	 * @param char -
+	 *            the type of quote desired (' or ").
+	 * @return String - the string generated
+	 */
+	String generateAttrValue(Attr attr, char quote);
+
+	/**
+	 * generateAttrValue
+	 * 
+	 * @param value
+	 *            the String value
+	 * @param char -
+	 *            the type of quote desired (' or ").
+	 * @return String - the string generated
+	 */
+	String generateAttrValue(String value, char quote);
+
+	/**
+	 * generateCDATASection method
+	 * 
+	 * @param comment
+	 *            CDATASection
+	 * @return String - the string generated
+	 */
+	String generateCDATASection(CDATASection cdata);
+
+	/**
+	 * generateChild method
+	 * 
+	 * @return String
+	 * @param Node
+	 * @return String - the string generated
+	 */
+	String generateChild(Node parentNode);
+
+	/**
+	 * generateCloseTag
+	 * 
+	 * @param node -
+	 *            the Node
+	 * @return String - the string generated
+	 */
+	String generateCloseTag(Node node);
+
+	/**
+	 * generateComment method
+	 * 
+	 * @param comment
+	 *            org.w3c.dom.Comment
+	 * @return String - the string generated
+	 */
+	String generateComment(Comment comment);
+
+	/**
+	 * generateDoctype method
+	 * 
+	 * @param docType
+	 *            DocumentType
+	 * @return String - the string generated
+	 */
+	String generateDoctype(DocumentType docType);
+
+	/**
+	 * generateElement method
+	 * 
+	 * @param element -
+	 *            Element
+	 * @return String - the string generated
+	 */
+	String generateElement(Element element);
+
+	/**
+	 * generateEndTag method
+	 * 
+	 * @param element -
+	 *            Element
+	 * @return String - the string generated
+	 */
+	String generateEndTag(Element element);
+
+	/**
+	 * generateEntityRef method
+	 * 
+	 * @param entityRef
+	 *            EntityReference
+	 * @return String - the string generated
+	 */
+	String generateEntityRef(EntityReference entityRef);
+
+	/**
+	 * generatePI method
+	 * 
+	 * @param pi -
+	 *            ProcessingInstruction
+	 * @return String - the string generated
+	 */
+	String generatePI(ProcessingInstruction pi);
+
+	/**
+	 * generateSource method
+	 * 
+	 * @param node -
+	 *            the Node
+	 * @return String - the string generated
+	 */
+	String generateSource(Node node);
+
+	/**
+	 * generateStartTag method
+	 * 
+	 * @param element
+	 *            Element
+	 * @return String - the string generated
+	 */
+	String generateStartTag(Element element);
+
+	/**
+	 * Generate tag name.
+	 * 
+	 * @param element -
+	 *            element
+	 * @return String - the string generated
+	 */
+	String generateTagName(Element element);
+
+	/**
+	 * generateText method
+	 * 
+	 * @param text -
+	 *            the Text
+	 * @return String - the string generated
+	 */
+	String generateText(Text text);
+
+	/**
+	 * generate text data
+	 * 
+	 * @param text -
+	 *            the Text
+	 * @param data -
+	 *            the data
+	 * @return String - the string generated
+	 */
+	String generateTextData(Text text, String data);
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/format/CommentNodeFormatter.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/format/CommentNodeFormatter.java
new file mode 100644
index 0000000..7fba905
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/format/CommentNodeFormatter.java
@@ -0,0 +1,101 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     David Carver (STAR) - bug 296999 - Inefficient use of new String()
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.provisional.format;
+
+import org.eclipse.wst.sse.core.internal.format.IStructuredFormatContraints;
+import org.eclipse.wst.sse.core.utils.StringUtils;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.w3c.dom.Node;
+
+
+public class CommentNodeFormatter extends NodeFormatter {
+	static private final String CR = "\r"; //$NON-NLS-1$
+	static private final String LF = "\n"; //$NON-NLS-1$
+
+	protected String adjustIndentations(String aString, String lineIndent, String singleIndent) {
+		String result = NodeFormatter.EMPTY_STRING;
+
+		int indexOfLineDelimiter = StringUtils.indexOfLineDelimiter(aString);
+		result = aString.substring(0, indexOfLineDelimiter);
+		while (indexOfLineDelimiter != -1) {
+			// Before find the next LineDelimiter, we have to figure out the
+			// size of the current LineDelimiter
+			// so we can figure out how many bytes to skip before finding the
+			// next LineDelimiter.
+			// Otherwise, we may treat the LF in CRLF as the next
+			// LineDelimiter.
+			int lineDelimiterSize = 1;
+			if (aString.length() >= indexOfLineDelimiter + 2 && aString.substring(indexOfLineDelimiter, indexOfLineDelimiter + 1).compareTo(CR) == 0 && aString.substring(indexOfLineDelimiter + 1, indexOfLineDelimiter + 2).compareTo(LF) == 0)
+				lineDelimiterSize = 2;
+
+			int indexOfNextLineDelimiter = StringUtils.indexOfLineDelimiter(aString, indexOfLineDelimiter + lineDelimiterSize);
+			int indexOfNonblank = StringUtils.indexOfNonblank(aString, indexOfLineDelimiter);
+
+			if (indexOfNonblank != -1) {
+				if (indexOfNextLineDelimiter == -1) {
+					// last line; copy till the end
+					result += lineIndent + singleIndent + aString.substring(indexOfNonblank);
+				} else if (indexOfNextLineDelimiter != -1 && indexOfNextLineDelimiter < indexOfNonblank) {
+					// blank line; just add a indent
+					result += lineIndent + singleIndent;
+				} else {
+					// copy all text between indexOfNonblank and
+					// indexOfNextLineDelimiter
+					result += lineIndent + singleIndent + aString.substring(indexOfNonblank, indexOfNextLineDelimiter);
+				}
+
+				indexOfLineDelimiter = indexOfNextLineDelimiter;
+			} else {
+				if (indexOfNextLineDelimiter == -1) {
+					result += lineIndent;
+				} else {
+					// blank line; just add a indent
+					result += lineIndent + singleIndent;
+				}
+
+				indexOfLineDelimiter = indexOfNextLineDelimiter;
+			}
+		}
+
+		return result;
+	}
+
+	protected void formatNode(IDOMNode node, IStructuredFormatContraints formatContraints) {
+		if (node != null) {
+			// lineDelimiterFound means multi line comment
+			String nodeValue = node.getNodeValue();
+			boolean lineDelimiterFoundInComment = StringUtils.containsLineDelimiter(nodeValue);
+
+			if (lineDelimiterFoundInComment) {
+				// format indentation before node
+				formatIndentationBeforeNode(node, formatContraints);
+
+				// adjust indentations in multi line comment
+				String lineDelimiter = node.getModel().getStructuredDocument().getLineDelimiter();
+				String lineIndent = formatContraints.getCurrentIndent();
+				String singleIndent = getFormatPreferences().getIndent();
+				String newNodevalue = adjustIndentations(nodeValue, lineDelimiter + lineIndent, singleIndent);
+				if (nodeValue.compareTo(newNodevalue) != 0)
+					node.setNodeValue(newNodevalue);
+			}
+
+			if (!nodeHasSiblings(node) || (node.getPreviousSibling() != null && node.getPreviousSibling().getNodeType() == Node.TEXT_NODE && !StringUtils.containsLineDelimiter(node.getPreviousSibling().getNodeValue()) && node.getNextSibling() == null)) {
+				// single child
+				// or inline comment after text
+				// do nothing
+			} else
+				// format indentation after node
+				formatIndentationAfterNode(node, formatContraints);
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/format/DocumentNodeFormatter.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/format/DocumentNodeFormatter.java
new file mode 100644
index 0000000..297df28
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/format/DocumentNodeFormatter.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     Jesper Steen Møller - xml:space='preserve' support
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.provisional.format;
+
+import org.eclipse.wst.sse.core.internal.format.IStructuredFormatContraints;
+import org.eclipse.wst.sse.core.internal.format.IStructuredFormatter;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+
+
+public class DocumentNodeFormatter extends NodeFormatter {
+	protected void formatChildren(IDOMNode node, IStructuredFormatContraints formatContraints) {
+		String singleIndent = getFormatPreferences().getIndent();
+		String lineIndent = formatContraints.getCurrentIndent();
+
+		if (node != null && (fProgressMonitor == null || !fProgressMonitor.isCanceled())) {
+			// normalize node first to combine adjacent text nodes
+			node.normalize();
+
+			IDOMNode nextChild = (IDOMNode) node.getFirstChild();
+			while (nextChild != null) {
+				IDOMNode eachChildNode = nextChild;
+				nextChild = (IDOMNode) eachChildNode.getNextSibling();
+				IStructuredFormatter formatter = getFormatter(eachChildNode);
+				IStructuredFormatContraints childFormatContraints = formatter.getFormatContraints();
+				String childIndent = lineIndent + singleIndent;
+				childFormatContraints.setCurrentIndent(childIndent);
+				childFormatContraints.setClearAllBlankLines(formatContraints.getClearAllBlankLines());
+				childFormatContraints.setInPreserveSpaceElement(formatContraints.getInPreserveSpaceElement());
+
+				// format each child
+				formatter.format(eachChildNode, childFormatContraints);
+
+				if (nextChild != null && nextChild.getParentNode() == null)
+					// nextNode is deleted during format
+					nextChild = (IDOMNode) eachChildNode.getNextSibling();
+			}
+		}
+	}
+
+	protected void formatNode(IDOMNode node, IStructuredFormatContraints formatContraints) {
+		if (node != null)
+			formatChildren(node, formatContraints);
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/format/ElementNodeFormatter.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/format/ElementNodeFormatter.java
new file mode 100644
index 0000000..6baf55b
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/format/ElementNodeFormatter.java
@@ -0,0 +1,425 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     Jesper Steen Møller - xml:space='preserve' support
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.provisional.format;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.wst.sse.core.internal.format.IStructuredFormatContraints;
+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.ITextRegionList;
+import org.eclipse.wst.sse.core.utils.StringUtils;
+import org.eclipse.wst.xml.core.internal.Logger;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.document.AttrImpl;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
+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.provisional.document.ISourceGenerator;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+import org.eclipse.wst.xml.core.internal.ssemodelquery.ModelQueryAdapter;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+
+public class ElementNodeFormatter extends DocumentNodeFormatter {
+	static private final char DOUBLE_QUOTE = '"';//$NON-NLS-1$
+	static private final String DOUBLE_QUOTES = "\"\"";//$NON-NLS-1$
+	static private final char EQUAL_CHAR = '='; // equal sign$NON-NLS-1$
+	static private final String PRESERVE = "preserve";//$NON-NLS-1$
+	static private final String PRESERVE_QUOTED = "\"preserve\"";//$NON-NLS-1$
+	static private final char SINGLE_QUOTE = '\'';//$NON-NLS-1$
+	static private final String XML_SPACE = "xml:space";//$NON-NLS-1$
+	static private final char SPACE_CHAR = ' '; //$NON-NLS-1$
+	static private final String XSL_NAMESPACE = "http://www.w3.org/1999/XSL/Transform"; //$NON-NLS-1$
+	static private final String XSL_ATTRIBUTE = "attribute"; //$NON-NLS-1$
+	static private final String XSL_TEXT = "text"; //$NON-NLS-1$
+
+	protected void formatEndTag(IDOMNode node, IStructuredFormatContraints formatContraints) {
+		if (!isEndTagMissing(node)) {
+			// end tag exists
+
+			IStructuredDocument structuredDocument = node.getModel().getStructuredDocument();
+			String lineDelimiter = structuredDocument.getLineDelimiter();
+			String nodeIndentation = getNodeIndent(node);
+			IDOMNode lastChild = (IDOMNode) node.getLastChild();
+			if (lastChild != null && lastChild.getNodeType() != Node.TEXT_NODE) {
+				if (isEndTagMissing(lastChild)) {
+					// find deepest child
+					IDOMNode deepestChild = (IDOMNode) lastChild.getLastChild();
+					while (deepestChild != null && deepestChild.getLastChild() != null && isEndTagMissing(deepestChild)) {
+						lastChild = deepestChild;
+						deepestChild = (IDOMNode) deepestChild.getLastChild();
+					}
+
+					if (deepestChild != null) {
+						if (deepestChild.getNodeType() == Node.TEXT_NODE) {
+							// Special indentation handling if lastChild's end
+							// tag is missing and deepestChild is a text node.
+							String nodeText = deepestChild.getNodeValue();
+
+							if (!nodeText.endsWith(lineDelimiter + nodeIndentation)) {
+								nodeText = StringUtils.appendIfNotEndWith(nodeText, lineDelimiter);
+								nodeText = StringUtils.appendIfNotEndWith(nodeText, nodeIndentation);
+							}
+
+							replaceNodeValue(deepestChild, nodeText);
+						}
+						else
+							insertAfterNode(lastChild, lineDelimiter + nodeIndentation);
+					}
+				}
+				else
+					// indent end tag
+					insertAfterNode(lastChild, lineDelimiter + nodeIndentation);
+			}
+			else if (lastChild == null && firstStructuredDocumentRegionContainsLineDelimiters(node)) {
+				// BUG174243 do not indent end tag if node has empty content
+				// (otherwise new text node would be introduced)
+				ModelQueryAdapter adapter = (ModelQueryAdapter) ((IDOMDocument) node.getOwnerDocument()).getAdapterFor(ModelQueryAdapter.class);
+				CMElementDeclaration elementDeclaration = (CMElementDeclaration) adapter.getModelQuery().getCMNode(node);
+				if ((elementDeclaration == null) || (elementDeclaration.getContentType() != CMElementDeclaration.EMPTY)) {
+					// indent end tag
+					replace(structuredDocument, node.getFirstStructuredDocumentRegion().getEndOffset(), 0, lineDelimiter + nodeIndentation);
+				}
+			}
+
+			// format end tag name
+			IStructuredDocumentRegion endTagStructuredDocumentRegion = node.getLastStructuredDocumentRegion();
+			if (endTagStructuredDocumentRegion.getRegions().size() >= 3) {
+				ITextRegion endTagNameRegion = endTagStructuredDocumentRegion.getRegions().get(1);
+				removeRegionSpaces(node, endTagStructuredDocumentRegion, endTagNameRegion);
+			}
+		}
+	}
+
+	protected void formatNode(IDOMNode node, IStructuredFormatContraints formatContraints) {
+		if (node != null) {
+			// format indentation before node
+			formatIndentationBeforeNode(node, formatContraints);
+
+			// format start tag
+			IDOMNode newNode = node;
+			int startTagStartOffset = node.getStartOffset();
+			IDOMModel structuredModel = node.getModel();
+
+			boolean currentlyInXmlSpacePreserve = formatContraints.getInPreserveSpaceElement();
+			formatStartTag(node, formatContraints);
+			// save new node
+			newNode = (IDOMNode) structuredModel.getIndexedRegion(startTagStartOffset);
+
+			IStructuredDocumentRegion flatNode = newNode.getFirstStructuredDocumentRegion();
+			if (flatNode != null) {
+				ITextRegionList regions = flatNode.getRegions();
+				ITextRegion lastRegion = regions.get(regions.size() - 1);
+				// format children and end tag if not empty start tag
+				if (lastRegion.getType() != DOMRegionContext.XML_EMPTY_TAG_CLOSE) {
+					// format children
+					formatChildren(newNode, formatContraints);
+
+					// save new node
+					newNode = (IDOMNode) structuredModel.getIndexedRegion(startTagStartOffset);
+
+					// format end tag
+					formatEndTag(newNode, formatContraints);
+				}
+			}
+
+			formatContraints.setInPreserveSpaceElement(currentlyInXmlSpacePreserve);
+			// only indent if not at last node
+			if (newNode != null && newNode.getNextSibling() != null)
+				// format indentation after node
+				formatIndentationAfterNode(newNode, formatContraints);
+		}
+	}
+
+	/**
+	 * This method formats the start tag name, and formats the attributes if
+	 * available.
+	 */
+	protected void formatStartTag(IDOMNode node, IStructuredFormatContraints formatContraints) {
+		StructuredFormatPreferencesXML preferences = (StructuredFormatPreferencesXML) getFormatPreferences();
+		String singleIndent = preferences.getIndent();
+		String lineIndent = formatContraints.getCurrentIndent();
+		String attrIndent = lineIndent + singleIndent;
+		boolean splitMultiAttrs = preferences.getSplitMultiAttrs();
+		boolean alignEndBracket = preferences.isAlignEndBracket();
+		boolean sawXmlSpace = false;
+
+		IStructuredDocumentRegion flatNode = node.getFirstStructuredDocumentRegion();
+		NamedNodeMap attributes = node.getAttributes();
+
+		// Note: attributes should not be null even if the node has no
+		// attributes. However, attributes.getLength() will be 0. But, check
+		// for null just in case.
+		if (attributes != null) {
+			// compute current available line width
+			int currentAvailableLineWidth = 0;
+			try {
+				// 1 is for "<"
+				int nodeNameOffset = node.getStartOffset() + 1 + node.getNodeName().length();
+				int lineOffset = node.getStructuredDocument().getLineInformationOfOffset(nodeNameOffset).getOffset();
+				String text = node.getStructuredDocument().get(lineOffset, nodeNameOffset - lineOffset);
+				int usedWidth = getIndentationLength(text);
+				currentAvailableLineWidth = preferences.getLineWidth() - usedWidth;
+			}
+			catch (BadLocationException e) {
+				// log for now, unless we find reason not to
+				Logger.log(Logger.INFO, e.getMessage());
+			}
+
+			StringBuffer stringBuffer = new StringBuffer();
+			String lineDelimiter = node.getModel().getStructuredDocument().getLineDelimiter();
+			int attrLength = attributes.getLength();
+			int lastUndefinedRegionOffset = 0;
+			boolean startTagSpansOver1Line = false;
+
+			for (int i = 0; i < attrLength; i++) {
+				AttrImpl attr = (AttrImpl) attributes.item(i);
+				ITextRegion nameRegion = attr.getNameRegion();
+				ITextRegion equalRegion = attr.getEqualRegion();
+				ITextRegion valueRegion = attr.getValueRegion();
+
+				// append undefined regions
+				String undefinedRegion = getUndefinedRegions(node, lastUndefinedRegionOffset, attr.getStartOffset() - lastUndefinedRegionOffset);
+				stringBuffer.append(undefinedRegion);
+				lastUndefinedRegionOffset = attr.getStartOffset();
+
+				// check for xml:space attribute
+				if (flatNode.getText(nameRegion).compareTo(XML_SPACE) == 0) {
+					if (valueRegion == null) {
+						// [111674] If nothing has been written yet, treat as
+						// preserve, but only as hint
+						formatContraints.setInPreserveSpaceElement(true);
+						// Note we don't set 'sawXmlSpace', so that default or
+						// fixed DTD/XSD values may override.
+					}
+					else {
+						ISourceGenerator generator = node.getModel().getGenerator();
+						String newAttrValue = generator.generateAttrValue(attr);
+
+						// There is a problem in
+						// StructuredDocumentRegionUtil.getAttrValue(ITextRegion)
+						// when the region is instanceof ContextRegion.
+						// Workaround for now.
+						if (flatNode.getText(valueRegion).length() == 1) {
+							char firstChar = flatNode.getText(valueRegion).charAt(0);
+							if ((firstChar == DOUBLE_QUOTE) || (firstChar == SINGLE_QUOTE))
+								newAttrValue = DOUBLE_QUOTES;
+						}
+
+						if (newAttrValue.compareTo(PRESERVE_QUOTED) == 0)
+							formatContraints.setInPreserveSpaceElement(true);
+						else
+							formatContraints.setInPreserveSpaceElement(false);
+						sawXmlSpace = true;
+					}
+				}
+
+				if (splitMultiAttrs && attrLength > 1) {
+					stringBuffer.append(lineDelimiter + attrIndent);
+					stringBuffer.append(flatNode.getText(nameRegion));
+					startTagSpansOver1Line = true;
+					if (valueRegion != null) {
+						// append undefined regions
+						undefinedRegion = getUndefinedRegions(node, lastUndefinedRegionOffset, flatNode.getStartOffset(equalRegion) - lastUndefinedRegionOffset);
+						stringBuffer.append(undefinedRegion);
+						lastUndefinedRegionOffset = flatNode.getStartOffset(equalRegion);
+
+						stringBuffer.append(EQUAL_CHAR);
+
+						// append undefined regions
+						undefinedRegion = getUndefinedRegions(node, lastUndefinedRegionOffset, flatNode.getStartOffset(valueRegion) - lastUndefinedRegionOffset);
+						stringBuffer.append(undefinedRegion);
+						lastUndefinedRegionOffset = flatNode.getStartOffset(valueRegion);
+
+						// Note: trim() should not be needed for
+						// valueRegion.getText(). Just a workaround for a
+						// problem found in valueRegion for now.
+						stringBuffer.append(flatNode.getText(valueRegion).trim());
+					}
+				}
+				else {
+					if (valueRegion != null) {
+						int textLength = 1 + flatNode.getText(nameRegion).length() + 1 + flatNode.getText(valueRegion).length();
+						if (i == attrLength - 1) {
+							if (flatNode != null) {
+								ITextRegionList regions = flatNode.getRegions();
+								ITextRegion lastRegion = regions.get(regions.size() - 1);
+								if (lastRegion.getType() != DOMRegionContext.XML_EMPTY_TAG_CLOSE)
+									// 3 is for " />"
+									textLength += 3;
+								else
+									// 1 is for ">"
+									textLength++;
+							}
+						}
+
+						if (currentAvailableLineWidth >= textLength) {
+							stringBuffer.append(SPACE_CHAR);
+							currentAvailableLineWidth--;
+						}
+						else {
+							stringBuffer.append(lineDelimiter + attrIndent);
+							startTagSpansOver1Line = true;
+							currentAvailableLineWidth = preferences.getLineWidth() - attrIndent.length();
+						}
+
+						stringBuffer.append(flatNode.getText(nameRegion));
+
+						// append undefined regions
+						undefinedRegion = getUndefinedRegions(node, lastUndefinedRegionOffset, flatNode.getStartOffset(equalRegion) - lastUndefinedRegionOffset);
+						stringBuffer.append(undefinedRegion);
+						lastUndefinedRegionOffset = flatNode.getStartOffset(equalRegion);
+
+						stringBuffer.append(EQUAL_CHAR);
+
+						// append undefined regions
+						undefinedRegion = getUndefinedRegions(node, lastUndefinedRegionOffset, flatNode.getStartOffset(valueRegion) - lastUndefinedRegionOffset);
+						stringBuffer.append(undefinedRegion);
+						lastUndefinedRegionOffset = flatNode.getStartOffset(valueRegion);
+
+						// Note: trim() should not be needed for
+						// valueRegion.getText(). Just a workaround for a
+						// problem found in valueRegion for now.
+						stringBuffer.append(flatNode.getText(valueRegion).trim());
+
+						currentAvailableLineWidth -= flatNode.getText(nameRegion).length();
+						currentAvailableLineWidth--;
+						currentAvailableLineWidth -= flatNode.getText(valueRegion).trim().length();
+					}
+					else {
+						if (currentAvailableLineWidth >= 1 + flatNode.getText(nameRegion).length()) {
+							stringBuffer.append(SPACE_CHAR);
+							currentAvailableLineWidth--;
+						}
+						else {
+							stringBuffer.append(lineDelimiter + attrIndent);
+							startTagSpansOver1Line = true;
+							currentAvailableLineWidth = preferences.getLineWidth() - attrIndent.length();
+						}
+
+						stringBuffer.append(flatNode.getText(nameRegion));
+
+						currentAvailableLineWidth -= flatNode.getText(nameRegion).length();
+					}
+				}
+			}
+
+			// append undefined regions
+			String undefinedRegion = getUndefinedRegions(node, lastUndefinedRegionOffset, node.getEndOffset() - lastUndefinedRegionOffset);
+			stringBuffer.append(undefinedRegion);
+
+			IDOMModel structuredModel = node.getModel();
+			IStructuredDocument structuredDocument = structuredModel.getStructuredDocument();
+			// 1 is for "<"
+			int offset = node.getStartOffset() + 1 + node.getNodeName().length();
+			// 1 is for "<"
+			int length = node.getFirstStructuredDocumentRegion().getTextLength() - 1 - node.getNodeName().length();
+
+			if (flatNode != null) {
+				ITextRegionList regions = flatNode.getRegions();
+				ITextRegion firstRegion = regions.get(0);
+				ITextRegion lastRegion = regions.get(regions.size() - 1);
+
+				if (firstRegion.getType() == DOMRegionContext.XML_END_TAG_OPEN)
+					// skip formatting for end tags in this format: </tagName>
+					return;
+				else {
+					if (lastRegion.getType() == DOMRegionContext.XML_TAG_CLOSE || lastRegion.getType() == DOMRegionContext.XML_EMPTY_TAG_CLOSE)
+						length = length - lastRegion.getLength();
+
+					if (lastRegion.getType() == DOMRegionContext.XML_EMPTY_TAG_CLOSE) {
+						// leave space before XML_EMPTY_TAG_CLOSE: <tagName />
+						// unless already going to move end bracket
+						if (!startTagSpansOver1Line || !alignEndBracket)
+							stringBuffer.append(SPACE_CHAR);
+					}
+				}
+			}
+
+			if (startTagSpansOver1Line && alignEndBracket) {
+				stringBuffer.append(lineDelimiter).append(lineIndent);
+			}
+
+			replace(structuredDocument, offset, length, stringBuffer.toString());
+
+			// BUG108074 & BUG84688 - preserve whitespace in xsl:text &
+			// xsl:attribute
+			String nodeNamespaceURI = node.getNamespaceURI();
+			if (XSL_NAMESPACE.equals(nodeNamespaceURI)) {
+				String nodeName = ((Element) node).getLocalName();
+				if (XSL_ATTRIBUTE.equals(nodeName) || XSL_TEXT.equals(nodeName)) {
+					sawXmlSpace = true;
+					formatContraints.setInPreserveSpaceElement(true);
+				}
+			}
+
+			// If we didn't see a xml:space attribute above, we'll look for
+			// one in the DTD.
+			// We do not check for a conflict between a DTD's 'fixed' value
+			// and the attribute value found in the instance document, we
+			// leave that to the validator.
+			if (!sawXmlSpace) {
+				ModelQueryAdapter adapter = (ModelQueryAdapter) ((IDOMDocument) node.getOwnerDocument()).getAdapterFor(ModelQueryAdapter.class);
+				CMElementDeclaration elementDeclaration = (CMElementDeclaration) adapter.getModelQuery().getCMNode(node);
+				if (elementDeclaration != null) {
+					int contentType = elementDeclaration.getContentType();
+					if (preferences.isPreservePCDATAContent() && contentType == CMElementDeclaration.PCDATA) {
+						formatContraints.setInPreserveSpaceElement(true);
+					}
+					else {
+						CMNamedNodeMap cmAttributes = elementDeclaration.getAttributes();
+						// Check implied values from the DTD way.
+						CMAttributeDeclaration attributeDeclaration = (CMAttributeDeclaration) cmAttributes.getNamedItem(XML_SPACE);
+						if (attributeDeclaration != null) {
+							// CMAttributeDeclaration found, check it out.
+							String defaultValue = attributeDeclaration.getAttrType().getImpliedValue();
+
+							// xml:space="preserve" means preserve space,
+							// everything else means back to default.
+							if (PRESERVE.compareTo(defaultValue) == 0)
+								formatContraints.setInPreserveSpaceElement(true);
+							else
+								formatContraints.setInPreserveSpaceElement(false);
+						}
+					}
+				}
+			}
+		}
+	}
+
+	protected String getUndefinedRegions(IDOMNode node, int startOffset, int length) {
+		String result = NodeFormatter.EMPTY_STRING;
+
+		IStructuredDocumentRegion flatNode = node.getFirstStructuredDocumentRegion();
+		ITextRegionList regions = flatNode.getRegions();
+		for (int i = 0; i < regions.size(); i++) {
+			ITextRegion region = regions.get(i);
+			String regionType = region.getType();
+			int regionStartOffset = flatNode.getStartOffset(region);
+
+			if (regionType.compareTo(DOMRegionContext.UNDEFINED) == 0 && regionStartOffset >= startOffset && regionStartOffset < startOffset + length)
+				result = result + flatNode.getFullText(region);
+		}
+
+		if (result.length() > 0)
+			return SPACE_CHAR + result.trim();
+		else
+			return result;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/format/FormatProcessorXML.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/format/FormatProcessorXML.java
new file mode 100644
index 0000000..a798dbd
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/format/FormatProcessorXML.java
@@ -0,0 +1,115 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.provisional.format;
+
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.wst.sse.core.internal.format.AbstractStructuredFormatProcessor;
+import org.eclipse.wst.sse.core.internal.format.IStructuredFormatPreferences;
+import org.eclipse.wst.sse.core.internal.format.IStructuredFormatter;
+import org.eclipse.wst.xml.core.internal.XMLCorePlugin;
+import org.eclipse.wst.xml.core.internal.preferences.XMLCorePreferenceNames;
+import org.w3c.dom.Node;
+
+public class FormatProcessorXML extends AbstractStructuredFormatProcessor {
+	protected IStructuredFormatPreferences fFormatPreferences = null;
+
+	protected String getFileExtension() {
+		return "xml"; //$NON-NLS-1$
+	}
+
+	public IStructuredFormatPreferences getFormatPreferences() {
+		if (fFormatPreferences == null) {
+			fFormatPreferences = new StructuredFormatPreferencesXML();
+
+			Preferences preferences = getModelPreferences();
+			if (preferences != null) {
+				fFormatPreferences.setLineWidth(preferences.getInt(XMLCorePreferenceNames.LINE_WIDTH));
+				((StructuredFormatPreferencesXML) fFormatPreferences).setSplitMultiAttrs(preferences.getBoolean(XMLCorePreferenceNames.SPLIT_MULTI_ATTRS));
+				((StructuredFormatPreferencesXML) fFormatPreferences).setAlignEndBracket(preferences.getBoolean(XMLCorePreferenceNames.ALIGN_END_BRACKET));
+				((StructuredFormatPreferencesXML) fFormatPreferences).setPreservePCDATAContent(preferences.getBoolean(XMLCorePreferenceNames.PRESERVE_CDATACONTENT));
+				fFormatPreferences.setClearAllBlankLines(preferences.getBoolean(XMLCorePreferenceNames.CLEAR_ALL_BLANK_LINES));
+
+				char indentChar = ' ';
+				String indentCharPref = preferences.getString(XMLCorePreferenceNames.INDENTATION_CHAR);
+				if (XMLCorePreferenceNames.TAB.equals(indentCharPref)) {
+					indentChar = '\t';
+				}
+				int indentationWidth = preferences.getInt(XMLCorePreferenceNames.INDENTATION_SIZE);
+
+				StringBuffer indent = new StringBuffer();
+				for (int i = 0; i < indentationWidth; i++) {
+					indent.append(indentChar);
+				}
+				fFormatPreferences.setIndent(indent.toString());
+			}
+		}
+
+		return fFormatPreferences;
+	}
+
+	protected IStructuredFormatter getFormatter(Node node) {
+		// 262135 - NPE during format of empty document
+		if (node == null)
+			return null;
+
+		short nodeType = node.getNodeType();
+		IStructuredFormatter formatter = null;
+		switch (nodeType) {
+			case Node.ELEMENT_NODE : {
+				formatter = new ElementNodeFormatter();
+				break;
+			}
+			case Node.TEXT_NODE : {
+				formatter = new TextNodeFormatter();
+				break;
+			}
+			case Node.CDATA_SECTION_NODE : {
+				formatter = new NoMoveFormatter();
+				break;
+			}
+			case Node.COMMENT_NODE : {
+				formatter = new CommentNodeFormatter();
+				break;
+			}
+			case Node.PROCESSING_INSTRUCTION_NODE : {
+				formatter = new NodeFormatter();
+				break;
+			}
+			case Node.DOCUMENT_NODE : {
+				formatter = new DocumentNodeFormatter();
+				break;
+			}
+			case Node.ENTITY_REFERENCE_NODE : {
+				formatter = new NoMoveFormatter();
+				break;
+			}
+			default : {
+				formatter = new NodeFormatter();
+			}
+		}
+
+		// init fomatter
+		formatter.setFormatPreferences(getFormatPreferences());
+		formatter.setProgressMonitor(fProgressMonitor);
+
+		return formatter;
+	}
+
+	protected Preferences getModelPreferences() {
+		return XMLCorePlugin.getDefault().getPluginPreferences();
+	}
+
+	protected void refreshFormatPreferences() {
+		fFormatPreferences = null;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/format/NoMoveFormatter.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/format/NoMoveFormatter.java
new file mode 100644
index 0000000..7b68ece
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/format/NoMoveFormatter.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.provisional.format;
+
+import org.eclipse.wst.sse.core.internal.format.IStructuredFormatContraints;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+
+/**
+ * Formats entities which really need no formatting. They are just like text
+ * nodes.
+ */
+class NoMoveFormatter extends NodeFormatter {
+	protected void formatIndentationBeforeNode(IDOMNode node, IStructuredFormatContraints formatContraints) {
+		// node nothing
+	}
+
+	protected void formatIndentationAfterNode(IDOMNode node, IStructuredFormatContraints formatContraints) {
+		// still do nothing
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/format/NodeFormatter.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/format/NodeFormatter.java
new file mode 100644
index 0000000..f48ed18
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/format/NodeFormatter.java
@@ -0,0 +1,753 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     Jesper Steen Møller - xml:space='preserve' support
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.provisional.format;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.wst.sse.core.internal.format.IStructuredFormatContraints;
+import org.eclipse.wst.sse.core.internal.format.IStructuredFormatPreferences;
+import org.eclipse.wst.sse.core.internal.format.IStructuredFormatter;
+import org.eclipse.wst.sse.core.internal.format.StructuredFormatContraints;
+import org.eclipse.wst.sse.core.internal.parser.ContextRegion;
+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.ITextRegionList;
+import org.eclipse.wst.sse.core.utils.StringUtils;
+import org.eclipse.wst.xml.core.internal.Logger;
+import org.eclipse.wst.xml.core.internal.XMLCorePlugin;
+import org.eclipse.wst.xml.core.internal.document.CDATASectionImpl;
+import org.eclipse.wst.xml.core.internal.document.CharacterDataImpl;
+import org.eclipse.wst.xml.core.internal.document.CommentImpl;
+import org.eclipse.wst.xml.core.internal.parser.regions.TagNameRegion;
+import org.eclipse.wst.xml.core.internal.preferences.XMLCorePreferenceNames;
+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 org.w3c.dom.Node;
+
+public class NodeFormatter implements IStructuredFormatter {
+	static protected final String EMPTY_STRING = ""; //$NON-NLS-1$
+	static private final char SPACE_CHAR = ' '; //$NON-NLS-1$
+	static private final char TAB_CHAR = '\t'; //$NON-NLS-1$
+	static private final String TAB = "\t"; //$NON-NLS-1$
+	protected IStructuredFormatContraints fFormatContraints = null;
+	protected IStructuredFormatPreferences fFormatPreferences = null;
+	protected IProgressMonitor fProgressMonitor = null;
+
+	protected boolean firstStructuredDocumentRegionContainsLineDelimiters(IDOMNode node) {
+		boolean result = false;
+
+		if (node != null) {
+			IStructuredDocumentRegion firstStructuredDocumentRegion = node.getFirstStructuredDocumentRegion();
+			if (firstStructuredDocumentRegion != null) {
+				String firstStructuredDocumentRegionText = firstStructuredDocumentRegion.getText();
+				result = StringUtils.containsLineDelimiter(firstStructuredDocumentRegionText);
+			}
+		}
+
+		return result;
+	}
+
+	public void format(Node node) {
+		IStructuredFormatContraints formatContraints = getFormatContraints();
+
+		format(node, formatContraints);
+	}
+
+	public void format(Node node, IStructuredFormatContraints formatContraints) {
+		if (formatContraints.getFormatWithSiblingIndent())
+			formatContraints.setCurrentIndent(getSiblingIndent(node));
+
+		if (node instanceof IDOMNode)
+			formatNode((IDOMNode) node, formatContraints);
+	}
+
+	protected void formatIndentationAfterNode(IDOMNode node, IStructuredFormatContraints formatContraints) {
+		// [111674] If inside xml:space="preserve" element, we bail
+		if (formatContraints.getInPreserveSpaceElement())
+			return;
+		if (node != null) {
+			IDOMNode nextSibling = (IDOMNode) node.getNextSibling();
+			IStructuredDocument doc = node.getModel().getStructuredDocument();
+			String lineDelimiter = getLineDelimiter(node, doc);
+
+			if (node.getParentNode() != null) {
+				if (node.getParentNode().getNodeType() == Node.DOCUMENT_NODE)
+					if (nextSibling != null)
+						if (nextSibling.getNodeType() == Node.TEXT_NODE)
+							getFormatter(nextSibling).format(nextSibling, formatContraints);
+						else if (nextSibling.getNodeType() == Node.COMMENT_NODE) {
+							// do nothing
+						}
+						else {
+							String lineIndent = formatContraints.getCurrentIndent();
+							insertAfterNode(node, lineDelimiter + lineIndent);
+						}
+					else {
+					}
+
+				else if (nextSibling != null)
+					if (nextSibling.getNodeType() == Node.TEXT_NODE)
+						getFormatter(nextSibling).format(nextSibling, formatContraints);
+					else if (nextSibling.getNodeType() == Node.COMMENT_NODE) {
+						// do nothing
+					}
+					else {
+						String lineIndent = formatContraints.getCurrentIndent();
+						insertAfterNode(node, lineDelimiter + lineIndent);
+					}
+				else {
+					IDOMNode indentNode = getParentIndentNode(node);
+					String lineIndent = getNodeIndent(indentNode);
+					IDOMNode lastChild = getDeepestChildNode(node);
+					boolean clearAllBlankLines = formatContraints.getClearAllBlankLines();
+
+					if (lastChild != null) {
+						if ((lastChild.getNodeType() == Node.TEXT_NODE) && (lastChild.getNodeValue().endsWith(lineDelimiter + lineIndent))) {
+							// this text node already ends with the requested
+							// indentation
+						}
+
+						else if ((lastChild.getNodeType() == Node.TEXT_NODE) && (lastChild.getNodeValue() != null && lastChild.getNodeValue().endsWith(lineDelimiter)))
+							if (clearAllBlankLines) {
+								replaceNodeValue(lastChild, lineDelimiter + lineIndent);
+							}
+							else {
+								// append indentation
+								insertAfterNode(lastChild, lineIndent);
+							}
+						else if (lastChild.getNodeType() == Node.TEXT_NODE)
+							if (lastChild.getNodeValue().length() == 0) {
+								// replace
+								replaceNodeValue(lastChild, lineDelimiter + lineIndent);
+							}
+							else {
+								// append indentation
+								insertAfterNode(lastChild, lineDelimiter + lineIndent);
+							}
+						else {
+							// as long as not at the end of the document
+							IStructuredDocumentRegion endRegion = node.getLastStructuredDocumentRegion();
+							if (endRegion != null && endRegion.getNext() != null)
+								// append indentation
+								insertAfterNode(lastChild, lineDelimiter + lineIndent);
+						}
+					}
+				}
+			}
+		}
+	}
+
+	protected void formatIndentationBeforeNode(IDOMNode node, IStructuredFormatContraints formatContraints) {
+		// [111674] If inside xml:space="preserve" element, we bail
+		if (formatContraints.getInPreserveSpaceElement())
+			return;
+		if (node != null) {
+			IDOMNode previousSibling = (IDOMNode) node.getPreviousSibling();
+			IStructuredDocument doc = node.getModel().getStructuredDocument();
+			String lineDelimiter = getLineDelimiter(node, doc);
+
+			String lineIndent = formatContraints.getCurrentIndent();
+
+			if (node.getParentNode() != null) {
+				if (node.getParentNode().getNodeType() == Node.DOCUMENT_NODE) {
+					if (previousSibling != null)
+						if (previousSibling.getNodeType() == Node.TEXT_NODE)
+							getFormatter(previousSibling).format(previousSibling, formatContraints);
+						else {
+							insertBeforeNode(node, lineDelimiter + lineIndent);
+						}
+				}
+				else {
+					if (previousSibling == null || previousSibling.getNodeType() != Node.TEXT_NODE) {
+						// 261968 - formatting tag without closing bracket:
+						// <t1><t1
+						// 265673 - Null ptr in formatIndentationBeforeNode
+						int prevEndNodeOffset = -1;
+						int prevEndRegionOffset = -1;
+						if (previousSibling != null) {
+							prevEndNodeOffset = previousSibling.getEndOffset();
+							IStructuredDocumentRegion endRegion = previousSibling.getEndStructuredDocumentRegion();
+							if (endRegion != null) {
+								prevEndRegionOffset = endRegion.getTextEndOffset();
+							}
+						}
+						if ((previousSibling == null) || (prevEndNodeOffset != -1 && prevEndNodeOffset == prevEndRegionOffset)) {
+							insertBeforeNode(node, lineDelimiter + lineIndent);
+						}
+
+					}
+					else {
+						if (previousSibling.getNodeValue().length() == 0) {
+							// replace
+							replaceNodeValue(previousSibling, lineDelimiter + lineIndent);
+						}
+						else {
+							// append indentation
+							if (!previousSibling.getNodeValue().endsWith(lineDelimiter + lineIndent)) {
+								if (previousSibling.getNodeValue().endsWith(lineDelimiter)) {
+									insertAfterNode(previousSibling, lineIndent);
+								}
+								else
+									getFormatter(previousSibling).format(previousSibling, formatContraints);
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+
+	private String getLineDelimiter(IDOMNode node, IStructuredDocument doc) {
+		int line = doc.getLineOfOffset(node.getStartOffset());
+		String lineDelimiter = doc.getLineDelimiter();
+		try {
+			if (line > 0) {
+				lineDelimiter = doc.getLineDelimiter(line - 1);
+			}
+		}
+		catch (BadLocationException e) {
+			// log for now, unless we find reason not to
+			Logger.log(Logger.INFO, e.getMessage());
+		}
+		// BUG115716: if cannot get line delimiter from current line, just
+		// use default line delimiter
+		if (lineDelimiter == null)
+			lineDelimiter = doc.getLineDelimiter();
+		return lineDelimiter;
+	}
+
+	protected void formatNode(IDOMNode node, IStructuredFormatContraints formatContraints) {
+		if (node != null && (fProgressMonitor == null || !fProgressMonitor.isCanceled())) {
+			// format indentation before node
+			formatIndentationBeforeNode(node, formatContraints);
+
+			// format indentation after node
+			formatIndentationAfterNode(node, formatContraints);
+		}
+	}
+
+	/**
+	 * This method will compute the correct indentation after this node
+	 * depending on the indentations of its sibling nodes and parent node. Not
+	 * needed anymore?
+	 */
+	protected void formatTrailingText(IDOMNode node, IStructuredFormatContraints formatContraints) {
+		// [111674] If inside xml:space="preserve" element, we bail
+		if (formatContraints.getInPreserveSpaceElement())
+			return;
+
+		String lineDelimiter = node.getModel().getStructuredDocument().getLineDelimiter();
+		String lineIndent = formatContraints.getCurrentIndent();
+		String parentLineIndent = getNodeIndent(node.getParentNode());
+		boolean clearAllBlankLines = formatContraints.getClearAllBlankLines();
+
+		if ((node != null) && (node.getNodeType() != Node.DOCUMENT_NODE)) {
+			IDOMNode nextSibling = (IDOMNode) node.getNextSibling();
+			if ((nextSibling != null) && (nextSibling.getNodeType() == Node.TEXT_NODE)) {
+				String nextSiblingText = nextSibling.getNodeValue();
+				if (nextSibling.getNextSibling() == null)
+					if ((nextSibling.getParentNode().getNodeType() == Node.DOCUMENT_NODE) && (nextSiblingText.trim().length() == 0))
+						// delete spaces at the end of the document
+						replaceNodeValue(nextSibling, EMPTY_STRING);
+					else
+						// replace the text node with parent indentation
+						replaceNodeValue(nextSibling, lineDelimiter + parentLineIndent);
+				else
+					// replace the text node with indentation
+					replaceNodeValue(nextSibling, lineDelimiter + lineIndent);
+			}
+			else {
+				if (nextSibling == null) {
+					lineIndent = parentLineIndent;
+
+					if (node.getParentNode().getNodeType() != Node.DOCUMENT_NODE)
+						if ((node.getNodeType() == Node.TEXT_NODE) && (node.getNodeValue().endsWith(lineDelimiter + lineIndent))) {
+							// this text node already ends with the requested
+							// indentation
+						}
+
+						else if ((node.getNodeType() == Node.TEXT_NODE) && (node.getNodeValue().endsWith(lineDelimiter)))
+							if (clearAllBlankLines)
+								replaceNodeValue(node, lineDelimiter + lineIndent);
+							else
+								// append indentation
+								insertAfterNode(node, lineIndent);
+						else if (node.getNodeType() == Node.TEXT_NODE)
+							if (node.getNodeValue().length() == 0)
+								// replace
+								replaceNodeValue(node, lineDelimiter + lineIndent);
+							else
+							// append indentation
+							if (!node.getNodeValue().endsWith(lineDelimiter + lineIndent))
+								if (node.getNodeValue().endsWith(lineDelimiter))
+									insertAfterNode(node, lineIndent);
+								else
+									insertAfterNode(node, lineDelimiter + lineIndent);
+							else
+								replaceNodeValue(node, lineDelimiter + lineIndent);
+				}
+				else {
+					if ((node.getNodeType() == Node.TEXT_NODE) && (node.getNodeValue().endsWith(lineDelimiter + lineIndent))) {
+						// this text node already ends with the requested
+						// indentation
+					}
+
+					else if ((node.getNodeType() == Node.TEXT_NODE) && (node.getNodeValue().endsWith(lineDelimiter)))
+						if (clearAllBlankLines)
+							replaceNodeValue(node, lineDelimiter + lineIndent);
+						else
+							// append indentation
+							insertAfterNode(node, lineIndent);
+					else if (node.getNodeType() == Node.TEXT_NODE)
+						if (node.getNodeValue().length() == 0)
+							// replace
+							replaceNodeValue(node, lineDelimiter + lineIndent);
+						else
+							// append indentation
+							insertAfterNode(node, lineDelimiter + lineIndent);
+					else
+						// append indentation
+						insertAfterNode(node, lineDelimiter + lineIndent);
+				}
+			}
+		}
+	}
+
+	protected IDOMNode getDeepestChildNode(IDOMNode node) {
+		IDOMNode result = null;
+		IDOMNode lastChild = (IDOMNode) node.getLastChild();
+
+		if (lastChild == null)
+			result = node;
+		else {
+			result = getDeepestChildNode(lastChild);
+
+			if ((result.getNodeType() == Node.TEXT_NODE || result.getNodeType() == Node.COMMENT_NODE) && !isEndTagMissing(node))
+				result = node;
+		}
+
+		return result;
+	}
+
+	public IStructuredFormatContraints getFormatContraints() {
+		if (fFormatContraints == null) {
+			fFormatContraints = new StructuredFormatContraints();
+
+			fFormatContraints.setClearAllBlankLines(getFormatPreferences().getClearAllBlankLines());
+		}
+
+		return fFormatContraints;
+	}
+
+	public IStructuredFormatPreferences getFormatPreferences() {
+		if (fFormatPreferences == null) {
+			fFormatPreferences = new StructuredFormatPreferencesXML();
+
+			Preferences preferences = getModelPreferences();
+			if (preferences != null) {
+				fFormatPreferences.setLineWidth(preferences.getInt(XMLCorePreferenceNames.LINE_WIDTH));
+				((StructuredFormatPreferencesXML) fFormatPreferences).setSplitMultiAttrs(preferences.getBoolean(XMLCorePreferenceNames.SPLIT_MULTI_ATTRS));
+				((StructuredFormatPreferencesXML) fFormatPreferences).setAlignEndBracket(preferences.getBoolean(XMLCorePreferenceNames.ALIGN_END_BRACKET));
+				((StructuredFormatPreferencesXML) fFormatPreferences).setPreservePCDATAContent(preferences.getBoolean(XMLCorePreferenceNames.PRESERVE_CDATACONTENT));
+				fFormatPreferences.setClearAllBlankLines(preferences.getBoolean(XMLCorePreferenceNames.CLEAR_ALL_BLANK_LINES));
+
+				char indentChar = ' ';
+				String indentCharPref = preferences.getString(XMLCorePreferenceNames.INDENTATION_CHAR);
+				if (XMLCorePreferenceNames.TAB.equals(indentCharPref)) {
+					indentChar = '\t';
+				}
+				int indentationWidth = preferences.getInt(XMLCorePreferenceNames.INDENTATION_SIZE);
+
+				StringBuffer indent = new StringBuffer();
+				for (int i = 0; i < indentationWidth; i++) {
+					indent.append(indentChar);
+				}
+				fFormatPreferences.setIndent(indent.toString());
+			}
+		}
+
+		return fFormatPreferences;
+	}
+
+	protected IStructuredFormatter getFormatter(IDOMNode node) {
+		// 262135 - NPE during format of empty document
+		if (node == null)
+			return null;
+
+		short nodeType = ((Node) node).getNodeType();
+		IStructuredFormatter formatter = null;
+		switch (nodeType) {
+			case Node.ELEMENT_NODE : {
+				formatter = new ElementNodeFormatter();
+				break;
+			}
+			case Node.TEXT_NODE : {
+				formatter = new TextNodeFormatter();
+				break;
+			}
+			case Node.CDATA_SECTION_NODE : {
+				formatter = new NoMoveFormatter();
+				break;
+			}
+			case Node.COMMENT_NODE : {
+				formatter = new CommentNodeFormatter();
+				break;
+			}
+			case Node.PROCESSING_INSTRUCTION_NODE : {
+				formatter = new NodeFormatter();
+				break;
+			}
+			case Node.DOCUMENT_NODE : {
+				formatter = new DocumentNodeFormatter();
+				break;
+			}
+			case Node.ENTITY_REFERENCE_NODE : {
+				formatter = new NoMoveFormatter();
+				break;
+			}
+			default : {
+				formatter = new NodeFormatter();
+			}
+		}
+
+		// init fomatter
+		formatter.setFormatPreferences(getFormatPreferences());
+		formatter.setProgressMonitor(fProgressMonitor);
+
+		return formatter;
+	}
+
+	protected int getIndentationLength(String indent) {
+		// TODO Kit : The calculation of IndentationLength is not correct
+		// here.
+		// nodeIndentation may contain tabs. Multiply by 4 temporarily to get
+		// approx. width.
+		// Need to re-work.
+
+		int indentationLength = 0;
+
+		for (int i = 0; i < indent.length(); i++) {
+			if (indent.substring(i, i + 1).compareTo(TAB) == 0)
+				indentationLength += 4;
+			else
+				indentationLength++;
+		}
+
+		return indentationLength;
+	}
+
+	protected Preferences getModelPreferences() {
+		return XMLCorePlugin.getDefault().getPluginPreferences();
+	}
+
+	/**
+	 * This method will find the indentation for this node. It will search
+	 * backwards starting from the beginning of the node until a character
+	 * other than a space or a tab is found. If this node is null or it's a
+	 * document node or it's a first level node (node's parent is a document
+	 * node) the default empty string will be returned as the indentation.
+	 */
+	protected String getNodeIndent(Node node) {
+		String result = EMPTY_STRING;
+
+		if ((node != null) && (node.getNodeType() != Node.DOCUMENT_NODE) && (node.getParentNode() != null) && (node.getParentNode().getNodeType() != Node.DOCUMENT_NODE)) {
+			IDOMNode siblingTextNode = (IDOMNode) node.getPreviousSibling();
+			if ((siblingTextNode != null) && (siblingTextNode.getNodeType() == Node.TEXT_NODE)) {
+				// find the indentation
+				String siblingText = siblingTextNode.getNodeValue();
+				int siblingTextLength = siblingText.length();
+				if ((siblingText != null) && (siblingTextLength > 0) && ((siblingText.charAt(siblingTextLength - 1) == SPACE_CHAR) || (siblingText.charAt(siblingTextLength - 1) == TAB_CHAR))) {
+					int searchIndex = siblingTextLength - 1;
+					while ((searchIndex >= 0) && ((siblingText.charAt(searchIndex) == SPACE_CHAR) || (siblingText.charAt(searchIndex) == TAB_CHAR)))
+						searchIndex--;
+
+					if (searchIndex < siblingTextLength)
+						result = siblingText.substring(searchIndex + 1, siblingTextLength);
+				}
+			}
+		}
+
+		return result;
+	}
+
+	protected String getNodeName(IDOMNode node) {
+		return node.getNodeName();
+	}
+
+	protected String getNodeText(IDOMNode node) {
+		String text = null;
+
+		if ((node instanceof CharacterDataImpl) && !(node instanceof CommentImpl) && !(node instanceof CDATASectionImpl) && !isJSPTag(node))
+			text = ((CharacterDataImpl) node).getSource();
+		else
+			text = node.getFirstStructuredDocumentRegion().getText();
+
+		return text;
+	}
+
+	protected IDOMNode getParentIndentNode(IDOMNode node) {
+		IDOMNode result = null;
+		IDOMNode parentNode = (IDOMNode) node.getParentNode();
+
+		if (parentNode.getNodeType() == Node.DOCUMENT_NODE)
+			result = parentNode;
+		else {
+			ITextRegion region = parentNode.getLastStructuredDocumentRegion().getFirstRegion();
+			if (region.getType() == DOMRegionContext.XML_END_TAG_OPEN)
+				result = parentNode;
+			else
+				result = getParentIndentNode(parentNode);
+		}
+
+		return result;
+	}
+
+	/**
+	 * This method will find the indentation for a node sibling to this node.
+	 * It will try to find a sibling node before this node first. If there is
+	 * no sibling node before this node, it will try to find a sibling node
+	 * after this node. If still not found, we will check if this node is
+	 * already indented from its parent. If yes, this node's indentation will
+	 * be used. Otherwise, the parent node's indentation plus one indentation
+	 * will be used. If this node is null or it's a document node or it's a
+	 * first level node (node's parent is a document node) the default empty
+	 * string will be returned as the indentation.
+	 */
+	protected String getSiblingIndent(Node node) {
+		String result = EMPTY_STRING;
+
+		if ((node != null) && (node.getNodeType() != Node.DOCUMENT_NODE) && (node.getParentNode() != null) && (node.getParentNode().getNodeType() != Node.DOCUMENT_NODE)) {
+			// find the text node before the previous non-text sibling
+			// if that's not found, we will try the text node before the next
+			// non-text sibling
+			IDOMNode sibling = (IDOMNode) node.getPreviousSibling();
+			while ((sibling != null) && (sibling.getNodeType() == Node.TEXT_NODE || sibling.getNodeType() == Node.COMMENT_NODE)) {
+				if (sibling.getNodeType() == Node.COMMENT_NODE && sibling.getPreviousSibling() != null && sibling.getPreviousSibling().getNodeType() == Node.TEXT_NODE && StringUtils.containsLineDelimiter(sibling.getPreviousSibling().getNodeValue()))
+					break;
+				sibling = (IDOMNode) sibling.getPreviousSibling();
+			}
+			if (sibling == null) {
+				sibling = (IDOMNode) node.getNextSibling();
+				while ((sibling != null) && (sibling.getNodeType() == Node.TEXT_NODE))
+					sibling = (IDOMNode) sibling.getNextSibling();
+			}
+			String singleIndent = getFormatPreferences().getIndent();
+			String parentLineIndent = getNodeIndent(node.getParentNode());
+
+			if (sibling != null) {
+				String siblingIndent = getNodeIndent(sibling);
+				if (siblingIndent.length() > 0)
+					result = siblingIndent;
+				else {
+					String nodeIndent = getNodeIndent(node);
+					if (nodeIndent.length() > parentLineIndent.length())
+						// this node is indented from its parent, its
+						// indentation will be used
+						result = nodeIndent;
+					else
+						result = parentLineIndent + singleIndent;
+				}
+			}
+			else {
+				String nodeIndent = getNodeIndent(node);
+				if (nodeIndent.length() > parentLineIndent.length())
+					// this node is indented from its parent, its indentation
+					// will be used
+					result = nodeIndent;
+				else
+					result = parentLineIndent + singleIndent;
+			}
+		}
+
+		return result;
+	}
+
+	protected void insertAfterNode(IDOMNode node, String string) {
+		IDOMModel structuredModel = node.getModel();
+		IStructuredDocument structuredDocument = structuredModel.getStructuredDocument();
+
+		int offset = node.getEndOffset();
+		int length = 0;
+
+		// 261968 - formatting tag without closing bracket: <t1><t1
+		if (node.getEndStructuredDocumentRegion() != null) {
+			offset = node.getEndStructuredDocumentRegion().getTextEndOffset();
+			length = node.getEndOffset() - offset;
+		}
+		replace(structuredDocument, offset, length, string);
+	}
+
+	protected void insertBeforeNode(IDOMNode node, String string) {
+		IDOMModel structuredModel = node.getModel();
+		IStructuredDocument structuredDocument = structuredModel.getStructuredDocument();
+
+		replace(structuredDocument, node.getStartOffset(), 0, string);
+	}
+
+	/**
+	 * Allowing the INodeAdapter to compare itself against the type allows it
+	 * to return true in more than one case.
+	 */
+	public boolean isAdapterForType(Object type) {
+		return type.equals(IStructuredFormatter.class);
+	}
+
+	protected boolean isEndTagMissing(IDOMNode node) {
+		boolean result = false;
+
+		if ((node != null) && (node.getNodeType() != Node.DOCUMENT_NODE) && !isJSPTag(node)) {
+			IStructuredDocumentRegion startTagStructuredDocumentRegion = node.getFirstStructuredDocumentRegion();
+			IStructuredDocumentRegion endTagStructuredDocumentRegion = node.getLastStructuredDocumentRegion();
+
+			ITextRegion startTagNameRegion = null;
+			if (startTagStructuredDocumentRegion.getRegions().size() > 1)
+				startTagNameRegion = startTagStructuredDocumentRegion.getRegions().get(1);
+			ITextRegion endTagNameRegion = null;
+			if (endTagStructuredDocumentRegion.getRegions().size() > 1)
+				endTagNameRegion = endTagStructuredDocumentRegion.getRegions().get(1);
+
+			ITextRegionList startTagRegions = startTagStructuredDocumentRegion.getRegions();
+			if (startTagNameRegion == endTagNameRegion && startTagNameRegion != null && (startTagRegions.get(0)).getType() != DOMRegionContext.XML_END_TAG_OPEN && (startTagRegions.get(startTagRegions.size() - 1).getType()) != DOMRegionContext.XML_EMPTY_TAG_CLOSE)
+				// end tag missing
+				result = true;
+		}
+
+		return result;
+	}
+
+	protected boolean nodeHasSiblings(IDOMNode node) {
+		return (node.getPreviousSibling() != null) || (node.getNextSibling() != null);
+	}
+
+	/**
+	 * Node changed. No format should be performed automatically.
+	 */
+	public void notifyChanged(org.eclipse.wst.sse.core.internal.provisional.INodeNotifier notifier, int eventType, Object changedFeature, Object oldValue, Object newValue, int pos) {
+	}
+
+	protected void removeRegionSpaces(IDOMNode node, IStructuredDocumentRegion flatNode, ITextRegion region) {
+		if ((region != null) && (region instanceof ContextRegion || region instanceof TagNameRegion) && (flatNode.getEndOffset(region) > flatNode.getTextEndOffset(region))) {
+			IDOMModel structuredModel = node.getModel();
+			IStructuredDocument structuredDocument = structuredModel.getStructuredDocument();
+
+			replace(structuredDocument, flatNode.getTextEndOffset(region), flatNode.getEndOffset(region) - flatNode.getTextEndOffset(region), EMPTY_STRING);
+		}
+	}
+
+	/**
+	 * This method will replace the string at offset and length with a new
+	 * string. If the string to be replaced is the same as the new string, the
+	 * string will not be replaced.
+	 */
+	protected void replace(IStructuredDocument structuredDocument, int offset, int length, String string) {
+		try {
+			String structuredDocumentString = structuredDocument.get(offset, length);
+			if (structuredDocumentString.compareTo(string) != 0)
+				structuredDocument.replaceText(structuredDocument, offset, length, string);
+		}
+		catch (BadLocationException e) {
+			// log for now, unless we find reason not to
+			Logger.log(Logger.INFO, e.getMessage());
+		}
+	}
+
+	/**
+	 * This method will replace the node value with a new string. If the node
+	 * value to be replaced is the same as the new string, the node value will
+	 * not be replaced.
+	 */
+	protected void replaceNodeValue(IDOMNode node, String string) {
+		IDOMModel structuredModel = node.getModel();
+		IStructuredDocument structuredDocument = structuredModel.getStructuredDocument();
+		int offset = node.getStartOffset();
+		int length = node.getEndOffset() - node.getStartOffset();
+
+		try {
+			String structuredDocumentString = structuredDocument.get(offset, length);
+			if (structuredDocumentString.compareTo(string) != 0)
+				replace(structuredDocument, offset, length, string);
+		}
+		catch (BadLocationException e) {
+			// log for now, unless we find reason not to
+			Logger.log(Logger.INFO, e.getMessage());
+		}
+	}
+
+	public void setFormatPreferences(IStructuredFormatPreferences formatPreferences) {
+		fFormatPreferences = formatPreferences;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.wst.sse.core.format.IStructuredFormatter#setProgressMonitor(org.eclipse.core.runtime.IProgressMonitor)
+	 */
+	public void setProgressMonitor(IProgressMonitor monitor) {
+		fProgressMonitor = monitor;
+	}
+
+	/**
+	 * ISSUE: this is a bit of hidden JSP knowledge that was implemented this
+	 * way for expedency. Should be evolved in future to depend on
+	 * "nestedContext".
+	 */
+	private boolean isJSPTag(Node node) {
+
+		final String JSP_CLOSE = "JSP_CLOSE"; //$NON-NLS-1$
+		// final String JSP_COMMENT_CLOSE = "JSP_COMMENT_CLOSE"; //$NON-NLS-1$
+
+		// final String JSP_COMMENT_OPEN = "JSP_COMMENT_OPEN"; //$NON-NLS-1$
+		// final String JSP_COMMENT_TEXT = "JSP_COMMENT_TEXT"; //$NON-NLS-1$
+
+		final String JSP_CONTENT = "JSP_CONTENT"; //$NON-NLS-1$
+		final String JSP_DECLARATION_OPEN = "JSP_DECLARATION_OPEN"; //$NON-NLS-1$
+		final String JSP_DIRECTIVE_CLOSE = "JSP_DIRECTIVE_CLOSE"; //$NON-NLS-1$
+		final String JSP_DIRECTIVE_NAME = "JSP_DIRECTIVE_NAME"; //$NON-NLS-1$
+
+		final String JSP_DIRECTIVE_OPEN = "JSP_DIRECTIVE_OPEN"; //$NON-NLS-1$
+		final String JSP_EXPRESSION_OPEN = "JSP_EXPRESSION_OPEN"; //$NON-NLS-1$
+
+		// final String JSP_ROOT_TAG_NAME = "JSP_ROOT_TAG_NAME"; //$NON-NLS-1$
+
+		final String JSP_SCRIPTLET_OPEN = "JSP_SCRIPTLET_OPEN"; //$NON-NLS-1$
+
+		boolean result = false;
+
+		if (node instanceof IDOMNode) {
+			IStructuredDocumentRegion flatNode = ((IDOMNode) node).getFirstStructuredDocumentRegion();
+			// in some cases, the nodes exists, but hasn't been associated
+			// with
+			// a flatnode yet (the screen updates can be initiated on a
+			// different thread,
+			// so the request for a flatnode can come in before the node is
+			// fully formed.
+			// if the flatnode is null, we'll just allow the defaults to
+			// apply.
+			if (flatNode != null) {
+				String flatNodeType = flatNode.getType();
+				// should not be null, but just to be sure
+				if (flatNodeType != null) {
+					if ((flatNodeType.equals(JSP_CONTENT)) || (flatNodeType.equals(JSP_EXPRESSION_OPEN)) || (flatNodeType.equals(JSP_SCRIPTLET_OPEN)) || (flatNodeType.equals(JSP_DECLARATION_OPEN)) || (flatNodeType.equals(JSP_DIRECTIVE_CLOSE)) || (flatNodeType.equals(JSP_DIRECTIVE_NAME)) || (flatNodeType.equals(JSP_DIRECTIVE_OPEN)) || (flatNodeType.equals(JSP_CLOSE))) {
+						result = true;
+					}
+				}
+			}
+		}
+
+		return result;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/format/StructuredFormatPreferencesXML.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/format/StructuredFormatPreferencesXML.java
new file mode 100644
index 0000000..07024eb
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/format/StructuredFormatPreferencesXML.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.provisional.format;
+
+import org.eclipse.wst.sse.core.internal.format.StructuredFormatPreferences;
+
+public class StructuredFormatPreferencesXML extends StructuredFormatPreferences {
+	private boolean fSplitMultiAttrs = false;
+	private boolean fPreservePCDATAContent = false;
+	private boolean fAlignEndBracket = false;
+
+	/**
+	 * True if formatter should split elements with multiple attributes onto
+	 * new lines.
+	 * 
+	 * @return boolean
+	 */
+	public boolean getSplitMultiAttrs() {
+		return fSplitMultiAttrs;
+	}
+
+	/**
+	 * Sets whether or not formatter should split elements with multiple
+	 * attributes onto new lines.
+	 * 
+	 * @param splitMultiAttrs
+	 */
+	public void setSplitMultiAttrs(boolean splitMultiAttrs) {
+		fSplitMultiAttrs = splitMultiAttrs;
+	}
+
+	/**
+	 * True if tags with PCDATA content should not have their whitespace
+	 * messed with when formatting.
+	 * 
+	 * @return boolean
+	 */
+	public boolean isPreservePCDATAContent() {
+		return fPreservePCDATAContent;
+	}
+
+	/**
+	 * Sets whether or not formatter should preserve whitespace in tags with
+	 * PCDATA content.
+	 * 
+	 * @param preservePCDATAContent
+	 */
+	public void setPreservePCDATAContent(boolean preservePCDATAContent) {
+		fPreservePCDATAContent = preservePCDATAContent;
+	}
+
+	/**
+	 * True if end brackets of start tags should be placed on a new line if
+	 * the start tag spans more than one line.
+	 * 
+	 * @return
+	 */
+	public boolean isAlignEndBracket() {
+		return fAlignEndBracket;
+	}
+
+	/**
+	 * Sets whether or not formatter should align the end bracket of a start
+	 * tag on a new line if the start tag spans more than one line.
+	 * 
+	 * @param alignEndBracket
+	 */
+	public void setAlignEndBracket(boolean alignEndBracket) {
+		fAlignEndBracket = alignEndBracket;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/format/TextNodeFormatter.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/format/TextNodeFormatter.java
new file mode 100644
index 0000000..873ab76
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/format/TextNodeFormatter.java
@@ -0,0 +1,385 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2008 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     Jesper Steen Møller - xml:space='preserve' support
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.provisional.format;
+
+import java.util.List;
+import java.util.Vector;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.wst.sse.core.internal.format.IStructuredFormatContraints;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+import org.eclipse.wst.sse.core.utils.StringUtils;
+import org.eclipse.wst.xml.core.internal.Logger;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.w3c.dom.Node;
+
+
+public class TextNodeFormatter extends NodeFormatter {
+	static private final String CR = "\r"; //$NON-NLS-1$
+	static private final String DELIMITERS = " \t\n\r\f"; //$NON-NLS-1$
+	static private final String EMPTY_STRING = ""; //$NON-NLS-1$
+	static private final String FF = "\f"; //$NON-NLS-1$
+	static private final String LF = "\n"; //$NON-NLS-1$
+	static private final String SPACE = " "; //$NON-NLS-1$
+	static private final String TAB = "\t"; //$NON-NLS-1$
+
+	private String compressSpaces(String string, IStructuredFormatContraints formatContraints) {
+		/*
+		 * Note that the StructuredTextEditor supports mixed new line
+		 * characters (CR, LF, CRLF) in one file. We have to handle that when
+		 * we try to preserve blank lines.
+		 */
+		String[] stringArray = null;
+		boolean clearAllBlankLines = formatContraints.getClearAllBlankLines();
+
+		if (clearAllBlankLines)
+			stringArray = StringUtils.asArray(string);
+		else
+			stringArray = StringUtils.asArray(string, DELIMITERS, true);
+
+		StringBuffer compressedString = new StringBuffer();
+		if (stringArray.length > 0) {
+			boolean cr = false, lf = false, cr2 = false, nonSpace = true;
+
+			if (stringArray[0].compareTo(CR) == 0)
+				cr = true;
+			else if (stringArray[0].compareTo(LF) == 0)
+				lf = true;
+			else if ((stringArray[0].compareTo(SPACE) != 0) && (stringArray[0].compareTo(TAB) != 0) && (stringArray[0].compareTo(FF) != 0)) {
+				compressedString.append(stringArray[0]);
+				nonSpace = true;
+			}
+
+			for (int i = 1; i < stringArray.length; i++) {
+				if (stringArray[i].compareTo(CR) == 0) {
+					if (cr && lf) {
+						if (nonSpace) {
+							compressedString.append(CR + LF);
+							nonSpace = false;
+						}
+						compressedString.append(stringArray[i]);
+						cr2 = true;
+					}
+					else if (cr) {
+						if (nonSpace) {
+							compressedString.append(CR);
+							nonSpace = false;
+						}
+						compressedString.append(stringArray[i]);
+						cr2 = true;
+					}
+					else
+						cr = true;
+				}
+				else if (stringArray[i].compareTo(LF) == 0) {
+					if (cr && lf && cr2) {
+						compressedString.append(stringArray[i]);
+					}
+					else if (lf) {
+						if (nonSpace) {
+							compressedString.append(LF);
+							nonSpace = false;
+						}
+						compressedString.append(stringArray[i]);
+					}
+					else
+						lf = true;
+				}
+				else if ((stringArray[i].compareTo(SPACE) != 0) && (stringArray[i].compareTo(TAB) != 0) && (stringArray[i].compareTo(FF) != 0)) {
+					if (compressedString.length() > 0)
+						compressedString.append(SPACE);
+					compressedString.append(stringArray[i]);
+
+					cr = false;
+					lf = false;
+					cr2 = false;
+					nonSpace = true;
+				}
+			}
+		}
+
+		return compressedString.toString();
+	}
+
+	protected void formatNode(IDOMNode node, IStructuredFormatContraints formatContraints) {
+		// [111674] If inside xml:space="preserve" element, we bail
+		if (formatContraints.getInPreserveSpaceElement())
+			return;
+		if (node != null) {
+			IStructuredDocument doc = node.getStructuredDocument();
+
+			int lineWidth = getFormatPreferences().getLineWidth();
+			int currentAvailableLineWidth = computeAvailableLineWidth(doc, node.getStartOffset(), lineWidth);
+
+			String nodeText = getNodeText(node);
+			String compressedText = compressSpaces(nodeText, formatContraints);
+
+			IDOMNode parentNode = (IDOMNode) node.getParentNode();
+
+			if (((enoughSpace(parentNode, currentAvailableLineWidth, compressedText)) && (noSiblingsAndNoFollowingComment(node)) && !firstStructuredDocumentRegionContainsLineDelimiters(parentNode)) || node.getStartOffset() == 0) {
+				handleNoReflow(node, doc, compressedText, parentNode);
+			}
+			else {
+				// not enough space, need to reflow text
+				String nodeIndentation = formatContraints.getCurrentIndent();
+				currentAvailableLineWidth = lineWidth - getIndentationLength(nodeIndentation);
+				List vector = reflowText(compressedText, currentAvailableLineWidth);
+				int vectorSize = vector.size();
+				StringBuffer reflowedTextBuffer = new StringBuffer();
+				String lineDelimiter = getLineDelimiter(doc, node.getStartOffset());
+				// handle first line specially to check for allowWhitespace
+				if (vectorSize > 0) {
+					// determines whether or not to allow whitespace if there
+					// is an entity or cdata before it
+					boolean allowWhitespace = true;
+					// [206072] StringIndexOutOfBoundsException
+					if (nodeText.length() == 0 || !Character.isWhitespace(nodeText.charAt(0))) {
+						Node previousSibling = node.getPreviousSibling();
+						if (previousSibling != null && (previousSibling.getNodeType() == Node.ENTITY_REFERENCE_NODE || previousSibling.getNodeType() == Node.CDATA_SECTION_NODE))
+							allowWhitespace = false;
+					}
+					String theString = (String) vector.get(0);
+					if (allowWhitespace) {
+						reflowedTextBuffer.append(lineDelimiter);
+						if (theString.trim().length() > 0)
+							reflowedTextBuffer.append(nodeIndentation).append(theString);
+					}
+					else {
+						reflowedTextBuffer.append(theString);
+					}
+				}
+				// do the rest of the lines
+				for (int i = 1; i < vectorSize; i++) {
+					String theString = (String) vector.get(i);
+					if (theString.trim().length() > 0)
+						reflowedTextBuffer.append(lineDelimiter).append(nodeIndentation).append(theString);
+					else
+						reflowedTextBuffer.append(lineDelimiter);
+				}
+				String reflowedText = reflowedTextBuffer.toString();
+				if (node.getNextSibling() == null) {
+					if (isEndTagMissing(parentNode)) {
+						// don't add indentation to end if parent end tag is
+						// missing
+					}
+
+					else {
+						// add parent's indentation to end
+						nodeIndentation = getNodeIndent(parentNode);
+						if (!reflowedText.endsWith(lineDelimiter + nodeIndentation)) {
+							reflowedText = StringUtils.appendIfNotEndWith(reflowedText, lineDelimiter);
+							reflowedText = StringUtils.appendIfNotEndWith(reflowedText, nodeIndentation);
+						}
+					}
+				}
+				else {
+					if (!reflowedText.endsWith(lineDelimiter + nodeIndentation)) {
+						// not already ended with the expected indentation
+						Node nextSibling = node.getNextSibling();
+						if (nextSibling.getNodeType() == Node.COMMENT_NODE) {
+							// add indentation to end if
+							// currentTextEndsWithLineDelimiter
+							// or followed by multiLineComment
+
+							int indexOfLastLineDelimiter = StringUtils.indexOfLastLineDelimiter(nodeText);
+							boolean currentTextEndsWithLineDelimiter = indexOfLastLineDelimiter != -1;
+							if (currentTextEndsWithLineDelimiter) {
+								// no more non blank character after the last
+								// line delimiter
+								currentTextEndsWithLineDelimiter = StringUtils.indexOfNonblank(nodeText, indexOfLastLineDelimiter) == -1;
+							}
+
+							String nodeValue = nextSibling.getNodeValue();
+							boolean multiLineComment = StringUtils.containsLineDelimiter(nodeValue);
+
+							if (currentTextEndsWithLineDelimiter || multiLineComment) {
+								reflowedText = StringUtils.appendIfNotEndWith(reflowedText, lineDelimiter);
+								reflowedText = StringUtils.appendIfNotEndWith(reflowedText, nodeIndentation);
+							}
+						}
+						else if (nextSibling.getNodeType() == Node.ENTITY_REFERENCE_NODE || nextSibling.getNodeType() == Node.CDATA_SECTION_NODE) {
+							int textLength = nodeText.length();
+							if (textLength > 0 && Character.isWhitespace(nodeText.charAt(textLength - 1))) {
+								reflowedText = StringUtils.appendIfNotEndWith(reflowedText, lineDelimiter);
+								reflowedText = StringUtils.appendIfNotEndWith(reflowedText, nodeIndentation);
+							}
+						}
+						else {
+							// not a comment, just add add indentation to end
+							reflowedText = StringUtils.appendIfNotEndWith(reflowedText, lineDelimiter);
+							reflowedText = StringUtils.appendIfNotEndWith(reflowedText, nodeIndentation);
+						}
+					}
+				}
+
+				replaceNodeValue(node, reflowedText);
+			}
+		}
+	}
+
+	/**
+	 * Keeps text inline with its parent (no reflow necessary)
+	 * 
+	 * @param node
+	 * @param doc
+	 * @param compressedText
+	 * @param parentNode
+	 */
+	private void handleNoReflow(IDOMNode node, IStructuredDocument doc, String compressedText, IDOMNode parentNode) {
+		String nodeIndentation;
+		// enough space and text has no line delimiters and (node has no
+		// siblings or followed by inline comment) and
+		// parentFirstStructuredDocumentRegionContainsLineDelimiters
+
+		if (isEndTagMissing(parentNode)) {
+			parentNode = (IDOMNode) parentNode.getParentNode();
+			while (isEndTagMissing(parentNode))
+				parentNode = (IDOMNode) parentNode.getParentNode();
+
+			// add parent's indentation to end
+			nodeIndentation = getNodeIndent(parentNode);
+			String lineDelimiter = getLineDelimiter(doc, node.getStartOffset());
+			if (!compressedText.endsWith(lineDelimiter + nodeIndentation)) {
+				compressedText = StringUtils.appendIfNotEndWith(compressedText, lineDelimiter);
+				compressedText = StringUtils.appendIfNotEndWith(compressedText, nodeIndentation);
+			}
+		}
+
+		if ((parentNode != null) && (parentNode.getNodeType() == Node.DOCUMENT_NODE) && (node.getNodeValue().length() > 0) && (node.getNodeValue().trim().length() == 0) && ((node.getPreviousSibling() == null) || (node.getNextSibling() == null)))
+			// delete spaces at the beginning or end of the document
+			compressedText = EMPTY_STRING;
+
+		replaceNodeValue(node, compressedText);
+	}
+
+	private boolean noSiblingsAndNoFollowingComment(IDOMNode node) {
+		IDOMNode nextSibling = (IDOMNode) node.getNextSibling();
+		return !nodeHasSiblings(node) || (noLineDelimiter(node) && isComment(nextSibling) && noLineDelimiter(nextSibling));
+	}
+
+	private boolean isComment(IDOMNode node) {
+		boolean result = false;
+		if (node != null) {
+			result = node.getNodeType() == Node.COMMENT_NODE;
+		}
+		return result;
+	}
+
+	private boolean noLineDelimiter(IDOMNode node) {
+		boolean result = false;
+		if (node != null) {
+			result = !StringUtils.containsLineDelimiter(node.getNodeValue());
+		}
+		return result;
+	}
+
+	/**
+	 * Calculates if there is enough space on the current line for
+	 * compressedText (and for its parent end tag)
+	 * 
+	 * @param parentNode
+	 * @param currentAvailableLineWidth
+	 * @param compressedText
+	 * @return
+	 */
+	private boolean enoughSpace(IDOMNode parentNode, int currentAvailableLineWidth, String compressedText) {
+		int parentEndTagLength = parentNode.getNodeName().length() + 3;
+		return compressedText.length() <= (currentAvailableLineWidth - parentEndTagLength) && !StringUtils.containsLineDelimiter(compressedText);
+	}
+
+	protected Vector reflowText(String text, int availableWidth) {
+		String[] stringArray = null;
+		boolean clearAllBlankLines = getFormatPreferences().getClearAllBlankLines();
+
+		if (clearAllBlankLines)
+			stringArray = StringUtils.asArray(text);
+		else
+			stringArray = StringUtils.asArray(text, DELIMITERS, true);
+
+		Vector output = new Vector();
+		if ((stringArray != null) && (stringArray.length > 0)) {
+			StringBuffer buffer = new StringBuffer();
+			if (stringArray[0].compareTo(CR) != 0)
+				buffer.append(stringArray[0]);
+			int bufferLength = stringArray[0].toString().length();
+			boolean cr = stringArray[0].compareTo(CR) == 0;
+
+			for (int i = 1; i < stringArray.length; i++) {
+				String eachString = stringArray[i];
+				if ((eachString.compareTo(SPACE) != 0) && (eachString.compareTo(TAB) != 0) && (eachString.compareTo(FF) != 0)) {
+					if ((bufferLength + 1 + eachString.length() > availableWidth) || (eachString.compareTo(CR) == 0) || (eachString.compareTo(LF) == 0)) {
+						if ((eachString.compareTo(LF) == 0) && cr) {
+							// do nothing
+						}
+						else {
+							output.add(buffer.toString());
+							buffer = new StringBuffer();
+							bufferLength = 0;
+						}
+						cr = eachString.compareTo(CR) == 0;
+					}
+					else if (buffer.toString().trim().length() > 0) {
+						buffer.append(SPACE);
+						bufferLength++;
+					}
+					if ((eachString.compareTo(CR) != 0) && (eachString.compareTo(LF) != 0)) {
+						buffer.append(eachString);
+						bufferLength = bufferLength + eachString.length();
+					}
+				}
+			}
+			output.add(buffer.toString());
+		}
+		else
+			output.add(text);
+
+		return output;
+	}
+
+	private String getLineDelimiter(IStructuredDocument doc, int nodeOffset) {
+		int line = doc.getLineOfOffset(nodeOffset);
+		String lineDelimiter = doc.getLineDelimiter();
+		try {
+			if (line > 0) {
+				lineDelimiter = doc.getLineDelimiter(line - 1);
+			}
+		}
+		catch (BadLocationException e) {
+			// log for now, unless we find reason not to
+			Logger.log(Logger.INFO, e.getMessage());
+		}
+		// BUG115716: if cannot get line delimiter from current line, just
+		// use default line delimiter
+		if (lineDelimiter == null)
+			lineDelimiter = doc.getLineDelimiter();
+		return lineDelimiter;
+	}
+
+	private int computeAvailableLineWidth(IStructuredDocument doc, int nodeOffset, int lineWidth) {
+		// compute current available line width
+		int currentAvailableLineWidth = 0;
+		try {
+			int lineOffset = doc.getLineInformationOfOffset(nodeOffset).getOffset();
+			String text = doc.get(lineOffset, nodeOffset - lineOffset);
+			int usedWidth = getIndentationLength(text);
+			currentAvailableLineWidth = lineWidth - usedWidth;
+		}
+		catch (BadLocationException e) {
+			// log for now, unless we find reason not to
+			Logger.log(Logger.INFO, e.getMessage());
+		}
+		return currentAvailableLineWidth;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/text/IXMLPartitions.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/text/IXMLPartitions.java
new file mode 100644
index 0000000..5d36751
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/provisional/text/IXMLPartitions.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.provisional.text;
+
+
+
+/**
+ * This interface is not intended to be implemented.
+ * It defines the partition types for XML.
+ * Clients should reference the partition type Strings defined here directly.
+ * 
+ * @deprecated use org.eclipse.wst.xml.core.text
+ */
+public interface IXMLPartitions {
+	
+	String XML_DEFAULT = "org.eclipse.wst.xml.XML_DEFAULT"; //$NON-NLS-1$
+	String XML_CDATA = "org.eclipse.wst.xml.XML_CDATA"; //$NON-NLS-1$
+	String XML_PI = "org.eclipse.wst.xml.XML_PI"; //$NON-NLS-1$
+	String XML_DECLARATION = "org.eclipse.wst.xml.XML_DECL"; //$NON-NLS-1$
+	String XML_COMMENT = "org.eclipse.wst.xml.XML_COMMENT"; //$NON-NLS-1$
+	
+	/*
+	 * This value is used as a prefix to any unknown processing instructions
+	 * we find. The processor target name is converted to uppercase and
+	 * appended to the prefix to create a unique partition type.
+	 */
+	String PROCESSING_INSTRUCTION_PREFIX = "org.eclipse.wst.xml.PROCESSING_INSTRUCTION:"; //$NON-NLS-1$
+
+	/**
+	 * Should match
+	 * org.eclipse.wst.sse.core.dtd.partitioning.StructuredTextPartitionerForDTD.ST_DTD_SUBSET
+	 */
+	String DTD_SUBSET = "org.eclipse.wst.xml.dtd.internal_subset"; //$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/regions/DOMRegionContext.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/regions/DOMRegionContext.java
new file mode 100644
index 0000000..4a73d8d
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/regions/DOMRegionContext.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.regions;
+
+public interface DOMRegionContext {
+
+	public static final String BLOCK_TEXT = "BLOCK_TEXT"; //$NON-NLS-1$
+
+	public static final String UNDEFINED = "UNDEFINED"; //$NON-NLS-1$
+
+	public static final String WHITE_SPACE = "WHITE_SPACE"; //$NON-NLS-1$
+	public static final String XML_ATTLIST_DECL_CLOSE = "XML_ATTLIST_DECL_CLOSE"; //$NON-NLS-1$
+	public static final String XML_ATTLIST_DECL_CONTENT = "XML_ATTLIST_DECL_CONTENT"; //$NON-NLS-1$
+	public static final String XML_ATTLIST_DECL_NAME = "XML_ATTLIST_DECL_NAME"; //$NON-NLS-1$
+
+	public static final String XML_ATTLIST_DECLARATION = "XML_ATTLIST_DECLARATION"; //$NON-NLS-1$
+	public static final String XML_CDATA_CLOSE = "XML_CDATA_CLOSE"; //$NON-NLS-1$
+	public static final String XML_CDATA_OPEN = "XML_CDATA_OPEN"; //$NON-NLS-1$
+	public static final String XML_CDATA_TEXT = "XML_CDATA_TEXT"; //$NON-NLS-1$
+	public static final String XML_CHAR_REFERENCE = "XML_CHAR_REFERENCE"; //$NON-NLS-1$
+	public static final String XML_COMMENT_CLOSE = "XML_COMMENT_CLOSE"; //$NON-NLS-1$
+
+	public static final String XML_COMMENT_OPEN = "XML_COMMENT_OPEN"; //$NON-NLS-1$
+	public static final String XML_COMMENT_TEXT = "XML_COMMENT_TEXT"; //$NON-NLS-1$
+
+	public static final String XML_CONTENT = "XML_CONTENT"; //$NON-NLS-1$
+	public static final String XML_DECLARATION_CLOSE = "XML_DECLARATION_CLOSE"; //$NON-NLS-1$
+
+	public static final String XML_DECLARATION_OPEN = "XML_DECLARATION_OPEN"; //$NON-NLS-1$
+
+	public static final String XML_DOCTYPE_DECLARATION = "XML_DOCTYPE_DECLARATION"; //$NON-NLS-1$
+	public static final String XML_DOCTYPE_DECLARATION_CLOSE = "XML_DOCTYPE_DECLARATION_CLOSE"; //$NON-NLS-1$
+	public static final String XML_DOCTYPE_EXTERNAL_ID_PUBLIC = "XML_DOCTYPE_EXTERNAL_ID_PUBLIC"; //$NON-NLS-1$
+	public static final String XML_DOCTYPE_EXTERNAL_ID_PUBREF = "XML_DOCTYPE_EXTERNAL_ID_PUBREF"; //$NON-NLS-1$
+	public static final String XML_DOCTYPE_EXTERNAL_ID_SYSREF = "XML_DOCTYPE_EXTERNAL_ID_SYSREF"; //$NON-NLS-1$
+	public static final String XML_DOCTYPE_EXTERNAL_ID_SYSTEM = "XML_DOCTYPE_EXTERNAL_ID_SYSTEM"; //$NON-NLS-1$
+	public static final String XML_DOCTYPE_INTERNAL_SUBSET = "XML_DOCTYPE_INTERNAL_SUBSET"; //$NON-NLS-1$
+	public static final String XML_DOCTYPE_NAME = "XML_DOCTYPE_NAME"; //$NON-NLS-1$
+	public static final String XML_ELEMENT_DECL_CLOSE = "XML_ELEMENT_DECL_CLOSE"; //$NON-NLS-1$
+	public static final String XML_ELEMENT_DECL_CONTENT = "XML_ELEMENT_DECL_CONTENT"; //$NON-NLS-1$
+	public static final String XML_ELEMENT_DECL_NAME = "XML_ELEMENT_DECL_NAME"; //$NON-NLS-1$
+
+	public static final String XML_ELEMENT_DECLARATION = "XML_ELEMENT_DECLARATION"; //$NON-NLS-1$
+	public static final String XML_EMPTY_TAG_CLOSE = "XML_EMPTY_TAG_CLOSE"; //$NON-NLS-1$
+	public static final String XML_END_TAG_OPEN = "XML_END_TAG_OPEN"; //$NON-NLS-1$
+	public static final String XML_ENTITY_REFERENCE = "XML_ENTITY_REFERENCE"; //$NON-NLS-1$
+
+	public static final String XML_PE_REFERENCE = "XML_PE_REFERENCE"; //$NON-NLS-1$
+	public static final String XML_PI_CLOSE = "XML_PI_CLOSE"; //$NON-NLS-1$
+	public static final String XML_PI_CONTENT = "XML_PI_CONTENT"; //$NON-NLS-1$
+	public static final String XML_PI_OPEN = "XML_PI_OPEN"; //$NON-NLS-1$
+	public static final String XML_TAG_ATTRIBUTE_EQUALS = "XML_TAG_ATTRIBUTE_EQUALS"; //$NON-NLS-1$
+	public static final String XML_TAG_ATTRIBUTE_NAME = "XML_TAG_ATTRIBUTE_NAME"; //$NON-NLS-1$
+	public static final String XML_TAG_ATTRIBUTE_VALUE = "XML_TAG_ATTRIBUTE_VALUE"; //$NON-NLS-1$
+	public static final String XML_TAG_CLOSE = "XML_TAG_CLOSE"; //$NON-NLS-1$
+	public static final String XML_TAG_NAME = "XML_TAG_NAME"; //$NON-NLS-1$
+
+	public static final String XML_TAG_OPEN = "XML_TAG_OPEN"; //$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/ssemodelquery/ModelQueryAdapter.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/ssemodelquery/ModelQueryAdapter.java
new file mode 100644
index 0000000..74ad2a1
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/ssemodelquery/ModelQueryAdapter.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.ssemodelquery;
+
+import org.eclipse.wst.common.uriresolver.internal.provisional.URIResolver;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapter;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.CMDocumentCache;
+
+public interface ModelQueryAdapter extends INodeAdapter {
+
+	public CMDocumentCache getCMDocumentCache();
+
+	public URIResolver getIdResolver();
+
+	public ModelQuery getModelQuery();
+
+	void release();
+
+	void setIdResolver(URIResolver newIdResolver);
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/ssemodelquery/ModelQueryAdapterImpl.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/ssemodelquery/ModelQueryAdapterImpl.java
new file mode 100644
index 0000000..a68e672
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/ssemodelquery/ModelQueryAdapterImpl.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.ssemodelquery;
+
+
+
+import org.eclipse.wst.common.uriresolver.internal.provisional.URIResolver;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.CMDocumentCache;
+
+
+public class ModelQueryAdapterImpl implements ModelQueryAdapter {
+	protected CMDocumentCache cmDocumentCache;
+	protected URIResolver idResolver;
+
+	protected ModelQuery modelQuery;
+
+	public ModelQueryAdapterImpl(CMDocumentCache cmDocumentCache, ModelQuery modelQuery, URIResolver idResolver) {
+		this.cmDocumentCache = cmDocumentCache;
+		this.modelQuery = modelQuery;
+		this.idResolver = idResolver;
+	}
+
+	public CMDocumentCache getCMDocumentCache() {
+		return cmDocumentCache;
+	}
+
+	public URIResolver getIdResolver() {
+		return idResolver;
+	}
+
+	public ModelQuery getModelQuery() {
+		return modelQuery;
+	}
+
+	/**
+	 * Allowing the INodeAdapter to compare itself against the type allows it
+	 * to return true in more than one case.
+	 */
+	public boolean isAdapterForType(Object type) {
+		return type.equals(ModelQueryAdapter.class);
+	}
+
+	/**
+	 */
+
+	public void notifyChanged(INodeNotifier notifier, int eventType, Object changedFeature, Object oldValue, Object newValue, int pos) {
+	}
+
+	/**
+	 * @see ModelQueryAdapter#release()
+	 */
+	public void release() {
+	}
+
+	/**
+	 * @see ModelQueryAdapter#setIdResolver(URIResolver)
+	 */
+
+	public void setIdResolver(URIResolver newIdResolver) {
+		idResolver = newIdResolver;
+		if (modelQuery instanceof MovableModelQuery)
+			((MovableModelQuery) modelQuery).setIdResolver(newIdResolver);
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/ssemodelquery/MovableModelQuery.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/ssemodelquery/MovableModelQuery.java
new file mode 100644
index 0000000..49d7339
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/ssemodelquery/MovableModelQuery.java
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.ssemodelquery;
+
+
+
+import org.eclipse.wst.common.uriresolver.internal.provisional.URIResolver;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+
+public interface MovableModelQuery extends ModelQuery {
+
+	void setIdResolver(URIResolver newURIResolver);
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/tasks/XMLFileTaskScanner.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/tasks/XMLFileTaskScanner.java
new file mode 100644
index 0000000..94b8155
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/tasks/XMLFileTaskScanner.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.tasks;
+
+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.tasks.StructuredFileTaskScanner;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+
+public class XMLFileTaskScanner extends StructuredFileTaskScanner {
+	public XMLFileTaskScanner() {
+		super();
+	}
+
+	protected boolean isCommentRegion(IStructuredDocumentRegion region, ITextRegion textRegion) {
+		return textRegion.getType().equals(DOMRegionContext.XML_COMMENT_TEXT);
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/text/XMLStructuredDocumentRegion.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/text/XMLStructuredDocumentRegion.java
new file mode 100644
index 0000000..e26bf08
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/text/XMLStructuredDocumentRegion.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.text;
+
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.internal.text.BasicStructuredDocumentRegion;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+
+
+public class XMLStructuredDocumentRegion extends BasicStructuredDocumentRegion implements IStructuredDocumentRegion {
+
+	public XMLStructuredDocumentRegion() {
+		super();
+	}
+
+	public String getType() {
+		String result = super.getType();
+		// normally, we want the second region as the flatnode type ... since
+		// the
+		// first one is usually just "open tag".
+		if ((result != DOMRegionContext.XML_PI_OPEN) && (getRegions().size() > 1)) {
+			result = getRegions().get(1).getType();
+		}
+		return result;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/text/rules/StructuredTextPartitionerForXML.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/text/rules/StructuredTextPartitionerForXML.java
new file mode 100644
index 0000000..8b73869
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/text/rules/StructuredTextPartitionerForXML.java
@@ -0,0 +1,132 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.text.rules;
+
+import java.util.Locale;
+
+import org.eclipse.jface.text.IDocumentPartitioner;
+import org.eclipse.wst.sse.core.internal.parser.ForeignRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredTextPartitioner;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+import org.eclipse.wst.sse.core.internal.text.rules.StructuredTextPartitioner;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+import org.eclipse.wst.xml.core.text.IXMLPartitions;
+
+public class StructuredTextPartitionerForXML extends StructuredTextPartitioner implements IStructuredTextPartitioner {
+
+	private final static String[] configuredContentTypes = new String[]{IXMLPartitions.XML_DEFAULT, IXMLPartitions.XML_CDATA, IXMLPartitions.XML_PI, IXMLPartitions.XML_DECLARATION, IXMLPartitions.XML_COMMENT, IXMLPartitions.DTD_SUBSET};
+
+	public StructuredTextPartitionerForXML() {
+		super();
+	}
+
+	protected void setInternalPartition(int offset, int length, String type) {
+		super.setInternalPartition(offset, length, type);
+	}
+
+	protected void initLegalContentTypes() {
+		fSupportedTypes = configuredContentTypes;
+	}
+
+	public String getPartitionType(ITextRegion region, int offset) {
+		String result = null;
+		if (region.getType() == DOMRegionContext.XML_COMMENT_TEXT)
+			result = IXMLPartitions.XML_COMMENT;
+		else if (region.getType() == DOMRegionContext.XML_CDATA_TEXT)
+			result = IXMLPartitions.XML_CDATA;
+		else if (region.getType() == DOMRegionContext.XML_PI_CONTENT) {
+			/**
+			 * Grammatically, it's impossible to get a PI_CONTENT region
+			 * without a preceding XML_TAG_NAME region. Relying on this,
+			 * extract the target processor name and create a partition type
+			 * dynamically.
+			 */
+			IStructuredDocumentRegion docRegion = fStructuredDocument.getRegionAtCharacterOffset(offset);
+			ITextRegion name = docRegion.getRegionAtCharacterOffset(docRegion.getStartOffset() + region.getStart() - 1);
+			result = IXMLPartitions.PROCESSING_INSTRUCTION_PREFIX + docRegion.getText(name).toUpperCase(Locale.ENGLISH);
+		}
+		else if (region.getType() == DOMRegionContext.XML_PI_OPEN)
+			result = IXMLPartitions.XML_PI;
+		else if (region.getType() == DOMRegionContext.XML_DOCTYPE_DECLARATION)
+			result = IXMLPartitions.XML_DECLARATION;
+		else if (region.getType() == DOMRegionContext.XML_DOCTYPE_INTERNAL_SUBSET)
+			result = IXMLPartitions.DTD_SUBSET;
+		else
+			result = super.getPartitionType(region, offset);
+		return result;
+	}
+
+	protected String getPartitionType(ForeignRegion region, int offset) {
+		// temp added just to dis-ambiguate call from subclass
+		return super.getPartitionType(region, offset);
+	}
+
+	public String getPartitionTypeBetween(IStructuredDocumentRegion previousNode, IStructuredDocumentRegion nextNode) {
+		return super.getPartitionTypeBetween(previousNode, nextNode);
+	}
+
+	public String getDefaultPartitionType() {
+		return IXMLPartitions.XML_DEFAULT;
+	}
+
+	public IDocumentPartitioner newInstance() {
+		StructuredTextPartitionerForXML instance = new StructuredTextPartitionerForXML();
+		return instance;
+	}
+
+	/**
+	 * @return
+	 */
+	public static String[] getConfiguredContentTypes() {
+		return configuredContentTypes;
+	}
+
+	protected String getPartitionFromBlockedText(ITextRegion region, int offset, String result) {
+		// was moved to subclass for quick transition
+		String newResult = result;
+		// nsd_TODO: David and I need to discuss, design, and implement this
+		// for all block tags and comments
+		// and make sure is part of "extensible" design of block tags
+		if (region.getType() == DOMRegionContext.BLOCK_TEXT) {
+			// for code safety, we'll always check instanceof, but I think
+			// always true.
+			if (region instanceof ForeignRegion) {
+				// super is used below so won't be ambiguous
+				newResult = getPartitionType((ForeignRegion) region, offset);
+			}
+			else if (region instanceof ForeignRegion) {
+				newResult = getPartitionType((ForeignRegion) region, offset);
+			}
+			else {
+				newResult = getUnknown();
+			}
+		}
+		return newResult;
+	}
+
+	protected boolean doParserSpecificCheck(int offset, boolean partitionFound, IStructuredDocumentRegion sdRegion, IStructuredDocumentRegion previousStructuredDocumentRegion, ITextRegion next, ITextRegion previousStart) {
+		// this was moved down to subclass of StructuredTextPartioner
+		// for quick fix to transition problems. Heirarchy needs lots of
+		// cleanup.
+		if (previousStart != null && previousStart.getType() == DOMRegionContext.XML_TAG_OPEN && next.getType() == DOMRegionContext.XML_END_TAG_OPEN) {
+			ITextRegion previousName = previousStructuredDocumentRegion.getRegionAtCharacterOffset(previousStructuredDocumentRegion.getEndOffset(previousStart));
+			ITextRegion nextName = sdRegion.getRegionAtCharacterOffset(sdRegion.getEndOffset(next));
+			if (previousName != null && nextName != null && previousName.getType() == DOMRegionContext.XML_TAG_NAME && nextName.getType() == DOMRegionContext.XML_TAG_NAME) {
+				setInternalPartition(offset, 0, getPartitionTypeBetween(previousStructuredDocumentRegion, sdRegion));
+				partitionFound = true;
+			}
+		}
+		return partitionFound;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/validate/AbstractPropagatingValidator.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/validate/AbstractPropagatingValidator.java
new file mode 100644
index 0000000..3fddda3
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/validate/AbstractPropagatingValidator.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2008 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.validate;
+
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
+import org.eclipse.wst.sse.core.internal.validate.ValidationAdapter;
+import org.w3c.dom.Node;
+
+
+public abstract class AbstractPropagatingValidator extends ValidationComponent {
+
+	/**
+	 * Constructor for AbstractPropagatingValidator.
+	 */
+	public AbstractPropagatingValidator() {
+		super();
+	}
+
+	protected abstract ValidationComponent getPropagatee();
+
+	protected abstract ValidationAdapter getValidator();
+
+
+	public void validate(IndexedRegion node) {
+		if (node == null)
+			return;
+		getValidator().validate(node);
+
+		propagateToChildElements(getPropagatee(), (Node) node);
+	}
+
+	private void propagateToChildElements(ValidationComponent validator, Node parent) {
+		if (parent == null)
+			return;
+		Class clazz = validator.getClass();
+
+		Node child = parent.getFirstChild();
+		while (child != null) {
+			if (child.getNodeType() == Node.ELEMENT_NODE) {
+				INodeNotifier notifier = (INodeNotifier) child;
+				ValidationAdapter va = (ValidationAdapter) notifier.getExistingAdapter(clazz);
+				if (va == null) {
+					notifier.addAdapter(validator);
+					va = validator;
+				}
+				// bug 143213 - Can't batch validate open HTML files when
+				// as-you-type validation is enabled
+				va.setReporter(validator.getReporter());
+				va.validate((IndexedRegion) child);
+			}
+			child = child.getNextSibling();
+		}
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/validate/Propagator.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/validate/Propagator.java
new file mode 100644
index 0000000..3ce6569
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/validate/Propagator.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.validate;
+
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
+import org.eclipse.wst.sse.core.internal.validate.ValidationAdapter;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * @deprecated since 2.0 M5 - if propogateToChildElement is needed, just copy
+ *             method to your own class
+ */
+public class Propagator {
+
+	public static void propagateToChildElements(ValidationComponent validator, Node parent) {
+		if (parent == null)
+			return;
+		Class clazz = validator.getClass();
+
+		NodeList children = parent.getChildNodes();
+		for (int i = 0; i < children.getLength(); i++) {
+			Node child = children.item(i);
+			if (child == null || child.getNodeType() != Node.ELEMENT_NODE)
+				continue;
+
+			INodeNotifier notifier = (INodeNotifier) child;
+			ValidationAdapter va = (ValidationAdapter) notifier.getExistingAdapter(clazz);
+			if (va == null) {
+				notifier.addAdapter(validator);
+				va = validator;
+			}
+			va.validate((IndexedRegion) child);
+		}
+	}
+
+	/**
+	 * Propagator is just a placeholder of utilities. Don't instantiate.
+	 */
+	private Propagator() {
+		super();
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/validate/ValidationComponent.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/validate/ValidationComponent.java
new file mode 100644
index 0000000..dfd921f
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/validate/ValidationComponent.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.validate;
+
+
+
+import org.eclipse.wst.sse.core.internal.validate.ValidationAdapter;
+import org.eclipse.wst.sse.core.internal.validate.ValidationReporter;
+
+public abstract class ValidationComponent implements ValidationAdapter {
+
+	protected ValidationReporter reporter = null;
+
+	/**
+	 * ValidationComponent constructor comment.
+	 */
+	public ValidationComponent() {
+		super();
+	}
+
+	/**
+	 * Allowing the INodeAdapter to compare itself against the type allows it
+	 * to return true in more than one case.
+	 */
+	public boolean isAdapterForType(Object type) {
+		return (type == ValidationAdapter.class);
+	}
+
+	/**
+	 */
+	public void notifyChanged(org.eclipse.wst.sse.core.internal.provisional.INodeNotifier notifier, int eventType, Object changedFeature, Object oldValue, Object newValue, int pos) {
+		// This method will be implemented in the V2.
+	}
+
+	/**
+	 */
+	public void setReporter(ValidationReporter reporter) {
+		this.reporter = reporter;
+	}
+
+	ValidationReporter getReporter() {
+		return this.reporter;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/text/IXMLPartitions.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/text/IXMLPartitions.java
new file mode 100644
index 0000000..d8da786
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/text/IXMLPartitions.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.text;
+
+
+
+/**
+ * This interface is not intended to be implemented.
+ * It defines the partition types for XML.
+ * Clients should reference the partition type Strings defined here directly.
+ * 
+ * @since 1.1
+ */
+public interface IXMLPartitions {
+	
+	String XML_DEFAULT = "org.eclipse.wst.xml.XML_DEFAULT"; //$NON-NLS-1$
+	String XML_CDATA = "org.eclipse.wst.xml.XML_CDATA"; //$NON-NLS-1$
+	String XML_PI = "org.eclipse.wst.xml.XML_PI"; //$NON-NLS-1$
+	String XML_DECLARATION = "org.eclipse.wst.xml.XML_DECL"; //$NON-NLS-1$
+	String XML_COMMENT = "org.eclipse.wst.xml.XML_COMMENT"; //$NON-NLS-1$
+	
+	/*
+	 * This value is used as a prefix to any unknown processing instructions
+	 * we find. The processor target name is converted to uppercase and
+	 * appended to the prefix to create a unique partition type.
+	 */
+	String PROCESSING_INSTRUCTION_PREFIX = "org.eclipse.wst.xml.PROCESSING_INSTRUCTION:"; //$NON-NLS-1$
+
+	/**
+	 * Should match
+	 * org.eclipse.wst.sse.core.dtd.partitioning.StructuredTextPartitionerForDTD.ST_DTD_SUBSET
+	 */
+	String DTD_SUBSET = "org.eclipse.wst.xml.dtd.internal_subset"; //$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/.classpath b/bundles/org.eclipse.wst.xml.ui/.classpath
new file mode 100644
index 0000000..9d03c22
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/.classpath
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src" />
+	<classpathentry kind="src" path="src-validation" />
+	<classpathentry kind="src" path="src-multipage" />
+	<classpathentry kind="src" path="src-wizards" />
+	<classpathentry kind="src" path="src-catalog" />
+	<classpathentry kind="con"
+		path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.4" />
+	<classpathentry kind="con"
+		path="org.eclipse.pde.core.requiredPlugins">
+		<accessrules>
+			<accessrule kind="accessible"
+				pattern="org/eclipse/wst/validation/internal/core/ValidationException" />
+			<accessrule kind="accessible"
+				pattern="org/eclipse/wst/validation/internal/operations/LocalizedMessage/" />
+			<accessrule kind="accessible"
+				pattern="org/eclipse/wst/validation/internal/provisional/core/IMessage" />
+			<accessrule kind="accessible"
+				pattern="org/eclipse/wst/validation/internal/core/Message" />
+			<accessrule kind="accessible"
+				pattern="org/eclipse/wst/validation/internal/provisional/core/IReporter" />
+			<accessrule kind="accessible"
+				pattern="org/eclipse/wst/validation/internal/provisional/core/IValidationContext" />
+			<accessrule kind="accessible"
+				pattern="org/eclipse/wst/validation/internal/provisional/core/IValidator" />
+			<accessrule kind="accessible"
+				pattern="org/eclipse/wst/common/ui/internal/dnd/DefaultDragAndDropCommand" />
+			<accessrule kind="accessible"
+				pattern="org/eclipse/wst/common/ui/internal/dialogs/SelectSingleFileDialog" />
+			<accessrule kind="accessible"
+				pattern="org/eclipse/wst/validation/internal/core/IMessageAccess" />
+			<accessrule kind="accessible"
+				pattern="org/eclipse/wst/validation/internal/provisional/core/IProjectValidationContext" />
+			<accessrule kind="accessible"
+				pattern="org/eclipse/wst/validation/internal/provisional/core/IValidatorJob" />
+			<accessrule kind="accessible"
+				pattern="org/eclipse/wst/common/ui/internal/viewers/SelectSingleFileView" />
+			<accessrule kind="accessible"
+				pattern="org/eclipse/wst/common/ui/internal/dnd/DragAndDropCommand" />
+			<accessrule kind="accessible"
+				pattern="org/eclipse/wst/common/ui/internal/dnd/DragAndDropManager" />
+			<accessrule kind="accessible"
+				pattern="org/eclipse/wst/common/ui/internal/dnd/ObjectTransfer" />
+			<accessrule kind="accessible"
+				pattern="org/eclipse/wst/common/ui/internal/dnd/ViewerDragAdapter" />
+			<accessrule kind="accessible"
+				pattern="org/eclipse/wst/common/ui/internal/dnd/ViewerDropAdapter" />
+			<accessrule kind="accessible"
+				pattern="org/eclipse/wst/validation/internal/ConfigurationManager" />
+			<accessrule kind="accessible"
+				pattern="org/eclipse/wst/validation/internal/ProjectConfiguration" />
+			<accessrule kind="accessible"
+				pattern="org/eclipse/wst/validation/internal/ValidationRegistryReader" />
+			<accessrule kind="accessible"
+				pattern="org/eclipse/wst/validation/internal/ValidatorMetaData" />
+			<accessrule kind="accessible"
+				pattern="org/eclipse/wst/validation/internal/provisional/ValidationFactory" />
+			<accessrule kind="accessible"
+				pattern="org/eclipse/wst/common/ui/internal/viewers/*" />
+			<accessrule kind="accessible"
+				pattern="org/eclipse/wst/validation/internal/ValidationConfiguration" />
+		</accessrules>
+	</classpathentry>
+	<classpathentry kind="output" path="bin" />
+</classpath>
diff --git a/bundles/org.eclipse.wst.xml.ui/.cvsignore b/bundles/org.eclipse.wst.xml.ui/.cvsignore
new file mode 100644
index 0000000..701c285
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/.cvsignore
@@ -0,0 +1,10 @@
+bin
+temp.folder
+build.xml
+xmleditor.jar
+org.eclipse.wst.xml.ui_1.0.0.jar
+org.eclipse.wst.xml.ui_1.0.0.zip
+xmleditorsrc.zip
+@dot
+src.zip
+javaCompiler...args
diff --git a/bundles/org.eclipse.wst.xml.ui/.options b/bundles/org.eclipse.wst.xml.ui/.options
new file mode 100644
index 0000000..5acae8f
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/.options
@@ -0,0 +1 @@
+org.eclipse.wst.xml.ui/projectionperf=false
diff --git a/bundles/org.eclipse.wst.xml.ui/.project b/bundles/org.eclipse.wst.xml.ui/.project
new file mode 100644
index 0000000..50dc4a8
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/.project
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.wst.xml.ui</name>
+	<comment></comment>
+	<projects></projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.ManifestBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.SchemaBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.PluginNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
diff --git a/bundles/org.eclipse.wst.xml.ui/.settings/org.eclipse.core.resources.prefs b/bundles/org.eclipse.wst.xml.ui/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..afa5c91
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+#Tue Apr 04 03:36:32 EDT 2006
+eclipse.preferences.version=1
+encoding/<project>=ISO-8859-1
diff --git a/bundles/org.eclipse.wst.xml.ui/.settings/org.eclipse.core.runtime.prefs b/bundles/org.eclipse.wst.xml.ui/.settings/org.eclipse.core.runtime.prefs
new file mode 100644
index 0000000..7ec5750
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/.settings/org.eclipse.core.runtime.prefs
@@ -0,0 +1,3 @@
+#Mon Apr 17 01:48:39 EDT 2006
+eclipse.preferences.version=1
+line.separator=\r\n
diff --git a/bundles/org.eclipse.wst.xml.ui/.settings/org.eclipse.jdt.core.prefs b/bundles/org.eclipse.wst.xml.ui/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..a512da0
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,79 @@
+#Sat Mar 24 02:59:49 EDT 2007

+eclipse.preferences.version=1

+org.eclipse.jdt.core.builder.cleanOutputFolder=clean

+org.eclipse.jdt.core.builder.duplicateResourceTask=warning

+org.eclipse.jdt.core.builder.invalidClasspath=ignore

+org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch

+org.eclipse.jdt.core.circularClasspath=error

+org.eclipse.jdt.core.classpath.exclusionPatterns=enabled

+org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled

+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=disabled

+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.2

+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve

+org.eclipse.jdt.core.compiler.compliance=1.4

+org.eclipse.jdt.core.compiler.debug.lineNumber=generate

+org.eclipse.jdt.core.compiler.debug.localVariable=generate

+org.eclipse.jdt.core.compiler.debug.sourceFile=generate

+org.eclipse.jdt.core.compiler.doc.comment.support=enabled

+org.eclipse.jdt.core.compiler.maxProblemPerUnit=100

+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning

+org.eclipse.jdt.core.compiler.problem.assertIdentifier=warning

+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore

+org.eclipse.jdt.core.compiler.problem.deprecation=ignore

+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled

+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=enabled

+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning

+org.eclipse.jdt.core.compiler.problem.emptyStatement=warning

+org.eclipse.jdt.core.compiler.problem.enumIdentifier=warning

+org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore

+org.eclipse.jdt.core.compiler.problem.finalParameterBound=ignore

+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=error

+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error

+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning

+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning

+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore

+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=error

+org.eclipse.jdt.core.compiler.problem.invalidJavadoc=ignore

+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled

+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled

+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=private

+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore

+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=error

+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore

+org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore

+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=enabled

+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public

+org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore

+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=enabled

+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=private

+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore

+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=error

+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=error

+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning

+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore

+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning

+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=error

+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=enabled

+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=error

+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled

+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore

+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=ignore

+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning

+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore

+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning

+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore

+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=error

+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore

+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore

+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled

+org.eclipse.jdt.core.compiler.problem.unusedImport=error

+org.eclipse.jdt.core.compiler.problem.unusedLabel=error

+org.eclipse.jdt.core.compiler.problem.unusedLocal=error

+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore

+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled

+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled

+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=error

+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning

+org.eclipse.jdt.core.compiler.source=1.3

+org.eclipse.jdt.core.incompatibleJDKLevel=ignore

+org.eclipse.jdt.core.incompleteClasspath=error

diff --git a/bundles/org.eclipse.wst.xml.ui/.settings/org.eclipse.jdt.ui.prefs b/bundles/org.eclipse.wst.xml.ui/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000..0ece7b5
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,51 @@
+#Wed Nov 22 23:23:01 EST 2006
+cleanup.add_default_serial_version_id=true
+cleanup.add_generated_serial_version_id=false
+cleanup.add_missing_annotations=false
+cleanup.add_missing_deprecated_annotations=true
+cleanup.add_missing_nls_tags=false
+cleanup.add_missing_override_annotations=true
+cleanup.add_serial_version_id=true
+cleanup.always_use_blocks=true
+cleanup.always_use_parentheses_in_expressions=true
+cleanup.always_use_this_for_non_static_field_access=false
+cleanup.always_use_this_for_non_static_method_access=false
+cleanup.convert_to_enhanced_for_loop=false
+cleanup.format_comment=true
+cleanup.format_javadoc=true
+cleanup.format_multi_line_comment=true
+cleanup.format_single_line_comment=true
+cleanup.format_source_code=true
+cleanup.make_local_variable_final=true
+cleanup.make_parameters_final=false
+cleanup.make_private_fields_final=true
+cleanup.make_variable_declarations_final=false
+cleanup.never_use_blocks=false
+cleanup.never_use_parentheses_in_expressions=false
+cleanup.organize_imports=true
+cleanup.qualify_static_field_accesses_with_declaring_class=false
+cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+cleanup.qualify_static_member_accesses_with_declaring_class=true
+cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.remove_private_constructors=true
+cleanup.remove_unnecessary_casts=true
+cleanup.remove_unnecessary_nls_tags=true
+cleanup.remove_unused_imports=true
+cleanup.remove_unused_local_variables=false
+cleanup.remove_unused_private_fields=true
+cleanup.remove_unused_private_members=true
+cleanup.remove_unused_private_methods=true
+cleanup.remove_unused_private_types=true
+cleanup.use_blocks=true
+cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_parentheses_in_expressions=true
+cleanup.use_this_for_non_static_field_access=false
+cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+cleanup.use_this_for_non_static_method_access=false
+cleanup.use_this_for_non_static_method_access_only_if_necessary=true
+cleanup_profile=_SSE Team Styles
+cleanup_settings_version=2
+eclipse.preferences.version=1
+internal.default.compliance=default
+org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8"?>\r\n<templates/>
diff --git a/bundles/org.eclipse.wst.xml.ui/.settings/org.eclipse.ltk.core.refactoring.prefs b/bundles/org.eclipse.wst.xml.ui/.settings/org.eclipse.ltk.core.refactoring.prefs
new file mode 100644
index 0000000..c59368c
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/.settings/org.eclipse.ltk.core.refactoring.prefs
@@ -0,0 +1,3 @@
+#Tue Apr 04 03:36:32 EDT 2006
+eclipse.preferences.version=1
+org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false
diff --git a/bundles/org.eclipse.wst.xml.ui/.settings/org.eclipse.pde.prefs b/bundles/org.eclipse.wst.xml.ui/.settings/org.eclipse.pde.prefs
new file mode 100644
index 0000000..de4a8be
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/.settings/org.eclipse.pde.prefs
@@ -0,0 +1,25 @@
+#Wed Jun 04 20:07:47 EDT 2008
+compilers.f.unresolved-features=1
+compilers.f.unresolved-plugins=1
+compilers.incompatible-environment=0
+compilers.p.build=0
+compilers.p.deprecated=1
+compilers.p.discouraged-class=1
+compilers.p.illegal-att-value=0
+compilers.p.internal=1
+compilers.p.missing-packages=1
+compilers.p.no-required-att=0
+compilers.p.not-externalized-att=0
+compilers.p.unknown-attribute=0
+compilers.p.unknown-class=0
+compilers.p.unknown-element=0
+compilers.p.unknown-identifier=0
+compilers.p.unknown-resource=0
+compilers.p.unresolved-ex-points=0
+compilers.p.unresolved-import=0
+compilers.p.unused-element-or-attribute=0
+compilers.s.create-docs=false
+compilers.s.doc-folder=doc
+compilers.s.open-tags=1
+compilers.use-project=true
+eclipse.preferences.version=1
diff --git a/bundles/org.eclipse.wst.xml.ui/META-INF/MANIFEST.MF b/bundles/org.eclipse.wst.xml.ui/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..445a2e8
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/META-INF/MANIFEST.MF
@@ -0,0 +1,62 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %pluginName
+Bundle-SymbolicName: org.eclipse.wst.xml.ui; singleton:=true
+Bundle-Version: 1.1.105.qualifier
+Bundle-Activator: org.eclipse.wst.xml.ui.internal.XMLUIPlugin
+Bundle-Vendor: %providerName
+Bundle-Localization: plugin
+Export-Package: org.eclipse.wst.xml.ui,
+ org.eclipse.wst.xml.ui.internal;x-friends:="org.eclipse.wst.xsd.ui,org.eclipse.wst.dtd.ui",
+ org.eclipse.wst.xml.ui.internal.actions;x-friends:="org.eclipse.wst.xsd.ui,org.eclipse.wst.dtd.ui",
+ org.eclipse.wst.xml.ui.internal.autoedit;x-friends:="org.eclipse.wst.xsd.ui,org.eclipse.wst.dtd.ui",
+ org.eclipse.wst.xml.ui.internal.catalog;x-friends:="org.eclipse.wst.xsd.ui,org.eclipse.wst.dtd.ui",
+ org.eclipse.wst.xml.ui.internal.contentassist;x-friends:="org.eclipse.wst.xsd.ui,org.eclipse.wst.dtd.ui",
+ org.eclipse.wst.xml.ui.internal.contentoutline;x-friends:="org.eclipse.wst.xsd.ui,org.eclipse.wst.dtd.ui",
+ org.eclipse.wst.xml.ui.internal.correction;x-friends:="org.eclipse.wst.xsd.ui,org.eclipse.wst.dtd.ui",
+ org.eclipse.wst.xml.ui.internal.dialogs;x-friends:="org.eclipse.wst.xsd.ui,org.eclipse.wst.dtd.ui",
+ org.eclipse.wst.xml.ui.internal.dnd;x-friends:="org.eclipse.wst.xsd.ui,org.eclipse.wst.dtd.ui",
+ org.eclipse.wst.xml.ui.internal.doubleclick;x-friends:="org.eclipse.wst.xsd.ui,org.eclipse.wst.dtd.ui",
+ org.eclipse.wst.xml.ui.internal.editor;x-friends:="org.eclipse.wst.xsd.ui,org.eclipse.wst.dtd.ui",
+ org.eclipse.wst.xml.ui.internal.handlers;x-friends:="org.eclipse.wst.xsd.ui,org.eclipse.wst.dtd.ui",
+ org.eclipse.wst.xml.ui.internal.hyperlink;x-friends:="org.eclipse.wst.xsd.ui,org.eclipse.wst.dtd.ui",
+ org.eclipse.wst.xml.ui.internal.nsedit;x-friends:="org.eclipse.wst.xsd.ui,org.eclipse.wst.dtd.ui",
+ org.eclipse.wst.xml.ui.internal.perspective;x-friends:="org.eclipse.wst.xsl.ui",
+ org.eclipse.wst.xml.ui.internal.preferences;x-friends:="org.eclipse.wst.xsd.ui,org.eclipse.wst.dtd.ui",
+ org.eclipse.wst.xml.ui.internal.projection;x-friends:="org.eclipse.wst.xsd.ui,org.eclipse.wst.dtd.ui",
+ org.eclipse.wst.xml.ui.internal.properties;x-friends:="org.eclipse.wst.xsd.ui,org.eclipse.wst.dtd.ui",
+ org.eclipse.wst.xml.ui.internal.provisional;x-friends:="org.eclipse.wst.xsd.ui,org.eclipse.wst.dtd.ui",
+ org.eclipse.wst.xml.ui.internal.quickoutline,
+ org.eclipse.wst.xml.ui.internal.registry;x-friends:="org.eclipse.wst.xsd.ui,org.eclipse.wst.dtd.ui",
+ org.eclipse.wst.xml.ui.internal.search;x-friends:="org.eclipse.wst.xsd.ui,org.eclipse.wst.dtd.ui",
+ org.eclipse.wst.xml.ui.internal.selection;x-friends:="org.eclipse.wst.xsd.ui,org.eclipse.wst.dtd.ui",
+ org.eclipse.wst.xml.ui.internal.spelling,
+ org.eclipse.wst.xml.ui.internal.style;x-friends:="org.eclipse.wst.xsd.ui,org.eclipse.wst.dtd.ui",
+ org.eclipse.wst.xml.ui.internal.tabletree;x-friends:="org.eclipse.wst.xsd.ui,org.eclipse.wst.dtd.ui",
+ org.eclipse.wst.xml.ui.internal.taginfo;x-friends:="org.eclipse.wst.xsd.ui,org.eclipse.wst.dtd.ui",
+ org.eclipse.wst.xml.ui.internal.templates;x-friends:="org.eclipse.wst.xsd.ui,org.eclipse.wst.dtd.ui",
+ org.eclipse.wst.xml.ui.internal.text;x-friends:="org.eclipse.wst.xsd.ui,org.eclipse.wst.dtd.ui",
+ org.eclipse.wst.xml.ui.internal.util;x-friends:="org.eclipse.wst.xsd.ui,org.eclipse.wst.dtd.ui",
+ org.eclipse.wst.xml.ui.internal.validation;x-friends:="org.eclipse.wst.xsd.ui,org.eclipse.wst.dtd.ui",
+ org.eclipse.wst.xml.ui.internal.validation.core.errorinfo;x-friends:="org.eclipse.wst.xsd.ui,org.eclipse.wst.dtd.ui",
+ org.eclipse.wst.xml.ui.internal.wizards;x-friends:="org.eclipse.wst.xsd.ui,org.eclipse.wst.dtd.ui",
+ org.eclipse.wst.xml.ui.views.contentoutline,
+ org.eclipse.wst.xml.ui.views.properties
+Import-Package: com.ibm.icu.util; version="3.8",
+ com.ibm.icu.text; version="3.8"
+Require-Bundle: org.eclipse.ui.ide;bundle-version="[3.5.0,4.0.0)",
+ org.eclipse.ui.views;bundle-version="[3.4.0,4.0.0)",
+ org.eclipse.jface.text;bundle-version="[3.5.0,4.0.0)",
+ org.eclipse.ui.workbench.texteditor;bundle-version="[3.5.0,4.0.0)",
+ org.eclipse.wst.sse.ui;bundle-version="[1.2.0,1.3.0)",
+ org.eclipse.wst.sse.core;bundle-version="[1.1.500,1.2.0)",
+ org.eclipse.ui;bundle-version="[3.5.0,4.0.0)",
+ org.eclipse.core.resources;bundle-version="[3.5.0,4.0.0)",
+ org.eclipse.core.runtime;bundle-version="[3.5.0,4.0.0)",
+ org.eclipse.wst.common.uriresolver;bundle-version="[1.1.301,1.2.0)",
+ org.eclipse.wst.xml.core;bundle-version="[1.1.500,1.2.0)",
+ org.eclipse.wst.common.ui;bundle-version="[1.1.400,1.2.0)",
+ org.eclipse.wst.validation;bundle-version="[1.2.100,1.3.0)",
+ org.eclipse.core.expressions;bundle-version="[3.4.100,4.0.0)"
+Bundle-ActivationPolicy: lazy; exclude:="org.eclipse.wst.xml.ui.internal.validation.core.errorinfo"
+Bundle-RequiredExecutionEnvironment: J2SE-1.4
diff --git a/bundles/org.eclipse.wst.xml.ui/about.html b/bundles/org.eclipse.wst.xml.ui/about.html
new file mode 100644
index 0000000..2199df3
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/about.html
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
+<HTML>
+
+<head>
+<title>About</title>
+<meta http-equiv=Content-Type content="text/html; charset=ISO-8859-1">
+</head>
+
+<BODY lang="EN-US">
+
+<H3>About This Content</H3>
+
+<P>June, 2008</P>
+
+<H3>License</H3>
+
+<P>The Eclipse Foundation makes available all content in this plug-in 
+("Content"). Unless otherwise indicated below, the Content is provided to you 
+under the terms and conditions of the Eclipse Public License Version 1.0 
+("EPL"). A copy of the EPL is available at
+<A href="http://www.eclipse.org/org/documents/epl-v10.php">http://www.eclipse.org/org/documents/epl-v10.php</A>. 
+For purposes of the EPL, "Program" will mean the Content.</P>
+
+<P>If you did not receive this Content directly from the Eclipse Foundation, the 
+Content is being redistributed by another party ("Redistributor") and different 
+terms and conditions may apply to your use of any object code in the Content. 
+Check the RedistributorÂ’s license that was provided with the Content. If no such 
+license exists, contact the Redistributor. Unless otherwise indicated below, the 
+terms and conditions of the EPL still apply to any source code in the Content 
+and such source code may be obtained at
+<A href="http://www.eclipse.org/">http://www.eclipse.org/</A>.</P>
+
+</BODY>
+</HTML>
diff --git a/bundles/org.eclipse.wst.xml.ui/about.ini b/bundles/org.eclipse.wst.xml.ui/about.ini
new file mode 100644
index 0000000..68af291
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/about.ini
@@ -0,0 +1,12 @@
+# about.ini
+# contains information about a feature
+# java.io.Properties file (ISO 8859-1 with "\" escapes)
+# "%key" are externalized strings defined in about.properties
+# This file does not need to be translated.
+
+# Property "aboutText" contains blurb for "About" dialog (translated)
+aboutText=%blurb
+
+# Property "featureImage" contains path to feature image (32x32)
+featureImage=icons/WTP_icon_x32_v2.png
+
diff --git a/bundles/org.eclipse.wst.xml.ui/about.mappings b/bundles/org.eclipse.wst.xml.ui/about.mappings
new file mode 100644
index 0000000..bddaab4
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/about.mappings
@@ -0,0 +1,6 @@
+# about.mappings
+# contains fill-ins for about.properties
+# java.io.Properties file (ISO 8859-1 with "\" escapes)
+# This file does not need to be translated.
+
+0=@build@
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.xml.ui/about.properties b/bundles/org.eclipse.wst.xml.ui/about.properties
new file mode 100644
index 0000000..8f60396
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/about.properties
@@ -0,0 +1,24 @@
+###############################################################################
+# Copyright (c) 2005, 2009 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
+###############################################################################
+
+# about.properties
+# contains externalized strings for about.ini
+# java.io.Properties file (ISO 8859-1 with "\" escapes)
+# fill-ins are supplied by about.mappings
+# This file should be translated.
+
+blurb=Eclipse XML Editors and Tools\n\
+\n\
+Version: {featureVersion}\n\
+Build id: {0}\n\
+\n\
+(c) Copyright Eclipse contributors and others 2005, 2009.  All rights reserved.\n\
+Visit http://www.eclipse.org/webtools
diff --git a/bundles/org.eclipse.wst.xml.ui/build.properties b/bundles/org.eclipse.wst.xml.ui/build.properties
new file mode 100644
index 0000000..f7dbd12
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/build.properties
@@ -0,0 +1,32 @@
+###############################################################################
+# Copyright (c) 2001, 2006 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
+#     Jens Lukowski/Innoopract - initial renaming/restructuring
+#     
+###############################################################################
+bin.includes = plugin.xml,\
+               icons/,\
+               plugin.properties,\
+               templates/,\
+               examples/,\
+               META-INF/,\
+               .,\
+               .options,\
+               about.html,\
+               about.ini,\
+               about.properties,\
+               about.mappings
+bin.excludes = bin/**,\
+               @dot/**,\
+               temp.folder/**
+source.. = src/,\
+           src-multipage/,\
+           src-wizards/,\
+           src-catalog/,\
+           src-validation/
diff --git a/bundles/org.eclipse.wst.xml.ui/examples/EditingAndValidatingXML.zip b/bundles/org.eclipse.wst.xml.ui/examples/EditingAndValidatingXML.zip
new file mode 100644
index 0000000..6257767
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/examples/EditingAndValidatingXML.zip
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/WTP_icon_x32_v2.png b/bundles/org.eclipse.wst.xml.ui/icons/WTP_icon_x32_v2.png
new file mode 100644
index 0000000..6f09c2a
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/WTP_icon_x32_v2.png
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/XMLFile.gif b/bundles/org.eclipse.wst.xml.ui/icons/XMLFile.gif
new file mode 100644
index 0000000..14eb1be
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/XMLFile.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/collapse.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/collapse.gif
new file mode 100644
index 0000000..ce74721
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/collapse.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/collapse_all.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/collapse_all.gif
new file mode 100644
index 0000000..7dc0de5
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/collapse_all.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/constrainoff.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/constrainoff.gif
new file mode 100644
index 0000000..4bdceb8
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/constrainoff.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/constrainon.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/constrainon.gif
new file mode 100644
index 0000000..e823d57
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/constrainon.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/expand.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/expand.gif
new file mode 100644
index 0000000..bc37b7a
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/expand.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/expand_all.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/expand_all.gif
new file mode 100644
index 0000000..492c14f
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/expand_all.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/new_xml.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/new_xml.gif
new file mode 100644
index 0000000..e1cfdf7
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/new_xml.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/rldgrmr.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/rldgrmr.gif
new file mode 100644
index 0000000..49325dd
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/rldgrmr.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/validate.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/validate.gif
new file mode 100644
index 0000000..561d146
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/validate.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/etool16/collapse.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/etool16/collapse.gif
new file mode 100644
index 0000000..b75bc19
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/etool16/collapse.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/etool16/collapse_all.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/etool16/collapse_all.gif
new file mode 100644
index 0000000..a2d80a9
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/etool16/collapse_all.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/etool16/constrainoff.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/etool16/constrainoff.gif
new file mode 100644
index 0000000..c1ab04c
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/etool16/constrainoff.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/etool16/constrainon.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/etool16/constrainon.gif
new file mode 100644
index 0000000..082f9c0
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/etool16/constrainon.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/etool16/expand.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/etool16/expand.gif
new file mode 100644
index 0000000..b2f4530
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/etool16/expand.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/etool16/expand_all.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/etool16/expand_all.gif
new file mode 100644
index 0000000..0205b29
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/etool16/expand_all.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/etool16/new_xml.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/etool16/new_xml.gif
new file mode 100644
index 0000000..9dfb62d
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/etool16/new_xml.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/etool16/rldgrmr.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/etool16/rldgrmr.gif
new file mode 100644
index 0000000..049cac6
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/etool16/rldgrmr.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/etool16/validate.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/etool16/validate.gif
new file mode 100644
index 0000000..2b347ac
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/etool16/validate.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/XSDFile.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/XSDFile.gif
new file mode 100644
index 0000000..cc0eeb7
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/XSDFile.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/add_correction.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/add_correction.gif
new file mode 100644
index 0000000..252d7eb
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/add_correction.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/att_req_obj.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/att_req_obj.gif
new file mode 100644
index 0000000..a8c66d5
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/att_req_obj.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/attribute_obj.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/attribute_obj.gif
new file mode 100644
index 0000000..79d49d0
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/attribute_obj.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/cdatasection.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/cdatasection.gif
new file mode 100644
index 0000000..6b0872c
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/cdatasection.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/choice.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/choice.gif
new file mode 100644
index 0000000..d13ba2e
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/choice.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/comment_obj.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/comment_obj.gif
new file mode 100644
index 0000000..28c2ccb
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/comment_obj.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/correction_change.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/correction_change.gif
new file mode 100644
index 0000000..af83c52
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/correction_change.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/default.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/default.gif
new file mode 100644
index 0000000..9ced204
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/default.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/doctype.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/doctype.gif
new file mode 100644
index 0000000..3300f82
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/doctype.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/dtdfile.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/dtdfile.gif
new file mode 100644
index 0000000..3c0acad
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/dtdfile.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/element_obj.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/element_obj.gif
new file mode 100644
index 0000000..3567815
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/element_obj.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/entity.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/entity.gif
new file mode 100644
index 0000000..61fd3d4
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/entity.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/entity_reference.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/entity_reference.gif
new file mode 100644
index 0000000..3af9149
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/entity_reference.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/enum.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/enum.gif
new file mode 100644
index 0000000..5c0a481
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/enum.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/error-overlay.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/error-overlay.gif
new file mode 100644
index 0000000..119dccc
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/error-overlay.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/localvariable_obj.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/localvariable_obj.gif
new file mode 100644
index 0000000..3244b26
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/localvariable_obj.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/notation.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/notation.gif
new file mode 100644
index 0000000..57ad089
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/notation.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/occurone_obj.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/occurone_obj.gif
new file mode 100644
index 0000000..7bb65c9
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/occurone_obj.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/proinst_obj.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/proinst_obj.gif
new file mode 100644
index 0000000..74436d8
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/proinst_obj.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/sort.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/sort.gif
new file mode 100644
index 0000000..23c5d0b
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/sort.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/tag-generic.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/tag-generic.gif
new file mode 100644
index 0000000..65f516e
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/tag-generic.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/tag-macro.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/tag-macro.gif
new file mode 100644
index 0000000..5d1f81b
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/tag-macro.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/tag_generic_deemphasized_obj.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/tag_generic_deemphasized_obj.gif
new file mode 100644
index 0000000..cacb405
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/tag_generic_deemphasized_obj.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/tag_generic_emphasized_obj.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/tag_generic_emphasized_obj.gif
new file mode 100644
index 0000000..45c1db4
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/tag_generic_emphasized_obj.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/text.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/text.gif
new file mode 100644
index 0000000..efa7a38
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/text.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/txtext.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/txtext.gif
new file mode 100644
index 0000000..b226e41
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/txtext.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/warning_obj.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/warning_obj.gif
new file mode 100644
index 0000000..1e5f5eb
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/warning_obj.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/ovr16/error_ovr.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/ovr16/error_ovr.gif
new file mode 100644
index 0000000..119dccc
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/ovr16/error_ovr.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/ovr16/stale_error_ovr.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/ovr16/stale_error_ovr.gif
new file mode 100644
index 0000000..5b0471b
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/ovr16/stale_error_ovr.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/ovr16/warn_ovr.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/ovr16/warn_ovr.gif
new file mode 100644
index 0000000..c350704
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/ovr16/warn_ovr.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/view16/attibute.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/view16/attibute.gif
new file mode 100644
index 0000000..79d49d0
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/view16/attibute.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/wizban/generatexml_wiz.png b/bundles/org.eclipse.wst.xml.ui/icons/full/wizban/generatexml_wiz.png
new file mode 100644
index 0000000..b17e48a
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/wizban/generatexml_wiz.png
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/xml_perspective.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/xml_perspective.gif
new file mode 100644
index 0000000..f439b47
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/xml_perspective.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/newSampleProject_wiz.gif b/bundles/org.eclipse.wst.xml.ui/icons/newSampleProject_wiz.gif
new file mode 100644
index 0000000..dc96b10
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/newSampleProject_wiz.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/newSampleProject_wizbanner.png b/bundles/org.eclipse.wst.xml.ui/icons/newSampleProject_wizbanner.png
new file mode 100644
index 0000000..be71474
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/newSampleProject_wizbanner.png
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/sourceEditor.gif b/bundles/org.eclipse.wst.xml.ui/icons/sourceEditor.gif
new file mode 100644
index 0000000..75ebdb8
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/sourceEditor.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/xmldoc.gif b/bundles/org.eclipse.wst.xml.ui/icons/xmldoc.gif
new file mode 100644
index 0000000..14eb1be
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/xmldoc.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/plugin.properties b/bundles/org.eclipse.wst.xml.ui/plugin.properties
new file mode 100644
index 0000000..afc12c8
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/plugin.properties
@@ -0,0 +1,141 @@
+###############################################################################
+# Copyright (c) 2001, 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
+#     Jens Lukowski/Innoopract - initial renaming/restructuring
+#     David Carver / STAR Standards - added XML Catalog Import/Export Wizard
+#                                     bug 192568
+#     David Carver / STAR Standards - bug 212330 - migrate to org.eclipse.ui.menus 	
+###############################################################################
+providerName=Eclipse Web Tools Platform
+pluginName=Eclipse XML Editors and Tools
+XML.name=XML
+XML_Files.name=XML Files
+XML_Source.name=Editor
+XML_Content_Assist.name=Content Assist
+XML_Validator.name=Validation
+XML_Templates.name=Templates
+XML_Styles.name=Styles
+XML_Syntax_Coloring=Syntax Coloring
+XML_Typing=Typing
+XML_Editor.name=XML Editor
+###############################################################################
+_UI_WIZARD_NEW_XML=XML File
+_UI_WIZARD_XML_CATEGORY=XML
+genMenuLabel=&Generate
+_UI_ACTION_CREATE_XML=&XML File...
+_UI_CREATE_NEW_XML_FILE=Create a new XML file
+_UI_WIZARD_IMPORT_EXPORT_XMLCATALOG=XML Catalog
+_UI_IMPORT_XML_CATALOG_FILE=Import an existing XML Catalog.
+_UI_EXPORT_XML_CATALOG_FILE=Export an XML Catalog.
+XMLExample.name=Editing and validating XML files
+XMLExampleProjectCreationWizard.description=Create a project containing XML sample files
+XMLExampleProjectCreationWizard.projectname=XMLExamples
+XMLExampleProjectCreationWizard.pagetitle=XML sample files for editing and validating
+XMLExampleProjectCreationWizard.pagedescription=Create a project containing XML sample files.
+XMLExampleProjectCreationWizard.label=&Project Name:
+###############################################################################
+All_XML_context_type_Extension_Element.name=All XML
+XML_New_context_type_Extension_Element.name=New XML
+XML_Tag_context_type_Extension_Element.name=XML Tag
+XML_Attribute_context_type_Extension_Element.name=XML Attribute
+XML_Attribute_value_context_type_Extension_Element.name=XML Attribute value
+###############################################################################
+AddTask.label=Add &Task...
+AddTask.tooltip=Add Task...
+AddBookmark.label=Add Boo&kmark...
+AddBookmark.tooltip=Add Bookmark...
+SelectRuler.label=Select Ruler
+###############################################################################
+XML_Catalog_File_Type_Extension_Point.name=XML Catalog file type extension point
+_UI_PREF_XML_CATALOG=XML Catalog
+_UI_PREF_DTD_FILES=DTD Files
+_UI_PREF_XSD_FILES=XSD Files
+_UI_PREF_TAGLIB_DEF_FILES=Taglib Definition Files
+_UI_PREF_CATALOG_FILES=XML Catalog Files
+###############################################################################
+_UI_XML_VALIDATOR                   = XML Validator
+_UI_REF_FILE_SHOW_DETAILS           = Show Details...
+_UI_MENU_VALIDATE_XML               = Validate XML File
+##
+CleanupDocument_label=Cleanup Document...
+CleanupDocument_tooltip=Cleanup Document
+ToggleComment_label=Toggle Comment
+ToggleComment_tooltip=Toggle Comment
+AddBlockComment_label=Add Block Comment
+AddBlockComment_tooltip=Add Block Comment
+RemoveBlockComment_label=Remove Block Comment
+RemoveBlockComment_tooltip=Remove Block Comment
+FindOccurrences_label=Occurrences in File
+##
+preferenceKeywords.files=editor xml creating saving files suffix specified encoding iana
+preferenceKeywords.source=editor xml source formatting line width split multiple attributes new clear blank indent tabs spaces size content assist automatically suggestions prompt characters inserted strategy lax strict grammar constraints inferred absence dtd schema
+preferenceKeywords.contentassist=xml editor content code assist complete completion insert overwrite single proposal common prefix automatically import fill argument name guess alphabetical hide auto activation trigger category categories separate specific
+preferenceKeywords.templates=editor xml templates snippet macros
+preferenceKeywords.styles=editor xml style customize syntax highlighting type text content foreground background bold color
+preferenceKeywords.xmlcatalog=xml catalog entries
+preferenceKeywords.severities=xml grammar errors warnings ignore options severity severities suppress project specific projectspecific
+
+##
+XML_Source_target_name=XML Editors
+XML_hyperlink=Tags And Attributes
+##
+DesignMenu_name=&Design
+ReloadDependencies_name=Reload Dependencies
+ReloadDependencies_description=Reload Dependencies
+ReloadDependencies_mnemonic=R
+Constraints_name=Turn off Grammar Constraints
+Constraints_description=Turn off grammar Constraints
+Constraints_mnemonic=T
+ExpandAll_name=Expand All
+CollapseAll_name=Collapse All
+ActionDefinition.nextSibling.name=Next Sibling
+ActionDefinition.nextSibling.description=Go to Next Sibling
+ActionDefinition.previousSibling.name=Previous Sibling
+ActionDefinition.previousSibling.description=Go to Previous Sibling
+ActionDefinition.gotoMatchingTag.name=Matching Tag
+ActionDefinition.gotoMatchingTag.description=Go to Matching Tag
+MatchingTagPreference.label=Matching Tags
+
+scope.structured.text.editor.xml.name=Editing XML Source
+scope.structured.text.editor.xml.description=Editing XML Source
+scope.structured.text.editor.xml.navigation.name=XML Source Navigation
+scope.structured.text.editor.xml.navigation.description=XML Source Navigation
+scope.structured.text.editor.xml.cleanup.name=XML Source Cleanup
+scope.structured.text.editor.xml.cleanup.description=XML Source Cleanup
+scope.structured.text.editor.xml.comments.name=XML Source Comments
+scope.structured.text.editor.xml.comments.description=XML Source Comments
+scope.structured.text.editor.xml.selection.name=XML Source Selection
+scope.structured.text.editor.xml.selection.description=XML Source Selection
+scope.structured.text.editor.xml.dependencies.name=XML Source Dependencies
+scope.structured.text.editor.xml.dependencies.description=XML Source Dependencies
+scope.structured.text.editor.xml.grammar.name=XML Source Grammar
+scope.structured.text.editor.xml.grammar.description=XML Source Grammar
+scope.structured.text.editor.xml.expand.name=XML Source Expand/Collapse
+scope.structured.text.editor.xml.expand.description=XML Source Expand/Collapse
+scope.structured.text.editor.xml.occurrences.name=XML Source Occurrences
+scope.structured.text.editor.xml.occurrences.description=XML Source Occurrences
+
+Colors.tagAttributeName=Tag Attribute Name
+Colors.tagAttributeValue=Tag Attribute Value
+Colors.commentBorder=Comment Border
+Colors.commentText=Comment Text
+Colors.declBorder=Declaration Border
+Colors.doctypeName=Doctype Name
+Colors.doctypeExternalPubref=Doctype External Public Reference
+Colors.doctypeExternalId=Doctype External Id
+Colors.doctypeExtrenalSysref=Doctype External System Reference
+Colors.tagBorder=Tag Border
+Colors.tagName=Tag Name
+Colors.piBorder=Processing Instruction Border
+Colors.cdataBorder=CDATA Border
+Colors.cdataText=CDATA Text
+Colors.entityReference=Entity Reference
+# content assist
+proposalCategory.xmlTags=XML Tag Proposals
+proposalCategory.xmlTemplates=XML Template Proposals
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.xml.ui/plugin.xml b/bundles/org.eclipse.wst.xml.ui/plugin.xml
new file mode 100644
index 0000000..e0a183a
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/plugin.xml
@@ -0,0 +1,1650 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.3"?>
+<plugin>
+
+	<extension-point id="catalogFileType" name="%XML_Catalog_File_Type_Extension_Point.name" schema="schema/catalogFileType.exsd"/>
+
+	<extension point="org.eclipse.wst.xml.ui.catalogFileType">
+		<fileType
+			extensions="dtd, ent, mod"
+			description="%_UI_PREF_DTD_FILES"
+			id="org.eclipse.wst.xml.core.ui.catalogFileType.dtd">
+		</fileType>
+		<fileType
+			extensions="xsd"
+			description="%_UI_PREF_XSD_FILES"
+			id="org.eclipse.wst.xml.core.ui.catalogFileType.xsd">
+		</fileType>
+		<fileType
+			extensions="tld"
+			description="%_UI_PREF_TAGLIB_DEF_FILES"
+			id="org.eclipse.wst.xml.core.ui.catalogFileType.tld">
+		</fileType>
+		<fileType
+			extensions="xml, cat, xmlcatalog"
+			description="%_UI_PREF_CATALOG_FILES"
+			id="org.eclipse.wst.xml.core.ui.catalogFileType.cat">
+		</fileType>
+	</extension>
+
+	<!--The org.eclipse.wst.xml.core.xmlsource content type is only for
+		handling some special cases of ill-formed xml in a reasonable
+		manner, and should not be emulated by clients. The two content
+		types are often used interchangeably by the XML component, but
+		please use org.eclipse.core.runtime.xml instead. -->
+	<extension point="org.eclipse.wst.sse.ui.editorConfiguration">
+		<sourceViewerConfiguration
+			class="org.eclipse.wst.xml.ui.StructuredTextViewerConfigurationXML"
+			target="org.eclipse.core.runtime.xml, org.eclipse.wst.xml.core.xmlsource" />
+		<contentOutlineConfiguration
+			class="org.eclipse.wst.xml.ui.views.contentoutline.XMLContentOutlineConfiguration"
+			target="org.eclipse.core.runtime.xml, org.eclipse.wst.xml.core.xmlsource" />
+		<quickOutlineConfiguration
+			class="org.eclipse.wst.xml.ui.internal.quickoutline.XMLQuickOutlineConfiguration"
+			target="org.eclipse.core.runtime.xml, org.eclipse.wst.xml.core.xmlsource" />
+		<propertySheetConfiguration
+			class="org.eclipse.wst.xml.ui.views.properties.XMLPropertySheetConfiguration"
+			target="org.eclipse.core.runtime.xml, org.eclipse.wst.xml.core.xmlsource" />
+		<documentationTextHover
+        	class="org.eclipse.wst.xml.ui.internal.taginfo.XMLTagInfoHoverProcessor"
+        	target="org.eclipse.wst.xml.XML_DEFAULT">
+  		</documentationTextHover>
+  		<doubleClickStrategy
+        	class="org.eclipse.wst.xml.ui.internal.doubleclick.XMLDoubleClickStrategy"
+        	target="org.eclipse.wst.xml.XML_DEFAULT">
+  		</doubleClickStrategy>
+		<provisionalConfiguration
+			type="sourceeditingtexttools"
+			class="org.eclipse.wst.xml.ui.internal.provisional.XMLSourceEditingTextTools"
+			target="org.eclipse.core.runtime.xml, org.eclipse.wst.xml.core.xmlsource" />
+		<provisionalConfiguration
+			type="characterpairmatcher"
+			class="org.eclipse.wst.xml.ui.internal.text.XMLDocumentRegionEdgeMatcher"
+			target="org.eclipse.core.runtime.xml, org.eclipse.wst.xml.core.xmlsource" />
+		<provisionalConfiguration
+			type="foldingstrategy"
+			class="org.eclipse.wst.xml.ui.internal.projection.XMLFoldingStrategy"
+			target="org.eclipse.core.runtime.xml, org.eclipse.wst.xml.core.xmlsource" />
+		<provisionalConfiguration
+			type="org.eclipse.jface.text.quickassist.IQuickAssistProcessor"
+			class="org.eclipse.wst.xml.ui.internal.correction.XMLQuickAssistProcessor"
+			target="org.eclipse.wst.xml.XML_DEFAULT" />
+		<provisionalConfiguration
+			type="autoeditstrategy"
+			class="org.eclipse.wst.xml.ui.internal.autoedit.StructuredAutoEditStrategyXML"
+			target="org.eclipse.wst.xml.XML_DEFAULT" />
+		<provisionalDefinition
+			type="preferencepages"
+			value="org.eclipse.wst.xml.ui.preferences.xml.xml, org.eclipse.wst.sse.ui.preferences.xml.source, org.eclipse.wst.sse.ui.preferences.xml.templates, org.eclipse.wst.sse.ui.preferences.xml.colors, org.eclipse.wst.sse.ui.preferences.xml.contentassist"
+			target="org.eclipse.core.runtime.xml, org.eclipse.wst.xml.core.xmlsource" />
+		<provisionalDefinition
+			type="spellingregions"
+			value="XML_COMMENT_TEXT, XML_CONTENT, XML_DEFAULT"
+			target="org.eclipse.core.runtime.xml, org.eclipse.wst.xml.core.xmlsource" />
+		<provisionalDefinition
+			type="activecontexts"
+			value="org.eclipse.core.runtime.xml, org.eclipse.wst.xml.navigation, org.eclipse.wst.xml.cleanup, org.eclipse.wst.xml.selection, org.eclipse.wst.xml.dependencies, org.eclipse.wst.xml.grammar, org.eclipse.wst.xml.expand, org.eclipse.wst.xml.occurrences, org.eclipse.wst.sse.comments"
+        	target="org.eclipse.core.runtime.xml" />
+	</extension>
+	
+	<extension point="org.eclipse.ui.contexts">
+		<context
+			name="%scope.structured.text.editor.xml.name"
+			parentId="org.eclipse.wst.sse.ui.structuredTextEditorScope"
+			description="%scope.structured.text.editor.xml.description"
+			id="org.eclipse.core.runtime.xml">
+		</context>
+		<context
+			name="%scope.structured.text.editor.xml.navigation.name"
+			parentId="org.eclipse.wst.sse.ui.structuredTextEditorScope"
+			description="%scope.structured.text.editor.xml.navigation.description"
+			id="org.eclipse.wst.xml.navigation">
+		</context>
+		<context
+			name="%scope.structured.text.editor.xml.cleanup.name"
+			parentId="org.eclipse.wst.sse.ui.structuredTextEditorScope"
+			description="%scope.structured.text.editor.xml.cleanup.description"
+			id="org.eclipse.wst.xml.cleanup">
+		</context>
+		<context
+			name="%scope.structured.text.editor.xml.comments.name"
+			parentId="org.eclipse.wst.sse.ui.structuredTextEditorScope"
+			description="%scope.structured.text.editor.xml.comments.description"
+			id="org.eclipse.wst.xml.comments">
+		</context>
+		<context
+			name="%scope.structured.text.editor.xml.selection.name"
+			parentId="org.eclipse.wst.sse.ui.structuredTextEditorScope"
+			description="%scope.structured.text.editor.xml.selection.description"
+			id="org.eclipse.wst.xml.selection">
+		</context>
+		<context
+			name="%scope.structured.text.editor.xml.dependencies.name"
+			parentId="org.eclipse.wst.sse.ui.structuredTextEditorScope"
+			description="%scope.structured.text.editor.xml.dependencies.description"
+			id="org.eclipse.wst.xml.dependencies">
+		</context>
+		<context
+			name="%scope.structured.text.editor.xml.grammar.name"
+			parentId="org.eclipse.wst.sse.ui.structuredTextEditorScope"
+			description="%scope.structured.text.editor.xml.grammar.description"
+			id="org.eclipse.wst.xml.grammar">
+		</context>
+		<context
+			name="%scope.structured.text.editor.xml.expand.name"
+			parentId="org.eclipse.wst.sse.ui.structuredTextEditorScope"
+			description="%scope.structured.text.editor.xml.expand.description"
+			id="org.eclipse.wst.xml.expand">
+		</context>
+		<context
+			name="%scope.structured.text.editor.xml.occurrences.name"
+			parentId="org.eclipse.wst.sse.ui.structuredTextEditorScope"
+			description="%scope.structured.text.editor.xml.occurrences.description"
+			id="org.eclipse.wst.xml.occurrences">
+		</context>
+	</extension>
+	
+	<extension
+		point="org.eclipse.core.filebuffers.annotationModelCreation">
+		<factory
+			contentTypeId="org.eclipse.core.runtime.xml"
+			class="org.eclipse.wst.sse.ui.internal.StructuredResourceMarkerAnnotationModelFactory" />
+		<factory
+			contentTypeId="org.eclipse.wst.xml.core.xmlsource"
+			class="org.eclipse.wst.sse.ui.internal.StructuredResourceMarkerAnnotationModelFactory" />
+	</extension>
+	<extension
+		point="org.eclipse.wst.sse.ui.adapterFactoryDescription">
+		<adapterFactoryDescription
+			class="org.eclipse.wst.xml.ui.internal.registry.AdapterFactoryProviderForXML">
+			<contentType id="org.eclipse.core.runtime.xml" />
+			<contentType id="org.eclipse.wst.xml.core.xmlsource" />
+		</adapterFactoryDescription>
+	</extension>
+	<extension point="org.eclipse.ui.preferencePages">
+		<!-- The "top-level" XML category -->
+		<page
+			name="%XML.name"
+			class="org.eclipse.wst.xml.ui.internal.preferences.EmptyFilePreferencePage"
+			id="org.eclipse.wst.xml.ui.preferences.xml">
+		</page>
+		<!-- The "lower level" XML Files category/page -->
+		<page
+			name="%XML_Files.name"
+			category="org.eclipse.wst.xml.ui.preferences.xml"
+			class="org.eclipse.wst.xml.ui.internal.preferences.XMLFilesPreferencePage"
+			id="org.eclipse.wst.xml.ui.preferences.xml.xml">
+         	<keywordReference id="org.eclipse.wst.xml.ui.files"/>
+        </page>
+		<!-- XML PREFERENCE PAGES -->
+		<page
+			name="%XML_Source.name"
+			category="org.eclipse.wst.xml.ui.preferences.xml.xml"
+			class="org.eclipse.wst.xml.ui.internal.preferences.XMLSourcePreferencePage"
+			id="org.eclipse.wst.sse.ui.preferences.xml.source">
+         	<keywordReference id="org.eclipse.wst.xml.ui.source"/>
+		</page>
+		<page
+			name="%XML_Content_Assist.name"
+			category="org.eclipse.wst.sse.ui.preferences.xml.source"
+			class="org.eclipse.wst.xml.ui.internal.preferences.XMLContentAssistPreferencePage"
+			id="org.eclipse.wst.sse.ui.preferences.xml.contentassist">
+         	<keywordReference id="org.eclipse.wst.xml.ui.contentassist"/>
+		</page>
+		<page
+			name="%XML_Templates.name"
+			category="org.eclipse.wst.sse.ui.preferences.xml.source"
+			class="org.eclipse.wst.xml.ui.internal.preferences.XMLTemplatePreferencePage"
+			id="org.eclipse.wst.sse.ui.preferences.xml.templates">
+         	<keywordReference id="org.eclipse.wst.xml.ui.templates"/>
+		</page>
+		<page
+			name="%XML_Syntax_Coloring"
+			category="org.eclipse.wst.sse.ui.preferences.xml.source"
+			class="org.eclipse.wst.xml.ui.internal.preferences.XMLSyntaxColoringPage"
+			id="org.eclipse.wst.sse.ui.preferences.xml.colors">
+         	<keywordReference id="org.eclipse.wst.xml.ui.styles"/>
+		</page>
+		<page
+			name="%_UI_PREF_XML_CATALOG"
+			category="org.eclipse.wst.xml.ui.preferences.xml"
+			class="org.eclipse.wst.xml.ui.internal.catalog.XMLCatalogPreferencePage"
+			id="org.eclipse.wst.xml.core.ui.XMLCatalogPreferencePage">
+         	<keywordReference id="org.eclipse.wst.xml.ui.xmlcatalog"/>
+		</page>
+		<page
+			name="%XML_Typing"
+			category="org.eclipse.wst.sse.ui.preferences.xml.source"
+			class="org.eclipse.wst.xml.ui.internal.preferences.XMLTypingPreferencePage"
+			id="org.eclipse.wst.sse.ui.preferences.xml.typing">
+		</page>
+    	<page
+            name="%XML_Validator.name"
+            category="org.eclipse.wst.xml.ui.preferences.xml.xml"
+            class="org.eclipse.wst.xml.ui.internal.preferences.XMLValidatorPreferencePage"
+            id="org.eclipse.wst.sse.ui.preferences.xml.validation">
+       	    <keywordReference id="org.eclipse.wst.xml.ui.severities"/>
+    	</page>
+	</extension>
+	
+	<!-- Keywords for preference and properties pages -->
+	<extension point="org.eclipse.ui.keywords">
+		<keyword
+			label="%preferenceKeywords.files"
+			id="org.eclipse.wst.xml.ui.files"/>
+		<keyword
+			label="%preferenceKeywords.source"
+			id="org.eclipse.wst.xml.ui.source"/>
+		<keyword
+			label="%preferenceKeywords.contentassist"
+			id="org.eclipse.wst.xml.ui.contentassist"/>
+		<keyword
+			label="%preferenceKeywords.templates"
+			id="org.eclipse.wst.xml.ui.templates"/>
+		<keyword
+			label="%preferenceKeywords.styles"
+			id="org.eclipse.wst.xml.ui.styles"/>
+		<keyword
+			label="%preferenceKeywords.xmlcatalog"
+			id="org.eclipse.wst.xml.ui.xmlcatalog"/>
+		<keyword
+			label="%preferenceKeywords.severities"
+			id="org.eclipse.wst.xml.ui.severities"/>
+    </extension>
+	
+	<!-- Editor actionsets -->
+	<extension point="org.eclipse.ui.actionSetPartAssociations">
+		<actionSetPartAssociation
+			targetID="org.eclipse.ui.edit.text.actionSet.annotationNavigation">
+			<part id="org.eclipse.core.runtime.xml.source"></part>
+			<part id="org.eclipse.core.runtime.xml.source2"></part>
+		</actionSetPartAssociation>
+		<actionSetPartAssociation
+			targetID="org.eclipse.ui.NavigateActionSet">
+			<part id="org.eclipse.core.runtime.xml.source"></part>
+			<part id="org.eclipse.core.runtime.xml.source2"></part>
+		</actionSetPartAssociation>
+	</extension>
+
+	<!-- Templates -->
+	<extension point="org.eclipse.ui.editors.templates">
+		<contextType
+			name="%All_XML_context_type_Extension_Element.name"
+			class="org.eclipse.wst.xml.ui.internal.templates.TemplateContextTypeXML"
+			id="xml_all">
+		</contextType>
+		<contextType
+			name="%XML_New_context_type_Extension_Element.name"
+			class="org.eclipse.wst.xml.ui.internal.templates.TemplateContextTypeXML"
+			id="xml_new">
+		</contextType>
+		<contextType
+			name="%XML_Tag_context_type_Extension_Element.name"
+			class="org.eclipse.wst.xml.ui.internal.templates.TemplateContextTypeXML"
+			id="xml_tag">
+		</contextType>
+		<contextType
+			name="%XML_Attribute_context_type_Extension_Element.name"
+			class="org.eclipse.wst.xml.ui.internal.templates.TemplateContextTypeXML"
+			id="xml_attribute">
+		</contextType>
+		<contextType
+			name="%XML_Attribute_value_context_type_Extension_Element.name"
+			class="org.eclipse.wst.xml.ui.internal.templates.TemplateContextTypeXML"
+			id="xml_attribute_value">
+		</contextType>
+		<include
+			file="templates/xmldefault-templates.xml"
+			translations="$nl$/templates/xmldefault-templates.properties">
+		</include>
+	</extension>
+
+	<extension point="org.eclipse.ui.editors">
+		<editor
+			name="%XML_Editor.name"
+			icon="$nl$/icons/xmldoc.gif"
+			contributorClass="org.eclipse.wst.xml.ui.internal.tabletree.XMLMultiPageEditorActionBarContributor"
+			class="org.eclipse.wst.xml.ui.internal.tabletree.XMLMultiPageEditorPart"
+			symbolicFontName="org.eclipse.wst.sse.ui.textfont"
+			id="org.eclipse.wst.xml.ui.internal.tabletree.XMLMultiPageEditorPart">
+			<contentTypeBinding
+				contentTypeId="org.eclipse.core.runtime.xml" />
+			<contentTypeBinding
+				contentTypeId="org.eclipse.wst.xml.core.xmlsource" />
+
+		</editor>
+	</extension>
+
+	<!-- Editor actionsets -->
+	<extension point="org.eclipse.ui.actionSetPartAssociations">
+		<actionSetPartAssociation
+			targetID="org.eclipse.ui.edit.text.actionSet.annotationNavigation">
+			<part
+				id="org.eclipse.wst.xml.ui.internal.tabletree.XMLMultiPageEditorPart">
+			</part>
+		</actionSetPartAssociation>
+		<actionSetPartAssociation
+			targetID="org.eclipse.ui.NavigateActionSet">
+			<part
+				id="org.eclipse.wst.xml.ui.internal.tabletree.XMLMultiPageEditorPart">
+			</part>
+		</actionSetPartAssociation>
+	</extension>
+
+
+
+	<!-- ================================================== -->
+	<!-- Contribute a 'New Wizard' for XML files            -->
+	<!-- ================================================== -->
+	<extension point="org.eclipse.ui.newWizards">
+		<category
+			name="%_UI_WIZARD_XML_CATEGORY"
+			id="org.eclipse.wst.XMLCategory">
+		</category>
+		<wizard
+			name="%_UI_WIZARD_NEW_XML"
+			icon="/icons/full/etool16/new_xml.gif"
+			category="org.eclipse.wst.XMLCategory"
+			class="org.eclipse.wst.xml.ui.internal.wizards.NewXMLWizard"
+			id="org.eclipse.wst.xml.ui.internal.wizards.NewXMLWizard">
+			<description>%_UI_CREATE_NEW_XML_FILE</description>
+			<selection class="org.eclipse.core.resources.IResource">
+			</selection>
+		</wizard>
+	</extension>
+
+	<!-- =============================================================================== -->
+	<!-- Allow the 'New XML' wizard to be accessed via the 'Generate' menu on a XSD file -->
+	<!-- =============================================================================== -->
+<!--
+	<extension point="org.eclipse.ui.popupMenus">
+		<objectContribution
+			objectClass="org.eclipse.core.resources.IFile"
+			nameFilter="*.xsd"
+			id="org.eclipse.wst.xmlwizard.createXMLFromXSD">
+			<menu
+				label="%genMenuLabel"
+				path="additions"
+				id="generateXMLArtifacts">
+				<separator name="xml" />
+			</menu>
+			<action
+				label="%_UI_ACTION_CREATE_XML"
+				class="org.eclipse.wst.xml.ui.internal.wizards.XMLImportActionDelegate"
+				menubarPath="generateXMLArtifacts/xml"
+				enablesFor="1"
+				id="org.eclipse.wst.xmlwizard.createXMLFromXSDAction">
+			</action>
+		</objectContribution>
+	</extension>
+-->
+
+	<!-- =============================================================================== -->
+	<!-- Allow the 'New XML' wizard to be accessed via the 'Generate' menu on a DTD file -->
+	<!-- =============================================================================== -->
+<!--	
+	<extension point="org.eclipse.ui.popupMenus">
+		<objectContribution
+			objectClass="org.eclipse.core.resources.IFile"
+			nameFilter="*.dtd"
+			id="org.eclipse.wst.xmlwizard.createXMLFromDTD">
+			<menu
+				label="%genMenuLabel"
+				path="additions"
+				id="generateXMLArtifacts">
+				<separator name="xml" />
+			</menu>
+			<action
+				label="%_UI_ACTION_CREATE_XML"
+				class="org.eclipse.wst.xml.ui.internal.wizards.XMLImportActionDelegate"
+				menubarPath="generateXMLArtifacts/xml"
+				enablesFor="1"
+				id="org.eclipse.wst.xmlwizard.createXMLFromDTDAction">
+			</action>
+		</objectContribution>
+	</extension>
+-->
+
+	<!-- =============================================================================== -->
+	<!-- Contribute a New->Example... entry for Editing and Validating XML files         -->
+	<!-- =============================================================================== -->
+
+	<!-- define the XMLSamples project wizard -->
+	<extension point="org.eclipse.ui.newWizards">
+		<category
+			name="%_UI_WIZARD_XML_CATEGORY"
+			parentCategory="org.eclipse.ui.Examples"
+			id="org.eclipse.wst.xml.examples">
+		</category>
+		<wizard
+			name="%XMLExample.name"
+			class="org.eclipse.wst.xml.ui.internal.wizards.ExampleProjectCreationWizard"
+			category="org.eclipse.ui.Examples/org.eclipse.wst.xml.examples"
+			id="org.eclipse.wst.xml.ui.XMLExampleProjectCreationWizard"
+			project="true"
+			icon="$nl$/icons/newSampleProject_wiz.gif">
+			<description>
+				%XMLExampleProjectCreationWizard.description
+			</description>
+		</wizard>
+	</extension>
+
+	<!-- configure the XMLSamples project wizard -->
+	<extension
+		point="org.eclipse.wst.common.ui.exampleProjectCreationWizard"
+		id="XMLExampleProjectCreationWizardExtension">
+		<wizard
+			id="org.eclipse.wst.xml.ui.XMLExampleProjectCreationWizard"
+			banner="icons/newSampleProject_wizbanner.png">
+			<projectsetup
+				pagetitle="%XMLExampleProjectCreationWizard.pagetitle"
+				name="%XMLExampleProjectCreationWizard.projectname"
+				label="%XMLExampleProjectCreationWizard.label"
+				pagedescription="%XMLExampleProjectCreationWizard.pagedescription"
+				open="readme.html">
+				<import
+					dest=""
+					src="examples/EditingAndValidatingXML.zip" />
+			</projectsetup>
+		</wizard>
+	</extension>
+
+	<extension point="org.eclipse.core.runtime.adapters">
+		<factory
+			adaptableType="org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel"
+			class="org.eclipse.wst.xml.ui.internal.editor.DOMSelectionConvertorFactory">
+			<adapter
+            	type="org.eclipse.wst.sse.ui.internal.editor.SelectionConvertor"/>
+		</factory>
+		<factory
+			adaptableType="org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel"
+			class="org.eclipse.wst.xml.ui.internal.spelling.SpellcheckDelegateAdapterFactory">
+			<adapter
+            	type="org.eclipse.wst.sse.ui.internal.spelling.ISpellcheckDelegate"/>
+		</factory>
+	</extension>
+
+	<!-- initialize xml ui preferences -->
+	<extension point="org.eclipse.core.runtime.preferences">
+		<initializer
+			class="org.eclipse.wst.xml.ui.internal.preferences.XMLUIPreferenceInitializer" />
+	</extension>
+
+	<extension point="org.eclipse.wst.sse.ui.sourcevalidation">
+		<validator
+			scope="total"
+			class="org.eclipse.wst.xml.ui.internal.validation.DelegatingSourceValidatorForXML"
+			id="org.eclipse.wst.xml.ui.internal.validation.DelegatingSourceValidatorForXML">
+			<contentTypeIdentifier id="org.eclipse.core.runtime.xml">
+				<partitionType id="org.eclipse.wst.xml.XML_DEFAULT"/>
+				<partitionType id="org.eclipse.wst.xml.XML_COMMENT"/>
+				<partitionType id="org.eclipse.wst.sse.ST_DEFAULT"/>
+                <partitionType id="org.eclipse.wst.xml.XML_PI"/> 
+			</contentTypeIdentifier>
+			<contentTypeIdentifier id="org.eclipse.wst.xml.core.xmlsource">
+				<partitionType id="org.eclipse.wst.xml.XML_DEFAULT"/>
+				<partitionType id="org.eclipse.wst.xml.XML_COMMENT"/>
+				<partitionType id="org.eclipse.wst.sse.ST_DEFAULT"/>
+                <partitionType id="org.eclipse.wst.xml.XML_PI"/>
+			</contentTypeIdentifier>
+		</validator>
+	</extension>
+	
+		
+   <extension point="org.eclipse.ui.editors.annotationTypes">
+      <type name="org.eclipse.wst.xml.ui.matching.tag"/>
+   </extension>
+   <extension point="org.eclipse.ui.editors.markerAnnotationSpecification">
+      <specification
+      		includeOnPreferencePage="true"
+            colorPreferenceValue="212,212,212"
+            annotationType="org.eclipse.wst.xml.ui.matching.tag"
+            colorPreferenceKey="matchingTagIndicationColor"
+            presentationLayer="4"
+            label="%MatchingTagPreference.label"
+            icon="icons/full/obj16/tag-generic.gif"
+            textPreferenceValue="false"
+            textPreferenceKey="matchingTagIndication"
+            highlightPreferenceKey="matchingTagHighlight"
+            highlightPreferenceValue="true"
+            verticalRulerPreferenceKey="matchingTagVerticalRuler"
+            verticalRulerPreferenceValue="false"
+            overviewRulerPreferenceKey="matchingTagIndicationInOverviewRuler"
+            overviewRulerPreferenceValue="true"
+            textStylePreferenceKey="matchingTagTextStyle"
+			textStylePreferenceValue="NONE">
+      </specification>
+   </extension>
+
+	<!--======================================================================================-->
+	<!-- Document provider for ExternalFileEditorInput                                        -->
+	<!--======================================================================================-->
+	<extension point="org.eclipse.ui.editors.documentProviders">
+		<provider
+			inputTypes="org.eclipse.wst.xml.ui.internal.hyperlink.ExternalFileEditorInput"
+			class="org.eclipse.ui.editors.text.TextFileDocumentProvider"
+			id="org.eclipse.wst.xml.ui.internal.ExternalFileDocumentProvider">
+		</provider>
+	</extension>
+
+	<!-- To Do: migrate this to the org.eclipse.ui.menus popup: format -->
+	<extension point="org.eclipse.ui.popupMenus">
+		<viewerContribution
+			targetID="org.eclipse.core.runtime.xml.source.RulerContext"
+			id="org.eclipse.ui.texteditor.ruler.context.actions">
+			<action
+				label="%AddTask.label"
+				helpContextId="org.eclipse.ui.AddTask_action_context"
+				class="org.eclipse.ui.texteditor.TaskRulerAction"
+				tooltip="%AddTask.tooltip"
+				menubarPath="additions"
+				id="org.eclipse.ui.texteditor.TaskRulerAction">
+			</action>
+			<action
+				label="%AddBookmark.label"
+				helpContextId="org.eclipse.ui.bookmark_action_context"
+				class="org.eclipse.ui.texteditor.BookmarkRulerAction"
+				tooltip="%AddBookmark.tooltip"
+				menubarPath="additions"
+				id="org.eclipse.ui.texteditor.BookmarkRulerAction">
+			</action>
+		</viewerContribution>
+	</extension>
+
+	<!--======================================================================================-->
+	<!-- Pop-up menu and associated command/handler for nested validation messages.           -->
+	<!--======================================================================================-->
+
+	<extension point="org.eclipse.ui.menus">
+      <menuContribution locationURI="popup:org.eclipse.ui.ide.MarkersView">
+          <command commandId="org.eclipse.wst.xml.ui.referencedFileErrors">
+             <visibleWhen checkEnabled="false">
+				<reference definitionId="org.eclipse.wst.xml.ui.referencedFileErrors" />
+             </visibleWhen>
+         </command>
+      </menuContribution>
+	</extension>
+	
+	<extension point="org.eclipse.ui.commands">
+		<command
+			description="%_UI_REF_FILE_SHOW_DETAILS"
+			id="org.eclipse.wst.xml.ui.referencedFileErrors" 
+			name="%_UI_REF_FILE_SHOW_DETAILS" />
+	</extension>
+	
+    <extension point="org.eclipse.ui.handlers">
+       <handler
+             class="org.eclipse.wst.xml.ui.internal.validation.core.errorinfo.ReferencedFileErrorsHandler"
+             commandId="org.eclipse.wst.xml.ui.referencedFileErrors">
+             <enabledWhen>
+				<reference definitionId="org.eclipse.wst.xml.ui.referencedFileErrors" />
+             </enabledWhen>
+       </handler>
+	</extension>
+	
+	<extension point="org.eclipse.core.expressions.propertyTesters">
+	   <propertyTester
+	         class="org.eclipse.wst.xml.ui.internal.validation.core.errorinfo.GroupNamePropertyTester"
+	         id="org.eclipse.wst.xml.ui.markerGroupNamePropertyTester"
+	         namespace="org.eclipse.wst.xml.ui"
+	         properties="groupNamePrefix"
+	         type="org.eclipse.core.resources.IMarker">
+	   </propertyTester>
+	</extension>
+	 
+	<extension point="org.eclipse.core.expressions.definitions">
+		<definition id="org.eclipse.wst.xml.ui.referencedFileErrors">
+                <and>
+                   <count value="1" />
+                   <with variable="selection">
+                   		<iterate operator="or">
+                      		<adapt type="org.eclipse.core.resources.IMarker">
+                            	<test property="org.eclipse.wst.xml.ui.groupNamePrefix" value="referencedFileError" forcePluginActivation="true" />
+                      		</adapt>
+                   		</iterate>
+                	</with>
+                </and>
+		</definition>
+	</extension>	 
+
+<!--	
+	<extension point="org.eclipse.ui.editorActions">
+		<editorContribution
+			id="org.eclipse.core.runtime.xml.source.editorActions"
+			targetID="org.eclipse.core.runtime.xml.source">
+			<action
+				id="CleanupDocument"
+				label="%CleanupDocument_label"
+				definitionId="org.eclipse.wst.sse.ui.cleanup.document"
+				tooltip="%CleanupDocument_tooltip"
+				class="org.eclipse.wst.xml.ui.internal.actions.CleanupActionXMLDelegate"
+				actionID="CleanupDocument">
+			</action>
+			<action
+				id="ToggleComment"
+				label="%ToggleComment_label"
+				definitionId="org.eclipse.wst.sse.ui.toggle.comment"
+				tooltip="%ToggleComment_tooltip"
+				class="org.eclipse.wst.xml.ui.internal.actions.ToggleCommentActionXMLDelegate"
+				actionID="ToggleComment">
+			</action>
+			<action
+				id="AddBlockComment"
+				label="%AddBlockComment_label"
+				definitionId="org.eclipse.wst.sse.ui.add.block.comment"
+				tooltip="%AddBlockComment_tooltip"
+				class="org.eclipse.wst.xml.ui.internal.actions.AddBlockCommentActionXMLDelegate"
+				actionID="AddBlockComment">
+			</action>
+			<action
+				id="RemoveBlockComment"
+				label="%RemoveBlockComment_label"
+				definitionId="org.eclipse.wst.sse.ui.remove.block.comment"
+				tooltip="%RemoveBlockComment_tooltip"
+				class="org.eclipse.wst.xml.ui.internal.actions.RemoveBlockCommentActionXMLDelegate"
+				actionID="RemoveBlockComment">
+			</action>
+			<action
+				id="FindOccurrences"
+				label="%FindOccurrences_label"
+				definitionId="org.eclipse.wst.sse.ui.search.find.occurrences"
+				class="org.eclipse.wst.xml.ui.internal.search.XMLFindOccurrencesActionDelegate"
+				actionID="FindOccurrences">
+			</action>
+			<action
+				id="StructureSelectEnclosing"
+				label="%StructureSelectEnclosing_label"
+				definitionId="org.eclipse.wst.sse.ui.structure.select.enclosing"
+				tooltip="%StructureSelectEnclosing_tooltip"
+				class="org.eclipse.wst.xml.ui.internal.selection.StructuredSelectEnclosingXMLActionDelegate"
+				actionID="StructureSelectEnclosing">
+			</action>
+			<action
+				id="StructureSelectNext"
+				label="%StructureSelectNext_label"
+				definitionId="org.eclipse.wst.sse.ui.structure.select.next"
+				tooltip="%StructureSelectNext_tooltip"
+				class="org.eclipse.wst.xml.ui.internal.selection.StructuredSelectNextXMLActionDelegate"
+				actionID="StructureSelectNext">
+			</action>
+			<action
+				id="StructureSelectPrevious"
+				label="%StructureSelectPrevious_label"
+				definitionId="org.eclipse.wst.sse.ui.structure.select.previous"
+				tooltip="%StructureSelectPrevious_tooltip"
+				class="org.eclipse.wst.xml.ui.internal.selection.StructuredSelectPreviousXMLActionDelegate"
+				actionID="StructureSelectPrevious">
+			</action>
+			<action
+				id="StructureSelectHistory"
+				label="%StructureSelectHistory_label"
+				definitionId="org.eclipse.wst.sse.ui.structure.select.last"
+				tooltip="%StructureSelectHistory_tooltip"
+				class="org.eclipse.wst.sse.ui.internal.selection.StructuredSelectHistoryActionDelegate"
+				actionID="StructureSelectHistory">
+			</action>
+		</editorContribution>
+        <editorContribution
+            targetID="org.eclipse.core.runtime.xml.source"
+            id="org.eclipse.core.runtime.xml.source.ruler.actions">
+         <action
+               label="%AddBookmark.label"
+               helpContextId="org.eclipse.ui.bookmark_action_context"
+               class="org.eclipse.ui.texteditor.BookmarkRulerAction"
+               actionID="RulerDoubleClick"
+               id="org.eclipse.ui.texteditor.BookmarkRulerAction"/>
+         <action
+               label="%SelectRuler.label"
+               class="org.eclipse.ui.texteditor.SelectRulerAction"
+               actionID="RulerClick"
+               id="org.eclipse.ui.texteditor.SelectRulerAction"/>
+        </editorContribution>
+	</extension>
+-->
+
+	<extension
+		point="org.eclipse.ui.workbench.texteditor.hyperlinkDetectorTargets">
+		<target
+			id="org.eclipse.core.runtime.xml"
+			name="%XML_Source_target_name">
+		</target>
+	</extension>
+	<extension
+		point="org.eclipse.ui.workbench.texteditor.hyperlinkDetectors">
+		<hyperlinkDetector
+			class="org.eclipse.wst.xml.ui.internal.hyperlink.XMLHyperlinkDetector"
+			id="org.eclipse.wst.xml.ui.internal.hyperlink.XMLHyperlinkDetector"
+			name="%XML_hyperlink"
+			targetId="org.eclipse.core.runtime.xml">
+		</hyperlinkDetector>
+   </extension>
+ <extension
+       point="org.eclipse.ui.importWizards">
+    <category
+          id="org.eclipse.wst.XMLCategory"
+          name="%_UI_WIZARD_XML_CATEGORY">
+    </category>
+    <wizard
+          category="org.eclipse.wst.XMLCategory"
+          class="org.eclipse.wst.xml.ui.internal.wizards.ImportXMLCatalogWizard"
+          icon="icons/xmldoc.gif"
+          id="org.eclipse.wst.xml.ui.internal.wizards.ImportXMLCatalogWizard"
+          name="%_UI_WIZARD_IMPORT_EXPORT_XMLCATALOG">
+       <description>
+          %_UI_IMPORT_XML_CATALOG_FILE
+       </description>
+    </wizard>
+ </extension>
+ <extension
+       point="org.eclipse.ui.exportWizards">
+    <category
+          id="org.eclipse.wst.XMLCategory"
+          name="%_UI_WIZARD_XML_CATEGORY">
+    </category>
+    <wizard
+          category="org.eclipse.wst.XMLCategory"
+          class="org.eclipse.wst.xml.ui.internal.wizards.ExportXMLCatalogWizard"
+          icon="icons/xmldoc.gif"
+          id="org.eclipse.wst.xml.ui.internal.wizards.ExportXMLCatalogWizard"
+          name="%_UI_WIZARD_IMPORT_EXPORT_XMLCATALOG">
+       <description>
+          %_UI_EXPORT_XML_CATALOG_FILE
+       </description>
+    </wizard>
+ </extension>
+
+	<extension point="org.eclipse.ui.commands">
+		<!-- Navigate commands -->
+		<command
+			name="%ActionDefinition.nextSibling.name"
+			description="%ActionDefinition.nextSibling.description"
+			categoryId="org.eclipse.ui.category.edit"
+			id="org.eclipse.wst.xml.ui.nextSibling">
+		</command>
+		<command
+			name="%ActionDefinition.previousSibling.name"
+			description="%ActionDefinition.previousSibling.description"
+			categoryId="org.eclipse.ui.category.edit"
+			id="org.eclipse.wst.xml.ui.previousSibling">
+		</command>
+		<command
+			name="%ActionDefinition.gotoMatchingTag.name"
+			description="%ActionDefinition.gotoMatchingTag.description"
+			categoryId="org.eclipse.ui.category.edit"
+			id="org.eclipse.wst.xml.ui.gotoMatchingTag">
+		</command>
+	</extension>
+
+	<extension point="org.eclipse.ui.bindings">
+      <!--  win32:  M1=CTRL,    M2=SHIFT, M3=ALT, M4=-
+            carbon: M1=COMMAND, M2=SHIFT, M3=ALT, M4=CTRL
+            gtk: ? 
+      -->
+      <!-- Navigate commands -->
+		<key
+			sequence="M1+M2+ARROW_UP"
+			contextId="org.eclipse.wst.sse.ui.structuredTextEditorScope"
+			commandId="org.eclipse.wst.xml.ui.previousSibling"
+			schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"/>
+		<key
+			platform="carbon"
+			sequence="CTRL+SHIFT+ARROW_UP"
+			contextId="org.eclipse.wst.sse.ui.structuredTextEditorScope"
+			commandId="org.eclipse.wst.xml.ui.previousSibling"
+			schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"/>
+		<key
+			sequence="M1+M2+ARROW_DOWN"
+			contextId="org.eclipse.wst.sse.ui.structuredTextEditorScope"
+			commandId="org.eclipse.wst.xml.ui.nextSibling"
+			schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"/>
+		<key
+			platform="carbon"
+			sequence="CTRL+SHIFT+ARROW_DOWN"
+			contextId="org.eclipse.wst.sse.ui.structuredTextEditorScope"
+			commandId="org.eclipse.wst.xml.ui.nextSibling"
+			schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"/>
+		<key
+			sequence="M1+M2+&gt;"
+			contextId="org.eclipse.wst.sse.ui.structuredTextEditorScope"
+			commandId="org.eclipse.wst.xml.ui.gotoMatchingTag"
+			schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"/>
+		<key
+			platform="carbon"
+			sequence="CTRL+SHIFT+."
+			contextId="org.eclipse.wst.sse.ui.structuredTextEditorScope"
+			commandId="org.eclipse.wst.xml.ui.gotoMatchingTag"
+			schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"/>
+			
+	</extension>
+	
+<!--
+   This section contains the new org.eclipse.ui.menus extions points and command handler
+   definitions.
+ -->
+ 
+	<extension point="org.eclipse.ui.menus">
+		<!-- Unable to contribute to Search menu at the moment due to bug 213385 -->
+<!--
+		<menuContribution locationURI="menu:org.eclipse.search.menu">
+-->
+	    <menuContribution locationURI="menu:goTo?after=matchingEnd">
+<!--		
+	       <command commandId="org.eclipse.wst.xml.ui.gotoMatchingTag" id="GoToMatchingTag" label="%GoToMatchingTag_label" style="push">
+			   <visibleWhen checkEnabled="false">
+				   <reference definitionId="org.eclipse.wst.sse.ui.sseActiveContext.definition"></reference>
+			   </visibleWhen>
+	       </command>
+-->		
+	       <separator name="goToSiblingsBegin" visible="true"></separator>
+	       <command commandId="org.eclipse.wst.xml.ui.nextSibling" id="GoToNextSibling" label="%ActionDefinition.nextSibling.name" style="push">
+			   <visibleWhen checkEnabled="false">
+					<reference definitionId="org.eclipse.wst.xml.ui.navigation"></reference>
+				</visibleWhen>
+	       </command>
+	       <command commandId="org.eclipse.wst.xml.ui.previousSibling" id="GoToPreviousSibling" label="%ActionDefinition.previousSibling.name" style="push">
+			   <visibleWhen checkEnabled="false">
+					<reference definitionId="org.eclipse.wst.xml.ui.navigation"></reference>
+				</visibleWhen>
+	       </command>
+	       <separator name="goToSiblingsEnd" visible="false"></separator>
+		</menuContribution>
+       <menuContribution
+           locationURI="menu:org.eclipse.ui.main.menu?before=window">
+        <menu
+              id="org.eclipse.wst.xml.ui.designMenuId"
+              label="%DesignMenu_name">
+           <separator
+                 name="designStart">
+           </separator>
+           <command
+                 commandId="org.eclipse.wst.xml.ui.disable.grammar.constraints"
+                 icon="icons/full/etool16/constrainon.gif"
+                 id="ToggleGrammarConstraints"
+                 mnemonic="%Constraints_mnemonic"
+                 style="push">
+                 <visibleWhen checkEnabled="false">
+                	 <and>
+                       <reference definitionId="org.eclipse.wst.xml.ui.grammar"/>
+                       <not>
+                         <reference definitionId="org.eclipse.wst.sse.ui.sseActiveContext.definition"/>
+                       </not>
+                    </and>
+                 </visibleWhen>
+           </command>
+           <command
+                 commandId="org.eclipse.wst.xml.ui.reload.dependecies"
+                 icon="icons/full/etool16/rldgrmr.gif"
+                 id="ReloadDependencies"
+                 mnemonic="%ReloadDependencies_mnemonic"
+                 style="push">
+                 <visibleWhen checkEnabled="false">
+                	<and>
+                       <reference definitionId="org.eclipse.wst.xml.ui.dependencies"/>
+                       <not>
+                         <reference definitionId="org.eclipse.wst.sse.ui.sseActiveContext.definition"/>
+                       </not>
+                    </and>
+                 </visibleWhen>
+           </command>
+           <separator
+                 name="expand"
+                 visible="true">
+           </separator>
+           
+           <command
+                 commandId="sed.tabletree.expandAll"
+                 icon="icons/full/etool16/expand_all.gif"
+                 id="ExpandAll"
+                 style="push">
+                 <visibleWhen checkEnabled="false">
+                    <and>
+                       <reference definitionId="org.eclipse.wst.xml.ui.expand"/>
+                       <not>
+                         <reference definitionId="org.eclipse.wst.sse.ui.sseActiveContext.definition"/>
+                       </not>
+                    </and>
+                 </visibleWhen>
+           </command>
+           <command
+                 commandId="sed.tabletree.collapseAll"
+                 icon="icons/full/etool16/collapse_all.gif"
+                 id="CollapseAll"
+                 style="push">
+                 <visibleWhen checkEnabled="false">
+                    <and>
+                       <reference definitionId="org.eclipse.wst.xml.ui.expand"/>
+                       <not>
+                         <reference definitionId="org.eclipse.wst.sse.ui.sseActiveContext.definition"/>
+                       </not>
+                    </and>
+                 </visibleWhen>
+           </command>
+           
+           <separator
+                 name="additions"
+                 visible="true">
+           </separator>
+           <separator
+                 name="designEnd"
+                 visible="false">
+           </separator>
+        </menu>
+     </menuContribution>
+     <menuContribution locationURI="menu:edit?after=additions">
+		<command commandId="org.eclipse.ui.edit.text.contentAssist.proposals" id="XMLContentAssist" style="push">
+		   <visibleWhen checkEnabled="false">
+				<reference definitionId="org.eclipse.wst.xml.ui.xmlSourceContributions.definition"></reference>
+			</visibleWhen>
+		</command>
+	</menuContribution>		
+     <menuContribution
+           locationURI="popup:org.eclipse.ui.popup.any?after=additions">
+        <menu
+              id="generateMenuId"
+              label="%genMenuLabel">
+	        <command
+	              commandId="org.eclipse.wst.sse.ui.generate.xml"
+	              id="GenerateXML"
+	              style="push">
+	           <visibleWhen checkEnabled="false">
+	              <or>
+					<iterate ifEmpty="false">
+						<adapt
+							type="org.eclipse.core.resources.IFile">
+							<test
+								property="org.eclipse.wst.sse.core.resources.contentTypeId"
+                    			value="org.eclipse.wst.xsd.core.xsdsource">
+							</test>
+						</adapt>
+					</iterate>
+					<iterate ifEmpty="false">
+						<adapt
+							type="org.eclipse.core.resources.IFile">
+							<test
+								property="org.eclipse.wst.sse.core.resources.contentTypeId"
+                    			value="org.eclipse.wst.dtd.core.dtdsource">
+							</test>
+						</adapt>
+					</iterate>
+				 </or>	
+	           </visibleWhen>
+	        </command>
+        </menu>
+     </menuContribution>
+     
+     <menuContribution
+           locationURI="toolbar:org.eclipse.ui.main.toolbar?after=additions">
+        <toolbar
+              id="org.eclipse.wst.xml.ui.design.DesignToolBar">
+           <separator
+                 name="sed.tabletree.separator.1"
+                 visible="true">
+           </separator>
+           <command
+                 commandId="org.eclipse.wst.xml.ui.disable.grammar.constraints"
+                 icon="icons/full/etool16/constrainon.gif"
+                 id="ToggleGrammarConstraints"
+                 style="push"
+                 tooltip="%Constraints_name">
+	           <visibleWhen
+	                 checkEnabled="false">
+	              <reference
+	                    definitionId="org.eclipse.wst.xml.ui.grammar">
+	              </reference>
+	           </visibleWhen>
+           </command>
+           <command
+                 commandId="org.eclipse.wst.xml.ui.reload.dependecies"
+                 icon="icons/full/etool16/rldgrmr.gif"
+                 id="ReloadDependencies"
+                 style="push">
+	           <visibleWhen
+	                 checkEnabled="false">
+	              <reference
+	                    definitionId="org.eclipse.wst.xml.ui.dependencies">
+	              </reference>
+	           </visibleWhen>
+           </command>
+        </toolbar>
+     </menuContribution>
+	</extension>
+	
+	<extension point="org.eclipse.core.expressions.definitions">
+		<definition id="org.eclipse.wst.xml.ui.xmlSourceContributions.definition">
+            <with variable="activeContexts">
+	           <iterate operator="or">
+	              <equals value="org.eclipse.core.runtime.xml"/>
+	           </iterate>
+            </with>
+		</definition>
+	</extension>
+	
+	<extension point="org.eclipse.core.expressions.definitions">
+		<definition id="org.eclipse.wst.xml.ui.core">
+			<with variable="activeContexts">
+				<iterate operator="or">
+					<equals value="org.eclipse.core.runtime.xml"/>
+				</iterate>
+			</with>
+		</definition>
+	</extension>
+	
+	<extension point="org.eclipse.core.expressions.definitions">
+		<definition id="org.eclipse.wst.xml.ui.occurrences">
+            <with variable="activeContexts">
+	           <iterate operator="or">
+	              <equals value="org.eclipse.wst.xml.occurrences"/>
+	           </iterate>
+            </with>
+		</definition>
+	</extension>
+
+	<extension point="org.eclipse.core.expressions.definitions">
+		<definition id="org.eclipse.wst.xml.ui.comments">
+			<with variable="activeContexts">
+				<iterate operator="or">
+					<equals value="org.eclipse.wst.xml.comments"/>
+				</iterate>
+			</with>
+		</definition>
+	</extension>
+
+	<extension point="org.eclipse.core.expressions.definitions">
+		<definition id="org.eclipse.wst.xml.ui.cleanup">
+			<with variable="activeContexts">
+				<iterate operator="or">
+					<equals value="org.eclipse.wst.xml.cleanup"/>
+				</iterate>
+			</with>
+		</definition>
+	</extension>
+	
+	<extension point="org.eclipse.core.expressions.definitions">
+		<definition id="org.eclipse.wst.xml.ui.navigation">
+			<with variable="activeContexts">
+				<iterate operator="or">
+					<equals value="org.eclipse.wst.xml.navigation"/>
+				</iterate>
+			</with>
+		</definition>
+	</extension>
+	
+	<extension point="org.eclipse.core.expressions.definitions">
+		<definition id="org.eclipse.wst.xml.ui.selection">
+			<with variable="activeContexts">
+				<iterate operator="or">
+					<equals value="org.eclipse.wst.xml.selection"/>
+				</iterate>
+			</with>
+		</definition>
+	</extension>
+	
+	<extension point="org.eclipse.core.expressions.definitions">
+		<definition id="org.eclipse.wst.xml.ui.dependencies">
+			<or>
+				<with variable="activeEditorId">
+					<equals value="org.eclipse.wst.xml.ui.internal.tabletree.XMLMultiPageEditorPart"></equals>
+				</with>
+				<with variable="activeContexts">
+					<iterate operator="or">
+						<equals value="org.eclipse.wst.xml.dependencies"/>
+					</iterate>
+				</with>
+			</or>
+		</definition>
+	</extension>
+	
+	<extension point="org.eclipse.core.expressions.definitions">
+		<definition id="org.eclipse.wst.xml.ui.grammar">
+			<or>
+				<with variable="activeEditorId">
+					<equals value="org.eclipse.wst.xml.ui.internal.tabletree.XMLMultiPageEditorPart"></equals>
+				</with>
+				<with variable="activeContexts">
+					<iterate operator="or">
+						<equals value="org.eclipse.wst.xml.grammar"/>
+					</iterate>
+				</with>
+			</or>
+		</definition>
+	</extension>
+	
+	<extension point="org.eclipse.core.expressions.definitions">
+		<definition id="org.eclipse.wst.xml.ui.expand">
+			<or>
+				<with variable="activeEditorId">
+					<equals value="org.eclipse.wst.xml.ui.internal.tabletree.XMLMultiPageEditorPart"></equals>
+				</with>
+				<with variable="activeContexts">
+					<iterate operator="or">
+						<equals value="org.eclipse.wst.xml.expand"/>
+					</iterate>
+				</with>
+			</or>
+		</definition>
+	</extension>
+	
+    <extension
+       point="org.eclipse.ui.handlers">
+       <handler
+             class="org.eclipse.wst.xml.ui.internal.handlers.CleanupdocumentHandler"
+             commandId="org.eclipse.wst.sse.ui.cleanup.document">
+          <activeWhen>
+			 <reference definitionId="org.eclipse.wst.xml.ui.cleanup"/>
+          </activeWhen>
+          <enabledWhen>
+             <reference definitionId="org.eclipse.wst.xml.ui.cleanup"/>
+          </enabledWhen>
+       </handler>
+       <handler
+             class="org.eclipse.wst.xml.ui.internal.handlers.StructuredSelectEnclosingXMLHandler"
+             commandId="org.eclipse.wst.sse.ui.structure.select.enclosing">
+          <activeWhen>
+              <reference definitionId="org.eclipse.wst.xml.ui.selection"/>
+          </activeWhen>
+          <enabledWhen>
+              <reference definitionId="org.eclipse.wst.xml.ui.selection"/>
+          </enabledWhen>
+       </handler>
+       <handler
+             class="org.eclipse.wst.xml.ui.internal.handlers.StructuredSelectNextXMLHandler"
+             commandId="org.eclipse.wst.sse.ui.structure.select.next">
+          <activeWhen>
+              <reference definitionId="org.eclipse.wst.xml.ui.selection"/>
+          </activeWhen>
+          <enabledWhen>
+              <reference definitionId="org.eclipse.wst.xml.ui.selection"/>
+          </enabledWhen>
+       </handler>
+       <handler
+             class="org.eclipse.wst.xml.ui.internal.handlers.StructuredSelectPreviousXMLHandler"
+             commandId="org.eclipse.wst.sse.ui.structure.select.previous">
+          <activeWhen>
+              <reference definitionId="org.eclipse.wst.xml.ui.selection"/>
+          </activeWhen>
+          <enabledWhen>
+              <reference definitionId="org.eclipse.wst.xml.ui.selection"/>
+          </enabledWhen>
+       </handler>
+       <handler
+             class="org.eclipse.wst.sse.ui.internal.handlers.StructuredSelectHistoryHandler"
+             commandId="org.eclipse.wst.sse.ui.structure.select.last">
+          <activeWhen>
+              <reference definitionId="org.eclipse.wst.xml.ui.selection"/>
+          </activeWhen>
+          <enabledWhen>
+              <reference definitionId="org.eclipse.wst.xml.ui.selection"/>
+          </enabledWhen>
+       </handler>
+       <handler
+             class="org.eclipse.wst.xml.ui.internal.handlers.XMLFindOccurencesHandler"
+             commandId="org.eclipse.wst.sse.ui.search.find.occurrences">
+          <activeWhen>
+              <reference definitionId="org.eclipse.wst.xml.ui.occurrences"/>
+          </activeWhen>
+          <enabledWhen>
+              <reference definitionId="org.eclipse.wst.xml.ui.occurrences"/>
+          </enabledWhen>
+       </handler>
+<!--
+       <handler
+             class="org.eclipse.wst.xml.ui.internal.handlers.GoToMatchingTagHandler"
+             commandId="org.eclipse.wst.xml.ui.gotoMatchingTag">
+          <activeWhen>
+              <reference definitionId="org.eclipse.wst.xml.ui.navigation"/>
+          </activeWhen>
+          <enabledWhen>
+              <reference definitionId="org.eclipse.wst.xml.ui.navigation"/>
+          </enabledWhen>
+       </handler>
+-->
+       <handler
+             class="org.eclipse.wst.xml.ui.internal.handlers.NextSiblingNavigationHandler"
+             commandId="org.eclipse.wst.xml.ui.nextSibling">
+          <activeWhen>
+              <reference definitionId="org.eclipse.wst.xml.ui.navigation"/>
+          </activeWhen>
+          <enabledWhen>
+              <reference definitionId="org.eclipse.wst.xml.ui.navigation"/>
+          </enabledWhen>
+       </handler>
+       <handler
+             class="org.eclipse.wst.xml.ui.internal.handlers.PreviousSiblingNavigationHandler"
+             commandId="org.eclipse.wst.xml.ui.previousSibling">
+          <activeWhen>
+              <reference definitionId="org.eclipse.wst.xml.ui.navigation"/>
+          </activeWhen>
+          <enabledWhen>
+              <reference definitionId="org.eclipse.wst.xml.ui.navigation"/>
+          </enabledWhen>
+       </handler>
+       <handler
+             class="org.eclipse.wst.xml.ui.internal.handlers.ReloadDependenciesHandler"
+             commandId="org.eclipse.wst.xml.ui.reload.dependecies">
+          <activeWhen>
+              <reference definitionId="org.eclipse.wst.xml.ui.dependencies"/>
+          </activeWhen>
+          <enabledWhen>
+              <reference definitionId="org.eclipse.wst.xml.ui.dependencies"/>
+          </enabledWhen>
+       </handler>
+       <handler
+             class="org.eclipse.wst.xml.ui.internal.handlers.ToggleEditModeHandler"
+             commandId="org.eclipse.wst.xml.ui.disable.grammar.constraints">
+          <activeWhen>
+              <reference definitionId="org.eclipse.wst.xml.ui.grammar"/>
+          </activeWhen>
+          <enabledWhen>
+              <reference definitionId="org.eclipse.wst.xml.ui.grammar"/>
+          </enabledWhen>
+       </handler>
+       <handler
+             class="org.eclipse.wst.xml.ui.internal.wizards.NewXMLHandler"
+             commandId="org.eclipse.wst.sse.ui.generate.xml">
+       </handler>
+       <handler
+             class="org.eclipse.wst.xml.ui.internal.handlers.ExpandAllHandler"
+             commandId="sed.tabletree.expandAll">
+             <activeWhen>
+                 <not>
+		            <with variable="activeContexts">
+			           <iterate operator="or">
+			              <equals value="org.eclipse.wst.sse.ui.structuredTextEditorScope"/>
+			           </iterate>
+		            </with>
+                 </not>
+             </activeWhen>
+       </handler>
+       <handler
+             class="org.eclipse.wst.xml.ui.internal.handlers.CollapseAllHandler"
+             commandId="sed.tabletree.collapseAll">
+             <activeWhen>
+                 <not>
+		            <with variable="activeContexts">
+			           <iterate operator="or">
+			              <equals value="org.eclipse.wst.sse.ui.structuredTextEditorScope"/>
+			           </iterate>
+		            </with>
+                 </not>
+             </activeWhen>
+       </handler>
+    </extension>
+    
+    <extension
+       point="org.eclipse.ui.commands">
+	    <command
+	          id="org.eclipse.wst.sse.ui.generate.xml"
+	          name="%_UI_ACTION_CREATE_XML">
+	    </command>
+	    <command
+	          description="%ReloadDependencies_description"
+	          id="org.eclipse.wst.xml.ui.reload.dependecies"
+	          name="%ReloadDependencies_name">
+	    </command>
+	    <command
+	          description="%Constraints_description"
+	          id="org.eclipse.wst.xml.ui.disable.grammar.constraints"
+	          name="%Constraints_name">
+	    </command>
+	    <command
+	          id="sed.tabletree.expandAll"
+	          name="%ExpandAll_name">
+	    </command>
+	    <command
+	          id="sed.tabletree.collapseAll"
+	          name="%CollapseAll_name">
+	    </command>
+	</extension> 
+	
+	<!-- Define theme -->
+	<extension
+		point="org.eclipse.ui.themes">
+		<theme
+			id="org.eclipse.ui.ide.systemDefault">
+			<colorOverride
+				id="tagAttributeName"
+				value="COLOR_LIST_FOREGROUND">
+			</colorOverride>
+			<colorOverride
+				id="tagAttributeValue"
+				value="COLOR_LIST_FOREGROUND">
+			</colorOverride>
+			<colorOverride
+				id="commentBorder"
+				value="COLOR_LIST_SELECTION">
+			</colorOverride>
+			<colorOverride
+				id="commentText"
+				value="COLOR_LIST_SELECTION">
+			</colorOverride>
+			<colorOverride
+				id="declBoder"
+				value="COLOR_LIST_FOREGROUND">
+			</colorOverride>
+			<colorOverride
+				id="doctypeName"
+				value="COLOR_LIST_FOREGROUND">
+			</colorOverride>
+			<colorOverride
+				id="doctypeExternalPubref"
+				value="COLOR_LIST_FOREGROUND">
+			</colorOverride>
+			<colorOverride
+				id="doctypeExternalId"
+				value="COLOR_WIDGET_NORMAL_SHADOW">
+			</colorOverride>
+			<colorOverride
+				id="doctypeExtrenalSysref"
+				value="COLOR_LIST_FOREGROUND">
+			</colorOverride>
+			<colorOverride
+				id="tagBorder"
+				value="COLOR_LIST_FOREGROUND">
+			</colorOverride>
+			<colorOverride
+				id="tagName"
+				value="COLOR_LIST_FOREGROUND">
+			</colorOverride>
+			<colorOverride
+				id="piBorder"
+				value="COLOR_LIST_FOREGROUND">
+			</colorOverride>
+			<colorOverride
+				id="cdataBorder"
+				value="COLOR_LIST_FOREGROUND">
+			</colorOverride>
+			<colorOverride
+				id="cdataText"
+				value="COLOR_LIST_FOREGROUND">
+			</colorOverride>
+			<colorOverride
+				id="entityReference"
+				value="COLOR_LIST_FOREGROUND">
+			</colorOverride>
+		</theme>
+		<colorDefinition
+			id="tagAttributeName"
+			isEditable="false"
+			label="%Colors.tagAttributeName"
+			value="127, 0, 127">
+		</colorDefinition>
+		<colorDefinition
+			id="tagAttributeValue"
+			isEditable="false"
+			label="%Colors.tagAttributeValue"
+			value="42, 0, 255">
+		</colorDefinition>
+		<colorDefinition
+			id="commentBorder"
+			isEditable="false"
+			label="%Colors.commentBorder"
+			value="63, 95, 191">
+		</colorDefinition>
+		<colorDefinition
+			id="commentText"
+			isEditable="false"
+			label="%Colors.commentText"
+			value="63, 95, 191">
+		</colorDefinition>
+		<colorDefinition
+			id="declBoder"
+			isEditable="false"
+			label="%Colors.declBorder"
+			value="0, 128, 128">
+		</colorDefinition>
+		<colorDefinition
+			id="doctypeName"
+			isEditable="false"
+			label="%Colors.doctypeName"
+			value="0, 128, 128">
+		</colorDefinition>
+		<colorDefinition
+			id="doctypeExternalPubref"
+			isEditable="false"
+			label="%Colors.doctypeExternalPubref"
+			value="0, 128, 128">
+		</colorDefinition>
+		<colorDefinition
+			id="doctypeExternalId"
+			isEditable="false"
+			label="%Colors.doctypeExternalId"
+			value="128, 128, 128">
+		</colorDefinition>
+		<colorDefinition
+			id="doctypeExtrenalSysref"
+			isEditable="false"
+			label="%Colors.doctypeExtrenalSysref"
+			value="63, 127, 95">
+		</colorDefinition>
+		<colorDefinition
+			id="tagBorder"
+			isEditable="false"
+			label="%Colors.tagBorder"
+			value="0, 128, 128">
+		</colorDefinition>
+		<colorDefinition
+			id="tagName"
+			isEditable="false"
+			label="%Colors.tagName"
+			value="63, 127, 127">
+		</colorDefinition>
+		<colorDefinition
+			id="piBorder"
+			isEditable="false"
+			label="%Colors.piBorder"
+			value="0, 128, 128">
+		</colorDefinition>
+		<colorDefinition
+			id="cdataBorder"
+			isEditable="false"
+			label="%Colors.cdataBorder"
+			value="0, 128, 128">
+		</colorDefinition>
+		<colorDefinition
+			id="cdataText"
+			isEditable="false"
+			label="%Colors.cdataText"
+			value="0, 0, 0">
+		</colorDefinition>
+		<colorDefinition
+			id="entityReference"
+			isEditable="false"
+			label="%Colors.entityReference"
+			value="42, 0, 255">
+		</colorDefinition>
+	</extension>
+
+	<!-- Enable the FormatHandler for XML Content Type -->
+	<extension point="org.eclipse.ui.handlers">
+		<handler 
+			class="org.eclipse.wst.sse.ui.internal.handlers.FormatHandler"
+			commandId="org.eclipse.wst.sse.ui.format">
+			<activeWhen>
+				<reference definitionId="org.eclipse.wst.xml.ui.xmlContentType.definition"></reference>
+			</activeWhen>
+			<enabledWhen>
+				<reference definitionId="org.eclipse.wst.xml.ui.xmlContentType.definition"></reference>
+			</enabledWhen>
+		</handler>
+	</extension>
+	
+	<!-- Set up a definition for XML Content Types -->
+	<extension point="org.eclipse.core.expressions.definitions">
+		<definition id="org.eclipse.wst.xml.ui.xmlContentType.definition">
+			<or>
+            	<iterate ifEmpty="false">
+					<adapt type="org.eclipse.core.resources.IFile">
+						<!-- Force property tester to load, should not cause entire plug-in to start -->
+						<test property="org.eclipse.wst.sse.core.resources.contentTypeId" 
+							value="org.eclipse.wst.xml.core.xmlsource" forcePluginActivation="true"/>
+					</adapt>
+				</iterate>
+				<iterate ifEmpty="false">
+					<adapt type="org.eclipse.core.resources.IFile">
+						<!-- Force property tester to load, should not cause entire plug-in to start -->
+						<test property="org.eclipse.wst.sse.core.resources.contentTypeId"
+							value="org.eclipse.core.runtime.xml" forcePluginActivation="true"/>
+					</adapt>
+				</iterate>
+			</or>
+		</definition>
+	</extension>
+
+
+
+
+	<extension point="org.eclipse.ui.perspectives">
+		<perspective id="org.eclipse.wst.xml.ui.perspective"
+			class="org.eclipse.wst.xml.ui.internal.perspective.XMLPerspectiveFactory"
+			icon="$nl$/icons/full/xml_perspective.gif" 
+			name="%XML.name"/>
+	</extension>
+	
+ <extension point="org.eclipse.ui.perspectiveExtensions">
+	<perspectiveExtension targetID="org.eclipse.wst.xml.ui.perspective">
+		<!-- ProjectExplorer on the left -->
+		<!--<view id="org.eclipse.ui.navigator.ProjectExplorer" relative="org.eclipse.ui.editorss" relationship="left" ratio="0.23" />-->
+		<!-- XPath on the "bottom" left from its own UI plug-in since neither this bundle nor its owning feature require it -->
+		<!-- Content Outline on the right -->
+		<view id="org.eclipse.ui.views.ContentOutline" relative="org.eclipse.ui.editorss" relationship="right" ratio="0.7" />
+		<!-- Templates on the bottom right -->
+		<view id="org.eclipse.ui.texteditor.TemplatesView" relative="org.eclipse.ui.views.ContentOutline" relationship="bottom" ratio="0.6" />
+		<!-- everything else on the bottom -->
+		<view id="org.eclipse.ui.views.ProblemView" relative="org.eclipse.ui.editorss" relationship="bottom" ratio="0.6" />
+		<view id="org.eclipse.ui.views.PropertySheet" relative="org.eclipse.ui.views.ProblemView" relationship="stack"/>
+		<view id="org.eclipse.ui.console.ConsoleView" relative="org.eclipse.ui.views.ProblemView" relationship="stack" />
+		<view id="org.eclipse.wst.common.snippets.internal.ui.SnippetsView" relative="org.eclipse.ui.views.ProblemView" relationship="stack" />
+		<!-- view placeholders -->
+		<view id="org.eclipse.search.ui.views.SearchView" relative="org.eclipse.ui.views.ProblemView" relationship="stack" visible="false" />
+		<view id="org.eclipse.ui.views.ProgressView" relative="org.eclipse.ui.views.ProblemView" relationship="stack" visible="false" />
+
+		<actionSet id="org.eclipse.debug.ui.launchActionSet"/>
+	
+		<newWizardShortcut id="org.eclipse.wst.xml.ui.internal.wizards.NewXMLWizard"/>
+		<newWizardShortcut id="org.eclipse.wst.xsd.ui.internal.wizards.NewXSDWizard"/>
+		<newWizardShortcut id="org.eclipse.wst.dtd.ui.internal.wizard.NewDTDWizard"/>
+		<newWizardShortcut id="org.eclipse.ui.wizards.new.folder"/>
+		<newWizardShortcut id="org.eclipse.ui.wizards.new.file"/>
+		<newWizardShortcut id="org.eclipse.ui.editors.wizards.UntitledTextFileWizard"/>
+
+		<viewShortcut id="org.eclipse.ui.navigator.ProjectExplorer"/>
+		<viewShortcut id="org.eclipse.ui.views.ResourceNavigator"/>
+		<viewShortcut id="org.eclipse.ui.views.ContentOutline"/>
+		<viewShortcut id="org.eclipse.ui.views.PropertySheet"/>
+		<viewShortcut id="org.eclipse.ui.views.ProblemView"/>
+		<viewShortcut id="org.eclipse.ui.console.ConsoleView"/>
+		<viewShortcut id="org.eclipse.ui.views.TaskList"/>
+		<viewShortcut id="org.eclipse.ui.texteditor.TemplatesView"/>
+		<viewShortcut id="org.eclipse.search.ui.views.SearchView"/>
+		<viewShortcut id="org.eclipse.ui.views.ProgressView"/>
+
+		<perspectiveShortcut id="org.eclipse.debug.ui.DebugPerspective"/>
+		<perspectiveShortcut id="org.eclipse.ui.resourcePerspective"/>
+	</perspectiveExtension>
+	
+	<perspectiveExtension targetID="org.eclipse.ui.resourcePerspective">
+		<perspectiveShortcut id="org.eclipse.wst.xml.ui.perspective"/>
+	</perspectiveExtension>
+	<perspectiveExtension targetID="org.eclipse.debug.ui.DebugPerspective">
+		<perspectiveShortcut id="org.eclipse.wst.xml.ui.perspective"/>
+	</perspectiveExtension>
+ </extension>
+
+ <extension point="org.eclipse.ui.navigator.navigatorContent">
+	<commonWizard type="new" wizardId="org.eclipse.wst.xml.ui.internal.wizards.NewXMLWizard" menuGroupId="org.eclipse.wst.xml.new.menuGroup">
+		<enablement>
+			<instanceof value="org.eclipse.core.resources.IResource"/>
+			<with variable="activeWorkbenchWindow.activePerspective">
+			   <equals value="org.eclipse.wst.xml.ui.perspective"/>
+			</with>
+		</enablement>
+	</commonWizard>
+ </extension>
+
+ <extension point="org.eclipse.ui.menus" name="%XML.name" id="XML">
+	<menuContribution locationURI="toolbar:org.eclipse.ui.main.toolbar?after=additions">
+	 <toolbar id="org.eclipse.wst.xml.ui.perspective.NewFileToolBar">
+		<command
+				commandId="org.eclipse.ui.newWizard"
+				icon="$nl$/icons/full/etool16/new_xml.gif"
+				id="org.eclipse.wst.xml.ui.newXMLFile"
+				style="push"
+				tooltip="%XML_New_context_type_Extension_Element.name">
+			 <parameter name="newWizardId" value="org.eclipse.wst.xml.ui.internal.wizards.NewXMLWizard"/>
+          <visibleWhen checkEnabled="false">
+			<with variable="activeWorkbenchWindow.activePerspective">
+				<equals value="org.eclipse.wst.xml.ui.perspective"/>
+			</with>
+           </visibleWhen>         
+        </command>
+       <separator name="additions" visible="false"/>
+      </toolbar> 
+     </menuContribution>
+  </extension>
+ <extension
+       point="org.eclipse.wst.sse.ui.characterPairing">
+    <inserter
+          class="org.eclipse.wst.xml.ui.internal.text.CharacterPairInserter"
+          id="org.eclipse.wst.xml.ui.inserter">
+       <contentTypeIdentifier
+             id="org.eclipse.core.runtime.xml" partitions="org.eclipse.wst.xml.XML_DEFAULT,org.eclipse.wst.xml.XML_DECL">
+       </contentTypeIdentifier>
+       <contentTypeIdentifier
+             id="org.eclipse.wst.xml.core.xmlsource" partitions="org.eclipse.wst.xml.XML_DEFAULT,org.eclipse.wst.xml.XML_DECL">
+       </contentTypeIdentifier>
+    </inserter>
+ </extension>
+ <extension
+       point="org.eclipse.wst.sse.ui.commentingStrategy">
+    <blockCommentingStrategy
+          prefix="&lt;!--"
+          suffix="--&gt;">
+       <contentType
+             id="org.eclipse.core.runtime.xml"
+             associatedCommentPartitionTypeID="org.eclipse.wst.xml.XML_COMMENT">
+          <allowablePartitionTypes
+                anyPartitionType="true">
+          </allowablePartitionTypes>
+       </contentType>
+    </blockCommentingStrategy>
+ </extension>
+ <extension
+       point="org.eclipse.wst.sse.ui.completionProposal">
+    <proposalCategory
+          icon="icons/full/obj16/tag-generic.gif"
+          id="org.eclipse.wst.xml.ui.proposalCategory.xmlTags"
+          name="%proposalCategory.xmlTags">
+    </proposalCategory>
+    <proposalCategory
+          icon="icons/full/obj16/tag-macro.gif"
+          id="org.eclipse.wst.xml.ui.proposalCategory.xmlTemplates"
+          name="%proposalCategory.xmlTemplates">
+    </proposalCategory>
+    <proposalComputer
+          activate="false"
+          categoryId="org.eclipse.wst.xml.ui.proposalCategory.xmlTags"
+          class="org.eclipse.wst.xml.ui.internal.contentassist.XMLTagsCompletionProposalComputer"
+          id="org.eclipse.wst.xml.ui.proposalComputer.xmlTags">
+       <contentType
+             id="org.eclipse.core.runtime.xml">
+       </contentType>
+    </proposalComputer>
+    <proposalComputer
+          activate="false"
+          categoryId="org.eclipse.wst.xml.ui.proposalCategory.xmlTemplates"
+          class="org.eclipse.wst.xml.ui.internal.contentassist.XMLTemplatesCompletionProposalComputer"
+          id="org.eclipse.wst.xml.ui.proposalComputer.xmlTemplates">
+       <contentType
+             id="org.eclipse.core.runtime.xml">
+       </contentType>
+    </proposalComputer>
+ </extension>
+ <extension
+       point="org.eclipse.wst.sse.ui.completionProposalCategoriesConfiguration">
+    <categoriesConfiguration
+          class="org.eclipse.wst.xml.ui.internal.preferences.XMLCompletionProposalCategoriesConfiguration"
+          contentTypeID="org.eclipse.core.runtime.xml">
+    </categoriesConfiguration>
+ </extension>
+
+</plugin>
diff --git a/bundles/org.eclipse.wst.xml.ui/schema/catalogFileType.exsd b/bundles/org.eclipse.wst.xml.ui/schema/catalogFileType.exsd
new file mode 100644
index 0000000..3629659
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/schema/catalogFileType.exsd
@@ -0,0 +1,120 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.wst.xml.ui">
+<annotation>
+      <appInfo>
+         <meta.schema plugin="org.eclipse.wst.xml.ui" id="catalogFileType" name="XML Catalog file type extension point"/>
+      </appInfo>
+      <documentation>
+         &lt;b&gt;This extension point is internal and should not be used by any other plugins.&lt;/b&gt;
+      </documentation>
+   </annotation>
+
+   <element name="extension">
+      <complexType>
+         <sequence>
+            <element ref="fileType" minOccurs="1" maxOccurs="unbounded"/>
+         </sequence>
+         <attribute name="point" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="id" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="name" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+               <appInfo>
+                  <meta.attribute translatable="true"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <element name="fileType">
+      <complexType>
+         <attribute name="extensions" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="description" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="id" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="since"/>
+      </appInfo>
+      <documentation>
+         &lt;b&gt;This extension point is internal and should not be used by any other plugins.&lt;/b&gt;
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="examples"/>
+      </appInfo>
+      <documentation>
+         
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="apiInfo"/>
+      </appInfo>
+      <documentation>
+         
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="implementation"/>
+      </appInfo>
+      <documentation>
+         
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="copyright"/>
+      </appInfo>
+      <documentation>
+         Copyright (c) 2000, 2005 IBM Corporation and others.&lt;br&gt;
+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 &lt;a
+href=&quot;http://www.eclipse.org/legal/epl-v10.html&quot;&gt;http://www.eclipse.org/legal/epl-v10.html&lt;/a&gt;
+      </documentation>
+   </annotation>
+
+</schema>
diff --git a/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/AdvancedOptionsDialog.java b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/AdvancedOptionsDialog.java
new file mode 100644
index 0000000..ac1dec6
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/AdvancedOptionsDialog.java
@@ -0,0 +1,229 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.catalog;
+
+import java.io.ByteArrayInputStream;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.MultiStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.window.Window;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.dialogs.SaveAsDialog;
+import org.eclipse.wst.common.ui.internal.dialogs.SelectSingleFileDialog;
+import org.eclipse.wst.xml.core.internal.catalog.CatalogSet;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalog;
+import org.eclipse.wst.xml.ui.internal.XMLUIPlugin;
+
+public class AdvancedOptionsDialog extends Dialog {
+	protected ICatalog workingUserCatalog;
+
+	public AdvancedOptionsDialog(Shell parentShell, ICatalog workingUserCatalog) {
+		super(parentShell);
+		setShellStyle(getShellStyle() | SWT.RESIZE);
+		this.workingUserCatalog = workingUserCatalog;
+	}
+
+
+	protected void createButtonsForButtonBar(Composite parent) {
+		createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
+	}
+
+
+	protected Control createDialogArea(Composite parent) {
+		Composite dialogArea = (Composite) super.createDialogArea(parent);
+		// WorkbenchHelp.setHelp(dialogArea, new
+		// ControlContextComputer(dialogArea,
+		// XMLBuilderContextIds.XMLP_PROJECT_DIALOG));
+
+		Composite composite = new Composite(dialogArea, SWT.NONE);
+		composite.setLayout(new GridLayout());
+		composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+		Label label = new Label(composite, SWT.NONE);
+		label.setText(XMLCatalogMessages.UI_LABEL_DIALOG_DESCRIPTION);
+
+		Composite buttonComposite = new Composite(composite, SWT.NONE);
+		GridLayout gridLayout = new GridLayout();
+		gridLayout.numColumns = 3;
+		buttonComposite.setLayout(gridLayout);
+		buttonComposite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+		Composite placeHolder = new Composite(buttonComposite, SWT.NONE);
+		placeHolder.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+		Composite buttonGroup = new Composite(buttonComposite, SWT.NONE);
+		gridLayout = new GridLayout();
+		gridLayout.numColumns = 2;
+		gridLayout.makeColumnsEqualWidth = true;
+		buttonGroup.setLayout(gridLayout);
+		buttonGroup.setLayoutData(createGridData());
+
+		Button importButton = new Button(buttonGroup, SWT.PUSH | SWT.CENTER);
+		importButton.setText("  " + XMLCatalogMessages.UI_BUTTON_IMPORT + "  "); //$NON-NLS-1$ //$NON-NLS-2$
+
+		Button exportButton = new Button(buttonGroup, SWT.PUSH | SWT.CENTER);
+		exportButton.setText("  " + XMLCatalogMessages.UI_BUTTON_EXPORT + "  "); //$NON-NLS-1$ //$NON-NLS-2$
+
+		placeHolder = new Composite(buttonComposite, SWT.NONE);
+		placeHolder.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+		// add importButton listener
+		SelectionListener importButtonSelectionListener = new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				invokeImportDialog();
+			}
+		};
+		importButton.addSelectionListener(importButtonSelectionListener);
+
+		// add exportButton listener
+		SelectionListener exportButtonSelectionListener = new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				invokeExportDialog();
+			}
+		};
+		exportButton.addSelectionListener(exportButtonSelectionListener);
+
+		return dialogArea;
+	}
+
+	protected GridData createGridData() {
+		GridData gd = new GridData(GridData.CENTER);
+		gd.horizontalAlignment = GridData.HORIZONTAL_ALIGN_CENTER;
+		gd.verticalAlignment = GridData.VERTICAL_ALIGN_CENTER;
+		return gd;
+	}
+
+
+	protected void invokeImportDialog() {
+		SelectSingleFileDialog dialog = new SelectSingleFileDialog(getShell(), null, true);
+		String[] extensions = {".xmlcatalog", ".xml"}; //$NON-NLS-1$ //$NON-NLS-2$
+		dialog.addFilterExtensions(extensions);
+		dialog.create();
+		dialog.getShell().setText(XMLCatalogMessages.UI_LABEL_IMPORT_DIALOG_TITLE);
+		dialog.setTitle(XMLCatalogMessages.UI_LABEL_IMPORT_DIALOG_HEADING);
+		dialog.setMessage(XMLCatalogMessages.UI_LABEL_IMPORT_DIALOG_MESSAGE);
+		dialog.setBlockOnOpen(true);
+		int rc = dialog.open();
+		if (rc == Window.OK) {
+			IFile file = dialog.getFile();
+			if (file != null) {
+				String fileName = file.getLocation().toFile().toURI().toString();
+				try {
+					CatalogSet tempResourceSet = new CatalogSet();
+					ICatalog newCatalog = tempResourceSet.lookupOrCreateCatalog("temp", fileName); //$NON-NLS-1$
+					workingUserCatalog.addEntriesFromCatalog(newCatalog);
+				}
+				catch (Exception e) {
+					// TODO... give error message
+				}
+			}
+			close();
+		}
+	}
+
+
+	protected void invokeExportDialog() {
+		IPath originalFilePath = null;
+		IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
+		if (projects.length > 0) {
+			originalFilePath = projects[0].getFullPath().append(".xmlcatalog"); //$NON-NLS-1$
+		}
+
+		SaveAsDialog dialog = new SaveAsDialog(getShell());
+		if (originalFilePath != null) {
+			IFile originalFile = ResourcesPlugin.getWorkspace().getRoot().getFile(originalFilePath);
+			dialog.setOriginalFile(originalFile);
+		}
+		dialog.create();
+
+		dialog.getShell().setText(XMLCatalogMessages.UI_LABEL_EXPORT_DIALOG_TITLE);
+		dialog.setTitle(XMLCatalogMessages.UI_LABEL_EXPORT_DIALOG_HEADING);
+		dialog.setMessage(XMLCatalogMessages.UI_LABEL_EXPORT_DIALOG_MESSAGE);
+
+		dialog.setBlockOnOpen(true);
+		int rc = dialog.open();
+		if (rc == Window.OK) {
+			IPath path = dialog.getResult();
+			if (path != null) {
+				IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(path);
+				String fileName = file.getLocation().toFile().toURI().toString();
+
+				// here we save the catalog entries to the selected file
+				try {
+					createFileIfRequired(file);
+					workingUserCatalog.setLocation(fileName);
+					workingUserCatalog.save();
+				}
+				catch (Exception ex) {
+					try {
+						String title = XMLCatalogMessages.UI_LABEL_CATALOG_SAVE_ERROR;
+						String briefMessage = XMLCatalogMessages.UI_LABEL_CATALOG_COULD_NOT_BE_SAVED;
+						String reason = file.isReadOnly() ? NLS.bind(XMLCatalogMessages.UI_LABEL_FILE_IS_READ_ONLY, fileName) : NLS.bind(XMLCatalogMessages.ERROR_SAVING_FILE, fileName);
+						String details = NLS.bind(XMLCatalogMessages.ERROR_SAVING_FILE, fileName);
+
+						ErrorDialog.openError(Display.getCurrent().getActiveShell(), title, briefMessage, createStatus(reason, details));
+					}
+					catch (Exception ex2) {
+					}
+				}
+				close();
+			}
+		}
+	}
+
+	// TODO... This was copied from WindowUtility. Is there an easier way to
+	// create a status object?
+	// If not, we should open an eclipse bug or add a similar utility to
+	// baseExtensionsUI.
+	//
+	private static IStatus createStatus(String reason, String msg) {
+		String pluginId = XMLUIPlugin.getDefault().getBundle().getSymbolicName();
+		MultiStatus multiStatus = new MultiStatus(pluginId, 0, reason, null);
+		Status status = new Status(IStatus.ERROR, pluginId, 0, msg, null);
+		multiStatus.add(status);
+		return multiStatus;
+	}
+
+
+	protected void createFileIfRequired(IFile file) {
+		try {
+			if ((file != null) && !file.exists()) {
+				ByteArrayInputStream inputStream = new ByteArrayInputStream(new byte[0]);
+				file.create(inputStream, true, null);
+				// createEmptyXMLCatalog(file);
+			}
+		}
+		catch (Exception e) {
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/CatalogFileTypeRegistryReader.java b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/CatalogFileTypeRegistryReader.java
new file mode 100644
index 0000000..85b57d3
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/CatalogFileTypeRegistryReader.java
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.catalog;
+
+import java.util.Collection;
+import java.util.HashMap;
+
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtensionPoint;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.wst.xml.ui.internal.XMLUIPlugin;
+
+public class CatalogFileTypeRegistryReader {
+	private static CatalogFileTypeRegistryReader _instance;
+
+	static final String ATT_DESCRIPTION = "description"; //$NON-NLS-1$
+
+	static final String ATT_EXTENSIONS = "extensions"; //$NON-NLS-1$
+
+	static final String ATT_ICON = "icon"; //$NON-NLS-1$
+
+	static final String ATT_ID = "id"; //$NON-NLS-1$
+
+	static final String EXTENSION_POINT_ID = "catalogFileType"; //$NON-NLS-1$
+
+	static final String TAG_NAME = "fileType"; //$NON-NLS-1$
+
+	private static CatalogFileTypeRegistryReader getInstance() {
+		if (_instance == null) {
+			_instance = new CatalogFileTypeRegistryReader();
+		}
+		return _instance;
+	}
+
+	public static Collection getXMLCatalogFileTypes() {
+		return getInstance().hashMap.values();
+	}
+
+	private HashMap hashMap;
+
+	public CatalogFileTypeRegistryReader() {
+		this.hashMap = new HashMap();
+		readRegistry();
+	}
+
+	private void readElement(IConfigurationElement element) {
+		if (element.getName().equals(TAG_NAME)) {
+			String id = element.getAttribute(ATT_ID);
+			if (id != null) {
+				XMLCatalogFileType fileType = (XMLCatalogFileType) hashMap.get(id);
+				if (fileType == null) {
+					fileType = new XMLCatalogFileType();
+					hashMap.put(id, fileType);
+				}
+				fileType.id = id;
+				if (fileType.description == null) {
+					String description = element.getAttribute(ATT_DESCRIPTION);
+					fileType.description = description;
+				}
+
+				fileType.addExtensions(element.getAttribute(ATT_EXTENSIONS));
+			}
+		}
+	}
+
+	private void readRegistry() {
+		readRegistry(EXTENSION_POINT_ID);
+	}
+
+	private void readRegistry(String extensionPointId) {
+		IExtensionRegistry pluginRegistry = Platform.getExtensionRegistry();
+		IExtensionPoint point = pluginRegistry.getExtensionPoint(XMLUIPlugin.ID, extensionPointId);
+		if (point != null) {
+			IConfigurationElement[] elements = point.getConfigurationElements();
+			for (int i = 0; i < elements.length; i++) {
+				readElement(elements[i]);
+			}
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/EditCatalogEntryDialog.java b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/EditCatalogEntryDialog.java
new file mode 100644
index 0000000..578e8a8
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/EditCatalogEntryDialog.java
@@ -0,0 +1,1816 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.catalog;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.layout.FormAttachment;
+import org.eclipse.swt.layout.FormData;
+import org.eclipse.swt.layout.FormLayout;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.FileDialog;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.swt.widgets.ToolBar;
+import org.eclipse.swt.widgets.ToolItem;
+import org.eclipse.swt.widgets.Widget;
+import org.eclipse.ui.part.PageBook;
+import org.eclipse.wst.common.ui.internal.dialogs.SelectSingleFileDialog;
+import org.eclipse.wst.common.uriresolver.internal.URI;
+import org.eclipse.wst.common.uriresolver.internal.util.URIHelper;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalog;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalogElement;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalogEntry;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.IDelegateCatalog;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.INextCatalog;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.IRewriteEntry;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ISuffixEntry;
+
+public class EditCatalogEntryDialog extends Dialog {
+	protected static Image borwseImage = ImageFactory.INSTANCE.getImage("icons/obj16/file_expand.gif"); //$NON-NLS-1$
+	protected static Image catalogEntryToolBarImage = ImageFactory.INSTANCE.getImage("icons/etool50/catalogEntry.gif"); //$NON-NLS-1$
+	protected static Image nextCatalogToolBarImage = ImageFactory.INSTANCE.getImage("icons/etool50/nextCatalog.gif"); //$NON-NLS-1$
+	protected static Image delegateCatalogToolBarImage = ImageFactory.INSTANCE.getImage("icons/etool50/delegateCatalog.gif"); //$NON-NLS-1$
+	protected static Image rewriteToolBarImage = ImageFactory.INSTANCE.getImage("icons/etool50/rewrite.gif"); //$NON-NLS-1$
+	protected static Image prefixToolBarImage = ImageFactory.INSTANCE.getImage("icons/etool50/prefix.gif"); //$NON-NLS-1$
+	protected static Image suffixToolBarImage = ImageFactory.INSTANCE.getImage("icons/etool50/sufix.gif"); //$NON-NLS-1$
+	
+	protected class CatalogEntryPage extends CatalogElementPage {
+
+		protected Button browseWorkspaceButton;
+		
+		protected Button browseFileSystemButton;
+
+		protected ICatalogEntry catalogEntry;
+
+		protected Button checkboxButton;
+
+		protected Label errorMessageLabel;
+
+		protected Text keyField;
+
+		protected Combo keyTypeCombo;
+
+		protected Text resourceLocationField;
+
+		protected Combo resourceTypeCombo;
+
+		protected Text webAddressField;
+		
+		protected String key;
+		
+		protected int type;
+		
+		public void refresh() {
+			computeErrorMessage();
+			updateErrorMessageLabel(errorMessageLabel);
+			updateOKButtonState();
+		}
+
+		protected void computeErrorMessage() {
+			errorMessage = null;
+			warningMessage = null;
+
+			String fileName = resourceLocationField.getText();
+			if (fileName.trim().length() > 0) {
+				if ((fileName.indexOf("..") != -1) || (fileName.indexOf("./") != -1) || (fileName.indexOf("/.") != -1) || (fileName.indexOf(".\\") != -1) || (fileName.indexOf("\\.") != -1)) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
+					errorMessage = XMLCatalogMessages.UI_WARNING_URI_MUST_NOT_HAVE_DOTS;
+				}
+
+				String uri = fileName;
+				if (!URIHelper.hasProtocol(uri)) {
+					URIHelper.isAbsolute(uri);
+					uri = (URIHelper.isAbsolute(uri)) ? URIHelper.prependFileProtocol(uri) : URIHelper.prependPlatformResourceProtocol(uri);
+				}
+
+				if ((errorMessage == null) && !URIHelper.isReadableURI(uri, false)) {
+					errorMessage = XMLCatalogMessages.UI_WARNING_URI_NOT_FOUND_COLON + fileName;
+				}
+			}
+			else {
+				// this an error that is not actaully
+				// reported ... OK is just disabled
+				errorMessage = ""; //$NON-NLS-1$
+			}
+
+			// Make sure the key is a fully qualified URI in the cases
+			// where the key type is "System ID" or "Schema location"
+			if ((keyField.getText().length() > 0) && (getKeyType() == ICatalogEntry.ENTRY_TYPE_SYSTEM)) {
+				URI uri = URI.createURI(keyField.getText());
+				if (uri.scheme() == null) {
+					warningMessage = XMLCatalogMessages.UI_WARNING_SHOULD_BE_FULLY_QUALIFIED_URI;
+				}
+			}
+
+			if ((errorMessage == null) && checkboxButton.getSelection() && (webAddressField.getText().trim().length() == 0)) {
+				// this an error that is not actaully
+				// reported ... OK is just disabled
+				errorMessage = ""; //$NON-NLS-1$
+			}
+
+			if ((errorMessage == null) && (keyField.getText().trim().length() == 0)) {
+				// this an error that is not actaully
+				// reported ... OK is just disabled
+				errorMessage = ""; //$NON-NLS-1$
+			}
+		}
+
+		protected Control createCatalogEntryPanel(Composite parent) {
+
+			ModifyListener modifyListener = new ModifyListener() {
+				public void modifyText(ModifyEvent e) {
+					if (e.widget == resourceLocationField) {
+						if (keyField.getText().length() == 0) {
+							String uri = resourceLocationField.getText();
+							if (uri.endsWith("xsd") && !URIHelper.hasProtocol(uri)) { //$NON-NLS-1$
+								uri = URIHelper.isAbsolute(uri) ? URIHelper.prependFileProtocol(uri) : URIHelper.prependPlatformResourceProtocol(uri);
+								String namespaceURI = XMLQuickScan.getTargetNamespaceURIForSchema(uri);
+								if (namespaceURI != null) {
+									keyField.setText(namespaceURI);
+								}
+							}
+						}
+					}
+					updateWidgets(e.widget);
+				}
+			};
+
+
+			Composite composite = new Composite(parent, SWT.NONE);
+			GridData gd = new GridData(GridData.FILL_BOTH);
+			composite.setLayoutData(gd);
+
+			GridLayout layout = new GridLayout();
+			composite.setLayout(layout);
+
+			Composite group = new Composite(composite, SWT.NONE);
+			gd = new GridData(GridData.FILL_HORIZONTAL);
+			group.setLayoutData(gd);
+
+			layout = new GridLayout(2, false);
+			group.setLayout(layout);
+
+			Label resourceLocationLabel = new Label(group, SWT.NONE);
+			resourceLocationLabel.setText(XMLCatalogMessages.UI_LABEL_LOCATION_COLON);
+
+			resourceLocationField = new Text(group, SWT.SINGLE | SWT.BORDER);
+			gd = new GridData();
+			gd.horizontalAlignment = SWT.FILL;
+			gd.grabExcessHorizontalSpace = true;
+			resourceLocationField.setLayoutData(gd);
+
+			resourceLocationField.setText(getDisplayValue(URIUtils.convertURIToLocation(getEntry().getURI())));
+
+			// WorkbenchHelp.setHelp(resourceLocationField,
+			// XMLBuilderContextIds.XMLP_ENTRY_URI);
+			resourceLocationField.addModifyListener(modifyListener);
+
+			// WorkbenchHelp.setHelp(browseButton,
+			// XMLBuilderContextIds.XMLP_ENTRY_BROWSE);
+
+			Composite browseButtonsComposite = new Composite(group, SWT.NONE);
+			gd = new GridData(GridData.FILL_HORIZONTAL);
+			gd.horizontalSpan = 2;
+			gd.horizontalAlignment = GridData.END;
+			browseButtonsComposite.setLayoutData(gd);
+			
+			layout = new GridLayout();
+			layout.numColumns = 2;
+			layout.marginWidth = 0;
+			layout.marginHeight = 0;
+			layout.marginBottom = 5;
+			browseButtonsComposite.setLayout(layout);
+			
+			browseWorkspaceButton = new Button(browseButtonsComposite, SWT.PUSH);
+			browseWorkspaceButton.setText(XMLCatalogMessages.UI_BUTTON_MENU_BROWSE_WORKSPACE);
+			browseWorkspaceButton.addSelectionListener(new SelectionListener(){
+
+				public void widgetDefaultSelected(SelectionEvent e) {
+				}
+
+				public void widgetSelected(SelectionEvent e) {
+					String value = invokeWorkspaceFileSelectionDialog();
+					if(value != null) {
+						resourceLocationField.setText(value);
+					}
+				}
+			});
+			
+			browseFileSystemButton = new Button(browseButtonsComposite, SWT.PUSH);
+			browseFileSystemButton.setText(XMLCatalogMessages.UI_BUTTON_MENU_BROWSE_FILE_SYSTEM);
+			browseFileSystemButton.addSelectionListener(new SelectionListener(){
+
+				public void widgetDefaultSelected(SelectionEvent e) {
+				}
+
+				public void widgetSelected(SelectionEvent e) {
+					String value = invokeFileSelectionDialog();
+					if(value != null) {
+						resourceLocationField.setText(value);
+					}
+				}
+			});
+			
+			// Key Type
+			//
+			Label keyTypeLabel = new Label(group, SWT.NONE);
+			keyTypeLabel.setText(XMLCatalogMessages.UI_KEY_TYPE_COLON);
+
+			keyTypeCombo = new Combo(group, SWT.READ_ONLY);
+			gd = new GridData();
+			gd.horizontalAlignment = SWT.FILL;
+			gd.grabExcessHorizontalSpace = true;
+			keyTypeCombo.setLayoutData(gd);
+			updateKeyTypeCombo(getEntry().getEntryType());
+			keyTypeCombo.addModifyListener(modifyListener);
+			// WorkbenchHelp.setHelp(keyTypeCombo,
+			// XMLBuilderContextIds.XMLP_ENTRY_KEY_TYPE);
+
+			// Key
+			// 
+			Label keyValueLabel = new Label(group, SWT.NONE);
+			keyValueLabel.setText(XMLCatalogMessages.UI_LABEL_KEY_COLON);
+			keyField = new Text(group, SWT.SINGLE | SWT.BORDER);
+			// WorkbenchHelp.setHelp(keyField,
+			// XMLBuilderContextIds.XMLP_ENTRY_KEY);
+			keyField.setLayoutData(gd);
+			keyField.setText(getDisplayValue(getEntry().getKey()));
+			keyField.addModifyListener(modifyListener);
+
+			Composite group2 = new Composite(composite, SWT.NONE);
+			gd = new GridData(GridData.FILL_HORIZONTAL);
+			group2.setLayoutData(gd);
+
+			layout = new GridLayout();
+			group2.setLayout(layout);
+
+			// checkbox -- note parent is dialogArea
+			//
+			checkboxButton = new Button(group2, SWT.CHECK);
+			// WorkbenchHelp.setHelp(checkboxButton,
+			// XMLBuilderContextIds.XMLP_ENTRY_SPECIFY_ALTERNATIVE);
+			checkboxButton.setText(XMLCatalogMessages.UI_LABEL_SPECIFY_ALTERNATIVE_WEB_URL);
+			checkboxButton.setLayoutData(new GridData());
+			checkboxButton.setSelection(getEntry().getAttributeValue(ICatalogEntry.ATTR_WEB_URL) != null);
+			SelectionListener buttonListener = new SelectionListener() {
+				public void widgetDefaultSelected(SelectionEvent event) {
+					// no impl
+				}
+
+				public void widgetSelected(SelectionEvent event) {
+					if (event.widget == checkboxButton) {
+						updateWidgets(checkboxButton);
+					}
+				}
+			};
+			checkboxButton.addSelectionListener(buttonListener);
+
+			// Web Address field
+			//
+
+			ModifyListener webAddressFieldListener = new ModifyListener() {
+				public void modifyText(ModifyEvent e) {
+					computeErrorMessage();
+					updateErrorMessageLabel(errorMessageLabel);
+					updateOKButtonState();
+				}
+			};
+
+			webAddressField = new Text(group2, SWT.SINGLE | SWT.BORDER);
+			// WorkbenchHelp.setHelp(webAddressField,
+			// XMLBuilderContextIds.XMLP_ENTRY_WEB_ADDRESS);
+			webAddressField.setLayoutData(gd);
+			webAddressField.setText(getDisplayValue(getEntry().getAttributeValue(ICatalogEntry.ATTR_WEB_URL)));
+			webAddressField.setEnabled(false);
+			webAddressField.addModifyListener(webAddressFieldListener);
+
+
+			errorMessageLabel = new Label(group2, SWT.NONE);
+			errorMessageLabel.setForeground(color);
+			errorMessageLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+			updateWidgets(null);
+			
+			key = getEntry().getKey();
+			type = getEntry().getEntryType();
+
+			return composite;
+		}
+
+		public Control createControl(Composite parent) {
+
+			fControl = createCatalogEntryPanel(parent);
+
+			return fControl;
+		}
+
+
+		public ICatalogElement getData() {
+			return getEntry();
+		}
+
+		protected ICatalogEntry getEntry() {
+			if (catalogEntry == null) {
+				if ((fCatalogElement != null) && (fCatalogElement.getType() == ICatalogElement.TYPE_ENTRY)) {
+					catalogEntry = (ICatalogEntry) fCatalogElement;
+				}
+				else {
+					if (catalog != null) {
+						catalogEntry = (ICatalogEntry) catalog.createCatalogElement(ICatalogElement.TYPE_ENTRY);
+					}
+				}
+			}
+			return catalogEntry;
+		}
+
+		protected int getKeyType() {
+			switch (keyTypeCombo.getSelectionIndex()) {
+				case 0 :
+					if ("schema".equals(keyTypeCombo.getData("keyType"))) { //$NON-NLS-1$ //$NON-NLS-2$
+						return ICatalogEntry.ENTRY_TYPE_URI; // xsd
+																// namespace
+																// is URI type
+																// key
+					}
+					return ICatalogEntry.ENTRY_TYPE_PUBLIC;
+				case 1 :
+					return ICatalogEntry.ENTRY_TYPE_SYSTEM;
+				case 2 :
+					return ICatalogEntry.ENTRY_TYPE_URI;
+				default :
+					return ICatalogEntry.ENTRY_TYPE_PUBLIC;
+			}
+		}
+
+		public void saveData() {
+			if (validateData()) {
+				getEntry().setURI(URIUtils.convertLocationToURI(resourceLocationField.getText()));
+				getEntry().setKey(keyField.getText());
+				getEntry().setEntryType(getKeyType());
+				getEntry().setAttributeValue(ICatalogEntry.ATTR_WEB_URL, checkboxButton.getSelection() ? webAddressField.getText() : null);
+				dataSaved = true;
+			}
+			else {
+				errorMessage = XMLCatalogMessages.UI_WARNING_DUPLICATE_ENTRY;
+				errorMessageLabel.setText(errorMessage);
+				updateOKButtonState();
+				dataSaved = false;
+			}
+		}
+		
+		/**
+		 * Validates that the data entered does not conflict with an existing entry in either catalog.
+		 * @return True if validated, false otherwise.
+		 */
+		protected boolean validateData() {
+		
+			String result = null;
+			if (key == null || !key.equals(keyField.getText()) || type != getKeyType())
+			{
+				try {
+					switch( getKeyType() )
+					{
+					case ICatalogEntry.ENTRY_TYPE_PUBLIC:
+						result = catalog.resolvePublic(keyField.getText(), null);		
+						break;
+					case ICatalogEntry.ENTRY_TYPE_SYSTEM:
+						result = catalog.resolveSystem(keyField.getText());
+						break;
+					case ICatalogEntry.ENTRY_TYPE_URI:
+						result = catalog.resolveURI(keyField.getText());
+						break;
+					}
+				}
+				catch (Exception e) {
+				}
+			}
+			
+			return (result == null);
+		}
+
+		protected void updateKeyTypeCombo(int type) {
+			keyTypeCombo.removeAll();
+			for (Iterator i = CatalogFileTypeRegistryReader.getXMLCatalogFileTypes().iterator(); i.hasNext();) {
+				XMLCatalogFileType theFileType = (XMLCatalogFileType) i.next();
+				if (theFileType.extensions != null) {
+					for (Iterator j = theFileType.extensions.iterator(); j.hasNext();) {
+						String extension = (String) j.next();
+						if (resourceLocationField.getText().endsWith(extension)) {
+							if ("org.eclipse.wst.xml.core.ui.catalogFileType.xsd".equals(theFileType.id)) { //$NON-NLS-1$
+								keyTypeCombo.add(XMLCatalogMessages.UI_KEY_TYPE_DESCRIPTION_XSD_PUBLIC);
+								keyTypeCombo.add(XMLCatalogMessages.UI_KEY_TYPE_DESCRIPTION_XSD_SYSTEM);
+								keyTypeCombo.setData("keyType", "schema"); //$NON-NLS-1$ //$NON-NLS-2$
+							}
+							else if ("org.eclipse.wst.xml.core.ui.catalogFileType.dtd".equals(theFileType.id)) { //$NON-NLS-1$
+								keyTypeCombo.add(XMLCatalogMessages.UI_KEY_TYPE_DESCRIPTION_DTD_PUBLIC);
+								keyTypeCombo.add(XMLCatalogMessages.UI_KEY_TYPE_DESCRIPTION_DTD_SYSTEM);
+								keyTypeCombo.add(XMLCatalogMessages.UI_KEY_TYPE_DESCRIPTION_URI);
+							}
+							else {
+								keyTypeCombo.add(XMLCatalogMessages.UI_KEY_TYPE_DESCRIPTION_URI);
+							}
+						}
+
+					}
+
+				}
+			}
+			if (keyTypeCombo.getItemCount() == 0) {
+				keyTypeCombo.add(XMLCatalogMessages.UI_KEY_TYPE_DESCRIPTION_DTD_PUBLIC);
+				keyTypeCombo.add(XMLCatalogMessages.UI_KEY_TYPE_DESCRIPTION_DTD_SYSTEM);
+				keyTypeCombo.add(XMLCatalogMessages.UI_KEY_TYPE_DESCRIPTION_URI);
+			}
+
+			switch (type) {
+				case ICatalogEntry.ENTRY_TYPE_PUBLIC :
+					keyTypeCombo.select(0);
+					break;
+				case ICatalogEntry.ENTRY_TYPE_SYSTEM :
+					keyTypeCombo.select(1);
+					break;
+				case ICatalogEntry.ENTRY_TYPE_URI : // handle XML Schema,
+													// where namespace name is
+													// mapped to URI situation
+					if ("schema".equals(keyTypeCombo.getData("keyType"))) { //$NON-NLS-1$ //$NON-NLS-2$
+						keyTypeCombo.select(0); // namespace name as URI key
+												// type
+					}
+					else {
+						keyTypeCombo.select(2); // URI key type
+					}
+					break;
+				default :
+					if (keyTypeCombo.getItemCount() > 0) {
+						keyTypeCombo.select(0);
+					}
+					break;
+			}
+
+		}
+
+		protected void updateWebAddressWidgets(int keyType) {
+			boolean isPublicKeyType = (keyType == ICatalogEntry.ENTRY_TYPE_PUBLIC);
+			checkboxButton.setEnabled(isPublicKeyType);
+			webAddressField.setEnabled(isPublicKeyType && checkboxButton.getSelection());
+		}
+
+		protected void updateWidgets(Widget widget) {
+			if (widget != keyTypeCombo) {
+				updateKeyTypeCombo(getKeyType());
+			}
+			updateWebAddressWidgets(getKeyType());
+			computeErrorMessage();
+			updateErrorMessageLabel(errorMessageLabel);
+			updateOKButtonState();
+		}
+
+	}
+
+	protected class SuffixEntryPage extends CatalogElementPage {
+	
+		protected Button browseWorkspaceButton;
+		
+		protected Button browseFileSystemButton;
+	
+		protected ISuffixEntry catalogEntry;
+	
+		protected Label errorMessageLabel;
+	
+		protected Text suffixField;
+	
+		protected Combo keyTypeCombo;
+	
+		protected Text resourceLocationField;
+	
+		protected Combo resourceTypeCombo;
+
+		protected String key;
+		
+		protected int type;
+		
+		public void refresh() {
+			computeErrorMessage();
+			updateErrorMessageLabel(errorMessageLabel);
+			updateOKButtonState();
+		}
+	
+		protected void computeErrorMessage() {
+			errorMessage = null;
+			warningMessage = null;
+	
+			String fileName = resourceLocationField.getText();
+			if (fileName.trim().length() > 0) {
+				if ((fileName.indexOf("..") != -1) || (fileName.indexOf("./") != -1) || (fileName.indexOf("/.") != -1) || (fileName.indexOf(".\\") != -1) || (fileName.indexOf("\\.") != -1)) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
+					errorMessage = XMLCatalogMessages.UI_WARNING_URI_MUST_NOT_HAVE_DOTS;
+				}
+
+				String uri = fileName;
+				if (!URIHelper.hasProtocol(uri)) {
+					URIHelper.isAbsolute(uri);
+					uri = (URIHelper.isAbsolute(uri)) ? URIHelper.prependFileProtocol(uri) : URIHelper.prependPlatformResourceProtocol(uri);
+				}
+
+				if ((errorMessage == null) && !URIHelper.isReadableURI(uri, false)) {
+					errorMessage = XMLCatalogMessages.UI_WARNING_URI_NOT_FOUND_COLON + fileName;
+				}
+			}
+			else {
+				// this an error that is not actaully
+				// reported ... OK is just disabled
+				errorMessage = ""; //$NON-NLS-1$
+			}
+
+	
+			if ((errorMessage == null) && (suffixField.getText().trim().length() == 0)) {
+				// this an error that is not actaully
+				// reported ... OK is just disabled
+				errorMessage = ""; //$NON-NLS-1$
+			}
+		}
+	
+		protected Control createSuffixEntryPanel(Composite parent) {
+	
+			ModifyListener modifyListener = new ModifyListener() {
+				public void modifyText(ModifyEvent e) {
+					if (e.widget == resourceLocationField) {
+						if (suffixField.getText().length() == 0) {
+							String uri = resourceLocationField.getText();
+							if (uri.endsWith("xsd") && !URIHelper.hasProtocol(uri)) { //$NON-NLS-1$
+								uri = URIHelper.isAbsolute(uri) ? URIHelper.prependFileProtocol(uri) : URIHelper.prependPlatformResourceProtocol(uri);
+								String namespaceURI = XMLQuickScan.getTargetNamespaceURIForSchema(uri);
+								if (namespaceURI != null) {
+									suffixField.setText(namespaceURI);
+								}
+							}
+						}
+					}
+					updateWidgets(e.widget);
+				}
+			};
+	
+			Composite composite = new Composite(parent, SWT.NONE);
+			GridData gd = new GridData(GridData.FILL_BOTH);
+			composite.setLayoutData(gd);
+	
+			GridLayout layout = new GridLayout();
+			composite.setLayout(layout);
+	
+			Composite group = new Composite(composite, SWT.NONE);
+			gd = new GridData(GridData.FILL_HORIZONTAL);
+			group.setLayoutData(gd);
+	
+			layout = new GridLayout(2, false);
+			group.setLayout(layout);
+	
+			Label resourceLocationLabel = new Label(group, SWT.NONE);
+			resourceLocationLabel.setText(XMLCatalogMessages.UI_LABEL_LOCATION_COLON);
+	
+			resourceLocationField = new Text(group, SWT.SINGLE | SWT.BORDER);
+			gd = new GridData();
+			gd.horizontalAlignment = SWT.FILL;
+			gd.grabExcessHorizontalSpace = true;
+			resourceLocationField.setLayoutData(gd);
+	
+			resourceLocationField.setText(getDisplayValue(URIUtils.convertURIToLocation(getEntry().getURI())));
+			resourceLocationField.addModifyListener(modifyListener);
+		
+			Composite browseButtonsComposite = new Composite(group, SWT.NONE);
+			gd = new GridData(GridData.FILL_HORIZONTAL);
+			gd.horizontalSpan = 2;
+			gd.horizontalAlignment = GridData.END;
+			browseButtonsComposite.setLayoutData(gd);
+			
+			layout = new GridLayout();
+			layout.numColumns = 2;
+			layout.marginWidth = 0;
+			layout.marginHeight = 0;
+			layout.marginBottom = 5;
+			browseButtonsComposite.setLayout(layout);
+			
+			browseWorkspaceButton = new Button(browseButtonsComposite, SWT.PUSH);
+			browseWorkspaceButton.setText(XMLCatalogMessages.UI_BUTTON_MENU_BROWSE_WORKSPACE);
+			browseWorkspaceButton.addSelectionListener(new SelectionListener(){
+	
+				public void widgetDefaultSelected(SelectionEvent e) {
+				}
+	
+				public void widgetSelected(SelectionEvent e) {
+					String value = invokeWorkspaceFileSelectionDialog();
+					if(value != null) {
+						resourceLocationField.setText(value);
+					}
+				}
+			});
+			
+			browseFileSystemButton = new Button(browseButtonsComposite, SWT.PUSH);
+			browseFileSystemButton.setText(XMLCatalogMessages.UI_BUTTON_MENU_BROWSE_FILE_SYSTEM);
+			browseFileSystemButton.addSelectionListener(new SelectionListener(){
+	
+				public void widgetDefaultSelected(SelectionEvent e) {
+				}
+	
+				public void widgetSelected(SelectionEvent e) {
+					String value = invokeFileSelectionDialog();
+					if(value != null) {
+						resourceLocationField.setText(value);
+					}
+				}
+			});
+			
+			// Key Type
+			//
+			Label keyTypeLabel = new Label(group, SWT.NONE);
+			keyTypeLabel.setText(XMLCatalogMessages.UI_KEY_TYPE_COLON);
+	
+			keyTypeCombo = new Combo(group, SWT.READ_ONLY);
+			gd = new GridData();
+			gd.horizontalAlignment = SWT.FILL;
+			gd.grabExcessHorizontalSpace = true;
+			keyTypeCombo.setLayoutData(gd);
+			updateKeyTypeCombo(getEntry().getEntryType());
+			keyTypeCombo.addModifyListener(modifyListener);
+	
+			// Suffix
+			// 
+			Label suffixValueLabel = new Label(group, SWT.NONE);
+			suffixValueLabel.setText(XMLCatalogMessages.UI_LABEL_SUFFIX_COLON);
+			suffixField = new Text(group, SWT.SINGLE | SWT.BORDER);
+
+			suffixField.setLayoutData(gd);
+			suffixField.setText(getDisplayValue(getEntry().getSuffix()));
+			suffixField.addModifyListener(modifyListener);
+		
+			errorMessageLabel = new Label(composite, SWT.NONE);
+			errorMessageLabel.setForeground(color);
+			errorMessageLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+	
+			updateWidgets(null);
+			
+			key = getEntry().getSuffix();
+			type = getEntry().getEntryType();
+	
+			return composite;
+		}
+	
+		public Control createControl(Composite parent) {
+	
+			fControl = createSuffixEntryPanel(parent);
+	
+			return fControl;
+		}
+	
+	
+		public ICatalogElement getData() {
+			return getEntry();
+		}
+	
+		protected ISuffixEntry getEntry() {
+			if (catalogEntry == null) {
+				if ((fCatalogElement != null) && (fCatalogElement.getType() == ICatalogElement.TYPE_SUFFIX)) {
+					catalogEntry = (ISuffixEntry) fCatalogElement;
+				}
+				else {
+					if (catalog != null) {
+						catalogEntry = (ISuffixEntry) catalog.createCatalogElement(ICatalogElement.TYPE_SUFFIX);
+					}
+				}
+			}
+			return catalogEntry;
+		}
+	
+		protected int getKeyType() {
+			switch (keyTypeCombo.getSelectionIndex()) {
+				case 0 :
+					return ISuffixEntry.SUFFIX_TYPE_URI; // xsd namespace is URI type key
+				case 1 :
+					return ISuffixEntry.SUFFIX_TYPE_SYSTEM;
+				default :
+					return ISuffixEntry.SUFFIX_TYPE_URI;
+			}
+		}
+	
+		public void saveData() {
+			if (validateData()) {
+				getEntry().setURI(URIUtils.convertLocationToURI(resourceLocationField.getText()));
+				getEntry().setSuffix(suffixField.getText());
+				getEntry().setEntryType(getKeyType());
+				dataSaved = true;
+			}
+			else {
+				errorMessage = XMLCatalogMessages.UI_WARNING_DUPLICATE_SUFFIX;
+				errorMessageLabel.setText(errorMessage);
+				updateOKButtonState();
+				dataSaved = false;
+			}
+		}
+		
+		protected boolean validateData() {
+			ISuffixEntry entry = getEntry();
+			String uri = URIUtils.convertLocationToURI(resourceLocationField.getText());
+			if(entry.getEntryType() != getKeyType() || !entry.getSuffix().equals(suffixField.getText()) || !entry.getURI().equals(uri)) {
+				ISuffixEntry[] entries = catalog.getSuffixEntries();
+				for (int i = 0; i < entries.length; i++) {
+					if (entries[i].getSuffix().equals(suffixField.getText()) && entries[i].getEntryType() == getKeyType()) return false;
+				}
+			}
+			return true;
+		}
+	
+		protected void updateKeyTypeCombo(int type) {
+			keyTypeCombo.removeAll();
+			for (Iterator i = CatalogFileTypeRegistryReader.getXMLCatalogFileTypes().iterator(); i.hasNext();) {
+				XMLCatalogFileType theFileType = (XMLCatalogFileType) i.next();
+				if (theFileType.extensions != null) {
+					for (Iterator j = theFileType.extensions.iterator(); j.hasNext();) {
+						String extension = (String) j.next();
+						if (resourceLocationField.getText().endsWith(extension)) {
+							if ("org.eclipse.wst.xml.core.ui.catalogFileType.xsd".equals(theFileType.id)) { //$NON-NLS-1$
+								keyTypeCombo.add(XMLCatalogMessages.UI_KEY_TYPE_DESCRIPTION_XSD_PUBLIC);
+								keyTypeCombo.add(XMLCatalogMessages.UI_KEY_TYPE_DESCRIPTION_XSD_SYSTEM);
+							}
+							else if ("org.eclipse.wst.xml.core.ui.catalogFileType.dtd".equals(theFileType.id)) { //$NON-NLS-1$
+								keyTypeCombo.add(XMLCatalogMessages.UI_KEY_TYPE_DESCRIPTION_URI);
+								keyTypeCombo.add(XMLCatalogMessages.UI_KEY_TYPE_DESCRIPTION_DTD_SYSTEM);
+							}
+							else {
+								keyTypeCombo.add(XMLCatalogMessages.UI_KEY_TYPE_DESCRIPTION_URI);
+							}
+						}
+	
+					}
+	
+				}
+			}
+			if (keyTypeCombo.getItemCount() == 0) {
+				keyTypeCombo.add(XMLCatalogMessages.UI_KEY_TYPE_DESCRIPTION_URI);
+				keyTypeCombo.add(XMLCatalogMessages.UI_KEY_TYPE_DESCRIPTION_DTD_SYSTEM);
+			}
+	
+			switch (type) {
+				case ISuffixEntry.SUFFIX_TYPE_URI: // handle XML Schema,
+					keyTypeCombo.select(0); // namespace name as URI key
+					break;
+
+				case ISuffixEntry.SUFFIX_TYPE_SYSTEM :
+					keyTypeCombo.select(1);
+					break;
+
+				default :
+					if (keyTypeCombo.getItemCount() > 0) {
+						keyTypeCombo.select(0);
+					}
+					break;
+			}
+	
+		}
+		
+		protected void updateWidgets(Widget widget) {
+			if (widget != keyTypeCombo) {
+				updateKeyTypeCombo(getKeyType());
+			}
+			computeErrorMessage();
+			updateErrorMessageLabel(errorMessageLabel);
+			updateOKButtonState();
+		}
+	
+	}
+
+	protected abstract class CatalogElementPage {
+
+		Control fControl;
+
+		public CatalogElementPage() {
+			super();
+
+		}
+		
+		public abstract void refresh();
+
+		public abstract Control createControl(Composite parent);
+
+		public Control getControl() {
+			return fControl;
+		}
+
+		public abstract ICatalogElement getData();
+
+		public abstract void saveData();
+	}
+
+	protected class FilterableSelectSingleFileDialog extends SelectSingleFileDialog implements SelectionListener {
+		protected Combo filterControl;
+
+		public FilterableSelectSingleFileDialog(Shell parentShell) {
+			super(parentShell, null, true);
+			setFilters(null);
+		}
+
+		public void createAndOpen() {
+			this.create();
+			setBlockOnOpen(true);
+			getShell().setText(XMLCatalogMessages.UI_LABEL_FILE_SELECTION);
+			this.setTitle(XMLCatalogMessages.UI_LABEL_SELECT_FILE);
+			this.setMessage(XMLCatalogMessages.UI_LABEL_CHOOSE_FILE_TO_ADD_TO_CATALOG);
+			open();
+		}
+
+		public void createFilterControl(Composite composite) {
+			Label label = new Label(composite, SWT.NONE);
+			label.setText(XMLCatalogMessages.UI_LABEL_SELECT_FILE_FILTER_CONTROL);
+
+			filterControl = new Combo(composite, SWT.READ_ONLY);
+			GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+			filterControl.setLayoutData(gd);
+
+			filterControl.setText(XMLCatalogMessages.UI_TEXT_SELECT_FILE_FILTER_CONTROL);
+			filterControl.add(XMLCatalogMessages.UI_TEXT_SELECT_FILE_FILTER_CONTROL);
+
+			for (Iterator i = CatalogFileTypeRegistryReader.getXMLCatalogFileTypes().iterator(); i.hasNext();) {
+				XMLCatalogFileType fileType = (XMLCatalogFileType) i.next();
+				if (fileType.description != null) {
+					filterControl.add(fileType.description);
+				}
+			}
+
+			filterControl.select(0);
+			filterControl.addSelectionListener(this);
+		}
+
+		protected void setFilters(XMLCatalogFileType fileType) {
+			if (fileType == null) {
+				// compute all the supported file extensions
+				List list = new ArrayList();
+				for (Iterator i = CatalogFileTypeRegistryReader.getXMLCatalogFileTypes().iterator(); i.hasNext();) {
+					XMLCatalogFileType theFileType = (XMLCatalogFileType) i.next();
+					if (theFileType.extensions != null) {
+						list.addAll(theFileType.extensions);
+					}
+				}
+				// Any files are now supported with Resource URI
+				selectSingleFileView.setFilterExtensions(createStringArray(list));
+			}
+			else {
+				if (fileType.extensions != null) {
+					selectSingleFileView.setFilterExtensions(createStringArray(fileType.extensions));
+				}
+			}
+		}
+
+		public void widgetDefaultSelected(SelectionEvent e) {
+			// do nothing
+		}
+
+		public void widgetSelected(SelectionEvent e) {
+			String text = filterControl.getText();
+			XMLCatalogFileType fileType = getMatchingFileType(text);
+			setFilters(fileType);
+		}
+	}
+
+	protected abstract class AbstractDelegatePage extends CatalogElementPage {
+	
+		
+		protected Button browseWorkspaceButton;
+		
+		protected Button browseFileSystemButton;
+		
+		protected Text catalogLocationField;
+
+		protected Label errorMessageLabel;
+
+		protected void computeErrorMessage() {
+			errorMessage = null;
+			String fileName = catalogLocationField.getText();
+			if (fileName.trim().length() > 0) {
+				if ((fileName.indexOf("..") != -1) || (fileName.indexOf("./") != -1) || (fileName.indexOf("/.") != -1) || (fileName.indexOf(".\\") != -1) || (fileName.indexOf("\\.") != -1)) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
+					errorMessage = XMLCatalogMessages.UI_WARNING_URI_MUST_NOT_HAVE_DOTS;
+				}
+
+				String uri = fileName;
+				if (!URIHelper.hasProtocol(uri)) {
+					uri = URIHelper.isAbsolute(uri) ? URIHelper.prependFileProtocol(uri) : URIHelper.prependPlatformResourceProtocol(uri);
+				}
+
+				if ((errorMessage == null) && !URIHelper.isReadableURI(uri, false)) {
+					errorMessage = XMLCatalogMessages.UI_WARNING_URI_NOT_FOUND_COLON + fileName;
+				}
+			}
+			else {
+				// this an error that is not actually
+				// reported ... OK is just disabled
+				errorMessage = ""; //$NON-NLS-1$
+			}
+		}
+
+		public abstract Control createControl(Composite parent);
+
+		protected Control createNextCatalogPanel(Composite parent, String catalogUriLabel) {
+			ModifyListener modifyListener = new ModifyListener() {
+				public void modifyText(ModifyEvent e) {
+					updateWidgets(e.widget);
+				}
+			};
+
+			Composite composite = new Composite(parent, SWT.NONE);
+			GridData gd = new GridData(GridData.FILL_BOTH);
+			composite.setLayoutData(gd);
+
+			GridLayout layout = new GridLayout();
+			composite.setLayout(layout);
+
+			Composite group = new Composite(composite, SWT.NONE);
+			gd = new GridData(GridData.FILL_HORIZONTAL);
+			group.setLayoutData(gd);
+
+			layout = new GridLayout();
+			group.setLayout(layout);
+
+			createSpecificFields(group);
+			
+			Label resourceLocationLabel = new Label(group, SWT.NONE);
+			resourceLocationLabel.setText(catalogUriLabel);
+
+			catalogLocationField = new Text(group, SWT.SINGLE | SWT.BORDER);
+			catalogLocationField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+			catalogLocationField.setText(URIUtils.convertURIToLocation(getDisplayValue(getCatalogLocation())));
+			// WorkbenchHelp.setHelp(resourceLocationField,
+			// XMLBuilderContextIds.XMLP_ENTRY_URI);
+			catalogLocationField.addModifyListener(modifyListener);
+			
+			Composite browseButtonsComposite = new Composite(group, SWT.FLAT);
+			gd = new GridData(GridData.FILL_HORIZONTAL);
+			gd.horizontalSpan = 2;
+			gd.horizontalAlignment = GridData.END;
+			browseButtonsComposite.setLayoutData(gd);
+			
+			layout = new GridLayout();
+			layout.numColumns = 2;
+			layout.marginWidth = 0;
+			layout.marginHeight = 0;
+			layout.marginBottom = 5;
+			browseButtonsComposite.setLayout(layout);
+			
+			browseWorkspaceButton = new Button(browseButtonsComposite, SWT.PUSH);
+			browseWorkspaceButton.setText(XMLCatalogMessages.UI_BUTTON_MENU_BROWSE_WORKSPACE);
+			browseWorkspaceButton.addSelectionListener(new SelectionListener(){
+
+				public void widgetDefaultSelected(SelectionEvent e) {
+				}
+
+				public void widgetSelected(SelectionEvent e) {
+					String value = invokeWorkspaceFileSelectionDialog();
+					if(value != null) {
+						catalogLocationField.setText(value);
+					}
+				}
+			});
+			
+			browseFileSystemButton = new Button(browseButtonsComposite, SWT.PUSH);
+			browseFileSystemButton.setText(XMLCatalogMessages.UI_BUTTON_MENU_BROWSE_FILE_SYSTEM);
+			browseFileSystemButton.addSelectionListener(new SelectionListener(){
+
+				public void widgetDefaultSelected(SelectionEvent e) {
+				}
+
+				public void widgetSelected(SelectionEvent e) {
+					String value = invokeFileSelectionDialog();
+					if(value != null) {
+						catalogLocationField.setText(value);
+					}
+				}
+			});
+
+			errorMessageLabel = new Label(group, SWT.NONE);
+			errorMessageLabel.setForeground(color);
+			errorMessageLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+			updateWidgets(null);
+			return composite;
+		}
+
+		protected void createSpecificFields(Composite group) {
+		}
+
+		protected abstract String getCatalogLocation();
+
+		protected void updateWidgets(Widget widget) {
+			computeErrorMessage();
+			updateErrorMessageLabel(errorMessageLabel);
+			updateOKButtonState();
+		}
+	}
+
+	protected class NextCatalogPage extends AbstractDelegatePage {
+		protected INextCatalog nextCatalog;
+
+		public ICatalogElement getData() {
+			return getNextCatalog();
+		}
+		
+		public void refresh() {
+			computeErrorMessage();
+			updateErrorMessageLabel(errorMessageLabel);
+			updateOKButtonState();
+		}
+
+		protected INextCatalog getNextCatalog() {
+			if (nextCatalog == null) {
+				if ((fCatalogElement != null) && (fCatalogElement.getType() == ICatalogElement.TYPE_NEXT_CATALOG)) {
+					nextCatalog = (INextCatalog) fCatalogElement;
+				}
+				else {
+					if (catalog != null) {
+						nextCatalog = (INextCatalog) catalog.createCatalogElement(ICatalogElement.TYPE_NEXT_CATALOG);
+					}
+				}
+			}
+			return nextCatalog;
+		}
+
+		public void saveData() {
+			getNextCatalog().setCatalogLocation(URIUtils.convertLocationToURI(catalogLocationField.getText()));
+			dataSaved = true;
+		}
+
+		protected String getCatalogLocation() {
+			return getNextCatalog().getCatalogLocation();
+		}
+		
+		public Control createControl(Composite parent) {
+			fControl = createNextCatalogPanel(parent, XMLCatalogMessages.UI_LABEL_CATALOG_URI_COLON);
+			return fControl;
+		}
+	}
+
+	protected class DelegateCatalogPage extends AbstractDelegatePage {
+		protected IDelegateCatalog delegateCatalog;
+		private Text prefixField;
+		private Combo keyTypeCombo;
+		
+		public void refresh() {
+			computeErrorMessage();
+			updateErrorMessageLabel(errorMessageLabel);
+			updateOKButtonState();
+		}
+
+		protected void computeErrorMessage() {
+			errorMessage = null;
+			String prefix = prefixField.getText();
+			if(prefix.length() > 0) {
+				// good
+			} else {
+				errorMessage = "";
+			}
+		}
+		
+		public ICatalogElement getData() {
+			return getDelegateCatalog();
+		}
+
+		protected void createSpecificFields(Composite group) {
+			
+			Composite prefixComposite = new Composite(group, SWT.NONE);
+			
+			GridLayout layout = new GridLayout();
+			layout.numColumns = 2;
+			layout.marginWidth = 0;
+			layout.marginHeight = 0;
+			layout.marginBottom = 5;
+			prefixComposite.setLayout(layout);
+			
+			// Key Type
+			//
+			Label keyTypeLabel = new Label(prefixComposite, SWT.NONE);
+			keyTypeLabel.setText(XMLCatalogMessages.UI_MATCH_KEY_TYPE_COLON);
+	
+			keyTypeCombo = new Combo(prefixComposite, SWT.READ_ONLY);
+			GridData gd = new GridData();
+			gd.horizontalAlignment = SWT.FILL;
+			gd.grabExcessHorizontalSpace = true;
+			keyTypeCombo.setLayoutData(gd);
+			keyTypeCombo.add(XMLCatalogMessages.UI_KEY_TYPE_DESCRIPTION_DTD_PUBLIC);
+			keyTypeCombo.add(XMLCatalogMessages.UI_KEY_TYPE_DESCRIPTION_DTD_SYSTEM);
+			keyTypeCombo.add(XMLCatalogMessages.UI_KEY_TYPE_DESCRIPTION_URI);
+			switch (getDelegateCatalog().getEntryType()) {
+			case IDelegateCatalog.DELEGATE_TYPE_PUBLIC:
+				keyTypeCombo.select(0);
+				break;
+			case IDelegateCatalog.DELEGATE_TYPE_SYSTEM:
+				keyTypeCombo.select(1);
+				break;
+			default:
+			case IDelegateCatalog.DELEGATE_TYPE_URI:
+				keyTypeCombo.select(2);
+				break;
+			}
+
+			Label prefixLabel = new Label(prefixComposite, SWT.NONE);
+			prefixLabel.setText(XMLCatalogMessages.UI_LABEL_START_STRING_COLON);
+
+			prefixField = new Text(prefixComposite, SWT.SINGLE | SWT.BORDER);
+			prefixField.setLayoutData(new GridData(SWT.FILL, SWT.NONE, true, false));
+			prefixField.setText(getDisplayValue(getDelegateCatalog().getStartString()));
+			ModifyListener modifyListener = new ModifyListener() {
+				public void modifyText(ModifyEvent e) {
+					updateWidgets(e.widget);
+				}
+			};
+			prefixField.addModifyListener(modifyListener);
+			prefixComposite.setLayoutData(new GridData(SWT.FILL, SWT.NONE, true, false));
+		}
+
+		protected IDelegateCatalog getDelegateCatalog() {
+			if (delegateCatalog == null) {
+				if ((fCatalogElement != null) && (fCatalogElement.getType() == ICatalogElement.TYPE_DELEGATE)) {
+					delegateCatalog = (IDelegateCatalog) fCatalogElement;
+				}
+				else {	
+					if (catalog != null) {
+						delegateCatalog = (IDelegateCatalog) catalog.createCatalogElement(IDelegateCatalog.DELEGATE_TYPE_URI);
+					}
+				}
+			}
+			return delegateCatalog;
+		}
+
+		public void saveData() {
+			if (validateData())
+			{
+				getDelegateCatalog().setCatalogLocation(URIUtils.convertLocationToURI(catalogLocationField.getText()));
+				getDelegateCatalog().setStartString(prefixField.getText());
+				getDelegateCatalog().setEntryType(getDelegateType());
+				dataSaved = true;
+			}
+			else {
+				errorMessage = XMLCatalogMessages.UI_WARNING_DUPLICATE_DELEGATE;
+				errorMessageLabel.setText(errorMessage);
+				updateOKButtonState();
+				dataSaved = false;
+			}
+		}
+
+		private int getDelegateType() {
+			switch (keyTypeCombo.getSelectionIndex()) {
+			case 0:
+				return IDelegateCatalog.DELEGATE_TYPE_PUBLIC;
+
+			case 1:
+				return IDelegateCatalog.DELEGATE_TYPE_SYSTEM;
+			
+			case 2:				
+			default:
+				return IDelegateCatalog.DELEGATE_TYPE_URI;
+			}
+		}
+	
+		protected boolean validateData() {
+			IDelegateCatalog entry = getDelegateCatalog();
+			String prefix = prefixField.getText();
+			if(entry.getEntryType() != getDelegateType() || !prefix.equals(entry.getStartString())) {
+				IDelegateCatalog[] entries = catalog.getDelegateCatalogs();
+				for (int i = 0; i < entries.length; i++) {
+					if (entries[i].getStartString().equals(prefixField) && entries[i].getEntryType() == getDelegateType()) return false;
+				}
+			}
+			return true;
+		}
+
+		protected String getCatalogLocation() {
+			return getDelegateCatalog().getCatalogLocation();
+		}
+
+		public Control createControl(Composite parent) {
+			fControl = createNextCatalogPanel(parent, XMLCatalogMessages.UI_LABEL_DELEGATE_CATALOG_URI_COLON);
+			return fControl;
+		}
+	}
+
+	protected class RadioItemSelectionChangeListener implements SelectionListener {
+		public void widgetDefaultSelected(SelectionEvent e) {
+		}
+		
+		public void widgetSelected(SelectionEvent e) {
+			Object selection = e.getSource();
+			if (selection instanceof Button) {
+				Button button = (Button) selection;
+				if (button.getSelection()) {
+					if (!showPage((CatalogElementPage) button.getData())) {
+						// Page flipping wasn't successful
+						// handleError();
+					}
+				}
+			}
+		}
+
+	}
+
+	protected class RewriteEntryPage extends CatalogElementPage {
+		protected IRewriteEntry rewriteEntry;
+		private Text startStringField;
+		private Text prefixField;
+		private Combo keyTypeCombo;
+		
+		public void refresh() {
+			computeErrorMessage();
+			updateErrorMessageLabel(errorMessageLabel);
+			updateOKButtonState();
+		}
+	
+		public ICatalogElement getData() {
+			return getRewriteEntry();
+		}
+	
+		protected Label errorMessageLabel;
+
+		protected void computeErrorMessage() {
+			errorMessage = null;
+			
+			String start = startStringField.getText();
+			String prefix = prefixField.getText();
+			if (start.trim().length() > 0 && prefix.trim().length() > 0) {
+				// good
+			}
+			else {
+				// this an error that is not actually
+				// reported ... OK is just disabled
+				errorMessage = ""; //$NON-NLS-1$
+			}
+		}
+
+		protected IRewriteEntry getRewriteEntry() {
+			if (rewriteEntry == null) {
+				if ((fCatalogElement != null) && (fCatalogElement.getType() == ICatalogElement.TYPE_REWRITE)) {
+					rewriteEntry = (IRewriteEntry) fCatalogElement;
+				}
+				else {
+					if (catalog != null) {
+						rewriteEntry = (IRewriteEntry) catalog.createCatalogElement(IRewriteEntry.REWRITE_TYPE_SYSTEM);
+					}
+				}
+			}
+			return rewriteEntry;
+		}
+
+		protected void updateWidgets(Widget widget) {
+			computeErrorMessage();
+			updateErrorMessageLabel(errorMessageLabel);
+			updateOKButtonState();
+		}
+		public void saveData() {
+			if (validateData()) {
+				getRewriteEntry().setRewritePrefix(prefixField.getText());
+				getRewriteEntry().setStartString(startStringField.getText());
+				getRewriteEntry().setEntryType(getEntryType());
+				dataSaved = true;
+			}
+			else {
+				errorMessage = XMLCatalogMessages.UI_WARNING_DUPLICATE_REWRITE;
+				errorMessageLabel.setText(errorMessage);
+				updateOKButtonState();
+				dataSaved = false;
+			}
+		}
+
+		private int getEntryType() {
+			switch (keyTypeCombo.getSelectionIndex()) {
+			case 0:
+				return IRewriteEntry.REWRITE_TYPE_SYSTEM;
+			case 1:
+			default:
+				return IRewriteEntry.REWRITE_TYPE_URI;
+			}
+		}
+		
+		protected boolean validateData() {
+			IRewriteEntry entry = getRewriteEntry();
+			String startString = startStringField.getText();
+			if(entry.getEntryType() != getEntryType() || !entry.getStartString().equals(startString)) {
+				IRewriteEntry[] entries = catalog.getRewriteEntries();
+				for (int i = 0; i < entries.length; i++) {
+					if (entries[i].getStartString().equals(startString) && entries[i].getEntryType() == getEntryType()) return false;
+				}
+			}
+			return true;
+		}
+			
+		public Control createControl(Composite parent) {
+	
+			fControl = createRewriteEntryPanel(parent);
+	
+			return fControl;
+		}
+	
+		public Control createRewriteEntryPanel(Composite parent) {
+			ModifyListener modifyListener = new ModifyListener() {
+				public void modifyText(ModifyEvent e) {
+					updateWidgets(e.widget);
+				}
+			};
+
+			Composite composite = new Composite(parent, SWT.NONE);
+			GridData gd = new GridData(GridData.FILL_BOTH);
+			composite.setLayoutData(gd);
+
+			GridLayout layout = new GridLayout();
+			composite.setLayout(layout);
+
+			Composite group = new Composite(composite, SWT.NONE);
+			gd = new GridData(GridData.FILL_HORIZONTAL);
+			group.setLayoutData(gd);
+
+			layout = new GridLayout();
+			group.setLayout(layout);
+				
+			Composite prefixComposite = new Composite(group, SWT.NONE);
+			
+			layout = new GridLayout();
+			layout.numColumns = 2;
+			layout.marginWidth = 0;
+			layout.marginHeight = 0;
+			layout.marginBottom = 5;
+			prefixComposite.setLayout(layout);
+			
+			// Key Type
+			//
+			Label keyTypeLabel = new Label(prefixComposite, SWT.NONE);
+			keyTypeLabel.setText(XMLCatalogMessages.UI_MATCH_KEY_TYPE_COLON);
+	
+			keyTypeCombo = new Combo(prefixComposite, SWT.READ_ONLY);
+			gd = new GridData();
+			gd.horizontalAlignment = SWT.FILL;
+			gd.grabExcessHorizontalSpace = true;
+			keyTypeCombo.setLayoutData(gd);
+			keyTypeCombo.add(XMLCatalogMessages.UI_KEY_TYPE_DESCRIPTION_DTD_SYSTEM);
+			keyTypeCombo.add(XMLCatalogMessages.UI_KEY_TYPE_DESCRIPTION_URI);
+			switch (getRewriteEntry().getEntryType()) {
+			case IDelegateCatalog.DELEGATE_TYPE_SYSTEM:
+				keyTypeCombo.select(0);
+				break;
+			default:
+			case IDelegateCatalog.DELEGATE_TYPE_URI:
+				keyTypeCombo.select(1);
+				break;
+			}
+			Label startStringLabel = new Label(prefixComposite, SWT.NONE);
+			startStringLabel.setText(XMLCatalogMessages.UI_LABEL_START_STRING_COLON);
+	
+			startStringField = new Text(prefixComposite, SWT.SINGLE | SWT.BORDER);
+			startStringField.setLayoutData(new GridData(SWT.FILL, SWT.NONE, true, false));
+			startStringField.setText(getDisplayValue(getRewriteEntry().getStartString()));
+			startStringField.addModifyListener(modifyListener);
+
+			Label prefixLabel = new Label(prefixComposite, SWT.NONE);
+			prefixLabel.setText(XMLCatalogMessages.UI_LABEL_REWRITE_PREFIX_COLON);
+	
+			prefixField = new Text(prefixComposite, SWT.SINGLE | SWT.BORDER);
+			prefixField.setLayoutData(new GridData(SWT.FILL, SWT.NONE, true, false));
+			prefixField.setText(getDisplayValue(getRewriteEntry().getRewritePrefix()));
+			prefixField.addModifyListener(modifyListener);
+	
+			prefixComposite.setLayoutData(new GridData(SWT.FILL, SWT.NONE, true, false));
+
+			errorMessageLabel = new Label(group, SWT.NONE);
+			errorMessageLabel.setForeground(color);
+			errorMessageLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+			updateWidgets(null);
+			return composite;
+		}
+	}
+
+	protected class ToolBarItemSelectionChangeListener implements SelectionListener {
+		public void widgetDefaultSelected(SelectionEvent e) {}
+
+		public void widgetSelected(SelectionEvent e) {
+			Object selection = e.getSource();
+			if (selection instanceof ToolItem) {
+				ToolItem toolItem = (ToolItem)selection;
+				ToolBar toolbar = toolItem.getParent();
+				if(toolbar != null) {
+					ToolItem[] items = toolbar.getItems();
+					for (int i = 0; i < items.length; i++) {
+						items[i].setSelection(items[i] == toolItem);
+					}
+				}
+				if (!showPage((CatalogElementPage) toolItem.getData())) {
+					// Page flipping wasn't successful
+					// handleError();
+				}
+			}
+		}
+	}
+	
+	public static String[] createStringArray(List list) {
+		String[] stringArray = new String[list.size()];
+		for (int i = 0; i < stringArray.length; i++) {
+			stringArray[i] = (String) list.get(i);
+		}
+		return stringArray;
+	}
+
+	public static String removeLeadingSlash(String uri) {
+		// remove leading slash from the value to avoid the whole leading
+		// slash
+		// ambiguity problem
+		//       
+		if (uri != null) {
+			while (uri.startsWith("/") || uri.startsWith("\\")) { //$NON-NLS-1$ //$NON-NLS-2$
+				uri = uri.substring(1);
+			}
+		}
+		return uri;
+	}
+
+	protected ICatalog catalog;
+
+	protected ICatalogElement fCatalogElement;
+
+	protected String errorMessage;
+
+	protected String warningMessage;
+
+	protected Button okButton;
+
+	protected PageBook pageContainer;
+
+	protected CatalogElementPage selectedPage;
+
+	// protected TreeViewer treeViewer;
+	
+	protected ToolBar toolBar;
+
+	protected Composite elementTypeComposite;
+
+	protected Color color;
+	protected boolean dataSaved;
+
+	public EditCatalogEntryDialog(Shell parentShell, ICatalog aCatalog) {
+		super(parentShell);
+		setShellStyle(getShellStyle() | SWT.RESIZE);
+		this.catalog = aCatalog;
+	}
+
+	public EditCatalogEntryDialog(Shell parentShell, ICatalogElement catalogElement, ICatalog aCatalog) {
+		this(parentShell, aCatalog);
+		this.fCatalogElement = catalogElement;
+		// TODO EB: fix his
+		// entry.setURI(URIHelper.removePlatformResourceProtocol(entry.getURI()));
+	}
+
+	protected void buttonPressed(int buttonId) {
+		if (buttonId == IDialogConstants.OK_ID) {
+			selectedPage.saveData();
+			if (!dataSaved) {				
+				// do not exit edit dialog
+				return;
+			}
+		}
+		super.buttonPressed(buttonId);
+	}
+
+
+
+	protected void createButtonsForButtonBar(Composite parent) {
+		okButton = createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
+		okButton.setEnabled(false);
+		createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false);
+		updateOKButtonState();
+	}
+
+
+	protected Control createDialogArea(Composite parent) {
+		Composite dialogAreaComposite = (Composite) super.createDialogArea(parent);
+		color = new Color(dialogAreaComposite.getDisplay(), 200, 0, 0);
+		GridLayout layout = new GridLayout();
+		layout.marginHeight = 0;
+		layout.marginWidth = 0;
+		dialogAreaComposite.setLayout(layout);
+		GridData gd = new GridData(GridData.FILL_BOTH);
+		gd.widthHint = 550;
+		//gd.heightHint = 250;
+		dialogAreaComposite.setLayoutData(gd);
+		createMainComponent(dialogAreaComposite);
+		return this.dialogArea;
+	}
+
+	public boolean close() {
+		if (color != null) {
+			color.dispose();
+		}
+		return super.close();
+	}
+
+	protected Composite createMainComponent(Composite composite) {
+		if (fCatalogElement != null) // "edit" action
+		{
+			Composite composite1 = new Composite(composite, SWT.NONE);
+			GridData data = new GridData(GridData.FILL_BOTH);
+			composite1.setLayoutData(data);
+			GridLayout layout = new GridLayout();
+			composite1.setLayout(layout);
+
+			pageContainer = new PageBook(composite1, SWT.NONE);
+			pageContainer.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+			if (fCatalogElement.getType() == ICatalogElement.TYPE_ENTRY) {
+				CatalogElementPage entryPage = new CatalogEntryPage();
+				entryPage.createControl(pageContainer);
+				showPage(entryPage);
+			}
+			else if (fCatalogElement.getType() == ICatalogElement.TYPE_NEXT_CATALOG) {
+				CatalogElementPage nextCatalogPage = new NextCatalogPage();
+				nextCatalogPage.createControl(pageContainer);
+				showPage(nextCatalogPage);
+			}
+			else if (fCatalogElement.getType() == ICatalogElement.TYPE_DELEGATE) {
+				DelegateCatalogPage delegateCatalogPage = new DelegateCatalogPage();
+				delegateCatalogPage.createControl(pageContainer);
+				showPage(delegateCatalogPage);
+			}
+			else if (fCatalogElement.getType() == ICatalogElement.TYPE_SUFFIX) {
+				SuffixEntryPage suffixEntryPage = new SuffixEntryPage();
+				suffixEntryPage.createControl(pageContainer);
+				showPage(suffixEntryPage);
+			}
+			else if (fCatalogElement.getType() == ICatalogElement.TYPE_REWRITE) {
+				RewriteEntryPage rewriteEntryPage = new RewriteEntryPage();
+				rewriteEntryPage.createControl(pageContainer);
+				showPage(rewriteEntryPage);
+			}
+
+			return composite1;
+		}
+		return createMainComponentWithToolbar(composite);
+
+	}
+
+	
+	protected Composite createMainComponentWithToolbar(Composite composite) {
+
+		FormLayout formLayout = new FormLayout();
+		formLayout.marginHeight = 5;
+		formLayout.marginWidth = 5;
+		composite.setLayout(formLayout);
+
+		Label label = new Label(composite, SWT.NONE);
+		FormData data = new FormData();
+		data.top = new FormAttachment(0, 0);
+		data.left = new FormAttachment(0, 0);
+		data.right = new FormAttachment(100, 0);
+		label.setLayoutData(data);
+
+		toolBar = new ToolBar(composite, SWT.BORDER | SWT.FLAT | SWT.VERTICAL);
+		
+
+		data = new FormData();
+		data.top = new FormAttachment(label, 0);
+		data.left = new FormAttachment(0, 0);
+		data.bottom = new FormAttachment(100, 0);
+		// data.height = 250;
+		// data.width = 50;
+		toolBar.setLayoutData(data);
+
+		Composite composite1 = new Composite(composite, SWT.BORDER);
+		data = new FormData();
+		data.top = new FormAttachment(label, 0);
+		data.left = new FormAttachment(toolBar, 0, SWT.DEFAULT);
+		data.right = new FormAttachment(100, 0);
+		data.bottom = new FormAttachment(100, 0);
+		composite1.setLayoutData(data);
+		GridLayout layout = new GridLayout();
+		layout.marginHeight = 0;
+		layout.marginWidth = 0;
+		composite1.setLayout(layout);
+
+		// createPageBookPanel(composite1);
+		pageContainer = new PageBook(composite1, SWT.NONE);
+		pageContainer.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+		// add pages for each type of catalog element
+		createCatalogEntryButton();
+		createRewriteButton();
+		createSuffixCatalogButton();
+		createNextCatalogButton();
+		createDelegateCatalogButton();
+		if (toolBar.getItemCount() > 0) {
+			ToolItem item = toolBar.getItem(0);
+			showPage((CatalogElementPage) (item.getData()));
+		}
+		return composite1;
+	}
+	
+	protected void createCatalogEntryButton() {
+		CatalogElementPage page = new CatalogEntryPage();
+		page.createControl(pageContainer);
+		ToolItem toolItem = new ToolItem(toolBar, SWT.CHECK);
+		toolItem.setImage(catalogEntryToolBarImage);
+		toolItem.setText(XMLCatalogMessages.EditCatalogEntryDialog_catalogEntryLabel);
+		toolItem.setData(page);
+		toolItem.addSelectionListener(new ToolBarItemSelectionChangeListener());
+		toolItem.setSelection(true);
+	}
+
+	protected void createNextCatalogButton() {
+		CatalogElementPage page = new NextCatalogPage();
+		page.createControl(pageContainer);
+		ToolItem toolItem = new ToolItem(toolBar, SWT.CHECK);
+		toolItem.setImage(nextCatalogToolBarImage);
+		toolItem.setText(XMLCatalogMessages.EditCatalogEntryDialog_nextCatalogLabel);
+		toolItem.setData(page);
+		toolItem.addSelectionListener(new ToolBarItemSelectionChangeListener());
+
+	}
+	
+	protected void createRewriteButton() {
+		CatalogElementPage page = new RewriteEntryPage();
+		page.createControl(pageContainer);
+		ToolItem toolItem = new ToolItem(toolBar, SWT.CHECK);
+		toolItem.setImage(rewriteToolBarImage);
+		toolItem.setText(XMLCatalogMessages.EditCatalogEntryDialog_rewriteEntryLabel);
+		toolItem.setData(page);
+		toolItem.addSelectionListener(new ToolBarItemSelectionChangeListener());
+	}
+	
+	protected void createDelegateCatalogButton() {
+		CatalogElementPage page = new DelegateCatalogPage();
+		page.createControl(pageContainer);
+		ToolItem toolItem = new ToolItem(toolBar, SWT.CHECK);
+		toolItem.setImage(delegateCatalogToolBarImage);
+		toolItem.setText(XMLCatalogMessages.EditCatalogEntryDialog_delegateCatalogLabel);
+		toolItem.setData(page);
+		toolItem.addSelectionListener(new ToolBarItemSelectionChangeListener());
+	}
+	
+	protected void createSuffixCatalogButton() {
+		CatalogElementPage page = new SuffixEntryPage();
+		page.createControl(pageContainer);
+		ToolItem toolItem = new ToolItem(toolBar, SWT.CHECK);
+		toolItem.setImage(suffixToolBarImage);
+		toolItem.setText(XMLCatalogMessages.EditCatalogEntryDialog_suffixEntryLabel);
+		toolItem.setData(page);
+		toolItem.addSelectionListener(new ToolBarItemSelectionChangeListener());
+	}
+	
+	
+	
+	
+	
+	
+//
+//	protected void createRewriteEntryButton() {
+//		CatalogElementPage page = new RewriteEntryPage();
+//		page.createControl(pageContainer);
+//		Button radioButton = new Button(elementTypeComposite, SWT.RADIO);
+//		radioButton.setText(XMLCatalogMessages.EditCatalogEntryDialog_rewriteEntryLabel);
+//		radioButton.setData(page);
+//		radioButton.addSelectionListener(new RadioItemSelectionChangeListener());
+//	}
+//
+//	protected void createSuffixEntryButton() {
+//		CatalogElementPage page = new SuffixEntryPage();
+//		page.createControl(pageContainer);
+//		Button radioButton = new Button(elementTypeComposite, SWT.RADIO);
+//		radioButton.setText(XMLCatalogMessages.EditCatalogEntryDialog_suffixEntryLabel);
+//		radioButton.setData(page);
+//		radioButton.addSelectionListener(new RadioItemSelectionChangeListener());
+//	}
+//
+//	protected void createDelegateCatalogButton() {
+//		CatalogElementPage page = new DelegateCatalogPage();
+//		page.createControl(pageContainer);
+//		Button radioButton = new Button(elementTypeComposite, SWT.RADIO);
+//		radioButton.setText(XMLCatalogMessages.EditCatalogEntryDialog_delegateCatalogLabel);
+//		radioButton.setData(page);
+//		radioButton.addSelectionListener(new RadioItemSelectionChangeListener());
+//
+//	}
+
+	protected ICatalogElement getCatalogElement() {
+		return fCatalogElement;
+	}
+
+	protected String getDisplayValue(String string) {
+		return string != null ? string : ""; //$NON-NLS-1$
+	}
+
+	protected XMLCatalogFileType getMatchingFileType(String description) {
+		XMLCatalogFileType fileType = null;
+		for (Iterator i = CatalogFileTypeRegistryReader.getXMLCatalogFileTypes().iterator(); i.hasNext();) {
+			XMLCatalogFileType theFileType = (XMLCatalogFileType) i.next();
+			if ((theFileType.description != null) && theFileType.description.equals(description)) {
+				fileType = theFileType;
+			}
+		}
+		return fileType;
+	}
+
+	protected boolean showPage(CatalogElementPage page) {
+		if (pageContainer.isDisposed()) {
+			return false;
+		}
+		selectedPage = page;
+		pageContainer.setVisible(true);
+		pageContainer.showPage(selectedPage.getControl());
+		fCatalogElement = selectedPage.getData();
+		selectedPage.refresh();
+		return true;
+	}
+
+	protected void updateErrorMessageLabel(Label errorMessageLabel) {
+		if (errorMessage != null) {
+			errorMessageLabel.setText(errorMessage);
+		}
+		else if (warningMessage != null) {
+			errorMessageLabel.setText(warningMessage);
+		}
+		else {
+			errorMessageLabel.setText("");
+		}
+	}
+
+	protected void updateOKButtonState() {
+		if (okButton != null) {
+			okButton.setEnabled(errorMessage == null);
+		}
+	}
+
+	protected Button createBrowseButton(Composite composite) {
+		Button browseButton = new Button(composite, SWT.PUSH);
+		// browseButton.setText(XMLCatalogMessages.
+		// UI_BUTTON_BROWSE"));
+		browseButton.setImage(borwseImage);
+		Rectangle r = borwseImage.getBounds();
+		GridData gd = new GridData();
+		int IMAGE_WIDTH_MARGIN = 6;
+		int IMAGE_HEIGHT_MARGIN = 6;
+		gd.heightHint = r.height + IMAGE_HEIGHT_MARGIN;
+		gd.widthHint = r.width + IMAGE_WIDTH_MARGIN;
+		browseButton.setLayoutData(gd);
+
+		return browseButton;
+
+	}
+	
+	protected Button createWorkspaceBrowseButton(Composite composite) {
+		Button browseWorkspaceButton = new Button(composite, SWT.PUSH);
+		browseWorkspaceButton.setText(XMLCatalogMessages.UI_BUTTON_MENU_BROWSE_WORKSPACE);
+		return browseWorkspaceButton;
+	}
+	
+	protected Button createFileSystemBrowseButton(Composite composite) {
+		Button browseFileSystemButton = new Button(composite, SWT.PUSH);
+		browseFileSystemButton.setText(XMLCatalogMessages.UI_BUTTON_MENU_BROWSE_WORKSPACE);
+		return browseFileSystemButton;
+	}
+
+	
+	String invokeWorkspaceFileSelectionDialog() {
+		FilterableSelectSingleFileDialog dialog = new FilterableSelectSingleFileDialog(getShell());
+		dialog.createAndOpen();
+		IFile file = dialog.getFile();
+		String uri = null;
+		if (file != null) {
+			// remove leading slash from the value to avoid the
+			// whole leading slash ambiguity problem
+			//                    
+			uri = file.getFullPath().toString();
+			while (uri.startsWith("/") || uri.startsWith("\\")) { //$NON-NLS-1$ //$NON-NLS-2$
+				uri = uri.substring(1);
+			}
+		}
+		return uri;
+	}
+
+	String invokeFileSelectionDialog() {
+		FileDialog dialog = new FileDialog(getShell(), SWT.SINGLE);
+		return dialog.open();
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/ElementNodePage.java b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/ElementNodePage.java
new file mode 100644
index 0000000..0ec61e6
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/ElementNodePage.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.catalog;
+
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalogElement;
+
+
+public abstract class ElementNodePage {
+
+	Control fControl;
+
+	public ElementNodePage() {
+		super();
+
+	}
+
+	public abstract Control createControl(Composite parent);
+
+	public Control getControl() {
+		return fControl;
+	}
+
+	public abstract void saveData();
+
+	public abstract ICatalogElement getData();
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/ImageFactory.java b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/ImageFactory.java
new file mode 100644
index 0000000..3938a7e
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/ImageFactory.java
@@ -0,0 +1,201 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.catalog;
+
+import java.util.Hashtable;
+
+import org.eclipse.jface.resource.CompositeImageDescriptor;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.resource.ImageRegistry;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.wst.xml.ui.internal.XMLUIPlugin;
+
+public class ImageFactory {
+	public static final int TOP_LEFT = 1;
+	public static final int TOP_RIGHT = 2;
+	public static final int BOTTOM_LEFT = 3;
+	public static final int BOTTOM_RIGHT = 4;
+
+	protected static final int[][] OVERLAY_COORDINATE = {{0, 0}, {0, 2}, {2, 0}, {2, 2}};
+
+	protected static ImageFactory INSTANCE = new ImageFactory();
+
+	protected Hashtable compositeImageTable = new Hashtable();
+
+	public ImageFactory() {
+		super();
+	}
+
+	public Image getImage(String iconName) {
+		ImageRegistry imageRegistry = XMLUIPlugin.getDefault().getImageRegistry();
+
+		if (imageRegistry.get(iconName) != null) {
+			return imageRegistry.get(iconName);
+		}
+		else {
+			imageRegistry.put(iconName, ImageDescriptor.createFromFile(getClass(), iconName));
+			return imageRegistry.get(iconName);
+		}
+	}
+
+	public Image createCompositeImage(Image base, Image overlay, int overlayPosition) {
+		String key = base + "*" + overlay + "*" + overlayPosition; //$NON-NLS-1$ //$NON-NLS-2$
+		Image result = (Image) compositeImageTable.get(key);
+		if (result == null) {
+			ImageDescriptor overlays[][] = new ImageDescriptor[3][3];
+			int[] coord = OVERLAY_COORDINATE[overlayPosition];
+			overlays[coord[1]][coord[0]] = new ImageBasedImageDescriptor(overlay);
+			OverlayIcon icon = new OverlayIcon(new ImageBasedImageDescriptor(base), overlays, new Point(16, 16));
+			result = icon.createImage();
+			compositeImageTable.put(key, result);
+		}
+		return result;
+	}
+
+
+	public static ImageDescriptor createImageDescriptorWrapper(Image image) {
+		return new ImageBasedImageDescriptor(image);
+	}
+
+	/**
+	 * An OverlayIcon consists of a main icon and several adornments.
+	 */
+	class OverlayIcon extends CompositeImageDescriptor {
+
+		static final int DEFAULT_WIDTH = 22;
+
+		static final int DEFAULT_HEIGHT = 16;
+
+		private Point fSize = null;
+
+		private ImageDescriptor fBase;
+
+		private ImageDescriptor fOverlays[][];
+
+		public OverlayIcon(ImageDescriptor base, ImageDescriptor[][] overlays, Point size) {
+			fBase = base;
+			fOverlays = overlays;
+			fSize = size;
+		}
+
+		protected void drawBottomLeft(ImageDescriptor[] overlays) {
+			if (overlays == null) {
+				return;
+			}
+			int length = overlays.length;
+			int x = 0;
+			for (int i = 0; i < 3; i++) {
+				if ((i < length) && (overlays[i] != null)) {
+					ImageData id = overlays[i].getImageData();
+					drawImage(id, x, getSize().y - id.height);
+					x += id.width;
+				}
+			}
+		}
+
+		protected void drawBottomRight(ImageDescriptor[] overlays) {
+			if (overlays == null) {
+				return;
+			}
+			int length = overlays.length;
+			int x = getSize().x;
+			for (int i = 2; i >= 0; i--) {
+				if ((i < length) && (overlays[i] != null)) {
+					ImageData id = overlays[i].getImageData();
+					x -= id.width;
+					drawImage(id, x, getSize().y - id.height);
+				}
+			}
+		}
+
+		/**
+		 * @see CompositeImageDescriptor#drawCompositeImage(int, int)
+		 */
+		protected void drawCompositeImage(int width, int height) {
+			ImageData bg;
+			if ((fBase == null) || ((bg = fBase.getImageData()) == null)) {
+				bg = DEFAULT_IMAGE_DATA;
+			}
+			drawImage(bg, 0, 0);
+
+			if (fOverlays != null) {
+				if (fOverlays.length > 0) {
+					drawTopRight(fOverlays[0]);
+				}
+
+				if (fOverlays.length > 1) {
+					drawBottomRight(fOverlays[1]);
+				}
+
+				if (fOverlays.length > 2) {
+					drawBottomLeft(fOverlays[2]);
+				}
+
+				if (fOverlays.length > 3) {
+					drawTopLeft(fOverlays[3]);
+				}
+			}
+		}
+
+		protected void drawTopLeft(ImageDescriptor[] overlays) {
+			if (overlays == null) {
+				return;
+			}
+			int length = overlays.length;
+			int x = 0;
+			for (int i = 0; i < 3; i++) {
+				if ((i < length) && (overlays[i] != null)) {
+					ImageData id = overlays[i].getImageData();
+					drawImage(id, x, 0);
+					x += id.width;
+				}
+			}
+		}
+
+		protected void drawTopRight(ImageDescriptor[] overlays) {
+			if (overlays == null) {
+				return;
+			}
+			int length = overlays.length;
+			int x = getSize().x;
+			for (int i = 2; i >= 0; i--) {
+				if ((i < length) && (overlays[i] != null)) {
+					ImageData id = overlays[i].getImageData();
+					x -= id.width;
+					drawImage(id, x, 0);
+				}
+			}
+		}
+
+		/**
+		 * @see CompositeImageDescriptor#getSize()
+		 */
+		protected Point getSize() {
+			return fSize;
+		}
+	}
+
+	static class ImageBasedImageDescriptor extends ImageDescriptor {
+		protected Image image;
+
+		public ImageBasedImageDescriptor(Image image) {
+			this.image = image;
+		}
+
+		public ImageData getImageData() {
+			return image.getImageData();
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/URIUtils.java b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/URIUtils.java
new file mode 100644
index 0000000..ea0c2bc
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/URIUtils.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.catalog;
+
+import org.eclipse.wst.common.uriresolver.internal.util.URIHelper;
+
+public class URIUtils {
+	
+	  private static final String PROTOCOL_PATTERN = ":"; 
+	  private static final String FILE_PROTOCOL = "file:";
+	  private static final String PLATFORM_RESOURCE_PROTOCOL = "platform:/resource/";
+	  private static final String LOCAL_FILE_PROTOCOL_FORWARD_SLASH = "\\\\\\";
+	  private static final String LOCAL_FILE_PROTOCOL_BACK_SLASH = "///";
+	  private static final char   PATH_SEPARATOR_FORWARD_SLASH = '/';
+	  private static final char   PATH_SEPARATOR_BACK_SLASH = '\\';
+	  
+	  public static String convertURIToLocation(String uri) {
+			String location = uri;
+			if (uri != null) {
+				if (uri.startsWith(FILE_PROTOCOL)) {
+					location = org.eclipse.wst.common.uriresolver.internal.URI.createURI(uri).toFileString();
+					if (location != null && (location.startsWith(LOCAL_FILE_PROTOCOL_BACK_SLASH)
+							|| location.startsWith(LOCAL_FILE_PROTOCOL_FORWARD_SLASH))) {
+						location = location.substring(LOCAL_FILE_PROTOCOL_BACK_SLASH.length());
+					}
+				} else if (uri.startsWith(PLATFORM_RESOURCE_PROTOCOL)) {
+					location = uri.substring(PLATFORM_RESOURCE_PROTOCOL.length());
+				}
+			}
+		return location;
+	  }
+	  
+	  public static String convertLocationToURI(String location) {
+		  String uri = location;
+			if (!URIHelper.hasProtocol(location)) {
+				uri = URIHelper.isAbsolute(location)? org.eclipse.wst.common.uriresolver.internal.URI.createFileURI(location).toString()
+						: URIHelper.prependPlatformResourceProtocol(location);
+			}
+			if (uri.startsWith(FILE_PROTOCOL) && uri.indexOf(PROTOCOL_PATTERN, FILE_PROTOCOL.length()) != -1) {
+				uri = URIHelper.ensureFileURIProtocolFormat(uri);
+			}
+			uri = uri.replace(PATH_SEPARATOR_BACK_SLASH, PATH_SEPARATOR_FORWARD_SLASH);
+			return uri;
+	  }
+
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/XMLCatalogEntriesView.java b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/XMLCatalogEntriesView.java
new file mode 100644
index 0000000..92f8bb5
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/XMLCatalogEntriesView.java
@@ -0,0 +1,304 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2008 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.catalog;
+
+import java.util.Iterator;
+
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.wst.xml.core.internal.catalog.Catalog;
+import org.eclipse.wst.xml.core.internal.catalog.CatalogElement;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalog;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalogElement;
+import org.eclipse.wst.xml.ui.internal.XMLUIPlugin;
+
+
+
+public class XMLCatalogEntriesView extends Composite {
+	protected Button newButton;
+	protected Button editButton;
+	protected Button deleteButton;
+	protected XMLCatalogTreeViewer tableViewer;
+	protected ICatalog workingUserCatalog;
+	protected ICatalog systemCatalog;
+
+	// protected boolean isPageEnabled = true;
+
+	public XMLCatalogEntriesView(Composite parent, ICatalog workingUserCatalog, ICatalog systemCatalog) {
+		super(parent, SWT.NONE);
+		this.workingUserCatalog = workingUserCatalog;
+		this.systemCatalog = systemCatalog;
+
+		GridLayout gridLayout = new GridLayout();
+		gridLayout.numColumns = 2;
+		this.setLayout(gridLayout);
+
+		tableViewer = createTableViewer(this);
+		tableViewer.setInput("dummy"); //$NON-NLS-1$
+		
+		// https://bugs.eclipse.org/bugs/show_bug.cgi?id=202692
+		// specifically set size of tree before expanding it
+		Point initialSize = tableViewer.getTree().computeSize(SWT.DEFAULT, SWT.DEFAULT);
+		GridData gridData = new GridData(GridData.FILL_BOTH);
+		gridData.widthHint = initialSize.x;
+		gridData.heightHint = initialSize.y;
+		tableViewer.getControl().setLayoutData(gridData);
+		
+		tableViewer.expandToLevel(2);
+		tableViewer.reveal(XMLCatalogTreeViewer.USER_SPECIFIED_ENTRIES_OBJECT);
+		
+		ISelectionChangedListener listener = new ISelectionChangedListener() {
+			public void selectionChanged(SelectionChangedEvent event) {
+				updateWidgetEnabledState();
+			}
+		};
+		tableViewer.addSelectionChangedListener(listener);
+
+		createButtons(this);
+	}
+
+	public static String removeLeadingSlash(String uri) {
+		// remove leading slash from the value to avoid the whole leading
+		// slash ambiguity problem
+		//       
+		if (uri != null) {
+			while (uri.startsWith("/") || uri.startsWith("\\")) //$NON-NLS-1$ //$NON-NLS-2$
+			{
+				uri = uri.substring(1);
+			}
+		}
+		return uri;
+	}
+
+	protected XMLCatalogTreeViewer createTableViewer(Composite parent) {
+		String headings[] = new String[2];
+		headings[0] = XMLCatalogMessages.UI_LABEL_KEY;
+		headings[1] = XMLCatalogMessages.UI_LABEL_URI;
+
+		XMLCatalogTreeViewer theTableViewer = new XMLCatalogTreeViewer(parent, workingUserCatalog, systemCatalog);
+		return theTableViewer;
+	}
+
+	protected void createButtons(Composite parent) {
+		Composite composite = new Composite(parent, SWT.NONE);
+		GridData gd = new GridData();
+		gd.verticalAlignment = GridData.BEGINNING;
+		composite.setLayoutData(gd);
+		GridLayout gridLayout = new GridLayout();
+		gridLayout.marginHeight = 0;
+		gridLayout.marginWidth = 0;
+		gridLayout.marginLeft = 3;
+		composite.setLayout(gridLayout);
+
+		SelectionListener selectionListener = new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				if (e.widget == newButton) {
+					performNew();
+				}
+				else if (e.widget == editButton) {
+					performEdit();
+				}
+				else if (e.widget == deleteButton) {
+					performDelete();
+				}
+			}
+		};
+
+		// add the "New..." button
+		//
+		gd = new GridData();
+		gd.horizontalAlignment = GridData.FILL;
+		gd.grabExcessHorizontalSpace = true;
+
+		newButton = new Button(composite, SWT.NONE);
+		newButton.setText(XMLCatalogMessages.UI_BUTTON_NEW);
+		// WorkbenchHelp.setHelp(newButton,
+		// XMLBuilderContextIds.XMLP_MAPPING_NEW);
+		newButton.setLayoutData(gd);
+		newButton.addSelectionListener(selectionListener);
+
+		// add the "Edit..." button
+		//
+		gd = new GridData();
+		gd.horizontalAlignment = GridData.FILL;
+		gd.grabExcessHorizontalSpace = true;
+		editButton = new Button(composite, SWT.NONE);
+		editButton.setText(XMLCatalogMessages.UI_BUTTON_EDIT);
+		// WorkbenchHelp.setHelp(editButton,
+		// XMLBuilderContextIds.XMLP_MAPPING_EDIT);
+		editButton.setLayoutData(gd);
+		editButton.addSelectionListener(selectionListener);
+
+		// add the "Delete" button
+		//
+		gd = new GridData();
+		gd.horizontalAlignment = GridData.FILL;
+		gd.grabExcessHorizontalSpace = true;
+		deleteButton = new Button(composite, SWT.NONE);
+		deleteButton.setText(XMLCatalogMessages.UI_BUTTON_REMOVE);
+		// WorkbenchHelp.setHelp(deleteButton,
+		// XMLBuilderContextIds.XMLP_MAPPING_DELETE);
+		deleteButton.setLayoutData(gd);
+		deleteButton.addSelectionListener(selectionListener);
+		
+		gd = new GridData();
+		gd.horizontalAlignment = GridData.FILL;
+		gd.grabExcessHorizontalSpace = true;
+		gd.horizontalSpan = 4;
+
+		Button hiddenButton = new Button(composite, SWT.NONE);
+		hiddenButton.setLayoutData(gd);
+		hiddenButton.setVisible(false);
+		hiddenButton.setEnabled(false);
+
+		// a cruddy hack so that the PreferenceDialog doesn't close every time
+		// we press 'enter'
+		//
+		getShell().setDefaultButton(hiddenButton);
+		updateWidgetEnabledState();
+	}
+
+	public void refresh() {
+		tableViewer.refresh();// XMLCatalogTreeViewer.USER_SPECIFIED_ENTRIES_OBJECT);
+	}
+
+	protected EditCatalogEntryDialog invokeDialog(String title, ICatalogElement entry, ICatalog catalog) {
+		Shell shell = XMLUIPlugin.getInstance().getWorkbench().getActiveWorkbenchWindow().getShell();
+		EditCatalogEntryDialog dialog = entry != null ? new EditCatalogEntryDialog(shell, entry, catalog) : new EditCatalogEntryDialog(shell, catalog);
+		dialog.create();
+		dialog.getShell().setText(title);
+		dialog.setBlockOnOpen(true);
+		dialog.open();
+		return dialog;
+	}
+
+	protected EditCatalogEntryDialog invokeDialog(String title, ICatalog catalog) {
+		return invokeDialog(title, null, catalog);
+	}
+
+
+	protected void performNew() {
+
+		// ICatalogEntry newEntry =
+		// (ICatalogEntry)workingUserCatalog.createCatalogElement(ICatalogElement.TYPE_ENTRY);
+		EditCatalogEntryDialog dialog = invokeDialog(XMLCatalogMessages.UI_LABEL_NEW_DIALOG_TITLE, workingUserCatalog);
+		ICatalogElement element = dialog.getCatalogElement();
+		if (dialog.getReturnCode() == Window.OK) {
+			workingUserCatalog.addCatalogElement(element);
+			tableViewer.setSelection(new StructuredSelection(element), true);
+			tableViewer.refresh();
+		}
+	}
+
+	protected void performEdit() {
+		ISelection selection = tableViewer.getSelection();
+		Object selectedObject = (selection instanceof IStructuredSelection) ? ((IStructuredSelection) selection).getFirstElement() : null;
+
+		if (selectedObject instanceof ICatalogElement) {
+			ICatalogElement oldEntry = (ICatalogElement) selectedObject;
+			ICatalogElement newEntry = (ICatalogElement) ((CatalogElement) oldEntry).clone();
+
+			EditCatalogEntryDialog dialog = invokeDialog(XMLCatalogMessages.UI_LABEL_EDIT_DIALOG_TITLE, newEntry, workingUserCatalog);
+			if (dialog.getReturnCode() == Window.OK) {
+				// delete the old value if the 'mapFrom' has changed
+				//
+				workingUserCatalog.removeCatalogElement(oldEntry);
+
+				// update the new mapping
+				//
+				workingUserCatalog.addCatalogElement(newEntry);
+				tableViewer.setSelection(new StructuredSelection(newEntry));
+			}
+		}
+	}
+
+	protected void performDelete() {
+		ISelection selection = tableViewer.getSelection();
+		if(selection instanceof IStructuredSelection) {
+			IStructuredSelection structuredSelection = (IStructuredSelection)selection;
+			Iterator iterator = structuredSelection.iterator();
+			while(iterator.hasNext()) {
+				Object selectedObject = iterator.next();
+				if (selectedObject instanceof ICatalogElement) {
+					ICatalogElement catalogElement = (ICatalogElement) selectedObject;
+					workingUserCatalog.removeCatalogElement(catalogElement);
+				}
+			}
+		}
+	}
+
+	protected void updateWidgetEnabledState() {
+		boolean isEditable = false;
+		ISelection selection = tableViewer.getSelection();
+		boolean multipleSelection = false;
+		if(selection instanceof IStructuredSelection) {
+			IStructuredSelection structuredSelection = (IStructuredSelection)selection;
+			if(structuredSelection.size() > 1) {
+				multipleSelection = true;
+			}
+			Object selectedObject = structuredSelection.getFirstElement();
+			if (selectedObject instanceof ICatalogElement) {
+				ICatalogElement[] elements = ((Catalog) workingUserCatalog).getCatalogElements();
+				// dw List entriesList = new ArrayList(elements.length);
+				for (int i = 0; i < elements.length; i++) {
+					ICatalogElement element = elements[i];
+					isEditable = selectedObject.equals(element);
+					if (isEditable) {
+						break;
+					}
+				}
+			}
+		}
+
+		// if (isPageEnabled)
+		{
+			editButton.setEnabled(isEditable & !multipleSelection);
+			deleteButton.setEnabled(isEditable);
+		}
+	}
+
+	/*
+	 * public void setPageEnabled(boolean enabled) { isPageEnabled = enabled;
+	 * 
+	 * tableViewer.getControl().setEnabled(isPageEnabled);
+	 * 
+	 * newButton.setEnabled(isPageEnabled);
+	 * editButton.setEnabled(isPageEnabled);
+	 * deleteButton.setEnabled(isPageEnabled); }
+	 */
+	public void updatePage() {
+		refresh();
+		updateWidgetEnabledState();
+	}
+
+	public Viewer getViewer() {
+		return tableViewer;
+	}
+
+
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/XMLCatalogEntryDetailsView.java b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/XMLCatalogEntryDetailsView.java
new file mode 100644
index 0000000..0546950
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/XMLCatalogEntryDetailsView.java
@@ -0,0 +1,194 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.catalog;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.ScrollBar;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.wst.common.uriresolver.internal.util.URIHelper;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalogElement;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalogEntry;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.IDelegateCatalog;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.INextCatalog;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.IRewriteEntry;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ISuffixEntry;
+
+
+
+public class XMLCatalogEntryDetailsView {
+	protected Text detailsText;
+	protected ScrollBar verticalScroll, horizontalScroll;
+
+	public XMLCatalogEntryDetailsView(Composite parent) {
+		Color color = parent.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND);
+
+		detailsText = new Text(parent, SWT.MULTI | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
+
+		GridData data = new GridData(GridData.FILL_BOTH);
+		data.heightHint = 85;
+		detailsText.setLayoutData(data);
+
+		verticalScroll = detailsText.getVerticalBar();
+		// verticalScroll.setVisible(false);
+		horizontalScroll = detailsText.getHorizontalBar();
+		detailsText.setEditable(false);
+		detailsText.setBackground(color);
+	}
+
+	protected void setCatalogEntry(ICatalogEntry entry) {
+		if (entry == null) {
+			detailsText.setText(""); //$NON-NLS-1$
+			return;
+		}
+		String value = getDisplayValue(entry != null ? entry.getURI() : ""); //$NON-NLS-1$
+		String line0 = XMLCatalogMessages.UI_LABEL_ENTRY_ELEMENT_COLON + "\t\t"; //$NON-NLS-1$
+		String line2 = XMLCatalogMessages.UI_LABEL_DETAILS_URI_COLON + "\t\t\t\t" + value; //$NON-NLS-1$
+		String line1;
+		if (value.startsWith("jar:file:")) { //$NON-NLS-1$
+			String jarFile = URIUtils.convertURIToLocation(URIHelper.ensureURIProtocolFormat(value.substring("jar:".length(), value.indexOf('!')))); //$NON-NLS-1$
+			String internalFile = URIUtils.convertURIToLocation(URIHelper.ensureURIProtocolFormat("file://" + value.substring(value.indexOf('!') + 1))); //$NON-NLS-1$
+			line1 = XMLCatalogMessages.UI_LABEL_DETAILS_URI_LOCATION + "\t\t\t" + internalFile + " " + XMLCatalogMessages.UI_LABEL_DETAILS_IN_JAR_FILE + " " + jarFile; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+		}
+		else {
+			value = URIUtils.convertURIToLocation(value);
+			line1 = XMLCatalogMessages.UI_LABEL_DETAILS_URI_LOCATION + "\t\t\t" + value; //$NON-NLS-1$
+
+		}
+		switch(entry.getEntryType()) {
+			case ICatalogEntry.ENTRY_TYPE_PUBLIC: line0 += XMLCatalogMessages.UI_LABEL_PUBLIC; break;
+			case ICatalogEntry.ENTRY_TYPE_SYSTEM: line0 += XMLCatalogMessages.UI_LABEL_SYSTEM; break;
+			case ICatalogEntry.ENTRY_TYPE_URI: line0 += XMLCatalogMessages.UI_LABEL_URI; break;
+		}
+		value = entry != null ? getKeyTypeValue(entry) : ""; //$NON-NLS-1$
+		String line3 = XMLCatalogMessages.UI_KEY_TYPE_DETAILS_COLON + "\t\t\t" + value; //$NON-NLS-1$
+		value = getDisplayValue(entry != null ? entry.getKey() : ""); //$NON-NLS-1$
+		String line4 = XMLCatalogMessages.UI_LABEL_DETAILS_KEY_COLON + "\t\t\t\t" + value; //$NON-NLS-1$
+		String entireString = line0 + "\n" + line1 + "\n" + line2 + "\n" + line3 + "\n" + line4; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+		detailsText.setText(entireString);
+	}
+
+	protected void setNextCatalog(INextCatalog nextCatalog) {
+		String value = getDisplayValue(nextCatalog != null ? nextCatalog.getCatalogLocation() : ""); //$NON-NLS-1$
+		String line0 = XMLCatalogMessages.UI_LABEL_ENTRY_ELEMENT_COLON + "\t\t" + XMLCatalogMessages.UI_LABEL_NEXT_CATALOG; //$NON-NLS-1$
+		String line1 = XMLCatalogMessages.UI_LABEL_DETAILS_URI_LOCATION + "\t\t\t" + URIUtils.convertURIToLocation(value); //$NON-NLS-1$
+		String line2 = XMLCatalogMessages.UI_LABEL_DETAILS_URI_COLON + "\t\t\t\t" + value; //$NON-NLS-1$
+		String entireString = line0 + "\n" + line1 + "\n" + line2; //$NON-NLS-1$ //$NON-NLS-2$
+		detailsText.setText(entireString);
+	}
+	
+	protected void setSuffixEntry(ISuffixEntry element) {
+		String value = getDisplayValue(element != null ? element.getURI() : ""); //$NON-NLS-1$
+		String line0 = XMLCatalogMessages.UI_LABEL_ENTRY_ELEMENT_COLON + "\t\t" + XMLCatalogMessages.UI_LABEL_SUFFIX_ENTRY; //$NON-NLS-1$
+		String line1 = XMLCatalogMessages.UI_LABEL_DETAILS_SUFFIX_COLON + "\t\t\t\t" + element.getSuffix(); //$NON-NLS-1$
+		String line2 = XMLCatalogMessages.UI_LABEL_DETAILS_URI_LOCATION + "\t\t\t" + URIUtils.convertURIToLocation(value); //$NON-NLS-1$
+		String line3 = XMLCatalogMessages.UI_KEY_TYPE_DETAILS_COLON + "\t\t\t"; //$NON-NLS-1$
+		String uri = element.getURI();
+		boolean isSchema = false;
+		if(uri != null && uri.endsWith("xsd")) { //$NON-NLS-1$
+			isSchema = true;
+		}
+		switch (element.getEntryType()) {
+		case ISuffixEntry.SUFFIX_TYPE_SYSTEM:
+			line3 += isSchema? XMLCatalogMessages.UI_KEY_TYPE_DESCRIPTION_XSD_SYSTEM : XMLCatalogMessages.UI_KEY_TYPE_DESCRIPTION_DTD_SYSTEM;
+			break;
+		default:
+		case ISuffixEntry.SUFFIX_TYPE_URI:
+			line3 += isSchema? XMLCatalogMessages.UI_KEY_TYPE_DESCRIPTION_XSD_PUBLIC : XMLCatalogMessages.UI_KEY_TYPE_DESCRIPTION_URI;
+			break;
+		}
+		String entireString = line0 + "\n" + line1 +"\n" + line2 + "\n" + line3; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+		detailsText.setText(entireString);
+	}
+
+	protected void setRewriteEntry(IRewriteEntry element) {
+		String line0 = XMLCatalogMessages.UI_LABEL_ENTRY_ELEMENT_COLON + "\t\t" + XMLCatalogMessages.UI_LABEL_REWRITE_ENTRY; //$NON-NLS-1$
+		String line1 = XMLCatalogMessages.UI_LABEL_START_STRING + "\t\t" + element.getStartString(); //$NON-NLS-1$
+		String line2 = XMLCatalogMessages.UI_LABEL_REWRITE_PREFIX + "\t" + element.getRewritePrefix(); //$NON-NLS-1$
+		String line3 = XMLCatalogMessages.UI_KEY_TYPE_DETAILS_COLON  + "\t\t\t" ; //$NON-NLS-1$
+		switch (element.getEntryType()) {
+		case IRewriteEntry.REWRITE_TYPE_SYSTEM:
+			line3 += XMLCatalogMessages.UI_KEY_TYPE_DESCRIPTION_DTD_SYSTEM;
+			break;
+		default:
+		case IRewriteEntry.REWRITE_TYPE_URI:
+			line3 += XMLCatalogMessages.UI_KEY_TYPE_DESCRIPTION_URI;
+			break;
+		}
+		String entireString = line0 + "\n" + line1 + "\n" + line2 + "\n" + line3; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+		detailsText.setText(entireString);
+	}
+
+	protected void setDelegateCatalog(IDelegateCatalog element) {
+		String value = getDisplayValue(element != null ? element.getCatalogLocation() : ""); //$NON-NLS-1$
+		String line0 = XMLCatalogMessages.UI_LABEL_ENTRY_ELEMENT_COLON + "\t\t" + XMLCatalogMessages.UI_LABEL_DELEGATE_CATALOG; //$NON-NLS-1$
+		String line1 = XMLCatalogMessages.UI_LABEL_START_STRING + "\t\t" + element.getStartString(); //$NON-NLS-1$
+		String line2 = XMLCatalogMessages.UI_LABEL_DETAILS_URI_LOCATION + "\t\t\t" + URIUtils.convertURIToLocation(value); //$NON-NLS-1$
+		String line3 = XMLCatalogMessages.UI_KEY_TYPE_DETAILS_COLON + "\t\t\t"; //$NON-NLS-1$
+		switch (element.getEntryType()) {
+		case IDelegateCatalog.DELEGATE_TYPE_PUBLIC:
+			line3 += XMLCatalogMessages.UI_KEY_TYPE_DESCRIPTION_DTD_PUBLIC;
+			break;
+		case IDelegateCatalog.DELEGATE_TYPE_SYSTEM:
+			line3 += XMLCatalogMessages.UI_KEY_TYPE_DESCRIPTION_DTD_SYSTEM;
+			break;
+		default:
+		case IDelegateCatalog.DELEGATE_TYPE_URI:
+			line3 += XMLCatalogMessages.UI_KEY_TYPE_DESCRIPTION_URI;
+			break;
+		}
+		String entireString = line0 + "\n" + line1 + "\n" + line2 + "\n" + line3; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+		detailsText.setText(entireString);
+	}
+
+	public void setCatalogElement(ICatalogElement element) {
+		// I wish we had a visitor for this kind of mess
+		if (element instanceof ICatalogEntry) setCatalogEntry((ICatalogEntry)element);
+		else if (element instanceof INextCatalog) setNextCatalog((INextCatalog)element);
+		else if (element instanceof IDelegateCatalog) setDelegateCatalog((IDelegateCatalog)element);
+		else if (element instanceof IRewriteEntry) setRewriteEntry((IRewriteEntry)element);
+		else if (element instanceof ISuffixEntry) setSuffixEntry((ISuffixEntry)element);
+		else setCatalogEntry(null); // Gives null text
+	}
+
+
+	protected String getDisplayValue(String string) {
+		return string != null ? string : ""; //$NON-NLS-1$
+	}
+
+	protected String getKeyTypeValue(ICatalogEntry entry) {
+		String result = null;
+		if ((entry.getURI() != null) && entry.getURI().endsWith("xsd")) //$NON-NLS-1$
+		{
+			result = (entry.getEntryType() == ICatalogEntry.ENTRY_TYPE_URI) ? XMLCatalogMessages.UI_KEY_TYPE_DESCRIPTION_XSD_PUBLIC : XMLCatalogMessages.UI_KEY_TYPE_DESCRIPTION_XSD_SYSTEM;
+		}
+		else {
+			switch (entry.getEntryType()) {
+				case ICatalogEntry.ENTRY_TYPE_PUBLIC :
+					result = XMLCatalogMessages.UI_KEY_TYPE_DESCRIPTION_DTD_PUBLIC;
+					break;
+				case ICatalogEntry.ENTRY_TYPE_SYSTEM :
+					result = XMLCatalogMessages.UI_KEY_TYPE_DESCRIPTION_DTD_SYSTEM;
+					break;
+				default :
+					result = XMLCatalogMessages.UI_KEY_TYPE_DESCRIPTION_URI;
+					break;
+			}
+
+		}
+		return result;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/XMLCatalogFileType.java b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/XMLCatalogFileType.java
new file mode 100644
index 0000000..c3cbbe8
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/XMLCatalogFileType.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.catalog;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import com.ibm.icu.util.StringTokenizer;
+
+import org.eclipse.swt.graphics.Image;
+
+
+public class XMLCatalogFileType {
+	public String description;
+    public String id;
+	public List extensions = new ArrayList();
+	public String iconFileName;
+	public Image icon;
+
+	public void addExtensions(String contributedExtensions) {
+		List list = parseExtensions(contributedExtensions);
+		for (Iterator i = list.iterator(); i.hasNext();) {
+			String extension = (String) i.next();
+			if (!extensions.contains(extension)) {
+				extensions.add(extension);
+			}
+		}
+	}
+
+	protected List parseExtensions(String string) {
+		List list = new ArrayList();
+		for (StringTokenizer st = new StringTokenizer(string, ", "); st.hasMoreTokens();) //$NON-NLS-1$
+		{
+			String token = st.nextToken();
+			if (token != null) {
+				list.add(token);
+			}
+		}
+		return list;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/XMLCatalogMessages.java b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/XMLCatalogMessages.java
new file mode 100644
index 0000000..fc526b6
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/XMLCatalogMessages.java
@@ -0,0 +1,162 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 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 - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.catalog;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Strings used by XML Editor
+ * 
+ * @plannedfor 1.0
+ */
+public class XMLCatalogMessages extends NLS {
+	private static final String BUNDLE_NAME = "org.eclipse.wst.xml.ui.internal.catalog.XMLCatalogResources";//$NON-NLS-1$
+
+	public static String UI_WIZARD_SCHEMA_AND_NAME_SPACE_INFO;
+	public static String UI_LABEL_NAME_SPACE_PREFIX;
+	public static String UI_LABEL_NAME_SPACE_URI;
+	public static String UI_LABEL_XSD_LOCATION;
+	public static String UI_LABEL_DOCTYPE_INFORMATION;
+	public static String UI_LABEL_SYSTEM_ID;
+	public static String UI_LABEL_PUBLIC_ID;
+	public static String UI_LABEL_SELECT_FILE;
+	public static String UI_LABEL_KEY;
+	public static String UI_LABEL_KEY_COLON;
+	public static String UI_LABEL_SUFFIX;
+	public static String UI_LABEL_SUFFIX_COLON;
+	public static String UI_LABEL_DETAILS_KEY_COLON;
+	public static String UI_LABEL_DETAILS_IN_JAR_FILE;
+	public static String UI_LABEL_URI;
+	public static String UI_LABEL_LOCATION_COLON;
+	public static String UI_MATCH_KEY_TYPE_COLON;
+	public static String UI_LABEL_ARROW;
+	public static String UI_LABEL_CATALOG_URI_COLON;
+	public static String UI_LABEL_DETAILS_URI_COLON;
+	public static String UI_LABEL_DETAILS_URI_LOCATION;
+	public static String UI_KEY_TYPE_COLON;
+	public static String UI_ELEMENT_TYPE_COLON;
+	public static String UI_LABEL_START_STRING_COLON;
+	public static String UI_LABEL_REWRITE_PREFIX_COLON;
+	public static String UI_KEY_TYPE_DETAILS_COLON;
+	public static String UI_KEY_TYPE_DESCRIPTION_XSD_PUBLIC;
+	public static String UI_KEY_TYPE_DESCRIPTION_XSD_SYSTEM;
+	public static String UI_KEY_TYPE_DESCRIPTION_DTD_PUBLIC;
+	public static String UI_KEY_TYPE_DESCRIPTION_DTD_SYSTEM;
+	public static String UI_KEY_TYPE_DESCRIPTION_URI;
+	public static String UI_LABEL_SPECIFY_ALTERNATIVE_WEB_URL;
+	public static String UI_WARNING_URI_MUST_NOT_HAVE_DOTS;
+	public static String UI_LABEL_FILE_SELECTION;
+	public static String UI_LABEL_CHOOSE_FILE_TO_ADD_TO_CATALOG;
+
+
+	public static String UI_WARNING_URI_NOT_FOUND_COLON;
+	public static String UI_WARNING_URI_NOT_FOUND_LONG;
+	public static String UI_WARNING_INVALID_FILE;
+	public static String UI_WARNING_INVALID_FILE_LONG;
+	public static String UI_WARNING_NO_ELEMENT;
+	public static String UI_WARNING_NO_ELEMENT_DTD_LONG;
+	public static String UI_WARNING_NO_ELEMENT_XSD_LONG;
+	public static String UI_WARNING_SHOULD_BE_FULLY_QUALIFIED_URI;
+	public static String UI_WARNING_DUPLICATE_ENTRY;
+	public static String UI_WARNING_DUPLICATE_SUFFIX;
+	public static String UI_WARNING_DUPLICATE_REWRITE;
+	public static String UI_WARNING_DUPLICATE_DELEGATE;
+	
+	// NewModelWizard
+	public static String UI_INVALID_GRAMMAR_ERROR;
+	public static String UI_BUTTON_BROWSE;
+
+	// XMLCatalogIdMappingPage
+	public static String UI_LABEL_MAP_TO;
+	public static String UI_LABEL_MAP_FROM;
+	public static String UI_BUTTON_NEW;
+	public static String UI_BUTTON_EDIT;
+	public static String UI_BUTTON_DELETE;
+	public static String UI_BUTTON_REMOVE;
+	public static String UI_LABEL_NEW_DIALOG_TITLE;
+	public static String UI_LABEL_EDIT_DIALOG_TITLE;
+
+
+	// XMLCatalogPreferencePage
+	public static String UI_LABEL_USER_ENTRIES;
+	public static String UI_LABEL_USER_ENTRIES_TOOL_TIP;
+	public static String UI_LABEL_SYSTEM_ENTRIES;
+	public static String UI_LABEL_SYSTEM_ENTRIES_TOOL_TIP;
+	public static String UI_BUTTON_CHANGE;
+	public static String UI_LABEL_SELECT_PROJECT;
+	public static String UI_LABEL_SPECIFY_PROJECT_DESCRIPTION;
+	public static String UI_WARNING_NO_PROJECTS_CREATED;
+	public static String UI_WARNING_PROJECT_NOT_SPECIFIED;
+	public static String UI_WARNING_PROJECT_DOES_NOT_EXIST;
+	public static String UI_LABEL_PROJECT_TO_USE;
+	public static String UI_LABEL_CATALOG_SAVE_ERROR;
+	public static String UI_LABEL_CATALOG_COULD_NOT_BE_SAVED;
+	public static String UI_LABEL_ADVANCED;
+	public static String UI_LABEL_ADVANCED_XML_CATALOG_PREFS;
+	public static String UI_LABEL_SPECIFY_PERSISTENCE_FILE;
+	public static String UI_LABEL_SAVE_CATALOG_DIALOG_TITLE;
+	public static String UI_LABEL_SAVE_CATALOG_DIALOG_DESC;
+	public static String UI_LABEL_BROWSE_CATALOG_FILE_TITLE;
+	public static String UI_LABEL_BROWSE_CATALOG_FILE_DESC;
+	public static String UI_LABEL_DETAILS;
+	public static String UI_LABEL_USER_SPECIFIED_ENTRIES;
+	public static String UI_LABEL_PLUGIN_SPECIFIED_ENTRIES;
+	public static String UI_LABEL_PLATFORM_RESOURCE;
+	public static String UI_LABEL_FILE_SYSTEM_RESOURCE;
+	// AdvancedOptionsDialog
+	public static String UI_BUTTON_IMPORT;
+	public static String UI_BUTTON_EXPORT;
+
+	public static String UI_LABEL_IMPORT_DIALOG_TITLE;
+	public static String UI_LABEL_IMPORT_DIALOG_HEADING;
+	public static String UI_LABEL_IMPORT_DIALOG_MESSAGE;
+
+	public static String UI_LABEL_EXPORT_DIALOG_TITLE;
+	public static String UI_LABEL_EXPORT_DIALOG_HEADING;
+	public static String UI_LABEL_EXPORT_DIALOG_MESSAGE;
+	public static String ERROR_SAVING_FILE;
+	public static String UI_LABEL_FILE_IS_READ_ONLY;
+	public static String UI_LABEL_DIALOG_DESCRIPTION;
+
+	public static String UI_LABEL_NEXT_CATALOG;
+	public static String UI_LABEL_DELEGATE_CATALOG;
+	public static String UI_LABEL_REWRITE_ENTRY;
+	public static String UI_LABEL_SUFFIX_ENTRY;
+
+	public static String UI_LABEL_DELEGATE_CATALOG_URI_COLON;
+	public static String EditCatalogEntryDialog_catalogEntryLabel;
+	public static String EditCatalogEntryDialog_nextCatalogLabel;
+	public static String EditCatalogEntryDialog_rewriteEntryLabel;
+	public static String EditCatalogEntryDialog_suffixEntryLabel;
+	public static String EditCatalogEntryDialog_delegateCatalogLabel;
+	public static String UI_BUTTON_MENU_BROWSE_WORKSPACE;
+	public static String UI_BUTTON_MENU_BROWSE_FILE_SYSTEM;
+	public static String UI_LABEL_SELECT_FILE_FILTER_CONTROL;
+	public static String UI_TEXT_SELECT_FILE_FILTER_CONTROL;
+	
+	public static String UI_LABEL_PUBLIC;
+	public static String UI_LABEL_SYSTEM;
+
+	public static String UI_LABEL_START_STRING;
+	public static String UI_LABEL_REWRITE_PREFIX;
+	public static String UI_LABEL_ENTRY_ELEMENT_COLON;
+
+	public static String UI_LABEL_DETAILS_SUFFIX_COLON;
+	
+	static {
+		// load message values from bundle file
+		NLS.initializeMessages(BUNDLE_NAME, XMLCatalogMessages.class);
+	}
+
+	private XMLCatalogMessages() {
+		// cannot create new instance
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/XMLCatalogPreferencePage.java b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/XMLCatalogPreferencePage.java
new file mode 100644
index 0000000..e84a82a
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/XMLCatalogPreferencePage.java
@@ -0,0 +1,235 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     David Carver/STAR Standard - d_a_carver@yahoo.com - bug 192568
+ *            Removed Advanced button - Functionality is now in the
+ *            Import/Export XML Catalog Wizards. 
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.catalog;
+
+import org.eclipse.jface.preference.PreferencePage;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+import org.eclipse.wst.xml.core.internal.XMLCorePlugin;
+import org.eclipse.wst.xml.core.internal.catalog.CatalogSet;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalog;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalogElement;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalogEvent;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalogListener;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.INextCatalog;
+
+public class XMLCatalogPreferencePage extends PreferencePage implements IWorkbenchPreferencePage, ICatalogListener {
+
+	protected XMLCatalogEntriesView catalogEntriesView;
+
+	protected ICatalog workingUserCatalog;
+
+	protected ICatalog systemCatalog;
+
+	protected ICatalog userCatalog;
+
+	protected ICatalog defaultCatalog;
+
+	protected Button advancedButton;
+
+	public XMLCatalogPreferencePage() {
+		defaultCatalog = XMLCorePlugin.getDefault().getDefaultXMLCatalog();
+		INextCatalog[] nextCatalogs = defaultCatalog.getNextCatalogs();
+		for (int i = 0; i < nextCatalogs.length; i++) {
+			INextCatalog catalog = nextCatalogs[i];
+			ICatalog referencedCatalog = catalog.getReferencedCatalog();
+			if (referencedCatalog != null) {
+				if (XMLCorePlugin.SYSTEM_CATALOG_ID.equals(referencedCatalog.getId())) {
+					systemCatalog = referencedCatalog;
+				}
+				else if (XMLCorePlugin.USER_CATALOG_ID.equals(referencedCatalog.getId())) {
+					userCatalog = referencedCatalog;
+				}
+			}
+		}
+	}
+
+	public void dispose() {
+		super.dispose();
+		workingUserCatalog.removeListener(this);
+	}
+
+	/**
+	 * Refresh the view in responce to an event sent by the Catalog
+	 */
+	public void catalogChanged(ICatalogEvent event) {
+		catalogEntriesView.updatePage();
+	}
+
+	/**
+	 * Creates preference page controls on demand.
+	 * 
+	 * @param parent
+	 *            the parent for the preference page
+	 */
+	protected Control createContents(Composite parent) {
+		// we create a working copy of the 'User Settings' for the Catalog
+		// that we can modify
+		CatalogSet tempCatalogSet = new CatalogSet();
+		workingUserCatalog = tempCatalogSet.lookupOrCreateCatalog("working", ""); //$NON-NLS-1$ //$NON-NLS-2$
+
+		// TODO: add entries from the nested catalogs as well
+		workingUserCatalog.addEntriesFromCatalog(userCatalog);
+		workingUserCatalog.addListener(this);
+		noDefaultAndApplyButton();
+		Composite composite = new Composite(parent, SWT.NULL);
+		// WorkbenchHelp.setHelp(composite, new
+		// ControlContextComputer(composite,
+		// XMLBuilderContextIds.XMLP_CATALOG_PAGE));
+		composite.setLayout(new GridLayout());
+		composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+		createCatalogEntriesView(composite);
+		createCatalogDetailsView(composite);
+		//createAdvancedButton(composite);
+		// catalogEntriesView.updatePage();
+		applyDialogFont(composite);
+
+		return composite;
+	}
+
+	/**
+	 * @deprecated
+	 * @param composite
+	 */
+	protected void createAdvancedButton(Composite composite) {
+		Composite panel = new Composite(composite, SWT.NONE);
+		GridLayout gridLayout = new GridLayout();
+		gridLayout.numColumns = 3;
+		panel.setLayout(gridLayout);
+		panel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+		// TODO... is there a better way to expand the page width?
+		// This invisible label is created to force the width of the page to
+		// be
+		// wide enough to show
+		// the rather long uri and key fields of a catalog entry.
+		Label widthFudger = new Label(panel, SWT.NONE);
+		String widthFudgerString = ""; //$NON-NLS-1$
+		for (int i = 0; i < 55; i++) {
+			widthFudgerString += "x"; //$NON-NLS-1$
+		}
+		widthFudger.setText(widthFudgerString);
+		widthFudger.setVisible(false);
+		Composite placeHolder = new Composite(panel, SWT.NONE);
+		placeHolder.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+		advancedButton = new Button(panel, SWT.NONE);
+		advancedButton.setText(XMLCatalogMessages.UI_LABEL_ADVANCED);
+		SelectionListener selectionListener = new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				AdvancedOptionsDialog dialog = new AdvancedOptionsDialog(getShell(), workingUserCatalog);
+				dialog.create();
+				dialog.getShell().setText(XMLCatalogMessages.UI_LABEL_ADVANCED_XML_CATALOG_PREFS);
+				dialog.setBlockOnOpen(true);
+				dialog.open();
+			}
+		};
+		advancedButton.addSelectionListener(selectionListener);
+	}
+
+	public boolean isSameFileName(String a, String b) {
+		boolean result = false;
+		if ((a == null) && (b == null)) {
+			result = true;
+		}
+		else if ((a != null) && (b != null)) {
+			result = a.equals(b);
+		}
+		return result;
+	}
+
+	protected void createCatalogEntriesView(Composite parent) {
+		Group group = new Group(parent, SWT.NONE);
+		group.setLayout(new GridLayout());
+		group.setLayoutData(new GridData(GridData.FILL_BOTH));
+		group.setText(XMLCatalogMessages.UI_LABEL_USER_ENTRIES);
+		group.setToolTipText(XMLCatalogMessages.UI_LABEL_USER_ENTRIES_TOOL_TIP);
+		// WorkbenchHelp.setHelp(userEntriesGroup, new
+		// ControlContextComputer(userEntriesGroup,
+		// XMLBuilderContextIds.XMLP_CATALOG_USER_GROUP));
+		catalogEntriesView = new XMLCatalogEntriesView(group, workingUserCatalog, systemCatalog);
+		catalogEntriesView.setLayoutData(new GridData(GridData.FILL_BOTH));
+	}
+
+	protected void createCatalogDetailsView(Composite parent) {
+		Group detailsGroup = new Group(parent, SWT.NONE);
+		detailsGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+		detailsGroup.setLayout(new GridLayout());
+		detailsGroup.setText(XMLCatalogMessages.UI_LABEL_DETAILS);
+		final XMLCatalogEntryDetailsView detailsView = new XMLCatalogEntryDetailsView(detailsGroup);
+		ISelectionChangedListener listener = new ISelectionChangedListener() {
+			public void selectionChanged(SelectionChangedEvent event) {
+				ISelection selection = event.getSelection();
+				Object selectedObject = (selection instanceof IStructuredSelection) && ((IStructuredSelection) selection).size() == 1 ? ((IStructuredSelection) selection).getFirstElement() : null;
+				if (selectedObject instanceof ICatalogElement) {
+					detailsView.setCatalogElement((ICatalogElement)selectedObject);
+				} else {
+					detailsView.setCatalogElement(null);
+				}
+			}
+		};
+		catalogEntriesView.getViewer().addSelectionChangedListener(listener);
+	}
+
+	/**
+	 * Do anything necessary because the OK button has been pressed.
+	 * 
+	 * @return whether it is okay to close the preference page
+	 */
+	public boolean performOk() {
+		return storeValues();
+	}
+
+	/**
+	 * @see IWorkbenchPreferencePage
+	 */
+	public void init(IWorkbench workbench) {
+	}
+
+	/**
+	 * Stores the values of the controls back to the preference store.
+	 */
+	private boolean storeValues() {
+		// dw Object fileObject = null;
+		try {
+			// update the userCatalog so that its the same as the working
+			// catalog
+			userCatalog.clear();
+			// TODO add entries from the nested catalogs?
+			userCatalog.addEntriesFromCatalog(workingUserCatalog);
+			// now save the userCatalog
+			userCatalog.save();
+		}
+		catch (Exception e) {
+		}
+		return true;
+	}
+
+
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/XMLCatalogResources.properties b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/XMLCatalogResources.properties
new file mode 100644
index 0000000..9af908a
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/XMLCatalogResources.properties
@@ -0,0 +1,141 @@
+###############################################################################
+# 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
+#     David Carver/STAR Standard, d_a_carver@yahoo.com, bug 192568
+#        - Fixed grammar in XML Catalog Import dialog.
+###############################################################################
+UI_WIZARD_SCHEMA_AND_NAME_SPACE_INFO = Schema and Namespace Information
+UI_LABEL_NAME_SPACE_PREFIX           = Namespace prefix:
+UI_LABEL_NAME_SPACE_URI              = Namespace URI:
+UI_LABEL_XSD_LOCATION                = Schema location:
+UI_LABEL_DOCTYPE_INFORMATION         = Document type information
+UI_LABEL_SYSTEM_ID                   = &System ID:
+UI_LABEL_PUBLIC_ID                   = &Public ID:
+UI_LABEL_SELECT_FILE                 = Select File
+UI_LABEL_KEY                         = Key
+UI_LABEL_KEY_COLON                   = &Key:
+UI_LABEL_SUFFIX                      = Suffix
+UI_LABEL_SUFFIX_COLON                = S&uffix:
+UI_LABEL_DETAILS_KEY_COLON           = Key:
+UI_LABEL_DETAILS_IN_JAR_FILE		 = in jar file
+UI_LABEL_URI                         = URI
+UI_LABEL_START_STRING_COLON          = &Matching start string:
+UI_LABEL_REWRITE_PREFIX_COLON        = Rewrite prefi&x:   
+UI_LABEL_ARROW				         = ->
+UI_LABEL_LOCATION_COLON              = &Location:  
+UI_LABEL_DELEGATE_CATALOG_URI_COLON	 = D&elegate to this XML Catalog file:
+UI_LABEL_CATALOG_URI_COLON		      = &Location of another XML Catalog file:
+UI_LABEL_DETAILS_URI_COLON           = URI:   
+UI_KEY_TYPE_COLON                    = Key &type:
+UI_KEY_TYPE_DETAILS_COLON            = Key type:
+UI_MATCH_KEY_TYPE_COLON              = &Key type to match:
+UI_LABEL_DETAILS_URI_LOCATION        = Location:
+UI_KEY_TYPE_DESCRIPTION_XSD_PUBLIC   = Namespace name
+UI_KEY_TYPE_DESCRIPTION_XSD_SYSTEM   = Schema location
+UI_KEY_TYPE_DESCRIPTION_DTD_PUBLIC   = Public ID
+UI_KEY_TYPE_DESCRIPTION_DTD_SYSTEM   = System ID
+UI_KEY_TYPE_DESCRIPTION_URI   		 = URI
+UI_LABEL_SPECIFY_ALTERNATIVE_WEB_URL = &Alternative web address:
+UI_WARNING_URI_MUST_NOT_HAVE_DOTS    = URI must not include '.' or '..'
+UI_LABEL_PLATFORM_RESOURCE 		 	 = Workspace
+UI_LABEL_FILE_SYSTEM_RESOURCE		 = File system
+UI_ELEMENT_TYPE_COLON                = Catalog element type:
+UI_LABEL_NEXT_CATALOG				 = Next catalog
+UI_LABEL_DELEGATE_CATALOG			 = Delegate catalog
+UI_LABEL_REWRITE_ENTRY				 = Rewrite
+UI_LABEL_SUFFIX_ENTRY				 = Suffix
+UI_LABEL_ENTRY_ELEMENT_COLON		 = Entry element:
+UI_LABEL_PUBLIC						 = Public
+UI_LABEL_SYSTEM						 = System
+
+UI_WARNING_URI_NOT_FOUND_COLON       = The specified resource can't be located :
+UI_WARNING_SHOULD_BE_FULLY_QUALIFIED_URI = Warning: the key value should be a fully qualified URI
+UI_WARNING_URI_NOT_FOUND_LONG        = The specified file cannot be found. It may have been moved to a different location. If the file is located remotely, a network connection cannot be established to the remote location. 
+UI_WARNING_INVALID_FILE              = The specified file is invalid.
+UI_WARNING_INVALID_FILE_LONG         = The specified file is invalid. A proper XML file cannot be generated from it. Open the DTD or XML schema file, edit it as necessary, validate it and try again.
+UI_WARNING_NO_ELEMENT                = The specified file must contain at least one element declaration.
+UI_WARNING_NO_ELEMENT_DTD_LONG       = The specified file must contain at least one element declaration that can be used as the root element in the generated XML file.
+UI_WARNING_NO_ELEMENT_XSD_LONG       = The specified file must contain at least one global element declaration that can be used as the root element in the generated XML file.
+UI_WARNING_DUPLICATE_ENTRY			 = The specified entry is invalid. An existing entry has the same key and key type.
+UI_WARNING_DUPLICATE_SUFFIX			 = The specified suffix is invalid. An existing entry has the same key type and suffix.
+UI_WARNING_DUPLICATE_REWRITE		 = The specified rewrite start string is invalid. An existing entry has the same start string.
+UI_WARNING_DUPLICATE_DELEGATE		 = The specified delegate start string is invalid. An existing entry has the same prefix.
+
+
+!NewModelWizard
+UI_INVALID_GRAMMAR_ERROR             = Invalid Grammar
+UI_BUTTON_BROWSE                     = &Browse...
+
+!XMLCatalogIdMappingPage
+UI_LABEL_MAP_TO                      = Map to:
+UI_LABEL_MAP_FROM                    = Map from:
+UI_BUTTON_NEW                        = &Add...
+UI_BUTTON_EDIT                       = &Edit...
+UI_BUTTON_DELETE                     = &Delete
+UI_BUTTON_REMOVE                     = &Remove
+UI_LABEL_NEW_DIALOG_TITLE            = Add XML Catalog Element
+UI_LABEL_EDIT_DIALOG_TITLE           = Edit XML Catalog Element
+
+
+!XMLCatalogPreferencePage
+UI_LABEL_USER_ENTRIES                = XML Catalog Entries
+UI_LABEL_USER_ENTRIES_TOOL_TIP       = XML Catalog entries that have been specified by the user
+UI_LABEL_SYSTEM_ENTRIES              = Plug-in specified entries
+UI_LABEL_SYSTEM_ENTRIES_TOOL_TIP     = XML Catalog entries that have been specified by a plug-in
+UI_BUTTON_CHANGE                     = Change...
+UI_LABEL_SELECT_PROJECT              = Select Project
+UI_LABEL_SPECIFY_PROJECT_DESCRIPTION = Specify the project to persist the XML Catalog information
+UI_WARNING_NO_PROJECTS_CREATED       = No projects have been created yet.
+UI_WARNING_PROJECT_NOT_SPECIFIED     = A project name has not been specified.
+UI_WARNING_PROJECT_DOES_NOT_EXIST    = The specified project does not exist.
+UI_LABEL_PROJECT_TO_USE              = Project to use to persist XML Catalog User Entries: 
+UI_LABEL_CATALOG_SAVE_ERROR          = XML Catalog Save Error
+UI_LABEL_CATALOG_COULD_NOT_BE_SAVED  = The XML Catalog entry could not be saved.
+UI_LABEL_ADVANCED                    = &Advanced...
+UI_LABEL_ADVANCED_XML_CATALOG_PREFS  = Advanced XML Catalog Preferences   
+UI_LABEL_SPECIFY_PERSISTENCE_FILE    = &Specify a file to use to persist the XML Catalog information.
+UI_LABEL_SAVE_CATALOG_DIALOG_TITLE   = Save Changes
+UI_LABEL_SAVE_CATALOG_DIALOG_DESC    = You have made unsaved changes to the current XML Catalog settings. Do you wish to save your changes before loading the new XML Catalog settings?   
+UI_LABEL_BROWSE_CATALOG_FILE_TITLE   = Select Folder
+UI_LABEL_BROWSE_CATALOG_FILE_DESC    = Select the folder that contains the '.xmlcatalog' file.   
+UI_LABEL_DETAILS                     = Details
+UI_LABEL_USER_SPECIFIED_ENTRIES      = User Specified Entries
+UI_LABEL_PLUGIN_SPECIFIED_ENTRIES    = Plugin Specified Entries
+UI_LABEL_FILE_SELECTION				 = File Selection
+UI_LABEL_CHOOSE_FILE_TO_ADD_TO_CATALOG				 = Choose a file to add to the XML Catalog
+ 
+!AdvancedOptionsDialog
+UI_LABEL_DIALOG_DESCRIPTION          = Use the buttons below to import or export XML Catalog settings.
+UI_BUTTON_IMPORT                     = Import...
+UI_BUTTON_EXPORT                     = Export...
+                                   
+UI_LABEL_IMPORT_DIALOG_TITLE         = Import XML Catalog Settings
+UI_LABEL_IMPORT_DIALOG_HEADING       = Specify XML Catalog File
+UI_LABEL_IMPORT_DIALOG_MESSAGE       = Specify the file that will be used to load the XML Catalog Settings
+
+UI_LABEL_EXPORT_DIALOG_TITLE         = Export XML Catalog Settings
+UI_LABEL_EXPORT_DIALOG_HEADING       = Specify XML Catalog File
+UI_LABEL_EXPORT_DIALOG_MESSAGE       = Specify the file that will used to save the XML Catalog Setting
+ERROR_SAVING_FILE					 = Error saving file %1
+UI_LABEL_FILE_IS_READ_ONLY           = File %1 is read only
+
+UI_LABEL_START_STRING = Start string:
+UI_LABEL_REWRITE_PREFIX = Rewrite prefix:
+
+UI_LABEL_DETAILS_SUFFIX_COLON = Suffix:
+
+EditCatalogEntryDialog_catalogEntryLabel=&Catalog Entry
+EditCatalogEntryDialog_nextCatalogLabel=&Next Catalog
+EditCatalogEntryDialog_rewriteEntryLabel=&Rewrite Entry
+EditCatalogEntryDialog_suffixEntryLabel=&Suffix Entry
+EditCatalogEntryDialog_delegateCatalogLabel=&Delegate Catalog
+UI_BUTTON_MENU_BROWSE_WORKSPACE=&Workspace...
+UI_BUTTON_MENU_BROWSE_FILE_SYSTEM=&File System...
+UI_LABEL_SELECT_FILE_FILTER_CONTROL=Files of type:
+UI_TEXT_SELECT_FILE_FILTER_CONTROL=All Supported Files
diff --git a/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/XMLCatalogTreeViewer.java b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/XMLCatalogTreeViewer.java
new file mode 100644
index 0000000..e09b35c
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/XMLCatalogTreeViewer.java
@@ -0,0 +1,301 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.catalog;
+
+import com.ibm.icu.text.Collator;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerFilter;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.IEditorRegistry;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.wst.common.uriresolver.internal.util.URIHelper;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalog;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalogElement;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalogEntry;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.IDelegateCatalog;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.INextCatalog;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.IRewriteEntry;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ISuffixEntry;
+
+
+public class XMLCatalogTreeViewer extends TreeViewer {
+	protected static Image xmlCatalogImage = ImageFactory.INSTANCE.getImage("icons/obj16/xmlcatalog_obj.gif"); //$NON-NLS-1$
+	protected static Image errorImage = ImageFactory.INSTANCE.getImage("icons/ovr16/error-overlay.gif"); //$NON-NLS-1$
+	protected static Image entryImage = ImageFactory.INSTANCE.getImage("icons/obj16/entry_obj.png"); //$NON-NLS-1$
+	protected static Image nextCatalogImage = ImageFactory.INSTANCE.getImage("icons/obj16/nextCatalog_obj.gif"); //$NON-NLS-1$
+	protected static Image rewriteEntryImage = ImageFactory.INSTANCE.getImage("icons/obj16/rewrite_entry.gif"); //$NON-NLS-1$
+	protected static Image suffixEntryImage = ImageFactory.INSTANCE.getImage("icons/obj16/suffix_entry.gif"); //$NON-NLS-1$
+	protected static Image delegateCatalogImage = ImageFactory.INSTANCE.getImage("icons/obj16/delegate_catalog.gif"); //$NON-NLS-1$
+
+	protected static String ERROR_STATE_KEY = "errorstatekey"; //$NON-NLS-1$
+
+	protected ICatalog fWorkingUserCatalog;
+	protected ICatalog fSystemCatalog;
+
+	public static String USER_SPECIFIED_ENTRIES_OBJECT = XMLCatalogMessages.UI_LABEL_USER_SPECIFIED_ENTRIES;
+	public static String PLUGIN_SPECIFIED_ENTRIES_OBJECT = XMLCatalogMessages.UI_LABEL_PLUGIN_SPECIFIED_ENTRIES;
+
+	public XMLCatalogTreeViewer(Composite parent, ICatalog workingUserCatalog, ICatalog systemCatalog) {
+		super(parent, SWT.MULTI | SWT.BORDER);
+		this.fWorkingUserCatalog = workingUserCatalog;
+		this.fSystemCatalog = systemCatalog;
+
+		setContentProvider(new CatalogEntryContentProvider());
+		setLabelProvider(new CatalogEntryLabelProvider());
+	}
+
+	public void setFilterExtensions(String[] extensions) {
+		resetFilters();
+		addFilter(new XMLCatalogTableViewerFilter(extensions));
+	}
+
+	public class CatalogEntryLabelProvider extends LabelProvider {
+		protected HashMap imageTable = new HashMap();
+
+		public String getText(Object object) {
+			String result = null;
+			if (object instanceof ICatalogEntry) {
+				ICatalogEntry catalogEntry = (ICatalogEntry) object;
+				result = catalogEntry.getKey();
+			}
+			else if (object instanceof ISuffixEntry) {
+				ISuffixEntry entry = (ISuffixEntry) object;
+				result = "[...]" + entry.getSuffix() + " " + XMLCatalogMessages.UI_LABEL_ARROW + " " + entry.getURI();
+			}
+			else if (object instanceof IRewriteEntry) {
+				IRewriteEntry entry = (IRewriteEntry) object;
+				result = entry.getStartString() + "[...] " + XMLCatalogMessages.UI_LABEL_ARROW + " " + entry.getRewritePrefix() + "[...]";
+			}
+			else if (object instanceof INextCatalog) {
+				INextCatalog nextCatalog = (INextCatalog) object;
+				// result = nextCatalog.getCatalogLocation();
+				result = URIUtils.convertURIToLocation(nextCatalog.getCatalogLocation());
+				if (nextCatalog.getCatalogLocation().startsWith("file:")) {
+					result += " (" + XMLCatalogMessages.UI_LABEL_FILE_SYSTEM_RESOURCE + ")";
+				}
+				else if (nextCatalog.getCatalogLocation().startsWith("platform:")) {
+					result += " (" + XMLCatalogMessages.UI_LABEL_PLATFORM_RESOURCE + ")";
+				}
+			}
+			else if (object instanceof IDelegateCatalog) {
+				IDelegateCatalog nextCatalog = (IDelegateCatalog) object;
+				// result = nextCatalog.getCatalogLocation();
+				result = nextCatalog.getStartString() + " " + XMLCatalogMessages.UI_LABEL_ARROW + " " + URIUtils.convertURIToLocation(nextCatalog.getCatalogLocation());
+				if (nextCatalog.getCatalogLocation().startsWith("file:")) {
+					result += " (" + XMLCatalogMessages.UI_LABEL_FILE_SYSTEM_RESOURCE + ")";
+				}
+				else if (nextCatalog.getCatalogLocation().startsWith("platform:")) {
+					result += " (" + XMLCatalogMessages.UI_LABEL_PLATFORM_RESOURCE + ")";
+				}
+			}
+			return result != null ? result : object.toString();
+		}
+
+		public Image getImage(Object object) {
+			Image result = null;
+			if (object instanceof String) {
+				result = xmlCatalogImage;
+			}
+			else if (object instanceof ICatalogEntry) {
+				ICatalogEntry catalogEntry = (ICatalogEntry) object;
+				String uri = catalogEntry.getURI();
+				result = getResourceImage(uri);
+			}
+			else if (object instanceof INextCatalog) {
+				// TODO: add image to the imageTable and add error overlay if
+				// next catalog URI is not readable
+				result = nextCatalogImage;
+			}
+			else if (object instanceof IDelegateCatalog) {
+				// TODO: add image to the imageTable and add error overlay if
+				// next catalog URI is not readable
+				result = delegateCatalogImage;
+			}
+			else if (object instanceof ISuffixEntry) {
+				// TODO: add image to the imageTable and add error overlay if
+				// next catalog URI is not readable
+				result = suffixEntryImage;
+			}
+			else if (object instanceof IRewriteEntry) {
+				// TODO: add image to the imageTable and add error overlay if
+				// next catalog URI is not readable
+				result = rewriteEntryImage;
+			}
+			return result;
+		}
+
+		private Image getResourceImage(String uri) {
+			Image result = null;
+			Image base = null;
+
+			IEditorRegistry er = PlatformUI.getWorkbench().getEditorRegistry();
+			ImageDescriptor imageDescriptor = er.getImageDescriptor(uri);
+			Image image = (Image) imageTable.get(imageDescriptor);
+			if (image == null) {
+				image = imageDescriptor.createImage();
+				imageTable.put(imageDescriptor, image);
+			}
+			base = image;
+
+			if (base != null) {
+				// TODO: This should be moved into the catalog
+				if (URIHelper.isReadableURI(uri, false)) {
+					result = base;
+				}
+				else {
+					result = ImageFactory.INSTANCE.createCompositeImage(base, errorImage, ImageFactory.BOTTOM_LEFT);
+				}
+			}
+			return result;
+		}
+
+		public void dispose() {
+			super.dispose();
+			for (Iterator it = imageTable.values().iterator(); it.hasNext();) {
+				((Image) it.next()).dispose();
+			}
+		}
+	}
+
+
+	public class CatalogEntryContentProvider implements ITreeContentProvider {
+		protected Object[] roots;
+
+		public CatalogEntryContentProvider() {
+			roots = new Object[2];
+			roots[0] = USER_SPECIFIED_ENTRIES_OBJECT;
+			roots[1] = PLUGIN_SPECIFIED_ENTRIES_OBJECT;
+		}
+
+		public boolean isRoot(Object object) {
+			return (object instanceof String) || (object instanceof INextCatalog);
+		}
+
+		public Object[] getElements(Object element) {
+			return roots;
+		}
+
+		public Object[] getChildren(Object parentElement) {
+			Object[] result = new Object[0];
+			if (parentElement == roots[0]) {
+				result = getChildrenHelper(fWorkingUserCatalog);
+			}
+			else if (parentElement == roots[1]) {
+				result = getChildrenHelper(fSystemCatalog);
+			}
+			else if (parentElement instanceof INextCatalog) {
+				ICatalog nextCatalog = ((INextCatalog) parentElement).getReferencedCatalog();
+				result = getChildrenHelper(nextCatalog);
+			}
+			else if (parentElement instanceof IDelegateCatalog) {
+				ICatalog nextCatalog = ((IDelegateCatalog) parentElement).getReferencedCatalog();
+				result = getChildrenHelper(nextCatalog);
+			}
+			return result;
+		}
+
+		protected Object[] getChildrenHelper(ICatalog catalog) {
+
+			ICatalogEntry[] entries = catalog.getCatalogEntries();
+			if (entries.length > 0) {
+				Comparator comparator = new Comparator() {
+					public int compare(Object o1, Object o2) {
+						int result = 0;
+						if ((o1 instanceof ICatalogEntry) && (o2 instanceof ICatalogEntry)) {
+							ICatalogEntry entry1 = (ICatalogEntry) o1;
+							ICatalogEntry entry2 = (ICatalogEntry) o2;
+							result = Collator.getInstance().compare(entry1.getKey(), entry2.getKey());
+						}
+						return result;
+					}
+				};
+				Arrays.sort(entries, comparator);
+			}
+			Vector result = new Vector();
+			result.addAll(Arrays.asList(entries));
+			result.addAll(Arrays.asList(catalog.getRewriteEntries()));
+			result.addAll(Arrays.asList(catalog.getSuffixEntries()));
+			result.addAll(Arrays.asList(catalog.getDelegateCatalogs()));
+			INextCatalog[] nextCatalogs = catalog.getNextCatalogs();
+			List nextCatalogsList = Arrays.asList(nextCatalogs);
+			result.addAll(nextCatalogsList);
+
+			return result.toArray(new ICatalogElement[result.size()]);
+		}
+
+		public Object getParent(Object element) {
+			return (element instanceof String) ? null : USER_SPECIFIED_ENTRIES_OBJECT;
+		}
+
+		public boolean hasChildren(Object element) {
+			return isRoot(element) ? getChildren(element).length > 0 : false;
+		}
+
+		public void dispose() {
+			// nothing to dispose
+		}
+
+		public void inputChanged(Viewer viewer, Object old, Object newobj) {
+			// ISSUE: seems we should do something here
+		}
+
+		public boolean isDeleted(Object object) {
+			return false;
+		}
+	}
+
+
+	class XMLCatalogTableViewerFilter extends ViewerFilter {
+		protected String[] extensions;
+
+		public XMLCatalogTableViewerFilter(String[] extensions1) {
+			this.extensions = extensions1;
+		}
+
+		public boolean isFilterProperty(Object element, Object property) {
+			return false;
+		}
+
+		public boolean select(Viewer viewer, Object parent, Object element) {
+			boolean result = false;
+			if (element instanceof ICatalogEntry) {
+				ICatalogEntry catalogEntry = (ICatalogEntry) element;
+				for (int i = 0; i < extensions.length; i++) {
+					if (catalogEntry.getURI().endsWith(extensions[i])) {
+						result = true;
+						break;
+					}
+				}
+			}
+			else if (element.equals(XMLCatalogTreeViewer.PLUGIN_SPECIFIED_ENTRIES_OBJECT) || element.equals(XMLCatalogTreeViewer.USER_SPECIFIED_ENTRIES_OBJECT)) {
+				return true;
+			}
+			return result;
+		}
+	}
+
+
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/XMLQuickScan.java b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/XMLQuickScan.java
new file mode 100644
index 0000000..723539d
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/XMLQuickScan.java
@@ -0,0 +1,107 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.catalog;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.eclipse.wst.xml.ui.internal.Logger;
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * 
+ */
+public class XMLQuickScan {
+	public static String getTargetNamespaceURIForSchema(String uri) {
+		String result = null;
+		try {
+			URL url = new URL(uri);
+			InputStream inputStream = url.openStream();
+			result = XMLQuickScan.getTargetNamespaceURIForSchema(inputStream);
+		}
+		catch (Exception e) {
+		}
+		return result;
+	}
+
+	public static String getTargetNamespaceURIForSchema(InputStream input) {
+		TargetNamespaceURIContentHandler handler = new TargetNamespaceURIContentHandler();
+		ClassLoader prevClassLoader = Thread.currentThread().getContextClassLoader();
+		try {
+			Thread.currentThread().setContextClassLoader(XMLQuickScan.class.getClassLoader());
+			SAXParserFactory factory = SAXParserFactory.newInstance();
+			factory.setNamespaceAware(true);
+			SAXParser parser = factory.newSAXParser();
+			parser.parse(new InputSource(input), handler);
+		}
+		catch (StopParseException e) {
+			// this is a normal exception to stop parsing early,
+			// when info is found, so we can safely ignore
+		}
+		catch (ParserConfigurationException e) {
+			Logger.logException(e);
+		}
+		catch (SAXException e) {
+			Logger.logException(e);
+		}
+		catch (IOException e) {
+			Logger.logException(e);
+		}
+		finally {
+			Thread.currentThread().setContextClassLoader(prevClassLoader);
+		}
+		return handler.targetNamespaceURI;
+	}
+
+	/**
+	 * This is a special exception that is used to stop parsing when required
+	 * information is found.
+	 */
+	static class StopParseException extends org.xml.sax.SAXException {
+		static final long serialVersionUID = 1L;
+
+		/**
+		 * Constructor StopParseException.
+		 */
+		StopParseException() {
+			super("targetnamespace found, no need to continue the parse");
+		}
+	}
+
+	static class TargetNamespaceURIContentHandler extends DefaultHandler {
+		public String targetNamespaceURI;
+
+		public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
+			if (localName.equals("schema")) //$NON-NLS-1$
+			{
+				int nAttributes = attributes.getLength();
+				for (int i = 0; i < nAttributes; i++) {
+					if (attributes.getLocalName(i).equals("targetNamespace")) //$NON-NLS-1$
+					{
+						targetNamespaceURI = attributes.getValue(i);
+						break;
+					}
+				}
+			}
+			throw new StopParseException();
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/icons/etool50/catalogEntry.gif b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/icons/etool50/catalogEntry.gif
new file mode 100644
index 0000000..d65b280
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/icons/etool50/catalogEntry.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/icons/etool50/delegateCatalog.gif b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/icons/etool50/delegateCatalog.gif
new file mode 100644
index 0000000..c0d85ee
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/icons/etool50/delegateCatalog.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/icons/etool50/nextCatalog.gif b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/icons/etool50/nextCatalog.gif
new file mode 100644
index 0000000..3a934b9
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/icons/etool50/nextCatalog.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/icons/etool50/prefix.gif b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/icons/etool50/prefix.gif
new file mode 100644
index 0000000..6b87692
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/icons/etool50/prefix.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/icons/etool50/rewrite.gif b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/icons/etool50/rewrite.gif
new file mode 100644
index 0000000..f003064
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/icons/etool50/rewrite.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/icons/etool50/sufix.gif b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/icons/etool50/sufix.gif
new file mode 100644
index 0000000..2bd5b41
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/icons/etool50/sufix.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/icons/obj16/catalog_entry.gif b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/icons/obj16/catalog_entry.gif
new file mode 100644
index 0000000..a27e30a
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/icons/obj16/catalog_entry.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/icons/obj16/delegate_catalog.gif b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/icons/obj16/delegate_catalog.gif
new file mode 100644
index 0000000..11bd2d0
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/icons/obj16/delegate_catalog.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/icons/obj16/entry_obj.png b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/icons/obj16/entry_obj.png
new file mode 100644
index 0000000..be71474
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/icons/obj16/entry_obj.png
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/icons/obj16/file_expand.gif b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/icons/obj16/file_expand.gif
new file mode 100644
index 0000000..85f9baa
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/icons/obj16/file_expand.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/icons/obj16/file_obj.gif b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/icons/obj16/file_obj.gif
new file mode 100644
index 0000000..061161a
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/icons/obj16/file_obj.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/icons/obj16/nextCatalog_obj.gif b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/icons/obj16/nextCatalog_obj.gif
new file mode 100644
index 0000000..d4bfe79
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/icons/obj16/nextCatalog_obj.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/icons/obj16/next_catalog.gif b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/icons/obj16/next_catalog.gif
new file mode 100644
index 0000000..976cbc9
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/icons/obj16/next_catalog.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/icons/obj16/rewrite_entry.gif b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/icons/obj16/rewrite_entry.gif
new file mode 100644
index 0000000..9cc8ee9
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/icons/obj16/rewrite_entry.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/icons/obj16/suffix_entry.gif b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/icons/obj16/suffix_entry.gif
new file mode 100644
index 0000000..dc76407
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/icons/obj16/suffix_entry.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/icons/obj16/xmlcatalog_obj.gif b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/icons/obj16/xmlcatalog_obj.gif
new file mode 100644
index 0000000..a61441f
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/icons/obj16/xmlcatalog_obj.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/icons/ovr16/error-overlay.gif b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/icons/ovr16/error-overlay.gif
new file mode 100644
index 0000000..119dccc
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-catalog/org/eclipse/wst/xml/ui/internal/catalog/icons/ovr16/error-overlay.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/DOMPropertyDescriptorFactory.java b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/DOMPropertyDescriptorFactory.java
new file mode 100644
index 0000000..5bebb72
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/DOMPropertyDescriptorFactory.java
@@ -0,0 +1,135 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.tabletree;
+
+import org.eclipse.ui.views.properties.IPropertyDescriptor;
+import org.eclipse.ui.views.properties.TextPropertyDescriptor;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.modelquery.ModelQueryUtil;
+import org.eclipse.wst.xml.ui.internal.properties.EnumeratedStringPropertyDescriptor;
+import org.w3c.dom.Attr;
+import org.w3c.dom.CDATASection;
+import org.w3c.dom.Comment;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Element;
+import org.w3c.dom.EntityReference;
+import org.w3c.dom.Node;
+import org.w3c.dom.ProcessingInstruction;
+import org.w3c.dom.Text;
+
+
+public class DOMPropertyDescriptorFactory {
+
+	protected static final String HACK = "hack"; //$NON-NLS-1$
+
+	public DOMPropertyDescriptorFactory() {
+	}
+
+	public IPropertyDescriptor createAttributePropertyDescriptor(Attr attr) {
+		IPropertyDescriptor result = null;
+
+		String attributeName = attr.getName();
+
+		ModelQuery mq = ModelQueryUtil.getModelQuery(attr.getOwnerDocument());
+
+		if (mq != null) {
+			CMAttributeDeclaration ad = mq.getCMAttributeDeclaration(attr);
+			if (ad != null) {
+				String[] valuesArray = mq.getPossibleDataTypeValues(attr.getOwnerElement(), ad);
+				if ((valuesArray != null) && (valuesArray.length > 0)) {
+					result = new EnumeratedStringPropertyDescriptor(attributeName, attributeName, valuesArray);
+				}
+			}
+		}
+
+		if (result == null) {
+			result = createDefaultPropertyDescriptor(attributeName);
+		}
+		return result;
+	}
+
+	public IPropertyDescriptor createCDATASectionPropertyDescriptor(CDATASection cdataSection) {
+		return createDefaultPropertyDescriptor(HACK);
+	}
+
+	public IPropertyDescriptor createCommentPropertyDescriptor(Comment comment) {
+		return createDefaultPropertyDescriptor(HACK);
+	}
+
+	protected IPropertyDescriptor createDefaultPropertyDescriptor(String attributeName) {
+		TextPropertyDescriptor descriptor = new TextPropertyDescriptor(attributeName, attributeName);
+		return descriptor;
+	}
+
+	public IPropertyDescriptor createDocumentTypePropertyDescriptor(DocumentType documentType) {
+		return null; // new TextPropertyDescriptor(HACK, HACK);
+	}
+
+	public IPropertyDescriptor createElementPropertyDescriptor(Element element) {
+		return createDefaultPropertyDescriptor(HACK);
+	}
+
+	public IPropertyDescriptor createEntityReferencePropertyDescriptor(EntityReference entityReference) {
+		return createDefaultPropertyDescriptor(HACK);
+	}
+
+	public IPropertyDescriptor createProcessingInstructionPropertyDescriptor(ProcessingInstruction pi) {
+		return createDefaultPropertyDescriptor(HACK);
+	}
+
+	public IPropertyDescriptor createPropertyDescriptor(Object object) {
+		IPropertyDescriptor result = null;
+		if (object instanceof Node) {
+			Node node = (Node) object;
+			int nodeType = node.getNodeType();
+			switch (nodeType) {
+				case Node.ATTRIBUTE_NODE : {
+					result = createAttributePropertyDescriptor((Attr) node);
+					break;
+				}
+				case Node.CDATA_SECTION_NODE : {
+					result = createCDATASectionPropertyDescriptor((CDATASection) node);
+					break;
+				}
+				case Node.COMMENT_NODE : {
+					result = createCommentPropertyDescriptor((Comment) node);
+					break;
+				}
+				case Node.DOCUMENT_TYPE_NODE : {
+					result = createDocumentTypePropertyDescriptor((DocumentType) node);
+					break;
+				}
+				case Node.ELEMENT_NODE : {
+					result = createElementPropertyDescriptor((Element) node);
+					break;
+				}
+				case Node.ENTITY_REFERENCE_NODE : {
+					result = createEntityReferencePropertyDescriptor((EntityReference) node);
+					break;
+				}
+				case Node.PROCESSING_INSTRUCTION_NODE : {
+					result = createProcessingInstructionPropertyDescriptor((ProcessingInstruction) node);
+					break;
+				}
+				case Node.TEXT_NODE : {
+					result = createTextPropertyDescriptor((Text) node);
+					break;
+				}
+			}
+		}
+		return result;
+	}
+
+	public IPropertyDescriptor createTextPropertyDescriptor(Text text) {
+		return createDefaultPropertyDescriptor(HACK);
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/IDesignViewer.java b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/IDesignViewer.java
new file mode 100644
index 0000000..f1be97f
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/IDesignViewer.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.tabletree;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.swt.widgets.Control;
+
+public interface IDesignViewer {
+	public Control getControl();
+
+	String getTitle();
+
+	void setDocument(IDocument document);
+
+	ISelectionProvider getSelectionProvider();
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/IDesignViewerActionBarContributor.java b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/IDesignViewerActionBarContributor.java
new file mode 100644
index 0000000..411a3f9
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/IDesignViewerActionBarContributor.java
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.tabletree;
+
+
+
+import org.eclipse.ui.IActionBars;
+import org.eclipse.wst.sse.ui.internal.ISourceViewerActionBarContributor;
+
+
+public interface IDesignViewerActionBarContributor extends ISourceViewerActionBarContributor {
+	public void initViewerSpecificContributions(IActionBars bars);
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/SourceEditorActionBarContributor.java b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/SourceEditorActionBarContributor.java
new file mode 100644
index 0000000..d70cdd3
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/SourceEditorActionBarContributor.java
@@ -0,0 +1,230 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.tabletree;
+
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.IStatusLineManager;
+import org.eclipse.jface.action.IToolBarManager;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.IEditorActionBarContributor;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.part.MultiPageEditorActionBarContributor;
+import org.eclipse.ui.part.MultiPageEditorPart;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.wst.sse.ui.internal.ExtendedEditorActionBuilder;
+import org.eclipse.wst.sse.ui.internal.IExtendedContributor;
+import org.eclipse.wst.sse.ui.internal.ISourceViewerActionBarContributor;
+
+
+public class SourceEditorActionBarContributor extends MultiPageEditorActionBarContributor implements IExtendedContributor {
+
+	protected IEditorActionBarContributor designViewerActionBarContributor = null;
+	protected IEditorActionBarContributor sourceViewerActionContributor = null;
+	protected MultiPageEditorPart multiPageEditor = null;
+
+	// EditorExtension
+	private static final String EDITOR_ID = "org.eclipse.wst.xml.ui.XMLMultiPageEditorPart"; //$NON-NLS-1$
+	private IExtendedContributor extendedContributor;
+
+	public SourceEditorActionBarContributor() {
+		super();
+
+		sourceViewerActionContributor = new SourcePageActionContributor();
+
+		// Read action extensions.
+		ExtendedEditorActionBuilder builder = new ExtendedEditorActionBuilder();
+		extendedContributor = builder.readActionExtensions(EDITOR_ID);
+	}
+
+	public void init(IActionBars actionBars) {
+		super.init(actionBars);
+
+		if (actionBars != null) {
+			initDesignViewerActionBarContributor(actionBars);
+			initSourceViewerActionContributor(actionBars);
+		}
+	}
+
+	protected void initDesignViewerActionBarContributor(IActionBars actionBars) {
+		if (designViewerActionBarContributor != null) {
+			designViewerActionBarContributor.init(actionBars, getPage());
+		}
+	}
+
+	protected void initSourceViewerActionContributor(IActionBars actionBars) {
+		if (sourceViewerActionContributor != null) {
+			sourceViewerActionContributor.init(actionBars, getPage());
+		}
+	}
+
+	public void dispose() {
+		super.dispose();
+
+		if (designViewerActionBarContributor != null) {
+			designViewerActionBarContributor.dispose();
+		}
+
+		if (sourceViewerActionContributor != null) {
+			sourceViewerActionContributor.dispose();
+		}
+
+		if (extendedContributor != null) {
+			extendedContributor.dispose();
+		}
+		
+		multiPageEditor = null;
+	}
+
+	/**
+	 * @see org.eclipse.ui.part.EditorActionBarContributor#contributeToMenu(IMenuManager)
+	 */
+	public final void contributeToMenu(IMenuManager menu) {
+		super.contributeToMenu(menu);
+
+		//addToMenu(menu);
+
+		if (extendedContributor != null) {
+			extendedContributor.contributeToMenu(menu);
+		}
+	}
+
+	protected void addToMenu(IMenuManager menu) {
+	}
+
+	/**
+	 * @see IExtendedContributor#contributeToPopupMenu(IMenuManager)
+	 */
+	public final void contributeToPopupMenu(IMenuManager menu) {
+
+		addToPopupMenu(menu);
+
+		if (extendedContributor != null) {
+			extendedContributor.contributeToPopupMenu(menu);
+		}
+	}
+
+	protected void addToPopupMenu(IMenuManager menu) {
+	}
+
+	/**
+	 * @see org.eclipse.ui.part.EditorActionBarContributor#contributeToToolBar(IToolBarManager)
+	 */
+	public final void contributeToToolBar(IToolBarManager toolBarManager) {
+		super.contributeToToolBar(toolBarManager);
+
+		addToToolBar(toolBarManager);
+
+		if (extendedContributor != null) {
+			extendedContributor.contributeToToolBar(toolBarManager);
+		}
+	}
+
+	protected void addToToolBar(IToolBarManager toolBarManager) {
+	}
+
+	/**
+	 * @see org.eclipse.ui.part.EditorActionBarContributor#contributeToStatusLine(IStatusLineManager)
+	 */
+	public final void contributeToStatusLine(IStatusLineManager manager) {
+		super.contributeToStatusLine(manager);
+
+		addToStatusLine(manager);
+
+		if (extendedContributor != null) {
+			extendedContributor.contributeToStatusLine(manager);
+		}
+	}
+
+	protected void addToStatusLine(IStatusLineManager manager) {
+	}
+
+	/**
+	 * @see IExtendedContributor#updateToolbarActions()
+	 */
+	public void updateToolbarActions() {
+		if (extendedContributor != null) {
+			extendedContributor.updateToolbarActions();
+		}
+	}
+
+	public void setActiveEditor(IEditorPart targetEditor) {
+		// save multiPageEditor before calling
+		// super.setActiveEditor(targetEditor)
+		// super.setActiveEditor will call setActivePage(IEditorPart
+		// activeEditor)
+		// multiPageEditor is needed in setActivePage(IEditorPart
+		// activeEditor)
+		if (targetEditor instanceof MultiPageEditorPart) {
+			multiPageEditor = (MultiPageEditorPart) targetEditor;
+		}
+
+		super.setActiveEditor(targetEditor);
+
+		updateToolbarActions();
+
+		if (extendedContributor != null) {
+			extendedContributor.setActiveEditor(targetEditor);
+		}
+	}
+
+	public void setActivePage(IEditorPart activeEditor) {
+		// This contributor is designed for StructuredTextMultiPageEditorPart.
+		// To safe-guard this from problems caused by unexpected usage by
+		// other editors, the following
+		// check is added.
+		if (multiPageEditor != null) {
+			if ((activeEditor != null) && (activeEditor instanceof ITextEditor)) {
+				activateSourcePage(activeEditor);
+			}
+			else {
+				activateDesignPage(activeEditor);
+			}
+		}
+
+		updateToolbarActions();
+
+		IActionBars actionBars = getActionBars();
+		if (actionBars != null) {
+			// update menu bar and tool bar
+			actionBars.updateActionBars();
+		}
+	}
+
+	protected void activateDesignPage(IEditorPart activeEditor) {
+		if ((designViewerActionBarContributor != null) && (designViewerActionBarContributor instanceof IDesignViewerActionBarContributor)) {
+			designViewerActionBarContributor.setActiveEditor(multiPageEditor);
+		}
+
+		if ((sourceViewerActionContributor != null) && (sourceViewerActionContributor instanceof ISourceViewerActionBarContributor)) {
+			// if design page is not really an IEditorPart, activeEditor ==
+			// null, so pass in multiPageEditor instead (d282414)
+			if (activeEditor == null) {
+				sourceViewerActionContributor.setActiveEditor(multiPageEditor);
+			}
+			else {
+				sourceViewerActionContributor.setActiveEditor(activeEditor);
+			}
+			((ISourceViewerActionBarContributor) sourceViewerActionContributor).setViewerSpecificContributionsEnabled(false);
+		}
+	}
+
+	protected void activateSourcePage(IEditorPart activeEditor) {
+		if ((designViewerActionBarContributor != null) && (designViewerActionBarContributor instanceof IDesignViewerActionBarContributor)) {
+			designViewerActionBarContributor.setActiveEditor(multiPageEditor);
+		}
+
+		if ((sourceViewerActionContributor != null) && (sourceViewerActionContributor instanceof ISourceViewerActionBarContributor)) {
+			sourceViewerActionContributor.setActiveEditor(activeEditor);
+			((ISourceViewerActionBarContributor) sourceViewerActionContributor).setViewerSpecificContributionsEnabled(true);
+		}
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/SourcePageActionContributor.java b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/SourcePageActionContributor.java
new file mode 100644
index 0000000..bd1e251
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/SourcePageActionContributor.java
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.tabletree;
+
+
+
+import org.eclipse.ui.IActionBars;
+import org.eclipse.wst.xml.ui.internal.actions.ActionContributorXML;
+
+
+/**
+ * SourcePageActionContributor
+ * 
+ * This class is for multi page editor's source page contributor.
+ * 
+ * Use XMLEditorActionContributor for single page editor.
+ */
+public class SourcePageActionContributor extends ActionContributorXML {
+
+	private IActionBars fBars;
+
+	/**
+	 * This method calls:
+	 * <ul>
+	 * <li><code>contributeToMenu</code> with <code>bars</code>' menu
+	 * manager</li>
+	 * <li><code>contributeToToolBar</code> with <code>bars</code>' tool
+	 * bar manager</li>
+	 * <li><code>contributeToStatusLine</code> with <code>bars</code>'
+	 * status line manager</li>
+	 * </ul>
+	 * The given action bars are also remembered and made accessible via
+	 * <code>getActionBars</code>.
+	 * 
+	 * @param bars
+	 *            the action bars
+	 * 
+	 */
+	public void init(IActionBars bars) {
+		fBars = bars;
+		contributeToMenu(bars.getMenuManager());
+		contributeToToolBar(bars.getToolBarManager());
+		contributeToStatusLine(bars.getStatusLineManager());
+	}
+
+	/**
+	 * Returns this contributor's action bars.
+	 * 
+	 * @return the action bars
+	 */
+	public IActionBars getActionBars() {
+		return fBars;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/TreeContentHelper.java b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/TreeContentHelper.java
new file mode 100644
index 0000000..9033227
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/TreeContentHelper.java
@@ -0,0 +1,513 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+
+package org.eclipse.wst.xml.ui.internal.tabletree;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.DOMWriter;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.w3c.dom.Attr;
+import org.w3c.dom.CharacterData;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.ProcessingInstruction;
+import org.w3c.dom.Text;
+
+
+/**
+ * This performs the work of taking a DOM tree and converting it to a
+ * displayable 'UI' tree.
+ * 
+ * For example : - white space text nodes are ommited from the 'UI' tree -
+ * adjacent Text and EntityReference nodes are combined into a single 'UI'
+ * node - Elements with 'text only' children are diplayed without children
+ * 
+ */
+public class TreeContentHelper {
+
+	public static final int HIDE_WHITE_SPACE_TEXT_NODES = 8;
+	public static final int COMBINE_ADJACENT_TEXT_AND_ENTITY_REFERENCES = 16;
+	public static final int HIDE_ELEMENT_CHILD_TEXT_NODES = 32;
+
+	protected int style = HIDE_WHITE_SPACE_TEXT_NODES | COMBINE_ADJACENT_TEXT_AND_ENTITY_REFERENCES | HIDE_ELEMENT_CHILD_TEXT_NODES;
+
+	/**
+	 * 
+	 */
+	public boolean hasStyleFlag(int flag) {
+		return (style & flag) != 0;
+	}
+
+	/**
+	 * 
+	 */
+	public Object[] getChildren(Object element) {
+		Object[] result = null;
+
+		if (element instanceof Node) {
+			Node node = (Node) element;
+			List list = new ArrayList();
+			boolean textContentOnly = true;
+
+			NamedNodeMap map = node.getAttributes();
+			if (map != null) {
+				int length = map.getLength();
+				for (int i = 0; i < length; i++) {
+					list.add(map.item(i));
+					textContentOnly = false;
+				}
+			}
+
+			Node prevIncludedNode = null;
+			for (Node childNode = node.getFirstChild(); childNode != null; childNode = childNode.getNextSibling()) {
+				int childNodeType = childNode.getNodeType();
+				boolean includeNode = true;
+
+				if (includeNode && hasStyleFlag(HIDE_WHITE_SPACE_TEXT_NODES)) {
+					if (isIgnorableText(childNode)) {
+						// filter out the ignorable text node
+						includeNode = false;
+					}
+				}
+
+				if (includeNode && hasStyleFlag(COMBINE_ADJACENT_TEXT_AND_ENTITY_REFERENCES)) {
+					if (isTextOrEntityReferenceNode(childNode) && (prevIncludedNode != null) && isTextOrEntityReferenceNode(prevIncludedNode)) {
+						// we only show the first of a list of adjacent text
+						// or entity reference node in the tree
+						// so we filter out this subsequent one
+						includeNode = false;
+					}
+				}
+
+				if (hasStyleFlag(HIDE_ELEMENT_CHILD_TEXT_NODES)) {
+					if ((childNodeType != Node.TEXT_NODE) && (childNodeType != Node.ENTITY_REFERENCE_NODE)) {
+						textContentOnly = false;
+					}
+				}
+
+				if (includeNode) {
+					list.add(childNode);
+					prevIncludedNode = childNode;
+				}
+			}
+
+			if (hasStyleFlag(HIDE_ELEMENT_CHILD_TEXT_NODES) && textContentOnly) {
+				result = new Object[0];
+			}
+			else {
+				result = list.toArray();
+			}
+		}
+		return result;
+	}
+
+	/**
+	 * 
+	 */
+	protected boolean isTextOrEntityReferenceNode(Node node) {
+		return (node.getNodeType() == Node.TEXT_NODE) || (node.getNodeType() == Node.ENTITY_REFERENCE_NODE);
+	}
+
+	/**
+	 * 
+	 */
+	public boolean isIgnorableText(Node node) {
+		boolean result = false;
+		if (node.getNodeType() == Node.TEXT_NODE) {
+			String data = ((Text) node).getData();
+			result = ((data == null) || (data.trim().length() == 0));
+		}
+		return result;
+	}
+
+	/**
+	 * 
+	 */
+	public boolean isCombinedTextNode(Node node) {
+		boolean result = false;
+		if (node.getNodeType() == Node.TEXT_NODE) {
+			Node nextNode = node.getNextSibling();
+			if (nextNode != null) {
+				if (nextNode.getNodeType() == Node.ENTITY_REFERENCE_NODE) {
+					result = true;
+				}
+			}
+		}
+		else if (node.getNodeType() == Node.ENTITY_REFERENCE_NODE) {
+			result = true;
+		}
+		return result;
+	}
+
+	/**
+	 * 
+	 */
+	public List getCombinedTextNodeList(Node theNode) {
+		List list = new Vector();
+		boolean prevIsEntity = false;
+		for (Node node = theNode; node != null; node = node.getNextSibling()) {
+			int nodeType = node.getNodeType();
+			if (nodeType == Node.ENTITY_REFERENCE_NODE) {
+				prevIsEntity = true;
+				list.add(node);
+			}
+			else if ((nodeType == Node.TEXT_NODE) && (prevIsEntity || (node == theNode))) {
+				prevIsEntity = false;
+				list.add(node);
+			}
+			else {
+				break;
+			}
+		}
+		return list;
+	}
+
+	public String getElementTextValue(Element element) {
+		List list = _getElementTextContent(element);
+		return list != null ? getValueForTextContent(list) : null;
+	}
+
+	public void setElementTextValue(Element element, String value) {
+		setElementNodeValue(element, value);
+	}
+
+	private List _getElementTextContent(Element element) {
+		List result = null;
+
+		for (Node node = element.getFirstChild(); node != null; node = node.getNextSibling()) {
+			if ((node.getNodeType() == Node.TEXT_NODE) || (node.getNodeType() == Node.ENTITY_REFERENCE_NODE)) {
+				if (result == null) {
+					result = new Vector();
+				}
+				result.add(node);
+			}
+			else {
+				result = null;
+				break;
+			}
+		}
+		return result;
+	}
+
+	/**
+	 * If the element is has 'text only' content this method will return the
+	 * list of elements that compose the text only content
+	 */
+	public List getElementTextContent(Element element) {
+		List result = null;
+		if (!element.hasAttributes()) {
+			result = _getElementTextContent(element);
+		}
+		return result;
+	}
+
+
+	/**
+	 * 
+	 */
+	public String getNodeValue(Node node) {
+		String result = null;
+		int nodeType = node.getNodeType();
+		switch (nodeType) {
+			case Node.ATTRIBUTE_NODE : {
+				result = ((Attr) node).getValue();
+				break;
+			}
+			case Node.CDATA_SECTION_NODE :
+				// drop thru
+			case Node.COMMENT_NODE : {
+				result = ((CharacterData) node).getData();
+				break;
+			}
+			case Node.DOCUMENT_TYPE_NODE : {
+				result = getDocumentTypeValue((DocumentType) node);
+				break;
+			}
+			case Node.ELEMENT_NODE : {
+				result = getElementNodeValue((Element) node);
+				break;
+			}
+			case Node.ENTITY_REFERENCE_NODE :
+				// drop thru
+			case Node.TEXT_NODE : {
+				result = getTextNodeValue(node);
+				break;
+			}
+			case Node.PROCESSING_INSTRUCTION_NODE : {
+				result = ((ProcessingInstruction) node).getData();
+				break;
+			}
+		}
+		return result;
+	}
+
+	/**
+	 * 
+	 */
+	public void setNodeValue(Node node, String value) {
+		setNodeValue(node, value, null);
+	}
+
+	/**
+	 * Checks that the resource backing the model is writeable utilizing <code>validateEdit</code>
+	 * on a given <tt>IWorkspace</tt>.
+	 * 
+	 * @param model the model to be checked
+	 * @param context the shell context for which <code>validateEdit</code> will be run
+	 * @return boolean result of checking <code>validateEdit</code>. If the resource is unwriteable, <code>status.isOK()</code>
+	 * will return true; otherwise, false.
+	 */
+	private boolean validateEdit(IStructuredModel model, Shell context) {
+		if (model != null && model.getBaseLocation() != null) {
+			IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(model.getBaseLocation()));
+			return !file.isAccessible() || ResourcesPlugin.getWorkspace().validateEdit(new IFile[] {file}, context).isOK();
+		}
+		return false;
+	}
+
+	/**
+	 * 
+	 */
+	public void setNodeValue(Node node, String value, Shell context) {
+		// Model should not be edited because base location is read-only
+		if (node instanceof IDOMNode && !validateEdit(((IDOMNode) node).getModel(), context)) {
+			return;
+		}
+		int nodeType = node.getNodeType();
+		try {
+			switch (nodeType) {
+				case Node.ATTRIBUTE_NODE : {
+					((Attr) node).setValue(value);
+					break;
+				}
+				case Node.CDATA_SECTION_NODE :
+					// drop thru
+				case Node.COMMENT_NODE : {
+					((CharacterData) node).setData(value);
+					break;
+				}
+				case Node.ELEMENT_NODE : {
+					setElementNodeValue((Element) node, value);
+					break;
+				}
+				case Node.ENTITY_REFERENCE_NODE :
+					// drop thru
+				case Node.TEXT_NODE : {
+					setTextNodeValue(node, value);
+					break;
+				}
+				case Node.PROCESSING_INSTRUCTION_NODE : {
+					((ProcessingInstruction) node).setData(value);
+					break;
+				}
+			}
+		}
+		catch (DOMException e) {
+			Display d = getDisplay();
+			if (d != null) {
+				d.beep();
+			}
+		}
+	}
+
+	private Display getDisplay() {
+
+		return PlatformUI.getWorkbench().getDisplay();
+	}
+
+
+	/**
+	 * 
+	 */
+	protected String getDocumentTypeValue(DocumentType documentType) {
+		return DOMWriter.getDocumentTypeData(documentType);
+	}
+
+	/**
+	 * 
+	 */
+	protected String getElementNodeValue(Element element) {
+		String result = null;
+		List list = getElementTextContent(element);
+		if (list != null) {
+			result = getValueForTextContent(list);
+		}
+		return result;
+	}
+
+	/**
+	 * 
+	 */
+	protected void setElementNodeValue(Element element, String value) {
+		List list = getElementTextContent(element);
+		if (list != null) {
+			setValueForTextContent(list, value);
+		}
+		else {
+			Document document = element.getOwnerDocument();
+			Text text = document.createTextNode(value);
+			element.appendChild(text);
+		}
+	}
+
+	/**
+	 * 
+	 */
+	protected String getTextNodeValue(Node node) {
+		String result = null;
+		List list = null;
+		if (isCombinedTextNode(node)) {
+			list = getCombinedTextNodeList(node);
+		}
+		else {
+			list = new Vector();
+			list.add(node);
+		}
+		result = getValueForTextContent(list);
+		return result;
+	}
+
+	/**
+	 * 
+	 */
+	protected void setTextNodeValue(Node node, String value) {
+		List list = null;
+		if (isCombinedTextNode(node)) {
+			list = getCombinedTextNodeList(node);
+		}
+		else {
+			list = new Vector();
+			list.add(node);
+		}
+		setValueForTextContent(list, value);
+	}
+
+	public Text getEffectiveTextNodeForCombinedNodeList(List list) {
+		Text result = null;
+		for (Iterator i = list.iterator(); i.hasNext();) {
+			Node node = (Node) i.next();
+			if (node.getNodeType() == Node.TEXT_NODE) {
+				result = (Text) node;
+				break;
+			}
+		}
+		return result;
+	}
+
+	/**
+	 * 
+	 */
+	protected String getValueForTextContent(List list) {
+		String result = null;
+		if (list.size() > 0) {
+			if (list.get(0) instanceof IDOMNode) {
+				IDOMNode first = (IDOMNode) list.get(0);
+				IDOMNode last = (IDOMNode) list.get(list.size() - 1);
+				IDOMModel model = first.getModel();
+				int start = first.getStartOffset();
+				int end = last.getEndOffset();
+				try {
+					result = model.getStructuredDocument().get(start,
+							end - start);
+				} catch (Exception e) {
+
+				}
+			}
+			else
+			{
+				if (list.get(0) instanceof Node)
+				{
+					Node n = (Node) list.get(0);
+					for (Node node = n.getFirstChild(); node != null; node = node.getNextSibling()) {
+						if (node.getNodeType() == Node.TEXT_NODE) {
+							String text = node.getNodeValue();
+							if(!((text == null) || (text.trim().length() == 0))) {
+								result = text.trim();
+							}
+						}
+					}
+				}
+			}	
+		}
+
+		// we trim the content so that it looks nice when viewed
+		// we need to be carfull to preserve the 'trimmed' text when the value
+		// is set (see setValueForTextContent)
+		if (result != null) {
+			result = result.trim();
+		}
+		return result;
+	}
+
+	/**
+	 * 
+	 */
+	protected void setValueForTextContent(List list, String value) {
+		// String oldValue = getValueForTextContent();
+		// we worry about preserving trimmed text
+		if (list.size() > 0) {
+			if (list.get(0) instanceof IDOMNode) {
+				IDOMNode first = (IDOMNode) list.get(0);
+				IDOMNode last = (IDOMNode) list.get(list.size() - 1);
+				int start = first.getStartOffset();
+				int end = last.getEndOffset();
+				first.getModel().getStructuredDocument().replaceText(this,
+						start, end - start, value);
+			}
+		}
+	}
+
+	/**
+	 * 
+	 */
+	public boolean isEditable(Node node) {
+		int nodeType = node.getNodeType();
+		boolean result = false;
+		switch (nodeType) {
+			case Node.ATTRIBUTE_NODE :
+				// drop thru
+			case Node.CDATA_SECTION_NODE :
+				// drop thru
+			case Node.COMMENT_NODE :
+				// drop thru
+			case Node.ENTITY_REFERENCE_NODE :
+				// drop thru
+			case Node.TEXT_NODE :
+				// drop thru
+			case Node.PROCESSING_INSTRUCTION_NODE : {
+				result = true;
+				break;
+			}
+			case Node.ELEMENT_NODE : {
+				result = (getElementTextContent((Element) node) != null) || (node.getChildNodes().getLength() == 0);
+				break;
+			}
+		}
+		return result;
+	}
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/TreeExtension.java b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/TreeExtension.java
new file mode 100644
index 0000000..c9832cc
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/TreeExtension.java
@@ -0,0 +1,557 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+
+package org.eclipse.wst.xml.ui.internal.tabletree;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+import org.eclipse.jface.viewers.CellEditor;
+import org.eclipse.jface.viewers.ICellEditorListener;
+import org.eclipse.jface.viewers.ICellModifier;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.FocusEvent;
+import org.eclipse.swt.events.FocusListener;
+import org.eclipse.swt.events.KeyAdapter;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.KeyListener;
+import org.eclipse.swt.events.MouseAdapter;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseMoveListener;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Cursor;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.ScrollBar;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.swt.widgets.TreeItem;
+import org.eclipse.ui.PlatformUI;
+
+
+public class TreeExtension implements PaintListener {
+
+	protected Tree fTree;
+	protected EditManager editManager;
+	protected String[] fColumnProperties;
+	protected ICellModifier cellModifier;
+	protected int columnPosition = 300;
+	protected int columnHitWidth = 5;
+	protected Color tableLineColor;
+	protected int controlWidth;
+	protected DelayedDrawTimer delayedDrawTimer;
+	private boolean fisUnsupportedInput = false;
+
+	public TreeExtension(Tree tree) {
+		this.fTree = tree;
+		InternalMouseListener listener = new InternalMouseListener();
+		tree.addMouseMoveListener(listener);
+		tree.addMouseListener(listener);
+		tree.addPaintListener(this);
+		editManager = new EditManager(tree);
+		delayedDrawTimer = new DelayedDrawTimer(tree);
+
+		tableLineColor = tree.getDisplay().getSystemColor(SWT.COLOR_WIDGET_LIGHT_SHADOW);
+	}
+
+	public void dispose() {
+		tableLineColor.dispose();
+	}
+
+	public void setCellModifier(ICellModifier modifier) {
+		cellModifier = modifier;
+	}
+
+	public void resetCachedData() {
+		// todo: sure seems we should reset something?
+	}
+
+	public ICellModifier getCellModifier() {
+		return cellModifier;
+	}
+
+	public List getItemList() {
+		List list = new Vector();
+		getItemListHelper(fTree.getItems(), list);
+		return list;
+	}
+
+	protected void getItemListHelper(TreeItem[] items, List list) {
+		for (int i = 0; i < items.length; i++) {
+			TreeItem item = items[i];
+			list.add(item);
+			getItemListHelper(item.getItems(), list);
+		}
+	}
+
+	protected TreeItem getTreeItemOnRow(int px, int py) {
+		TreeItem result = null;
+		List list = getItemList();
+		for (Iterator i = list.iterator(); i.hasNext();) {
+			TreeItem item = (TreeItem) i.next();
+			Rectangle r = item.getBounds();
+			if ((r != null) && (px >= r.x) && (py >= r.y) && (py <= r.y + r.height)) {
+				result = item;
+			}
+		}
+		return result;
+	}
+
+	protected class InternalMouseListener extends MouseAdapter implements MouseMoveListener {
+		protected int columnDragged = -1;
+		protected boolean isDown = false;
+		protected int prevX = -1;
+		protected Cursor cursor = null;
+
+		public void mouseMove(MouseEvent e) {
+			if ((e.x > columnPosition - columnHitWidth) && (e.x < columnPosition + columnHitWidth)) {
+				if (cursor == null) {
+					cursor = new Cursor(fTree.getDisplay(), SWT.CURSOR_SIZEWE);
+					fTree.setCursor(cursor);
+				}
+			}
+			else {
+				if (cursor != null) {
+					fTree.setCursor(null);
+					cursor.dispose();
+					cursor = null;
+				}
+			}
+
+			if (columnDragged != -1) {
+				// using the delay timer will make redraws less flickery
+				if (e.x > 20) {
+					columnPosition = e.x;
+					delayedDrawTimer.reset(20);
+				}
+			}
+		}
+
+		public void mouseDown(MouseEvent e) {
+			// here we handle the column resizing by detect if the user has
+			// click on a column separator
+			//
+			columnDragged = -1;
+			editManager.deactivateCellEditor();
+
+			if ((e.x > columnPosition - columnHitWidth) && (e.x < columnPosition + columnHitWidth)) {
+				columnDragged = 0;
+			}
+
+			// here we handle selecting tree items when any thing on the 'row'
+			// is clicked
+			//
+			TreeItem item = fTree.getItem(new Point(e.x, e.y));
+			if (item == null) {
+				item = getTreeItemOnRow(e.x, e.y);
+				if (item != null) {
+					TreeItem[] items = new TreeItem[1];
+					items[0] = item;
+					fTree.setSelection(items);
+				}
+			}
+		}
+
+		public void mouseUp(MouseEvent e) {
+			columnDragged = -1;
+		}
+	}
+
+	public String[] getColumnProperties() {
+		return fColumnProperties;
+	}
+
+	public void setColumnProperties(String[] columnProperties) {
+		this.fColumnProperties = columnProperties;
+	}
+
+	public void paintControl(PaintEvent event) {
+		GC gc = event.gc;
+		Rectangle treeBounds = fTree.getBounds();
+
+		controlWidth = treeBounds.width;
+		Color bg = fTree.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND);
+		Color bg2 = fTree.getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION);
+
+		gc.setBackground(bg2);
+
+		// // This next part causes problems on LINUX, so let's not do it
+		// there
+		// if (B2BHacks.IS_UNIX == false) {
+		// TreeItem[] selectedItems = tree.getSelection();
+		// if (selectedItems.length > 0) {
+		// for (int i = 0; i < selectedItems.length; i++) {
+		// TreeItem item = selectedItems[i];
+		// Rectangle bounds = item.getBounds();
+		// if (bounds != null) {
+		// gc.fillRectangle(bounds.x + bounds.width, bounds.y, controlWidth,
+		// bounds.height);
+		// }
+		// }
+		// }
+		// }
+		//
+		if (!fisUnsupportedInput) {
+			TreeItem[] items = fTree.getItems();
+			if (items.length > 0) {
+				gc.setForeground(tableLineColor);
+				gc.setBackground(bg);
+
+				gc.fillRectangle(columnPosition, treeBounds.x, treeBounds.width, treeBounds.height);
+
+				Rectangle itemBounds = items[0].getBounds();
+				int height = computeTreeItemHeight();
+
+				if (itemBounds != null) {
+					/*
+					 * Bounds will be for the first item, which will either be
+					 * visible at the top of the Tree, or scrolled off with
+					 * negative values
+					 */
+					int startY = itemBounds.y;
+
+					/* Only draw lines within the Tree boundaries */
+					for (int i = startY; i < treeBounds.height; i += height) {
+						if (i >= treeBounds.y) {
+							gc.drawLine(0, i, treeBounds.width, i);
+						}
+					}
+				}
+				gc.drawLine(columnPosition, 0, columnPosition, treeBounds.height);
+				paintItems(gc, items, treeBounds);
+
+			}
+			else {
+				addEmptyTreeMessage(gc);
+			}
+		}
+		else {
+			addUnableToPopulateTreeMessage(gc);
+		}
+	}
+
+	protected int computeTreeItemHeight() {
+		int result = -1;
+
+		/*
+		 * On GTK tree.getItemHeight() seems to lie to us. It reports that the
+		 * tree item occupies a few pixles less vertical space than it should
+		 * (possibly because of the image height vs. the text height?). This
+		 * foils our code that draws the 'row' lines since we assume that
+		 * lines should be drawn at 'itemHeight' increments. Don't trust
+		 * getItemHeight() to compute the increment... instead compute the
+		 * value based on distance between two TreeItems, and then use the
+		 * larger value.
+		 * 
+		 * This strategy only works on trees where the items are of even
+		 * height, however bug
+		 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=117201 indicates that
+		 * this is no longer promised, at least on win32 and likely on other
+		 * platforms soon.
+		 */
+		if (fTree.getItemCount() > 0) {
+			TreeItem[] items = fTree.getItems();
+			Rectangle itemBounds = items[0].getBounds();
+
+			if (items[0].getExpanded()) {
+				TreeItem[] children = items[0].getItems();
+				if (children.length > 0) {
+					result = children[0].getBounds().y - itemBounds.y;
+				}
+			}
+			else if (items.length > 1) {
+				result = items[1].getBounds().y - itemBounds.y;
+			}
+		}
+
+		result = Math.max(fTree.getItemHeight(), result);
+		return result;
+	}
+
+	protected void addEmptyTreeMessage(GC gc) {
+		// nothing to add here
+	}
+
+	private void addUnableToPopulateTreeMessage(GC gc) {
+		// here we print a message when the document cannot be displayed just
+		// to give the
+		// user a visual cue
+		// so that they know how to proceed to edit the blank view
+		gc.setForeground(fTree.getDisplay().getSystemColor(SWT.COLOR_BLACK));
+		gc.setBackground(fTree.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND));
+		gc.drawString(XMLEditorMessages.TreeExtension_0, 10, 10);
+	}
+
+	void setIsUnsupportedInput(boolean isUnsupported) {
+		fisUnsupportedInput = isUnsupported;
+	}
+
+	public void paintItems(GC gc, TreeItem[] items, Rectangle treeBounds) {
+		if (items != null) {
+			for (int i = 0; i < items.length; i++) {
+				TreeItem item = items[i];
+				if (item != null) {
+					Rectangle bounds = item.getBounds();
+					if (bounds != null) {
+						if (treeBounds.intersects(bounds)) {
+							paintItem(gc, item, bounds);
+						}
+					}
+
+					// defect 241039
+					//
+					if (item.getExpanded()) {
+						paintItems(gc, item.getItems(), treeBounds);
+					}
+				}
+			}
+		}
+	}
+
+	protected void paintItem(GC gc, TreeItem item, Rectangle bounds) {
+		// nothing to paint
+	}
+
+	public interface ICellEditorProvider {
+		CellEditor getCellEditor(Object o, int col);
+	}
+
+	/**
+	 * This class is used to improve drawing during a column resize.
+	 */
+	public class DelayedDrawTimer implements Runnable {
+		protected Control control;
+
+		public DelayedDrawTimer(Control control1) {
+			this.control = control1;
+		}
+
+		public void reset(int milliseconds) {
+			getDisplay().timerExec(milliseconds, this);
+		}
+
+		public void run() {
+			control.redraw();
+		}
+	}
+
+	Display getDisplay() {
+
+		return PlatformUI.getWorkbench().getDisplay();
+	}
+
+	/**
+	 * EditManager
+	 */
+	public class EditManager {
+		protected Tree fTree1;
+		protected Control cellEditorHolder;
+		protected CellEditorState cellEditorState;
+
+		public EditManager(Tree tree) {
+			this.fTree1 = tree;
+			this.cellEditorHolder = new Composite(tree, SWT.NONE);
+
+			final Tree theTree = tree;
+
+			MouseAdapter theMouseAdapter = new MouseAdapter() {
+				public void mouseDown(MouseEvent e) {
+					deactivateCellEditor();
+
+					if (e.x > columnPosition + columnHitWidth) {
+						TreeItem[] items = theTree.getSelection();
+						// No edit if more than one row is selected.
+						if (items.length == 1) {
+							Rectangle bounds = items[0].getBounds();
+							if ((bounds != null) && (e.y >= bounds.y) && (e.y <= bounds.y + bounds.height)) {
+								int columnToEdit = 1;
+								activateCellEditor(items[0], columnToEdit);
+							}
+						}
+					}
+				}
+			};
+
+			SelectionListener selectionListener = new SelectionListener() {
+				public void widgetDefaultSelected(SelectionEvent e) {
+					applyCellEditorValue();
+				}
+
+				public void widgetSelected(SelectionEvent e) {
+					applyCellEditorValue();
+				}
+			};
+
+			KeyListener keyListener = new KeyAdapter() {
+				public void keyPressed(KeyEvent e) {
+					if (e.character == SWT.CR) {
+						deactivateCellEditor();
+						TreeItem[] items = theTree.getSelection();
+						if (items.length == 1) {
+							activateCellEditor(items[0], 1);
+						}
+					}
+				}
+			};
+
+			tree.addMouseListener(theMouseAdapter);
+			tree.addKeyListener(keyListener);
+			ScrollBar hBar = tree.getHorizontalBar();
+			if (hBar != null) {
+				hBar.addSelectionListener(selectionListener);
+			}
+			ScrollBar vBar = tree.getVerticalBar();
+			if (vBar != null) {
+				vBar.addSelectionListener(selectionListener);
+			}
+		}
+
+		public boolean isCellEditorActive() {
+			return cellEditorState != null;
+		}
+
+		public void applyCellEditorValue() {
+			if ((cellEditorState != null) && (cellModifier != null)) {
+				TreeItem treeItem = cellEditorState.fTreeItem;
+
+				// The area below the cell editor needs to be explicity
+				// repainted on Linux
+				//
+				// Rectangle r = B2BHacks.IS_UNIX ? treeItem.getBounds() :
+				// null;
+
+				Object value = cellEditorState.fCellEditor.getValue();
+				String property = cellEditorState.fProperty;
+
+				deactivateCellEditor();
+
+				cellModifier.modify(treeItem, property, value);
+
+				// if (r != null) {
+				// tree.redraw(r.x, r.y, tree.getBounds().width, r.height,
+				// false);
+				// }
+			}
+		}
+
+		public void deactivateCellEditor() {
+			// Clean up any previous editor control
+			if (cellEditorState != null) {
+				cellEditorState.deactivate();
+				cellEditorState = null;
+			}
+		}
+
+		public void activateCellEditor(TreeItem treeItem, int column) {
+			if (cellModifier instanceof ICellEditorProvider) {
+				ICellEditorProvider cellEditorProvider = (ICellEditorProvider) cellModifier;
+				Object data = treeItem.getData();
+				if (fColumnProperties.length > column) {
+					String property = fColumnProperties[column];
+					if (cellModifier.canModify(data, property)) {
+						CellEditor newCellEditor = cellEditorProvider.getCellEditor(data, column);
+						if (newCellEditor != null) {
+							// The control that will be the editor must be a
+							// child of the columnPosition
+							Control control = newCellEditor.getControl();
+							if (control != null) {
+								cellEditorState = new CellEditorState(newCellEditor, control, treeItem, column, property);
+								cellEditorState.activate();
+							}
+						}
+					}
+				}
+			}
+		}
+
+		/**
+		 * this class holds the state that is need on a per cell editor
+		 * invocation basis
+		 */
+		public class CellEditorState implements ICellEditorListener, FocusListener {
+			public CellEditor fCellEditor;
+			public Control fControl;
+			public TreeItem fTreeItem;
+			public int fColumnNumber;
+			public String fProperty;
+
+			public CellEditorState(CellEditor cellEditor, Control control, TreeItem treeItem, int columnNumber, String property) {
+				this.fCellEditor = cellEditor;
+				this.fControl = control;
+				this.fTreeItem = treeItem;
+				this.fColumnNumber = columnNumber;
+				this.fProperty = property;
+			}
+
+			public void activate() {
+				Object element = fTreeItem.getData();
+				String value = cellModifier.getValue(element, fProperty).toString();
+				if (fControl instanceof Text) {
+					Text text = (Text) fControl;
+					int requiredSize = value.length() + 100;
+					if (text.getTextLimit() < requiredSize) {
+						text.setTextLimit(requiredSize);
+					}
+				}
+				Rectangle r = fTreeItem.getBounds();
+				if (r != null) {
+					fControl.setBounds(columnPosition + 5, r.y + 1, fTree1.getClientArea().width - (columnPosition + 5), r.height - 1);
+					fControl.setVisible(true);
+					fCellEditor.setValue(value);
+					fCellEditor.addListener(this);
+					fCellEditor.setFocus();
+					fControl.addFocusListener(this);
+				}
+			}
+
+			public void deactivate() {
+				fCellEditor.removeListener(this);
+				fControl.removeFocusListener(this);
+				fCellEditor.deactivate();
+				fTree1.forceFocus();
+			}
+
+			// ICellEditorListener methods
+			//
+			public void applyEditorValue() {
+				applyCellEditorValue();
+			}
+
+			public void cancelEditor() {
+				deactivateCellEditor();
+			}
+
+			public void editorValueChanged(boolean oldValidState, boolean newValidState) {
+				// nothing, for now
+			}
+
+			// FocusListener methods
+			//
+			public void focusGained(FocusEvent e) {
+				// do nothing
+			}
+
+			public void focusLost(FocusEvent e) {
+				applyCellEditorValue();
+			}
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/ViewerExpandCollapseAction.java b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/ViewerExpandCollapseAction.java
new file mode 100644
index 0000000..02fd23c
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/ViewerExpandCollapseAction.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.tabletree;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.viewers.AbstractTreeViewer;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+
+public class ViewerExpandCollapseAction extends Action {
+
+	protected boolean isExpandAction;
+	protected AbstractTreeViewer viewer = null;
+
+	public ViewerExpandCollapseAction(boolean isExpandAction) {
+		this.isExpandAction = isExpandAction;
+		if (isExpandAction) {
+			ImageDescriptor e_imageDescriptor = XMLEditorPluginImageHelper.getInstance().getImageDescriptor(XMLEditorPluginImages.IMG_ETOOL_EXPANDALL);
+			ImageDescriptor d_imageDescriptor = XMLEditorPluginImageHelper.getInstance().getImageDescriptor(XMLEditorPluginImages.IMG_DTOOL_EXPANDALL);
+
+			setImageDescriptor(e_imageDescriptor);
+			setDisabledImageDescriptor(d_imageDescriptor);
+			setToolTipText(XMLUIMessages._UI_INFO_EXPAND_ALL);
+		}
+		else {
+			ImageDescriptor e_imageDescriptor = XMLEditorPluginImageHelper.getInstance().getImageDescriptor(XMLEditorPluginImages.IMG_ETOOL_COLLAPSEALL);
+			ImageDescriptor d_imageDescriptor = XMLEditorPluginImageHelper.getInstance().getImageDescriptor(XMLEditorPluginImages.IMG_DTOOL_COLLAPSEALL);
+
+			setImageDescriptor(e_imageDescriptor);
+			setDisabledImageDescriptor(d_imageDescriptor);
+			setToolTipText(XMLUIMessages._UI_INFO_COLLAPSE_ALL);
+		}
+	}
+
+	public void setViewer(AbstractTreeViewer viewer) {
+		this.viewer = viewer;
+	}
+
+	public void run() {
+		if (viewer != null) {
+			// temporarily set the visibility to false
+			// this has a HUGE performance benefit
+			boolean isVisible = viewer.getControl().getVisible();
+			viewer.getControl().setVisible(false);
+
+			if (isExpandAction) {
+				viewer.expandAll();
+			}
+			else {
+				viewer.collapseAll();
+			}
+
+			// restore the previous visibility state
+			// 
+			viewer.getControl().setVisible(isVisible);
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLEditorActionDefinitionIds.java b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLEditorActionDefinitionIds.java
new file mode 100644
index 0000000..1d380cf
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLEditorActionDefinitionIds.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.tabletree;
+
+
+
+/**
+ * Defines the definitions ids for the XML editor actions.
+ * 
+ * @deprecated Use org.eclipse.wst.sse.ui.edit.util.ActionDefinitionIds
+ *             instead
+ */
+public interface XMLEditorActionDefinitionIds {
+	public final static String CLEANUP_DOCUMENT = "org.eclipse.wst.sse.ui.edit.ui.cleanup.document";//$NON-NLS-1$
+	public final static String FORMAT_DOCUMENT = "org.eclipse.wst.sse.ui.edit.ui.format.document";//$NON-NLS-1$
+	public final static String FORMAT_ACTIVE_ELEMENTS = "org.eclipse.wst.sse.ui.edit.ui.format.active.elements";//$NON-NLS-1$
+	public final static String OPEN_FILE = "org.eclipse.wst.sse.ui.edit.ui.open.file.from.source";//$NON-NLS-1$
+	// public final static String INFORMATION =
+	// "org.eclipse.wst.sse.ui.edit.ui.show.tooltip.information";//$NON-NLS-1$
+	public final static String INFORMATION = "org.eclipse.jdt.ui.edit.text.java.show.javadoc";//$NON-NLS-1$
+	public final static String ADD_BREAKPOINTS = "org.eclipse.wst.sse.ui.edit.ui.add.breakpoints";//$NON-NLS-1$
+	public final static String MANAGE_BREAKPOINTS = "org.eclipse.wst.sse.ui.edit.ui.manage.breakpoints";//$NON-NLS-1$
+	public final static String ENABLE_BREAKPOINTS = "org.eclipse.wst.sse.ui.edit.ui.enable.breakpoints";//$NON-NLS-1$
+	public final static String DISABLE_BREAKPOINTS = "org.eclipse.wst.sse.ui.edit.ui.disable.breakpoints";//$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLEditorMessages.java b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLEditorMessages.java
new file mode 100644
index 0000000..4fbac12
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLEditorMessages.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2009 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 - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.tabletree;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Strings used by XML Editor
+ * 
+ * @plannedfor 1.0
+ */
+public class XMLEditorMessages extends NLS {
+	private static final String BUNDLE_NAME = "org.eclipse.wst.xml.ui.internal.tabletree.XMLEditorResources";//$NON-NLS-1$
+
+	public static String XMLTableTreeViewer_0;
+	public static String XMLTableTreeViewer_1;
+	public static String XMLTableTreeViewer_2;
+	public static String XMLMultiPageEditorPart_0;
+	public static String XMLTreeExtension_0;
+	public static String XMLTreeExtension_1;
+	public static String XMLTreeExtension_3;
+	public static String XMLTreeExtension_4;
+	public static String XMLTableTreeActionBarContributor_0;
+	public static String XMLTableTreeActionBarContributor_1;
+	public static String XMLTableTreeActionBarContributor_2;
+	public static String XMLTableTreeActionBarContributor_3;
+	public static String XMLTableTreeActionBarContributor_4;
+	public static String XMLTableTreeActionBarContributor_5;
+	public static String XMLTableTreeActionBarContributor_6;
+	public static String XMLTableTreeActionBarContributor_7;
+	public static String XMLTableTreeActionBarContributor_8;
+	public static String An_error_has_occurred_when1_ERROR_;
+	public static String Resource__does_not_exist;
+	public static String Editor_could_not_be_open;
+	public static String TreeExtension_0;
+
+	static {
+		// load message values from bundle file
+		NLS.initializeMessages(BUNDLE_NAME, XMLEditorMessages.class);
+	}
+
+	private XMLEditorMessages() {
+		// cannot create new instance
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLEditorPluginImageHelper.java b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLEditorPluginImageHelper.java
new file mode 100644
index 0000000..b0d11df
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLEditorPluginImageHelper.java
@@ -0,0 +1,157 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.tabletree;
+
+import java.util.HashMap;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.resource.ImageRegistry;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.eclipse.wst.xml.ui.internal.XMLUIPlugin;
+
+/**
+ * Helper class to handle images provided by this plug-in.
+ * 
+ * NOTE: For internal use only. For images used externally, please use the
+ * Shared***ImageHelper class instead.
+ * 
+ * @author amywu
+ */
+public class XMLEditorPluginImageHelper {
+	private final String PLUGINID = XMLUIPlugin.ID;
+	private static XMLEditorPluginImageHelper instance = null;
+
+	// save a descriptor for each image
+	private HashMap fImageDescRegistry = null;
+
+	/**
+	 * Gets the instance.
+	 * 
+	 * @return Returns a XMLEditorPluginImageHelper
+	 */
+	public synchronized static XMLEditorPluginImageHelper getInstance() {
+		if (instance == null) {
+			instance = new XMLEditorPluginImageHelper();
+		}
+		return instance;
+	}
+
+	/**
+	 * Retrieves the image associated with resource from the image registry.
+	 * If the image cannot be retrieved, attempt to find and load the image at
+	 * the location specified in resource.
+	 * 
+	 * @param resource
+	 *            the image to retrieve
+	 * @return Image the image associated with resource or null if one could
+	 *         not be found
+	 */
+	public Image getImage(String resource) {
+		Image image = getImageRegistry().get(resource);
+		if (image == null) {
+			// create an image
+			image = createImage(resource);
+		}
+		return image;
+	}
+
+	/**
+	 * Retrieves the image descriptor associated with resource from the image
+	 * descriptor registry. If the image descriptor cannot be retrieved,
+	 * attempt to find and load the image descriptor at the location specified
+	 * in resource.
+	 * 
+	 * @param resource
+	 *            the image descriptor to retrieve
+	 * @return ImageDescriptor the image descriptor assocated with resource or
+	 *         the default "missing" image descriptor if one could not be
+	 *         found
+	 */
+	public ImageDescriptor getImageDescriptor(String resource) {
+		ImageDescriptor imageDescriptor = null;
+		Object o = getImageDescriptorRegistry().get(resource);
+		if (o == null) {
+			// create a descriptor
+			imageDescriptor = createImageDescriptor(resource);
+		}
+		else {
+			imageDescriptor = (ImageDescriptor) o;
+		}
+		return imageDescriptor;
+	}
+
+	/**
+	 * Returns the image descriptor registry for this plugin.
+	 * 
+	 * @return HashMap - image descriptor registry for this plugin
+	 */
+	private HashMap getImageDescriptorRegistry() {
+		if (fImageDescRegistry == null) {
+			fImageDescRegistry = new HashMap();
+		}
+		return fImageDescRegistry;
+	}
+
+	/**
+	 * Returns the image registry for this plugin.
+	 * 
+	 * @return ImageRegistry - image registry for this plugin
+	 */
+	private ImageRegistry getImageRegistry() {
+		return JFaceResources.getImageRegistry();
+	}
+
+	/**
+	 * Creates an image from the given resource and adds the image to the
+	 * image registry.
+	 * 
+	 * @param resource
+	 * @return Image
+	 */
+	private Image createImage(String resource) {
+		ImageDescriptor desc = getImageDescriptor(resource);
+		Image image = null;
+
+		if (desc != null) {
+			image = desc.createImage();
+			// dont add the missing image descriptor image to the image
+			// registry
+			if (!desc.equals(ImageDescriptor.getMissingImageDescriptor())) {
+				getImageRegistry().put(resource, image);
+			}
+		}
+		return image;
+	}
+
+	/**
+	 * Creates an image descriptor from the given imageFilePath and adds the
+	 * image descriptor to the image descriptor registry. If an image
+	 * descriptor could not be created, the default "missing" image descriptor
+	 * is returned but not added to the image descriptor registry.
+	 * 
+	 * @param imageFilePath
+	 * @return ImageDescriptor image descriptor for imageFilePath or default
+	 *         "missing" image descriptor if resource could not be found
+	 */
+	private ImageDescriptor createImageDescriptor(String imageFilePath) {
+		ImageDescriptor imageDescriptor = AbstractUIPlugin.imageDescriptorFromPlugin(PLUGINID, imageFilePath);
+		if (imageDescriptor != null) {
+			getImageDescriptorRegistry().put(imageFilePath, imageDescriptor);
+		}
+		else {
+			imageDescriptor = ImageDescriptor.getMissingImageDescriptor();
+		}
+
+		return imageDescriptor;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLEditorPluginImages.java b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLEditorPluginImages.java
new file mode 100644
index 0000000..a35f00f
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLEditorPluginImages.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.tabletree;
+
+/**
+ * Bundle of most images used by the XML Editor plug-in.
+ */
+public class XMLEditorPluginImages {
+	public static final String IMG_DTOOL_COLLAPSE = "icons/full/dtool16/collapse.gif"; //$NON-NLS-1$
+	public static final String IMG_ETOOL_COLLAPSE = "icons/full/etool16/collapse.gif"; //$NON-NLS-1$
+	public static final String IMG_DTOOL_COLLAPSEALL = "icons/full/dtool16/collapse_all.gif"; //$NON-NLS-1$
+	public static final String IMG_ETOOL_COLLAPSEALL = "icons/full/etool16/collapse_all.gif"; //$NON-NLS-1$
+	public static final String IMG_DTOOL_EXPAND = "icons/full/dtool16/expand.gif"; //$NON-NLS-1$
+	public static final String IMG_ETOOL_EXPAND = "icons/full/etool16/expand.gif"; //$NON-NLS-1$
+	public static final String IMG_DTOOL_EXPANDALL = "icons/full/dtool16/expand_all.gif"; //$NON-NLS-1$
+	public static final String IMG_ETOOL_EXPANDALL = "icons/full/etool16/expand_all.gif"; //$NON-NLS-1$
+	public static final String IMG_DTOOL_NEW_XML = "icons/full/dtool16/new_xml.gif"; //$NON-NLS-1$
+	public static final String IMG_ETOOL_NEW_XML = "icons/full/etool16/new_xml.gif"; //$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLEditorResources.properties b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLEditorResources.properties
new file mode 100644
index 0000000..1943b11
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLEditorResources.properties
@@ -0,0 +1,32 @@
+###############################################################################
+# Copyright (c) 2004, 2009 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
+###############################################################################
+XMLTableTreeViewer_0=Design
+XMLTableTreeViewer_1=Node
+XMLTableTreeViewer_2=Content
+XMLMultiPageEditorPart_0=Source
+XMLTreeExtension_0=Structure
+XMLTreeExtension_1=Value
+XMLTreeExtension_3=The document is empty.
+XMLTreeExtension_4=Right mouse click here to insert content.
+XMLTableTreeActionBarContributor_0=&XML
+XMLTableTreeActionBarContributor_1=&Expand All
+XMLTableTreeActionBarContributor_2=&Collapse All
+XMLTableTreeActionBarContributor_3=Turn Grammar Constraints Off
+XMLTableTreeActionBarContributor_4=&Turn Grammar Constraints Off
+XMLTableTreeActionBarContributor_5=Turn Grammar Constraints On
+XMLTableTreeActionBarContributor_6=&Turn Grammar Constraints On
+XMLTableTreeActionBarContributor_7=Reload Dependencies
+XMLTableTreeActionBarContributor_8=&Reload Dependencies
+##
+An_error_has_occurred_when1_ERROR_=An error has occurred when initializing the input for the the editor's source page.
+Resource__does_not_exist=Resource {0} does not exist.
+Editor_could_not_be_open=Editor could not be open on {0}
+TreeExtension_0=Cannot display document contents.
diff --git a/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLMultiPageEditorActionBarContributor.java b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLMultiPageEditorActionBarContributor.java
new file mode 100644
index 0000000..7d4ee4b
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLMultiPageEditorActionBarContributor.java
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.tabletree;
+
+
+
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.wst.sse.ui.internal.ISourceViewerActionBarContributor;
+
+
+public class XMLMultiPageEditorActionBarContributor extends SourceEditorActionBarContributor {
+
+	private boolean needsMultiInit = true;
+
+	public XMLMultiPageEditorActionBarContributor() {
+		super();
+	}
+
+	protected void initDesignViewerActionBarContributor(IActionBars actionBars) {
+		super.initDesignViewerActionBarContributor(actionBars);
+
+		if (designViewerActionBarContributor != null) {
+			if (designViewerActionBarContributor instanceof IDesignViewerActionBarContributor) {
+				((IDesignViewerActionBarContributor) designViewerActionBarContributor).initViewerSpecificContributions(actionBars);
+			}
+		}
+	}
+
+	protected void activateDesignPage(IEditorPart activeEditor) {
+		if ((sourceViewerActionContributor != null) && (sourceViewerActionContributor instanceof ISourceViewerActionBarContributor)) {
+			// if design page is not really an IEditorPart, activeEditor ==
+			// null, so pass in multiPageEditor instead (d282414)
+			if (activeEditor == null) {
+				sourceViewerActionContributor.setActiveEditor(multiPageEditor);
+			}
+			else {
+				sourceViewerActionContributor.setActiveEditor(activeEditor);
+			}
+			((ISourceViewerActionBarContributor) sourceViewerActionContributor).setViewerSpecificContributionsEnabled(false);
+		}
+
+		if ((designViewerActionBarContributor != null) && (designViewerActionBarContributor instanceof IDesignViewerActionBarContributor)) {
+			designViewerActionBarContributor.setActiveEditor(multiPageEditor);
+			((IDesignViewerActionBarContributor) designViewerActionBarContributor).setViewerSpecificContributionsEnabled(true);
+		}
+	}
+
+	protected void activateSourcePage(IEditorPart activeEditor) {
+		if ((designViewerActionBarContributor != null) && (designViewerActionBarContributor instanceof IDesignViewerActionBarContributor)) {
+			designViewerActionBarContributor.setActiveEditor(multiPageEditor);
+			((IDesignViewerActionBarContributor) designViewerActionBarContributor).setViewerSpecificContributionsEnabled(false);
+		}
+
+		if ((sourceViewerActionContributor != null) && (sourceViewerActionContributor instanceof ISourceViewerActionBarContributor)) {
+			sourceViewerActionContributor.setActiveEditor(activeEditor);
+			((ISourceViewerActionBarContributor) sourceViewerActionContributor).setViewerSpecificContributionsEnabled(true);
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.ui.part.EditorActionBarContributor#init(org.eclipse.ui.IActionBars)
+	 */
+	public void init(IActionBars actionBars) {
+		super.init(actionBars);
+		needsMultiInit = true;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.ui.IEditorActionBarContributor#setActiveEditor(org.eclipse.ui.IEditorPart)
+	 */
+	public void setActiveEditor(IEditorPart targetEditor) {
+		if (needsMultiInit) {
+			designViewerActionBarContributor = new XMLTableTreeActionBarContributor();
+			initDesignViewerActionBarContributor(getActionBars());
+			needsMultiInit = false;
+		}
+		super.setActiveEditor(targetEditor);
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLMultiPageEditorPart.java b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLMultiPageEditorPart.java
new file mode 100644
index 0000000..57e8337
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLMultiPageEditorPart.java
@@ -0,0 +1,1060 @@
+/*****************************************************************************
+ * 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
+ ****************************************************************************/
+package org.eclipse.wst.xml.ui.internal.tabletree;
+
+
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExecutableExtension;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.action.IStatusLineManager;
+import org.eclipse.jface.action.ToolBarManager;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextInputListener;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.viewers.AbstractTreeViewer;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.IPostSelectionProvider;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.ToolBar;
+import org.eclipse.ui.IEditorActionBarContributor;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IEditorSite;
+import org.eclipse.ui.IPartListener;
+import org.eclipse.ui.IPartService;
+import org.eclipse.ui.IPropertyListener;
+import org.eclipse.ui.IWindowListener;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.ide.IDE;
+import org.eclipse.ui.ide.IGotoMarker;
+import org.eclipse.ui.part.MultiPageEditorActionBarContributor;
+import org.eclipse.ui.part.MultiPageEditorPart;
+import org.eclipse.ui.part.MultiPageEditorSite;
+import org.eclipse.ui.part.MultiPageSelectionProvider;
+import org.eclipse.ui.progress.UIJob;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+import org.eclipse.wst.sse.ui.StructuredTextEditor;
+import org.eclipse.wst.sse.ui.internal.contentoutline.IJFaceNodeAdapter;
+import org.eclipse.wst.xml.core.internal.provisional.IXMLPreferenceNames;
+import org.eclipse.wst.xml.core.internal.provisional.contenttype.ContentTypeIdForXML;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
+import org.eclipse.wst.xml.ui.internal.Logger;
+import org.eclipse.wst.xml.ui.internal.XMLUIPlugin;
+import org.eclipse.wst.xml.ui.internal.contentoutline.JFaceNodeLabelProvider;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+public class XMLMultiPageEditorPart extends MultiPageEditorPart {
+
+	/**
+	 * Internal part activation listener, copied from AbstractTextEditor
+	 */
+	class ActivationListener implements IPartListener, IWindowListener {
+
+		/**
+		 * The maximum number of children the root nodes can have for the
+		 * design page to auto expand the root nodes
+		 */
+		private static final int MAX_NUM_CHILD_NODES_FOR_AUTO_EXPAND = 500;
+		
+		/** Cache of the active workbench part. */
+		private IWorkbenchPart fActivePart;
+		/** Indicates whether activation handling is currently be done. */
+		private boolean fIsHandlingActivation = false;
+		/**
+		 * The part service.
+		 * 
+		 * @since 3.1
+		 */
+		private IPartService fPartService;
+
+		/**
+		 * Creates this activation listener.
+		 * 
+		 * @param partService
+		 *            the part service on which to add the part listener
+		 * @since 3.1
+		 */
+		public ActivationListener(IPartService partService) {
+			fPartService = partService;
+			fPartService.addPartListener(this);
+			PlatformUI.getWorkbench().addWindowListener(this);
+		}
+
+		/**
+		 * Disposes this activation listener.
+		 * 
+		 * @since 3.1
+		 */
+		public void dispose() {
+			fPartService.removePartListener(this);
+			PlatformUI.getWorkbench().removeWindowListener(this);
+			fPartService = null;
+		}
+
+		/*
+		 * @see IPartListener#partActivated(org.eclipse.ui.IWorkbenchPart)
+		 */
+		public void partActivated(IWorkbenchPart part) {
+			fActivePart = part;
+			handleActivation();
+		}
+
+		/*
+		 * @see IPartListener#partBroughtToTop(org.eclipse.ui.IWorkbenchPart)
+		 */
+		public void partBroughtToTop(IWorkbenchPart part) {
+			// do nothing
+		}
+
+		/*
+		 * @see IPartListener#partClosed(org.eclipse.ui.IWorkbenchPart)
+		 */
+		public void partClosed(IWorkbenchPart part) {
+			// do nothing
+		}
+
+		/*
+		 * @see IPartListener#partDeactivated(org.eclipse.ui.IWorkbenchPart)
+		 */
+		public void partDeactivated(IWorkbenchPart part) {
+			fActivePart = null;
+		}
+
+		/*
+		 * @see IPartListener#partOpened(org.eclipse.ui.IWorkbenchPart)
+		 */
+		public void partOpened(IWorkbenchPart part) {
+			if (fDesignViewer instanceof AbstractTreeViewer) {
+				IStructuredModel model = StructuredModelManager.getModelManager().getExistingModelForRead(getDocument());
+				try {
+					if (model instanceof IDOMModel) {
+						IDOMDocument modelDocument = ((IDOMModel) model).getDocument();
+						NodeList rootChildren = modelDocument.getChildNodes();
+
+						boolean tooManyChildren = (rootChildren.getLength() > MAX_NUM_CHILD_NODES_FOR_AUTO_EXPAND);
+						/*
+						 * For each root (there should really only be one
+						 * real root but there are also could be empty
+						 * text regions and doc type at the root level)
+						 * determine if it has to many children or not to
+						 * auto expand
+						 */
+						for (int i = 0; i < rootChildren.getLength() && !tooManyChildren; ++i) {
+							tooManyChildren = (rootChildren.item(i).getChildNodes().getLength() > MAX_NUM_CHILD_NODES_FOR_AUTO_EXPAND);
+						}
+
+						/*
+						 * if root node does not have to many children then
+						 * auto expand the root node
+						 */
+						if (!tooManyChildren) {
+							((AbstractTreeViewer) fDesignViewer).expandToLevel(2);
+						}
+					}
+				}
+				finally {
+					if (model != null) {
+						model.releaseFromRead();
+					}
+				}
+			}
+		}
+
+		/**
+		 * Handles the activation triggering a element state check in the
+		 * editor.
+		 */
+		void handleActivation() {
+			if (fIsHandlingActivation || (getTextEditor() == null)) {
+				return;
+			}
+
+			if (fActivePart == XMLMultiPageEditorPart.this) {
+				fIsHandlingActivation = true;
+				try {
+					getTextEditor().safelySanityCheckState(getEditorInput());
+				}
+				finally {
+					fIsHandlingActivation = false;
+				}
+			}
+		}
+
+		/*
+		 * @see org.eclipse.ui.IWindowListener#windowActivated(org.eclipse.ui.IWorkbenchWindow)
+		 * @since 3.1
+		 */
+		public void windowActivated(IWorkbenchWindow window) {
+			if (window == getEditorSite().getWorkbenchWindow()) {
+				/*
+				 * Workaround for problem described in
+				 * http://dev.eclipse.org/bugs/show_bug.cgi?id=11731 Will be
+				 * removed when SWT has solved the problem.
+				 */
+				window.getShell().getDisplay().asyncExec(new Runnable() {
+					public void run() {
+						handleActivation();
+					}
+				});
+			}
+		}
+
+		/*
+		 * @see org.eclipse.ui.IWindowListener#windowDeactivated(org.eclipse.ui.IWorkbenchWindow)
+		 * @since 3.1
+		 */
+		public void windowDeactivated(IWorkbenchWindow window) {
+			// do nothing
+		}
+
+		/*
+		 * @see org.eclipse.ui.IWindowListener#windowClosed(org.eclipse.ui.IWorkbenchWindow)
+		 * @since 3.1
+		 */
+		public void windowClosed(IWorkbenchWindow window) {
+			// do nothing
+		}
+
+		/*
+		 * @see org.eclipse.ui.IWindowListener#windowOpened(org.eclipse.ui.IWorkbenchWindow)
+		 * @since 3.1
+		 */
+		public void windowOpened(IWorkbenchWindow window) {
+			// do nothing
+		}
+	}
+
+	/**
+	 * Listens for selection from the source page, applying it to the design
+	 * viewer.
+	 */
+	private class TextEditorPostSelectionAdapter extends UIJob implements ISelectionChangedListener {
+		boolean forcePostSelection = false;
+		ISelection selection = null;
+
+		public TextEditorPostSelectionAdapter() {
+			super(getTitle());
+			setUser(true);
+		}
+
+		public IStatus runInUIThread(IProgressMonitor monitor) {
+			if (selection != null) {
+				fDesignViewer.getSelectionProvider().setSelection(selection);
+			}
+			return Status.OK_STATUS;
+		}
+
+		public void selectionChanged(SelectionChangedEvent event) {
+			if ((fDesignViewer != null) && ((getActivePage() != fDesignPageIndex) || !XMLMultiPageEditorPart.this.equals(getSite().getPage().getActivePart()))) {
+				if (forcePostSelection) {
+					selection = event.getSelection();
+					schedule(200);
+				}
+				else {
+					fDesignViewer.getSelectionProvider().setSelection(event.getSelection());
+				}
+			}
+		}
+	}
+
+	private class PageInitializationData {
+		IConfigurationElement fElement;
+		String fPropertyName;
+		Object fData;
+
+		PageInitializationData(IConfigurationElement cfig, String propertyName, Object data) {
+			super();
+			fElement = cfig;
+			fPropertyName = propertyName;
+			fData = data;
+		}
+
+		void sendInitializationData(IExecutableExtension executableExtension) {
+			try {
+				executableExtension.setInitializationData(fElement, fPropertyName, fData);
+			}
+			catch (CoreException e) {
+				Logger.logException(e);
+			}
+		}
+	}
+
+	/**
+	 * Internal IPropertyListener on the source page
+	 */
+	class PropertyListener implements IPropertyListener {
+		public void propertyChanged(Object source, int propId) {
+			switch (propId) {
+				// had to implement input changed "listener" so that
+				// StructuredTextEditor could tell it containing editor that
+				// the input has change, when a 'resource moved' event is
+				// found.
+				case IEditorPart.PROP_INPUT : {
+					if (source == getTextEditor() && fDesignViewer instanceof XMLTableTreeViewer) {
+						IStructuredModel model = StructuredModelManager.getModelManager().getExistingModelForRead(getDocument());
+						try {
+							if (model instanceof IDOMModel) {
+								IDOMDocument modelDocument = ((IDOMModel) model).getDocument();
+								Object designInput = ((XMLTableTreeViewer) fDesignViewer).getInput();
+								if (modelDocument != designInput)
+									setInput(getTextEditor().getEditorInput());
+							}
+						}
+						finally {
+							if (model != null)
+								model.releaseFromRead();
+						}
+					}
+				}
+				case IEditorPart.PROP_DIRTY : {
+					if (source == getTextEditor()) {
+						if (getTextEditor().getEditorInput() != getEditorInput()) {
+							setInput(getTextEditor().getEditorInput());
+							/*
+							 * title should always change when input changes.
+							 * create runnable for following post call
+							 */
+							Runnable runnable = new Runnable() {
+								public void run() {
+									_firePropertyChange(IWorkbenchPart.PROP_TITLE);
+								}
+							};
+							/*
+							 * Update is just to post things on the display
+							 * queue (thread). We have to do this to get the
+							 * dirty property to get updated after other
+							 * things on the queue are executed.
+							 */
+							((Control) getTextEditor().getAdapter(Control.class)).getDisplay().asyncExec(runnable);
+						}
+					}
+					break;
+				}
+				case IWorkbenchPart.PROP_TITLE : {
+					// update the input if the title is changed
+					if (source == getTextEditor()) {
+						if (getTextEditor().getEditorInput() != getEditorInput()) {
+							setInput(getTextEditor().getEditorInput());
+						}
+					}
+					break;
+				}
+				default : {
+					// propagate changes. Is this needed? Answer: Yes.
+					if (source == getTextEditor()) {
+						_firePropertyChange(propId);
+					}
+					break;
+				}
+			}
+
+		}
+	}
+
+	class TextInputListener implements ITextInputListener {
+		public void inputDocumentAboutToBeChanged(IDocument oldInput, IDocument newInput) {
+			// do nothing
+		}
+
+		public void inputDocumentChanged(IDocument oldInput, IDocument newInput) {
+			if ((fDesignViewer != null) && (newInput != null)) {
+				fDesignViewer.setDocument(newInput);
+			}
+		}
+	}
+
+	class StatusLineLabelProvider extends JFaceNodeLabelProvider {
+		public StatusLineLabelProvider() {
+		}
+
+		public String getText(Object element) {
+			if (element == null)
+				return null;
+
+			Node node = (Node) element;
+			if (node.getNodeType() == Node.ATTRIBUTE_NODE) {
+				return getText(((Attr) node).getOwnerElement());
+			}
+
+			StringBuffer s = new StringBuffer();
+			if (node.getNodeType() != Node.DOCUMENT_NODE) {
+				while (node != null && node instanceof INodeNotifier) {
+					INodeNotifier notifier = (INodeNotifier) node;
+					if (node.getNodeType() != Node.DOCUMENT_NODE) {
+						IJFaceNodeAdapter adapter = (IJFaceNodeAdapter) notifier.getAdapterFor(IJFaceNodeAdapter.class);
+						if (adapter != null) {
+							s.insert(0, adapter.getLabelText(node));
+						}
+					}
+					node = node.getParentNode();
+					if (node != null && node.getNodeType() != Node.DOCUMENT_NODE)
+						s.insert(0, IPath.SEPARATOR);
+				}
+			}
+			return s.toString();
+		}
+
+		public Image getImage(Object element) {
+			if (element == null)
+				return null;
+
+			Node node = (Node) element;
+			if (node.getNodeType() == Node.ATTRIBUTE_NODE) {
+				return getImage(((Attr) node).getOwnerElement());
+			}
+			return super.getImage(element);
+		}
+	}
+
+	/** The design page index. */
+	private int fDesignPageIndex;
+
+	/** The design viewer */
+	IDesignViewer fDesignViewer;
+	/** Any container for the design viewer */
+	private Composite fDesignContainer;
+
+	private ActivationListener fActivationListener;
+
+	IPropertyListener fPropertyListener = null;
+
+	/** The source page index. */
+	int fSourcePageIndex;
+
+	/** The text editor. */
+	private StructuredTextEditor fTextEditor;
+
+	private TextEditorPostSelectionAdapter fTextEditorSelectionListener;
+
+	private ILabelProvider fStatusLineLabelProvider;
+
+	private PageInitializationData fPageInitializer;
+	
+	private ToolBarManager fToolbarManager;
+
+	private boolean fAllocateToolbar = true;
+	
+	/**
+	 * StructuredTextMultiPageEditorPart constructor comment.
+	 */
+	public XMLMultiPageEditorPart() {
+		super();
+		fStatusLineLabelProvider = new StatusLineLabelProvider();
+	}
+
+	/*
+	 * This method is just to make firePropertyChanged accessible from some
+	 * (anonomous) inner classes.
+	 */
+	void _firePropertyChange(int property) {
+		super.firePropertyChange(property);
+	}
+
+	/**
+	 * Adds the source page of the multi-page editor.
+	 */
+	private void addSourcePage() throws PartInitException {
+		fSourcePageIndex = addPage(fTextEditor, getEditorInput());
+		setPageText(fSourcePageIndex, XMLEditorMessages.XMLMultiPageEditorPart_0);
+
+		firePropertyChange(PROP_TITLE);
+
+		// Changes to the Text Viewer's document instance should also
+		// force an
+		// input refresh
+		fTextEditor.getTextViewer().addTextInputListener(new TextInputListener());
+	}
+
+	/**
+	 * Connects the design viewer with the viewer selection manager. Should be
+	 * done after createSourcePage() is done because we need to get the
+	 * ViewerSelectionManager from the TextEditor. setModel is also done here
+	 * because getModel() needs to reference the TextEditor.
+	 */
+	private void connectDesignPage() {
+		if (fDesignViewer != null) {
+			fDesignViewer.setDocument(getDocument());
+		}
+
+		/*
+		 * Connect selection from the Design page to the selection provider
+		 * for the XMLMultiPageEditorPart so that selection changes in the
+		 * Design page will propagate across the workbench
+		 */
+		if (fDesignViewer.getSelectionProvider() instanceof IPostSelectionProvider) {
+			((IPostSelectionProvider) fDesignViewer.getSelectionProvider()).addPostSelectionChangedListener(new ISelectionChangedListener() {
+				public void selectionChanged(SelectionChangedEvent event) {
+					((MultiPageSelectionProvider) getSite().getSelectionProvider()).firePostSelectionChanged(event);
+				}
+			});
+		}
+		fDesignViewer.getSelectionProvider().addSelectionChangedListener(new ISelectionChangedListener() {
+			public void selectionChanged(SelectionChangedEvent event) {
+				((MultiPageSelectionProvider) getSite().getSelectionProvider()).fireSelectionChanged(event);
+			}
+		});
+
+		/*
+		 * Connect selection from the Design page to the selection provider of
+		 * the Source page so that selection in the Design page will drive
+		 * selection in the Source page. Prefer post selection.
+		 */
+		if (fDesignViewer.getSelectionProvider() instanceof IPostSelectionProvider) {
+			((IPostSelectionProvider) fDesignViewer.getSelectionProvider()).addPostSelectionChangedListener(new ISelectionChangedListener() {
+				public void selectionChanged(final SelectionChangedEvent event) {
+					/*
+					 * Only force selection update if source page is not
+					 * active
+					 */
+					if (getActivePage() != fSourcePageIndex) {
+						getTextEditor().getSelectionProvider().setSelection(event.getSelection());
+					}
+				}
+			});
+		}
+		else {
+			fDesignViewer.getSelectionProvider().addSelectionChangedListener(new ISelectionChangedListener() {
+				public void selectionChanged(SelectionChangedEvent event) {
+					/*
+					 * Only force selection update if source page is not
+					 * active
+					 */
+					if (getActivePage() != fSourcePageIndex) {
+						getTextEditor().getSelectionProvider().setSelection(event.getSelection());
+					}
+					/*
+					 * Bug 210481 - Removed call to updateStatusLine because
+					 * this is already handled by the selection in the source
+					 * page
+					 */
+				}
+			});
+		}
+
+		/*
+		 * Handle double-click in the Design page by selecting the
+		 * corresponding amount of text in the Source page.
+		 * 
+		 * Warning: This implies more knowledge of the design viewer's underlying
+		 * Control than expressed in the IDesignViewer interface
+		 */
+		fDesignViewer.getControl().addListener(SWT.MouseDoubleClick, new Listener() {
+			public void handleEvent(Event event) {
+				ISelection selection = fDesignViewer.getSelectionProvider().getSelection();
+				int start = -1;
+				int length = -1;
+				if (selection instanceof IStructuredSelection) {
+					/*
+					 * selection goes from the start of the first object to
+					 * the end of the last
+					 */
+					IStructuredSelection structuredSelection = (IStructuredSelection) selection;
+					Object o = structuredSelection.getFirstElement();
+					Object o2 = null;
+					if (structuredSelection.size() > 1) {
+						o2 = structuredSelection.toArray()[structuredSelection.size() - 1];
+					}
+					else {
+						o2 = o;
+					}
+					if (o instanceof IndexedRegion) {
+						start = ((IndexedRegion) o).getStartOffset();
+						length = ((IndexedRegion) o2).getEndOffset() - start;
+					}
+					else if (o2 instanceof ITextRegion) {
+						start = ((ITextRegion) o).getStart();
+						length = ((ITextRegion) o2).getEnd() - start;
+					}
+				}
+				else if (selection instanceof ITextSelection) {
+					start = ((ITextSelection) selection).getOffset();
+					length = ((ITextSelection) selection).getLength();
+				}
+				if ((start > -1) && (length > -1)) {
+					getTextEditor().selectAndReveal(start, length);
+				}
+			}
+		});
+
+		/*
+		 * Connect selection from the Source page to the selection provider of
+		 * the Design page so that selection in the Source page will drive
+		 * selection in the Design page. Prefer post selection.
+		 */
+		ISelectionProvider provider = getTextEditor().getSelectionProvider();
+		if (fTextEditorSelectionListener == null) {
+			fTextEditorSelectionListener = new TextEditorPostSelectionAdapter();
+		}
+		if (provider instanceof IPostSelectionProvider) {
+			fTextEditorSelectionListener.forcePostSelection = false;
+			((IPostSelectionProvider) provider).addPostSelectionChangedListener(fTextEditorSelectionListener);
+		}
+		else {
+			fTextEditorSelectionListener.forcePostSelection = true;
+			provider.addSelectionChangedListener(fTextEditorSelectionListener);
+		}
+	}
+
+	/**
+	 * Create and Add the Design Page using a registered factory
+	 * 
+	 */
+	private void createAndAddDesignPage() {
+		IDesignViewer designViewer = createDesignPage();
+
+		fDesignViewer = designViewer;
+		// note: By adding the design page as a Control instead of an
+		// IEditorPart, page switches will indicate
+		// a "null" active editor when the design page is made active
+		if (fDesignContainer != null)
+			fDesignPageIndex = addPage(fDesignContainer);
+		else
+			fDesignPageIndex = addPage(designViewer.getControl());
+			
+		setPageText(fDesignPageIndex, designViewer.getTitle());
+	}
+
+	protected IDesignViewer createDesignPage() {		
+		Composite container = getDesignContainer(getContainer());
+
+		XMLTableTreeViewer tableTreeViewer = new XMLTableTreeViewer(container);
+		tableTreeViewer.getControl().setLayoutData(new GridData(GridData.FILL_BOTH));
+		// Set the default info-pop for XML design viewer.
+		XMLUIPlugin.getInstance().getWorkbench().getHelpSystem().setHelp(tableTreeViewer.getControl(), XMLTableTreeHelpContextIds.XML_DESIGN_VIEW_HELPID);
+
+		// Toolbar wasn't allocated
+		if (fToolbarManager != null) {
+			addToolBarActions(tableTreeViewer);
+		}
+		return tableTreeViewer;
+	}
+
+	protected Composite getDesignContainer(Composite defaultContainer) {
+		Composite container = defaultContainer;
+		// create a container to hold the toolbar if it should be created
+		if (fAllocateToolbar) {
+			container = new Composite(defaultContainer, SWT.NONE);
+			GridLayout layout = new GridLayout();
+			layout.marginHeight = 0;
+			layout.verticalSpacing = 0;
+			layout.marginWidth = 0;
+			container.setLayout(layout);
+	
+			ToolBar tb = new ToolBar(container, SWT.FLAT);
+			fToolbarManager = new ToolBarManager(tb);
+			tb.setLayoutData(new GridData(GridData.END, GridData.VERTICAL_ALIGN_BEGINNING, true, false));
+			fDesignContainer = container;
+		}
+		return container;
+	}
+
+	private void addToolBarActions(IDesignViewer viewer) {
+		if (viewer instanceof AbstractTreeViewer) {
+			ViewerExpandCollapseAction expand = new ViewerExpandCollapseAction(true);
+			ViewerExpandCollapseAction collapse = new ViewerExpandCollapseAction(false);
+			fToolbarManager.add(expand);
+			fToolbarManager.add(collapse);
+			fToolbarManager.update(true);
+	
+	
+			expand.setViewer((AbstractTreeViewer) viewer);
+			collapse.setViewer((AbstractTreeViewer) viewer);
+		}
+	}
+
+	/**
+	 * Creates the pages of this multi-page editor.
+	 * <p>
+	 * Subclasses of <code>MultiPageEditor</code> must implement this method.
+	 * </p>
+	 */
+	protected void createPages() {
+		try {
+			// source page MUST be created before design page, now
+			createSourcePage();
+
+			createAndAddDesignPage();
+			addSourcePage();
+			connectDesignPage();
+
+			// set the active editor in the action bar contributor first
+			// before setactivepage calls action bar contributor's
+			// setactivepage (bug141013 - remove when bug151488 is fixed)
+			IEditorActionBarContributor contributor = getEditorSite().getActionBarContributor();
+			if (contributor instanceof MultiPageEditorActionBarContributor) {
+				((MultiPageEditorActionBarContributor) contributor).setActiveEditor(this);
+			}
+
+			int activePageIndex = getPreferenceStore().getInt(IXMLPreferenceNames.LAST_ACTIVE_PAGE);
+			if ((activePageIndex >= 0) && (activePageIndex < getPageCount())) {
+				setActivePage(activePageIndex);
+			}
+			else {
+				setActivePage(fSourcePageIndex);
+			}
+		}
+		catch (PartInitException e) {
+			Logger.logException(e);
+			throw new RuntimeException(e);
+		}
+	}
+
+	/**
+	 * @see org.eclipse.ui.part.MultiPageEditorPart#createSite(org.eclipse.ui.IEditorPart)
+	 */
+	protected IEditorSite createSite(IEditorPart editor) {
+		IEditorSite site = null;
+		if (editor == fTextEditor) {
+			site = new MultiPageEditorSite(this, editor) {
+				/**
+				 * @see org.eclipse.ui.part.MultiPageEditorSite#getActionBarContributor()
+				 */
+				public IEditorActionBarContributor getActionBarContributor() {
+					IEditorActionBarContributor contributor = super.getActionBarContributor();
+					IEditorActionBarContributor multiContributor = XMLMultiPageEditorPart.this.getEditorSite().getActionBarContributor();
+					if (multiContributor instanceof XMLMultiPageEditorActionBarContributor) {
+						contributor = ((XMLMultiPageEditorActionBarContributor) multiContributor).sourceViewerActionContributor;
+					}
+					return contributor;
+				}
+
+				public String getId() {
+					// sets this id so nested editor is considered xml source
+					// page
+					return ContentTypeIdForXML.ContentTypeID_XML + ".source"; //$NON-NLS-1$;
+				}
+			};
+		}
+		else {
+			site = super.createSite(editor);
+		}
+		return site;
+	}
+
+	/**
+	 * Creates the source page of the multi-page editor.
+	 */
+	protected void createSourcePage() throws PartInitException {
+		fTextEditor = createTextEditor();
+		fTextEditor.setEditorPart(this);
+
+		/*
+		 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=134301 - XML editor
+		 * does not remember font settings
+		 * 
+		 * @see
+		 * org.eclipse.ui.texteditor.AbstractTextEditor#getSymbolicFontName()
+		 */
+		fPageInitializer.sendInitializationData(fTextEditor);
+
+		if (fPropertyListener == null) {
+			fPropertyListener = new PropertyListener();
+		}
+		fTextEditor.addPropertyListener(fPropertyListener);
+	}
+
+	/**
+	 * Method createTextEditor.
+	 * 
+	 * @return StructuredTextEditor
+	 */
+	private StructuredTextEditor createTextEditor() {
+		return new StructuredTextEditor();
+	}
+
+	private void disconnectDesignPage() {
+		if (fDesignViewer != null) {
+			fDesignViewer.setDocument(null);
+		}
+	}
+
+	public void dispose() {
+		Logger.trace("Source Editor", "XMLMultiPageEditorPart::dispose entry"); //$NON-NLS-1$ //$NON-NLS-2$
+
+		disconnectDesignPage();
+
+		if (fActivationListener != null) {
+			fActivationListener.dispose();
+			fActivationListener = null;
+		}
+
+		if ((fTextEditor != null) && (fPropertyListener != null)) {
+			fTextEditor.removePropertyListener(fPropertyListener);
+		}
+		
+		// moved to last when added window ... seems like
+		// we'd be in danger of losing some data, like site,
+		// or something.
+		super.dispose();
+
+		Logger.trace("Source Editor", "StructuredTextMultiPageEditorPart::dispose exit"); //$NON-NLS-1$ //$NON-NLS-2$
+
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.ui.ISaveablePart#doSave(org.eclipse.core.runtime.IProgressMonitor)
+	 */
+	public void doSave(IProgressMonitor monitor) {
+		fTextEditor.doSave(monitor);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.ui.ISaveablePart#doSaveAs()
+	 */
+	public void doSaveAs() {
+		fTextEditor.doSaveAs();
+		/*
+		 * Update the design viewer since the editor input would have changed
+		 * to the new file.
+		 */
+		if (fDesignViewer != null) {
+			fDesignViewer.setDocument(getDocument());
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class)
+	 */
+	public Object getAdapter(Class key) {
+		Object result = null;
+
+		// we extend superclass, not override it, so allow it first
+		// chance to satisfy request.
+		result = super.getAdapter(key);
+
+		if (result == null) {
+			if (key == IDesignViewer.class) {
+				result = fDesignViewer;
+
+			}
+			else if (key.equals(IGotoMarker.class)) {
+				result = new IGotoMarker() {
+					public void gotoMarker(IMarker marker) {
+						XMLMultiPageEditorPart.this.gotoMarker(marker);
+					}
+				};
+			}
+			else {
+				/*
+				 * DMW: I'm bullet-proofing this because its been reported (on
+				 * very early versions) a null pointer sometimes happens here
+				 * on startup, when an editor has been left open when
+				 * workbench shutdown.
+				 */
+				if (fTextEditor != null) {
+					result = fTextEditor.getAdapter(key);
+				}
+			}
+		}
+		return result;
+	}
+
+	private IDocument getDocument() {
+		IDocument document = null;
+		if (fTextEditor != null) {
+			document = fTextEditor.getDocumentProvider().getDocument(fTextEditor.getEditorInput());
+		}
+		return document;
+	}
+
+	private IPreferenceStore getPreferenceStore() {
+		return XMLUIPlugin.getDefault().getPreferenceStore();
+	}
+
+	StructuredTextEditor getTextEditor() {
+		return fTextEditor;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.ui.IWorkbenchPart#getTitle()
+	 */
+	public String getTitle() {
+		String title = null;
+		if (getTextEditor() == null) {
+			if (getEditorInput() != null) {
+				title = getEditorInput().getName();
+			}
+		}
+		else {
+			title = getTextEditor().getTitle();
+		}
+		if (title == null) {
+			title = getPartName();
+		}
+		return title;
+	}
+
+	void gotoMarker(IMarker marker) {
+		setActivePage(fSourcePageIndex);
+		IDE.gotoMarker(fTextEditor, marker);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.ui.IEditorPart#init(org.eclipse.ui.IEditorSite,
+	 * org.eclipse.ui.IEditorInput)
+	 */
+	public void init(IEditorSite site, IEditorInput input) throws PartInitException {
+		try {
+			super.init(site, input);
+			// we want to listen for our own activation
+			fActivationListener = new ActivationListener(site.getWorkbenchWindow().getPartService());
+		}
+		catch (Exception e) {
+			Logger.logException("exception initializing " + getClass().getName(), e); //$NON-NLS-1$
+		}
+		setPartName(input.getName());
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.ui.ISaveablePart#isSaveAsAllowed()
+	 */
+	public boolean isSaveAsAllowed() {
+		return (fTextEditor != null) && fTextEditor.isSaveAsAllowed();
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.ui.ISaveablePart#isSaveOnCloseNeeded()
+	 */
+	public boolean isSaveOnCloseNeeded() {
+		// overriding super class since it does a lowly isDirty!
+		if (fTextEditor != null) {
+			return fTextEditor.isSaveOnCloseNeeded();
+		}
+		return isDirty();
+	}
+	
+	/**
+	 * Prevents the creation of the in-editor toolbar, if called before
+	 * createPageContainer() during editor initialization.
+	 */
+	protected final void noToolbar() {
+		fAllocateToolbar = false;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.ui.part.MultiPageEditorPart#pageChange(int)
+	 */
+	protected void pageChange(int newPageIndex) {
+		super.pageChange(newPageIndex);
+		saveLastActivePageIndex(newPageIndex);
+
+		if (newPageIndex == fDesignPageIndex) {
+			// design page isn't an IEditorPart, therefore we have to send
+			// selection changes ourselves
+			ISelectionProvider selectionProvider = fDesignViewer.getSelectionProvider();
+			if (selectionProvider != null) {
+				SelectionChangedEvent event = new SelectionChangedEvent(selectionProvider, selectionProvider.getSelection());
+				((MultiPageSelectionProvider) getSite().getSelectionProvider()).fireSelectionChanged(event);
+				((MultiPageSelectionProvider) getSite().getSelectionProvider()).firePostSelectionChanged(event);
+			}
+		}
+	}
+
+	private void saveLastActivePageIndex(int newPageIndex) {
+		// save the last active page index to preference manager
+		getPreferenceStore().setValue(IXMLPreferenceNames.LAST_ACTIVE_PAGE, newPageIndex);
+	}
+
+	public void setFocus() {
+		super.setFocus();
+		Control control = fDesignViewer.getControl();
+		control.setFocus();
+		// 271382 - Focus not set properly after activating XML editor
+		control.forceFocus();
+	}
+
+	public void setInitializationData(IConfigurationElement cfig, String propertyName, Object data) {
+		super.setInitializationData(cfig, propertyName, data);
+		fPageInitializer = new PageInitializationData(cfig, propertyName, data);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.ui.part.EditorPart#setInput(org.eclipse.ui.IEditorInput)
+	 */
+	protected void setInput(IEditorInput input) {
+		/*
+		 * If driven from the Source page, it's "model" may not be up to date
+		 * with (or even exist for) the input just yet. Later notification
+		 * from the TextViewer could set us straight, although it's not
+		 * guaranteed to happen after the model has been created.
+		 */
+		super.setInput(input);
+		if (fDesignViewer != null) {
+			fDesignViewer.setDocument(getDocument());
+		}
+		setPartName(input.getName());
+	}
+
+	void updateStatusLine(ISelection selection) {
+		IStatusLineManager statusLineManager = getEditorSite().getActionBars().getStatusLineManager();
+		if (fStatusLineLabelProvider != null && statusLineManager != null) {
+			String text = null;
+			Image image = null;
+			if (selection instanceof IStructuredSelection && !selection.isEmpty()) {
+				Object firstElement = ((IStructuredSelection) selection).getFirstElement();
+				if (firstElement != null) {
+					text = fStatusLineLabelProvider.getText(firstElement);
+					image = fStatusLineLabelProvider.getImage((firstElement));
+				}
+			}
+			if (image == null) {
+				statusLineManager.setMessage(text);
+			}
+			else {
+				statusLineManager.setMessage(image, text);
+			}
+		}
+	}
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLTableTreeActionBarContributor.java b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLTableTreeActionBarContributor.java
new file mode 100644
index 0000000..4af5032
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLTableTreeActionBarContributor.java
@@ -0,0 +1,321 @@
+/*******************************************************************************
+ * 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
+ *     David Carver - bug 212330 - migrate to org.eclipse.ui.menus extension point
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.tabletree;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.IContributionManager;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IEditorSite;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchPartSite;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.ui.texteditor.ITextEditorActionConstants;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.ui.StructuredTextEditor;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelqueryimpl.CMDocumentLoader;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelqueryimpl.InferredGrammarBuildingCMDocumentLoader;
+import org.eclipse.wst.xml.core.internal.modelquery.ModelQueryUtil;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
+import org.eclipse.wst.xml.ui.internal.util.SharedXMLEditorPluginImageHelper;
+import org.w3c.dom.Document;
+
+/**
+ * 
+ */
+public class XMLTableTreeActionBarContributor implements IDesignViewerActionBarContributor {
+
+	protected IEditorPart editorPart;
+	protected final static String DESIGN_VIEWER_SEPARATOR_1_ID = "sed.tabletree.separator.1"; //$NON-NLS-1$
+	protected final static String DESIGN_VIEWER_SEPARATOR_2_ID = "sed.tabletree.separator.2"; //$NON-NLS-1$
+	protected final static String VALIDATE_XML_ID = "sed.tabletree.validateXML"; //$NON-NLS-1$
+	protected final static String RELOAD_GRAMMAR_ID = "sed.tabletree.reloadGrammar"; //$NON-NLS-1$
+	protected final static String TOGGLE_EDIT_MODE_ID = "sed.tabletree.toggleEditMode"; //$NON-NLS-1$
+	protected final static String EXPAND_ALL_ID = "sed.tabletree.expandAll"; //$NON-NLS-1$
+	protected final static String COLLAPSE_ALL_ID = "sed.tabletree.collapseAll"; //$NON-NLS-1$
+
+	protected ToggleEditModeAction toggleAction;
+	protected ReloadGrammarAction reloadGrammarAction;
+	// protected ValidateXMLAction validateXMLAction;
+	protected ViewerExpandCollapseAction expandAction;
+	protected ViewerExpandCollapseAction collapseAction;
+	protected ViewerExpandCollapseAction xmlMenuExpandAction;
+	protected ViewerExpandCollapseAction xmlMenuCollapseAction;
+
+	public XMLTableTreeActionBarContributor() {
+	}
+
+	protected void removeContributions(IContributionManager manager) {
+/*		try {
+			doRemove(manager, DESIGN_VIEWER_SEPARATOR_1_ID);
+			doRemove(manager, DESIGN_VIEWER_SEPARATOR_2_ID);
+			doRemove(manager, VALIDATE_XML_ID);
+			doRemove(manager, RELOAD_GRAMMAR_ID);
+			doRemove(manager, TOGGLE_EDIT_MODE_ID);
+			doRemove(manager, EXPAND_ALL_ID);
+			doRemove(manager, COLLAPSE_ALL_ID);
+		}
+		catch (Exception e) {
+		}
+*/		
+	}
+
+	protected void doRemove(IContributionManager manager, String id) {
+/*		try {
+			if (manager.find(id) != null) {
+				manager.remove(id);
+			}
+		}
+		catch (Exception e) {
+		}
+*/	}
+
+	public void init(IActionBars bars, IWorkbenchPage page) {
+		init(bars);
+	}
+
+	public void init(IActionBars bars) {
+//		IToolBarManager tbm = bars.getToolBarManager();
+
+/*		IMenuManager xmlMenu = bars.getMenuManager().findMenuUsingPath("org.eclipse.core.runtime.xml.design.xmlmenu"); //$NON-NLS-1$
+
+		if (xmlMenu == null) {
+			xmlMenu = new MenuManager(XMLEditorMessages.XMLTableTreeActionBarContributor_0, "org.eclipse.core.runtime.xml.design.xmlmenu"); //$NON-NLS-1$
+			// For RCP usage
+			if (bars.getMenuManager().find(IWorkbenchActionConstants.M_WINDOW) != null) {
+				bars.getMenuManager().insertBefore(IWorkbenchActionConstants.M_WINDOW, xmlMenu);
+			}
+		}
+		else {
+			removeContributions(xmlMenu);
+		}
+
+		tbm.add(new Separator("DESIGN_VIEWER_SEPARATOR_1_ID")); //$NON-NLS-1$
+*/
+		// ToggleEditModeAction
+		//           
+/*		toggleAction = new ToggleEditModeAction();
+		toggleAction.setId(TOGGLE_EDIT_MODE_ID);
+		xmlMenu.add(toggleAction);
+		tbm.add(toggleAction);
+*/
+		// ReloadGrammarAction
+		//
+/*		reloadGrammarAction = new ReloadGrammarAction();
+		reloadGrammarAction.setId(RELOAD_GRAMMAR_ID);
+		tbm.add(reloadGrammarAction);
+		xmlMenu.add(reloadGrammarAction);
+
+		xmlMenu.add(new Separator());
+*/
+		// ExpandCollapseAction
+		//
+/*		xmlMenuExpandAction = new ViewerExpandCollapseAction(true);
+		xmlMenuExpandAction.setId(EXPAND_ALL_ID);
+		xmlMenuExpandAction.setText(XMLEditorMessages.XMLTableTreeActionBarContributor_1);
+		xmlMenu.add(xmlMenuExpandAction);
+
+		xmlMenuCollapseAction = new ViewerExpandCollapseAction(false);
+		xmlMenuCollapseAction.setId(COLLAPSE_ALL_ID);
+		xmlMenuCollapseAction.setId(EXPAND_ALL_ID);
+		xmlMenuCollapseAction.setText(XMLEditorMessages.XMLTableTreeActionBarContributor_2);
+		xmlMenu.add(xmlMenuCollapseAction);
+*/		
+	}
+
+	protected void addActionWithId(IMenuManager menuManager, Action action, String id) {
+		action.setId(id);
+		menuManager.add(action);
+	}
+
+	public void initViewerSpecificContributions(IActionBars bars) {
+/*		IToolBarManager tbm = bars.getToolBarManager();
+		tbm.add(new Separator(DESIGN_VIEWER_SEPARATOR_2_ID));
+
+		expandAction = new ViewerExpandCollapseAction(true);
+		expandAction.setId(EXPAND_ALL_ID);
+		tbm.add(expandAction);
+
+		collapseAction = new ViewerExpandCollapseAction(false);
+		collapseAction.setId(COLLAPSE_ALL_ID);
+		tbm.add(collapseAction);
+*/		
+	}
+
+	public void setViewerSpecificContributionsEnabled(boolean enabled) {
+/*		if (expandAction != null) {
+			expandAction.setEnabled(enabled);
+			xmlMenuExpandAction.setEnabled(enabled);
+		}
+
+		if (collapseAction != null) {
+			collapseAction.setEnabled(enabled);
+			xmlMenuCollapseAction.setEnabled(enabled);
+		}
+*/		
+	}
+
+	public void setActiveEditor(IEditorPart targetEditor) {
+		editorPart = targetEditor;
+
+//		IStructuredModel model = getModelForEditorPart(targetEditor);
+/*		reloadGrammarAction.setModel(model);
+		toggleAction.setModelQuery(ModelQueryUtil.getModelQuery(model));
+
+		XMLTableTreeViewer tableTreeViewer = getTableTreeViewerForEditorPart(editorPart);
+		if (tableTreeViewer != null) {
+			expandAction.setViewer(tableTreeViewer);
+			collapseAction.setViewer(tableTreeViewer);
+
+			xmlMenuExpandAction.setViewer(tableTreeViewer);
+			xmlMenuCollapseAction.setViewer(tableTreeViewer);
+		}
+*/
+		if (editorPart instanceof XMLMultiPageEditorPart) {
+			IWorkbenchPartSite site = editorPart.getSite();
+			if (site instanceof IEditorSite) {
+				ITextEditor textEditor = ((XMLMultiPageEditorPart) editorPart).getTextEditor();
+				IActionBars actionBars = ((IEditorSite) site).getActionBars();
+				actionBars.setGlobalActionHandler(ITextEditorActionConstants.UNDO, getAction(textEditor, ITextEditorActionConstants.UNDO));
+				actionBars.setGlobalActionHandler(ITextEditorActionConstants.REDO, getAction(textEditor, ITextEditorActionConstants.REDO));
+			}
+		}
+
+		// TODO... uncomment this and investigate NPE
+		//
+		// add the cut/copy/paste for text fields
+		// ActionHandlerPlugin.connectPart(editorPart);
+	}
+
+	protected final IAction getAction(ITextEditor editor, String actionId) {
+		return (editor == null ? null : editor.getAction(actionId));
+	}
+
+	/**
+	 * @deprecated - not to be used
+	 */
+	protected IStructuredModel getModelForEditorPart(IEditorPart targetEditor) {
+		IStructuredModel result = null;
+		if (editorPart instanceof XMLMultiPageEditorPart) {
+			StructuredTextEditor textEditor = ((XMLMultiPageEditorPart) targetEditor).getTextEditor();
+			result = (textEditor != null) ? textEditor.getModel() : null;
+		}
+		return result;
+	}
+
+	/**
+	 * @deprecated - not to be used
+	 */
+	protected XMLTableTreeViewer getTableTreeViewerForEditorPart(IEditorPart targetEditor) {
+		XMLTableTreeViewer result = null;
+		Object object = targetEditor.getAdapter(IDesignViewer.class);
+		if (object instanceof XMLTableTreeViewer) {
+			result = (XMLTableTreeViewer) object;
+		}
+		return result;
+	}
+
+	/**
+	 * 
+	 */
+	public class ToggleEditModeAction extends Action {
+		protected ImageDescriptor onImage = SharedXMLEditorPluginImageHelper.getImageDescriptor(SharedXMLEditorPluginImageHelper.IMG_ETOOL_CONSTRAINON);
+		protected ImageDescriptor offImage = SharedXMLEditorPluginImageHelper.getImageDescriptor(SharedXMLEditorPluginImageHelper.IMG_ETOOL_CONSTRAINOFF);
+		protected ModelQuery modelQuery;
+
+		public ToggleEditModeAction() {
+			setAppearanceForEditMode(ModelQuery.EDIT_MODE_CONSTRAINED_STRICT);
+		}
+
+		public void run() {
+			if (modelQuery != null) {
+				int newState = getNextState(modelQuery.getEditMode());
+				modelQuery.setEditMode(newState);
+				setAppearanceForEditMode(newState);
+			}
+		}
+
+		public void setModelQuery(ModelQuery newModelQuery) {
+			modelQuery = newModelQuery;
+			if (modelQuery != null) {
+				setAppearanceForEditMode(modelQuery.getEditMode());
+			}
+		}
+
+		public void setAppearanceForEditMode(int editMode) {
+			if (editMode == ModelQuery.EDIT_MODE_CONSTRAINED_STRICT) {
+				setToolTipText(XMLEditorMessages.XMLTableTreeActionBarContributor_3);
+				setText(XMLEditorMessages.XMLTableTreeActionBarContributor_4);
+				setImageDescriptor(onImage);
+			}
+			else {
+				setToolTipText(XMLEditorMessages.XMLTableTreeActionBarContributor_5);
+				setText(XMLEditorMessages.XMLTableTreeActionBarContributor_6);
+				setImageDescriptor(offImage);
+			}
+		}
+
+		public int getNextState(int editMode) {
+			int result = -1;
+			if (editMode == ModelQuery.EDIT_MODE_CONSTRAINED_STRICT) {
+				result = ModelQuery.EDIT_MODE_UNCONSTRAINED;
+			}
+			else {
+				result = ModelQuery.EDIT_MODE_CONSTRAINED_STRICT;
+			}
+			return result;
+		}
+	}
+
+	/**
+	 * 
+	 */
+	public class ReloadGrammarAction extends Action {
+		protected IStructuredModel model;
+
+		public ReloadGrammarAction() {
+			setDisabledImageDescriptor(SharedXMLEditorPluginImageHelper.getImageDescriptor(SharedXMLEditorPluginImageHelper.IMG_DTOOL_RLDGRMR));
+			setImageDescriptor(SharedXMLEditorPluginImageHelper.getImageDescriptor(SharedXMLEditorPluginImageHelper.IMG_ETOOL_RLDGRMR));
+			setToolTipText(XMLEditorMessages.XMLTableTreeActionBarContributor_7);
+			setText(XMLEditorMessages.XMLTableTreeActionBarContributor_8);
+		}
+
+		public void setModel(IStructuredModel newModel) {
+			this.model = newModel;
+		}
+
+		public void run() {
+			if (model != null) {
+				ModelQuery modelQuery = ModelQueryUtil.getModelQuery(model);
+				Document document = ((IDOMModel) model).getDocument();
+				if ((modelQuery != null) && (modelQuery.getCMDocumentManager() != null)) {
+					modelQuery.getCMDocumentManager().getCMDocumentCache().clear();
+					// TODO... need to figure out how to access the
+					// DOMObserver via ModelQuery
+					// ...why?
+					CMDocumentLoader loader = new InferredGrammarBuildingCMDocumentLoader(document, modelQuery);
+					loader.loadCMDocuments();
+				}
+			}
+		}
+	}
+
+	/**
+	 * @see org.eclipse.ui.IEditorActionBarContributor#dispose()
+	 */
+	public void dispose() {
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLTableTreeContentProvider.java b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLTableTreeContentProvider.java
new file mode 100644
index 0000000..95125b6
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLTableTreeContentProvider.java
@@ -0,0 +1,381 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+
+package org.eclipse.wst.xml.ui.internal.tabletree;
+
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.jface.viewers.ITableColorProvider;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.StructuredViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.sse.ui.internal.contentoutline.IJFaceNodeAdapter;
+import org.eclipse.wst.sse.ui.internal.contentoutline.IJFaceNodeAdapterFactory;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.CMDocumentManager;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.CMDocumentManagerListener;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.CMDescriptionBuilder;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.CMDocumentCache;
+import org.eclipse.wst.xml.core.internal.modelquery.ModelQueryUtil;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.eclipse.wst.xml.ui.internal.Logger;
+import org.eclipse.wst.xml.ui.internal.util.SharedXMLEditorPluginImageHelper;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.ProcessingInstruction;
+import org.w3c.dom.Text;
+
+
+public class XMLTableTreeContentProvider implements ITreeContentProvider, ITableLabelProvider, ITableColorProvider, ILabelProvider, CMDocumentManagerListener {
+
+	protected CMDocumentManager documentManager;
+
+	StructuredViewer fViewer = null;
+
+	private TreeContentHelper treeContentHelper = new TreeContentHelper();
+
+	private CMDescriptionBuilder descriptionBuilder = new CMDescriptionBuilder();
+
+	private Color fCMColor = null;
+
+	public XMLTableTreeContentProvider() {
+		super();
+	}
+
+	//
+	// ILabelProvider stuff
+	//
+	public void addListener(ILabelProviderListener listener) {
+		// since we always return 'false' for "isLabelProperty",
+		// not need to listen. Maybe that should change some day?
+	}
+
+	// CMDocumentManagerListener
+	//
+	public void cacheCleared(CMDocumentCache cache) {
+		doDelayedRefreshForViewers();
+	}
+
+	public void cacheUpdated(CMDocumentCache cache, final String uri, int oldStatus, int newStatus, CMDocument cmDocument) {
+		if ((newStatus == CMDocumentCache.STATUS_LOADED) || (newStatus == CMDocumentCache.STATUS_ERROR)) {
+			doDelayedRefreshForViewers();
+		}
+	}
+
+	public void dispose() {
+		if (documentManager != null) {
+			documentManager.removeListener(this);
+		}
+		if (fViewer != null && fViewer.getInput() != null) {
+			if (fViewer.getInput() instanceof IDOMNode) {
+				IJFaceNodeAdapterFactory factory = (IJFaceNodeAdapterFactory) ((IDOMNode) fViewer.getInput()).getModel().getFactoryRegistry().getFactoryFor(IJFaceNodeAdapter.class);
+				if (factory != null) {
+					factory.removeListener(fViewer);
+				}
+			}
+		}
+		if (fCMColor != null) {
+			fCMColor.dispose();
+		}
+	}
+
+	private void doDelayedRefreshForViewers() {
+		if ((fViewer != null) && !fViewer.getControl().isDisposed()) {
+			fViewer.getControl().getDisplay().asyncExec(new Runnable() {
+				public void run() {
+					if ((fViewer != null) && !fViewer.getControl().isDisposed()) {
+						fViewer.refresh(true);
+					}
+				}
+			});
+		}
+	}
+
+	public Object[] getChildren(Object element) {
+		if (element instanceof INodeNotifier) {
+			((INodeNotifier) element).getAdapterFor(IJFaceNodeAdapter.class);
+		}
+		return treeContentHelper.getChildren(element);
+	}
+
+	public Image getColumnImage(Object object, int columnIndex) {
+		return (columnIndex == 0) ? getImage(object) : null;
+	}
+
+	//
+	// ITableLabelProvider stuff
+	//
+	public String getColumnText(Object object, int column) {
+		String result = null;
+		if (column == 0) {
+			result = getText(object);
+		}
+		else if ((column == 1) && (object instanceof Node)) {
+			result = treeContentHelper.getNodeValue((Node) object);
+			if (result == null)
+				result = getElementValueHelper((Element) object);
+				
+		}
+		return result != null ? result : ""; //$NON-NLS-1$
+	}
+	
+	private String getElementValueHelper(Element element) {
+		String result = null;
+
+		ModelQuery mq = ModelQueryUtil.getModelQuery(element.getOwnerDocument());
+		if ((result == null) && (mq != null)) {
+			CMElementDeclaration ed = mq.getCMElementDeclaration(element);
+			if ((ed != null) && !Boolean.TRUE.equals(ed.getProperty("isInferred"))) { //$NON-NLS-1$
+				result = descriptionBuilder.buildDescription(ed);
+			}
+		}
+		return result != null ? result : ""; //$NON-NLS-1$
+	}
+
+	public Object[] getElements(Object element) {
+		return getChildren(element);
+	}
+
+	public Image getImage(Object object) {
+		if (object instanceof INodeNotifier) {
+			((INodeNotifier) object).getAdapterFor(IJFaceNodeAdapter.class);
+		}
+
+		Image image = null;
+		if (object instanceof Node) {
+			Node node = (Node) object;
+			switch (node.getNodeType()) {
+				case Node.ATTRIBUTE_NODE : {
+					image = SharedXMLEditorPluginImageHelper.getImage(SharedXMLEditorPluginImageHelper.IMG_OBJ_ATTRIBUTE);
+					break;
+				}
+				case Node.CDATA_SECTION_NODE : {
+					image = SharedXMLEditorPluginImageHelper.getImage(SharedXMLEditorPluginImageHelper.IMG_OBJ_CDATASECTION);
+					break;
+				}
+				case Node.COMMENT_NODE : {
+					image = SharedXMLEditorPluginImageHelper.getImage(SharedXMLEditorPluginImageHelper.IMG_OBJ_COMMENT);
+					break;
+				}
+				case Node.DOCUMENT_TYPE_NODE : {
+					image = SharedXMLEditorPluginImageHelper.getImage(SharedXMLEditorPluginImageHelper.IMG_OBJ_DOCTYPE);
+					break;
+				}
+				case Node.ELEMENT_NODE : {
+					image = SharedXMLEditorPluginImageHelper.getImage(SharedXMLEditorPluginImageHelper.IMG_OBJ_ELEMENT);
+					break;
+				}
+				case Node.PROCESSING_INSTRUCTION_NODE : {
+					image = SharedXMLEditorPluginImageHelper.getImage(SharedXMLEditorPluginImageHelper.IMG_OBJ_PROCESSINGINSTRUCTION);
+					break;
+				}
+				case Node.TEXT_NODE : {
+					image = SharedXMLEditorPluginImageHelper.getImage(SharedXMLEditorPluginImageHelper.IMG_OBJ_TXTEXT);
+					break;
+				}
+				case Node.ENTITY_REFERENCE_NODE : {
+					image = SharedXMLEditorPluginImageHelper.getImage(SharedXMLEditorPluginImageHelper.IMG_OBJ_ENTITY_REFERENCE);
+					break;
+				}
+			}
+
+			// if (image != null) {
+			// Image markerOverlayImage =
+			// overlayIconManager.getOverlayImageForObject(node);
+			// if (markerOverlayImage != null) {
+			// image = imageFactory.createCompositeImage(image,
+			// markerOverlayImage, ImageFactory.BOTTOM_LEFT);
+			// }
+			// }
+		}
+		return image;
+	}
+
+	public Object getParent(Object o) {
+		if (o instanceof INodeNotifier) {
+			((INodeNotifier) o).getAdapterFor(IJFaceNodeAdapter.class);
+		}
+
+		Object result = null;
+		if (o instanceof Node) {
+			Node node = (Node) o;
+			if (node.getNodeType() == Node.ATTRIBUTE_NODE) {
+				result = ((Attr) node).getOwnerElement();
+			}
+			else {
+				result = node.getParentNode();
+			}
+		}
+		return result;
+	}
+
+	public Element getRootElement(Document document) {
+		Element rootElement = null;
+
+		for (Node childNode = document.getFirstChild(); childNode != null; childNode = childNode.getNextSibling()) {
+			if (childNode.getNodeType() == Node.ELEMENT_NODE) {
+				rootElement = (Element) childNode;
+				break;
+			}
+		}
+		return rootElement;
+	}
+
+	public String getText(Object object) {
+		if (object instanceof INodeNotifier) {
+			((INodeNotifier) object).getAdapterFor(IJFaceNodeAdapter.class);
+		}
+
+		String result = null;
+		if (object instanceof Node) {
+			Node node = (Node) object;
+			switch (node.getNodeType()) {
+				case Node.ATTRIBUTE_NODE : {
+					result = node.getNodeName();
+					break;
+				}
+				case Node.DOCUMENT_TYPE_NODE : {
+					result = "DOCTYPE"; //$NON-NLS-1$
+					break;
+				}
+				case Node.ELEMENT_NODE : {
+					result = node.getNodeName();
+					break;
+				}
+				case Node.PROCESSING_INSTRUCTION_NODE : {
+					result = ((ProcessingInstruction) node).getTarget();
+					break;
+				}
+			}
+		}
+		return result != null ? result : ""; //$NON-NLS-1$
+	}
+
+	public boolean hasChildren(Object element) {
+		return getChildren(element).length > 0;
+	}
+
+	public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+		// remove our listeners to the old state
+		if (oldInput != null) {
+			Document domDoc = (Document) oldInput;
+			ModelQuery mq = ModelQueryUtil.getModelQuery(domDoc);
+			if (mq != null) {
+				documentManager = mq.getCMDocumentManager();
+				if (documentManager != null) {
+					documentManager.removeListener(this);
+				}
+			}
+		}
+
+		if ((oldInput != null) && (oldInput instanceof IDOMNode)) {
+			IJFaceNodeAdapterFactory factory = (IJFaceNodeAdapterFactory) ((IDOMNode) oldInput).getModel().getFactoryRegistry().getFactoryFor(IJFaceNodeAdapter.class);
+			if (factory != null) {
+				factory.removeListener(viewer);
+			}
+		}
+
+		if (viewer instanceof StructuredViewer) {
+			fViewer = null;
+		}
+		else {
+			fViewer = (StructuredViewer) viewer;
+		}
+
+		if ((newInput != null) && (newInput instanceof IDOMNode)) {
+			IJFaceNodeAdapterFactory factory = (IJFaceNodeAdapterFactory) ((IDOMNode) newInput).getModel().getFactoryRegistry().getFactoryFor(IJFaceNodeAdapter.class);
+			if (factory != null) {
+				factory.addListener(viewer);
+			}
+		}
+
+		if (newInput != null) {
+			Document domDoc = (Document) newInput;
+			ModelQuery mq = ModelQueryUtil.getModelQuery(domDoc);
+
+			if (mq != null) {
+				documentManager = mq.getCMDocumentManager();
+				if (documentManager != null) {
+					documentManager.setPropertyEnabled(CMDocumentManager.PROPERTY_ASYNC_LOAD, true);
+					documentManager.addListener(this);
+				}
+			}
+		}
+	}
+
+	public boolean isDeleted(Object element) {
+		return element != null;
+	}
+
+	// the following methods handle filtering aspects of the viewer
+	//
+	//
+	public boolean isIgnorableText(Node node) {
+		boolean result = false;
+		try {
+			if (node.getNodeType() == Node.TEXT_NODE) {
+				String data = ((Text) node).getData();
+				result = ((data == null) || (data.trim().length() == 0));
+			}
+		}
+		catch (Exception e) {
+			Logger.logException(e);
+		}
+		return result;
+	}
+
+	public boolean isLabelProperty(Object object, String property) {
+		return false;
+	}
+
+	public void propertyChanged(CMDocumentManager cmDocumentManager, String propertyName) {
+		if (cmDocumentManager.getPropertyEnabled(CMDocumentManager.PROPERTY_AUTO_LOAD)) {
+			doDelayedRefreshForViewers();
+		}
+	}
+
+	public void removeListener(ILabelProviderListener listener) {
+		// since we always return 'false' for "isLabelProperty",
+		// not need to listen. Maybe that should change some day?
+	}
+
+	public Color getBackground(Object element, int columnIndex) {
+		return null;
+	}
+
+	public Color getForeground(Object element, int columnIndex) {
+		if (columnIndex == 1 && treeContentHelper.getNodeValue((Node) element) == null)
+			return getCMColor();
+		return null;
+	}
+	
+	private Color getCMColor() {
+		if (fCMColor == null) {
+			Color background = Display.getCurrent().getSystemColor(SWT.COLOR_LIST_BACKGROUND);
+			int r = Math.abs(background.getRed() - 125);
+			int g = Math.abs(background.getGreen() - 85);
+			int b = Math.abs(background.getBlue() - 105);
+			fCMColor = new Color(Display.getCurrent(), r, g, b);
+		}
+		return fCMColor;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLTableTreeHelpContextIds.java b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLTableTreeHelpContextIds.java
new file mode 100644
index 0000000..60bc4df
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLTableTreeHelpContextIds.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.tabletree;
+
+import org.eclipse.wst.xml.ui.internal.XMLUIPlugin;
+
+
+
+/**
+ * Help context ids for the TableTree view.
+ * <p>
+ * This interface contains constants only; it is not intended to be
+ * implemented or extended.
+ * </p>
+ * 
+ */
+public interface XMLTableTreeHelpContextIds {
+	// org.eclipse.wst.xml.ui.
+	public static final String PREFIX = XMLUIPlugin.ID + "."; //$NON-NLS-1$
+
+	// XML Design View
+	public static final String XML_DESIGN_VIEW_HELPID = PREFIX + "xmlm3000"; //$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLTableTreePropertyDescriptorFactory.java b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLTableTreePropertyDescriptorFactory.java
new file mode 100644
index 0000000..b929b4c
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLTableTreePropertyDescriptorFactory.java
@@ -0,0 +1,118 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+
+package org.eclipse.wst.xml.ui.internal.tabletree;
+
+import java.util.List;
+
+import org.eclipse.ui.views.properties.IPropertyDescriptor;
+import org.eclipse.ui.views.properties.TextPropertyDescriptor;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.modelquery.ModelQueryUtil;
+import org.eclipse.wst.xml.ui.internal.properties.EnumeratedStringPropertyDescriptor;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.Text;
+
+
+public class XMLTableTreePropertyDescriptorFactory extends DOMPropertyDescriptorFactory {
+
+	protected TreeContentHelper treeContentHelper = new TreeContentHelper();
+
+	public XMLTableTreePropertyDescriptorFactory() {
+		super();
+	}
+
+	protected IPropertyDescriptor createPropertyDescriptorHelper(String name, Element element, CMNode cmNode) {
+		IPropertyDescriptor result = null;
+
+		ModelQuery mq = ModelQueryUtil.getModelQuery(element.getOwnerDocument());
+		String[] valuesArray = null;
+		if (mq != null) {
+			valuesArray = mq.getPossibleDataTypeValues(element, cmNode);
+		}
+		if ((valuesArray != null) && (valuesArray.length > 0)) {
+			result = new EnumeratedStringPropertyDescriptor(name, name, valuesArray);
+		}
+		else {
+			result = createDefaultPropertyDescriptor(name);
+		}
+
+		return result;
+	}
+
+	public IPropertyDescriptor createTextPropertyDescriptor(Text text) {
+		IPropertyDescriptor result = null;
+		Node parentNode = text.getParentNode();
+		if ((parentNode != null) && (parentNode.getNodeType() == Node.ELEMENT_NODE)) {
+			Element parentElement = (Element) parentNode;
+			ModelQuery mq = ModelQueryUtil.getModelQuery(text.getOwnerDocument());
+			CMElementDeclaration ed = null;
+			if (mq != null) {
+				ed = mq.getCMElementDeclaration(parentElement);
+			}
+			if (ed != null) {
+				result = createPropertyDescriptorHelper(HACK, parentElement, ed);
+			}
+			else {
+				result = createDefaultPropertyDescriptor(parentElement.getNodeName());
+			}
+		}
+
+		if (result == null) {
+			result = new TextPropertyDescriptor(HACK, HACK);
+		}
+
+		return result;
+	}
+
+	public IPropertyDescriptor createAttributePropertyDescriptor(Attr attr) {
+		IPropertyDescriptor result = null;
+
+		String attributeName = attr.getName();
+		ModelQuery mq = ModelQueryUtil.getModelQuery(attr.getOwnerDocument());
+
+		CMAttributeDeclaration ad = null;
+		if (mq != null) {
+			ad = mq.getCMAttributeDeclaration(attr);
+		}
+		if (ad != null) {
+			result = createPropertyDescriptorHelper(attributeName, attr.getOwnerElement(), ad);
+		}
+
+		if (result == null) {
+			result = new TextPropertyDescriptor(attributeName, attributeName);
+		}
+
+		return result;
+	}
+
+	public IPropertyDescriptor createElementPropertyDescriptor(Element element) {
+		IPropertyDescriptor result = null;
+		List list = treeContentHelper.getElementTextContent(element);
+		if (list != null) {
+			Text text = treeContentHelper.getEffectiveTextNodeForCombinedNodeList(list);
+			if (text != null) {
+				result = createTextPropertyDescriptor(text);
+			}
+		}
+
+		if (result == null) {
+			result = new TextPropertyDescriptor(HACK, HACK);
+		}
+		return result;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLTableTreeViewer.java b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLTableTreeViewer.java
new file mode 100644
index 0000000..4a994d7
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLTableTreeViewer.java
@@ -0,0 +1,428 @@
+/*****************************************************************************
+ * 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
+ ****************************************************************************/
+package org.eclipse.wst.xml.ui.internal.tabletree;
+
+import java.util.Iterator;
+
+import org.eclipse.jface.action.IMenuListener;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.action.Separator;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.util.LocalSelectionTransfer;
+import org.eclipse.jface.util.SafeRunnable;
+import org.eclipse.jface.viewers.CellEditor;
+import org.eclipse.jface.viewers.ICellModifier;
+import org.eclipse.jface.viewers.IPostSelectionProvider;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.TextCellEditor;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.dnd.DND;
+import org.eclipse.swt.dnd.DragSource;
+import org.eclipse.swt.dnd.DragSourceEvent;
+import org.eclipse.swt.dnd.DragSourceListener;
+import org.eclipse.swt.dnd.DropTarget;
+import org.eclipse.swt.dnd.DropTargetEvent;
+import org.eclipse.swt.dnd.DropTargetListener;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.swt.events.ControlAdapter;
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Item;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.swt.widgets.TreeColumn;
+import org.eclipse.swt.widgets.TreeItem;
+import org.eclipse.ui.views.properties.IPropertyDescriptor;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
+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 org.eclipse.wst.xml.ui.internal.actions.NodeAction;
+import org.eclipse.wst.xml.ui.internal.contentoutline.XMLNodeActionManager;
+import org.eclipse.wst.xml.ui.internal.dnd.DragNodeCommand;
+import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+public class XMLTableTreeViewer extends TreeViewer implements IDesignViewer {
+
+	class NodeActionMenuListener implements IMenuListener {
+		public void menuAboutToShow(IMenuManager menuManager) {
+			// used to disable NodeSelection listening while running
+			// NodeAction
+			XMLNodeActionManager nodeActionManager = new XMLNodeActionManager(((IDOMDocument) getInput()).getModel(), XMLTableTreeViewer.this) {
+				public void beginNodeAction(NodeAction action) {
+					super.beginNodeAction(action);
+				}
+
+				public void endNodeAction(NodeAction action) {
+					super.endNodeAction(action);
+				}
+			};
+			nodeActionManager.fillContextMenu(menuManager, getSelection());
+		}
+	}
+	
+	private class SelectionProvider implements IPostSelectionProvider {
+
+		public void addPostSelectionChangedListener(ISelectionChangedListener listener) {
+			XMLTableTreeViewer.this.addPostSelectionChangedListener(listener);
+		}
+
+		public void removePostSelectionChangedListener(ISelectionChangedListener listener) {
+			XMLTableTreeViewer.this.removePostSelectionChangedListener(listener);
+		}
+
+		public void addSelectionChangedListener(ISelectionChangedListener listener) {
+			XMLTableTreeViewer.this.addSelectionChangedListener(listener);
+		}
+
+		public ISelection getSelection() {
+			return XMLTableTreeViewer.this.getSelection();
+		}
+
+		public void removeSelectionChangedListener(ISelectionChangedListener listener) {
+			XMLTableTreeViewer.this.removeSelectionChangedListener(listener);
+		}
+
+		public void setSelection(ISelection selection) {
+			boolean selectionSet = false;
+			if (!selection.isEmpty() && selection instanceof IStructuredSelection) {
+				IStructuredSelection structuredSelection = (IStructuredSelection) selection;
+				if (selection instanceof ITextSelection) {
+					ITextSelection textSelection = (ITextSelection) selection;
+					
+					if (structuredSelection.size() == 1) {
+						if (structuredSelection.getFirstElement() instanceof IDOMNode) {
+							IDOMNode domNode = (IDOMNode) structuredSelection.getFirstElement();
+							IStructuredDocumentRegion startStructuredDocumentRegion = domNode.getStartStructuredDocumentRegion();
+							if (startStructuredDocumentRegion != null) {
+								ITextRegion matchingRegion = startStructuredDocumentRegion.getRegionAtCharacterOffset(textSelection.getOffset());
+								int allowedIterations = 40;
+								while (matchingRegion != null && !matchingRegion.getType().equals(DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) && allowedIterations > 0) {
+									matchingRegion = startStructuredDocumentRegion.getRegionAtCharacterOffset(startStructuredDocumentRegion.getStartOffset(matchingRegion) - 1);
+									allowedIterations--;
+								}
+								if (matchingRegion != null && matchingRegion.getType().equals(DOMRegionContext.XML_TAG_ATTRIBUTE_NAME)) {
+									String attrName = startStructuredDocumentRegion.getText(matchingRegion);
+									NamedNodeMap attributes = domNode.getAttributes();
+									if (attributes != null && attrName.length() > 0) {
+										Node attr = attributes.getNamedItem(attrName);
+										if (attr != null) {
+											selectionSet = true;
+											XMLTableTreeViewer.this.setSelection(new StructuredSelection(attr));
+										}
+									}
+								}
+							}
+						}
+					}
+				}
+			}
+			if (!selectionSet) {
+				XMLTableTreeViewer.this.setSelection(selection);
+			}
+		}
+	}
+
+	private PaintListener fContentPaintListener = new PaintListener() {
+
+		public void paintControl(PaintEvent e) {
+			GC gc = e.gc;
+			if (getTree().getItemCount() == 0) {
+				gc.setForeground(getTree().getDisplay().getSystemColor(SWT.COLOR_LIST_FOREGROUND));
+				gc.setBackground(getTree().getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND));
+				gc.drawString(XMLEditorMessages.XMLTreeExtension_3, 10, 10);
+				gc.drawString(XMLEditorMessages.XMLTreeExtension_4, 10, 10 + gc.getFontMetrics().getHeight());
+			}
+		}
+		
+	};
+
+	private ISelectionProvider fSelectionProvider = new SelectionProvider();
+	// node: 40%, content: 60%
+	static final double[] WEIGHTS = { .4, .6 };
+
+	private ControlAdapter fResizeAdapter = new ControlAdapter() {
+		public void controlResized(ControlEvent e) {
+			sizeColumns(getTree().getSize().x, WEIGHTS);
+		}
+
+		private void sizeColumns(int width, double[] weights) {
+			TreeColumn[] columns = getTree().getColumns();
+			int size = columns.length;
+			for (int i = 0; i < size; i++) {
+				columns[i].setWidth((int)(weights[i] * width));
+			}
+		}
+	};
+
+	public XMLTableTreeViewer(Composite parent) {
+		super(parent, SWT.FULL_SELECTION | SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
+		
+		TreeColumn column = new TreeColumn(this.getTree(), SWT.LEFT);
+		column.setText(XMLEditorMessages.XMLTableTreeViewer_1);
+
+		column = new TreeColumn(this.getTree(), SWT.LEFT);
+		column.setText(XMLEditorMessages.XMLTableTreeViewer_2);
+
+		this.getTree().setHeaderVisible(true);
+		this.getTree().setLinesVisible(true);
+		getTree().addControlListener(fResizeAdapter);
+
+		// set up providers
+		propertyDescriptorFactory = new XMLTableTreePropertyDescriptorFactory();
+
+		XMLTableTreeContentProvider provider = new XMLTableTreeContentProvider();
+		setContentProvider(provider);
+		setLabelProvider(provider);
+
+		setColumnProperties(new String[] {STRUCTURE_PROPERTY, VALUE_PROPERTY});
+		setCellEditors(new CellEditor[] {null, new TextCellEditor(this.getTree())});
+
+		setCellModifier(new XMLCMCellModifier());
+		createContextMenu();
+
+		DragSource dragSource = new DragSource(getControl(), DND.DROP_COPY | DND.DROP_MOVE);
+		dragSource.addDragListener(createDragSourceListener());
+		dragSource.setTransfer(new Transfer[] {LocalSelectionTransfer.getTransfer()});
+		DropTarget dropTarget = new DropTarget(getControl(), DND.DROP_COPY | DND.DROP_MOVE);
+		dropTarget.addDropListener(createDropTargetListener());
+		dropTarget.setTransfer(new Transfer[] {LocalSelectionTransfer.getTransfer()});
+
+		this.getTree().addPaintListener(fContentPaintListener);
+	}
+
+	/**
+	 * This creates a context menu for the viewer and adds a listener as well
+	 * registering the menu for extension.
+	 */
+	protected void createContextMenu() {
+		MenuManager contextMenu = new MenuManager("#PopUp"); //$NON-NLS-1$
+		contextMenu.add(new Separator("additions")); //$NON-NLS-1$
+		contextMenu.setRemoveAllWhenShown(true);
+		contextMenu.addMenuListener(new NodeActionMenuListener());
+		Menu menu = contextMenu.createContextMenu(getControl());
+		getControl().setMenu(menu);
+	}
+
+	private DragSourceListener createDragSourceListener() {
+		return new DragSourceListener() {
+			public void dragFinished(DragSourceEvent event) {
+				LocalSelectionTransfer.getTransfer().setSelection(null);
+			}
+
+			public void dragSetData(DragSourceEvent event) {
+			}
+
+			public void dragStart(DragSourceEvent event) {
+				LocalSelectionTransfer.getTransfer().setSelection(getSelection());
+			}
+		};
+	}
+
+	private DropTargetListener createDropTargetListener() {
+		return new DropTargetListener() {
+			public void dragEnter(DropTargetEvent event) {
+			}
+
+			public void dragLeave(DropTargetEvent event) {
+			}
+
+			public void dragOperationChanged(DropTargetEvent event) {
+			}
+
+			public void drop(DropTargetEvent event) {
+				if (event.operations != DND.DROP_NONE && LocalSelectionTransfer.getTransfer().getSelection() instanceof IStructuredSelection) {
+					dragOver(event);
+					IStructuredSelection selection = (IStructuredSelection) LocalSelectionTransfer.getTransfer().getSelection();
+					if (selection != null && !selection.isEmpty() && event.item != null && event.item.getData() != null) {
+						/*
+						 * the command uses these numbers instead of the
+						 * feedback constants (even though it converts in
+						 * the other direction as well)
+						 */
+						float feedbackFloat = getHeightInItem(event);
+
+						final DragNodeCommand command = new DragNodeCommand(event.item.getData(), feedbackFloat, event.operations, event.detail, selection.toList(), XMLTableTreeViewer.this);
+						if (command != null && command.canExecute()) {
+							SafeRunnable.run(new SafeRunnable() {
+								public void run() throws Exception {
+									command.execute();
+								}
+							});
+						}
+					}
+				}
+			}
+
+			public void dropAccept(DropTargetEvent event) {
+			}
+
+			public void dragOver(DropTargetEvent event) {
+				event.feedback = DND.FEEDBACK_SELECT;
+				float feedbackFloat = getHeightInItem(event);
+				if (feedbackFloat > 0.75) {
+					event.feedback = DND.FEEDBACK_INSERT_AFTER;
+				}
+				else if (feedbackFloat < 0.25) {
+					event.feedback = DND.FEEDBACK_INSERT_BEFORE;
+				}
+				event.feedback |= DND.FEEDBACK_EXPAND | DND.FEEDBACK_SCROLL;
+				if ( getLocalNodeSelection(event) == null){
+					event.detail = DND.DROP_NONE;
+				}
+			}
+
+			private IStructuredSelection getLocalNodeSelection(DropTargetEvent event){
+				IStructuredSelection selection = (IStructuredSelection) LocalSelectionTransfer.getTransfer().getSelection();
+				if (selection != null && !selection.isEmpty() ) {
+					for (Iterator i = selection.iterator(); i.hasNext();) {
+						Object node = i.next();
+						if (node instanceof Node){
+							return selection;
+						}
+					}
+				}
+				return null;
+			}
+			private float getHeightInItem(DropTargetEvent event) {
+				if(event.item == null) return .5f;
+				if (event.item instanceof TreeItem) {
+					TreeItem treeItem = (TreeItem) event.item;
+					Control control = treeItem.getParent();
+					Point point = control.toControl(new Point(event.x, event.y));
+					Rectangle bounds = treeItem.getBounds();
+					return (float) (point.y - bounds.y) / (float) bounds.height;
+				}
+				else if (event.item instanceof TableItem) {
+					TableItem tableItem = (TableItem) event.item;
+					Control control = tableItem.getParent();
+					Point point = control.toControl(new Point(event.x, event.y));
+					Rectangle bounds = tableItem.getBounds(0);
+					return (float) (point.y - bounds.y) / (float) bounds.height;
+				}
+				else {
+					return 0.0F;
+				}
+			}
+		};
+	}
+	
+	protected void doRefresh(Object o, boolean fromDelayed) {
+		super.refresh(o);
+	}
+
+	public ISelectionProvider getSelectionProvider() {
+		return fSelectionProvider;
+	}
+
+	public String getTitle() {
+		return XMLEditorMessages.XMLTableTreeViewer_0;
+	}
+
+	protected void handleDispose(DisposeEvent event) {
+		super.handleDispose(event);
+		this.getTree().removePaintListener(fContentPaintListener);
+		getTree().removeControlListener(fResizeAdapter);
+		setDocument(null);
+	}
+
+	public void setDocument(IDocument document) {
+		/*
+		 * let the text editor to be the one that manages the model's lifetime
+		 */
+		IStructuredModel model = null;
+		try {
+			model = StructuredModelManager.getModelManager().getExistingModelForRead(document);
+
+			if ((model != null) && (model instanceof IDOMModel)) {
+				Document domDoc = null;
+				domDoc = ((IDOMModel) model).getDocument();
+				setInput(domDoc);
+			}
+		}
+		finally {
+			if (model != null) {
+				model.releaseFromRead();
+			}
+		}
+
+	}
+	
+	protected TreeContentHelper treeContentHelper = new TreeContentHelper();
+	protected XMLTableTreePropertyDescriptorFactory propertyDescriptorFactory;
+	
+	private final static String STRUCTURE_PROPERTY = XMLEditorMessages.XMLTreeExtension_0;
+	private final static String VALUE_PROPERTY = XMLEditorMessages.XMLTreeExtension_1;
+	
+	public class XMLCMCellModifier implements ICellModifier, TreeExtension.ICellEditorProvider {
+		public boolean canModify(Object element, String property) {
+			boolean result = false;
+			if (element instanceof Node) {
+				Node node = (Node) element;
+				if (property == VALUE_PROPERTY) {
+					result = treeContentHelper.isEditable(node);
+					if (result) {
+						/* Set up the cell editor based on the element */
+						CellEditor[] editors = getCellEditors();
+						if (editors.length > 0) {
+							if (editors[1] != null)
+								editors[1].dispose();
+							editors[1] = getCellEditor(element, 1);
+						}
+					}
+					
+				}
+			}
+			return result;
+		}
+
+		public Object getValue(Object object, String property) {
+			String result = null;
+			if (object instanceof Node) {
+				result = treeContentHelper.getNodeValue((Node) object);
+			}
+			return (result != null) ? result : ""; //$NON-NLS-1$
+		}
+
+		public void modify(Object element, String property, Object value) {
+			Item item = (Item) element;
+			String oldValue = treeContentHelper.getNodeValue((Node) item.getData());
+			String newValue = value.toString();
+			if ((newValue != null) && !newValue.equals(oldValue)) {
+				treeContentHelper.setNodeValue((Node) item.getData(), value.toString(), getControl().getShell());
+			}
+		}
+
+		public CellEditor getCellEditor(Object o, int col) {
+			IPropertyDescriptor pd = propertyDescriptorFactory.createPropertyDescriptor(o);
+			return pd != null ? pd.createPropertyEditor(XMLTableTreeViewer.this.getTree()) : null;
+		}
+	}
+
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLTreeExtension.java b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLTreeExtension.java
new file mode 100644
index 0000000..b8601f8
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLTreeExtension.java
@@ -0,0 +1,174 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.tabletree;
+
+import org.eclipse.jface.viewers.CellEditor;
+import org.eclipse.jface.viewers.ICellModifier;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Item;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.swt.widgets.TreeItem;
+import org.eclipse.ui.views.properties.IPropertyDescriptor;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.CMDescriptionBuilder;
+import org.eclipse.wst.xml.core.internal.modelquery.ModelQueryUtil;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+/**
+ * 
+ * @deprecated No longer used
+ */
+public class XMLTreeExtension extends TreeExtension {
+
+	public final static String STRUCTURE_PROPERTY = XMLEditorMessages.XMLTreeExtension_0;
+	public final static String VALUE_PROPERTY = XMLEditorMessages.XMLTreeExtension_1;
+
+	protected Composite control;
+	protected MyCellModifier modifier;
+	protected XMLTableTreePropertyDescriptorFactory propertyDescriptorFactory;
+	protected CMDescriptionBuilder decriptionBuilder = new CMDescriptionBuilder();
+	protected TreeContentHelper treeContentHelper = new TreeContentHelper();
+
+	protected Color f1, f2, b1, b2;
+	protected boolean cachedDataIsValid = true;
+
+	public XMLTreeExtension(Tree tree) {
+		super(tree);
+		control = tree;
+		modifier = new MyCellModifier();
+		setCellModifier(modifier);
+		String[] properties = {STRUCTURE_PROPERTY, VALUE_PROPERTY};
+		setColumnProperties(properties);
+
+		/* https://bugs.eclipse.org/bugs/show_bug.cgi?id=185851 - Used to be hardcoded as COLOR_BLACK */
+		f1 = tree.getDisplay().getSystemColor(SWT.COLOR_LIST_FOREGROUND);
+		Color background = tree.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND);
+
+		int r = Math.abs(background.getRed() - 125);
+		int g = Math.abs(background.getGreen() - 85);
+		int b = Math.abs(background.getBlue() - 105);
+
+		f2 = new Color(tree.getDisplay(), r, g, b);
+		b1 = tree.getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION);
+		b2 = background;
+
+		propertyDescriptorFactory = new XMLTableTreePropertyDescriptorFactory();
+	}
+
+	public void dispose() {
+		super.dispose();
+		f2.dispose();
+	}
+
+	public void resetCachedData() {
+		cachedDataIsValid = false;
+	}
+
+	public void paintItems(GC gc, TreeItem[] items, Rectangle treeBounds) {
+		super.paintItems(gc, items, treeBounds);
+		cachedDataIsValid = true;
+	}
+
+	protected Object[] computeTreeExtensionData(Object object) {
+		Color color = f1;
+		String string = ""; //$NON-NLS-1$
+		if (string.length() == 0) {
+			string = (String) modifier.getValue(object, VALUE_PROPERTY);
+			color = f1;
+		}
+		if ((string.length() == 0) && (object instanceof Element)) {
+			string = getElementValueHelper((Element) object);
+			color = f2;
+		}
+		Object[] data = new Object[2];
+		data[0] = string;
+		data[1] = color;
+		return data;
+	}
+
+	protected void paintItem(GC gc, TreeItem item, Rectangle bounds) {
+		super.paintItem(gc, item, bounds);
+		Object[] data = computeTreeExtensionData(item.getData());
+		if ((data != null) && (data.length == 2)) {
+			gc.setClipping(columnPosition, bounds.y + 1, controlWidth, bounds.height);
+			gc.setForeground((Color) data[1]);
+			gc.drawString((String) data[0], columnPosition + 5, bounds.y + 1);
+			gc.setClipping((Rectangle) null);
+		}
+	}
+
+	protected void addEmptyTreeMessage(GC gc) {
+		// here we print a message when the document is empty just to give the
+		// user a visual cue
+		// so that they know how to proceed to edit the blank view
+		gc.setForeground(fTree.getDisplay().getSystemColor(SWT.COLOR_BLACK));
+		gc.setBackground(fTree.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND));
+		gc.drawString(XMLEditorMessages.XMLTreeExtension_3, 10, 10);
+		gc.drawString(XMLEditorMessages.XMLTreeExtension_4, 10, 10 + gc.getFontMetrics().getHeight());
+	}
+
+	public String getElementValueHelper(Element element) {
+		String result = null;
+
+		ModelQuery mq = ModelQueryUtil.getModelQuery(element.getOwnerDocument());
+		if ((result == null) && (mq != null)) {
+			CMElementDeclaration ed = mq.getCMElementDeclaration(element);
+			if ((ed != null) && !Boolean.TRUE.equals(ed.getProperty("isInferred"))) { //$NON-NLS-1$
+				result = decriptionBuilder.buildDescription(ed);
+			}
+		}
+		return result != null ? result : ""; //$NON-NLS-1$
+	}
+
+	/**
+	 * 
+	 */
+	public class MyCellModifier implements ICellModifier, TreeExtension.ICellEditorProvider {
+		public boolean canModify(Object element, String property) {
+			boolean result = false;
+			if (element instanceof Node) {
+				Node node = (Node) element;
+				result = (property == VALUE_PROPERTY) && treeContentHelper.isEditable(node);
+			}
+			return result;
+		}
+
+		public Object getValue(Object object, String property) {
+			String result = null;
+			if (object instanceof Node) {
+				result = treeContentHelper.getNodeValue((Node) object);
+			}
+			return (result != null) ? result : ""; //$NON-NLS-1$
+		}
+
+		public void modify(Object element, String property, Object value) {
+			// enableNodeSelectionListener(false);
+			Item item = (Item) element;
+			String oldValue = treeContentHelper.getNodeValue((Node) item.getData());
+			String newValue = value.toString();
+			if ((newValue != null) && !newValue.equals(oldValue)) {
+				treeContentHelper.setNodeValue((Node) item.getData(), value.toString());
+			}
+			// enableNodeSelectionListener(true);
+		}
+
+		public CellEditor getCellEditor(Object o, int col) {
+			IPropertyDescriptor pd = propertyDescriptorFactory.createPropertyDescriptor(o);
+			return pd != null ? pd.createPropertyEditor(control) : null;
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src-validation/org/eclipse/wst/xml/ui/internal/validation/XMLValidationUIMessages.java b/bundles/org.eclipse.wst.xml.ui/src-validation/org/eclipse/wst/xml/ui/internal/validation/XMLValidationUIMessages.java
new file mode 100644
index 0000000..ff3bea2
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-validation/org/eclipse/wst/xml/ui/internal/validation/XMLValidationUIMessages.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.validation;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Strings used by XML Validation
+ */
+public class XMLValidationUIMessages extends NLS {
+	private static final String BUNDLE_NAME = "org.eclipse.wst.xml.ui.internal.validation.xmlvalidation"; //$NON-NLS-1$
+
+	private XMLValidationUIMessages() {
+		// cannot create new instance
+	}
+
+	static {
+		// initialize resource bundle
+		NLS.initializeMessages(BUNDLE_NAME, XMLValidationUIMessages.class);
+	}
+	public static String _UI_REF_FILE_ERROR_DESCRIPTION;
+	public static String _UI_REF_FILE_ERROR_MESSAGE;
+	public static String _UI_REF_FILE_ERROR_DETAILS;
+	public static String _UI_DETAILS_INFORMATION_UNAVAILABLE;
+	public static String _UI_DETAILS_INFO_REVALIDATE_TO_REGENERATE;
+	public static String _UI_SAVE_DIRTY_FILE_MESSAGE;
+	public static String _UI_SAVE_DIRTY_FILE_TITLE;
+	public static String TaskListTableViewer_0;
+	public static String TaskListTableViewer_1;
+	public static String TaskListTableViewer_2;
+	public static String TaskListTableViewer_3;
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src-validation/org/eclipse/wst/xml/ui/internal/validation/core/errorinfo/GroupNamePropertyTester.java b/bundles/org.eclipse.wst.xml.ui/src-validation/org/eclipse/wst/xml/ui/internal/validation/core/errorinfo/GroupNamePropertyTester.java
new file mode 100644
index 0000000..7c3e9bc
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-validation/org/eclipse/wst/xml/ui/internal/validation/core/errorinfo/GroupNamePropertyTester.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.xml.ui.internal.validation.core.errorinfo;
+
+
+import org.eclipse.core.expressions.PropertyTester;
+import org.eclipse.core.resources.IMarker;
+
+
+/**
+ * Custom property tester used to determine if the groupName attribute is
+ * present on a marker and that its value starts with a given expected value.
+ */
+public class GroupNamePropertyTester extends PropertyTester
+{
+  /**
+   * The group name prefix property name.
+   */
+  private static final String GROUP_NAME_PREFIX = "groupNamePrefix"; //$NON-NLS-1$  
+
+  /**
+   * The group name marker attribute.
+   */
+  private static final String GROUP_NAME = "groupName"; //$NON-NLS-1$
+
+  public boolean test(Object receiver, String property, Object[] args, Object expectedValue)
+  {
+    if (GROUP_NAME_PREFIX.equals(property))
+    {
+      if (receiver instanceof IMarker)
+      {
+        IMarker marker = (IMarker)receiver;
+
+        String groupName = marker.getAttribute(GROUP_NAME, null);
+
+        boolean testValue = groupName != null && expectedValue instanceof String && groupName.startsWith((String)expectedValue);
+        return testValue;
+      }
+    }
+
+    return false;
+  }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src-validation/org/eclipse/wst/xml/ui/internal/validation/core/errorinfo/ReferencedFileErrorDialog.java b/bundles/org.eclipse.wst.xml.ui/src-validation/org/eclipse/wst/xml/ui/internal/validation/core/errorinfo/ReferencedFileErrorDialog.java
new file mode 100644
index 0000000..4cc9f29
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-validation/org/eclipse/wst/xml/ui/internal/validation/core/errorinfo/ReferencedFileErrorDialog.java
@@ -0,0 +1,254 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.validation.core.errorinfo;
+
+import java.util.List;
+import com.ibm.icu.util.StringTokenizer;
+
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StyleRange;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseMoveListener;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.wst.xml.core.internal.validation.core.ValidationMessage;
+import org.eclipse.wst.xml.ui.internal.validation.XMLValidationUIMessages;
+
+
+public class ReferencedFileErrorDialog extends Dialog {
+	protected TaskListTableViewer tableViewer;
+	protected List errorList;
+	protected String markedUpDetailsMessage;
+	protected String contextFile;
+	protected String referencedFile;
+	protected StyledText styledText;
+	protected Text fullFileNameField;
+
+	public ReferencedFileErrorDialog(Shell parentShell, List errorList, String contextFile, String referencedFile) {
+		super(parentShell);
+
+		int styleBits = getShellStyle() | SWT.RESIZE;
+		styleBits &= ~SWT.APPLICATION_MODAL;
+
+		setShellStyle(styleBits);
+		this.errorList = errorList;
+
+		this.referencedFile = referencedFile;
+		this.contextFile = contextFile;
+		this.markedUpDetailsMessage = getMarkedUpDetailsMessage();
+	}
+
+	public int createAndOpen() {
+		create();
+		getShell().setText(XMLValidationUIMessages._UI_REF_FILE_ERROR_DETAILS);
+
+		setBlockOnOpen(false);
+		return open();
+	}
+
+
+	protected Control createButtonBar(Composite parent) {
+		Composite composite = new Composite(parent, SWT.NONE);
+		composite.setLayout(new GridLayout(2, false));
+		composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+		fullFileNameField = new Text(composite, SWT.NONE);
+		fullFileNameField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+		fullFileNameField.setBackground(parent.getBackground());
+		fullFileNameField.setEditable(false);
+
+		super.createButtonBar(composite);
+
+		return composite;
+	}
+
+	protected Control createDialogArea(Composite parent) {
+		Composite dialogArea = (Composite) super.createDialogArea(parent);
+		dialogArea.setLayout(new GridLayout());
+
+		Composite c = new Composite(dialogArea, SWT.NONE);
+		c.setLayout(new GridLayout());
+		c.setLayoutData(createGridData(true, -1, 200));
+
+		styledText = new StyledText(c, SWT.MULTI | SWT.WRAP);
+		styledText.setBackground(c.getBackground());
+		setStyledText(styledText, markedUpDetailsMessage);
+		styledText.setEditable(false);
+		styledText.setLayoutData(createGridData(false, 650, -1));
+
+		MouseListener mouseListener = new MouseListener();
+		styledText.addMouseMoveListener(mouseListener);
+
+		tableViewer = new TaskListTableViewer(c, 10);
+		tableViewer.setInput(errorList);
+		tableViewer.addSelectionChangedListener(new InternalSelectionListener());
+		tableViewer.getControl().setLayoutData(createGridData(true, 700, -1));
+		return dialogArea;
+	}
+
+	String getFullURI(int offset) {
+		String uri = ""; //$NON-NLS-1$
+		int index = getIndex(offset);
+		if (index != -1) {
+			if ((index == 0) || (index == 2) || (index == 3)) {
+				uri = referencedFile;
+			}
+			else {
+				uri = contextFile;
+			}
+		}
+		return uri;
+	}
+
+	private int getIndex(int offset) {
+		int result = -1;
+		StyleRange[] range = styledText.getStyleRanges();
+		for (int i = 0; i < range.length; i++) {
+			int l = range[i].start;
+			int r = l + range[i].length;
+			if ((l <= offset) && (r >= offset)) {
+				result = i;
+				break;
+			}
+		}
+		return result;
+	}
+
+	class MouseListener implements MouseMoveListener {
+		public void mouseMove(MouseEvent event) {
+			String toolTipText = ""; //$NON-NLS-1$
+			try {
+
+				int offset = styledText.getOffsetAtLocation(new Point(event.x, event.y));
+				toolTipText = getFullURI(offset);
+
+			}
+			catch (Exception e) {
+				// Do nothing.
+			}
+			styledText.setToolTipText(toolTipText);
+			if ((toolTipText != null) && (toolTipText.length() > 0)) {
+				fullFileNameField.setText(toolTipText);
+			}
+		}
+	}
+
+	private String getMarkedUpDetailsMessage() {
+		String detailsMessage = ""; //$NON-NLS-1$
+		// TODO... need to move '_UI_REF_FILE_ERROR_DESCRIPTION' to this
+		// plugin's properties file
+		//			
+		String string = XMLValidationUIMessages._UI_REF_FILE_ERROR_DESCRIPTION;
+		// TODO... need to edit the properties file to remove "'" characters
+		// from the string
+		// I'm using these characters to markup the bold font. It's safer if I
+		// add these programtically.
+		//
+		string = removePattern(string, "'"); //$NON-NLS-1$
+
+		String c = "'" + getLastSegment(contextFile) + "'"; //$NON-NLS-1$ //$NON-NLS-2$
+		String r = "'" + getLastSegment(referencedFile) + "'"; //$NON-NLS-1$ //$NON-NLS-2$
+
+		detailsMessage = NLS.bind(string, new Object[]{r, c, r, c});
+		return detailsMessage;
+	}
+
+	private String removePattern(String string, String pattern) {
+		while (true) {
+			int index = string.indexOf(pattern);
+			if (index != -1) {
+				string = string.substring(0, index) + string.substring(index + pattern.length());
+			}
+			else {
+				break;
+			}
+		}
+		return string;
+	}
+
+	private void setStyledText(StyledText styledText, String text) {
+		String visibleMessage = ""; //$NON-NLS-1$
+		for (StringTokenizer st = new StringTokenizer(markedUpDetailsMessage, "'", false); st.hasMoreTokens();) //$NON-NLS-1$
+		{
+			String token = st.nextToken();
+			visibleMessage += token;
+		}
+
+		styledText.setText(visibleMessage);
+		// dw Font font = styledText.getFont();
+
+		boolean inQuote = false;
+		int position = 0;
+		for (StringTokenizer st = new StringTokenizer(markedUpDetailsMessage, "'", true); st.hasMoreTokens();) //$NON-NLS-1$
+		{
+			String token = st.nextToken();
+
+			if (token.equals("'")) //$NON-NLS-1$
+			{
+				inQuote = !inQuote;
+			}
+			else {
+				if (inQuote) {
+					try {
+
+						StyleRange style = new StyleRange(position, token.length(), styledText.getForeground(), styledText.getBackground(), SWT.BOLD);
+						styledText.setStyleRange(style);
+					}
+					catch (Exception e) {
+						e.printStackTrace();
+					}
+				}
+				position = position + token.length();
+			}
+		}
+	}
+
+	private static GridData createGridData(boolean fillBoth, int w, int h) {
+		GridData gd = new GridData(fillBoth ? GridData.FILL_BOTH : GridData.FILL_HORIZONTAL);
+		gd.widthHint = w;
+		gd.heightHint = h;
+		return gd;
+	}
+
+	private static String getLastSegment(String uri) {
+		String result = uri;
+		int index = Math.max(uri.lastIndexOf("/"), uri.lastIndexOf("\\")); //$NON-NLS-1$ //$NON-NLS-2$
+		if (index != -1) {
+			result = uri.substring(index + 1);
+		}
+		return result;
+	}
+
+	protected class InternalSelectionListener implements ISelectionChangedListener {
+		public void selectionChanged(SelectionChangedEvent event) {
+			ISelection selection = event.getSelection();
+			if (selection instanceof StructuredSelection) {
+				ValidationMessage validationMessage = (ValidationMessage) ((StructuredSelection) selection).getFirstElement();
+				if (validationMessage != null) {
+					String uristring = validationMessage.getUri();
+					ReferencedFileErrorUtility.openEditorAndGotoError(uristring, validationMessage.getLineNumber(), validationMessage.getColumnNumber());
+				}
+			}
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src-validation/org/eclipse/wst/xml/ui/internal/validation/core/errorinfo/ReferencedFileErrorUtility.java b/bundles/org.eclipse.wst.xml.ui/src-validation/org/eclipse/wst/xml/ui/internal/validation/core/errorinfo/ReferencedFileErrorUtility.java
new file mode 100644
index 0000000..378ee89
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-validation/org/eclipse/wst/xml/ui/internal/validation/core/errorinfo/ReferencedFileErrorUtility.java
@@ -0,0 +1,118 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.validation.core.errorinfo;
+
+import java.net.URL;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.content.IContentType;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.IEditorDescriptor;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IEditorRegistry;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.editors.text.TextEditor;
+import org.eclipse.ui.part.FileEditorInput;
+import org.eclipse.ui.texteditor.IDocumentProvider;
+import org.eclipse.wst.xml.core.internal.validation.core.logging.LoggerFactory;
+
+
+public class ReferencedFileErrorUtility {
+	public static void openEditorAndGotoError(String uristring, final int line, final int column) {
+		if (uristring != null) {
+			try {
+				URL uri = new URL(uristring);
+				if (uri != null) {
+					if ("file".equals(uri.getProtocol())) //$NON-NLS-1$
+					{
+						String pathString = uri.getPath();
+						IPath path = new Path(pathString);
+						String device = path.getDevice();
+						if ((device != null) && device.startsWith("/")) //$NON-NLS-1$
+						{
+							path = path.setDevice(device.substring(1));
+						}
+						final IFile iFile = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(path);
+						if ((iFile != null) && iFile.exists()) {
+							// Open the editor for this file.
+							final IWorkbench workbench = PlatformUI.getWorkbench();
+							final IWorkbenchWindow workbenchWindow = workbench.getActiveWorkbenchWindow();
+
+							Display.getDefault().asyncExec(new Runnable() {
+								public void run() {
+									try {
+										IContentType contentType = iFile.getContentDescription().getContentType();
+										IEditorRegistry editorRegistry = workbench.getEditorRegistry();
+										String fileName = iFile.getName();
+										IEditorDescriptor descriptor = editorRegistry.getDefaultEditor(fileName, contentType);
+										String editorId;
+										if (descriptor != null) {
+											editorId = descriptor.getId();
+										}
+										else {
+											descriptor = editorRegistry.getDefaultEditor(fileName + ".txt"); //$NON-NLS-1$
+											editorId = descriptor.getId(); 
+										}
+										
+										if (editorId != null)
+										{
+										  FileEditorInput editorInput = new FileEditorInput(iFile);
+										  IWorkbenchPage activePage = workbenchWindow.getActivePage();
+										  activePage.openEditor(editorInput, editorId);
+										}
+									}
+									catch (Exception ex) {
+										LoggerFactory.getLoggerInstance().logError("Exception encountered when attempting to open file: " + iFile + "\n\n", ex); //$NON-NLS-1$ //$NON-NLS-2$
+									}
+								}
+							});
+
+							Runnable runnable = new Runnable() {
+								public void run() {
+									IEditorPart editorPart = workbenchWindow.getActivePage().getActiveEditor();
+									gotoError(editorPart, line, column);
+								}
+							};
+							Display.getCurrent().asyncExec(runnable);
+						}
+					}
+				}
+			}
+			catch (Exception e) {
+				// Do nothing.
+			}
+		}
+	}
+
+	static void gotoError(IEditorPart editorPart, int line, int column) {
+		if (editorPart != null) {
+			TextEditor textEditor = (TextEditor) editorPart.getAdapter(TextEditor.class);
+			if (textEditor != null) {
+				try {
+					IDocumentProvider dp = textEditor.getDocumentProvider();
+					IDocument document = (dp != null) ? dp.getDocument(textEditor.getEditorInput()) : null;
+					textEditor.selectAndReveal(document.getLineOffset(line - 1) + column - 1, 0);
+				}
+				catch (BadLocationException x) {
+					// marker refers to invalid text position -> do nothing
+				}
+			}
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src-validation/org/eclipse/wst/xml/ui/internal/validation/core/errorinfo/ReferencedFileErrorsHandler.java b/bundles/org.eclipse.wst.xml.ui/src-validation/org/eclipse/wst/xml/ui/internal/validation/core/errorinfo/ReferencedFileErrorsHandler.java
new file mode 100644
index 0000000..3db6243
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-validation/org/eclipse/wst/xml/ui/internal/validation/core/errorinfo/ReferencedFileErrorsHandler.java
@@ -0,0 +1,108 @@
+/*******************************************************************************
+ * Copyright (c) 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.xml.ui.internal.validation.core.errorinfo;
+
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.handlers.HandlerUtil;
+import org.eclipse.ui.views.markers.MarkerViewHandler;
+import org.eclipse.wst.xml.core.internal.validation.core.ValidationMessage;
+import org.eclipse.wst.xml.ui.internal.validation.XMLValidationUIMessages;
+
+
+/**
+ * Handler for the referenced file errors command. This class replaces the old
+ * ReferencedFileErrorActionDelegate.
+ */
+public class ReferencedFileErrorsHandler extends MarkerViewHandler
+{
+  public Object execute(ExecutionEvent event) throws ExecutionException
+  {
+    final IMarker[] selectedMarkers = getSelectedMarkers(event);
+
+    IMarker selectedMarker = selectedMarkers[0];
+
+    if (selectedMarker != null)
+    {
+      try
+      {
+
+        IResource resource = selectedMarker.getResource();
+        Map map = (Map)resource.getSessionProperty(ValidationMessage.ERROR_MESSAGE_MAP_QUALIFIED_NAME);
+        if (map == null)
+        {
+          String infoUnavailable = XMLValidationUIMessages._UI_DETAILS_INFORMATION_UNAVAILABLE;
+          String revalidateToRegenerateErrors = XMLValidationUIMessages._UI_DETAILS_INFO_REVALIDATE_TO_REGENERATE;
+          MessageDialog.openInformation(Display.getCurrent().getActiveShell(), infoUnavailable, revalidateToRegenerateErrors);
+        }
+        else
+        {
+          String uri = null;
+
+          String groupName = (String)selectedMarker.getAttribute("groupName"); //$NON-NLS-1$
+          if (groupName.startsWith("referencedFileError")) //$NON-NLS-1$
+          {
+            int index1 = groupName.indexOf("("); //$NON-NLS-1$
+            int index2 = groupName.lastIndexOf(")"); //$NON-NLS-1$
+            if ((index1 != -1) && (index2 > index1))
+            {
+              uri = groupName.substring(index1 + 1, index2);
+            }
+          }
+
+          if (uri != null)
+          {
+            List list = Collections.EMPTY_LIST;
+
+            ValidationMessage message = (ValidationMessage)map.get(uri);
+            if (message != null)
+            {
+              list = message.getNestedMessages();
+            }
+
+            IPath resourceLocation = resource.getLocation();
+            
+            if (resourceLocation != null)
+            {
+              String validatedFileURI = resourceLocation.toOSString();
+              validatedFileURI = "file:/" + validatedFileURI; //$NON-NLS-1$
+
+              ReferencedFileErrorDialog dialog = new ReferencedFileErrorDialog(
+                HandlerUtil.getActiveShell(event),
+                list,
+                validatedFileURI,
+                uri);
+              dialog.createAndOpen();
+            }
+          }
+        }
+      }
+      catch (CoreException e)
+      {
+        // Do nothing.
+      }
+    }
+
+    return this;
+  }
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.xml.ui/src-validation/org/eclipse/wst/xml/ui/internal/validation/core/errorinfo/TaskListTableViewer.java b/bundles/org.eclipse.wst.xml.ui/src-validation/org/eclipse/wst/xml/ui/internal/validation/core/errorinfo/TaskListTableViewer.java
new file mode 100644
index 0000000..433edf7
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-validation/org/eclipse/wst/xml/ui/internal/validation/core/errorinfo/TaskListTableViewer.java
@@ -0,0 +1,159 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.validation.core.errorinfo;
+
+import java.util.List;
+
+import org.eclipse.jface.viewers.ColumnWeightData;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.TableLayout;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.ui.ISharedImages;
+import org.eclipse.wst.validation.internal.provisional.core.IMessage;
+import org.eclipse.wst.xml.core.internal.validation.core.ValidationMessage;
+import org.eclipse.wst.xml.ui.internal.XMLUIPlugin;
+import org.eclipse.wst.xml.ui.internal.validation.XMLValidationUIMessages;
+
+
+
+public class TaskListTableViewer extends TableViewer {
+	protected static final int COLUMN_ICON = 0;
+	protected static final int COLUMN_DESCRIPTION = 1;
+	protected static final int COLUMN_RESOURCE = 3;
+	protected static final int COLUMN_LOCATION = 2;
+
+	protected static final String LABEL_ICON = ""; //$NON-NLS-1$
+	protected static final String LABEL_DESCRIPTION = XMLValidationUIMessages.TaskListTableViewer_0;
+	protected static final String LABEL_RESOURCE = XMLValidationUIMessages.TaskListTableViewer_1;
+	protected static final String LABEL_LOCATION = XMLValidationUIMessages.TaskListTableViewer_2;
+
+	protected int visibleRows = -1;
+
+	protected int getColumnWidth(int column) {
+		int result = 0;
+		switch (column) {
+			case COLUMN_ICON : {
+				result = 1;
+				break;
+			}
+			case COLUMN_DESCRIPTION : {
+				result = 20;
+				break;
+			}
+			case COLUMN_RESOURCE : {
+				result = 3;
+				break;
+			}
+			case COLUMN_LOCATION : {
+				result = 3;
+				break;
+			}
+		}
+		return result;
+	}
+
+	public TaskListTableViewer(Composite parent, int visibleRows) {
+		this(parent, SWT.FULL_SELECTION | SWT.MULTI | SWT.BORDER, visibleRows);
+	}
+
+	public TaskListTableViewer(Composite parent, int style, int visibleRows) {
+		super(new Table(parent, style));
+		getTable().setLinesVisible(true);
+
+		Provider provider = new Provider();
+		setContentProvider(provider);
+		setLabelProvider(provider);
+
+		String[] columnPropertiesArray = {LABEL_ICON, LABEL_DESCRIPTION, LABEL_LOCATION};
+		setColumnProperties(columnPropertiesArray);
+
+		Table table = getTable();
+		table.setHeaderVisible(true);
+		table.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+		TableLayout layout = new TableLayout();
+
+		for (int i = 0; i < columnPropertiesArray.length; i++) {
+			TableColumn column = new TableColumn(table, i);
+			column.setText(columnPropertiesArray[i]);
+			column.setAlignment(SWT.LEFT);
+			layout.addColumnData(new ColumnWeightData(getColumnWidth(i), true));
+		}
+
+		table.setLayout(layout);
+
+		this.visibleRows = visibleRows;
+	}
+
+	/**
+	 * NamespaceInfoTableLabelProvider
+	 */
+	protected class Provider extends LabelProvider implements ITableLabelProvider, IStructuredContentProvider {
+		Viewer viewer;
+		Image errorImage;
+		Image warnImage;
+
+		public Provider() {
+			errorImage = XMLUIPlugin.getInstance().getImage(ISharedImages.IMG_OBJS_ERROR_TSK);
+
+			warnImage = XMLUIPlugin.getInstance().getImage(ISharedImages.IMG_OBJS_WARN_TSK);
+		}
+
+		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+			this.viewer = viewer;
+		}
+
+		public Object[] getElements(Object inputElement) {
+			List list = (List) viewer.getInput();
+			return list != null ? list.toArray() : null;
+		}
+
+		public Image getColumnImage(Object object, int columnIndex) {
+			ValidationMessage validationMessage = (ValidationMessage) object;
+			Image result = null;
+			if (columnIndex == 0) {
+				int severity = validationMessage.getSeverity();
+				if ((severity == IMessage.HIGH_SEVERITY) || (severity == IMessage.NORMAL_SEVERITY)) {
+					result = errorImage;
+				}
+				else {
+					result = warnImage;
+				}
+			}
+			return result;
+		}
+
+		public String getColumnText(Object object, int column) {
+			ValidationMessage errorMessage = (ValidationMessage) object;
+			String result = ""; //$NON-NLS-1$
+			switch (column) {
+				case COLUMN_DESCRIPTION : {
+					result = errorMessage.getMessage();
+					break;
+				}
+				case COLUMN_LOCATION : {
+					result = XMLValidationUIMessages.TaskListTableViewer_3 + errorMessage.getLineNumber();
+					break;
+				}
+			}
+			return result;
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src-validation/org/eclipse/wst/xml/ui/internal/validation/xmlvalidation.properties b/bundles/org.eclipse.wst.xml.ui/src-validation/org/eclipse/wst/xml/ui/internal/validation/xmlvalidation.properties
new file mode 100644
index 0000000..c35c849
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-validation/org/eclipse/wst/xml/ui/internal/validation/xmlvalidation.properties
@@ -0,0 +1,29 @@
+###############################################################################
+# Copyright (c) 2001, 2006 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
+###############################################################################
+### Constants for strings  
+
+#
+# Referenced File Dialog Related Message
+#
+_UI_REF_FILE_ERROR_DESCRIPTION      = The errors below were detected when validating the file "{0}" via the file "{1}".  In most cases these errors can be detected by validating "{2}" directly.  However it is possible that errors will only occur when {2} is validated in the context of {3}.
+_UI_REF_FILE_ERROR_MESSAGE          = Referenced file contains errors ({0}).  For more information, right click on the message and select "Show Details..."
+_UI_REF_FILE_ERROR_DETAILS          = Referenced File Error Details
+
+_UI_DETAILS_INFORMATION_UNAVAILABLE       = Details Information Unavailable
+_UI_DETAILS_INFO_REVALIDATE_TO_REGENERATE = Details information currently unavailable.  Please revalidate the file to regenerate the error details.
+
+#
+# Dirty File Dialog Related Messages
+#
+TaskListTableViewer_0=Description
+TaskListTableViewer_1=Resource
+TaskListTableViewer_2=Location
+TaskListTableViewer_3=line 
diff --git a/bundles/org.eclipse.wst.xml.ui/src-wizards/org/eclipse/wst/xml/ui/internal/wizards/ExampleProjectCreationOperation.java b/bundles/org.eclipse.wst.xml.ui/src-wizards/org/eclipse/wst/xml/ui/internal/wizards/ExampleProjectCreationOperation.java
new file mode 100644
index 0000000..cd809c7
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-wizards/org/eclipse/wst/xml/ui/internal/wizards/ExampleProjectCreationOperation.java
@@ -0,0 +1,206 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.wizards;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.net.URL;
+import java.util.zip.ZipFile;
+
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IProjectDescription;
+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.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.SubProgressMonitor;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.ui.dialogs.IOverwriteQuery;
+import org.eclipse.ui.wizards.datatransfer.ImportOperation;
+import org.eclipse.ui.wizards.datatransfer.ZipFileStructureProvider;
+import org.eclipse.wst.xml.ui.internal.Logger;
+import org.eclipse.wst.xml.ui.internal.XMLUIPlugin;
+import org.osgi.framework.Bundle;
+
+public class ExampleProjectCreationOperation implements IRunnableWithProgress {
+
+	private IResource elementToOpen;
+
+	private IOverwriteQuery overwriteQuery;
+
+	private ExampleProjectCreationWizardPage[] pages;
+
+	/**
+	 * Constructor for ExampleProjectCreationOperation
+	 */
+	public ExampleProjectCreationOperation(ExampleProjectCreationWizardPage[] myPages, IOverwriteQuery myOverwriteQuery) {
+		elementToOpen = null;
+		pages = myPages;
+		overwriteQuery = myOverwriteQuery;
+	}
+
+	private IProject configNewProject(IWorkspaceRoot root, String name, String[] natureIds, IProject[] referencedProjects, IProgressMonitor monitor) throws InvocationTargetException {
+		try {
+			IProject project = root.getProject(name);
+			if (!project.exists()) {
+				project.create(null);
+			}
+			if (!project.isOpen()) {
+				project.open(null);
+			}
+			IProjectDescription desc = project.getDescription();
+			desc.setLocation(null);
+			desc.setNatureIds(natureIds);
+			desc.setReferencedProjects(referencedProjects);
+
+			project.setDescription(desc, new SubProgressMonitor(monitor, 1));
+
+			return project;
+		}
+		catch (CoreException e) {
+			throw new InvocationTargetException(e);
+		}
+	}
+
+	private void createProject(IWorkspaceRoot root, ExampleProjectCreationWizardPage page, IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
+		IConfigurationElement desc = page.getConfigurationElement();
+
+		IConfigurationElement[] imports = desc.getChildren("import"); //$NON-NLS-1$
+		IConfigurationElement[] natures = desc.getChildren("nature"); //$NON-NLS-1$
+		IConfigurationElement[] references = desc.getChildren("references"); //$NON-NLS-1$
+		int nImports = (imports == null) ? 0 : imports.length;
+		int nNatures = (natures == null) ? 0 : natures.length;
+		int nReferences = (references == null) ? 0 : references.length;
+
+		monitor.beginTask(XMLWizardsMessages.ExampleProjectCreationOperation_op_desc_proj, nImports + 1);
+
+		String name = page.getProjectName();
+
+		String[] natureIds = new String[nNatures];
+		for (int i = 0; i < nNatures; i++) {
+			natureIds[i] = natures[i].getAttribute("id"); //$NON-NLS-1$
+		}
+		IProject[] referencedProjects = new IProject[nReferences];
+		for (int i = 0; i < nReferences; i++) {
+			referencedProjects[i] = root.getProject(references[i].getAttribute("id")); //$NON-NLS-1$
+		}
+
+		IProject proj = configNewProject(root, name, natureIds, referencedProjects, monitor);
+
+		for (int i = 0; i < nImports; i++) {
+			doImports(proj, imports[i], new SubProgressMonitor(monitor, 1));
+		}
+
+		String open = desc.getAttribute("open"); //$NON-NLS-1$
+		if ((open != null) && (open.length() > 0)) {
+			IResource fileToOpen = proj.findMember(new Path(open));
+			if (fileToOpen != null) {
+				elementToOpen = fileToOpen;
+			}
+		}
+
+	}
+
+	private void doImports(IProject project, IConfigurationElement curr, IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
+		try {
+			IPath destPath;
+			String name = curr.getAttribute("dest"); //$NON-NLS-1$
+			if ((name == null) || (name.length() == 0)) {
+				destPath = project.getFullPath();
+			}
+			else {
+				IFolder folder = project.getFolder(name);
+				if (!folder.exists()) {
+					folder.create(true, true, null);
+				}
+				destPath = folder.getFullPath();
+			}
+			String importPath = curr.getAttribute("src"); //$NON-NLS-1$
+			if (importPath == null) {
+				importPath = ""; //$NON-NLS-1$
+				Logger.log(Logger.ERROR, "projectsetup descriptor: import missing"); //$NON-NLS-1$
+				return;
+			}
+
+			ZipFile zipFile = getZipFileFromPluginDir(importPath, getContributingPlugin(curr));
+			importFilesFromZip(zipFile, destPath, new SubProgressMonitor(monitor, 1));
+		}
+		catch (CoreException e) {
+			throw new InvocationTargetException(e);
+		}
+	}
+
+	private String getContributingPlugin(IConfigurationElement configurationElement) {
+		Object parent = configurationElement;
+		while (parent != null) {
+			if (parent instanceof IExtension) {
+				return ((IExtension) parent).getNamespace();
+			}
+			parent = ((IConfigurationElement) parent).getParent();
+		}
+		return null;
+	}
+
+	public IResource getElementToOpen() {
+		return elementToOpen;
+	}
+
+	private ZipFile getZipFileFromPluginDir(String pluginRelativePath, String symbolicName) throws CoreException {
+		try {
+			Bundle bundle = Platform.getBundle(symbolicName);
+			URL starterURL = new URL(bundle.getEntry("/"), pluginRelativePath); //$NON-NLS-1$
+			return new ZipFile(Platform.asLocalURL(starterURL).getFile());
+		}
+		catch (IOException e) {
+			String message = pluginRelativePath + ": " + e.getMessage(); //$NON-NLS-1$
+			Status status = new Status(IStatus.ERROR, XMLUIPlugin.ID, IStatus.ERROR, message, e);
+			throw new CoreException(status);
+		}
+	}
+
+	private void importFilesFromZip(ZipFile srcZipFile, IPath destPath, IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
+		ZipFileStructureProvider structureProvider = new ZipFileStructureProvider(srcZipFile);
+		ImportOperation op = new ImportOperation(destPath, structureProvider.getRoot(), structureProvider, overwriteQuery);
+		op.run(monitor);
+	}
+
+	/*
+	 * @see IRunnableWithProgress#run(IProgressMonitor)
+	 */
+	public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
+		if (monitor == null) {
+			monitor = new NullProgressMonitor();
+		}
+		try {
+			monitor.beginTask(XMLWizardsMessages.ExampleProjectCreationOperation_op_desc, pages.length);
+			IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+
+			for (int i = 0; i < pages.length; i++) {
+				createProject(root, pages[i], new SubProgressMonitor(monitor, 1));
+			}
+		}
+		finally {
+			monitor.done();
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src-wizards/org/eclipse/wst/xml/ui/internal/wizards/ExampleProjectCreationWizard.java b/bundles/org.eclipse.wst.xml.ui/src-wizards/org/eclipse/wst/xml/ui/internal/wizards/ExampleProjectCreationWizard.java
new file mode 100644
index 0000000..d968c92
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-wizards/org/eclipse/wst/xml/ui/internal/wizards/ExampleProjectCreationWizard.java
@@ -0,0 +1,232 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.wizards;
+
+import java.lang.reflect.InvocationTargetException;
+import java.net.URL;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExecutableExtension;
+import org.eclipse.core.runtime.IExtension;
+import org.eclipse.core.runtime.IExtensionPoint;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.wizard.Wizard;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.INewWizard;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.actions.WorkspaceModifyDelegatingOperation;
+import org.eclipse.ui.dialogs.IOverwriteQuery;
+import org.eclipse.ui.ide.IDE;
+import org.eclipse.ui.wizards.newresource.BasicNewProjectResourceWizard;
+import org.eclipse.ui.wizards.newresource.BasicNewResourceWizard;
+import org.eclipse.wst.xml.ui.internal.Logger;
+import org.eclipse.wst.xml.ui.internal.XMLUIPlugin;
+
+public class ExampleProjectCreationWizard extends Wizard implements INewWizard, IExecutableExtension {
+
+	private class ImportOverwriteQuery implements IOverwriteQuery {
+
+		private int openDialog(final String file) {
+			final int[] result = {IDialogConstants.CANCEL_ID};
+			getShell().getDisplay().syncExec(new Runnable() {
+				public void run() {
+					String title = XMLWizardsMessages.ExampleProjectCreationWizard_overwritequery_title;
+					String msg = NLS.bind(XMLWizardsMessages.ExampleProjectCreationWizard_overwritequery_message, file);
+					String[] options = {IDialogConstants.YES_LABEL, IDialogConstants.NO_LABEL, IDialogConstants.YES_TO_ALL_LABEL, IDialogConstants.CANCEL_LABEL};
+					MessageDialog dialog = new MessageDialog(getShell(), title, null, msg, MessageDialog.QUESTION, options, 0);
+					result[0] = dialog.open();
+				}
+			});
+			return result[0];
+		}
+
+		public String queryOverwrite(String file) {
+			String[] returnCodes = {YES, NO, ALL, CANCEL};
+			int returnVal = openDialog(file);
+			return returnVal < 0 ? CANCEL : returnCodes[returnVal];
+		}
+	}
+
+	private IConfigurationElement wizardConfigElement;
+	private IConfigurationElement exampleConfigElement;
+
+	private String EXAMPLE_WIZARD_XP_ID = "org.eclipse.wst.common.ui.exampleProjectCreationWizard"; //$NON-NLS-1$
+
+	private ExampleProjectCreationWizardPage[] pages;
+
+	private final String WEB_BROWSER_ID = "org.eclipse.ui.browser.editor"; //$NON-NLS-1$
+
+	public ExampleProjectCreationWizard() {
+		super();
+		setDialogSettings(XMLUIPlugin.getDefault().getDialogSettings());
+		setWindowTitle(XMLWizardsMessages.ExampleProjectCreationWizard_title);
+		setNeedsProgressMonitor(true);
+	}
+
+	/*
+	 * @see Wizard#addPages
+	 */
+	public void addPages() {
+		super.addPages();
+
+		if (exampleConfigElement == null) {
+			return;
+		}
+		IConfigurationElement[] children = exampleConfigElement.getChildren("projectsetup"); //$NON-NLS-1$
+		if ((children == null) || (children.length == 0)) {
+			Logger.log(Logger.ERROR, "descriptor must contain one ore more projectsetup tags"); //$NON-NLS-1$
+			return;
+		}
+
+		pages = new ExampleProjectCreationWizardPage[children.length];
+
+		for (int i = 0; i < children.length; i++) {
+			pages[i] = new ExampleProjectCreationWizardPage(i, children[i]);
+			addPage(pages[i]);
+		}
+	}
+
+	public void init(IWorkbench workbench, IStructuredSelection currentSelection) {
+		if (exampleConfigElement != null) {
+			String banner = exampleConfigElement.getAttribute("banner"); //$NON-NLS-1$
+			if (banner != null) {
+				URL imageURL = Platform.find(Platform.getBundle(exampleConfigElement.getDeclaringExtension().getNamespace()), new Path(banner));
+				ImageDescriptor desc = ImageDescriptor.createFromURL(imageURL);
+				setDefaultPageImageDescriptor(desc);
+			}
+		}
+	}
+
+	protected IConfigurationElement[] getExtendedConfigurationElements() {
+		IExtensionRegistry registry = Platform.getExtensionRegistry();
+		IExtensionPoint exampleWizardXP = registry.getExtensionPoint(EXAMPLE_WIZARD_XP_ID);
+		if (exampleWizardXP == null) {
+			return new IConfigurationElement[0];
+		}
+		IExtension extension = exampleWizardXP.getExtension(getWizardExtensionId());
+		if (extension != null) {
+			return extension.getConfigurationElements();
+		}
+		IConfigurationElement[] exampleWizardCEs = exampleWizardXP.getConfigurationElements();
+		return exampleWizardCEs;
+	}
+
+	private void handleException(Throwable target) {
+		String title = XMLWizardsMessages.ExampleProjectCreationWizard_op_error_title;
+		String message = XMLWizardsMessages.ExampleProjectCreationWizard_op_error_message;
+		if (target instanceof CoreException) {
+			IStatus status = ((CoreException) target).getStatus();
+			ErrorDialog.openError(getShell(), title, message, status);
+			Logger.logException(status.getMessage(), status.getException());
+		}
+		else {
+			MessageDialog.openError(getShell(), title, target.getMessage());
+			Logger.logException(target);
+		}
+	}
+
+	private void openResource(final IResource resource) {
+		if (resource.getType() != IResource.FILE) {
+			return;
+		}
+		IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+		if (window == null) {
+			return;
+		}
+		final IWorkbenchPage activePage = window.getActivePage();
+		if (activePage != null) {
+			final Display display = getShell().getDisplay();
+			display.asyncExec(new Runnable() {
+				public void run() {
+					try {
+						IDE.openEditor(activePage, (IFile) resource, WEB_BROWSER_ID, true);
+					}
+					catch (PartInitException e) {
+						Logger.logException(e);
+					}
+				}
+			});
+			BasicNewResourceWizard.selectAndReveal(resource, activePage.getWorkbenchWindow());
+		}
+	}
+
+	/*
+	 * @see Wizard#performFinish
+	 */
+	public boolean performFinish() {
+		ExampleProjectCreationOperation runnable = new ExampleProjectCreationOperation(pages, new ImportOverwriteQuery());
+
+		IRunnableWithProgress op = new WorkspaceModifyDelegatingOperation(runnable);
+		try {
+			getContainer().run(false, true, op);
+		}
+		catch (InvocationTargetException e) {
+			handleException(e.getTargetException());
+			return false;
+		}
+		catch (InterruptedException e) {
+			return false;
+		}
+		BasicNewProjectResourceWizard.updatePerspective(wizardConfigElement);
+		IResource res = runnable.getElementToOpen();
+		if (res != null) {
+			openResource(res);
+		}
+		return true;
+	}
+
+	/**
+	 * Stores the configuration element for the wizard. The config element
+	 * will be used in <code>performFinish</code> to set the result
+	 * perspective.
+	 */
+	public void setInitializationData(IConfigurationElement cfig, String propertyName, Object data) {
+		wizardConfigElement = cfig;
+		String title = wizardConfigElement.getAttribute("name"); //$NON-NLS-1$
+		if (title != null) {
+			setWindowTitle(title);
+		}
+		String wizardId = getWizardExtensionId();
+		IConfigurationElement[] exampleWizardCEs = getExtendedConfigurationElements();
+		for (int i = 0; i < exampleWizardCEs.length; i++) {
+			IConfigurationElement element = exampleWizardCEs[i];
+			String extWizardId = element.getAttribute("id"); //$NON-NLS-1$
+			if ((wizardId != null) && (extWizardId != null) && wizardId.equals(extWizardId)) {
+				exampleConfigElement = element;
+			}
+		}
+		// initializeDefaultPageImageDescriptor();
+	}
+
+	public String getWizardExtensionId() {
+		return wizardConfigElement.getAttribute("id"); //$NON-NLS-1$
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src-wizards/org/eclipse/wst/xml/ui/internal/wizards/ExampleProjectCreationWizardPage.java b/bundles/org.eclipse.wst.xml.ui/src-wizards/org/eclipse/wst/xml/ui/internal/wizards/ExampleProjectCreationWizardPage.java
new file mode 100644
index 0000000..3f13b33
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-wizards/org/eclipse/wst/xml/ui/internal/wizards/ExampleProjectCreationWizardPage.java
@@ -0,0 +1,111 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+
+package org.eclipse.wst.xml.ui.internal.wizards;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.jface.wizard.IWizard;
+import org.eclipse.jface.wizard.IWizardPage;
+import org.eclipse.ui.dialogs.WizardNewProjectCreationPage;
+
+public class ExampleProjectCreationWizardPage extends WizardNewProjectCreationPage {
+
+	private IConfigurationElement configurationElement;
+
+	public ExampleProjectCreationWizardPage(int pageNumber, IConfigurationElement elem) {
+
+		super("page" + pageNumber); //$NON-NLS-1$
+		configurationElement = elem;
+
+		String name = getAttribute(elem, "name"); //$NON-NLS-1$
+		setInitialProjectName(calculateInitialProjectName(name));
+
+		setDescription(getAttribute(configurationElement, "pagedescription")); //$NON-NLS-1$
+		setTitle(getAttribute(configurationElement, "pagetitle")); //$NON-NLS-1$
+
+	}
+
+	/*
+	 * Set the default project name that is to appear on the initialPage page
+	 * of this wizard.
+	 */
+	protected String calculateInitialProjectName(String projectName) {
+		IProject projectHandle = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);
+		if (!projectHandle.exists()) {
+			return projectName;
+		}
+		// Change the name until it doesn't exists. Try 9 times and then
+		// give up.
+		for (int i = 1; i < 10; i++) {
+			projectHandle = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName + i);
+			if (!projectHandle.exists()) {
+				return projectName + i;
+			}
+		}
+		return projectName + "9"; //$NON-NLS-1$
+
+	}
+
+	private String getAttribute(IConfigurationElement elem, String tag) {
+		String res = elem.getAttribute(tag);
+		if (res == null) {
+			return '!' + tag + '!';
+		}
+		return res;
+	}
+
+
+
+	/**
+	 * Returns the configuration element of this page.
+	 * 
+	 * @return Returns a IConfigurationElement
+	 */
+	public IConfigurationElement getConfigurationElement() {
+		return configurationElement;
+	}
+
+	/**
+	 * @see org.eclipse.ui.dialogs.WizardNewProjectCreationPage#validatePage()
+	 */
+	protected boolean validatePage() {
+		if (!super.validatePage()) {
+			return false;
+		}
+
+		String projectName = getProjectName();
+		if (projectName == null) {
+			return false;
+		}
+
+		IWizard wizard = getWizard();
+		if (wizard instanceof ExampleProjectCreationWizard) {
+			IWizardPage[] pages = wizard.getPages();
+			for (int i = 0; i < pages.length; i++) {
+				if ((pages[i] != this) && (pages[i] instanceof ExampleProjectCreationWizardPage)) {
+					if (projectName.equals(((ExampleProjectCreationWizardPage) pages[i]).getProjectName())) {
+						setErrorMessage(XMLWizardsMessages.ExampleProjectCreationWizardPage_error_alreadyexists);
+						return false;
+					}
+				}
+			}
+		}
+
+		return true;
+	}
+
+
+
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src-wizards/org/eclipse/wst/xml/ui/internal/wizards/ExportXMLCatalogWizard.java b/bundles/org.eclipse.wst.xml.ui/src-wizards/org/eclipse/wst/xml/ui/internal/wizards/ExportXMLCatalogWizard.java
new file mode 100644
index 0000000..478d459
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-wizards/org/eclipse/wst/xml/ui/internal/wizards/ExportXMLCatalogWizard.java
@@ -0,0 +1,95 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 Standards for Technology in Automotive Retail (STAR) 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:
+ *     David Carver/STAR - dcarver@starstandard.org/d_a_carver@yahoo.com - bug 192568
+ *            Initial API - This implements the functionality of the
+ *            old Export Dialog for the XML Catalog. 
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.wizards;
+
+import java.io.File;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.IExportWizard;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.dialogs.WizardNewFileCreationPage;
+import org.eclipse.ui.wizards.newresource.BasicNewFileResourceWizard;
+import org.eclipse.wst.xml.core.internal.XMLCorePlugin;
+import org.eclipse.wst.xml.core.internal.catalog.CatalogSet;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalog;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.INextCatalog;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImageHelper;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImages;
+
+public class ExportXMLCatalogWizard extends BasicNewFileResourceWizard implements IExportWizard {
+
+	protected WizardNewFileCreationPage exportPage = null;
+	protected ICatalog workingUserCatalog = null;
+	protected ICatalog userCatalog = null;
+	
+	public ExportXMLCatalogWizard() {
+		setWindowTitle(XMLWizardsMessages._UI_DIALOG_XMLCATALOG_EXPORT_TITLE);
+		ImageDescriptor descriptor = XMLEditorPluginImageHelper.getInstance().getImageDescriptor(XMLEditorPluginImages.IMG_WIZBAN_GENERATEXML);
+		setDefaultPageImageDescriptor(descriptor);
+		ICatalog defaultCatalog = XMLCorePlugin.getDefault().getDefaultXMLCatalog();
+		INextCatalog[] nextCatalogs = defaultCatalog.getNextCatalogs();
+		for (int i = 0; i < nextCatalogs.length; i++) {
+			INextCatalog catalog = nextCatalogs[i];
+			ICatalog referencedCatalog = catalog.getReferencedCatalog();
+			if (referencedCatalog != null) {
+				if (XMLCorePlugin.USER_CATALOG_ID.equals(referencedCatalog.getId())) {
+					userCatalog = referencedCatalog;
+				}
+			}
+		}
+		CatalogSet tempCatalogSet = new CatalogSet();
+		workingUserCatalog = tempCatalogSet.lookupOrCreateCatalog("working", ""); //$NON-NLS-1$ //$NON-NLS-2$
+		workingUserCatalog.addEntriesFromCatalog(userCatalog);
+
+	}
+
+	public boolean performFinish() {
+		IWorkspace workspace = ResourcesPlugin.getWorkspace();
+		IWorkspaceRoot workspaceRoot = workspace.getRoot();
+		String workspacePath = workspaceRoot.getLocation().toOSString();
+		String fullPath = workspacePath + exportPage.getContainerFullPath().toOSString();
+		String requiredString=fullPath + File.separator + exportPage.getFileName();
+		try {
+			IFile file = exportPage.createNewFile();
+			workingUserCatalog.setLocation(requiredString);
+			workingUserCatalog.save();
+			file.refreshLocal(IResource.DEPTH_ZERO, null);
+		} catch (Exception ex) {
+			return false;
+		}
+		return true;
+	}
+	
+	public void addPages() {
+		exportPage = new WizardNewFileCreationPage("XML Catalog Export",  getSelection());
+		exportPage.setTitle(XMLWizardsMessages._UI_DIALOG_XMLCATALOG_EXPORT_TITLE);
+		exportPage.setDescription(XMLWizardsMessages._UI_DIALOG_XMLCATALOG_EXPORT_DESCRIPTION);
+		exportPage.setFileExtension("xml"); //$NON-NLS-1$
+		
+		addPage(exportPage);
+	}
+	
+	public void init(IWorkbench workbench, IStructuredSelection currentSelection) {
+		super.init(workbench, currentSelection);
+		setWindowTitle(XMLWizardsMessages._UI_DIALOG_XMLCATALOG_EXPORT_TITLE);
+		ImageDescriptor descriptor = XMLEditorPluginImageHelper.getInstance().getImageDescriptor(XMLEditorPluginImages.IMG_WIZBAN_GENERATEXML);
+		setDefaultPageImageDescriptor(descriptor);
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src-wizards/org/eclipse/wst/xml/ui/internal/wizards/IXMLWizardHelpContextIds.java b/bundles/org.eclipse.wst.xml.ui/src-wizards/org/eclipse/wst/xml/ui/internal/wizards/IXMLWizardHelpContextIds.java
new file mode 100644
index 0000000..e342efa
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-wizards/org/eclipse/wst/xml/ui/internal/wizards/IXMLWizardHelpContextIds.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.wizards;
+
+import org.eclipse.wst.xml.ui.internal.XMLUIPlugin;
+
+/**
+ * Help context ids for the xml wizard.
+ * <p>
+ * This interface contains constants only; it is not intended to be
+ * implemented.
+ * </p>
+ */
+interface IXMLWizardHelpContextIds {
+	// org.eclipse.wst.xml.ui.
+	public static final String PREFIX = XMLUIPlugin.ID + "."; //$NON-NLS-1$
+	// Create XML file from a DTD file radio
+	public static final String XML_NEWWIZARD_CREATEXML1_HELPID = PREFIX + "xmlc0101"; //$NON-NLS-1$
+	// Create XML file from an XML schema file radio button
+	public static final String XML_NEWWIZARD_CREATEXML2_HELPID = PREFIX + "xmlc0102"; //$NON-NLS-1$
+	// Create XML file from scratch radio button
+	public static final String XML_NEWWIZARD_CREATEXML3_HELPID = PREFIX + "xmlc0103"; //$NON-NLS-1$
+	// Select Source file page
+	public static final String XML_NEWWIZARD_SELECTSOURCE_HELPID = PREFIX + "xmlc0500"; //$NON-NLS-1$
+	// Root element for both DTD and XML schema
+	public static final String XML_NEWWIZARD_SELECTROOTELEMENT_HELPID = PREFIX + "xmlc0410"; //$NON-NLS-1$
+	// Create Optional Attributes
+	public static final String XML_NEWWIZARD_SELECTROOTELEMENT1_HELPID = PREFIX + "xmlc0441"; //$NON-NLS-1$
+	// Create Optional Elements
+	public static final String XML_NEWWIZARD_SELECTROOTELEMENT2_HELPID = PREFIX + "xmlc0442"; //$NON-NLS-1$
+	// Create first choice of required choice
+	public static final String XML_NEWWIZARD_SELECTROOTELEMENT3_HELPID = PREFIX + "xmlc0443"; //$NON-NLS-1$
+	// Fill elements and attribute with data
+	public static final String XML_NEWWIZARD_SELECTROOTELEMENT4_HELPID = PREFIX + "xmlc0444"; //$NON-NLS-1$
+	// System ID for DTD
+	public static final String XML_NEWWIZARD_SELECTROOTELEMENT5_HELPID = PREFIX + "xmlc0210"; //$NON-NLS-1$
+	// Public ID for DTD
+	public static final String XML_NEWWIZARD_SELECTROOTELEMENT6_HELPID = PREFIX + "xmlc0220"; //$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src-wizards/org/eclipse/wst/xml/ui/internal/wizards/ImportXMLCatalogPage.java b/bundles/org.eclipse.wst.xml.ui/src-wizards/org/eclipse/wst/xml/ui/internal/wizards/ImportXMLCatalogPage.java
new file mode 100644
index 0000000..38e3447
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-wizards/org/eclipse/wst/xml/ui/internal/wizards/ImportXMLCatalogPage.java
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 Standards for Technology in Automotive Retail (STAR) 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:
+ *     David Carver/STAR - dcarver@starstandard.org/d_a_carver@yahoo.com - bug 192568
+ *            Initial API - This implements the functionality of the
+ *            old Import Dialog for the XML Catalog. 
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.wizards;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.wst.common.ui.internal.viewers.SelectSingleFileView;
+
+public class ImportXMLCatalogPage extends WizardPage {
+
+	protected SelectSingleFileView selectSingleFileView;
+	protected IStructuredSelection selection;
+	
+
+	public ImportXMLCatalogPage() {
+		super(XMLWizardsMessages._UI_DIALOG_XMLCATALOG_IMPORT_TITLE);
+		setTitle(XMLWizardsMessages._UI_DIALOG_XMLCATALOG_IMPORT_TITLE);
+		selection = new StructuredSelection();
+		selectSingleFileView = new SelectSingleFileView(selection, false) {
+			public void createFilterControl(Composite composite) {
+				ImportXMLCatalogPage.this.createFilterControl(composite);
+			}
+		};
+
+	}
+
+	public void createControl(Composite parent) {
+		Composite composite = new Composite(parent, SWT.NULL);
+		composite.setLayout(new GridLayout());
+		GridData gd = new GridData(GridData.FILL_BOTH);
+		gd.widthHint = 350;
+		gd.heightHint = 350;
+		composite.setLayoutData(gd);
+		String[] extensions = { ".xmlcatalog", ".xml" }; //$NON-NLS-1$ //$NON-NLS-2$
+		selectSingleFileView.addFilterExtensions(extensions);
+		selectSingleFileView.createControl(composite);
+		selectSingleFileView.setVisibleHelper(true);
+		selectSingleFileView.addSelectionChangedTreeListener(new ISelectionChangedListener(){
+			public void selectionChanged(SelectionChangedEvent event) {
+				ImportXMLCatalogPage.this.setPageComplete(selectSingleFileView.getFile() != null);
+			}
+		});
+		setControl(composite);
+	}
+
+	public void createFilterControl(Composite composite) {
+	}
+
+	public IFile getFile() {
+		return selectSingleFileView.getFile();
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src-wizards/org/eclipse/wst/xml/ui/internal/wizards/ImportXMLCatalogWizard.java b/bundles/org.eclipse.wst.xml.ui/src-wizards/org/eclipse/wst/xml/ui/internal/wizards/ImportXMLCatalogWizard.java
new file mode 100644
index 0000000..f1200a2
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-wizards/org/eclipse/wst/xml/ui/internal/wizards/ImportXMLCatalogWizard.java
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Standards for Technology in Automotive Retail (STAR) 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:
+ *     David Carver/STAR - dcarver@starstandard.org/d_a_carver@yahoo.com - bug 192568
+ *            Initial API - This implements the functionality of the
+ *            old Import Dialog for the XML Catalog. 
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.wizards;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.wizard.Wizard;
+import org.eclipse.ui.IImportWizard;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.wst.xml.core.internal.XMLCorePlugin;
+import org.eclipse.wst.xml.core.internal.catalog.CatalogSet;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalog;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.INextCatalog;
+import org.eclipse.wst.xml.ui.internal.catalog.XMLCatalogMessages;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImageHelper;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImages;
+
+public class ImportXMLCatalogWizard extends Wizard implements IImportWizard {
+
+	protected ImportXMLCatalogPage importPage = null;
+	protected ICatalog workingUserCatalog = null;
+	protected ICatalog userCatalog = null;
+	
+	public ImportXMLCatalogWizard() {
+		setWindowTitle(XMLWizardsMessages._UI_DIALOG_XMLCATALOG_IMPORT_TITLE);
+		ImageDescriptor descriptor = XMLEditorPluginImageHelper.getInstance().getImageDescriptor(XMLEditorPluginImages.IMG_WIZBAN_GENERATEXML);
+		setDefaultPageImageDescriptor(descriptor);
+		ICatalog defaultCatalog = XMLCorePlugin.getDefault().getDefaultXMLCatalog();
+		INextCatalog[] nextCatalogs = defaultCatalog.getNextCatalogs();
+		for (int i = 0; i < nextCatalogs.length; i++) {
+			INextCatalog catalog = nextCatalogs[i];
+			ICatalog referencedCatalog = catalog.getReferencedCatalog();
+			if (referencedCatalog != null) {
+				if (XMLCorePlugin.USER_CATALOG_ID.equals(referencedCatalog.getId())) {
+					userCatalog = referencedCatalog;
+				}
+			}
+		}
+
+		CatalogSet tempCatalogSet = new CatalogSet();
+		workingUserCatalog = tempCatalogSet.lookupOrCreateCatalog("working", ""); //$NON-NLS-1$ //$NON-NLS-2$
+		workingUserCatalog.addEntriesFromCatalog(userCatalog);
+	}
+	
+	public boolean canFinish() {
+		return importPage.isPageComplete();
+	}
+
+	public boolean performFinish() {
+		IFile file = importPage.getFile();
+		if (file != null) {
+			String fileName = file.getLocation().toFile().toURI().toString();
+			try {
+				CatalogSet tempResourceSet = new CatalogSet();
+				ICatalog newCatalog = tempResourceSet.lookupOrCreateCatalog("temp", fileName); //$NON-NLS-1$
+				
+				workingUserCatalog.addEntriesFromCatalog(newCatalog);
+				userCatalog.clear();
+				userCatalog.addEntriesFromCatalog(workingUserCatalog);
+				userCatalog.save();
+			}
+			catch (Exception e) {
+				return false;
+			}
+		}
+		
+		return true;
+	}
+
+	public void init(IWorkbench workbench, IStructuredSelection selection) {
+		// TODO Auto-generated method stub
+
+	}
+	
+	public void addPages() {
+		importPage = new ImportXMLCatalogPage();
+		importPage.setTitle(XMLCatalogMessages.UI_LABEL_IMPORT_DIALOG_HEADING);
+		importPage.setDescription(XMLWizardsMessages._UI_DIALOG_XMLCATALOG_IMPORT_DESCRIPTION);
+		importPage.setMessage(XMLCatalogMessages.UI_LABEL_IMPORT_DIALOG_MESSAGE);
+		addPage(importPage);
+		importPage.setPageComplete(false);
+	}
+}
+
+
diff --git a/bundles/org.eclipse.wst.xml.ui/src-wizards/org/eclipse/wst/xml/ui/internal/wizards/NamespaceInfoContentBuilder.java b/bundles/org.eclipse.wst.xml.ui/src-wizards/org/eclipse/wst/xml/ui/internal/wizards/NamespaceInfoContentBuilder.java
new file mode 100644
index 0000000..09eed81
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-wizards/org/eclipse/wst/xml/ui/internal/wizards/NamespaceInfoContentBuilder.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.wizards;
+
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Vector;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAnyElement;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.ContentBuilder;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.NamespaceInfo;
+
+public class NamespaceInfoContentBuilder extends ContentBuilder {
+	protected int count = 1;
+	public List list = new Vector();
+	protected Hashtable table = new Hashtable();
+
+	public NamespaceInfoContentBuilder() {
+		super();
+	}
+
+	public void visitCMElementDeclaration(CMElementDeclaration ed) {
+		if (ed.getProperty("http://org.eclipse.wst/cm/properties/definitionInfo") != null) //$NON-NLS-1$
+		{
+			super.visitCMElementDeclaration(ed);
+		}
+	}
+
+	protected void createAnyElementNode(CMAnyElement anyElement) {
+		String uri = anyElement.getNamespaceURI();
+		if ((uri != null) && !uri.startsWith("##")) //$NON-NLS-1$
+		{
+			if (table.get(uri) == null) {
+				NamespaceInfo info = new NamespaceInfo();
+				info.uri = uri;
+				info.prefix = "p" + count++; //$NON-NLS-1$
+				table.put(uri, info);
+				list.add(info);
+			}
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src-wizards/org/eclipse/wst/xml/ui/internal/wizards/NewModelWizard.java b/bundles/org.eclipse.wst.xml.ui/src-wizards/org/eclipse/wst/xml/ui/internal/wizards/NewModelWizard.java
new file mode 100644
index 0000000..4a400f2
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-wizards/org/eclipse/wst/xml/ui/internal/wizards/NewModelWizard.java
@@ -0,0 +1,329 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *	   David Schneider, david.schneider@unisys.com - [142500] WTP properties pages fonts don't follow Eclipse preferences
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.wizards;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.content.IContentType;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.wizard.Wizard;
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.FileDialog;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.INewWizard;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.dialogs.WizardNewFileCreationPage;
+import org.eclipse.wst.xml.core.internal.provisional.contenttype.ContentTypeIdForXML;
+
+public class NewModelWizard extends Wizard implements INewWizard {
+
+	protected IStructuredSelection fSelection;
+	protected IWorkbench fWorkbench;
+	protected String fCurrentDirectory;
+
+	public NewModelWizard() {
+		super();
+	}
+
+	public void init(IWorkbench workbench, IStructuredSelection selection) {
+		this.fWorkbench = workbench;
+		this.fSelection = selection;
+	}
+
+	public boolean performFinish() {
+		boolean result = true;
+		WizardPage currentPage = (WizardPage) getContainer().getCurrentPage();
+		if (currentPage != null) {
+			result = currentPage.isPageComplete();
+		}
+		return result;
+	}
+
+	/**
+	 * showFileDialog
+	 */
+	public FileDialog showFileDialog(Shell shell, String defaultDirectory, String defaultFile, String[] filterExtensions) {
+		FileDialog fileDialog = new FileDialog(shell, SWT.OPEN);
+
+		// Get the last visit directory if we haven't defined a particular one
+		// here.
+		if ((defaultDirectory == null) || (defaultDirectory.length() == 0)) {
+			// defaultDirectory =
+			// Locate.instance(this).getLastSelectedDirectory(getResourcePath());
+		}
+
+		if ((defaultDirectory != null) && (defaultDirectory.length() != 0)) {
+			fileDialog.setFilterPath(defaultDirectory);
+		}
+
+		fileDialog.setFileName(defaultFile);
+		fileDialog.setFilterExtensions(filterExtensions);
+
+		fileDialog.open();
+
+		return fileDialog;
+	}
+
+
+	public void setCurrentDirectory(String currentDirectory1) {
+		this.fCurrentDirectory = currentDirectory1;
+	}
+
+
+	public void createWorkbenchResource(IContainer container, String fileName) {
+		IPath path = container.getFullPath();
+		path = path.append(fileName);
+		IFile file = container.getWorkspace().getRoot().getFile(path);
+		if (!file.exists()) {
+			try {
+				file.create(null, true, null);
+			}
+			catch (CoreException e) {
+				// XMLBuilderPlugin.getPlugin().getMsgLogger().write("Encountered
+				// exception creating file: " + e.getMessage());
+			}
+		}
+	}
+
+	/**
+	 * StartPage
+	 */
+	public class StartPage extends WizardPage implements Listener {
+		protected int selectedButton;
+		protected String[] radioButtonLabel;
+		protected Button[] radioButton;
+
+		public StartPage(String pageName, String[] radioButtonLabel) {
+			super(pageName);
+			this.radioButtonLabel = radioButtonLabel;
+			radioButton = new Button[radioButtonLabel.length];
+		}
+
+		public Button getRadioButtonAtIndex(int i) {
+			Button result = null;
+			if ((i >= 0) && (i < radioButton.length)) {
+				result = radioButton[i];
+			}
+			return result;
+		}
+
+		public int getSelectedRadioButtonIndex() {
+			int result = -1;
+			for (int i = 0; i < radioButton.length; i++) {
+				if (radioButton[i].getSelection()) {
+					result = i;
+				}
+			}
+			return result;
+		}
+
+		public void createControl(Composite parent) {
+			Composite base = new Composite(parent, SWT.NONE);
+			base.setLayout(new GridLayout());
+
+			// radio buttons' container
+			Composite radioButtonsGroup = new Composite(base, SWT.NONE);
+			GridLayout layout = new GridLayout();
+			layout.numColumns = 1;
+			layout.makeColumnsEqualWidth = true;
+			layout.marginWidth = 0;
+
+			radioButtonsGroup.setLayout(layout);
+			GridData gd = new GridData(GridData.FILL_BOTH);
+			gd.heightHint = 300;
+			gd.widthHint = 400;
+			radioButtonsGroup.setLayoutData(gd);
+
+			for (int i = 0; i < radioButtonLabel.length; i++) {
+				radioButton[i] = new Button(radioButtonsGroup, SWT.RADIO);
+				radioButton[i].setText(radioButtonLabel[i]);
+				radioButton[i].setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+				// radioButton[i].addListener(SWT.Modify, this);
+			}
+			setControl(base);
+			setPageComplete(isPageComplete());
+			Dialog.applyDialogFont(parent);
+		}
+
+		public void handleEvent(Event event) {
+			if (event.type == SWT.Modify) {
+				setPageComplete(isPageComplete());
+			}
+		}
+	}
+
+
+	/**
+	 * NewFilePage
+	 */
+	public class NewFilePage extends WizardNewFileCreationPage {
+		public String defaultName = "NewFile"; //$NON-NLS-1$
+		public String defaultFileExtension = ".txt"; //$NON-NLS-1$
+		public String[] filterExtensions = {"*.txt"}; //$NON-NLS-1$
+		private List fValidExtensions = null;
+
+		public NewFilePage(IStructuredSelection selection) {
+			super("", selection); //$NON-NLS-1$
+		}
+
+		protected String computeDefaultFileName() {
+			int count = 0;
+			String fileName = defaultName + defaultFileExtension;
+			IPath containerFullPath = getContainerFullPath();
+			if (containerFullPath != null) {
+				while (true) {
+					IPath path = containerFullPath.append(fileName);
+					if (ResourcesPlugin.getWorkspace().getRoot().exists(path)) {
+						count++;
+						fileName = defaultName + count + defaultFileExtension;
+					}
+					else {
+						break;
+					}
+				}
+			}
+			return fileName;
+		}
+
+		// returns true if file of specified name exists in any case for
+		// selected container
+		protected String existsFileAnyCase(String fileName) {
+			if ((getContainerFullPath() != null) && (getContainerFullPath().isEmpty() == false) && (fileName.compareTo("") != 0)) //$NON-NLS-1$
+			{
+				// look through all resources at the specified container -
+				// compare in upper case
+				IResource parent = ResourcesPlugin.getWorkspace().getRoot().findMember(getContainerFullPath());
+				if (parent instanceof IContainer) {
+					IContainer container = (IContainer) parent;
+					try {
+						IResource[] members = container.members();
+						String enteredFileUpper = fileName.toUpperCase();
+						for (int i = 0; i < members.length; i++) {
+							String resourceUpperName = members[i].getName().toUpperCase();
+							if (resourceUpperName.equals(enteredFileUpper)) {
+								return members[i].getName();
+							}
+						}
+					}
+					catch (CoreException e) {
+					}
+				}
+			}
+			return null;
+		}
+
+
+		protected boolean validatePage() {
+			String fullFileName = getFileName();
+			if (!extensionValidForContentType(fullFileName)) {
+				setErrorMessage(NLS.bind(XMLWizardsMessages._ERROR_BAD_FILENAME_EXTENSION, getValidExtensions().toString()));
+				return false;
+			}
+			// no fileExtension, let's check for this file with default file
+			// extension
+			if (fullFileName.lastIndexOf('.') == -1)
+			{
+				fullFileName += defaultFileExtension;
+			}
+
+			if ((getContainerFullPath() != null) && (getContainerFullPath().isEmpty() == false) && (getFileName().compareTo("") != 0)) //$NON-NLS-1$
+			{
+				Path fullPath = new Path(getContainerFullPath().toString() + '/' + fullFileName);
+				IResource resource = ResourcesPlugin.getWorkspace().getRoot().findMember(fullPath);
+				if (resource != null) {
+					setErrorMessage(XMLWizardsMessages._ERROR_FILE_ALREADY_EXISTS);
+					return false;
+				}
+			}
+
+			// check for file should be case insensitive
+			String sameName = existsFileAnyCase(fullFileName);
+			if (sameName != null) {
+				// ISSUE: is qualitifedFileName not needed, or is it supposed
+				// to be used in error message?
+				// String qualifiedFileName =
+				// getContainerFullPath().toString() + '/' + fullFileName;
+				setErrorMessage(XMLWizardsMessages._ERROR_FILE_ALREADY_EXISTS + " " + sameName); //$NON-NLS-1$
+				return false;
+			}
+
+			return super.validatePage();
+		}
+
+		public void createControl(Composite parent) {
+			// inherit default container and name specification widgets
+			super.createControl(parent);
+			this.setFileName(computeDefaultFileName());
+			setPageComplete(validatePage());
+		}
+
+		/**
+		 * Get list of valid extensions for XML Content type
+		 * 
+		 * @return List
+		 */
+		List getValidExtensions() {
+			if (fValidExtensions == null) {
+				IContentType type = Platform.getContentTypeManager().getContentType(ContentTypeIdForXML.ContentTypeID_XML);
+				fValidExtensions = new ArrayList(Arrays.asList(type.getFileSpecs(IContentType.FILE_EXTENSION_SPEC)));
+			}
+			return fValidExtensions;
+		}
+
+		/**
+		 * Verifies if fileName is valid name for content type. Takes base
+		 * content type into consideration.
+		 * 
+		 * @param fileName
+		 * @return true if extension is valid for this content type
+		 */
+		boolean extensionValidForContentType(String fileName) {
+			boolean valid = false;
+
+			IContentType type = Platform.getContentTypeManager().getContentType(ContentTypeIdForXML.ContentTypeID_XML);
+			// there is currently an extension
+			if (fileName.lastIndexOf('.') != -1) {
+				// check what content types are associated with current
+				// extension
+				IContentType[] types = Platform.getContentTypeManager().findContentTypesFor(fileName);
+				int i = 0;
+				while ((i < types.length) && !valid) {
+					valid = types[i].isKindOf(type);
+					++i;
+				}
+			}
+			else {
+				valid = true; // no extension so valid
+			}
+			return valid;
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src-wizards/org/eclipse/wst/xml/ui/internal/wizards/NewXMLGenerator.java b/bundles/org.eclipse.wst.xml.ui/src-wizards/org/eclipse/wst/xml/ui/internal/wizards/NewXMLGenerator.java
new file mode 100644
index 0000000..476a754
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-wizards/org/eclipse/wst/xml/ui/internal/wizards/NewXMLGenerator.java
@@ -0,0 +1,422 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.wizards;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.ProjectScope;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.core.runtime.content.IContentType;
+import org.eclipse.core.runtime.preferences.IScopeContext;
+import org.eclipse.core.runtime.preferences.InstanceScope;
+import org.eclipse.jface.util.Assert;
+import org.eclipse.wst.common.uriresolver.internal.provisional.URIResolver;
+import org.eclipse.wst.common.uriresolver.internal.provisional.URIResolverPlugin;
+import org.eclipse.wst.common.uriresolver.internal.util.URIHelper;
+import org.eclipse.wst.sse.core.internal.encoding.CommonEncodingPreferenceNames;
+import org.eclipse.wst.sse.core.utils.StringUtils;
+import org.eclipse.wst.xml.core.internal.XMLCorePlugin;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalogEntry;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.ContentModelManager;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.ContentBuilder;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.DOMContentBuilderImpl;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.DOMWriter;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.NamespaceInfo;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+public class NewXMLGenerator {
+
+	protected String grammarURI;
+	protected CMDocument cmDocument;
+	protected int buildPolicy;
+	protected String rootElementName;
+
+	protected ICatalogEntry xmlCatalogEntry;
+	protected int optionalElementDepthLimit = -1;
+
+	// info for dtd
+	protected String publicId;
+	protected String systemId;
+	protected String defaultSystemId;
+
+	// info for xsd
+	public List namespaceInfoList;
+
+	public NewXMLGenerator() {
+		super();
+	}
+
+	public NewXMLGenerator(String grammarURI, CMDocument cmDocument) {
+		this.grammarURI = grammarURI;
+		this.cmDocument = cmDocument;
+	}
+
+
+	public static CMDocument createCMDocument(String uri, String[] errorInfo) {
+		String title = null;
+		String message = null;
+		List errorList = new Vector();
+		CMDocument cmDocument = null;
+
+		if (URIHelper.isReadableURI(uri, true)) {
+			// (cs) assume the uri has been provided in a normalized form
+			cmDocument = ContentModelManager.getInstance().createCMDocument(uri, null);
+
+			if (uri.endsWith(".dtd")) { //$NON-NLS-1$
+				if (errorList.size() > 0) {
+					title = XMLWizardsMessages._UI_INVALID_GRAMMAR_ERROR;
+					message = XMLWizardsMessages._UI_LABEL_ERROR_DTD_INVALID_INFO;
+				}
+			}
+			else // ".xsd"
+			{
+				// To be consistent with the schema editor validation
+				XMLSchemaValidationChecker validator = new XMLSchemaValidationChecker();
+				if (!validator.isValid(uri)) {
+					title = XMLWizardsMessages._UI_INVALID_GRAMMAR_ERROR;
+					message = XMLWizardsMessages._UI_LABEL_ERROR_SCHEMA_INVALID_INFO;
+				}
+				else if (cmDocument != null) {
+					int globalElementCount = cmDocument.getElements().getLength();
+					if (globalElementCount == 0) {
+						title = XMLWizardsMessages._UI_WARNING_TITLE_NO_ROOT_ELEMENTS;
+						message = XMLWizardsMessages._UI_WARNING_MSG_NO_ROOT_ELEMENTS;
+					}
+				}
+			}
+		}
+		else {
+			title = XMLWizardsMessages._UI_WARNING_TITLE_NO_ROOT_ELEMENTS;
+			message = XMLWizardsMessages._UI_WARNING_URI_NOT_FOUND_COLON + " " + uri; //$NON-NLS-1$
+		}
+		errorInfo[0] = title;
+		errorInfo[1] = message;
+
+		return cmDocument;
+	}
+	
+	private String applyLineDelimiter(IFile file, String text) {
+		String systemLineSeparator = System.getProperty("line.separator");
+		String lineDelimiter = Platform.getPreferencesService().getString(Platform.PI_RUNTIME, Platform.PREF_LINE_SEPARATOR, systemLineSeparator, new IScopeContext[] {new ProjectScope(file.getProject()), new InstanceScope() });//$NON-NLS-1$
+		if(!systemLineSeparator.equals(lineDelimiter)) {
+			String convertedText = StringUtils.replace(text, "\r\n", "\n");
+			convertedText = StringUtils.replace(convertedText, "\r", "\n");
+			convertedText = StringUtils.replace(convertedText, "\n", lineDelimiter);
+			return convertedText;
+		}
+		return text;
+	}
+
+	/**
+	 * @deprecated use createTemplateXMLDocument(IFile, String) instead
+	 */
+	public void createEmptyXMLDocument(IFile newFile) throws Exception {
+		String charSet = getUserPreferredCharset();
+		String contents = "<?xml version=\"1.0\" encoding=\"" + charSet + "\"?>"; //$NON-NLS-1$ //$NON-NLS-2$
+		createTemplateXMLDocument(newFile, contents);
+	}
+	
+	void createTemplateXMLDocument(IFile newFile, String contents) throws Exception {
+		if (contents != null) {
+			String charSet = getUserPreferredCharset();
+			ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+	
+			PrintWriter writer = new PrintWriter(new OutputStreamWriter(outputStream, charSet));
+			contents = applyLineDelimiter(newFile, contents);
+			writer.println(contents);
+			writer.flush();
+			outputStream.close();
+	
+			ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
+			newFile.setContents(inputStream, true, true, null);
+			inputStream.close();
+		}
+	}
+
+	private String getUserPreferredCharset() {
+		Preferences preference = XMLCorePlugin.getDefault().getPluginPreferences();
+		String charSet = preference.getString(CommonEncodingPreferenceNames.OUTPUT_CODESET);
+		return charSet;
+	}
+
+	public void createXMLDocument(String xmlFileName) throws Exception {
+		IContentType contentType = Platform.getContentTypeManager().findContentTypeFor(xmlFileName);
+		String charset = null;
+		if (contentType != null) {
+			charset = contentType.getDefaultCharset();
+		}
+		ByteArrayOutputStream outputStream = createXMLDocument(xmlFileName, charset);
+
+		File file = new File(xmlFileName);
+		FileOutputStream fos = new FileOutputStream(file);
+		outputStream.writeTo(fos);
+		fos.close();
+	}
+
+
+	public void createXMLDocument(IFile newFile, String xmlFileName) throws Exception {
+		String charset = newFile.getCharset();
+		ByteArrayOutputStream outputStream = createXMLDocument(xmlFileName, charset);
+
+		String contents = outputStream.toString(charset);
+		contents = applyLineDelimiter(newFile, contents);
+
+		ByteArrayInputStream inputStream = new ByteArrayInputStream(contents.getBytes(charset));
+		newFile.setContents(inputStream, true, true, null);
+		inputStream.close();
+	}
+
+
+	public ByteArrayOutputStream createXMLDocument(String xmlFileName, String charset) throws Exception {
+		if (charset == null) {
+			charset = getUserPreferredCharset();
+			if (charset == null) {
+				charset = "UTF-8"; //$NON-NLS-1$
+			}
+		}
+		CMDocument cmDocument = getCMDocument();
+
+		Assert.isNotNull(cmDocument);
+		Assert.isNotNull(getRootElementName());
+
+		// create the xml model
+		CMNamedNodeMap nameNodeMap = cmDocument.getElements();
+		CMElementDeclaration cmElementDeclaration = (CMElementDeclaration) nameNodeMap.getNamedItem(getRootElementName());
+
+		Document xmlDocument = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
+		DOMContentBuilderImpl contentBuilder = new DOMContentBuilderImpl(xmlDocument);
+
+		// this 'uglyTempHack' flag is required in order to supress the
+		// creation a default encoding
+		// we'll handle this later in the domWriter.print() method used below
+		//
+		contentBuilder.supressCreationOfDoctypeAndXMLDeclaration = true;
+		contentBuilder.setBuildPolicy(buildPolicy);
+		contentBuilder.setOptionalElementDepthLimit(optionalElementDepthLimit);
+		contentBuilder.setExternalCMDocumentSupport(new MyExternalCMDocumentSupport(namespaceInfoList, xmlFileName));
+		contentBuilder.createDefaultRootContent(cmDocument, cmElementDeclaration, namespaceInfoList);
+
+		ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+		OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream, charset);
+
+		DOMWriter domWriter = new DOMWriter(outputStreamWriter);
+
+		// TODO... instead of relying on file extensions, we need to keep
+		// track of the grammar type
+		// better yet we should reate an SSE document so that we can format it
+		// nicely before saving
+		// then we won't need the DOMWriter at all
+		//
+		domWriter.print(xmlDocument, charset, cmDocument.getNodeName(), getNonWhitespaceString(getPublicId()), getNonWhitespaceString(getSystemId()));
+		outputStream.flush();
+		outputStream.close();
+
+		return outputStream;
+	}
+
+
+	public void createNamespaceInfoList() {
+		List result = new Vector();
+		if (cmDocument != null) {
+			result = (List) cmDocument.getProperty("http://org.eclipse.wst/cm/properties/completeNamespaceInfo"); //$NON-NLS-1$
+			if (result != null) {
+				int size = result.size();
+				for (int i = 0; i < size; i++) {
+					NamespaceInfo info = (NamespaceInfo) result.get(i);
+					if (i == 0) {
+						String locationInfo = null;
+						if (xmlCatalogEntry != null) {
+							if (xmlCatalogEntry.getEntryType() == ICatalogEntry.ENTRY_TYPE_PUBLIC) {
+								locationInfo = xmlCatalogEntry.getAttributeValue(ICatalogEntry.ATTR_WEB_URL);
+							}
+							else {
+								locationInfo = xmlCatalogEntry.getKey();
+							}
+						}
+						if (locationInfo == null) {
+							locationInfo = defaultSystemId;
+						}
+						info.locationHint = locationInfo;
+						info.setProperty("locationHint-readOnly", "true"); //$NON-NLS-1$ //$NON-NLS-2$
+						info.setProperty("uri-readOnly", "true"); //$NON-NLS-1$ //$NON-NLS-2$
+						info.setProperty("unremovable", "true"); //$NON-NLS-1$ //$NON-NLS-2$
+					} else {
+						info.locationHint = null;
+					}
+				}
+			}
+
+			NamespaceInfoContentBuilder builder = new NamespaceInfoContentBuilder();
+			builder.setBuildPolicy(ContentBuilder.BUILD_ONLY_REQUIRED_CONTENT);
+			builder.visitCMNode(cmDocument);
+			result.addAll(builder.list);
+		}
+		namespaceInfoList = result;
+	}
+
+
+	public boolean isMissingNamespaceLocation() {
+		boolean result = false;
+		for (Iterator i = namespaceInfoList.iterator(); i.hasNext();) {
+			NamespaceInfo info = (NamespaceInfo) i.next();
+			if (info.locationHint == null) {
+				result = true;
+				break;
+			}
+		}
+		return result;
+	}
+
+
+	public String[] getNamespaceInfoErrors() {
+		String[] errorList = null;
+
+// No warnings should be given when namespaces entries have missing location hints
+// See https://bugs.eclipse.org/bugs/show_bug.cgi?id=105128		
+//		if ((namespaceInfoList != null) && isMissingNamespaceLocation()) {
+//			String title = XMLWizardsMessages._UI_LABEL_NO_LOCATION_HINT;
+//			String message = XMLWizardsMessages._UI_WARNING_MSG_NO_LOCATION_HINT_1 + " " + XMLWizardsMessages._UI_WARNING_MSG_NO_LOCATION_HINT_2 + "\n\n" + XMLWizardsMessages._UI_WARNING_MSG_NO_LOCATION_HINT_3; //$NON-NLS-1$ //$NON-NLS-2$
+//
+//			errorList = new String[2];
+//			errorList[0] = title;
+//			errorList[1] = message;
+//		}
+		return errorList;
+	}
+
+
+	public void setXMLCatalogEntry(ICatalogEntry catalogEntry) {
+		xmlCatalogEntry = catalogEntry;
+	}
+
+	public ICatalogEntry getXMLCatalogEntry() {
+		return xmlCatalogEntry;
+	}
+
+
+	public void setBuildPolicy(int policy) {
+		buildPolicy = policy;
+	}
+
+
+	public void setDefaultSystemId(String sysId) {
+		defaultSystemId = sysId;
+	}
+
+	public String getDefaultSystemId() {
+		return defaultSystemId;
+	}
+
+	public void setSystemId(String sysId) {
+		systemId = sysId;
+	}
+
+	public String getSystemId() {
+		return systemId;
+	}
+
+	public void setPublicId(String pubId) {
+		publicId = pubId;
+	}
+
+	public String getPublicId() {
+		return publicId;
+	}
+
+	public void setGrammarURI(String gramURI) {
+		grammarURI = gramURI;
+	}
+
+	public String getGrammarURI() {
+		return grammarURI;
+	}
+
+	public void setCMDocument(CMDocument cmDoc) {
+		cmDocument = cmDoc;
+	}
+
+	public CMDocument getCMDocument() {
+		return cmDocument;
+	}
+
+	public void setRootElementName(String rootName) {
+		rootElementName = rootName;
+	}
+
+	public String getRootElementName() {
+		return rootElementName;
+	}
+
+
+	protected class MyExternalCMDocumentSupport implements DOMContentBuilderImpl.ExternalCMDocumentSupport {
+		protected List namespaceInfoList1;
+		protected URIResolver idResolver;
+		protected String resourceLocation;
+
+		protected MyExternalCMDocumentSupport(List namespaceInfoListParam, String resourceLocation) {
+			this.namespaceInfoList1 = namespaceInfoListParam;
+			this.resourceLocation = resourceLocation;
+			idResolver = URIResolverPlugin.createResolver();
+		}
+
+		public CMDocument getCMDocument(Element element, String namespaceURI) {
+			CMDocument result = null;
+			if ((namespaceURI != null) && (namespaceURI.trim().length() > 0)) {
+				String locationHint = null;
+				for (Iterator i = namespaceInfoList1.iterator(); i.hasNext();) {
+					NamespaceInfo info = (NamespaceInfo) i.next();
+					if (namespaceURI.equals(info.uri)) {
+						locationHint = info.locationHint;
+						break;
+					}
+				}
+				if (locationHint != null) {
+					grammarURI = idResolver.resolve(resourceLocation, locationHint, locationHint);
+					result = ContentModelManager.getInstance().createCMDocument(getGrammarURI(), null);
+				}
+			}
+			else {
+				result = cmDocument;
+			}
+			return result;
+		}
+	}
+
+	public static String getNonWhitespaceString(String string) {
+		String result = null;
+		if (string != null) {
+			if (string.trim().length() > 0) {
+				result = string;
+			}
+		}
+		return result;
+	}
+	
+	public void setOptionalElementDepthLimit(int optionalElementDepthLimit) {
+		this.optionalElementDepthLimit = optionalElementDepthLimit;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src-wizards/org/eclipse/wst/xml/ui/internal/wizards/NewXMLHandler.java b/bundles/org.eclipse.wst.xml.ui/src-wizards/org/eclipse/wst/xml/ui/internal/wizards/NewXMLHandler.java
new file mode 100644
index 0000000..38c2669
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-wizards/org/eclipse/wst/xml/ui/internal/wizards/NewXMLHandler.java
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Standards for Technology in Automotive Retail 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:
+ *     David Carver - initial API and implementation, bug 212330
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.wizards;
+
+import java.util.Iterator;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.commands.IHandler;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+public class NewXMLHandler extends AbstractHandler implements IHandler {
+
+	/**
+	 * 
+	 */
+	public NewXMLHandler() {
+		super();
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.core.commands.AbstractHandler#execute(org.eclipse.core.commands.ExecutionEvent)
+	 */
+	public Object execute(ExecutionEvent event) throws ExecutionException {
+		IWorkbenchWindow workbenchWindow = 	HandlerUtil.getActiveWorkbenchWindow(event);
+		ISelection selection = workbenchWindow.getSelectionService().getSelection();
+		Object selectedObject = getSelection(selection);
+
+		if ((selectedObject instanceof IFile) && (selection instanceof IStructuredSelection)) {
+			IFile file = (IFile) selectedObject;
+			IStructuredSelection structuredSelection = (IStructuredSelection) selection;
+			try {
+				NewXMLWizard.showDialog(workbenchWindow.getShell(), file, structuredSelection);
+			}
+			catch (Exception e) {
+				// XMLCorePlugin.getDefault().getLog().log();
+			}
+		}
+		return null;
+	}
+	
+	public static Object getSelection(ISelection selection) {
+		if (selection == null) {
+			return null;
+		} 
+
+		Object result = null;
+		if (selection instanceof IStructuredSelection) {
+			IStructuredSelection es = (IStructuredSelection) selection;
+			Iterator i = es.iterator();
+			if (i.hasNext()) {
+				result = i.next();
+			}
+		}
+		return result;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src-wizards/org/eclipse/wst/xml/ui/internal/wizards/NewXMLTemplatesWizardPage.java b/bundles/org.eclipse.wst.xml.ui/src-wizards/org/eclipse/wst/xml/ui/internal/wizards/NewXMLTemplatesWizardPage.java
new file mode 100644
index 0000000..0a4b580
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-wizards/org/eclipse/wst/xml/ui/internal/wizards/NewXMLTemplatesWizardPage.java
@@ -0,0 +1,524 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.wizards;
+
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.preference.PreferenceDialog;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.text.Document;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.text.source.SourceViewer;
+import org.eclipse.jface.text.source.SourceViewerConfiguration;
+import org.eclipse.jface.text.templates.DocumentTemplateContext;
+import org.eclipse.jface.text.templates.Template;
+import org.eclipse.jface.text.templates.TemplateBuffer;
+import org.eclipse.jface.text.templates.TemplateContext;
+import org.eclipse.jface.text.templates.TemplateContextType;
+import org.eclipse.jface.text.templates.persistence.TemplateStore;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.TableLayout;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerSorter;
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ControlAdapter;
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Link;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.dialogs.PreferencesUtil;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.ui.StructuredTextViewerConfiguration;
+import org.eclipse.wst.sse.ui.internal.StructuredTextViewer;
+import org.eclipse.wst.sse.ui.internal.provisional.style.LineStyleProvider;
+import org.eclipse.wst.xml.core.internal.provisional.contenttype.ContentTypeIdForXML;
+import org.eclipse.wst.xml.ui.StructuredTextViewerConfigurationXML;
+import org.eclipse.wst.xml.ui.internal.Logger;
+import org.eclipse.wst.xml.ui.internal.XMLUIPlugin;
+import org.eclipse.wst.xml.ui.internal.editor.IHelpContextIds;
+import org.eclipse.wst.xml.ui.internal.preferences.XMLUIPreferenceNames;
+import org.eclipse.wst.xml.ui.internal.templates.TemplateContextTypeIdsXML;
+
+/**
+ * Templates page in new file wizard. Allows users to select a new file
+ * template to be applied in new file.
+ * 
+ */
+public class NewXMLTemplatesWizardPage extends WizardPage {
+
+	/**
+	 * Content provider for templates
+	 */
+	private class TemplateContentProvider implements IStructuredContentProvider {
+		/** The template store. */
+		private TemplateStore fStore;
+
+		/*
+		 * @see IContentProvider#dispose()
+		 */
+		public void dispose() {
+			fStore = null;
+		}
+
+		/*
+		 * @see IStructuredContentProvider#getElements(Object)
+		 */
+		public Object[] getElements(Object input) {
+			return fStore.getTemplates(TemplateContextTypeIdsXML.NEW);
+		}
+
+		/*
+		 * @see IContentProvider#inputChanged(Viewer, Object, Object)
+		 */
+		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+			fStore = (TemplateStore) newInput;
+		}
+	}
+
+	/**
+	 * Label provider for templates.
+	 */
+	private class TemplateLabelProvider extends LabelProvider implements ITableLabelProvider {
+
+		/*
+		 * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java.lang.Object,
+		 *      int)
+		 */
+		public Image getColumnImage(Object element, int columnIndex) {
+			return null;
+		}
+
+		/*
+		 * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java.lang.Object,
+		 *      int)
+		 */
+		public String getColumnText(Object element, int columnIndex) {
+			Template template = (Template) element;
+
+			switch (columnIndex) {
+				case 0 :
+					return template.getName();
+				case 1 :
+					return template.getDescription();
+				default :
+					return ""; //$NON-NLS-1$
+			}
+		}
+	}
+
+	/** Last selected template name */
+	private String fLastSelectedTemplateName;
+	/** The viewer displays the pattern of selected template. */
+	private SourceViewer fPatternViewer;
+	/** The table presenting the templates. */
+	private TableViewer fTableViewer;
+	/** Template store used by this wizard page */
+	private TemplateStore fTemplateStore;
+	/** Checkbox for using templates. */
+	private Button fUseTemplateButton;
+
+	public NewXMLTemplatesWizardPage() {
+		super("NewXMLTemplatesWizardPage", XMLWizardsMessages.NewXMLTemplatesWizardPage_0, null); //$NON-NLS-1$
+		setDescription(XMLWizardsMessages.NewXMLTemplatesWizardPage_1);
+	}
+
+	/**
+	 * Correctly resizes the table so no phantom columns appear
+	 * 
+	 * @param parent
+	 *            the parent control
+	 * @param buttons
+	 *            the buttons
+	 * @param table
+	 *            the table
+	 * @param column1
+	 *            the first column
+	 * @param column2
+	 *            the second column
+	 * @param column3
+	 *            the third column
+	 */
+	private void configureTableResizing(final Composite parent, final Table table, final TableColumn column1, final TableColumn column2) {
+		parent.addControlListener(new ControlAdapter() {
+			public void controlResized(ControlEvent e) {
+				Rectangle area = parent.getClientArea();
+				Point preferredSize = table.computeSize(SWT.DEFAULT, SWT.DEFAULT);
+				int width = area.width - 2 * table.getBorderWidth();
+				if (preferredSize.y > area.height) {
+					// Subtract the scrollbar width from the total column
+					// width
+					// if a vertical scrollbar will be required
+					Point vBarSize = table.getVerticalBar().getSize();
+					width -= vBarSize.x;
+				}
+
+				Point oldSize = table.getSize();
+				if (oldSize.x > width) {
+					// table is getting smaller so make the columns
+					// smaller first and then resize the table to
+					// match the client area width
+					column1.setWidth(width / 2);
+					column2.setWidth(width / 2);
+					table.setSize(width, area.height);
+				}
+				else {
+					// table is getting bigger so make the table
+					// bigger first and then make the columns wider
+					// to match the client area width
+					table.setSize(width, area.height);
+					column1.setWidth(width / 2);
+					column2.setWidth(width / 2);
+				}
+			}
+		});
+	}
+
+	public void createControl(Composite ancestor) {
+		Composite parent = new Composite(ancestor, SWT.NONE);
+		GridLayout layout = new GridLayout();
+		layout.numColumns = 2;
+		parent.setLayout(layout);
+
+		// create checkbox for user to use XML Template
+		fUseTemplateButton = new Button(parent, SWT.CHECK);
+		fUseTemplateButton.setText(XMLWizardsMessages.NewXMLTemplatesWizardPage_4);
+		GridData data = new GridData(SWT.FILL, SWT.FILL, true, false, 2, 1);
+		fUseTemplateButton.setLayoutData(data);
+		fUseTemplateButton.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				enableTemplates();
+			}
+		});
+
+		// create composite for Templates table
+		Composite innerParent = new Composite(parent, SWT.NONE);
+		GridLayout innerLayout = new GridLayout();
+		innerLayout.numColumns = 2;
+		innerLayout.marginHeight = 0;
+		innerLayout.marginWidth = 0;
+		innerParent.setLayout(innerLayout);
+		GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1);
+		innerParent.setLayoutData(gd);
+
+		Label label = new Label(innerParent, SWT.NONE);
+		label.setText(XMLWizardsMessages.NewXMLTemplatesWizardPage_7);
+		data = new GridData(SWT.FILL, SWT.FILL, true, false, 2, 1);
+		label.setLayoutData(data);
+
+		// create table that displays templates
+		Table table = new Table(innerParent, SWT.BORDER | SWT.FULL_SELECTION);
+
+		data = new GridData(GridData.FILL_BOTH);
+		data.widthHint = convertWidthInCharsToPixels(2);
+		data.heightHint = convertHeightInCharsToPixels(10);
+		data.horizontalSpan = 2;
+		table.setLayoutData(data);
+		table.setHeaderVisible(true);
+		table.setLinesVisible(true);
+		TableLayout tableLayout = new TableLayout();
+		table.setLayout(tableLayout);
+
+		TableColumn column1 = new TableColumn(table, SWT.NONE);
+		column1.setText(XMLWizardsMessages.NewXMLTemplatesWizardPage_2);
+
+		TableColumn column2 = new TableColumn(table, SWT.NONE);
+		column2.setText(XMLWizardsMessages.NewXMLTemplatesWizardPage_3);
+
+		fTableViewer = new TableViewer(table);
+		fTableViewer.setLabelProvider(new TemplateLabelProvider());
+		fTableViewer.setContentProvider(new TemplateContentProvider());
+
+		fTableViewer.setSorter(new ViewerSorter() {
+			public int compare(Viewer viewer, Object object1, Object object2) {
+				if ((object1 instanceof Template) && (object2 instanceof Template)) {
+					Template left = (Template) object1;
+					Template right = (Template) object2;
+					int result = left.getName().compareToIgnoreCase(right.getName());
+					if (result != 0) {
+						return result;
+					}
+					return left.getDescription().compareToIgnoreCase(right.getDescription());
+				}
+				return super.compare(viewer, object1, object2);
+			}
+
+			public boolean isSorterProperty(Object element, String property) {
+				return true;
+			}
+		});
+
+		fTableViewer.addSelectionChangedListener(new ISelectionChangedListener() {
+			public void selectionChanged(SelectionChangedEvent e) {
+				updateViewerInput();
+			}
+		});
+
+		// create viewer that displays currently selected template's contents
+		fPatternViewer = doCreateViewer(parent);
+
+		fTemplateStore = XMLUIPlugin.getDefault().getTemplateStore();
+		fTableViewer.setInput(fTemplateStore);
+
+		// Create linked text to just to templates preference page
+		Link link = new Link(parent, SWT.NONE);
+		link.setText(XMLWizardsMessages.NewXMLTemplatesWizardPage_6);
+		data = new GridData(SWT.END, SWT.FILL, true, false, 2, 1);
+		link.setLayoutData(data);
+		link.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				linkClicked();
+			}
+		});
+
+		configureTableResizing(innerParent, table, column1, column2);
+		loadLastSavedPreferences();
+
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(parent, IHelpContextIds.XML_NEWWIZARD_TEMPLATE_HELPID);
+		Dialog.applyDialogFont(parent);
+		setControl(parent);
+	}
+
+	/**
+	 * Creates, configures and returns a source viewer to present the template
+	 * pattern on the preference page. Clients may override to provide a
+	 * custom source viewer featuring e.g. syntax coloring.
+	 * 
+	 * @param parent
+	 *            the parent control
+	 * @return a configured source viewer
+	 */
+	private SourceViewer createViewer(Composite parent) {
+		SourceViewerConfiguration sourceViewerConfiguration = new StructuredTextViewerConfiguration() {
+			StructuredTextViewerConfiguration baseConfiguration = new StructuredTextViewerConfigurationXML();
+
+			public String[] getConfiguredContentTypes(ISourceViewer sourceViewer) {
+				return baseConfiguration.getConfiguredContentTypes(sourceViewer);
+			}
+
+			public LineStyleProvider[] getLineStyleProviders(ISourceViewer sourceViewer, String partitionType) {
+				return baseConfiguration.getLineStyleProviders(sourceViewer, partitionType);
+			}
+		};
+		SourceViewer viewer = new StructuredTextViewer(parent, null, null, false, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
+		viewer.getTextWidget().setFont(JFaceResources.getFont("org.eclipse.wst.sse.ui.textfont")); //$NON-NLS-1$
+		IStructuredModel scratchModel = StructuredModelManager.getModelManager().createUnManagedStructuredModelFor(ContentTypeIdForXML.ContentTypeID_XML);
+		IDocument document = scratchModel.getStructuredDocument();
+		viewer.configure(sourceViewerConfiguration);
+		viewer.setDocument(document);
+		return viewer;
+	}
+
+	private SourceViewer doCreateViewer(Composite parent) {
+		Label label = new Label(parent, SWT.NONE);
+		label.setText(XMLWizardsMessages.NewXMLTemplatesWizardPage_5);
+		GridData data = new GridData();
+		data.horizontalSpan = 2;
+		label.setLayoutData(data);
+
+		SourceViewer viewer = createViewer(parent);
+		viewer.setEditable(false);
+
+		Control control = viewer.getControl();
+		data = new GridData(GridData.FILL_BOTH);
+		data.horizontalSpan = 2;
+		data.heightHint = convertHeightInCharsToPixels(5);
+		// [261274] - source viewer was growing to fit the max line width of the template
+		data.widthHint = convertWidthInCharsToPixels(2);
+		control.setLayoutData(data);
+
+		return viewer;
+	}
+
+	/**
+	 * Enable/disable controls in page based on fUseTemplateButton's current
+	 * state.
+	 */
+	void enableTemplates() {
+		boolean enabled = fUseTemplateButton.getSelection();
+
+		if (!enabled) {
+			// save last selected template
+			Template template = getSelectedTemplate();
+			if (template != null) {
+				fLastSelectedTemplateName = template.getName();
+			}
+			else {
+				fLastSelectedTemplateName = ""; //$NON-NLS-1$
+			}
+
+			fTableViewer.setSelection(null);
+		}
+		else {
+			setSelectedTemplate(fLastSelectedTemplateName);
+		}
+
+		fTableViewer.getControl().setEnabled(enabled);
+		fPatternViewer.getControl().setEnabled(enabled);
+	}
+
+	/**
+	 * Return the template preference page id
+	 * 
+	 * @return
+	 */
+	private String getPreferencePageId() {
+		return "org.eclipse.wst.sse.ui.preferences.xml.templates"; //$NON-NLS-1$
+	}
+
+	/**
+	 * Get the currently selected template.
+	 * 
+	 * @return
+	 */
+	private Template getSelectedTemplate() {
+		Template template = null;
+		IStructuredSelection selection = (IStructuredSelection) fTableViewer.getSelection();
+
+		if (selection.size() == 1) {
+			template = (Template) selection.getFirstElement();
+		}
+		return template;
+	}
+
+	/**
+	 * Returns template string to insert.
+	 * 
+	 * @return String to insert or null if none is to be inserted
+	 */
+	String getTemplateString() {
+		String templateString = null;
+
+		Template template = getSelectedTemplate();
+		if (template != null) {
+			TemplateContextType contextType = XMLUIPlugin.getDefault().getTemplateContextRegistry().getContextType(TemplateContextTypeIdsXML.NEW);
+			IDocument document = new Document();
+			TemplateContext context = new DocumentTemplateContext(contextType, document, 0, 0);
+			try {
+				TemplateBuffer buffer = context.evaluate(template);
+				templateString = buffer.getString();
+			}
+			catch (Exception e) {
+				Logger.log(Logger.WARNING_DEBUG, "Could not create template for new xml", e); //$NON-NLS-1$
+			}
+		}
+
+		return templateString;
+	}
+
+	void linkClicked() {
+		String pageId = getPreferencePageId();
+		PreferenceDialog dialog = PreferencesUtil.createPreferenceDialogOn(getShell(), pageId, new String[]{pageId}, null);
+		dialog.open();
+		fTableViewer.refresh();
+	}
+
+	/**
+	 * Load the last template name used in New XML File wizard.
+	 */
+	private void loadLastSavedPreferences() {
+		fLastSelectedTemplateName = ""; //$NON-NLS-1$
+		boolean setSelection = false;
+		String templateName = XMLUIPlugin.getDefault().getPreferenceStore().getString(XMLUIPreferenceNames.NEW_FILE_TEMPLATE_NAME);
+		if (templateName == null || templateName.length() == 0) {
+			templateName = XMLUIPlugin.getDefault().getPreferenceStore().getString(XMLUIPreferenceNames.NEW_FILE_TEMPLATE_ID);
+			if (templateName != null && templateName.length() > 0) {
+				Template template = fTemplateStore.findTemplateById(templateName);
+				if (template != null) {
+					fLastSelectedTemplateName = template.getName();
+					setSelection = true;
+				}
+			}
+		}
+		else {
+			fLastSelectedTemplateName = templateName;
+			setSelection = true;
+		}
+		fUseTemplateButton.setSelection(setSelection);
+		enableTemplates();
+	}
+
+	/**
+	 * Save template name used for next call to New XML File wizard.
+	 */
+	void saveLastSavedPreferences() {
+		String templateName = ""; //$NON-NLS-1$
+
+		Template template = getSelectedTemplate();
+		if (template != null) {
+			templateName = template.getName();
+		}
+
+		XMLUIPlugin.getDefault().getPreferenceStore().setValue(XMLUIPreferenceNames.NEW_FILE_TEMPLATE_NAME, templateName);
+		XMLUIPlugin.getDefault().savePluginPreferences();
+	}
+
+	/**
+	 * Select a template in the table viewer given the template name. If
+	 * template name cannot be found or templateName is null, just select
+	 * first item in table. If no items in table select nothing.
+	 * 
+	 * @param templateName
+	 */
+	private void setSelectedTemplate(String templateName) {
+		Object template = null;
+
+		if ((templateName != null) && (templateName.length() > 0)) {
+			// pick the last used template
+			template = fTemplateStore.findTemplate(templateName, TemplateContextTypeIdsXML.NEW);
+		}
+
+		// no record of last used template so just pick first element
+		if (template == null) {
+			// just pick first element
+			template = fTableViewer.getElementAt(0);
+		}
+
+		if (template != null) {
+			IStructuredSelection selection = new StructuredSelection(template);
+			fTableViewer.setSelection(selection, true);
+		}
+	}
+
+	/**
+	 * Updates the pattern viewer.
+	 */
+	void updateViewerInput() {
+		Template template = getSelectedTemplate();
+		if (template != null) {
+			fPatternViewer.getDocument().set(template.getPattern());
+		}
+		else {
+			fPatternViewer.getDocument().set(""); //$NON-NLS-1$
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src-wizards/org/eclipse/wst/xml/ui/internal/wizards/NewXMLWizard.java b/bundles/org.eclipse.wst.xml.ui/src-wizards/org/eclipse/wst/xml/ui/internal/wizards/NewXMLWizard.java
new file mode 100644
index 0000000..bc77849
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-wizards/org/eclipse/wst/xml/ui/internal/wizards/NewXMLWizard.java
@@ -0,0 +1,967 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2008 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
+ *	   David Schneider, david.schneider@unisys.com - [142500] WTP properties pages fonts don't follow Eclipse preferences
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.wizards;
+
+import java.io.File;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Vector;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.util.Assert;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.wizard.IWizardPage;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.IEditorDescriptor;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.part.FileEditorInput;
+import org.eclipse.ui.part.PageBook;
+import org.eclipse.ui.wizards.newresource.BasicNewResourceWizard;
+import org.eclipse.wst.common.uriresolver.internal.util.URIHelper;
+import org.eclipse.wst.xml.core.internal.XMLCorePlugin;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalogEntry;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.DOMContentBuilder;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.NamespaceInfo;
+import org.eclipse.wst.xml.core.internal.preferences.XMLCorePreferenceNames;
+import org.eclipse.wst.xml.ui.internal.Logger;
+import org.eclipse.wst.xml.ui.internal.dialogs.NamespaceInfoErrorHelper;
+import org.eclipse.wst.xml.ui.internal.dialogs.SelectFileOrXMLCatalogIdPanel;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImageHelper;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImages;
+import org.eclipse.wst.xml.ui.internal.nsedit.CommonEditNamespacesDialog;
+
+import com.ibm.icu.text.Collator;
+
+public class NewXMLWizard extends NewModelWizard {
+	protected static final int CREATE_FROM_DTD = 0;
+	protected static final int CREATE_FROM_XSD = 1;
+	protected static final int CREATE_FROM_SCRATCH = 2;
+
+	protected static final String[] createFromRadioButtonLabel = {XMLWizardsMessages._UI_RADIO_XML_FROM_DTD, XMLWizardsMessages._UI_RADIO_XML_FROM_SCHEMA, XMLWizardsMessages._UI_RADIO_XML_FROM_SCRATCH};
+
+	protected static final String[] filePageFilterExtensions = {".xml"}; //$NON-NLS-1$
+	protected static final String[] browseXSDFilterExtensions = {".xsd"}; //$NON-NLS-1$
+	protected static final String[] browseDTDFilterExtensions = {".dtd"}; //$NON-NLS-1$
+	
+	protected static final int OPTIONAL_ELEMENT_DEPTH_LIMIT_DEFAULT_VALUE = 2;
+	
+	protected static final long XML_EDITOR_FILE_SIZE_LIMIT = 26214400; // 25 mb
+
+	protected NewFilePage newFilePage;
+	/**
+	 * @deprecated clients should not be allowed to change start page
+	 */
+	protected StartPage startPage;
+	private StartPage fCreateXMLFromWizardPage;
+	protected SelectGrammarFilePage selectGrammarFilePage;
+	protected SelectRootElementPage selectRootElementPage;
+
+	protected String cmDocumentErrorMessage;
+
+	protected NewXMLGenerator generator;
+	private NewXMLTemplatesWizardPage fNewXMLTemplatesWizardPage;
+
+
+	public NewXMLWizard() {
+		setWindowTitle(XMLWizardsMessages._UI_WIZARD_CREATE_NEW_TITLE);
+		ImageDescriptor descriptor = XMLEditorPluginImageHelper.getInstance().getImageDescriptor(XMLEditorPluginImages.IMG_WIZBAN_GENERATEXML);
+		setDefaultPageImageDescriptor(descriptor);
+		generator = new NewXMLGenerator();
+	}
+
+
+	public NewXMLWizard(IFile file, CMDocument cmDocument) {
+		this();
+
+		generator.setGrammarURI(URIHelper.getPlatformURI(file));
+		generator.setCMDocument(cmDocument);
+	}
+
+
+	public static void showDialog(Shell shell, IFile file, IStructuredSelection structuredSelection) {
+		String[] errorInfo = new String[2];
+		// (cs) the URI argument to createCMDocument needs to be a fully
+		// qualified URI
+		//
+		CMDocument cmDocument = NewXMLGenerator.createCMDocument(URIHelper.getPlatformURI(file), errorInfo);
+		if (errorInfo[0] == null) {
+			NewXMLWizard wizard = new NewXMLWizard(file, cmDocument);
+			wizard.init(PlatformUI.getWorkbench(), structuredSelection);
+			wizard.setNeedsProgressMonitor(true);
+			WizardDialog dialog = new WizardDialog(shell, wizard);
+			dialog.create();
+			dialog.getShell().setText(XMLWizardsMessages._UI_DIALOG_NEW_TITLE);
+			dialog.setBlockOnOpen(true);
+			dialog.open();
+		}
+		else {
+			MessageDialog.openInformation(shell, errorInfo[0], errorInfo[1]);
+		}
+	}
+
+	public void addPages() {
+		String grammarURI = generator.getGrammarURI();
+		
+		// new file page
+		newFilePage = new NewFilePage(fSelection);
+		newFilePage.setTitle(XMLWizardsMessages._UI_WIZARD_CREATE_XML_FILE_HEADING);
+		newFilePage.setDescription(XMLWizardsMessages._UI_WIZARD_CREATE_XML_FILE_EXPL);
+		newFilePage.defaultName = (grammarURI != null) ? URIHelper.removeFileExtension(URIHelper.getLastSegment(grammarURI)) : "NewFile"; //$NON-NLS-1$
+		Preferences preference = XMLCorePlugin.getDefault().getPluginPreferences();
+		String ext = preference.getString(XMLCorePreferenceNames.DEFAULT_EXTENSION);
+		newFilePage.defaultFileExtension = "." + ext; //$NON-NLS-1$
+		newFilePage.filterExtensions = filePageFilterExtensions;
+		addPage(newFilePage);
+
+		if (grammarURI == null) {
+			// create xml from page
+			fCreateXMLFromWizardPage = new StartPage("StartPage", createFromRadioButtonLabel) //$NON-NLS-1$
+			{
+				public void createControl(Composite parent) {
+					super.createControl(parent);
+				}
+
+				public void setVisible(boolean visible) {
+					super.setVisible(visible);
+					getRadioButtonAtIndex(getCreateMode()).setSelection(true);
+					getRadioButtonAtIndex(getCreateMode()).setFocus();
+
+					// Set the help context for each button
+					PlatformUI.getWorkbench().getHelpSystem().setHelp(fCreateXMLFromWizardPage.getRadioButtonAtIndex(0), IXMLWizardHelpContextIds.XML_NEWWIZARD_CREATEXML1_HELPID);
+					PlatformUI.getWorkbench().getHelpSystem().setHelp(fCreateXMLFromWizardPage.getRadioButtonAtIndex(1), IXMLWizardHelpContextIds.XML_NEWWIZARD_CREATEXML2_HELPID);
+					PlatformUI.getWorkbench().getHelpSystem().setHelp(fCreateXMLFromWizardPage.getRadioButtonAtIndex(2), IXMLWizardHelpContextIds.XML_NEWWIZARD_CREATEXML3_HELPID);
+				}
+			};
+
+
+			fCreateXMLFromWizardPage.setTitle(XMLWizardsMessages._UI_WIZARD_CREATE_XML_HEADING);
+			fCreateXMLFromWizardPage.setDescription(XMLWizardsMessages._UI_WIZARD_CREATE_XML_EXPL);
+			addPage(fCreateXMLFromWizardPage);
+		}
+
+		// selectGrammarFilePage
+		selectGrammarFilePage = new SelectGrammarFilePage();
+		addPage(selectGrammarFilePage);
+
+		// select root element page
+		selectRootElementPage = new SelectRootElementPage();
+		selectRootElementPage.setTitle(XMLWizardsMessages._UI_WIZARD_SELECT_ROOT_HEADING);
+		selectRootElementPage.setDescription(XMLWizardsMessages._UI_WIZARD_SELECT_ROOT_EXPL);
+		addPage(selectRootElementPage);
+
+		// from "scratch"
+		fNewXMLTemplatesWizardPage = new NewXMLTemplatesWizardPage();
+		addPage(fNewXMLTemplatesWizardPage);
+	}
+
+
+	public IWizardPage getStartingPage() {
+		WizardPage result = null;
+		if (startPage != null) {
+			result = startPage;
+		}
+		else {
+			result = newFilePage;
+		}
+		return result;
+	}
+
+
+	public int getCreateMode() {
+		String grammarURI = generator.getGrammarURI();
+
+		int result = CREATE_FROM_SCRATCH;
+		if (grammarURI != null) {
+			if (grammarURI.endsWith(".dtd")) //$NON-NLS-1$
+			{
+				result = CREATE_FROM_DTD;
+			}
+			else if (grammarURI.endsWith(".xsd")) //$NON-NLS-1$
+			{
+				result = CREATE_FROM_XSD;
+			}
+		}
+		else if (fCreateXMLFromWizardPage != null) {
+			int selectedIndex = fCreateXMLFromWizardPage.getSelectedRadioButtonIndex();
+			if (selectedIndex != -1) {
+				result = selectedIndex;
+			}
+		}
+		return result;
+	}
+
+
+	public IWizardPage getNextPage(IWizardPage currentPage) {
+		WizardPage nextPage = null;
+		if (currentPage == startPage) {
+			nextPage = newFilePage;
+		}
+		else if (currentPage == newFilePage) {
+			if (generator.getGrammarURI() == null)
+				nextPage = fCreateXMLFromWizardPage;
+			else
+				nextPage = selectRootElementPage;
+		}
+		else if (currentPage == fCreateXMLFromWizardPage) {
+			if (getCreateMode() == CREATE_FROM_SCRATCH) {
+				nextPage = fNewXMLTemplatesWizardPage;
+			}
+			else if (generator.getGrammarURI() == null) {
+				nextPage = selectGrammarFilePage;
+			}
+			else {
+				nextPage = selectRootElementPage;
+			}
+		}
+		else if (currentPage == selectGrammarFilePage) {
+			nextPage = selectRootElementPage;
+		}
+		return nextPage;
+	}
+
+
+	public boolean canFinish() {
+		boolean result = false;
+
+		IWizardPage currentPage = getContainer().getCurrentPage();
+		// can finish on: new file page, create from & template page if creating from scratch, select root element page
+		if ((currentPage == newFilePage && generator.getGrammarURI() == null) || (fCreateXMLFromWizardPage != null && fCreateXMLFromWizardPage.getSelectedRadioButtonIndex() == CREATE_FROM_SCRATCH) || (currentPage == selectRootElementPage)) {
+			result = currentPage.isPageComplete();
+		}
+		return result;
+	}
+
+
+	public boolean performFinish() {
+		boolean result = super.performFinish();
+		// save user options for next use
+		fNewXMLTemplatesWizardPage.saveLastSavedPreferences();
+		
+		String fileName = null;
+		try {
+
+			String[] namespaceErrors = generator.getNamespaceInfoErrors();
+			if (namespaceErrors != null) {
+				String title = namespaceErrors[0];
+				String message = namespaceErrors[1];
+				result = MessageDialog.openQuestion(getShell(), title, message);
+			}
+
+			if (result) {
+				fileName = newFilePage.getFileName();
+				if ((new Path(fileName)).getFileExtension() == null) {
+					newFilePage.setFileName(fileName.concat(newFilePage.defaultFileExtension));
+				}
+
+				final IFile newFile = newFilePage.createNewFile();
+				final String xmlFileName = newFile.getLocation().toOSString();
+				final String grammarFileName = fileName;
+
+				if (getContainer().getCurrentPage() == selectRootElementPage) {
+
+					int limit = selectRootElementPage.getOptionalElementDepthLimit();
+					generator.setOptionalElementDepthLimit(limit);
+					setNeedsProgressMonitor(true);
+					getContainer().run(true, false, new IRunnableWithProgress(){
+						public void run(IProgressMonitor progressMonitor) throws InvocationTargetException, InterruptedException {
+							progressMonitor.beginTask(XMLWizardsMessages._UI_WIZARD_GENERATING_XML_DOCUMENT, IProgressMonitor.UNKNOWN);
+							try {
+								generator.createXMLDocument(newFile, xmlFileName);
+							} catch (Exception exception) {
+								Logger.logException("Exception completing New XML wizard " + grammarFileName, exception); //$NON-NLS-1$
+							}
+							progressMonitor.done();
+						}
+					});
+				}
+				else {
+					// put template contents into file
+					String templateString = fNewXMLTemplatesWizardPage.getTemplateString();
+					generator.createTemplateXMLDocument(newFile, templateString);
+				}
+				newFile.refreshLocal(IResource.DEPTH_ONE, null);
+				IWorkbenchWindow workbenchWindow = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+				BasicNewResourceWizard.selectAndReveal(newFile, workbenchWindow);
+				openEditor(newFile);
+			}
+		}
+		catch (Exception e) {
+			Logger.logException("Exception completing New XML wizard " + fileName, e); //$NON-NLS-1$
+		}
+		return result;
+	}
+
+	public void openEditor(IFile file) {
+		long length = 0;
+		IPath location = file.getLocation();
+		if (location != null) {
+			File localFile = location.toFile();
+			length = localFile.length();
+		}
+		if(length < XML_EDITOR_FILE_SIZE_LIMIT) {
+			// Open editor on new file.
+			String editorId = null;
+			try {
+				IEditorDescriptor editor = PlatformUI.getWorkbench().getEditorRegistry().getDefaultEditor(file.getLocation().toOSString(), file.getContentDescription().getContentType());
+				if (editor != null) {
+					editorId = editor.getId();
+				}
+			}
+			catch (CoreException e1) {
+				// editor id could not be retrieved, so we can not open editor
+				return;
+			}
+			IWorkbenchWindow dw = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+			try {
+				if (dw != null) {
+					IWorkbenchPage page = dw.getActivePage();
+					if (page != null) {
+						page.openEditor(new FileEditorInput(file), editorId, true);
+					}
+				}
+			}
+			catch (PartInitException e) {
+				// editor can not open for some reason
+				return;
+			}
+		}
+	}
+
+
+	protected String getDefaultSystemId() {
+		String relativePath = "platform:/resource/" + newFilePage.getContainerFullPath().toString() + "/dummy"; //$NON-NLS-1$ //$NON-NLS-2$
+		return URIHelper.getRelativeURI(generator.getGrammarURI(), relativePath);
+	}
+
+
+	/**
+	 * SelectGrammarFilePage
+	 */
+	class SelectGrammarFilePage extends WizardPage {
+		protected SelectFileOrXMLCatalogIdPanel panel;
+
+		SelectGrammarFilePage() {
+			super("SelectGrammarFilePage"); //$NON-NLS-1$
+		}
+
+		public void createControl(Composite parent) {
+			Composite composite = new Composite(parent, SWT.NONE);
+			PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, IXMLWizardHelpContextIds.XML_NEWWIZARD_SELECTSOURCE_HELPID);
+			composite.setLayout(new GridLayout());
+			composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+			setControl(composite);
+
+			panel = new SelectFileOrXMLCatalogIdPanel(composite);
+			panel.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+			SelectFileOrXMLCatalogIdPanel.Listener listener = new SelectFileOrXMLCatalogIdPanel.Listener() {
+				public void completionStateChanged() {
+					updateErrorMessage();
+				}
+			};
+			panel.setListener(listener);
+			Dialog.applyDialogFont(parent);
+		}
+
+		public void setVisible(boolean visible) {
+			super.setVisible(visible);
+			if (visible) {
+				if (getCreateMode() == CREATE_FROM_DTD) {
+					setTitle(XMLWizardsMessages._UI_WIZARD_SELECT_DTD_FILE_TITLE);
+					setDescription(XMLWizardsMessages._UI_WIZARD_SELECT_DTD_FILE_DESC);
+					panel.setFilterExtensions(browseDTDFilterExtensions);
+				}
+				else {
+					setTitle(XMLWizardsMessages._UI_WIZARD_SELECT_XSD_FILE_TITLE);
+					setDescription(XMLWizardsMessages._UI_WIZARD_SELECT_XSD_FILE_DESC);
+					panel.setFilterExtensions(browseXSDFilterExtensions);
+				}
+				generator.setGrammarURI(null);
+				generator.setCMDocument(null);
+				cmDocumentErrorMessage = null;
+			}
+			panel.setVisibleHelper(visible);
+		}
+
+		public String getURI() {
+			String uri = panel.getXMLCatalogURI();
+			if (uri == null) {
+				IFile file = panel.getFile();
+				if (file != null) {
+					uri = URIHelper.getPlatformURI(file);
+				}
+			}
+			return uri;
+		}
+
+		public boolean isPageComplete() {
+			return (getURI() != null) && (getErrorMessage() == null);
+		}
+
+		public String getXMLCatalogId() {
+			return panel.getXMLCatalogId();
+		}
+
+		public ICatalogEntry getXMLCatalogEntry() {
+			return panel.getXMLCatalogEntry();
+		}
+
+		public String computeErrorMessage() {
+			String errorMessage = null;
+			String uri = getURI();
+			if (uri != null) {
+				if (!URIHelper.isReadableURI(uri, false)) {
+					errorMessage = XMLWizardsMessages._UI_LABEL_ERROR_CATALOG_ENTRY_INVALID;
+				}
+			}
+			return errorMessage;
+		}
+
+
+		public void updateErrorMessage() {
+			String errorMessage = computeErrorMessage();
+			setErrorMessage(errorMessage);
+			setPageComplete(isPageComplete());
+		}
+	}
+
+
+	/**
+	 * SelectRootElementPage
+	 */
+	class SelectRootElementPage extends WizardPage implements SelectionListener {
+		protected Combo combo;
+		protected Button[] radioButton;
+		protected PageBook pageBook;
+		protected XSDOptionsPanel xsdOptionsPanel;
+		protected DTDOptionsPanel dtdOptionsPanel;
+		protected Text limitOptionalElementDepthTextControl;
+		protected Button limitOptionalElementDepthCheckButtonControl;
+		 
+
+
+		SelectRootElementPage() {
+			super("SelectRootElementPage"); //$NON-NLS-1$
+		}
+
+		public void createControl(Composite parent) {
+			// container group
+			Composite containerGroup = new Composite(parent, SWT.NONE);
+			PlatformUI.getWorkbench().getHelpSystem().setHelp(containerGroup, IXMLWizardHelpContextIds.XML_NEWWIZARD_SELECTROOTELEMENT_HELPID);
+			containerGroup.setLayout(new GridLayout());
+			containerGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+			setControl(containerGroup);
+
+			// select root element
+			Label containerLabel = new Label(containerGroup, SWT.NONE);
+			containerLabel.setText(XMLWizardsMessages._UI_LABEL_ROOT_ELEMENT);
+			combo = new Combo(containerGroup, SWT.DROP_DOWN | SWT.READ_ONLY);
+			combo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+			combo.addSelectionListener(this);
+
+			// Options
+			{
+				Group group = new Group(containerGroup, SWT.NONE);
+				group.setText(XMLWizardsMessages._UI_WIZARD_CONTENT_OPTIONS);
+
+				GridLayout layout = new GridLayout();
+				layout.numColumns = 1;
+				layout.makeColumnsEqualWidth = true;
+				layout.marginWidth = 0;
+				group.setLayout(layout);
+				group.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+				radioButton = new Button[4];
+
+				radioButton[0] = new Button(group, SWT.CHECK);
+				radioButton[0].setText(XMLWizardsMessages._UI_WIZARD_CREATE_OPTIONAL_ATTRIBUTES);
+				radioButton[0].setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+				radioButton[0].setSelection(false);
+				PlatformUI.getWorkbench().getHelpSystem().setHelp(radioButton[0], IXMLWizardHelpContextIds.XML_NEWWIZARD_SELECTROOTELEMENT1_HELPID);
+
+				radioButton[1] = new Button(group, SWT.CHECK);
+				radioButton[1].setText(XMLWizardsMessages._UI_WIZARD_CREATE_OPTIONAL_ELEMENTS);
+				radioButton[1].setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+				radioButton[1].setSelection(false);
+				PlatformUI.getWorkbench().getHelpSystem().setHelp(radioButton[1], IXMLWizardHelpContextIds.XML_NEWWIZARD_SELECTROOTELEMENT2_HELPID);
+
+				radioButton[1].addSelectionListener(new SelectionAdapter(){
+					public void widgetSelected(SelectionEvent selectionEvent) {
+						boolean enabled = radioButton[1].getSelection();
+						limitOptionalElementDepthCheckButtonControl.setEnabled(enabled);
+						enabled = enabled && limitOptionalElementDepthCheckButtonControl.getSelection();
+						limitOptionalElementDepthTextControl.setEnabled(enabled);
+					}
+				});
+				Composite composite = new Composite(group, SWT.NONE);
+				GridLayout gridLayout = new GridLayout();
+				gridLayout.marginHeight = 0;
+				gridLayout.marginWidth = 0;
+				gridLayout.numColumns = 2;
+				gridLayout.marginLeft = 20;
+				composite.setLayout(gridLayout);
+				limitOptionalElementDepthCheckButtonControl = new Button(composite, SWT.CHECK);
+				limitOptionalElementDepthCheckButtonControl.setText(XMLWizardsMessages._UI_WIZARD_LIMIT_OPTIONAL_ELEMENT_DEPTH);
+				limitOptionalElementDepthCheckButtonControl.setEnabled(false);
+				limitOptionalElementDepthCheckButtonControl.setSelection(true);
+				limitOptionalElementDepthCheckButtonControl.addSelectionListener(new SelectionAdapter(){
+					public void widgetSelected(SelectionEvent selectionEvent) {
+						boolean enabled = limitOptionalElementDepthCheckButtonControl.getSelection();
+						limitOptionalElementDepthTextControl.setEnabled(enabled);
+					}
+				});
+				limitOptionalElementDepthTextControl = new Text(composite, SWT.BORDER);
+				limitOptionalElementDepthTextControl.setText(Integer.toString(OPTIONAL_ELEMENT_DEPTH_LIMIT_DEFAULT_VALUE));
+				limitOptionalElementDepthTextControl.setEnabled(false);
+				GridData gridaData = new GridData();
+				gridaData.widthHint = 25;
+				limitOptionalElementDepthTextControl.setLayoutData(gridaData);
+				limitOptionalElementDepthTextControl.addListener(SWT.Verify, new Listener() {
+					public void handleEvent(Event event) {
+						String string = event.text;
+						char[] chars = new char[string.length()];
+						string.getChars(0, chars.length, chars, 0);
+						for (int i = 0; i < chars.length; i++) {
+							if (!('0' <= chars[i] && chars[i] <= '9')) {
+								event.doit = false;
+								return;
+							}
+						}
+					}
+				});
+				
+				radioButton[2] = new Button(group, SWT.CHECK);
+				radioButton[2].setText(XMLWizardsMessages._UI_WIZARD_CREATE_FIRST_CHOICE);
+				radioButton[2].setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+				radioButton[2].setSelection(true);
+				PlatformUI.getWorkbench().getHelpSystem().setHelp(radioButton[2], IXMLWizardHelpContextIds.XML_NEWWIZARD_SELECTROOTELEMENT3_HELPID);
+
+				radioButton[3] = new Button(group, SWT.CHECK);
+				radioButton[3].setText(XMLWizardsMessages._UI_WIZARD_FILL_ELEMENTS_AND_ATTRIBUTES);
+				radioButton[3].setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+				radioButton[3].setSelection(true);
+				PlatformUI.getWorkbench().getHelpSystem().setHelp(radioButton[3], IXMLWizardHelpContextIds.XML_NEWWIZARD_SELECTROOTELEMENT4_HELPID);
+				/*
+				 * radioButton = new Button[2];
+				 * 
+				 * radioButton[0] = new Button(group, SWT.RADIO);
+				 * radioButton[0].setText(XMLWizardsMessages.getString("_UI_WIZARD_CREATE_REQUIRED"));
+				 * radioButton[0].setLayoutData(new
+				 * GridData(GridData.FILL_HORIZONTAL));
+				 * radioButton[0].setSelection(true);
+				 * WorkbenchHelp.setHelp(radioButton[0],
+				 * XMLBuilderContextIds.XMLC_CREATE_REQUIRED_ONLY);
+				 * 
+				 * radioButton[1] = new Button(group, SWT.RADIO);
+				 * radioButton[1].setText(XMLWizardsMessages.getString("_UI_WIZARD_CREATE_OPTIONAL"));
+				 * radioButton[1].setLayoutData(new
+				 * GridData(GridData.FILL_HORIZONTAL));
+				 * WorkbenchHelp.setHelp(radioButton[1],
+				 * XMLBuilderContextIds.XMLC_CREATE_REQUIRED_AND_OPTION);
+				 */
+			}
+
+			// add the grammar specific generation options
+			//
+			{
+				pageBook = new PageBook(containerGroup, SWT.NONE);
+				pageBook.setLayoutData(new GridData(GridData.FILL_BOTH));
+				xsdOptionsPanel = new XSDOptionsPanel(this, pageBook);
+				dtdOptionsPanel = new DTDOptionsPanel(this, pageBook);
+				pageBook.showPage(xsdOptionsPanel);
+			}
+		}
+
+		public void widgetSelected(SelectionEvent event) {
+			int index = combo.getSelectionIndex();
+			String rootElementName = (index != -1) ? combo.getItem(index) : null;
+			generator.setRootElementName(rootElementName);
+		}
+
+		public void widgetDefaultSelected(SelectionEvent event) {
+			// do nothing
+		}
+
+		public void setVisible(boolean visible) {
+			super.setVisible(visible);
+
+			if (visible) {
+				try {
+					if (generator.getGrammarURI() == null) {
+						generator.setGrammarURI(selectGrammarFilePage.getURI());
+						generator.setXMLCatalogEntry(selectGrammarFilePage.getXMLCatalogEntry());
+					}
+					Assert.isNotNull(generator.getGrammarURI());
+
+					if (generator.getCMDocument() == null) {
+						final String[] errorInfo = new String[2];
+						final CMDocument[] cmdocs = new CMDocument[1];
+						Runnable r = new Runnable() {
+							public void run() {
+								cmdocs[0] = NewXMLGenerator.createCMDocument(generator.getGrammarURI(), errorInfo);
+							}
+						};
+						org.eclipse.swt.custom.BusyIndicator.showWhile(Display.getCurrent(), r);
+
+						generator.setCMDocument(cmdocs[0]);
+						cmDocumentErrorMessage = errorInfo[1];
+					}
+
+					combo.removeAll();
+					if ((generator.getCMDocument() != null) && (cmDocumentErrorMessage == null)) {
+						CMNamedNodeMap nameNodeMap = generator.getCMDocument().getElements();
+						Vector nameNodeVector = new Vector();
+
+						for (int i = 0; i < nameNodeMap.getLength(); i++) {
+							CMElementDeclaration cmElementDeclaration = (CMElementDeclaration) nameNodeMap.item(i);
+							Object value = cmElementDeclaration.getProperty("Abstract"); //$NON-NLS-1$
+							if (value != Boolean.TRUE) {
+								nameNodeVector.add(cmElementDeclaration.getElementName());
+							}
+						}
+
+						Object[] nameNodeArray = nameNodeVector.toArray();
+						if (nameNodeArray.length > 0) {
+							Arrays.sort(nameNodeArray, Collator.getInstance());
+						}
+
+						String defaultRootName = (String) (generator.getCMDocument()).getProperty("http://org.eclipse.wst/cm/properties/defaultRootName"); //$NON-NLS-1$
+						int defaultRootIndex = -1;
+						for (int i = 0; i < nameNodeArray.length; i++) {
+							String elementName = (String) nameNodeArray[i];
+
+							combo.add(elementName);
+							if ((defaultRootName != null) && defaultRootName.equals(elementName)) {
+								defaultRootIndex = i;
+							}
+						}
+
+						if (nameNodeArray.length > 0) {
+							defaultRootIndex = defaultRootIndex != -1 ? defaultRootIndex : 0;
+							combo.select(defaultRootIndex);
+							generator.setRootElementName(combo.getItem(defaultRootIndex));
+						}
+					}
+
+					if (generator.getGrammarURI().endsWith("xsd")) //$NON-NLS-1$
+					{
+						pageBook.showPage(xsdOptionsPanel);
+						generator.setDefaultSystemId(getDefaultSystemId());
+						generator.createNamespaceInfoList();
+
+						// Provide default namespace prefix if none
+						for (int i = 0; i < generator.namespaceInfoList.size(); i++) {
+							NamespaceInfo nsinfo = (NamespaceInfo) generator.namespaceInfoList.get(i);
+							if (((nsinfo.prefix == null) || (nsinfo.prefix.trim().length() == 0)) && ((nsinfo.uri != null) && (nsinfo.uri.trim().length() != 0))) {
+								nsinfo.prefix = getDefaultPrefix(generator.namespaceInfoList);
+							}
+						}
+						xsdOptionsPanel.setNamespaceInfoList(generator.namespaceInfoList);
+					}
+					else if (generator.getGrammarURI().endsWith("dtd")) //$NON-NLS-1$
+					{
+						pageBook.showPage(dtdOptionsPanel);
+						dtdOptionsPanel.update();
+					}
+				}
+				catch (Exception e) {
+					// XMLBuilderPlugin.getPlugin().getMsgLogger().writeCurrentThread();
+				}
+
+				/*
+				 * String errorMessage = computeErrorMessage(); if
+				 * (errorMessage == null) super.setVisible(visible);
+				 */
+
+				updateErrorMessage();
+			}
+		}
+
+		private String getDefaultPrefix(List nsInfoList) {
+			String defaultPrefix = "p"; //$NON-NLS-1$
+			if (nsInfoList == null) {
+				return defaultPrefix;
+			}
+
+			Vector v = new Vector();
+			for (int i = 0; i < nsInfoList.size(); i++) {
+				NamespaceInfo nsinfo = (NamespaceInfo) nsInfoList.get(i);
+				if (nsinfo.prefix != null) {
+					v.addElement(nsinfo.prefix);
+				}
+			}
+
+			if (v.contains(defaultPrefix)) {
+				String s = defaultPrefix;
+				for (int j = 0; v.contains(s); j++) {
+					s = defaultPrefix + Integer.toString(j);
+				}
+				return s;
+			}
+			return defaultPrefix;
+		}
+		
+		public int getOptionalElementDepthLimit() {
+			int depth = -1;
+			if(radioButton[1].getSelection() && limitOptionalElementDepthCheckButtonControl.getSelection()) {
+				try {
+					depth = Integer.parseInt(limitOptionalElementDepthTextControl.getText());
+				} catch( Exception exception) {}
+			}
+			return depth;
+		}
+
+		public boolean isPageComplete() {
+			boolean complete = ((generator.getRootElementName() != null) && (generator.getRootElementName().length() > 0)) && (getErrorMessage() == null);
+
+			if (complete) {
+				/*
+				 * int buildPolicy = radioButton[0].getSelection() ?
+				 * DOMContentBuilder.BUILD_ONLY_REQUIRED_CONTENT :
+				 * DOMContentBuilder.BUILD_ALL_CONTENT;
+				 */
+				int buildPolicy = 0;
+				if (radioButton[0].getSelection()) {
+					buildPolicy = buildPolicy | DOMContentBuilder.BUILD_OPTIONAL_ATTRIBUTES;
+				}
+				if (radioButton[1].getSelection()) {
+					buildPolicy = buildPolicy | DOMContentBuilder.BUILD_OPTIONAL_ELEMENTS;
+				}
+				if (radioButton[2].getSelection()) {
+					buildPolicy = buildPolicy | DOMContentBuilder.BUILD_FIRST_CHOICE | DOMContentBuilder.BUILD_FIRST_SUBSTITUTION;
+				}
+				if (radioButton[3].getSelection()) {
+					buildPolicy = buildPolicy | DOMContentBuilder.BUILD_TEXT_NODES;
+				}
+
+				generator.setBuildPolicy(buildPolicy);
+			}
+
+			return complete;
+		}
+
+		public String computeErrorMessage() {
+			String errorMessage = null;
+
+			if (cmDocumentErrorMessage != null) {
+				errorMessage = cmDocumentErrorMessage;
+			}
+			else if ((generator.getRootElementName() == null) || (generator.getRootElementName().length() == 0)) {
+				errorMessage = XMLWizardsMessages._ERROR_ROOT_ELEMENT_MUST_BE_SPECIFIED;
+			}
+
+			return errorMessage;
+		}
+
+
+		public void updateErrorMessage() {
+			String errorMessage = computeErrorMessage();
+			if (errorMessage == null) {
+				if (xsdOptionsPanel.isVisible()) {
+
+					errorMessage = xsdOptionsPanel.computeErrorMessage();
+				}
+				else if (dtdOptionsPanel.isVisible()) {
+					errorMessage = dtdOptionsPanel.computeErrorMessage();
+				}
+			}
+			setErrorMessage(errorMessage);
+			setPageComplete(isPageComplete());
+		}
+	}
+
+	// //////////////End SelectRootElementPage
+
+
+
+	public static GridLayout createOptionsPanelLayout() {
+		GridLayout gridLayout = new GridLayout();
+		gridLayout.marginWidth = 0;
+		gridLayout.horizontalSpacing = 0;
+		return gridLayout;
+	}
+
+
+
+	/**
+	 * 
+	 */
+	class XSDOptionsPanel extends Composite {
+		protected String errorMessage = null;
+		protected SelectRootElementPage parentPage;
+		protected CommonEditNamespacesDialog editNamespaces;
+		private IPath currentPath = null;
+
+		public XSDOptionsPanel(SelectRootElementPage parentPage, Composite parent) {
+			super(parent, SWT.NONE);
+			this.parentPage = parentPage;
+
+			setLayout(createOptionsPanelLayout());
+			setLayoutData(new GridData(GridData.FILL_BOTH));
+		}
+		
+		private CommonEditNamespacesDialog getEditNamespaces() {
+			if (editNamespaces == null) {
+				Composite co = new Composite(this, SWT.NONE);
+				co.setLayout(new GridLayout());
+				String tableTitle = XMLWizardsMessages._UI_LABEL_NAMESPACE_INFORMATION;
+				editNamespaces = new CommonEditNamespacesDialog(co, null, tableTitle, true, true);
+				this.layout();
+			}
+			return editNamespaces;
+		}
+
+		public void setNamespaceInfoList(List list) {
+			CommonEditNamespacesDialog editDialog = getEditNamespaces();
+			
+		    if (newFilePage != null) {
+		      IPath newPath = newFilePage.getContainerFullPath();
+		      if (newPath != null) {
+		        if (!newPath.equals(currentPath)) {
+	                String resourceURI = "platform:/resource" + newPath.toString() + "/dummy"; //$NON-NLS-1$ //$NON-NLS-2$
+	                String resolvedPath = URIHelper.normalize(resourceURI, null, null);
+	                resolvedPath = URIHelper.removeProtocol(resolvedPath);
+	                
+	                currentPath = new Path(resolvedPath);
+	                editDialog.setResourcePath(currentPath);
+		        }
+		      }
+		    }
+		    editDialog.setNamespaceInfoList(list);
+		    editDialog.updateErrorMessage(list);
+		}
+
+		public void updateErrorMessage(List namespaceInfoList) {
+			NamespaceInfoErrorHelper helper = new NamespaceInfoErrorHelper();
+			errorMessage = helper.computeErrorMessage(namespaceInfoList, null);
+			parentPage.updateErrorMessage();
+		}
+
+
+		public String computeErrorMessage() {
+			return errorMessage;
+		}
+	}
+
+
+	/**
+	 * 
+	 */
+	public class DTDOptionsPanel extends Composite implements ModifyListener {
+		protected Group group;
+		protected Text systemIdField;
+		protected Text publicIdField;
+		protected SelectRootElementPage parentPage;
+
+		public DTDOptionsPanel(SelectRootElementPage parentPage, Composite parent) {
+			super(parent, SWT.NONE);
+			this.parentPage = parentPage;
+			setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+			setLayout(createOptionsPanelLayout());
+			Group group = new Group(this, SWT.NONE);
+			group.setText(XMLWizardsMessages._UI_LABEL_DOCTYPE_INFORMATION);
+
+			GridLayout layout = new GridLayout();
+			layout.numColumns = 2;
+			group.setLayout(layout);
+			group.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+			Label publicIdLabel = new Label(group, SWT.NONE);
+			publicIdLabel.setText(XMLWizardsMessages._UI_LABEL_PUBLIC_ID);
+			publicIdField = new Text(group, SWT.SINGLE | SWT.BORDER);
+			publicIdField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+			publicIdField.addModifyListener(this);
+			PlatformUI.getWorkbench().getHelpSystem().setHelp(publicIdField, IXMLWizardHelpContextIds.XML_NEWWIZARD_SELECTROOTELEMENT5_HELPID);
+
+			Label systemIdLabel = new Label(group, SWT.NONE);
+			systemIdLabel.setText(XMLWizardsMessages._UI_LABEL_SYSTEM_ID);
+			systemIdField = new Text(group, SWT.SINGLE | SWT.BORDER);
+			systemIdField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+			systemIdField.addModifyListener(this);
+			PlatformUI.getWorkbench().getHelpSystem().setHelp(systemIdField, IXMLWizardHelpContextIds.XML_NEWWIZARD_SELECTROOTELEMENT6_HELPID);
+		}
+
+		public void update() {
+			String thePublicId = null;
+			String theSystemId = null;
+			ICatalogEntry xmlCatalogEntry = generator.getXMLCatalogEntry();
+
+			if (xmlCatalogEntry != null) {
+				if (xmlCatalogEntry.getEntryType() == ICatalogEntry.ENTRY_TYPE_PUBLIC) {
+					thePublicId = xmlCatalogEntry.getKey();
+					theSystemId = xmlCatalogEntry.getAttributeValue(ICatalogEntry.ATTR_WEB_URL);
+					if (theSystemId == null) {
+						theSystemId = generator.getGrammarURI().startsWith("http:") ? generator.getGrammarURI() : URIHelper.getLastSegment(generator.getGrammarURI()); //$NON-NLS-1$
+					}
+				}
+				else {
+					theSystemId = xmlCatalogEntry.getKey();
+				}
+			}
+			else {
+				theSystemId = getDefaultSystemId();
+			}
+
+			publicIdField.setText(thePublicId != null ? thePublicId : ""); //$NON-NLS-1$
+			systemIdField.setText(theSystemId != null ? theSystemId : ""); //$NON-NLS-1$
+		}
+
+		public void modifyText(ModifyEvent e) {
+			generator.setSystemId(systemIdField.getText());
+			generator.setPublicId(publicIdField.getText());
+			parentPage.updateErrorMessage();
+		}
+
+		public String computeErrorMessage() {
+			return null;
+		}
+	}
+
+
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src-wizards/org/eclipse/wst/xml/ui/internal/wizards/XMLImportActionDelegate.java b/bundles/org.eclipse.wst.xml.ui/src-wizards/org/eclipse/wst/xml/ui/internal/wizards/XMLImportActionDelegate.java
new file mode 100644
index 0000000..4b923c4
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-wizards/org/eclipse/wst/xml/ui/internal/wizards/XMLImportActionDelegate.java
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.wizards;
+
+import java.util.Iterator;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.IActionDelegate;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+
+// TODO cs... rename this class NewXMLActionDelegate
+// we need to re-add pre-validation using the validation framework API's
+// since we also need to add validation to the 'New XML' case, this
+// prevalidation
+// function should really go into the NewWizard somewhere
+//
+public class XMLImportActionDelegate implements IActionDelegate {
+	/**
+	 * Checks the current selection and runs the separate browser to show the
+	 * content of the Readme file. This code shows how to launch separate
+	 * browsers that are not VA/Base desktop parts.
+	 * 
+	 * @param action
+	 *            the action that was performed
+	 */
+	public void run(IAction action) {
+		IWorkbenchWindow workbenchWindow = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+		ISelection selection = workbenchWindow.getSelectionService().getSelection();
+		Object selectedObject = getSelection(selection);
+
+		if ((selectedObject instanceof IFile) && (selection instanceof IStructuredSelection)) {
+			IFile file = (IFile) selectedObject;
+			IStructuredSelection structuredSelection = (IStructuredSelection) selection;
+			try {
+				NewXMLWizard.showDialog(workbenchWindow.getShell(), file, structuredSelection);
+			}
+			catch (Exception e) {
+				// XMLCorePlugin.getDefault().getLog().log();
+			}
+		}
+	}
+
+	/**
+	 * unused
+	 */
+	public void selectionChanged(IAction action, ISelection selection) {
+		// unused
+	}
+
+	// scammed from WindowUtility
+	//
+	public static Object getSelection(ISelection selection) {
+		if (selection == null) {
+			return null;
+		} // end of if ()
+
+		Object result = null;
+		if (selection instanceof IStructuredSelection) {
+			IStructuredSelection es = (IStructuredSelection) selection;
+			Iterator i = es.iterator();
+			if (i.hasNext()) {
+				result = i.next();
+			}
+		}
+		return result;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src-wizards/org/eclipse/wst/xml/ui/internal/wizards/XMLSchemaValidationChecker.java b/bundles/org.eclipse.wst.xml.ui/src-wizards/org/eclipse/wst/xml/ui/internal/wizards/XMLSchemaValidationChecker.java
new file mode 100644
index 0000000..e56a3d3
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-wizards/org/eclipse/wst/xml/ui/internal/wizards/XMLSchemaValidationChecker.java
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.wizards;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.wst.common.uriresolver.internal.util.URIHelper;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+public class XMLSchemaValidationChecker {
+	public boolean isValid(IFile ifile) {
+		String xsdFileName = ifile.getLocation().toString();
+		return isValid(xsdFileName);
+	}
+
+	/**
+	 * Should this be implemented as a Validator and simply called as such
+	 * with a reporter that only checks the results for severity = error? Or
+	 * should the Xerces requirement be broken using a plug-in extension?
+	 */
+
+	public boolean isValid(String xsdFileName) {
+		// DOMASBuilderImpl builder = new DOMASBuilderImpl();
+		// DOMErrorHandler errorHandler = new DOMErrorHandler();
+		// builder.setErrorHandler(errorHandler);
+		try {
+			// String uri =
+			URIHelper.getURIForFilePath(xsdFileName);
+			// ASModel model = builder.parseASURI(uri);
+			// if (errorHandler.hasError())
+			// return false;
+		}
+		catch (Exception e) // invalid schema
+		{
+			return false;
+		}
+
+		return true;
+	}
+
+	// inner class
+	class DOMErrorHandler implements ErrorHandler {
+		private boolean hasError = false;
+
+		public boolean hasError() {
+			return hasError;
+		}
+
+		public void error(SAXParseException err) {
+			hasError = true;
+		}
+
+		public void fatalError(SAXParseException exception) throws SAXException {
+			hasError = true;
+		}
+
+		public void warning(SAXParseException exception) throws SAXException {
+			// not an error
+		}
+	} // end DOMErrorHandlerImpl
+
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src-wizards/org/eclipse/wst/xml/ui/internal/wizards/XMLWizard.java b/bundles/org.eclipse.wst.xml.ui/src-wizards/org/eclipse/wst/xml/ui/internal/wizards/XMLWizard.java
new file mode 100644
index 0000000..ffea5d4
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-wizards/org/eclipse/wst/xml/ui/internal/wizards/XMLWizard.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.wizards;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jface.resource.ImageDescriptor;
+
+public class XMLWizard {
+	protected static XMLWizard instance = new XMLWizard();
+
+	public synchronized static XMLWizard getInstance() {
+		return instance;
+	}
+
+	public XMLWizard() {
+		instance = this;
+
+	}
+
+	public ImageDescriptor getImageDescriptor(String name) {
+		try {
+			URL url = new URL(Platform.getBundle("org.eclipse.wst.xml.ui").getEntry("/"), name); //$NON-NLS-1$ //$NON-NLS-2$
+			return ImageDescriptor.createFromURL(url);
+		}
+		catch (MalformedURLException e) {
+			return ImageDescriptor.getMissingImageDescriptor();
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src-wizards/org/eclipse/wst/xml/ui/internal/wizards/XMLWizardsMessages.java b/bundles/org.eclipse.wst.xml.ui/src-wizards/org/eclipse/wst/xml/ui/internal/wizards/XMLWizardsMessages.java
new file mode 100644
index 0000000..61e8947
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-wizards/org/eclipse/wst/xml/ui/internal/wizards/XMLWizardsMessages.java
@@ -0,0 +1,101 @@
+/**********************************************************************
+ * Copyright (c) 2005, 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 - Initial API and implementation
+ * David Carver/STAR Standard - d_a_carver@yahoo.com - bug 192568
+ **********************************************************************/
+package org.eclipse.wst.xml.ui.internal.wizards;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Strings used by XML Wizards
+ * 
+ * @plannedfor 1.0
+ */
+public class XMLWizardsMessages extends NLS {
+	private static final String BUNDLE_NAME = "org.eclipse.wst.xml.ui.internal.wizards.wizardResource";//$NON-NLS-1$
+
+	public static String _UI_DIALOG_NEW_TITLE;
+	public static String _UI_DIALOG_TITLE_INVALID_GRAMMAR;
+	public static String _UI_DIALOG_MESSAGE_INVALID_GRAMMAR;
+	public static String _UI_WIZARD_CREATE_NEW_TITLE;
+	public static String _UI_RADIO_XML_FROM_DTD;
+	public static String _UI_RADIO_XML_FROM_SCHEMA;
+	public static String _UI_RADIO_XML_FROM_SCRATCH;
+	public static String _UI_WIZARD_CREATE_XML_HEADING;
+	public static String _UI_WIZARD_CREATE_XML_EXPL;
+	public static String _UI_WIZARD_CREATE_XML_FILE_HEADING;
+	public static String _UI_WIZARD_CREATE_XML_FILE_EXPL;
+	public static String _UI_WIZARD_SELECT_DTD_FILE_DESC;
+	public static String _UI_WIZARD_SELECT_DTD_FILE_TITLE;
+	public static String _UI_WIZARD_SELECT_XSD_FILE_DESC;
+	public static String _UI_WIZARD_SELECT_XSD_FILE_TITLE;
+	public static String _UI_WIZARD_SELECT_ROOT_HEADING;
+	public static String _UI_WIZARD_SELECT_ROOT_EXPL;
+	public static String _UI_LABEL_ROOT_ELEMENT;
+	public static String _UI_WARNING_TITLE_NO_ROOT_ELEMENTS;
+	public static String _UI_WARNING_MSG_NO_ROOT_ELEMENTS;
+	public static String _UI_LABEL_NO_LOCATION_HINT;
+	public static String _UI_WARNING_MSG_NO_LOCATION_HINT_1;
+	public static String _UI_WARNING_MSG_NO_LOCATION_HINT_2;
+	public static String _UI_WARNING_MSG_NO_LOCATION_HINT_3;
+	public static String _UI_WIZARD_CONTENT_OPTIONS;
+	public static String _UI_WIZARD_CREATE_REQUIRED;// commented out
+	public static String _UI_WIZARD_CREATE_OPTIONAL;// commented out
+	public static String _UI_WIZARD_CREATE_OPTIONAL_ATTRIBUTES;
+	public static String _UI_WIZARD_CREATE_OPTIONAL_ELEMENTS;
+	public static String _UI_WIZARD_CREATE_FIRST_CHOICE;
+	public static String _UI_WIZARD_FILL_ELEMENTS_AND_ATTRIBUTES;
+	public static String _UI_LABEL_DOCTYPE_INFORMATION;
+	public static String _UI_LABEL_SYSTEM_ID;
+	public static String _UI_LABEL_PUBLIC_ID;
+	public static String _UI_WARNING_URI_NOT_FOUND_COLON;
+	public static String _UI_INVALID_GRAMMAR_ERROR;
+	public static String _ERROR_BAD_FILENAME_EXTENSION;
+	public static String _ERROR_FILE_ALREADY_EXISTS;
+	public static String _ERROR_ROOT_ELEMENT_MUST_BE_SPECIFIED;
+	public static String _UI_LABEL_ERROR_SCHEMA_INVALID_INFO;
+	public static String _UI_LABEL_ERROR_DTD_INVALID_INFO;
+	public static String _UI_LABEL_ERROR_CATALOG_ENTRY_INVALID;
+	public static String _UI_LABEL_NAMESPACE_INFORMATION;
+	public static String Validation_Plugins_Unavailable;
+	public static String Validation_cannot_be_performed;
+	public static String ExampleProjectCreationOperation_op_desc;
+	public static String ExampleProjectCreationOperation_op_desc_proj;
+	public static String ExampleProjectCreationWizard_title;
+	public static String ExampleProjectCreationWizard_op_error_title;
+	public static String ExampleProjectCreationWizard_op_error_message;
+	public static String ExampleProjectCreationWizard_overwritequery_title;
+	public static String ExampleProjectCreationWizard_overwritequery_message;
+	public static String ExampleProjectCreationWizardPage_error_alreadyexists;
+
+	public static String NewXMLTemplatesWizardPage_0;
+	public static String NewXMLTemplatesWizardPage_1;
+	public static String NewXMLTemplatesWizardPage_2;
+	public static String NewXMLTemplatesWizardPage_3;
+	public static String NewXMLTemplatesWizardPage_4;
+	public static String NewXMLTemplatesWizardPage_5;
+	public static String NewXMLTemplatesWizardPage_6;
+	public static String NewXMLTemplatesWizardPage_7;
+	
+	public static String _UI_DIALOG_XMLCATALOG_IMPORT_TITLE;
+	public static String _UI_DIALOG_XMLCATALOG_EXPORT_TITLE;
+	public static String _UI_DIALOG_XMLCATALOG_EXPORT_DESCRIPTION;
+    public static String _UI_DIALOG_XMLCATALOG_IMPORT_DESCRIPTION;
+    public static String _UI_WIZARD_LIMIT_OPTIONAL_ELEMENT_DEPTH;
+    public static String _UI_WIZARD_GENERATING_XML_DOCUMENT;
+    
+	static {
+		// load message values from bundle file
+		NLS.initializeMessages(BUNDLE_NAME, XMLWizardsMessages.class);
+	}
+
+	private XMLWizardsMessages() {
+		// cannot create new instance
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src-wizards/org/eclipse/wst/xml/ui/internal/wizards/wizardResource.properties b/bundles/org.eclipse.wst.xml.ui/src-wizards/org/eclipse/wst/xml/ui/internal/wizards/wizardResource.properties
new file mode 100644
index 0000000..06a2a6f
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-wizards/org/eclipse/wst/xml/ui/internal/wizards/wizardResource.properties
@@ -0,0 +1,102 @@
+###############################################################################
+# Copyright (c) 2001, 2009 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
+#     David Carver/STAR Standard - d_a_carver@yahoo.com - bug 192568
+###############################################################################
+! Properties file for component: XML Tools -  New XML Wizard
+! Packaged for translation in:  xml.zip
+
+!XMLImportActionDelegate
+_UI_DIALOG_NEW_TITLE        = New XML File
+_UI_DIALOG_TITLE_INVALID_GRAMMAR = Invalid Grammar
+_UI_DIALOG_MESSAGE_INVALID_GRAMMAR = The grammar file contains errors. If you proceed, an incorrect result file will be generated. Do you want to continue?
+
+!NewXMLBWizard
+_UI_WIZARD_CREATE_NEW_TITLE           = New XML File
+_UI_RADIO_XML_FROM_DTD                = Create XML file from a &DTD file
+_UI_RADIO_XML_FROM_SCHEMA             = Create XML file from an &XML schema file
+_UI_RADIO_XML_FROM_SCRATCH            = Create XML file from an XML &template
+_UI_WIZARD_CREATE_XML_HEADING         = Create XML File From
+_UI_WIZARD_CREATE_XML_EXPL            = Select how you would like to create your XML file.
+_UI_WIZARD_CREATE_XML_FILE_HEADING    = XML
+_UI_WIZARD_CREATE_XML_FILE_EXPL       = Create a new XML file.
+_UI_WIZARD_SELECT_DTD_FILE_DESC       = Select the DTD file to create the XML file.
+_UI_WIZARD_SELECT_DTD_FILE_TITLE      = Select DTD File
+_UI_WIZARD_SELECT_XSD_FILE_DESC       = Select the schema file to create the XML file.
+_UI_WIZARD_SELECT_XSD_FILE_TITLE      = Select XML Schema File
+_UI_WIZARD_SELECT_ROOT_HEADING        = Select Root Element
+_UI_WIZARD_SELECT_ROOT_EXPL           = Select the root element of the XML file.
+_UI_LABEL_ROOT_ELEMENT                = Root element:
+_UI_WARNING_TITLE_NO_ROOT_ELEMENTS    = No Root Elements
+_UI_WARNING_MSG_NO_ROOT_ELEMENTS      = No root element exists since the schema provided has no global elements.
+_UI_LABEL_NO_LOCATION_HINT            = Unspecified Namespace Location
+_UI_WARNING_MSG_NO_LOCATION_HINT_1    = You have not specified a location hint for one or more namespace entries.
+_UI_WARNING_MSG_NO_LOCATION_HINT_2    = Elements from these namespaces will not be generated. This may lead to an invalid generated document.
+_UI_WARNING_MSG_NO_LOCATION_HINT_3    = Click Yes to continue, Click No to go back and specify the location hints.
+_UI_WIZARD_CONTENT_OPTIONS            = Content options
+
+_UI_WIZARD_CREATE_REQUIRED            = &Create required content only
+_UI_WIZARD_CREATE_OPTIONAL            = Create required and &optional content
+_UI_WIZARD_LIMIT_OPTIONAL_ELEMENT_DEPTH = L&imit optional element depth to:
+_UI_WIZARD_GENERATING_XML_DOCUMENT	  = Generating XML document...
+
+_UI_WIZARD_CREATE_OPTIONAL_ATTRIBUTES = Create optional &attributes
+_UI_WIZARD_CREATE_OPTIONAL_ELEMENTS   = Create optional e&lements
+_UI_WIZARD_CREATE_FIRST_CHOICE        = Create first choice of required &choice
+_UI_WIZARD_FILL_ELEMENTS_AND_ATTRIBUTES = Fill elements and attributes with &data
+
+_UI_LABEL_DOCTYPE_INFORMATION         = Document type information
+_UI_LABEL_SYSTEM_ID                   = &System ID:
+_UI_LABEL_PUBLIC_ID                   = &Public ID:
+
+_UI_WARNING_URI_NOT_FOUND_COLON       = The specified resource cannot be located :
+
+!NewModelWizard
+_UI_INVALID_GRAMMAR_ERROR             = Invalid Grammar
+
+!NewModelWizard
+_ERROR_BAD_FILENAME_EXTENSION         = The file name must end in one of the following extensions {0}.
+_ERROR_FILE_ALREADY_EXISTS            = The same file already exists.
+_ERROR_ROOT_ELEMENT_MUST_BE_SPECIFIED = A root element must be specified.
+_UI_LABEL_ERROR_SCHEMA_INVALID_INFO   = The schema file contains errors. Open it in the XML schema editor for details.
+_UI_LABEL_ERROR_DTD_INVALID_INFO      = The DTD file contains errors. Open it in the DTD editor for details.
+
+_UI_LABEL_ERROR_CATALOG_ENTRY_INVALID = The selected catalog entry specifies a URI that can not be located.
+
+_UI_LABEL_NAMESPACE_INFORMATION=Namespace Information
+
+Validation_Plugins_Unavailable=Validation Plugins Unavailable
+Validation_cannot_be_performed=Validation cannot be performed because the validation plugins were disabled or not found.  The generated file may be invalid.  Do you wish to continue?
+
+!ImportXMLCatalogWizard
+_UI_DIALOG_XMLCATALOG_IMPORT_TITLE    = Import XML Catalog
+_UI_DIALOG_XMLCATALOG_IMPORT_DESCRIPTION = Import all entries from an existing XML Catalog into the User Catalog.
+
+!ExportXMLCatalogWizard
+_UI_DIALOG_XMLCATALOG_EXPORT_TITLE    = Export Existing XML Catalog
+_UI_DIALOG_XMLCATALOG_EXPORT_DESCRIPTION = Export all existing User Catalog entries.
+#
+# ExampleProject
+ExampleProjectCreationOperation_op_desc=Creating example projects...
+ExampleProjectCreationOperation_op_desc_proj=Configuring project...
+ExampleProjectCreationWizard_title=New Example Project
+ExampleProjectCreationWizard_op_error_title=Project Creation Failed
+ExampleProjectCreationWizard_op_error_message=Project could not be created.
+ExampleProjectCreationWizard_overwritequery_title=Overwrite
+ExampleProjectCreationWizard_overwritequery_message=Do you want to overwrite {0}?
+ExampleProjectCreationWizardPage_error_alreadyexists=Project already exists.
+
+NewXMLTemplatesWizardPage_0=Select XML Template
+NewXMLTemplatesWizardPage_1=Select a template as initial content in the XML page.
+NewXMLTemplatesWizardPage_2=Name
+NewXMLTemplatesWizardPage_3=Description
+NewXMLTemplatesWizardPage_4=&Use XML Template
+NewXMLTemplatesWizardPage_5=&Preview:
+NewXMLTemplatesWizardPage_6=Templates are 'New XML' templates found in the <a>XML Templates</a> preference page.
+NewXMLTemplatesWizardPage_7=&Templates:
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/StructuredTextViewerConfigurationXML.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/StructuredTextViewerConfigurationXML.java
new file mode 100644
index 0000000..2c11ee3
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/StructuredTextViewerConfigurationXML.java
@@ -0,0 +1,226 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Vector;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.jface.text.IAutoEditStrategy;
+import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
+import org.eclipse.jface.text.formatter.IContentFormatter;
+import org.eclipse.jface.text.formatter.MultiPassContentFormatter;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.wst.sse.core.text.IStructuredPartitions;
+import org.eclipse.wst.sse.ui.StructuredTextViewerConfiguration;
+import org.eclipse.wst.sse.ui.internal.provisional.style.LineStyleProvider;
+import org.eclipse.wst.xml.core.internal.XMLCorePlugin;
+import org.eclipse.wst.xml.core.internal.preferences.XMLCorePreferenceNames;
+import org.eclipse.wst.xml.core.internal.provisional.contenttype.ContentTypeIdForXML;
+import org.eclipse.wst.xml.core.internal.text.rules.StructuredTextPartitionerForXML;
+import org.eclipse.wst.xml.core.text.IXMLPartitions;
+import org.eclipse.wst.xml.ui.internal.XMLFormattingStrategy;
+import org.eclipse.wst.xml.ui.internal.autoedit.AutoEditStrategyForTabs;
+import org.eclipse.wst.xml.ui.internal.contentassist.XMLStructuredContentAssistProcessor;
+import org.eclipse.wst.xml.ui.internal.contentoutline.JFaceNodeLabelProvider;
+import org.eclipse.wst.xml.ui.internal.style.LineStyleProviderForXML;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Node;
+
+/**
+ * Configuration for a source viewer which shows XML content.
+ * <p>
+ * Clients can subclass and override just those methods which must be specific
+ * to their needs.
+ * </p>
+ * 
+ * @see org.eclipse.wst.sse.ui.StructuredTextViewerConfiguration
+ * @since 1.0
+ */
+public class StructuredTextViewerConfigurationXML extends StructuredTextViewerConfiguration {
+	/*
+	 * One instance per configuration because not sourceviewer-specific and
+	 * it's a String array
+	 */
+	private String[] fConfiguredContentTypes;
+	/*
+	 * One instance per configuration
+	 */
+	private LineStyleProvider fLineStyleProviderForXML;
+	private ILabelProvider fStatusLineLabelProvider;
+
+	/**
+	 * Create new instance of StructuredTextViewerConfigurationXML
+	 */
+	public StructuredTextViewerConfigurationXML() {
+		// Must have empty constructor to createExecutableExtension
+		super();
+	}
+
+	public IAutoEditStrategy[] getAutoEditStrategies(ISourceViewer sourceViewer, String contentType) {
+		List allStrategies = new ArrayList(0);
+
+		IAutoEditStrategy[] superStrategies = super.getAutoEditStrategies(sourceViewer, contentType);
+		for (int i = 0; i < superStrategies.length; i++) {
+			allStrategies.add(superStrategies[i]);
+		}
+
+		// be sure this is last, so it can modify any results form previous
+		// commands that might on on same partiion type.
+		// add auto edit strategy that handles when tab key is pressed
+		allStrategies.add(new AutoEditStrategyForTabs());
+
+		return (IAutoEditStrategy[]) allStrategies.toArray(new IAutoEditStrategy[allStrategies.size()]);
+	}
+
+	public String[] getConfiguredContentTypes(ISourceViewer sourceViewer) {
+
+		if (fConfiguredContentTypes == null) {
+			String[] xmlTypes = StructuredTextPartitionerForXML.getConfiguredContentTypes();
+			fConfiguredContentTypes = new String[xmlTypes.length + 2];
+			fConfiguredContentTypes[0] = IStructuredPartitions.DEFAULT_PARTITION;
+			fConfiguredContentTypes[1] = IStructuredPartitions.UNKNOWN_PARTITION;
+			int index = 0;
+			System.arraycopy(xmlTypes, 0, fConfiguredContentTypes, index += 2, xmlTypes.length);
+		}
+		return fConfiguredContentTypes;
+	}
+	
+	/**
+	 * @see org.eclipse.wst.sse.ui.StructuredTextViewerConfiguration#getContentAssistProcessors(
+	 * 	org.eclipse.jface.text.source.ISourceViewer, java.lang.String)
+	 */
+	protected IContentAssistProcessor[] getContentAssistProcessors(ISourceViewer sourceViewer, String partitionType) {
+		IContentAssistProcessor processor = new XMLStructuredContentAssistProcessor(
+				this.getContentAssistant(), partitionType, sourceViewer);
+		return new IContentAssistProcessor[]{processor};
+	}
+
+	public IContentFormatter getContentFormatter(ISourceViewer sourceViewer) {
+		IContentFormatter formatter = super.getContentFormatter(sourceViewer);
+		// super was unable to create a formatter, probably because
+		// sourceViewer does not have document set yet, so just create a
+		// generic one
+		if (!(formatter instanceof MultiPassContentFormatter))
+			formatter = new MultiPassContentFormatter(getConfiguredDocumentPartitioning(sourceViewer), IXMLPartitions.XML_DEFAULT);
+		((MultiPassContentFormatter) formatter).setMasterStrategy(new XMLFormattingStrategy());		
+//		((MultiPassContentFormatter) formatter).setMasterStrategy(new StructuredFormattingStrategy(new FormatProcessorXML()));
+
+		return formatter;
+	}
+
+	public String[] getIndentPrefixes(ISourceViewer sourceViewer, String contentType) {
+		Vector vector = new Vector();
+
+		// prefix[0] is either '\t' or ' ' x tabWidth, depending on preference
+		Preferences preferences = XMLCorePlugin.getDefault().getPluginPreferences();
+		int indentationWidth = preferences.getInt(XMLCorePreferenceNames.INDENTATION_SIZE);
+		String indentCharPref = preferences.getString(XMLCorePreferenceNames.INDENTATION_CHAR);
+		boolean useSpaces = XMLCorePreferenceNames.SPACE.equals(indentCharPref);
+
+		for (int i = 0; i <= indentationWidth; i++) {
+			StringBuffer prefix = new StringBuffer();
+			boolean appendTab = false;
+
+			if (useSpaces) {
+				for (int j = 0; j + i < indentationWidth; j++) {
+					prefix.append(' ');
+				}
+
+				if (i != 0) {
+					appendTab = true;
+				}
+			}
+			else {
+				for (int j = 0; j < i; j++) {
+					prefix.append(' ');
+				}
+
+				if (i != indentationWidth) {
+					appendTab = true;
+				}
+			}
+
+			if (appendTab) {
+				prefix.append('\t');
+				vector.add(prefix.toString());
+				// remove the tab so that indentation - tab is also an indent
+				// prefix
+				prefix.deleteCharAt(prefix.length() - 1);
+			}
+			vector.add(prefix.toString());
+		}
+
+		vector.add(""); //$NON-NLS-1$
+
+		return (String[]) vector.toArray(new String[vector.size()]);
+	}
+
+	public LineStyleProvider[] getLineStyleProviders(ISourceViewer sourceViewer, String partitionType) {
+		LineStyleProvider[] providers = null;
+
+		if ((partitionType == IXMLPartitions.XML_DEFAULT) || (partitionType == IXMLPartitions.XML_CDATA) || (partitionType == IXMLPartitions.XML_COMMENT) || (partitionType == IXMLPartitions.XML_DECLARATION) || (partitionType == IXMLPartitions.XML_PI)) {
+			providers = new LineStyleProvider[]{getLineStyleProviderForXML()};
+		}
+
+		return providers;
+	}
+
+	private LineStyleProvider getLineStyleProviderForXML() {
+		if (fLineStyleProviderForXML == null) {
+			fLineStyleProviderForXML = new LineStyleProviderForXML();
+		}
+		return fLineStyleProviderForXML;
+	}
+
+	public ILabelProvider getStatusLineLabelProvider(ISourceViewer sourceViewer) {
+		if (fStatusLineLabelProvider == null) {
+			fStatusLineLabelProvider = new JFaceNodeLabelProvider() {
+				public String getText(Object element) {
+					if (element == null)
+						return null;
+
+					StringBuffer s = new StringBuffer();
+					Node node = (Node) element;
+					while (node != null) {
+						if (node.getNodeType() != Node.DOCUMENT_NODE) {
+							s.insert(0, super.getText(node));
+						}
+
+						if (node.getNodeType() == Node.ATTRIBUTE_NODE)
+							node = ((Attr) node).getOwnerElement();
+						else
+							node = node.getParentNode();
+					
+						if (node != null && node.getNodeType() != Node.DOCUMENT_NODE) {
+							s.insert(0, IPath.SEPARATOR);
+						}
+					}
+					return s.toString();
+				}
+
+			};
+		}
+		return fStatusLineLabelProvider;
+	}
+
+	protected Map getHyperlinkDetectorTargets(ISourceViewer sourceViewer) {
+		Map targets = super.getHyperlinkDetectorTargets(sourceViewer);
+		targets.put(ContentTypeIdForXML.ContentTypeID_XML, null);
+		return targets;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/DOMObserver.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/DOMObserver.java
new file mode 100644
index 0000000..4b90cfb
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/DOMObserver.java
@@ -0,0 +1,237 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2009 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal;
+
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapter;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.ui.internal.SSEUIMessages;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.CMDocumentManager;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelqueryimpl.CMDocumentLoader;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelqueryimpl.InferredGrammarBuildingCMDocumentLoader;
+import org.eclipse.wst.xml.core.internal.modelquery.ModelQueryUtil;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+/**
+ * This class is used to observe changes in the DOM and perform
+ * occasional'scans' to deduce information. We use a delay timer mechanism to
+ * ensure scans are made every couple of seconds to avoid performance
+ * problems. Currently this class is used to keep track of referenced grammar
+ * uri's within the document ensure that they are loaded by the
+ * CMDocumentManager. We might want to generalize this class to perform other
+ * suplimental information gathering that is suitable for 'time delayed'
+ * computation (error hints etc.).
+ */
+// TODO: Where should this class go?
+public class DOMObserver {
+
+
+	// An abstract adapter that ensures that the children of a new Node are
+	// also adapted
+	//
+	abstract class DocumentAdapter implements INodeAdapter {
+		public DocumentAdapter() {
+		}
+
+		public void connect(Document document) {
+			((INodeNotifier) document).addAdapter(this);
+			adapt(document.getDocumentElement());
+		}
+
+		public void dicconnect(Document document) {
+			((INodeNotifier) document).removeAdapter(this);
+		}
+
+		public void adapt(Element element) {
+			if (element != null) {
+				if (((INodeNotifier) element).getExistingAdapter(this) == null) {
+					((INodeNotifier) element).addAdapter(this);
+
+					for (Node child = element.getFirstChild(); child != null; child = child.getNextSibling()) {
+						if (child.getNodeType() == Node.ELEMENT_NODE) {
+							adapt((Element) child);
+						}
+					}
+				}
+			}
+		}
+
+		public boolean isAdapterForType(Object type) {
+			return type == this;
+		}
+
+		abstract public void notifyChanged(INodeNotifier notifier, int eventType, Object feature, Object oldValue, Object newValue, int index);
+	}
+
+	/**
+	 * This class listens to the changes in the CMDocument and triggers a
+	 * CMDocument load
+	 */
+	class MyDocumentAdapter extends DocumentAdapter {
+
+		public void notifyChanged(INodeNotifier notifier, int eventType, Object feature, Object oldValue, Object newValue, int index) {
+			switch (eventType) {
+				case INodeNotifier.ADD : {
+					if (newValue instanceof Element) {
+						// System.out.println("ADD (to " +
+						// ((Node)notifier).getNodeName() + ") " +
+						// ((Element)newValue).getNodeName() + " old " +
+						// oldValue);
+						adapt((Element) newValue);
+					}
+					break;
+				}
+					// case INodeNotifier.REMOVE:
+				case INodeNotifier.CHANGE :
+				case INodeNotifier.STRUCTURE_CHANGED :
+				case INodeNotifier.CONTENT_CHANGED : {
+					Node node = (Node) notifier;
+					if (node.getNodeType() == Node.ELEMENT_NODE) {
+						switch (eventType) {
+							case INodeNotifier.CHANGE :
+							case INodeNotifier.STRUCTURE_CHANGED : {
+								// structure change
+								invokeDelayedCMDocumentLoad();
+								break;
+							}
+							case INodeNotifier.CONTENT_CHANGED : {
+								// some content changed
+								break;
+							}
+						}
+					}
+					else if (node.getNodeType() == Node.DOCUMENT_NODE) {
+						invokeDelayedCMDocumentLoad();
+					}
+					break;
+				}
+			}
+		}
+	}
+
+	/**
+	 * Intentionally left visible to the user
+	 */
+	class TimerJob extends Job {
+		public TimerJob() {
+			super(SSEUIMessages.LoadingReferencedGrammars);
+		}
+
+		public IStatus run(IProgressMonitor monitor) {
+			monitor.beginTask("", IProgressMonitor.UNKNOWN); //$NON-NLS-1$
+			Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
+			invokeCMDocumentLoad();
+			monitor.done();
+			return Status.OK_STATUS;
+		}
+	}
+
+	private Job timer = new TimerJob();
+	protected Document fDocument;
+	protected boolean isGrammarInferenceEnabled;
+	/**
+	 * If true, DOMObserver is currently disabled and not loading the content
+	 * model
+	 */
+	private boolean fIsDisabled = false;
+	/**
+	 * If true, DOMObserver is currently trying to load the content model
+	 */
+	private boolean fIsLoading = false;
+
+	public DOMObserver(IStructuredModel model) {
+		fDocument = (model instanceof IDOMModel) ? ((IDOMModel) model).getDocument() : null;
+
+		if (fDocument != null) {
+			// here we create and init an adapter that will listen to
+			// changes to the document and contained elements
+			MyDocumentAdapter adapter = new MyDocumentAdapter();
+			adapter.connect(fDocument);
+
+			ModelQuery modelQuery = ModelQueryUtil.getModelQuery(fDocument);
+			if ((modelQuery != null) && (modelQuery.getCMDocumentManager() != null)) {
+				CMDocumentManager cmDocumentManager = modelQuery.getCMDocumentManager();
+				cmDocumentManager.setPropertyEnabled(CMDocumentManager.PROPERTY_AUTO_LOAD, false);
+			}
+			
+			// attach a dom observer adapter to the document so others have access to
+			// domobserver if needed
+			INodeAdapter domObserverAdapter = ((INodeNotifier)fDocument).getExistingAdapter(DOMObserverAdapter.class);
+			if (domObserverAdapter == null) {
+				domObserverAdapter = new DOMObserverAdapter();
+				((INodeNotifier)fDocument).addAdapter(domObserverAdapter);
+			}
+			((DOMObserverAdapter)domObserverAdapter).setDOMObserver(this);
+		}
+	}
+
+	public void init() {
+		// CS: we seem to expose an XSD initialization problem when we do this
+		// immediately
+		// very nasty... I need to revist this problem with Ed Merks
+		//
+		timer.schedule();
+	}
+
+	public void invokeCMDocumentLoad() {
+		if (fIsDisabled) return;
+		try {
+			fIsLoading = true;
+			
+			ModelQuery modelQuery = ModelQueryUtil.getModelQuery(fDocument);
+			if ((modelQuery != null) && (modelQuery.getCMDocumentManager() != null)) {
+				CMDocumentLoader loader = isGrammarInferenceEnabled ? new InferredGrammarBuildingCMDocumentLoader(fDocument, modelQuery) : new CMDocumentLoader(fDocument, modelQuery);
+				loader.loadCMDocuments();
+			}
+		} finally {
+			fIsLoading = false;
+		}
+	}
+
+	public void invokeDelayedCMDocumentLoad() {
+		if (fIsDisabled) return;
+		timer.schedule(2000);
+	}
+
+	public void setGrammarInferenceEnabled(boolean isEnabled) {
+		isGrammarInferenceEnabled = isEnabled;
+	}
+	
+	boolean setDisabled(boolean isDisabled, boolean forced) {
+		boolean success = true;
+		
+		if (fIsDisabled != isDisabled) {
+			fIsDisabled = isDisabled;
+			if (forced) {
+				if (isDisabled)
+					success = timer.cancel();
+				else
+					invokeCMDocumentLoad();
+			}
+		}
+		return success;
+	}
+	
+	boolean isLoading() {
+		return fIsLoading;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/DOMObserverAdapter.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/DOMObserverAdapter.java
new file mode 100644
index 0000000..fcd60c4
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/DOMObserverAdapter.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright (c) 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal;
+
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapter;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+
+/**
+ * This is just an adapter that sits on a document node to allow clients
+ * limited access to the DOMObserver. Clients who handle their own content
+ * model document loading (as opposed to letting the DOMObserver do it) may
+ * use this class to stop the DOMObserver from loading and possibly
+ * interfering with the client's document loading.
+ */
+public class DOMObserverAdapter implements INodeAdapter {
+	private DOMObserver fObserver = null;
+
+	public boolean isAdapterForType(Object type) {
+		return type == DOMObserverAdapter.class;
+	}
+
+	public void notifyChanged(INodeNotifier notifier, int eventType, Object changedFeature, Object oldValue, Object newValue, int pos) {
+		// do nothing
+	}
+
+	/**
+	 * The DOMObserver is the one that adds the adapter to the document node,
+	 * so it'll set itself up here as well.
+	 * 
+	 * @param observer
+	 */
+	void setDOMObserver(DOMObserver observer) {
+		fObserver = observer;
+	}
+
+	/**
+	 * Disable the DOMObserver to prevent it from future content model loading
+	 * for this document.
+	 * 
+	 * @param disable
+	 *            true if caller wants DOMObserver disabled. false if caller
+	 *            wants DOMObserver enabled.
+	 * @param force
+	 *            if true, DOMObserver will forcibly be disabled (if the
+	 *            DOMObserver model loading job is scheduled, it will be
+	 *            cancelled)
+	 * @return true if DOMObserver was successfully disabled. false if
+	 *         DOMObserver was already in the process of loading and was
+	 *         unable to stop
+	 */
+	public boolean disableObserver(boolean disable, boolean force) {
+		return fObserver.setDisabled(disable, force);
+	}
+
+	/**
+	 * Returns whether or not DOMObserver is currently attempting to load the
+	 * content model.
+	 * 
+	 * @return true if DOMObserver is currently in the process of loading the
+	 *         content models. false otherwise.
+	 */
+	public boolean isObserverLoading() {
+		return fObserver.isLoading();
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/IProductConstants.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/IProductConstants.java
new file mode 100644
index 0000000..ab66be9
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/IProductConstants.java
@@ -0,0 +1,18 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal;
+
+public interface IProductConstants {
+	/**
+	 * The explorer view to use when creating the XML perspective
+	 */
+	String PERSPECTIVE_EXPLORER_VIEW = "idPerspectiveHierarchyView"; //$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/Logger.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/Logger.java
new file mode 100644
index 0000000..b98e7ab
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/Logger.java
@@ -0,0 +1,163 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal;
+
+
+
+import com.ibm.icu.util.StringTokenizer;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.osgi.framework.Bundle;
+
+/**
+ * Small convenience class to log messages to plugin's log file and also, if
+ * desired, the console. This class should only be used by classes in this
+ * plugin. Other plugins should make their own copy, with appropriate ID.
+ */
+public class Logger {
+	private static final String PLUGIN_ID = "org.eclipse.wst.xml.ui"; //$NON-NLS-1$
+
+	public static final int ERROR = IStatus.ERROR; // 4
+	public static final int ERROR_DEBUG = 200 + ERROR;
+	public static final int INFO = IStatus.INFO; // 1
+	public static final int INFO_DEBUG = 200 + INFO;
+
+	public static final int OK = IStatus.OK; // 0
+
+	public static final int OK_DEBUG = 200 + OK;
+
+	private static final String TRACEFILTER_LOCATION = "/debug/tracefilter"; //$NON-NLS-1$
+	public static final int WARNING = IStatus.WARNING; // 2
+	public static final int WARNING_DEBUG = 200 + WARNING;
+
+	/**
+	 * Adds message to log.
+	 * 
+	 * @param level
+	 *            severity level of the message (OK, INFO, WARNING, ERROR,
+	 *            OK_DEBUG, INFO_DEBUG, WARNING_DEBUG, ERROR_DEBUG)
+	 * @param message
+	 *            text to add to the log
+	 * @param exception
+	 *            exception thrown
+	 */
+	protected static void _log(int level, String message, Throwable exception) {
+		if ((level == OK_DEBUG) || (level == INFO_DEBUG) || (level == WARNING_DEBUG) || (level == ERROR_DEBUG)) {
+			if (!isDebugging()) {
+				return;
+			}
+		}
+
+		int severity = IStatus.OK;
+		switch (level) {
+			case INFO_DEBUG :
+			case INFO :
+				severity = IStatus.INFO;
+				break;
+			case WARNING_DEBUG :
+			case WARNING :
+				severity = IStatus.WARNING;
+				break;
+			case ERROR_DEBUG :
+			case ERROR :
+				severity = IStatus.ERROR;
+		}
+		message = (message != null) ? message : "null"; //$NON-NLS-1$
+		Status statusObj = new Status(severity, PLUGIN_ID, severity, message, exception);
+		Bundle bundle = Platform.getBundle(PLUGIN_ID);
+		if (bundle != null) {
+			Platform.getLog(bundle).log(statusObj);
+		}
+	}
+
+	/**
+	 * Prints message to log if category matches /debug/tracefilter option.
+	 * 
+	 * @param message
+	 *            text to print
+	 * @param category
+	 *            category of the message, to be compared with
+	 *            /debug/tracefilter
+	 */
+	protected static void _trace(String category, String message, Throwable exception) {
+		if (isTracing(category)) {
+			message = (message != null) ? message : "null"; //$NON-NLS-1$
+			Status statusObj = new Status(IStatus.OK, PLUGIN_ID, IStatus.OK, message, exception);
+			Bundle bundle = Platform.getBundle(PLUGIN_ID);
+			if (bundle != null) {
+				Platform.getLog(bundle).log(statusObj);
+			}
+		}
+	}
+
+	/**
+	 * @return true if the platform is debugging
+	 */
+	public static boolean isDebugging() {
+		return Platform.inDebugMode();
+	}
+
+	/**
+	 * Determines if currently tracing a category
+	 * 
+	 * @param category
+	 * @return true if tracing category, false otherwise
+	 */
+	public static boolean isTracing(String category) {
+		if (!isDebugging()) {
+			return false;
+		}
+
+		String traceFilter = Platform.getDebugOption(PLUGIN_ID + TRACEFILTER_LOCATION);
+		if (traceFilter != null) {
+			StringTokenizer tokenizer = new StringTokenizer(traceFilter, ","); //$NON-NLS-1$
+			while (tokenizer.hasMoreTokens()) {
+				String cat = tokenizer.nextToken().trim();
+				if (category.equals(cat)) {
+					return true;
+				}
+			}
+		}
+		return false;
+	}
+
+	public static void log(int level, String message) {
+		_log(level, message, null);
+	}
+
+	public static void log(int level, String message, Throwable exception) {
+		_log(level, message, exception);
+	}
+
+	public static void logException(String message, Throwable exception) {
+		_log(ERROR, message, exception);
+	}
+
+	public static void logException(Throwable exception) {
+		_log(ERROR, exception.getMessage(), exception);
+	}
+
+	public static void trace(String category, String message) {
+		_trace(category, message, null);
+	}
+
+	public static void traceException(String category, String message, Throwable exception) {
+		_trace(category, message, exception);
+	}
+
+	public static void traceException(String category, Throwable exception) {
+		_trace(category, exception.getMessage(), exception);
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/ProductProperties.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/ProductProperties.java
new file mode 100644
index 0000000..6f88be4
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/ProductProperties.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal;
+
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.ui.IPageLayout;
+
+public class ProductProperties {
+	/**
+	 * Default values for WTP level product
+	 */
+	static final String ID_PERSPECTIVE_EXPLORER_VIEW = IPageLayout.ID_PROJECT_EXPLORER;
+
+	/**
+	 * Return the value for the associated key from the Platform Product registry or return the
+	 * WTP default.
+	 * 
+	 * @param key
+	 * @return String value of product's property
+	 */
+	public static String getProperty(String key) {
+		if (key == null)
+			return null;
+		String value = null;
+		if (Platform.getProduct()!=null)
+			value = Platform.getProduct().getProperty(key);
+		if (value == null) {
+			if (key.equals(IProductConstants.PERSPECTIVE_EXPLORER_VIEW))
+				return ID_PERSPECTIVE_EXPLORER_VIEW;
+		}
+		return value;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/XMLFormattingStrategy.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/XMLFormattingStrategy.java
new file mode 100644
index 0000000..39432ef
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/XMLFormattingStrategy.java
@@ -0,0 +1,105 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal;
+
+import java.util.LinkedList;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.TypedPosition;
+import org.eclipse.jface.text.formatter.ContextBasedFormattingStrategy;
+import org.eclipse.jface.text.formatter.FormattingContextProperties;
+import org.eclipse.jface.text.formatter.IFormattingContext;
+import org.eclipse.jface.text.formatter.IFormattingStrategyExtension;
+import org.eclipse.text.edits.TextEdit;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+import org.eclipse.wst.sse.ui.internal.Logger;
+import org.eclipse.wst.xml.core.internal.formatter.DefaultXMLPartitionFormatter;
+
+public class XMLFormattingStrategy extends ContextBasedFormattingStrategy implements IFormattingStrategyExtension {
+
+	/** Documents to be formatted by this strategy */
+	private final LinkedList fDocuments = new LinkedList();
+	/** Partitions to be formatted by this strategy */
+	private final LinkedList fPartitions = new LinkedList();
+	private IRegion fRegion;
+	private DefaultXMLPartitionFormatter formatter = new DefaultXMLPartitionFormatter();
+
+	/**
+	 * @param formatProcessor
+	 */
+	public XMLFormattingStrategy() {
+		super();
+	}
+
+	/*
+	 * @see org.eclipse.jface.text.formatter.ContextBasedFormattingStrategy#format()
+	 */
+	public void format() {
+		super.format();
+
+		final IDocument document = (IDocument) fDocuments.removeFirst();
+		final TypedPosition partition = (TypedPosition) fPartitions.removeFirst();
+
+		if (document != null && partition != null && fRegion != null) {
+			try {
+				if (document instanceof IStructuredDocument) {
+					IStructuredModel model = StructuredModelManager.getModelManager().getModelForEdit((IStructuredDocument) document);
+					if (model != null) {
+						try {
+							TextEdit edit = formatter.format(model, fRegion.getOffset(), fRegion.getLength());
+							if (edit != null) {
+								try {
+									model.aboutToChangeModel();
+									edit.apply(document);
+								}
+								finally {
+									model.changedModel();
+								}
+							}
+						}
+						finally {
+							model.releaseFromEdit();
+						}
+					}
+				}
+			}
+			catch (BadLocationException e) {
+				// log for now, unless we find reason not to
+				Logger.log(Logger.INFO, e.getMessage());
+			}
+		}
+	}
+
+	/*
+	 * @see org.eclipse.jface.text.formatter.ContextBasedFormattingStrategy#formatterStarts(org.eclipse.jface.text.formatter.IFormattingContext)
+	 */
+	public void formatterStarts(final IFormattingContext context) {
+		super.formatterStarts(context);
+
+		fPartitions.addLast(context.getProperty(FormattingContextProperties.CONTEXT_PARTITION));
+		fDocuments.addLast(context.getProperty(FormattingContextProperties.CONTEXT_MEDIUM));
+		fRegion = (IRegion) context.getProperty(FormattingContextProperties.CONTEXT_REGION);
+	}
+
+	/*
+	 * @see org.eclipse.jface.text.formatter.ContextBasedFormattingStrategy#formatterStops()
+	 */
+	public void formatterStops() {
+		super.formatterStops();
+
+		fPartitions.clear();
+		fDocuments.clear();
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/XMLUIMessages.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/XMLUIMessages.java
new file mode 100644
index 0000000..2f03c15
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/XMLUIMessages.java
@@ -0,0 +1,358 @@
+/**********************************************************************
+ * Copyright (c) 2005, 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 - Initial API and implementation
+ * Benjamin Muskalla, b.muskalla@gmx.net - [158660] character entities should have their own syntax highlighting preference
+ * David Carver - STAR - [205989] - [validation] validate XML after XInclude resolution
+ **********************************************************************/
+package org.eclipse.wst.xml.ui.internal;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Strings used by XML UI
+ * 
+ * @plannedfor 1.0
+ */
+public class XMLUIMessages extends NLS {
+	private static final String BUNDLE_NAME = "org.eclipse.wst.xml.ui.internal.XMLUIPluginResources";//$NON-NLS-1$
+	private static ResourceBundle fResourceBundle;
+
+	public static String Sample_XML_doc;
+	public static String Comment_Delimiters_UI_;
+	public static String Comment_Content_UI_;
+	public static String Tag_Delimiters_UI_;
+	public static String Tag_Names_UI_;
+	public static String Attribute_Names_UI_;
+	public static String Attribute_Equals_UI_;
+	public static String Attribute_Values_UI_;
+	public static String Declaration_Delimiters_UI_;
+	public static String Content_UI_;
+	public static String CDATA_Delimiters_UI_;
+	public static String CDATA_Content_UI_;
+	public static String Processing_Instruction_Del_UI_;
+	public static String Processing_Instruction_Con_UI__UI_;
+	public static String DOCTYPE_Name_UI_;
+	public static String DOCTYPE_SYSTEM_PUBLIC_Keyw_UI_;
+	public static String DOCTYPE_Public_Reference_UI_;
+	public static String DOCTYPE_System_Reference_UI_;
+	public static String Entity_Reference_UI_;
+	public static String DELETE;
+	public static String ADD_PROCESSING_INSTRUCTION;
+	public static String _UI_MENU_ADD_AFTER;
+	public static String _UI_MENU_ADD_ATTRIBUTE;
+	public static String _UI_MENU_ADD_BEFORE;
+	public static String _UI_MENU_ADD_CHILD;
+	public static String _UI_MENU_REMOVE;
+	public static String _UI_MENU_REPLACE_WITH;
+	public static String _UI_MENU_EDIT_DOCTYPE;
+	public static String _UI_LABEL_UNDO_REPLACE_DESCRIPTION;
+	public static String _UI_LABEL_EDIT_DOCTYPE;
+	public static String _UI_INFO_EXPAND_ALL;
+	public static String _UI_INFO_COLLAPSE_ALL;
+	public static String _UI_MENU_ADD_DTD_INFORMATION;
+	public static String _UI_MENU_ADD_SCHEMA_INFORMATION;
+	public static String _UI_MENU_EDIT_PROCESSING_INSTRUCTION;
+	public static String _UI_MENU_EDIT_NAMESPACES;
+	public static String _UI_MENU_ADD_DTD_INFORMATION_TITLE;
+	public static String _UI_MENU_EDIT_PROCESSING_INSTRUCTION_TITLE;
+	public static String _UI_MENU_EDIT_SCHEMA_INFORMATION_TITLE;
+	public static String _UI_MENU_NEW_ATTRIBUTE;
+	public static String _UI_MENU_NEW_ATTRIBUTE_TITLE;
+	public static String _UI_MENU_EDIT_ATTRIBUTE;
+	public static String _UI_MENU_EDIT_ATTRIBUTE_TITLE;
+	public static String _UI_MENU_NEW_ELEMENT;
+	public static String _UI_MENU_NEW_ELEMENT_TITLE;
+	public static String _UI_MENU_RENAME;
+	public static String _UI_MENU_RENAME_TITLE;
+	public static String _UI_LABEL_ELEMENT_NAME;
+	public static String _UI_MENU_ADD_COMMENT;
+	public static String _UI_MENU_ADD_PROCESSING_INSTRUCTION;
+	public static String _UI_MENU_ADD_CDATA_SECTION;
+	public static String _UI_MENU_ADD_PCDATA;
+	public static String _UI_MENU_COMMENT;
+	public static String _UI_MENU_PROCESSING_INSTRUCTION;
+	public static String _UI_MENU_CDATA_SECTION;
+	public static String _UI_MENU_PCDATA;
+	public static String _UI_MENU_ADD;
+	public static String _UI_COMMENT_VALUE;
+	public static String _UI_PI_TARGET_VALUE;
+	public static String _UI_PI_DATA_VALUE;
+	public static String _UI_LABEL_ROOT_ELEMENT_VALUE;
+	public static String _UI_LABEL_TARGET_COLON;
+	public static String _UI_LABEL_DATA_COLON;
+	public static String _UI_LABEL_ROOT_ELEMENT_NAME_COLON;
+	public static String _UI_LABEL_PUBLIC_ID_COLON;
+	public static String _UI_LABEL_SYSTEM_ID_COLON;
+	public static String _UI_LABEL_BROWSE;
+	public static String _UI_LABEL_SELECT_XML_CATALOG_ENTRY;
+	public static String _UI_LABEL_SPECIFY_SYSTEM_ID;
+	public static String _UI_LABEL_SELECT_FILE;
+	public static String _UI_LABEL_KEY;
+	public static String _UI_LABEL_URI;
+	public static String _UI_LABEL_XML_CATALOG_COLON;
+	public static String _UI_LABEL_NAMESPACE_NAME;
+	public static String _UI_LABEL_LOCATION_HINT;
+	public static String _UI_LABEL_PREFIX;
+	public static String _UI_LABEL_NAMESPACE_NAME_COLON;
+	public static String _UI_LABEL_LOCATION_HINT_COLON;
+	public static String _UI_LABEL_PREFIX_COLON;
+	public static String _UI_NO_NAMESPACE_NAME;
+	public static String _UI_NO_PREFIX;
+	public static String _UI_LABEL_XML_SCHEMA_INFORMATION;
+	public static String _UI_LABEL_NAME_COLON;
+	public static String _UI_LABEL_VALUE_COLON;
+	public static String _UI_BUTTON_DELETE;
+	public static String _UI_BUTTON_NEW;
+	public static String _UI_BUTTON_EDIT;
+	public static String _UI_LABEL_NEW_NAMESPACE_INFORMATION;
+	public static String _UI_RADIO_BUTTON_SELECT_FROM_WORKSPACE;
+	public static String _UI_RADIO_BUTTON_SELECT_FROM_CATALOG;
+	public static String _UI_WARNING_MORE_THAN_ONE_NS_WITH_NAME;
+	public static String _UI_WARNING_MORE_THAN_ONE_NS_WITHOUT_NAME;
+	public static String _UI_WARNING_MORE_THAN_ONE_NS_WITHOUT_PREFIX;
+	public static String _UI_WARNING_MORE_THAN_ONE_NS_WITH_PREFIX;
+	public static String _UI_WARNING_SCHEMA_CAN_NOT_BE_LOCATED;
+	public static String _UI_WARNING_LOCATION_HINT_NOT_SPECIFIED;
+	public static String _UI_WARNING_NAMESPACE_NAME_NOT_SPECIFIED;
+	public static String _UI_WARNING_PREFIX_NOT_SPECIFIED;
+	public static String _UI_WARNING_ROOT_ELEMENT_MUST_BE_SPECIFIED;
+	public static String _UI_WARNING_SYSTEM_ID_MUST_BE_SPECIFIED;
+	public static String _UI_INVALID_NAME;
+	public static String _UI_ENTER_REQ_PREFIX_AND_NAMESPACE;
+	public static String _UI_SELECT_REGISTERED_NAMESPACES;
+	public static String _UI_SPECIFY_NEW_NAMESPACE;
+	public static String _UI_SELECT_NAMESPACE_TO_ADD;
+	public static String _UI_ADD_NAMESPACE_DECLARATIONS;
+	public static String _UI_NAMESPACE_DECLARATIONS;
+	public static String _UI_TARGET_NAMESPACE;
+	public static String _ERROR_XML_ATTRIBUTE_ALREADY_EXISTS;
+	public static String error_message_goes_here;
+	public static String SurroundWithNewElementQuickAssistProposal_0;
+	public static String SurroundWithNewElementQuickAssistProposal_1;
+	public static String RenameInFileQuickAssistProposal_0;
+	public static String RenameInFileQuickAssistProposal_1;
+	public static String InsertRequiredAttrsQuickAssistProposal_0;
+	public static String InsertRequiredAttrsQuickAssistProposal_1;
+	public static String EncodingSettings_0;
+	public static String EncodingSettings_1;
+	public static String DragNodeCommand_0;
+	public static String DragNodeCommand_1;
+	public static String CommonEditNamespacesDialog_0;
+	public static String JFaceNodeAdapter_1;
+	public static String QuickFixProcessorXML_0;
+	public static String QuickFixProcessorXML_1;
+	public static String QuickFixProcessorXML_2;
+	public static String QuickFixProcessorXML_3;
+	public static String QuickFixProcessorXML_4;
+	public static String QuickFixProcessorXML_5;
+	public static String QuickFixProcessorXML_6;
+	public static String QuickFixProcessorXML_7;
+	public static String QuickFixProcessorXML_8;
+	public static String QuickFixProcessorXML_9;
+	public static String QuickFixProcessorXML_10;
+	public static String QuickFixProcessorXML_11;
+	public static String QuickFixProcessorXML_12;
+	public static String QuickFixProcessorXML_13;
+	public static String QuickFixProcessorXML_14;
+	public static String QuickFixProcessorXML_15;
+	public static String XMLPropertySourceAdapter_0;
+	public static String WorkbenchDefaultEncodingSettings_0;
+	public static String refreshoutline_0;
+	public static String Creating_files_encoding;
+	public static String End_tag_has_attributes;
+	public static String Attribute__is_missing_a_value;
+	public static String Attribute__has_no_value;
+	public static String Missing_end_tag_;
+	public static String Missing_start_tag_;
+	public static String ReconcileStepForMarkup_0;
+	public static String ReconcileStepForMarkup_1;
+	public static String ReconcileStepForMarkup_2;
+	public static String ReconcileStepForMarkup_3;
+	public static String ReconcileStepForMarkup_4;
+	public static String ReconcileStepForMarkup_5;
+	public static String ReconcileStepForMarkup_6;
+	public static String End_with_;
+	public static String SEVERE_internal_error_occu_UI_;
+	public static String No_known_attribute__UI_;
+	public static String Content_Assist_not_availab_UI_;
+	public static String Element__is_unknown;
+	public static String Comment__;
+	public static String Close_with__;
+	public static String End_with__;
+	public static String Close_with___;
+	public static String Close_with____;
+	public static String _Has_no_available_child;
+	public static String No_known_child_tag;
+	public static String __Has_no_known_child;
+	public static String No_known_child_tag_names;
+	public static String The_document_element__;
+	public static String No_definition_for_in;
+	public static String No_definition_for;
+	public static String No_content_model_for;
+	public static String No_content_model_found_UI_;
+	public static String Cleanup_UI_;
+	public static String Compress_empty_element_tags_UI_;
+	public static String Insert_required_attributes_UI_;
+	public static String Insert_missing_tags_UI_;
+	public static String Quote_attribute_values_UI_;
+	public static String Format_source_UI_;
+	public static String Convert_EOL_codes_UI_;
+	public static String Insert_XML_decl;
+	public static String EOL_Windows_UI;
+	public static String EOL_Unix_UI;
+	public static String EOL_Mac_UI;
+	public static String Creating_files;
+	public static String Encoding_desc;
+	public static String Encoding;
+	public static String Creating_or_saving_files;
+	public static String End_of_line_code_desc;
+	public static String End_of_line_code;
+	public static String EOL_Windows;
+	public static String EOL_Unix;
+	public static String EOL_Mac;
+	public static String EOL_NoTranslation;
+	public static String XMLFilesPreferencePage_ExtensionLabel;
+	public static String XMLFilesPreferencePage_ExtensionError;
+	public static String XMLContentAssistPreferencePage_Auto_Activation_UI_;
+	public static String XMLContentAssistPreferencePage_Cycling_UI_;
+	public static String Automatically_make_suggest_UI_;
+	public static String Prompt_when_these_characte_UI_;
+	public static String Formatting_UI_;
+	public static String Line_width__UI_;
+	public static String Split_multiple_attributes;
+	public static String Align_final_bracket;
+	public static String Preserve_PCDATA_Content;
+	public static String Space_before_empty_close_tag;
+	public static String Indent_using_tabs;
+	public static String Indent_using_spaces;
+	public static String Indentation_size;
+	public static String Indentation_size_tip;
+	public static String Clear_all_blank_lines_UI_;
+	public static String Format_comments;
+	public static String Format_comments_join_lines;
+	public static String Grammar_Constraints;
+	public static String Use_inferred_grammar_in_absence_of;
+	public static String Suggestion_Strategy;
+	public static String Suggestion_Strategy_Lax;
+	public static String Suggestion_Strategy_Strict;
+	public static String Element____1;
+	public static String Content_Model____2;
+	public static String Attribute____3;
+	public static String Data_Type____4;
+	public static String Enumerated_Values____5;
+	public static String Default_Value____6;
+	public static String SourceMenu_label;
+	public static String Comment_label; // Resource bundle
+	public static String Comment_tooltip; // Resource bundle
+	public static String Comment_description; // Resource bundle
+	public static String Uncomment_label; // Resource bundle
+	public static String Uncomment_tooltip; // Resource bundle
+	public static String Uncomment_description; // Resource bundle
+	public static String ToggleComment_label; // Resource bundle
+	public static String ToggleComment_tooltip; // Resource bundle
+	public static String ToggleComment_description; // Resource bundle
+	public static String AddBlockComment_label; // Resource bundle
+	public static String AddBlockComment_tooltip; // Resource bundle
+	public static String AddBlockComment_description; // Resource bundle
+	public static String RemoveBlockComment_label; // Resource bundle
+	public static String RemoveBlockComment_tooltip; // Resource bundle
+	public static String RemoveBlockComment_description; // Resource bundle
+	public static String CleanupDocument_label; // Resource bundle
+	public static String CleanupDocument_tooltip; // Resource bundle
+	public static String CleanupDocument_description; // Resource bundle
+	public static String FindOccurrences_label; // Resource bundle
+	public static String OpenFileFromSource_label; // Resource bundle
+	public static String OpenFileFromSource_tooltip; // Resource bundle
+	public static String OpenFileFromSource_description; // Resource bundle
+	public static String XMLContentOutlineConfiguration_0;
+	public static String XMLTyping_Auto_Complete;
+	public static String XMLTyping_Auto_Remove;
+	public static String XMLTyping_Complete_Comments;
+	public static String XMLTyping_Close_Strings;
+	public static String XMLTyping_Close_Brackets;
+	public static String XMLTyping_Complete_End_Tags;
+	public static String XMLTyping_Complete_Elements;
+	public static String XMLTyping_Remove_End_Tags;
+	public static String XMLTyping_Start_Tag;
+	public static String XMLTyping_End_Tag;
+	public static String StructureSelectEnclosing_label;
+	public static String StructureSelectEnclosing_tooltip;
+	public static String StructureSelectEnclosing_description;
+	public static String StructureSelectNext_label;
+	public static String StructureSelectNext_tooltip;
+	public static String StructureSelectNext_description;
+	public static String StructureSelectPrevious_label;
+	public static String StructureSelectPrevious_tooltip;
+	public static String StructureSelectPrevious_description;
+	public static String MESSAGE_XML_VALIDATION_MESSAGE_UI_;
+	public static String Indicate_no_grammar_specified;
+	public static String Indicate_no_grammar_specified_severities_error;
+	public static String Indicate_no_grammar_specified_severities_warning;
+	public static String Indicate_no_grammar_specified_severities_ignore;
+	public static String Validating_files;
+	public static String SyntaxColoringPage_0;
+	public static String SyntaxColoringPage_2;
+	public static String SyntaxColoringPage_3;
+	public static String SyntaxColoringPage_4;
+	public static String SyntaxColoringPage_5;
+	public static String SyntaxColoringPage_6;
+	public static String EmptyFilePreferencePage_0;
+	public static String _UI_STRUCTURED_TEXT_EDITOR_PREFS_LINK;
+	public static String gotoMatchingTag_label;
+	public static String gotoMatchingTag_description;
+	public static String gotoMatchingTag_start;
+	public static String gotoMatchingTag_end;
+	public static String nextSibling_label;
+	public static String nextSibling_description;
+	public static String previousSibling_label;
+	public static String previousSibling_description;
+	public static String Use_XInclude;
+    public static String Honour_all_schema_locations;   
+	public static String Open;
+	public static String _UI_BUTTON_SORT;
+	public static String MarkupValidation_files_label;
+	public static String MarkupValidation_files;
+	public static String Severity_error;
+	public static String Severity_warning;
+	public static String Severity_ignore;
+	public static String Empty_element_tag;
+	public static String End_tag_with_attributes;
+	public static String Invalid_whitespace_before_tagname;
+	public static String Missing_closing_bracket;
+	public static String Missing_closing_quote;
+	public static String Missing_end_tag;
+	public static String Missing_start_tag;
+	public static String Missing_quotes;
+	public static String Namespace_in_pi_target;
+	public static String Tag_name_missing;
+	public static String Whitespace_at_start;
+
+	static {
+		// load message values from bundle file
+		NLS.initializeMessages(BUNDLE_NAME, XMLUIMessages.class);
+	}
+
+	private XMLUIMessages() {
+		// cannot create new instance
+	}
+
+	public static ResourceBundle getResourceBundle() {
+		try {
+			if (fResourceBundle == null) {
+				fResourceBundle = ResourceBundle.getBundle(BUNDLE_NAME);
+			}
+		}
+		catch (MissingResourceException x) {
+			fResourceBundle = null;
+		}
+		return fResourceBundle;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/XMLUIPlugin.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/XMLUIPlugin.java
new file mode 100644
index 0000000..fe8f171
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/XMLUIPlugin.java
@@ -0,0 +1,117 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal;
+
+import java.io.IOException;
+
+import org.eclipse.jface.text.templates.ContextTypeRegistry;
+import org.eclipse.jface.text.templates.persistence.TemplateStore;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.ui.editors.text.templates.ContributionContextTypeRegistry;
+import org.eclipse.ui.editors.text.templates.ContributionTemplateStore;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.eclipse.wst.sse.ui.internal.provisional.registry.AdapterFactoryRegistry;
+import org.eclipse.wst.sse.ui.internal.provisional.registry.AdapterFactoryRegistryImpl;
+import org.eclipse.wst.xml.ui.internal.preferences.XMLUIPreferenceNames;
+import org.eclipse.wst.xml.ui.internal.templates.TemplateContextTypeIdsXML;
+
+/**
+ * The main plugin class to be used in the desktop.
+ */
+public class XMLUIPlugin extends AbstractUIPlugin {
+	public final static String ID = "org.eclipse.wst.xml.ui"; //$NON-NLS-1$
+
+	protected static XMLUIPlugin instance = null;
+
+	public static XMLUIPlugin getDefault() {
+		return instance;
+	}
+
+	public synchronized static XMLUIPlugin getInstance() {
+		return instance;
+	}
+
+	/**
+	 * The template context type registry for the xml editor.
+	 */
+	private ContextTypeRegistry fContextTypeRegistry;
+
+	/**
+	 * The template store for the xml editor.
+	 * 
+	 */
+	private TemplateStore fTemplateStore;
+
+	public XMLUIPlugin() {
+		super();
+		instance = this;
+	}
+
+	public AdapterFactoryRegistry getAdapterFactoryRegistry() {
+		return AdapterFactoryRegistryImpl.getInstance();
+
+	}
+
+	/**
+	 * Returns the template store for the xml editor templates.
+	 * 
+	 * @return the template store for the xml editor templates
+	 */
+	public TemplateStore getTemplateStore() {
+		if (fTemplateStore == null) {
+			fTemplateStore = new ContributionTemplateStore(getTemplateContextRegistry(), getPreferenceStore(), XMLUIPreferenceNames.TEMPLATES_KEY);
+
+			try {
+				fTemplateStore.load();
+			}
+			catch (IOException e) {
+				Logger.logException(e);
+			}
+		}
+		return fTemplateStore;
+	}
+
+	/**
+	 * Returns the template context type registry for the xml plugin.
+	 * 
+	 * @return the template context type registry for the xml plugin
+	 */
+	public ContextTypeRegistry getTemplateContextRegistry() {
+		if (fContextTypeRegistry == null) {
+			ContributionContextTypeRegistry registry = new ContributionContextTypeRegistry();
+			registry.addContextType(TemplateContextTypeIdsXML.ALL);
+			registry.addContextType(TemplateContextTypeIdsXML.NEW);
+			registry.addContextType(TemplateContextTypeIdsXML.TAG);
+			registry.addContextType(TemplateContextTypeIdsXML.ATTRIBUTE);
+			registry.addContextType(TemplateContextTypeIdsXML.ATTRIBUTE_VALUE);
+
+			fContextTypeRegistry = registry;
+		}
+
+		return fContextTypeRegistry;
+	}
+
+	/**
+	 * Get an image from the registry.
+	 * 
+	 * *This method is used by the referencingfile dialog and should be
+	 * removed when the dialog is moved to anothercomponent.
+	 * 
+	 * @param imageName
+	 *            The name of the image.
+	 * @return The image registered for the given name.
+	 */
+	public Image getImage(String imageName) {
+		return getWorkbench().getSharedImages().getImage(imageName);
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/XMLUIPluginResources.properties b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/XMLUIPluginResources.properties
new file mode 100644
index 0000000..7c1f7c3
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/XMLUIPluginResources.properties
@@ -0,0 +1,370 @@
+###############################################################################
+# Copyright (c) 2001, 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
+#     Jens Lukowski/Innoopract - initial renaming/restructuring
+#     Benjamin Muskalla, b.muskalla@gmx.net - [158660] character entities should have their own syntax highlighting preference
+#     David Carver - STAR - [205989] - [validation] validate XML after XInclude resolution
+###############################################################################
+## The following line is a sample XML document.  Please translate only the following parts:
+## begin color definitions
+## Normal text content.
+Sample_XML_doc=<?xml version=\"1.0\"?>\n<?customProcessingInstruction\n\tXML processor specific\n\tcontent ?>\n<!DOCTYPE colors\n\tPUBLIC \"//IBM/XML/COLORS/\" \"colors.dtd\">\n<colors>\n\t<!-- begin color definitions -->\n\t<color name=\"plaintext\" foreground=\"#000000\"\n\t\tbackground=\"#D4D0C8\" />\n\t<color name=\"bold\" foreground=\"#000000\"\n\t\tbackground=\"#B3ACA0\" />\n\t<![CDATA[<123456789>]]>\n\tNormal text content.\n\t===&gt;look at me!&lt;===\n\t<color name=\"inverse\" foreground=\"#F0F0F0\"\n\t\tbackground=\"#D4D0C8\" />\n\n</colors>\n
+Comment_Delimiters_UI_=Comment Delimiters
+Comment_Content_UI_=Comment Content
+Tag_Delimiters_UI_=Tag Delimiters
+Tag_Names_UI_=Tag Names
+Attribute_Names_UI_=Attribute Names
+Attribute_Equals_UI_=Attribute Equal Signs
+Attribute_Values_UI_=Attribute Values
+Declaration_Delimiters_UI_=Declaration Delimiters
+Content_UI_=Content
+Entity_Reference_UI_=Entity References
+## on the following 2 lines, do not translate CDATA
+CDATA_Delimiters_UI_=CDATA Delimiters
+CDATA_Content_UI_=CDATA Content
+Processing_Instruction_Del_UI_=Processing Instruction Delimiters
+Processing_Instruction_Con_UI__UI_=Processing Instruction Content
+## on the following line solely translate:  Name
+DOCTYPE_Name_UI_=DOCTYPE Name
+## on the following line solely translate:  Keyword
+DOCTYPE_SYSTEM_PUBLIC_Keyw_UI_=DOCTYPE SYSTEM/PUBLIC Keyword
+## on the following line solely translate:  Public Reference
+DOCTYPE_Public_Reference_UI_=DOCTYPE Public Reference
+## on the following line solely translate:  System Reference
+DOCTYPE_System_Reference_UI_=DOCTYPE System Reference
+# XML Common UI
+# Constants for strings
+
+DELETE=Remove
+ADD_PROCESSING_INSTRUCTION=Add Processing Instruction
+
+_UI_MENU_ADD_AFTER=Add &After
+_UI_MENU_ADD_ATTRIBUTE=Add A&ttribute
+_UI_MENU_ADD_BEFORE=Add &Before
+_UI_MENU_ADD_CHILD=Add &Child
+_UI_MENU_REMOVE=Re&move
+_UI_MENU_REPLACE_WITH=Re&place With
+_UI_MENU_EDIT_DOCTYPE=Edit DOCTYPE...
+_UI_LABEL_UNDO_REPLACE_DESCRIPTION=Replace
+_UI_LABEL_EDIT_DOCTYPE=Edit DOCTYPE
+_UI_INFO_EXPAND_ALL=Expand All
+_UI_INFO_COLLAPSE_ALL=Collapse All
+
+_UI_MENU_ADD_DTD_INFORMATION=Add DTD Information...
+_UI_MENU_ADD_SCHEMA_INFORMATION=Add Schema Information...
+_UI_MENU_EDIT_PROCESSING_INSTRUCTION=Edit Process&ing Instruction...
+_UI_MENU_EDIT_NAMESPACES=Edit &Namespaces...
+
+_UI_MENU_ADD_DTD_INFORMATION_TITLE=Add DTD Information
+_UI_MENU_EDIT_PROCESSING_INSTRUCTION_TITLE=Edit Processing Instruction
+_UI_MENU_EDIT_SCHEMA_INFORMATION_TITLE=Edit Schema Information
+
+_UI_MENU_NEW_ATTRIBUTE=&New Attribute...
+_UI_MENU_NEW_ATTRIBUTE_TITLE=New Attribute
+_UI_MENU_EDIT_ATTRIBUTE=Edit Attribute...
+_UI_MENU_EDIT_ATTRIBUTE_TITLE=Edit Attribute
+_UI_MENU_NEW_ELEMENT=New &Element...
+_UI_MENU_NEW_ELEMENT_TITLE=New Element
+_UI_MENU_RENAME=R&ename
+_UI_MENU_RENAME_TITLE=Rename
+_UI_LABEL_ELEMENT_NAME=Element name:
+
+_UI_MENU_ADD_COMMENT=Add Comment
+_UI_MENU_ADD_PROCESSING_INSTRUCTION=Add Processing Instruction
+_UI_MENU_ADD_CDATA_SECTION=Add CDATA Section
+_UI_MENU_ADD_PCDATA=Add #PCDATA;
+
+_UI_MENU_COMMENT=C&omment
+_UI_MENU_PROCESSING_INSTRUCTION=P&rocessing Instruction
+_UI_MENU_CDATA_SECTION=CDATA Section
+_UI_MENU_PCDATA=#PC&DATA;
+
+_UI_MENU_ADD=Add
+
+_UI_COMMENT_VALUE=comment
+_UI_PI_TARGET_VALUE=target
+_UI_PI_DATA_VALUE=data
+_UI_LABEL_ROOT_ELEMENT_VALUE=RootElement
+
+_UI_LABEL_TARGET_COLON=Target:
+_UI_LABEL_DATA_COLON=Data:
+_UI_LABEL_ROOT_ELEMENT_NAME_COLON=Root element name:
+_UI_LABEL_PUBLIC_ID_COLON=Public ID:
+_UI_LABEL_SYSTEM_ID_COLON=System ID:
+_UI_LABEL_BROWSE=Browse...
+_UI_LABEL_SELECT_XML_CATALOG_ENTRY=Select XML Catalog Entry
+_UI_LABEL_SPECIFY_SYSTEM_ID=Specify System ID
+_UI_LABEL_SELECT_FILE=Select File
+
+_UI_LABEL_KEY=Key
+_UI_LABEL_URI=URI:
+_UI_LABEL_XML_CATALOG_COLON=XML Catalog
+_UI_LABEL_NAMESPACE_NAME=Namespace Name
+_UI_LABEL_LOCATION_HINT=Location Hint
+_UI_LABEL_PREFIX=Prefix
+_UI_LABEL_NAMESPACE_NAME_COLON=Namespace Name:
+_UI_LABEL_LOCATION_HINT_COLON=Location Hint:
+_UI_LABEL_PREFIX_COLON=Prefix:
+_UI_NO_NAMESPACE_NAME=<no namespace name>
+_UI_NO_PREFIX=<no prefix>
+
+_UI_LABEL_XML_SCHEMA_INFORMATION=XML Schema Information
+
+_UI_LABEL_NAME_COLON=Name:
+_UI_LABEL_VALUE_COLON=Value:
+
+_UI_BUTTON_DELETE=Delete
+_UI_BUTTON_NEW=New...
+_UI_BUTTON_EDIT=Edit...
+
+_UI_LABEL_NEW_NAMESPACE_INFORMATION=New Namespace Information
+
+# SelectFileOrXMLCatalogIdPanel.java
+
+_UI_RADIO_BUTTON_SELECT_FROM_WORKSPACE=Select file from Workspace
+_UI_RADIO_BUTTON_SELECT_FROM_CATALOG=Select XML Catalog entry
+
+_UI_WARNING_MORE_THAN_ONE_NS_WITH_NAME=More than one namespace has been specified with the namespace name :
+_UI_WARNING_MORE_THAN_ONE_NS_WITHOUT_NAME=More than one schema has been specified without a namespace name
+_UI_WARNING_MORE_THAN_ONE_NS_WITHOUT_PREFIX=More than one namespace has been specificed without a prefix
+_UI_WARNING_MORE_THAN_ONE_NS_WITH_PREFIX=More than one namespace has been specified with the prefix :
+_UI_WARNING_SCHEMA_CAN_NOT_BE_LOCATED=The specified schema can not be located :
+_UI_WARNING_LOCATION_HINT_NOT_SPECIFIED=A location hint has not been specified for the namespace with name
+_UI_WARNING_NAMESPACE_NAME_NOT_SPECIFIED=A name must be specified for the namespace with prefix :
+_UI_WARNING_PREFIX_NOT_SPECIFIED=A prefix must be specified for the namespace named :
+_UI_WARNING_ROOT_ELEMENT_MUST_BE_SPECIFIED=A root element name must be specified.
+_UI_WARNING_SYSTEM_ID_MUST_BE_SPECIFIED=A system ID must be specified.
+
+_UI_INVALID_NAME=Invalid name
+
+# String used for editing namespaces (org.eclipse.wst.xml.ui.nsedit)
+_UI_ENTER_REQ_PREFIX_AND_NAMESPACE=Enter the required prefix and namespace URI for the namespace declaration.
+_UI_SELECT_REGISTERED_NAMESPACES=Select From Registered Namespaces
+_UI_SPECIFY_NEW_NAMESPACE=Specify New Namespace
+_UI_SELECT_NAMESPACE_TO_ADD=Select the namespace declarations to add.
+_UI_ADD_NAMESPACE_DECLARATIONS=Add Namespace Declarations
+_UI_NAMESPACE_DECLARATIONS=Namespace Declarations
+_UI_TARGET_NAMESPACE=Target Namespace
+
+_ERROR_XML_ATTRIBUTE_ALREADY_EXISTS=The element already has an attribute with this name.
+
+#
+error_message_goes_here=error message goes here
+SurroundWithNewElementQuickAssistProposal_0=Surround with new element
+SurroundWithNewElementQuickAssistProposal_1=Surround with new element
+RenameInFileQuickAssistProposal_0=Link all references for a rename in file (does not change references in other files)
+RenameInFileQuickAssistProposal_1=Rename in file
+InsertRequiredAttrsQuickAssistProposal_0=Insert required attributes
+InsertRequiredAttrsQuickAssistProposal_1=Insert required attributes
+EncodingSettings_0=IANA:
+EncodingSettings_1=Encoding:
+DragNodeCommand_0=Move
+DragNodeCommand_1=Copy
+CommonEditNamespacesDialog_0=Add...
+JFaceNodeAdapter_1=Refresh Property Sheet
+QuickFixProcessorXML_0=Remove empty tag
+QuickFixProcessorXML_1=Change to empty-element tag
+QuickFixProcessorXML_2=Remove this tag
+QuickFixProcessorXML_3=Insert end tag before first child element
+QuickFixProcessorXML_4=Insert end tag at end of element
+QuickFixProcessorXML_5=Remove attributes in end tag
+QuickFixProcessorXML_6=Insert default attribute value
+QuickFixProcessorXML_7=Remove this attribute
+QuickFixProcessorXML_8=Remove spaces before tag name
+QuickFixProcessorXML_9=Remove spaces before processing instruction
+QuickFixProcessorXML_10=Remove namespace in processing instruction
+QuickFixProcessorXML_11=Remove this element
+QuickFixProcessorXML_12=Remove this attribute value
+QuickFixProcessorXML_13=Insert required attribute
+QuickFixProcessorXML_14=Quote attribute value
+QuickFixProcessorXML_15=Insert closing bracket
+XMLPropertySourceAdapter_0=Attributes
+
+WorkbenchDefaultEncodingSettings_0=Use workspace encoding
+refreshoutline_0=Refreshing Outline
+Creating_files_encoding=Creating files encoding preference
+# ReconcileStepForMarkup
+End_tag_has_attributes=End tag has attributes
+Attribute__is_missing_a_value=Attribute \"{0}\" is missing a value
+Attribute__has_no_value=Attribute \"{0}\"  has no value
+Missing_start_tag_=Missing start tag \"{0}\"
+Missing_end_tag_=Missing end tag \"{0}\"
+ReconcileStepForMarkup_0=Missing closing quote
+ReconcileStepForMarkup_1=Missing quotes for attribute value
+ReconcileStepForMarkup_2=A tagname cannot start with a space
+ReconcileStepForMarkup_3=Empty tags are not allowed
+ReconcileStepForMarkup_4=Namespaces are not allowed in a Processing Instruction target
+ReconcileStepForMarkup_5=Spaces are not allowed before a Processing Instruction
+ReconcileStepForMarkup_6=Tag missing closing bracket '>'
+# Content Assist
+End_with_=End with {0}>
+SEVERE_internal_error_occu_UI_=SEVERE internal error occurred
+No_known_attribute__UI_=No known attribute
+Content_Assist_not_availab_UI_=Content Assist not available at the current location
+Element__is_unknown=Element <{0}> is unknown.
+Comment__=comment {0}
+Close_with__=Close with {0}
+End_with__=End with \"</{0}>\"
+Close_with___=Close with \"{0}\"
+Close_with____=Close with \"></{0}>\"
+_Has_no_available_child={0} has no available child tags.
+No_known_child_tag=No known child tag names of <{0}> begin with \"{1}\".
+__Has_no_known_child=<{0}> has no known child tags.
+No_known_child_tag_names=No known child tag names of <{0}> begin with \"{1}\"
+The_document_element__=The document element <{0}> is already present.
+No_definition_for_in=No definition was found for element <{0}> in {1}
+No_definition_for=No definition was found for element <{0}>
+No_content_model_for=No content model found for {0}.
+No_content_model_found_UI_=No content model found
+## The following strings are for the XML Cleanup dialog
+Cleanup_UI_=Cleanup
+Compress_empty_element_tags_UI_=&Compress empty element tags
+Insert_required_attributes_UI_=Insert &required attributes
+Insert_missing_tags_UI_=&Insert missing tags
+Quote_attribute_values_UI_=&Quote attribute values
+Format_source_UI_=&Format source
+Convert_EOL_codes_UI_=Convert line &delimiters to
+Insert_XML_decl=Fix XML declaration
+EOL_Windows_UI=&Windows
+EOL_Unix_UI=U&NIX
+EOL_Mac_UI=&Mac
+## XML Files preference page
+Creating_files=Creating files
+Encoding_desc=The following encoding will apply:
+Encoding=En&coding:
+Creating_or_saving_files=Creating or saving files
+End_of_line_code_desc=The following line delimiter will apply:
+End_of_line_code=&Line delimiter:
+EOL_Windows=Windows
+EOL_Unix=UNIX
+EOL_Mac=Mac
+EOL_NoTranslation=No translation
+Validating_files=Validating files
+Indicate_no_grammar_specified=Indicate when no &grammar is specified:
+Indicate_no_grammar_specified_severities_error=Error
+Indicate_no_grammar_specified_severities_warning=Warning
+Indicate_no_grammar_specified_severities_ignore=Ignore
+XMLFilesPreferencePage_ExtensionLabel=Add this suffix (if not specified):
+XMLFilesPreferencePage_ExtensionError=Suffix must be one of the following {0}.
+## XML Source preference page
+XMLContentAssistPreferencePage_Auto_Activation_UI_=Auto Activation
+XMLContentAssistPreferencePage_Cycling_UI_=Cycling
+Automatically_make_suggest_UI_=Automatically ma&ke suggestions
+Prompt_when_these_characte_UI_=P&rompt when these characters are inserted:
+Formatting_UI_=Formatting
+Line_width__UI_=Line &width:
+Split_multiple_attributes=Split &multiple attributes each on a new line
+Align_final_bracket=&Align final bracket in multi-line element tags
+Preserve_PCDATA_Content=&Preserve whitespace in tags with PCDATA content
+Space_before_empty_close_tag=Ins&ert whitespace before closing empty end-tags
+Indent_using_tabs=&Indent using tabs
+Indent_using_spaces=I&ndent using spaces
+Indentation_size=In&dentation size:
+Indentation_size_tip=Indentation size
+Clear_all_blank_lines_UI_=Clear all &blank lines
+Format_comments=&Format comments
+Format_comments_join_lines=&Join lines
+Grammar_Constraints=Grammar Constraints
+Use_inferred_grammar_in_absence_of=&Use inferred grammar in absence of DTD/Schema
+Suggestion_Strategy=&Suggestion strategy:
+Suggestion_Strategy_Lax=Lax
+Suggestion_Strategy_Strict=Strict
+## tag info
+Element____1=Element :
+Content_Model____2=Content Model :
+Attribute____3=Attribute :
+Data_Type____4=Data Type :
+Enumerated_Values____5=Enumerated Values :
+Default_Value____6=Default Value :
+## copied from sse.ui
+SourceMenu_label=&Source
+Comment_label=Co&mment
+Comment_tooltip=Comment
+Comment_description=Comment
+Uncomment_label=&Uncomment
+Uncomment_tooltip=Uncomment
+Uncomment_description=Uncomment
+ToggleComment_label=Toggle Comment
+ToggleComment_tooltip=Toggle Comment
+ToggleComment_description=Toggle Comment
+AddBlockComment_label=Add Block Comment
+AddBlockComment_tooltip=Add Block Comment
+AddBlockComment_description=Add Block Comment
+RemoveBlockComment_label=Remove Block Comment
+RemoveBlockComment_tooltip=Remove Block Comment
+RemoveBlockComment_description=Remove Block Comment
+CleanupDocument_label=Cleanup Document...
+CleanupDocument_tooltip=Cleanup Document
+CleanupDocument_description=Cleanup Document
+FindOccurrences_label=Occurrences in File
+OpenFileFromSource_label=Op&en Selection
+OpenFileFromSource_tooltip=Open an editor on the selected link
+OpenFileFromSource_description=Open an editor on the selected link
+XMLContentOutlineConfiguration_0=Show Attributes
+XMLTyping_Auto_Complete=Automatically close
+XMLTyping_Auto_Remove=Automatically remove
+XMLTyping_Complete_Comments=&Comments
+XMLTyping_Close_Strings=A&ttribute values
+XMLTyping_Close_Brackets=(Parentheses) and [square] brac&kets
+XMLTyping_Complete_End_Tags=&Automatically close the tag
+XMLTyping_Complete_Elements=&Insert a matching end tag
+XMLTyping_Remove_End_Tags=E&nd tags when creating empty self-closing tags
+XMLTyping_Start_Tag=When typing a start tag
+XMLTyping_End_Tag=When typing an end tag
+StructureSelectEnclosing_label=Enclosing Element
+StructureSelectEnclosing_tooltip=Expand selection to include enclosing element
+StructureSelectEnclosing_description=Expand selection to include enclosing element
+StructureSelectNext_label=Next Element
+StructureSelectNext_tooltip=Expand selection to include next sibling
+StructureSelectNext_description=Expand selection to include next sibling
+StructureSelectPrevious_label=Previous Element
+StructureSelectPrevious_tooltip=Expand selection to include previous sibling
+StructureSelectPrevious_description=Expand selection to include previous sibling
+MESSAGE_XML_VALIDATION_MESSAGE_UI_=XML Validator validating {0}
+SyntaxColoringPage_0=Syntax Element:
+SyntaxColoringPage_2=Enable
+SyntaxColoringPage_3=&Bold
+SyntaxColoringPage_4=&Italic
+SyntaxColoringPage_5=&Strikethrough
+SyntaxColoringPage_6=&Underline
+EmptyFilePreferencePage_0=Expand the tree to edit preferences for a specific feature.
+_UI_STRUCTURED_TEXT_EDITOR_PREFS_LINK=XML editing preferences.  Note that some preferences may be set on the <a>{0}</a> preference page.
+Use_XInclude=Process XML &Inclusions
+Honour_all_schema_locations=&Honour all XML schema locations
+nextSibling_label=Next Sibling
+nextSibling_description=Go to Next Sibling
+previousSibling_label=Previous Sibling
+previousSibling_description=Go to Previous Sibling
+gotoMatchingTag_label=Matching Tag
+gotoMatchingTag_description=Go To Matching Tag
+gotoMatchingTag_start=Start tag of element <{0}>
+gotoMatchingTag_end=End tag of element <{0}>
+Open=Open ''{0}''
+_UI_BUTTON_SORT=Sort
+Validating_files=Validating files
+Indicate_no_grammar_specified=Indicate when no &grammar is specified:
+Indicate_no_grammar_specified_severities_error=Error
+Indicate_no_grammar_specified_severities_warning=Warning
+Indicate_no_grammar_specified_severities_ignore=Ignore
+MarkupValidation_files_label=Errors/Warnings
+MarkupValidation_files=&Enable markup validation
+Severity_error=Error
+Severity_warning=Warning
+Severity_ignore=Ignore
+Empty_element_tag=Invalid e&mpty element tag:
+End_tag_with_attributes=Invalid end &tag with attributes:
+Invalid_whitespace_before_tagname=Invalid &white space before tag name:
+Missing_closing_bracket=Missing &closing bracket:
+Missing_closing_quote=Missing closing &quote:
+Missing_end_tag=Missing e&nd tag:
+Missing_start_tag=Missing &start tag:
+Missing_quotes=Missing q&uotes:
+Namespace_in_pi_target=In&valid name space in PI:
+Tag_name_missing=Missing tag n&ame:
+Whitespace_at_start=Inva&lid white space at start:
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/AbstractCommentActionXMLDelegate.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/AbstractCommentActionXMLDelegate.java
new file mode 100644
index 0000000..e00b29d
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/AbstractCommentActionXMLDelegate.java
@@ -0,0 +1,117 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+
+package org.eclipse.wst.xml.ui.internal.actions;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.text.TextSelection;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.ui.IActionDelegate2;
+import org.eclipse.ui.IEditorActionDelegate;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IViewActionDelegate;
+import org.eclipse.ui.IViewPart;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.wst.xml.ui.internal.Logger;
+
+/**
+ * Abstract comment action delegate for XML editors
+ */
+abstract public class AbstractCommentActionXMLDelegate implements IEditorActionDelegate, IActionDelegate2, IViewActionDelegate {
+	static final String CLOSE_COMMENT = "-->"; //$NON-NLS-1$
+	static final String OPEN_COMMENT = "<!--"; //$NON-NLS-1$
+
+	IEditorPart fEditor;
+
+	public void setActiveEditor(IAction action, IEditorPart targetEditor) {
+		fEditor = targetEditor;
+	}
+
+	public void dispose() {
+		// nulling out just in case
+		fEditor = null;
+	}
+
+	public void runWithEvent(IAction action, Event event) {
+		run(action);
+	}
+
+	public void run(IAction action) {
+		if (fEditor instanceof ITextEditor) {
+			ITextEditor textEditor = (ITextEditor) fEditor;
+			IDocument document = textEditor.getDocumentProvider().getDocument(textEditor.getEditorInput());
+			if (document != null) {
+				// get current text selection
+				ITextSelection textSelection = getCurrentSelection();
+				if (textSelection.isEmpty()) {
+					return;
+				}
+
+				processAction(document, textSelection);
+			}
+		}
+	}
+
+	public void init(IViewPart view) {
+		// do nothing
+	}
+
+	public void selectionChanged(IAction action, ISelection selection) {
+		// do nothing
+	}
+
+	private ITextSelection getCurrentSelection() {
+		if (fEditor instanceof ITextEditor) {
+			ISelectionProvider provider = ((ITextEditor) fEditor).getSelectionProvider();
+			if (provider != null) {
+				ISelection selection = provider.getSelection();
+				if (selection instanceof ITextSelection) {
+					return (ITextSelection) selection;
+				}
+			}
+		}
+		return TextSelection.emptySelection();
+	}
+
+	abstract void processAction(IDocument document, ITextSelection textSelection);
+
+	void removeOpenCloseComments(IDocument document, int offset, int length) {
+		try {
+			int adjusted_length = length;
+
+			// remove open comments
+			String string = document.get(offset, length);
+			int index = string.lastIndexOf(OPEN_COMMENT);
+			while (index != -1) {
+				document.replace(offset + index, OPEN_COMMENT.length(), ""); //$NON-NLS-1$
+				index = string.lastIndexOf(OPEN_COMMENT, index - 1);
+				adjusted_length -= OPEN_COMMENT.length();
+			}
+
+			// remove close comments
+			string = document.get(offset, adjusted_length);
+			index = string.lastIndexOf(CLOSE_COMMENT);
+			while (index != -1) {
+				document.replace(offset + index, CLOSE_COMMENT.length(), ""); //$NON-NLS-1$
+				index = string.lastIndexOf(CLOSE_COMMENT, index - 1);
+			}
+		}
+		catch (BadLocationException e) {
+			Logger.log(Logger.WARNING_DEBUG, e.getMessage(), e);
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/AbstractNodeActionManager.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/AbstractNodeActionManager.java
new file mode 100644
index 0000000..be7e202
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/AbstractNodeActionManager.java
@@ -0,0 +1,690 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2009 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.actions;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.CMDescriptionBuilder;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.DOMContentBuilder;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.DOMContentBuilderImpl;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.DOMNamespaceHelper;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+import org.eclipse.wst.xml.ui.internal.XMLUIPlugin;
+import org.eclipse.wst.xml.ui.internal.editor.CMImageUtil;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImageHelper;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImages;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.ProcessingInstruction;
+
+public abstract class AbstractNodeActionManager extends BaseNodeActionManager {
+
+
+	/**
+	 * AddNodeAction
+	 */
+	public class AddNodeAction extends NodeAction {
+		protected CMNode cmnode;
+		protected String description;
+		protected int index;
+		protected int nodeType;
+		protected Node parent;
+		protected String undoDescription;
+
+
+		public AddNodeAction(CMNode cmnode, Node parent, int index) {
+			this.cmnode = cmnode;
+			this.parent = parent;
+			this.index = index;
+
+			String text = getLabel(parent, cmnode);
+			setText(text);
+			description = text;
+			undoDescription = XMLUIMessages._UI_MENU_ADD + " " + text; //$NON-NLS-1$ 
+			ImageDescriptor descriptor = CMImageUtil.getImageDescriptor(cmnode);
+			if (descriptor == null) {
+				descriptor = imageDescriptorCache.getImageDescriptor(cmnode);
+			}
+			setImageDescriptor(descriptor);
+		}
+
+
+		public AddNodeAction(int nodeType, Node parent, int index) {
+			this.nodeType = nodeType;
+			this.index = index;
+			this.parent = parent;
+
+			switch (nodeType) {
+				case Node.COMMENT_NODE : {
+					description = XMLUIMessages._UI_MENU_COMMENT;
+					undoDescription = XMLUIMessages._UI_MENU_ADD_COMMENT;
+					break;
+				}
+				case Node.PROCESSING_INSTRUCTION_NODE : {
+					description = XMLUIMessages._UI_MENU_PROCESSING_INSTRUCTION;
+					undoDescription = XMLUIMessages._UI_MENU_ADD_PROCESSING_INSTRUCTION;
+					break;
+				}
+				case Node.CDATA_SECTION_NODE : {
+					description = XMLUIMessages._UI_MENU_CDATA_SECTION;
+					undoDescription = XMLUIMessages._UI_MENU_ADD_CDATA_SECTION;
+					break;
+				}
+				case Node.TEXT_NODE : {
+					description = XMLUIMessages._UI_MENU_PCDATA;
+					undoDescription = XMLUIMessages._UI_MENU_ADD_PCDATA;
+					break;
+				}
+			}
+			setText(description);
+			setImageDescriptor(imageDescriptorCache.getImageDescriptor(new Integer(nodeType)));
+		}
+
+
+		protected void addNodeForCMNode() {
+			if (parent != null) {
+				insert(parent, cmnode, index);
+			}
+		}
+
+
+		protected void addNodeForNodeType() {
+			Document document = parent.getNodeType() == Node.DOCUMENT_NODE ? (Document) parent : parent.getOwnerDocument();
+			Node newChildNode = null;
+			boolean format = true;
+			switch (nodeType) {
+				case Node.COMMENT_NODE : {
+					newChildNode = document.createComment(XMLUIMessages._UI_COMMENT_VALUE);
+					break;
+				}
+				case Node.PROCESSING_INSTRUCTION_NODE : {
+					newChildNode = document.createProcessingInstruction(XMLUIMessages._UI_PI_TARGET_VALUE, XMLUIMessages._UI_PI_DATA_VALUE);
+					break;
+				}
+				case Node.CDATA_SECTION_NODE : {
+					newChildNode = document.createCDATASection(""); //$NON-NLS-1$
+					break;
+				}
+				case Node.TEXT_NODE : {
+					format = false;
+					newChildNode = document.createTextNode(parent.getNodeName());
+					break;
+				}
+			}
+
+			if (newChildNode != null) {
+				List list = new Vector(1);
+				list.add(newChildNode);
+				insertNodesAtIndex(parent, list, index, format);
+			}
+		}
+
+
+		public String getUndoDescription() {
+			return undoDescription;
+		}
+
+
+		public void run() {
+			if (validateEdit(getModel(), getWorkbenchWindowShell())) {
+				beginNodeAction(this);
+				if (cmnode != null) {
+					addNodeForCMNode();
+				}
+				else {
+					addNodeForNodeType();
+				}
+				endNodeAction(this);
+			}
+		}
+	}
+
+
+	/**
+	 * DeleteAction
+	 */
+	public class DeleteAction extends NodeAction {
+		protected List list;
+
+		public DeleteAction(List list) {
+			setText(XMLUIMessages._UI_MENU_REMOVE);
+			this.list = list;
+		}
+
+		public DeleteAction(Node node) {
+			setText(XMLUIMessages._UI_MENU_REMOVE);
+			list = new Vector();
+			list.add(node);
+		}
+
+		public String getUndoDescription() {
+			return XMLUIMessages.DELETE;
+		}
+
+		public void run() {
+			if (validateEdit(getModel(), getWorkbenchWindowShell())) {
+				beginNodeAction(this);
+	
+				for (Iterator i = list.iterator(); i.hasNext();) {
+					Node node = (Node) i.next();
+					if (node.getNodeType() == Node.ATTRIBUTE_NODE) {
+						Attr attr = (Attr) node;
+						attr.getOwnerElement().removeAttributeNode(attr);
+					}
+					else {
+						Node parent = node.getParentNode();
+						if (parent != null) {
+							Node previousSibling = node.getPreviousSibling();
+							if ((previousSibling != null) && isWhitespaceTextNode(previousSibling)) {
+								parent.removeChild(previousSibling);
+							}
+							parent.removeChild(node);
+						}
+					}
+				}
+
+				endNodeAction(this);
+			}
+		}
+	}
+
+
+	class ImageDescriptorCache {
+		protected ImageDescriptor attributeImage = XMLEditorPluginImageHelper.getInstance().getImageDescriptor(XMLEditorPluginImages.IMG_OBJ_ATTRIBUTE);
+		protected ImageDescriptor attributeReqImage = XMLEditorPluginImageHelper.getInstance().getImageDescriptor(XMLEditorPluginImages.IMG_OBJ_ATT_REQ_OBJ);
+		protected ImageDescriptor cdataSectionImage = XMLEditorPluginImageHelper.getInstance().getImageDescriptor(XMLEditorPluginImages.IMG_OBJ_CDATASECTION);
+		protected ImageDescriptor commentImage = XMLEditorPluginImageHelper.getInstance().getImageDescriptor(XMLEditorPluginImages.IMG_OBJ_COMMENT);
+		protected ImageDescriptor elementImage = XMLEditorPluginImageHelper.getInstance().getImageDescriptor(XMLEditorPluginImages.IMG_OBJ_ELEMENT);
+		protected ImageDescriptor piImage = XMLEditorPluginImageHelper.getInstance().getImageDescriptor(XMLEditorPluginImages.IMG_OBJ_PROCESSINGINSTRUCTION);
+		protected ImageDescriptor textImage = XMLEditorPluginImageHelper.getInstance().getImageDescriptor(XMLEditorPluginImages.IMG_OBJ_TXTEXT);
+
+		public ImageDescriptor getImageDescriptor(Object object) {
+			ImageDescriptor result = null;
+			if (object instanceof CMNode) {
+				CMNode cmnode = (CMNode) object;
+				switch (cmnode.getNodeType()) {
+					case CMNode.ATTRIBUTE_DECLARATION : {
+						result = CMImageUtil.getImageDescriptor(cmnode);
+						if (result == null) {
+							if (((CMAttributeDeclaration) cmnode).getUsage() == CMAttributeDeclaration.REQUIRED) {
+								result = attributeReqImage;
+							}
+							else {
+								result = attributeImage;
+							}
+						}
+						break;
+					}
+					case CMNode.DATA_TYPE : {
+						result = textImage;
+						break;
+					}
+					case CMNode.ELEMENT_DECLARATION : {
+						result = CMImageUtil.getImageDescriptor(cmnode);
+						if (result == null) {
+							result = elementImage;
+						}
+						break;
+					}
+					case CMNode.GROUP : {
+						result = elementImage;
+						break;
+					}
+				}
+			}
+			else if (object instanceof Integer) {
+				Integer integer = (Integer) object;
+				switch (integer.intValue()) {
+					case Node.COMMENT_NODE : {
+						result = commentImage;
+						break;
+					}
+					case Node.PROCESSING_INSTRUCTION_NODE : {
+						result = piImage;
+						break;
+					}
+					case Node.CDATA_SECTION_NODE : {
+						result = cdataSectionImage;
+						break;
+					}
+					case Node.TEXT_NODE : {
+						result = textImage;
+						break;
+					}
+				}
+			}
+			return result;
+		}
+	}
+
+	// TODO... remove this class. I'm pretty sure it is no longer used by
+	// anyone.
+	/**
+	 * @depracated
+	 */
+	public class InsertAction extends NodeAction {
+		protected String description;
+		protected int index;
+		protected int nodeType;
+		protected Node parent;
+
+		public InsertAction(int nodeType, Node parent, int index) {
+			this.nodeType = nodeType;
+			this.index = index;
+			this.parent = parent;
+			switch (nodeType) {
+				case Node.COMMENT_NODE : {
+					description = XMLUIMessages._UI_MENU_COMMENT;
+					break;
+				}
+				case Node.PROCESSING_INSTRUCTION_NODE : {
+					description = XMLUIMessages._UI_MENU_PROCESSING_INSTRUCTION;
+					break;
+				}
+				case Node.CDATA_SECTION_NODE : {
+					description = XMLUIMessages._UI_MENU_CDATA_SECTION;
+					break;
+				}
+				case Node.TEXT_NODE : {
+					description = XMLUIMessages._UI_MENU_PCDATA;
+					break;
+				}
+			}
+			setText(description);
+			setImageDescriptor(imageDescriptorCache.getImageDescriptor(new Integer(nodeType)));
+		}
+
+		public InsertAction(int nodeType, Node parent, int index, String title) {
+			this.nodeType = nodeType;
+			this.index = index;
+			this.parent = parent;
+			description = title;
+			setText(description);
+			setImageDescriptor(imageDescriptorCache.getImageDescriptor(new Integer(nodeType)));
+		}
+
+		public String getUndoDescription() {
+			return XMLUIMessages._UI_MENU_ADD + " " + description; //$NON-NLS-1$ 
+		}
+
+		public void run() {
+			if (validateEdit(getModel(), getWorkbenchWindowShell())) {
+				beginNodeAction(this);
+	
+				Document document = parent.getNodeType() == Node.DOCUMENT_NODE ? (Document) parent : parent.getOwnerDocument();
+				Node newChildNode = null;
+				boolean format = true;
+				switch (nodeType) {
+					case Node.COMMENT_NODE : {
+						newChildNode = document.createComment(XMLUIMessages._UI_COMMENT_VALUE);
+						break;
+					}
+					case Node.PROCESSING_INSTRUCTION_NODE : {
+						newChildNode = document.createProcessingInstruction(XMLUIMessages._UI_PI_TARGET_VALUE, XMLUIMessages._UI_PI_DATA_VALUE);
+						break;
+					}
+					case Node.CDATA_SECTION_NODE : {
+						newChildNode = document.createCDATASection(""); //$NON-NLS-1$
+						break;
+					}
+					case Node.TEXT_NODE : {
+						format = false;
+						newChildNode = document.createTextNode(parent.getNodeName());
+						break;
+					}
+				}
+	
+				if (newChildNode != null) {
+					List list = new Vector(1);
+					list.add(newChildNode);
+					insertNodesAtIndex(parent, list, index, format);
+				}
+	
+				endNodeAction(this);
+			}
+		}
+	}
+
+
+	/**
+	 * ReplaceNodeAction
+	 */
+	public class ReplaceNodeAction extends NodeAction {
+		protected CMNode cmnode;
+		protected String description;
+		protected int endIndex;
+		protected Node parent;
+		protected int startIndex;
+
+
+		public ReplaceNodeAction(Node parent, CMNode cmnode, int startIndex, int endIndex) {
+			this.parent = parent;
+			this.cmnode = cmnode;
+			this.startIndex = startIndex;
+			this.endIndex = endIndex;
+
+			setText(getLabel(parent, cmnode));
+			setImageDescriptor(imageDescriptorCache.getImageDescriptor(cmnode));
+		}
+
+		public String getUndoDescription() {
+			String result = XMLUIMessages._UI_LABEL_UNDO_REPLACE_DESCRIPTION;
+			result += " " + getLabel(parent, cmnode); //$NON-NLS-1$
+			return result;
+		}
+
+		public void run() {
+			if (validateEdit(getModel(), getWorkbenchWindowShell())) {
+				beginNodeAction(this);
+	
+				if ((parent != null) && (cmnode != null)) {
+					remove(parent, startIndex, endIndex);
+					insert(parent, cmnode, startIndex);
+				}
+				endNodeAction(this);
+			}
+		}
+	}
+
+	protected ImageDescriptorCache imageDescriptorCache = new ImageDescriptorCache();
+	protected Viewer fViewer;
+
+	public AbstractNodeActionManager(IStructuredModel model, ModelQuery modelQuery, Viewer viewer) {
+		super(model, modelQuery);
+		this.fViewer = viewer;
+	}
+
+
+	public void beginNodeAction(NodeAction action) {
+		fModel.beginRecording(action, action.getUndoDescription());
+	}
+
+
+	protected Action createAddAttributeAction(Element parent, CMAttributeDeclaration ad) {
+		Action action = null;
+		if (ad == null) {
+			action = new EditAttributeAction(this, parent, null, XMLUIMessages._UI_MENU_NEW_ATTRIBUTE, XMLUIMessages._UI_MENU_NEW_ATTRIBUTE_TITLE);
+		}
+		else {
+			action = new AddNodeAction(ad, parent, -1);
+		}
+		return action;
+	}
+
+
+	protected Action createAddCDataSectionAction(Node parent, int index) {
+		return new AddNodeAction(Node.CDATA_SECTION_NODE, parent, index);
+	}
+
+
+	protected Action createAddCommentAction(Node parent, int index) {
+		return new AddNodeAction(Node.COMMENT_NODE, parent, index);
+	}
+
+
+	protected Action createAddDoctypeAction(Document document, int index) {
+		return new EditDoctypeAction(fModel, document, fModel.getBaseLocation(), XMLUIMessages._UI_MENU_ADD_DTD_INFORMATION);
+	}
+
+
+	protected Action createAddElementAction(Node parent, CMElementDeclaration ed, int index) {
+		Action action = null;
+		if (ed == null) {
+			action = new EditElementAction(this, parent, index, XMLUIMessages._UI_MENU_NEW_ELEMENT, XMLUIMessages._UI_MENU_NEW_ELEMENT_TITLE);
+		}
+		else {
+			action = new AddNodeAction(ed, parent, index);
+		}
+		return action;
+	}
+
+
+	protected Action createAddPCDataAction(Node parent, CMDataType dataType, int index) {
+		Action action = null;
+		if (dataType == null) {
+			action = new AddNodeAction(Node.TEXT_NODE, parent, index);
+		}
+		else {
+			action = new AddNodeAction(dataType, parent, index);
+		}
+		return action;
+	}
+
+
+	protected Action createAddProcessingInstructionAction(Node parent, int index) {
+		Node refChild = getRefChildNodeAtIndex(parent, index);
+		Action action = new EditProcessingInstructionAction(this, parent, refChild, XMLUIMessages._UI_MENU_ADD_PROCESSING_INSTRUCTION, XMLUIMessages.ADD_PROCESSING_INSTRUCTION);
+		action.setImageDescriptor(imageDescriptorCache.getImageDescriptor(new Integer(Node.PROCESSING_INSTRUCTION_NODE)));
+		return action;
+	}
+
+
+	protected Action createAddSchemaInfoAction(Element element) {
+		return new EditSchemaInfoAction(this, element.getOwnerDocument(), fModel.getBaseLocation(), XMLUIMessages._UI_MENU_ADD_SCHEMA_INFORMATION);
+	}
+
+
+	protected Action createDeleteAction(List selection) {
+		DeleteAction deleteAction = new DeleteAction(selection);
+		deleteAction.setEnabled(selection.size() > 0);
+		return deleteAction;
+	}
+
+
+	public DOMContentBuilder createDOMContentBuilder(Document document) {
+		DOMContentBuilderImpl builder = new DOMContentBuilderImpl(document);
+		return builder;
+	}
+
+
+	protected Action createEditAttributeAction(Attr attr, CMAttributeDeclaration ad) {
+		return new EditAttributeAction(this, attr.getOwnerElement(), attr, XMLUIMessages._UI_MENU_EDIT_ATTRIBUTE, XMLUIMessages._UI_MENU_EDIT_ATTRIBUTE_TITLE);
+	}
+
+
+	protected Action createEditDoctypeAction(DocumentType doctype) {
+		return new EditDoctypeAction(fModel, doctype, fModel.getBaseLocation(), XMLUIMessages._UI_MENU_EDIT_DOCTYPE);
+	}
+
+
+	protected Action createEditProcessingInstructionAction(ProcessingInstruction pi) {
+		return new EditProcessingInstructionAction(this, pi, XMLUIMessages._UI_MENU_EDIT_PROCESSING_INSTRUCTION, XMLUIMessages._UI_MENU_EDIT_PROCESSING_INSTRUCTION_TITLE);
+	}
+
+
+	protected Action createEditSchemaInfoAction(Element element) {
+		return new EditSchemaInfoAction(this, element.getOwnerDocument(), fModel.getBaseLocation(), XMLUIMessages._UI_MENU_EDIT_NAMESPACES);
+	}
+
+
+	protected Action createRenameAction(Node node) {
+		Action result = null;
+		if (node instanceof Element) {
+			result = new EditElementAction(this, (Element) node, XMLUIMessages._UI_MENU_RENAME, XMLUIMessages._UI_MENU_RENAME_TITLE);
+		}
+		return result;
+	}
+
+
+	protected Action createReplaceAction(Node parent, CMNode cmnode, int startIndex, int endIndex) {
+		return new ReplaceNodeAction(parent, cmnode, startIndex, endIndex);
+	}
+
+	public void endNodeAction(NodeAction action) {
+		fModel.endRecording(action);
+	}
+
+
+
+	public void fillContextMenu(IMenuManager menuManager, ISelection selection) {
+		try {
+			List selectionList = new ArrayList();
+			if (selection instanceof IStructuredSelection) {
+				IStructuredSelection es = (IStructuredSelection) selection;
+				selectionList.addAll(es.toList());
+			}
+
+			contributeActions(menuManager, selectionList);
+		}
+		catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
+
+	/**
+	 * 
+	 */
+	public String getLabel(Node parent, CMNode cmnode) {
+		String result = "?" + cmnode + "?"; //$NON-NLS-1$ //$NON-NLS-2$
+		if (cmnode != null) {
+			// https://bugs.eclipse.org/bugs/show_bug.cgi?id=155800
+			result = cmnode.getNodeName();
+			if(result == null) {
+				result = (String) cmnode.getProperty("description"); //$NON-NLS-1$
+			}
+			if (result == null || result.length() == 0) {
+				if (cmnode.getNodeType() == CMNode.GROUP) {
+					CMDescriptionBuilder descriptionBuilder = new CMDescriptionBuilder();
+					result = descriptionBuilder.buildDescription(cmnode);
+				}
+				else {
+					result = DOMNamespaceHelper.computeName(cmnode, parent, null);
+				}
+			}
+		}
+		return result;
+	}
+
+
+	public IStructuredModel getModel() {
+		return fModel;
+	}
+
+
+	public Shell getWorkbenchWindowShell() {
+		return XMLUIPlugin.getInstance().getWorkbench().getActiveWorkbenchWindow().getShell();
+	}
+
+
+	public void insert(Node parent, CMNode cmnode, int index) {
+		Document document = parent.getNodeType() == Node.DOCUMENT_NODE ? (Document) parent : parent.getOwnerDocument();
+		DOMContentBuilder builder = createDOMContentBuilder(document);
+		builder.setBuildPolicy(DOMContentBuilder.BUILD_ONLY_REQUIRED_CONTENT);
+		builder.build(parent, cmnode);
+		insertNodesAtIndex(parent, builder.getResult(), index);
+	}
+
+
+	public void insertNodesAtIndex(Node parent, List list, int index) {
+		insertNodesAtIndex(parent, list, index, true);
+	}
+
+
+	public void insertNodesAtIndex(Node parent, List list, int index, boolean format) {
+		NodeList nodeList = parent.getChildNodes();
+		if (index == -1) {
+			index = nodeList.getLength();
+		}
+		Node refChild = (index < nodeList.getLength()) ? nodeList.item(index) : null;
+
+		// here we consider the case where the previous node is a 'white
+		// space' Text node
+		// we should really do the insert before this node
+		//
+		int prevIndex = index - 1;
+		Node prevChild = (prevIndex < nodeList.getLength()) ? nodeList.item(prevIndex) : null;
+		if (isWhitespaceTextNode(prevChild)) {
+			refChild = prevChild;
+		}
+
+		for (Iterator i = list.iterator(); i.hasNext();) {
+			Node newNode = (Node) i.next();
+
+			if (newNode.getNodeType() == Node.ATTRIBUTE_NODE) {
+				Element parentElement = (Element) parent;
+				parentElement.setAttributeNode((Attr) newNode);
+			}
+			else {
+				parent.insertBefore(newNode, refChild);
+			}
+		}
+
+		boolean formatDeep = false;
+		for (Iterator i = list.iterator(); i.hasNext();) {
+			Node newNode = (Node) i.next();
+			if (newNode.getNodeType() == Node.ELEMENT_NODE) {
+				formatDeep = true;
+			}
+
+			if (format) {
+				reformat(newNode, formatDeep);
+			}
+		}
+
+		setViewerSelection(list);
+	}
+
+
+	/**
+	 * This method is abstract since currently, the sed editor is required to
+	 * perform formating and we don't want to create a dependency on the sed
+	 * editor.
+	 */
+	public abstract void reformat(Node parent, boolean deep);
+
+
+	public void remove(Node parent, int startIndex, int endIndex) {
+		NodeList nodeList = parent.getChildNodes();
+		for (int i = endIndex; i >= startIndex; i--) {
+			Node node = nodeList.item(i);
+			if (node != null) {
+				parent.removeChild(node);
+			}
+		}
+	}
+
+
+	public void setViewerSelection(List list) {
+		if (fViewer != null) {
+			fViewer.setSelection(new StructuredSelection(list), true);
+		}
+	}
+
+
+	public void setViewerSelection(Node node) {
+		if (fViewer != null) {
+			fViewer.setSelection(new StructuredSelection(node), true);
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/ActionContributorXML.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/ActionContributorXML.java
new file mode 100644
index 0000000..c4f8285
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/ActionContributorXML.java
@@ -0,0 +1,224 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2008 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.actions;
+
+import java.util.ResourceBundle;
+
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.IStatusLineManager;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbenchActionConstants;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
+import org.eclipse.ui.texteditor.RetargetTextEditorAction;
+import org.eclipse.wst.sse.ui.internal.actions.ActionContributor;
+import org.eclipse.wst.sse.ui.internal.actions.ActionDefinitionIds;
+import org.eclipse.wst.sse.ui.internal.actions.StructuredTextEditorActionConstants;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+
+/**
+ * XMLEditorActionContributor
+ * 
+ * This class should not be used inside multi page editor's
+ * ActionBarContributor, since cascaded init() call from the
+ * ActionBarContributor will causes exception and it leads to lose whole
+ * toolbars.
+ * 
+ * Instead, use SourcePageActionContributor for source page contributor of
+ * multi page editor.
+ * 
+ * Note that this class is still valid for single page editor.
+ */
+public class ActionContributorXML extends ActionContributor {
+	private static final String[] EDITOR_IDS = {"org.eclipse.core.runtime.xml.source", "org.eclipse.core.runtime.xml.source2", "org.eclipse.wst.sse.ui.StructuredTextEditor"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+	private static final String GO_TO_MATCHING_TAG_ID = "org.eclipse.wst.xml.ui.gotoMatchingTag"; //$NON-NLS-1$
+	
+	protected RetargetTextEditorAction fCleanupDocument = null;
+	protected RetargetTextEditorAction fComment = null;
+	protected RetargetTextEditorAction fContentAssist = null;
+	protected RetargetTextEditorAction fFindOccurrences = null;
+	protected RetargetTextEditorAction fFormatActiveElements = null;
+	protected RetargetTextEditorAction fFormatDocument = null;
+	protected RetargetTextEditorAction fOpenFileAction = null; // open file
+
+	protected RetargetTextEditorAction fUncomment = null;
+	private GoToMatchingTagAction fGoToMatchingTagAction;
+
+	public ActionContributorXML() {
+		super();
+
+		ResourceBundle resourceBundle = XMLUIMessages.getResourceBundle();
+
+		fContentAssist = new RetargetTextEditorAction(resourceBundle, ""); //$NON-NLS-1$
+		fContentAssist.setActionDefinitionId(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS);
+
+		// source commands
+		fCleanupDocument = new RetargetTextEditorAction(resourceBundle, ""); //$NON-NLS-1$
+		fCleanupDocument.setActionDefinitionId(ActionDefinitionIds.CLEANUP_DOCUMENT);
+
+		fFormatDocument = new RetargetTextEditorAction(resourceBundle, ""); //$NON-NLS-1$
+		fFormatDocument.setActionDefinitionId(ActionDefinitionIds.FORMAT_DOCUMENT);
+
+		fFormatActiveElements = new RetargetTextEditorAction(resourceBundle, ""); //$NON-NLS-1$
+		fFormatActiveElements.setActionDefinitionId(ActionDefinitionIds.FORMAT_ACTIVE_ELEMENTS);
+
+		// navigate commands
+		fOpenFileAction = new RetargetTextEditorAction(resourceBundle, ""); //$NON-NLS-1$
+		fOpenFileAction.setActionDefinitionId(ActionDefinitionIds.OPEN_FILE);
+
+		fFindOccurrences = new RetargetTextEditorAction(resourceBundle, ""); //$NON-NLS-1$
+		fFindOccurrences.setActionDefinitionId(ActionDefinitionIds.FIND_OCCURRENCES);
+
+		fGoToMatchingTagAction = new GoToMatchingTagAction(resourceBundle, "gotoMatchingTag_", null); //$NON-NLS-1$
+		fGoToMatchingTagAction.setActionDefinitionId(GO_TO_MATCHING_TAG_ID);
+		fGoToMatchingTagAction.setId(GO_TO_MATCHING_TAG_ID);
+	}
+	
+	/**
+	 * @see org.eclipse.ui.part.EditorActionBarContributor#contributeToMenu(IMenuManager)
+	 */
+	public void contributeToMenu(IMenuManager menu) {
+		// navigate commands
+		IMenuManager navigateMenu = menu.findMenuUsingPath(IWorkbenchActionConstants.M_NAVIGATE);
+		if (navigateMenu != null) {
+			navigateMenu.appendToGroup(IWorkbenchActionConstants.OPEN_EXT, fCommandsSeparator);
+			navigateMenu.appendToGroup(IWorkbenchActionConstants.OPEN_EXT, fOpenFileAction);
+
+			IMenuManager gotoGroup = navigateMenu.findMenuUsingPath(IWorkbenchActionConstants.GO_TO);
+			if (gotoGroup != null) {
+				gotoGroup.appendToGroup("matchingBegin", fGoToMatchingTagAction); //$NON-NLS-1$
+			}
+		}
+		super.contributeToMenu(menu);
+	}
+
+	protected void addToMenu(IMenuManager menu) {
+/*
+		// edit commands
+		IMenuManager editMenu = menu.findMenuUsingPath(IWorkbenchActionConstants.M_EDIT);
+		if (editMenu != null) {
+			editMenu.add(fCommandsSeparator);
+			editMenu.add(fToggleInsertModeAction);
+			editMenu.add(fCommandsSeparator);
+			editMenu.add(fExpandSelectionToMenu);
+			editMenu.add(fCommandsSeparator);
+			editMenu.add(fContentAssist);
+			editMenu.add(fMenuAdditionsGroupMarker);
+		}
+
+		// source commands
+		String sourceMenuLabel = XMLUIMessages.SourceMenu_label;
+		String sourceMenuId = "sourceMenuId"; //$NON-NLS-1$
+		IMenuManager sourceMenu = new MenuManager(sourceMenuLabel, sourceMenuId);
+		menu.insertAfter(IWorkbenchActionConstants.M_EDIT, sourceMenu);
+		if (sourceMenu != null) {
+			sourceMenu.add(fCommandsSeparator);
+			sourceMenu.add(fToggleComment);
+			sourceMenu.add(fAddBlockComment);
+			sourceMenu.add(fRemoveBlockComment);
+			sourceMenu.add(fShiftRight);
+			sourceMenu.add(fShiftLeft);
+			sourceMenu.add(fCleanupDocument);
+			sourceMenu.add(fFormatDocument);
+			sourceMenu.add(fFormatActiveElements);
+			sourceMenu.add(fCommandsSeparator);
+			sourceMenu.add(fFindOccurrences);
+		}
+
+		// navigate commands
+		IMenuManager navigateMenu = menu.findMenuUsingPath(IWorkbenchActionConstants.M_NAVIGATE);
+		if (navigateMenu != null) {
+			navigateMenu.appendToGroup(IWorkbenchActionConstants.OPEN_EXT, fCommandsSeparator);
+			navigateMenu.appendToGroup(IWorkbenchActionConstants.OPEN_EXT, fOpenFileAction);
+
+			IMenuManager gotoGroup = navigateMenu.findMenuUsingPath(IWorkbenchActionConstants.GO_TO);
+			if (gotoGroup != null) {
+				gotoGroup.add(fGotoMatchingBracketAction);
+				gotoGroup.add(fGoToMatchingTagAction);
+				gotoGroup.add(new Separator());
+			}
+		}
+*/
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.wst.sse.ui.edit.util.ActionContributor#getExtensionIDs()
+	 */
+	protected String[] getExtensionIDs() {
+		return EDITOR_IDS;
+	}
+
+	/**
+	 * @see org.eclipse.ui.IEditorActionBarContributor#setActiveEditor(IEditorPart)
+	 */
+	public void setActiveEditor(IEditorPart activeEditor) {
+		if (getActiveEditorPart() == activeEditor) {
+			return;
+		}
+		super.setActiveEditor(activeEditor);
+
+		IActionBars actionBars = getActionBars();
+		if (actionBars != null) {
+			IStatusLineManager statusLineManager = actionBars.getStatusLineManager();
+			if (statusLineManager != null) {
+				statusLineManager.setMessage(null);
+				statusLineManager.setErrorMessage(null);
+			}
+		}
+
+		ITextEditor textEditor = getTextEditor(activeEditor);
+
+		fContentAssist.setAction(getAction(textEditor, StructuredTextEditorActionConstants.ACTION_NAME_CONTENTASSIST_PROPOSALS));
+
+		fCleanupDocument.setAction(getAction(textEditor, StructuredTextEditorActionConstants.ACTION_NAME_CLEANUP_DOCUMENT));
+		fFormatDocument.setAction(getAction(textEditor, StructuredTextEditorActionConstants.ACTION_NAME_FORMAT_DOCUMENT));
+		fFormatActiveElements.setAction(getAction(textEditor, StructuredTextEditorActionConstants.ACTION_NAME_FORMAT_ACTIVE_ELEMENTS));
+		fCleanupDocument.setEnabled((textEditor != null) && textEditor.isEditable());
+		fFormatDocument.setEnabled((textEditor != null) && textEditor.isEditable());
+		fFormatActiveElements.setEnabled((textEditor != null) && textEditor.isEditable());
+
+		fOpenFileAction.setAction(getAction(textEditor, StructuredTextEditorActionConstants.ACTION_NAME_OPEN_FILE));
+
+		fFindOccurrences.setAction(getAction(textEditor, StructuredTextEditorActionConstants.ACTION_NAME_FIND_OCCURRENCES));
+
+		fGoToMatchingTagAction.setEditor(textEditor);
+		if (textEditor != null) {
+			textEditor.setAction(GO_TO_MATCHING_TAG_ID, fGoToMatchingTagAction);
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.wst.sse.ui.ISourceViewerActionBarContributor#setViewerSpecificContributionsEnabled(boolean)
+	 */
+	public void setViewerSpecificContributionsEnabled(boolean enabled) {
+		super.setViewerSpecificContributionsEnabled(enabled);
+
+		fContentAssist.setEnabled(enabled);
+		// cleanup and format document actions do not rely on source viewer
+		// being enabled
+		// fCleanupDocument.setEnabled(enabled);
+		// fFormatDocument.setEnabled(enabled);
+
+		fFormatActiveElements.setEnabled(enabled);
+		fOpenFileAction.setEnabled(enabled);
+		fFindOccurrences.setEnabled(enabled);
+
+		fGoToMatchingTagAction.setEnabled(enabled);
+		fGotoMatchingBracketAction.setEnabled(enabled);
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/AddBlockCommentActionXMLDelegate.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/AddBlockCommentActionXMLDelegate.java
new file mode 100644
index 0000000..a038376
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/AddBlockCommentActionXMLDelegate.java
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+
+package org.eclipse.wst.xml.ui.internal.actions;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
+import org.eclipse.wst.xml.core.internal.document.CommentImpl;
+import org.eclipse.wst.xml.ui.internal.Logger;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+
+/**
+ * Add block comment action delegate for XML editor
+ */
+public class AddBlockCommentActionXMLDelegate extends AbstractCommentActionXMLDelegate {
+
+	public void init(IAction action) {
+		if (action != null) {
+			action.setText(XMLUIMessages.AddBlockComment_label);
+			action.setToolTipText(XMLUIMessages.AddBlockComment_tooltip);
+			action.setDescription(XMLUIMessages.AddBlockComment_description);
+		}
+	}
+
+	void processAction(IDocument document, ITextSelection textSelection) {
+		IStructuredModel model = StructuredModelManager.getModelManager().getExistingModelForEdit(document);
+		if (model != null) {
+			try {
+				IndexedRegion selectionStartIndexedRegion = model.getIndexedRegion(textSelection.getOffset());
+				IndexedRegion selectionEndIndexedRegion = model.getIndexedRegion(textSelection.getOffset() + textSelection.getLength());
+
+				if (selectionStartIndexedRegion == null) {
+					return;
+				}
+				if ((selectionEndIndexedRegion == null) && (textSelection.getLength() > 0)) {
+					selectionEndIndexedRegion = model.getIndexedRegion(textSelection.getOffset() + textSelection.getLength() - 1);
+				}
+				if (selectionEndIndexedRegion == null) {
+					return;
+				}
+
+				int openCommentOffset = selectionStartIndexedRegion.getStartOffset();
+				int closeCommentOffset = selectionEndIndexedRegion.getEndOffset() + OPEN_COMMENT.length();
+
+
+				if ((textSelection.getLength() == 0) && (selectionStartIndexedRegion instanceof CommentImpl)) {
+					return;
+				}
+
+				model.beginRecording(this, XMLUIMessages.AddBlockComment_tooltip);
+				model.aboutToChangeModel();
+
+				try {
+					document.replace(openCommentOffset, 0, OPEN_COMMENT);
+					document.replace(closeCommentOffset, 0, CLOSE_COMMENT);
+					removeOpenCloseComments(document, openCommentOffset + OPEN_COMMENT.length(), closeCommentOffset - openCommentOffset - CLOSE_COMMENT.length());
+				}
+				catch (BadLocationException e) {
+					Logger.log(Logger.WARNING_DEBUG, e.getMessage(), e);
+				}
+				finally {
+					model.changedModel();
+					model.endRecording(this);
+				}
+			}
+			finally {
+				model.releaseFromEdit();
+			}
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/BaseNodeActionManager.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/BaseNodeActionManager.java
new file mode 100644
index 0000000..4465152
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/BaseNodeActionManager.java
@@ -0,0 +1,521 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.actions;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQueryAction;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.ProcessingInstruction;
+
+public abstract class BaseNodeActionManager {
+
+
+	/**
+	 * MyMenuManager
+	 */
+	public static class MyMenuManager extends MenuManager {
+		protected String title;
+
+		public MyMenuManager(String s) {
+			super(s);
+			title = s;
+		}
+
+		public boolean isEnabled() {
+			return !isEmpty();
+		}
+
+		public String toString() {
+			return title;
+		}
+	}
+
+	public static DocumentType getDoctype(Node node) {
+		Document document = (node.getNodeType() == Node.DOCUMENT_NODE) ? (Document) node : node.getOwnerDocument();
+		return document.getDoctype();
+	}
+
+	protected MenuBuilder menuBuilder = new MenuBuilder();
+	protected IStructuredModel fModel;
+	protected ModelQuery modelQuery;
+
+	protected BaseNodeActionManager(IStructuredModel model, ModelQuery modelQuery) {
+		this.fModel = model;
+		this.modelQuery = modelQuery;
+	}
+
+
+	protected void addActionHelper(IMenuManager menu, List modelQueryActionList) {
+		List actionList = new Vector();
+		for (Iterator i = modelQueryActionList.iterator(); i.hasNext();) {
+			ModelQueryAction action = (ModelQueryAction) i.next();
+			if (action.getCMNode() != null) {
+				int cmNodeType = action.getCMNode().getNodeType();
+				if (action.getKind() == ModelQueryAction.INSERT) {
+					switch (cmNodeType) {
+						case CMNode.ATTRIBUTE_DECLARATION : {
+							actionList.add(createAddAttributeAction((Element) action.getParent(), (CMAttributeDeclaration) action.getCMNode()));
+							break;
+						}
+						case CMNode.ELEMENT_DECLARATION : {
+							actionList.add(createAddElementAction(action.getParent(), (CMElementDeclaration) action.getCMNode(), action.getStartIndex()));
+							break;
+						}
+					}
+				}
+				else if (action.getKind() == ModelQueryAction.REPLACE) {
+					if ((action.getParent() != null) && (action.getCMNode() != null)) {
+						actionList.add(createReplaceAction(action.getParent(), action.getCMNode(), action.getStartIndex(), action.getEndIndex()));
+					}
+				}
+			}
+		}
+		menuBuilder.populateMenu(menu, actionList, false);
+	}
+
+	protected void contributeAction(IMenuManager menu, Action action) {
+		if (action != null) {
+			menu.add(action);
+		}
+	}
+
+
+	public void contributeActions(IMenuManager menu, List selection) {
+		int editMode = modelQuery.getEditMode();
+		int ic = ModelQuery.INCLUDE_CHILD_NODES;
+		int vc = (editMode == ModelQuery.EDIT_MODE_CONSTRAINED_STRICT) ? ModelQuery.VALIDITY_STRICT : ModelQuery.VALIDITY_NONE;
+
+		List implicitlySelectedNodeList = null;
+
+		if (selection.size() > 0) {
+			implicitlySelectedNodeList = getSelectedNodes(selection, true);
+
+			// contribute delete actions
+			contributeDeleteActions(menu, implicitlySelectedNodeList, ic, vc);
+		}
+
+		if (selection.size() == 1) {
+			Node node = (Node) selection.get(0);
+
+			// contribute edit actions
+			contributeEditActions(menu, node);
+
+			// contribute add child actions
+			contributeAddChildActions(menu, node, ic, vc);
+
+			// contribute add before actions
+			contributeAddSiblingActions(menu, node, ic, vc);
+		}
+
+		if (selection.size() > 0) {
+			// contribute replace actions
+			contributeReplaceActions(menu, implicitlySelectedNodeList, ic, vc);
+		}
+
+		if (selection.size() == 0) {
+			Document document = ((IDOMModel) fModel).getDocument();
+			contributeAddDocumentChildActions(menu, document, ic, vc);
+			contributeEditGrammarInformationActions(menu, document);
+		}
+	}
+
+	protected boolean canContributeChildActions(Node node){
+		return true;
+	}
+
+	protected void contributeAddChildActions(IMenuManager menu, Node node, int ic, int vc) {
+		int nodeType = node.getNodeType();
+
+		if (nodeType == Node.ELEMENT_NODE && canContributeChildActions(node)) {
+			// 'Add Child...' and 'Add Attribute...' actions
+			//
+			Element element = (Element) node;
+
+			IMenuManager addAttributeMenu = new MyMenuManager(XMLUIMessages._UI_MENU_ADD_ATTRIBUTE);
+			IMenuManager addChildMenu = new MyMenuManager(XMLUIMessages._UI_MENU_ADD_CHILD);
+			menu.add(addAttributeMenu);
+			menu.add(addChildMenu);
+		
+			CMElementDeclaration ed = modelQuery.getCMElementDeclaration(element);
+			if (ed != null) {
+				// add insert attribute actions
+				//
+				List modelQueryActionList = new ArrayList();
+				modelQuery.getInsertActions(element, ed, -1, ModelQuery.INCLUDE_ATTRIBUTES, vc, modelQueryActionList);
+				addActionHelper(addAttributeMenu, modelQueryActionList);
+				// add insert child node actions
+				//
+				modelQueryActionList = new ArrayList();
+				modelQuery.getInsertActions(element, ed, -1, ic, vc, modelQueryActionList);
+				addActionHelper(addChildMenu, modelQueryActionList);
+			}
+
+			// add PI and COMMENT
+			contributePIAndCommentActions(addChildMenu, element, ed, -1);
+
+			// add PCDATA, CDATA_SECTION
+			contributeTextNodeActions(addChildMenu, element, ed, -1);
+
+			// add NEW ELEMENT
+			contributeUnconstrainedAddElementAction(addChildMenu, element, ed, -1);
+
+			// add ATTRIBUTE
+			contributeUnconstrainedAttributeActions(addAttributeMenu, element, ed);
+		}
+	}
+
+
+	protected void contributeAddDocumentChildActions(IMenuManager menu, Document document, int ic, int vc) {
+		IMenuManager addChildMenu = new MyMenuManager(XMLUIMessages._UI_MENU_ADD_CHILD);
+		menu.add(addChildMenu);
+
+		// add PI and COMMENT
+		contributePIAndCommentActions(addChildMenu, document, -1);
+
+		// add NEW ELEMENT
+		contributeUnconstrainedAddElementAction(addChildMenu, document, -1);
+	}
+
+
+	protected void contributeAddSiblingActions(IMenuManager menu, Node node, int ic, int vc) {
+		IMenuManager addBeforeMenu = new MyMenuManager(XMLUIMessages._UI_MENU_ADD_BEFORE);
+		IMenuManager addAfterMenu = new MyMenuManager(XMLUIMessages._UI_MENU_ADD_AFTER);
+		menu.add(addBeforeMenu);
+		menu.add(addAfterMenu);
+
+		Node parentNode = node.getParentNode();
+		if (parentNode != null) {
+			int index = getIndex(parentNode, node);
+			if (parentNode.getNodeType() == Node.ELEMENT_NODE) {
+				Element parentElement = (Element) parentNode;
+				CMElementDeclaration parentED = modelQuery.getCMElementDeclaration(parentElement);
+				if (parentED != null) {
+					// 'Add Before...' and 'Add After...' actions
+					//
+					List modelQueryActionList = new ArrayList();
+					modelQuery.getInsertActions(parentElement, parentED, index, ic, vc, modelQueryActionList);
+					addActionHelper(addBeforeMenu, modelQueryActionList);
+
+					modelQueryActionList = new ArrayList();
+					modelQuery.getInsertActions(parentElement, parentED, index + 1, ic, vc, modelQueryActionList);
+					addActionHelper(addAfterMenu, modelQueryActionList);
+				}
+
+				// add COMMENT and PI before and after
+				contributePIAndCommentActions(addBeforeMenu, parentElement, parentED, index);
+				contributePIAndCommentActions(addAfterMenu, parentElement, parentED, index + 1);
+
+				// add PCDATA, CDATA_SECTION before and after
+				contributeTextNodeActions(addBeforeMenu, parentElement, parentED, index);
+				contributeTextNodeActions(addAfterMenu, parentElement, parentED, index + 1);
+
+				// add NEW ELEMENT before and after
+				contributeUnconstrainedAddElementAction(addBeforeMenu, parentElement, parentED, index);
+				contributeUnconstrainedAddElementAction(addAfterMenu, parentElement, parentED, index + 1);
+			}
+			else if (parentNode.getNodeType() == Node.DOCUMENT_NODE) {
+				Document document = (Document) parentNode;
+				CMDocument cmDocument = modelQuery.getCorrespondingCMDocument(parentNode);
+				if (cmDocument != null) {
+					// add possible root element insertions
+					//        
+					List modelQueryActionList = new ArrayList();
+					modelQuery.getInsertActions(document, cmDocument, index, ic, vc, modelQueryActionList);
+					addActionHelper(addAfterMenu, modelQueryActionList);
+
+					modelQueryActionList = new ArrayList();
+					modelQuery.getInsertActions(document, cmDocument, index + 1, ic, vc, modelQueryActionList);
+					addActionHelper(addAfterMenu, modelQueryActionList);
+				}
+
+				// add COMMENT and PI before and after
+				contributePIAndCommentActions(addBeforeMenu, document, index);
+				contributePIAndCommentActions(addAfterMenu, document, index + 1);
+
+				// add ELEMENT before and after
+				contributeUnconstrainedAddElementAction(addBeforeMenu, document, index);
+				contributeUnconstrainedAddElementAction(addAfterMenu, document, index + 1);
+			}
+		}
+	}
+
+	protected void contributeDeleteActions(IMenuManager menu, List list, int ic, int vc) {
+		boolean canRemove = modelQuery.canRemove(list, vc);
+
+
+		// a delete action with an empty list will produce a disabled menu
+		// item
+		//
+		List resultList = canRemove ? list : Collections.EMPTY_LIST;
+		contributeAction(menu, createDeleteAction(resultList));
+	}
+
+
+	protected void contributeEditActions(IMenuManager menu, Node node) {
+		contributeEditGrammarInformationActions(menu, node);
+
+		if (node.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE) {
+			contributeAction(menu, createEditProcessingInstructionAction((ProcessingInstruction) node));
+		}
+		else if (node.getNodeType() == Node.ATTRIBUTE_NODE) {
+			contributeAction(menu, createEditAttributeAction((Attr) node, null));
+		}
+	}
+
+
+	protected void contributeEditGrammarInformationActions(IMenuManager menu, Node node) {
+		Document document = node.getNodeType() == Node.DOCUMENT_NODE ? (Document) node : node.getOwnerDocument();
+
+		DocumentType doctype = getDoctype(node);
+		if (doctype == null) {
+			contributeAction(menu, createAddDoctypeAction(document, -1));
+		}
+
+		if (node.getNodeType() == Node.DOCUMENT_TYPE_NODE) {
+			contributeAction(menu, createEditDoctypeAction((DocumentType) node));
+		}
+
+		if ((doctype == null) && (getRootElement(document) != null)) {
+			contributeAction(menu, createEditSchemaInfoAction(getRootElement(document)));
+		}
+	}
+
+	protected void contributePIAndCommentActions(IMenuManager menu, Document document, int index) {
+		// test to make sure that the index isn't before the XML declaration
+		// 
+		contributeAction(menu, createAddCommentAction(document, index));
+		contributeAction(menu, createAddProcessingInstructionAction(document, index));
+	}
+
+
+	protected void contributePIAndCommentActions(IMenuManager menu, Element parentElement, CMElementDeclaration parentEd, int index) {
+		if ((parentEd == null) || isCommentAllowed(parentEd)) {
+			contributeAction(menu, createAddCommentAction(parentElement, index));
+			contributeAction(menu, createAddProcessingInstructionAction(parentElement, index));
+		}
+	}
+
+
+	protected void contributeReplaceActions(IMenuManager menu, List selectedNodeList, int ic, int vc) {
+		// 'Replace With...' actions
+		//                                                                                                                   
+		IMenuManager replaceWithMenu = new MyMenuManager(XMLUIMessages._UI_MENU_REPLACE_WITH);
+		menu.add(replaceWithMenu);
+
+		if ((modelQuery.getEditMode() == ModelQuery.EDIT_MODE_CONSTRAINED_STRICT) && (selectedNodeList.size() > 0)) {
+			Node node = (Node) selectedNodeList.get(0);
+			Node parentNode = node.getParentNode();
+			if ((parentNode != null) && (parentNode.getNodeType() == Node.ELEMENT_NODE)) {
+				Element parentElement = (Element) parentNode;
+				CMElementDeclaration parentED = modelQuery.getCMElementDeclaration(parentElement);
+				if (parentED != null) {
+					List replaceActionList = new Vector();
+					modelQuery.getReplaceActions(parentElement, parentED, selectedNodeList, ic, vc, replaceActionList);
+					addActionHelper(replaceWithMenu, replaceActionList);
+				}
+			}
+		}
+	}
+
+	protected void contributeTextNodeActions(IMenuManager menu, Element parentElement, CMElementDeclaration parentEd, int index) {
+		if ((parentEd == null) || isTextAllowed(parentEd)) {
+			CMDataType dataType = parentEd != null ? parentEd.getDataType() : null;
+			contributeAction(menu, createAddPCDataAction(parentElement, dataType, index));
+			contributeAction(menu, createAddCDataSectionAction(parentElement, index));
+		}
+	}
+
+
+	protected void contributeUnconstrainedAddElementAction(IMenuManager menu, Document document, int index) {
+		if (isUnconstrainedActionAllowed()) {
+			if (getRootElement(document) == null) {
+				int xmlDeclarationIndex = -1;
+				int doctypeIndex = -1;
+				NodeList nodeList = document.getChildNodes();
+				int nodeListLength = nodeList.getLength();
+				for (int i = 0; i < nodeListLength; i++) {
+					Node node = nodeList.item(i);
+					int nodeType = node.getNodeType();
+					if (nodeType == Node.DOCUMENT_TYPE_NODE) {
+						doctypeIndex = i;
+						break;
+					}
+					else if (nodeType == Node.PROCESSING_INSTRUCTION_NODE) {
+						ProcessingInstruction pi = (ProcessingInstruction) node;
+						if (pi.getTarget().equalsIgnoreCase("xml") && (xmlDeclarationIndex == -1)) { //$NON-NLS-1$
+							xmlDeclarationIndex = i;
+						}
+					}
+				}
+
+				if (((xmlDeclarationIndex == -1) || (index > xmlDeclarationIndex)) && ((doctypeIndex == -1) || (index > doctypeIndex))) {
+					contributeAction(menu, createAddElementAction(document, null, index));
+				}
+			}
+		}
+	}
+
+
+	protected void contributeUnconstrainedAddElementAction(IMenuManager menu, Element parentElement, CMElementDeclaration parentEd, int index) {
+		if (isUnconstrainedActionAllowed()) {
+			if ((parentEd == null) || (parentEd.getProperty("isInferred") == Boolean.TRUE) || ((modelQuery.getEditMode() != ModelQuery.EDIT_MODE_CONSTRAINED_STRICT) && isElementAllowed(parentEd))) { //$NON-NLS-1$
+				contributeAction(menu, createAddElementAction(parentElement, null, index));
+			}
+		}
+	}
+
+
+	protected void contributeUnconstrainedAttributeActions(IMenuManager menu, Element parentElement, CMElementDeclaration parentEd) {
+		if (isUnconstrainedActionAllowed()) {
+			if ((parentEd == null) || (parentEd.getProperty("isInferred") == Boolean.TRUE) || (modelQuery.getEditMode() != ModelQuery.EDIT_MODE_CONSTRAINED_STRICT)) { //$NON-NLS-1$
+				contributeAction(menu, createAddAttributeAction(parentElement, null));
+			}
+		}
+	}
+
+	abstract protected Action createAddAttributeAction(Element parent, CMAttributeDeclaration ad);
+
+	abstract protected Action createAddCDataSectionAction(Node parent, int index);
+
+	abstract protected Action createAddCommentAction(Node parent, int index);
+
+	abstract protected Action createAddDoctypeAction(Document parent, int index);
+
+	abstract protected Action createAddElementAction(Node parent, CMElementDeclaration ed, int index);
+
+	abstract protected Action createAddPCDataAction(Node parent, CMDataType dataType, int index);
+
+	abstract protected Action createAddProcessingInstructionAction(Node parent, int index);
+
+	abstract protected Action createAddSchemaInfoAction(Element element);
+
+	abstract protected Action createDeleteAction(List selection);
+
+	abstract protected Action createEditAttributeAction(Attr attribute, CMAttributeDeclaration ad);
+
+	abstract protected Action createEditDoctypeAction(DocumentType doctype);
+
+	abstract protected Action createEditProcessingInstructionAction(ProcessingInstruction pi);
+
+	abstract protected Action createEditSchemaInfoAction(Element element);
+
+	abstract protected Action createRenameAction(Node node);
+
+	abstract protected Action createReplaceAction(Node parent, CMNode cmnode, int startIndex, int endIndex);
+
+
+	public int getIndex(Node parentNode, Node child) {
+		NodeList nodeList = parentNode.getChildNodes();
+		int index = -1;
+		int size = nodeList.getLength();
+		for (int i = 0; i < size; i++) {
+			if (nodeList.item(i) == child) {
+				index = i;
+				break;
+			}
+		}
+		return index;
+	}
+
+
+	public Node getRefChildNodeAtIndex(Node parent, int index) {
+		NodeList nodeList = parent.getChildNodes();
+		Node refChild = ((index >= 0) && (index < nodeList.getLength())) ? nodeList.item(index) : null;
+		return refChild;
+	}
+
+
+	protected Element getRootElement(Document document) {
+		Element result = null;
+		NodeList nodeList = document.getChildNodes();
+		int nodeListLength = nodeList.getLength();
+		for (int i = 0; i < nodeListLength; i++) {
+			Node node = nodeList.item(i);
+			if (node.getNodeType() == Node.ELEMENT_NODE) {
+				result = (Element) node;
+				break;
+			}
+		}
+		return result;
+	}
+
+
+	protected List getSelectedNodes(List list, boolean includeTextNodes) {
+		List result = new ArrayList(0);
+		for (Iterator i = list.iterator(); i.hasNext();) {
+			Object object = i.next();
+			if (object instanceof Node) {
+				Node node = (Node) object;
+				if (node.getNodeType() == Node.TEXT_NODE) {
+					if (includeTextNodes) {
+						result.add(object);
+					}
+				}
+				else {
+					result.add(node);
+				}
+			}
+		}
+		return result;
+	}
+
+
+	protected boolean isCommentAllowed(CMElementDeclaration parentEd) {
+		int contentType = parentEd.getContentType();
+		return (contentType == CMElementDeclaration.ELEMENT) || (contentType == CMElementDeclaration.MIXED) || (contentType == CMElementDeclaration.PCDATA) || (contentType == CMElementDeclaration.ANY);
+	}
+
+
+	protected boolean isElementAllowed(CMElementDeclaration parentEd) {
+		int contentType = parentEd.getContentType();
+		return (contentType == CMElementDeclaration.ELEMENT) || (contentType == CMElementDeclaration.MIXED) || (contentType == CMElementDeclaration.ANY);
+	}
+
+
+	protected boolean isTextAllowed(CMElementDeclaration parentEd) {
+		int contentType = parentEd.getContentType();
+		return (contentType == CMElementDeclaration.MIXED) || (contentType == CMElementDeclaration.PCDATA) || (contentType == CMElementDeclaration.ANY);
+	}
+
+
+	protected boolean isUnconstrainedActionAllowed() {
+		return true;
+	}
+
+
+	protected boolean isWhitespaceTextNode(Node node) {
+		return (node != null) && (node.getNodeType() == Node.TEXT_NODE) && (node.getNodeValue().trim().length() == 0);
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/CleanupActionXMLDelegate.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/CleanupActionXMLDelegate.java
new file mode 100644
index 0000000..d91a815
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/CleanupActionXMLDelegate.java
@@ -0,0 +1,139 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+
+package org.eclipse.wst.xml.ui.internal.actions;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.custom.BusyIndicator;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.ui.IActionDelegate2;
+import org.eclipse.ui.IEditorActionDelegate;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IViewActionDelegate;
+import org.eclipse.ui.IViewPart;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.cleanup.IStructuredCleanupProcessor;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.ui.internal.SSEUIMessages;
+import org.eclipse.wst.xml.core.internal.cleanup.CleanupProcessorXML;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+
+/**
+ * Cleanup action delegate for CSS editor
+ */
+public class CleanupActionXMLDelegate implements IEditorActionDelegate, IActionDelegate2, IViewActionDelegate {
+	private IEditorPart fEditor;
+	private IStructuredCleanupProcessor fCleanupProcessor;
+
+	public void setActiveEditor(IAction action, IEditorPart targetEditor) {
+		fEditor = targetEditor;
+	}
+
+	public void dispose() {
+		// nulling out just in case
+		fEditor = null;
+		fCleanupProcessor = null;
+	}
+
+	public void init(IAction action) {
+		if (action != null) {
+			action.setText(XMLUIMessages.CleanupDocument_label);
+			action.setToolTipText(XMLUIMessages.CleanupDocument_tooltip);
+			action.setDescription(XMLUIMessages.CleanupDocument_description);
+		}
+	}
+
+	public void runWithEvent(IAction action, Event event) {
+		run(action);
+	}
+
+	public void init(IViewPart view) {
+		// do nothing
+	}
+
+	public void run(IAction action) {
+		if (fEditor instanceof ITextEditor) {
+			final ITextEditor editor = (ITextEditor) fEditor;
+			Dialog cleanupDialog = new CleanupDialogXML(editor.getSite().getShell());
+			if (cleanupDialog.open() == Window.OK) {
+				// setup runnable
+				Runnable runnable = new Runnable() {
+					public void run() {
+						IStructuredCleanupProcessor cleanupProcessor = getCleanupProcessor();
+						if (cleanupProcessor != null) {
+							IStructuredModel model = null;
+							try {
+								model = StructuredModelManager.getModelManager().getExistingModelForEdit(editor.getDocumentProvider().getDocument(editor.getEditorInput()));
+								if (model != null) {
+									cleanupProcessor.cleanupModel(model);
+								}
+							}
+							finally {
+								if (model != null) {
+									model.releaseFromEdit();
+								}
+							}
+						}
+					}
+				};
+
+				// TODO: make independent of 'model'.
+				IStructuredModel model = null;
+				try {
+					model = StructuredModelManager.getModelManager().getExistingModelForEdit(editor.getDocumentProvider().getDocument(editor.getEditorInput()));
+					if (model != null) {
+						// begin recording
+						ITextSelection selection = (ITextSelection) editor.getSelectionProvider().getSelection();
+						model.beginRecording(this, SSEUIMessages.Cleanup_Document_UI_, SSEUIMessages.Cleanup_Document_UI_, selection.getOffset(), selection.getLength());
+
+						// tell the model that we are about to make a big
+						// model change
+						model.aboutToChangeModel();
+
+						// run
+						BusyIndicator.showWhile(fEditor.getEditorSite().getWorkbenchWindow().getShell().getDisplay(), runnable);
+					}
+				}
+				finally {
+					if (model != null) {
+						// tell the model that we are done with the big
+						// model
+						// change
+						model.changedModel();
+
+						// end recording
+						ITextSelection selection = (ITextSelection) editor.getSelectionProvider().getSelection();
+						model.endRecording(this, selection.getOffset(), selection.getLength());
+						model.releaseFromEdit();
+					}
+				}
+			}
+		}
+	}
+
+	public void selectionChanged(IAction action, ISelection selection) {
+		// do nothing
+	}
+
+	IStructuredCleanupProcessor getCleanupProcessor() {
+		if (fCleanupProcessor == null) {
+			fCleanupProcessor = new CleanupProcessorXML();
+		}
+
+		return fCleanupProcessor;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/CleanupDialogXML.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/CleanupDialogXML.java
new file mode 100644
index 0000000..199eac0
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/CleanupDialogXML.java
@@ -0,0 +1,220 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.actions;
+
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.wst.sse.core.internal.encoding.CommonEncodingPreferenceNames;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.xml.core.internal.XMLCorePlugin;
+import org.eclipse.wst.xml.core.internal.preferences.XMLCorePreferenceNames;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+import org.eclipse.wst.xml.ui.internal.editor.IHelpContextIds;
+
+public class CleanupDialogXML extends Dialog implements SelectionListener {
+	protected Button fCheckBoxCompressEmptyElementTags;
+	protected Button fCheckBoxConvertEOLCodes;
+	protected Button fCheckBoxFormatSource;
+	protected Button fCheckBoxInsertMissingTags;
+	protected Button fCheckBoxInsertRequiredAttrs;
+	protected Button fCheckBoxQuoteAttrValues;
+	protected Button fCheckBoxInsertXMLDeclaration;
+	protected IStructuredModel fModel = null;
+	protected Preferences fPreferences = null;
+	protected Button fRadioButtonAttrNameCaseAsis;
+	protected Button fRadioButtonAttrNameCaseLower;
+	protected Button fRadioButtonAttrNameCaseUpper;
+	protected Button fRadioButtonConvertEOLMac;
+	protected Button fRadioButtonConvertEOLUnix;
+	protected Button fRadioButtonConvertEOLWindows;
+
+	protected Button fRadioButtonTagNameCaseAsis;
+	protected Button fRadioButtonTagNameCaseLower;
+	protected Button fRadioButtonTagNameCaseUpper;
+
+	public CleanupDialogXML(Shell shell) {
+
+		super(shell);
+	}
+
+	public Control createDialogArea(Composite parent) {
+
+		getShell().setText(XMLUIMessages.Cleanup_UI_);
+		Composite composite = new Composite(parent, SWT.NULL);
+		createDialogAreaInComposite(composite);
+		initializeOptions();
+		return composite;
+	}
+
+	protected void createDialogAreaInComposite(Composite composite) {
+
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, IHelpContextIds.CLEANUP_XML_HELPID); // use
+		// XML
+		// specific
+		// help
+
+		GridLayout layout = new GridLayout();
+		layout.numColumns = 1;
+		layout.makeColumnsEqualWidth = true;
+		composite.setLayout(layout);
+
+		// Compress empty element tags
+		fCheckBoxCompressEmptyElementTags = new Button(composite, SWT.CHECK);
+		fCheckBoxCompressEmptyElementTags.setText(XMLUIMessages.Compress_empty_element_tags_UI_);
+		fCheckBoxCompressEmptyElementTags.addSelectionListener(this);
+
+		// Insert missing required attrs
+		fCheckBoxInsertRequiredAttrs = new Button(composite, SWT.CHECK);
+		fCheckBoxInsertRequiredAttrs.setText(XMLUIMessages.Insert_required_attributes_UI_);
+		fCheckBoxInsertRequiredAttrs.addSelectionListener(this);
+
+		// Insert missing begin/end tags
+		fCheckBoxInsertMissingTags = new Button(composite, SWT.CHECK);
+		fCheckBoxInsertMissingTags.setText(XMLUIMessages.Insert_missing_tags_UI_);
+		fCheckBoxInsertMissingTags.addSelectionListener(this);
+
+		// Quote attribute values
+		fCheckBoxQuoteAttrValues = new Button(composite, SWT.CHECK);
+		fCheckBoxQuoteAttrValues.setText(XMLUIMessages.Quote_attribute_values_UI_);
+		fCheckBoxQuoteAttrValues.addSelectionListener(this);
+
+		// Format source
+		fCheckBoxFormatSource = new Button(composite, SWT.CHECK);
+		fCheckBoxFormatSource.setText(XMLUIMessages.Format_source_UI_);
+		fCheckBoxFormatSource.addSelectionListener(this);
+
+		fCheckBoxInsertXMLDeclaration = new Button(composite, SWT.CHECK);
+		fCheckBoxInsertXMLDeclaration.setText(XMLUIMessages.Insert_XML_decl);
+		fCheckBoxInsertXMLDeclaration.addSelectionListener(this);
+
+		// Convert EOL code
+		fCheckBoxConvertEOLCodes = new Button(composite, SWT.CHECK);
+		fCheckBoxConvertEOLCodes.setText(XMLUIMessages.Convert_EOL_codes_UI_);
+		fCheckBoxConvertEOLCodes.addSelectionListener(this);
+		Composite EOLCodes = new Composite(composite, SWT.NULL);
+		GridLayout hLayout = new GridLayout();
+		hLayout.numColumns = 3;
+		EOLCodes.setLayout(hLayout);
+		fRadioButtonConvertEOLWindows = new Button(EOLCodes, SWT.RADIO);
+		fRadioButtonConvertEOLWindows.setText(XMLUIMessages.EOL_Windows_UI);
+		fRadioButtonConvertEOLWindows.addSelectionListener(this);
+		fRadioButtonConvertEOLUnix = new Button(EOLCodes, SWT.RADIO);
+		fRadioButtonConvertEOLUnix.setText(XMLUIMessages.EOL_Unix_UI);
+		fRadioButtonConvertEOLUnix.addSelectionListener(this);
+		fRadioButtonConvertEOLMac = new Button(EOLCodes, SWT.RADIO);
+		fRadioButtonConvertEOLMac.setText(XMLUIMessages.EOL_Mac_UI);
+		fRadioButtonConvertEOLMac.addSelectionListener(this);
+	}
+
+	protected void enableEOLCodeRadios(boolean enable) {
+
+		if ((fRadioButtonConvertEOLWindows != null) && (fRadioButtonConvertEOLUnix != null) && (fRadioButtonConvertEOLMac != null)) {
+			fRadioButtonConvertEOLWindows.setEnabled(enable);
+			fRadioButtonConvertEOLUnix.setEnabled(enable);
+			fRadioButtonConvertEOLMac.setEnabled(enable);
+			if (!fRadioButtonConvertEOLWindows.getSelection() && !fRadioButtonConvertEOLUnix.getSelection() && !fRadioButtonConvertEOLMac.getSelection()) {
+				fRadioButtonConvertEOLWindows.setSelection(true);
+			}
+		}
+	}
+
+	protected Preferences getModelPreferences() {
+		return XMLCorePlugin.getDefault().getPluginPreferences();
+	}
+
+	protected void initializeOptions() {
+
+		fCheckBoxCompressEmptyElementTags.setSelection(getModelPreferences().getBoolean(XMLCorePreferenceNames.COMPRESS_EMPTY_ELEMENT_TAGS));
+		fCheckBoxInsertRequiredAttrs.setSelection(getModelPreferences().getBoolean(XMLCorePreferenceNames.INSERT_REQUIRED_ATTRS));
+		fCheckBoxInsertMissingTags.setSelection(getModelPreferences().getBoolean(XMLCorePreferenceNames.INSERT_MISSING_TAGS));
+		fCheckBoxQuoteAttrValues.setSelection(getModelPreferences().getBoolean(XMLCorePreferenceNames.QUOTE_ATTR_VALUES));
+		fCheckBoxFormatSource.setSelection(getModelPreferences().getBoolean(XMLCorePreferenceNames.FORMAT_SOURCE));
+		fCheckBoxConvertEOLCodes.setSelection(getModelPreferences().getBoolean(XMLCorePreferenceNames.CONVERT_EOL_CODES));
+		fCheckBoxInsertXMLDeclaration.setSelection(getModelPreferences().getBoolean(XMLCorePreferenceNames.FIX_XML_DECLARATION));
+		String EOLCode = getModelPreferences().getString(XMLCorePreferenceNames.CLEANUP_EOL_CODE);
+		if (EOLCode.compareTo(CommonEncodingPreferenceNames.LF) == 0) {
+			fRadioButtonConvertEOLUnix.setSelection(true);
+		}
+		else if (EOLCode.compareTo(CommonEncodingPreferenceNames.CR) == 0) {
+			fRadioButtonConvertEOLMac.setSelection(true);
+		}
+		else {
+			fRadioButtonConvertEOLWindows.setSelection(true);
+		}
+		enableEOLCodeRadios(fCheckBoxConvertEOLCodes.getSelection());
+	}
+
+	protected void okPressed() {
+
+		storeOptions();
+		super.okPressed();
+	}
+
+	public void setModel(IStructuredModel model) {
+
+		fModel = model;
+	}
+
+	protected void storeOptions() {
+
+		getModelPreferences().setValue(XMLCorePreferenceNames.COMPRESS_EMPTY_ELEMENT_TAGS, fCheckBoxCompressEmptyElementTags.getSelection());
+		getModelPreferences().setValue(XMLCorePreferenceNames.INSERT_REQUIRED_ATTRS, fCheckBoxInsertRequiredAttrs.getSelection());
+		getModelPreferences().setValue(XMLCorePreferenceNames.INSERT_MISSING_TAGS, fCheckBoxInsertMissingTags.getSelection());
+		getModelPreferences().setValue(XMLCorePreferenceNames.QUOTE_ATTR_VALUES, fCheckBoxQuoteAttrValues.getSelection());
+		getModelPreferences().setValue(XMLCorePreferenceNames.FORMAT_SOURCE, fCheckBoxFormatSource.getSelection());
+		getModelPreferences().setValue(XMLCorePreferenceNames.CONVERT_EOL_CODES, fCheckBoxConvertEOLCodes.getSelection());
+		getModelPreferences().setValue(XMLCorePreferenceNames.FIX_XML_DECLARATION, fCheckBoxInsertXMLDeclaration.getSelection());
+		if (fRadioButtonConvertEOLUnix.getSelection()) {
+			getModelPreferences().setValue(XMLCorePreferenceNames.CLEANUP_EOL_CODE, CommonEncodingPreferenceNames.LF);
+		}
+		else if (fRadioButtonConvertEOLMac.getSelection()) {
+			getModelPreferences().setValue(XMLCorePreferenceNames.CLEANUP_EOL_CODE, CommonEncodingPreferenceNames.CR);
+		}
+		else {
+			getModelPreferences().setValue(XMLCorePreferenceNames.CLEANUP_EOL_CODE, CommonEncodingPreferenceNames.CRLF);
+		}
+		// explicitly save plugin preferences so values are stored
+		XMLCorePlugin.getDefault().savePluginPreferences();
+	}
+
+	public void widgetDefaultSelected(SelectionEvent e) {
+
+		widgetSelected(e);
+	}
+
+	public void widgetSelected(SelectionEvent e) {
+
+		getButton(OK).setEnabled(((fRadioButtonTagNameCaseLower != null) && (fRadioButtonTagNameCaseLower.getSelection() || fRadioButtonTagNameCaseUpper.getSelection())) 
+				|| ((fRadioButtonAttrNameCaseLower != null) && (fRadioButtonAttrNameCaseLower.getSelection() || fRadioButtonAttrNameCaseUpper.getSelection()))
+				|| fCheckBoxInsertMissingTags.getSelection()
+				|| fCheckBoxQuoteAttrValues.getSelection() 
+				|| fCheckBoxFormatSource.getSelection() 
+				|| fCheckBoxInsertXMLDeclaration.getSelection()
+				|| fCheckBoxCompressEmptyElementTags.getSelection()
+				|| fCheckBoxInsertRequiredAttrs.getSelection()
+				|| (( fCheckBoxConvertEOLCodes.getSelection() && fRadioButtonConvertEOLUnix != null ) && (fRadioButtonConvertEOLUnix.getSelection() || fRadioButtonConvertEOLMac.getSelection()
+						|| fRadioButtonConvertEOLWindows.getSelection())));
+		if (e.widget == fCheckBoxConvertEOLCodes) {
+			enableEOLCodeRadios(fCheckBoxConvertEOLCodes.getSelection());
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/EditAttributeAction.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/EditAttributeAction.java
new file mode 100644
index 0000000..0cdc771
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/EditAttributeAction.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2009 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.actions;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.wst.xml.ui.internal.XMLUIPlugin;
+import org.eclipse.wst.xml.ui.internal.dialogs.EditAttributeDialog;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImageHelper;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImages;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+public class EditAttributeAction extends NodeAction {
+	protected static ImageDescriptor imageDescriptor;
+
+	public static ImageDescriptor createImageDescriptor() {
+		if (imageDescriptor == null) {
+			imageDescriptor = XMLEditorPluginImageHelper.getInstance().getImageDescriptor(XMLEditorPluginImages.IMG_OBJ_ATTRIBUTE);
+		}
+		return imageDescriptor;
+	}
+
+	protected Attr attr;
+	protected AbstractNodeActionManager manager;
+	protected Element ownerElement;
+	protected String title;
+
+	public EditAttributeAction(AbstractNodeActionManager manager, Element ownerElement, Attr attr, String actionLabel, String title) {
+		this.manager = manager;
+		this.ownerElement = ownerElement;
+		this.attr = attr;
+		this.title = title;
+		setText(actionLabel);
+		// assume if attr is null then this is an 'Add' that requires action
+		// an icons... otherwise this is an edit
+		if (attr == null) {
+			setImageDescriptor(createImageDescriptor());
+		}
+	}
+
+	public String getUndoDescription() {
+		return title;
+	}
+
+	public void run() {
+		Shell shell = XMLUIPlugin.getInstance().getWorkbench().getActiveWorkbenchWindow().getShell();
+		if (validateEdit(manager.getModel(), shell)) {
+			manager.beginNodeAction(this);
+			EditAttributeDialog dialog = new EditAttributeDialog(shell, ownerElement, attr);
+			dialog.create();
+			dialog.getShell().setText(title);
+			dialog.setBlockOnOpen(true);
+			dialog.open();
+	
+			if (dialog.getReturnCode() == Window.OK) {
+				if (attr != null) {
+					ownerElement.removeAttributeNode(attr);
+				}
+				Document document = ownerElement.getOwnerDocument();
+				Attr newAttribute = document.createAttribute(dialog.getAttributeName());
+				newAttribute.setValue(dialog.getAttributeValue());
+				ownerElement.setAttributeNode(newAttribute);
+				manager.setViewerSelection(newAttribute);
+			}
+			manager.endNodeAction(this);
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/EditDoctypeAction.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/EditDoctypeAction.java
new file mode 100644
index 0000000..4ce515c
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/EditDoctypeAction.java
@@ -0,0 +1,192 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2009 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.actions;
+
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.xml.core.internal.document.DocumentImpl;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocumentType;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+import org.eclipse.wst.xml.ui.internal.dialogs.EditDoctypeDialog;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * EditDoctypeAction
+ */
+public class EditDoctypeAction extends NodeAction {
+	protected DocumentType doctype;
+	protected Document document;
+	protected IStructuredModel model;
+	protected String resourceLocation;
+	protected String title;
+
+	/**
+	 * This constructor is used to create a new doctype.
+	 */
+	public EditDoctypeAction(IStructuredModel model, Document document, String resourceLocation, String title) {
+		setText(title);
+		this.model = model;
+		this.document = document;
+		this.resourceLocation = resourceLocation;
+		this.title = title;
+	}
+
+	/**
+	 * This constructor is used to edit an exisitng doctype.
+	 */
+	public EditDoctypeAction(IStructuredModel model, DocumentType doctype, String resourceLocation, String title) {
+		setText(title);
+		this.model = model;
+		this.doctype = doctype;
+		this.resourceLocation = resourceLocation;
+		this.title = title;
+	}
+
+
+	protected DocumentType createDoctype(EditDoctypeDialog dialog, Document document) {
+		DocumentType result = null;
+		if (document instanceof DocumentImpl) {
+			IDOMDocument documentImpl = (IDOMDocument) document;
+			IDOMDocumentType doctypeImpl = (IDOMDocumentType) documentImpl.createDoctype(dialog.getName());
+			doctypeImpl.setPublicId(dialog.getPublicId());
+			doctypeImpl.setSystemId(dialog.getSystemId());
+			result = doctypeImpl;
+		}
+		return result;
+	}
+
+	private Display getDisplay() {
+
+		return PlatformUI.getWorkbench().getDisplay();
+	}
+
+
+	protected String getRootElementName(Document document) {
+		Element rootElement = null;
+		NodeList nodeList = document.getChildNodes();
+		int nodeListLength = nodeList.getLength();
+		for (int i = 0; i < nodeListLength; i++) {
+			Node childNode = nodeList.item(i);
+			if (childNode.getNodeType() == Node.ELEMENT_NODE) {
+				rootElement = (Element) childNode;
+				break;
+			}
+		}
+		return rootElement != null ? rootElement.getNodeName() : XMLUIMessages._UI_LABEL_ROOT_ELEMENT_VALUE;
+	}
+
+	public String getUndoDescription() {
+		return title;
+	}
+
+
+	protected void insertDoctype(DocumentType doctype, Document document) {
+		Node refChild = null;
+		NodeList nodeList = document.getChildNodes();
+		int nodeListLength = nodeList.getLength();
+		for (int i = 0; i < nodeListLength; i++) {
+			Node childNode = nodeList.item(i);
+			if ((childNode.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE) || (childNode.getNodeType() == Node.COMMENT_NODE)) {
+				// continue on to the nextNode
+			}
+			else {
+				refChild = childNode;
+				break;
+			}
+		}
+
+		document.insertBefore(doctype, refChild);
+		// manager.reformat(doctype, false);
+	}
+
+	public void run() {
+		Shell shell = getDisplay().getActiveShell();
+		if (validateEdit(model, shell)) {
+			model.beginRecording(this, getUndoDescription());
+			// Shell shell =
+			// XMLCommonUIPlugin.getInstance().getWorkbench().getActiveWorkbenchWindow().getShell();
+			EditDoctypeDialog dialog = showEditDoctypeDialog(shell);
+	
+			if (dialog.getReturnCode() == Window.OK) {
+				if (doctype != null) {
+					updateDoctype(dialog, doctype);
+				}
+				else if (document != null) {
+					DocumentType doctype = createDoctype(dialog, document);
+					if (doctype != null) {
+						insertDoctype(doctype, document);
+					}
+				}
+			}
+			model.endRecording(this);
+		}
+	}
+
+	protected EditDoctypeDialog showEditDoctypeDialog(Shell shell) {
+		EditDoctypeDialog dialog = null;
+
+		if (doctype != null) {
+			dialog = new EditDoctypeDialog(shell, doctype);
+			if (title == null) {
+				title = XMLUIMessages._UI_LABEL_EDIT_DOCTYPE;
+			}
+		}
+		else if (document != null) {
+			String rootElementName = getRootElementName(document);
+			dialog = new EditDoctypeDialog(shell, rootElementName, "", rootElementName + ".dtd"); //$NON-NLS-1$ //$NON-NLS-2$
+			if (title == null) {
+				title = XMLUIMessages._UI_MENU_ADD_DTD_INFORMATION_TITLE;
+			}
+		}
+
+		dialog.setComputeSystemId((doctype == null) || (doctype.getSystemId() == null) || (doctype.getSystemId().trim().length() == 0));
+
+		dialog.setErrorChecking(false);// !model.getType().equals(IStructuredModel.HTML));
+		dialog.create();
+		dialog.getShell().setText(title);
+		dialog.setBlockOnOpen(true);
+		dialog.setResourceLocation(new Path(resourceLocation));
+		dialog.open();
+
+		return dialog;
+	}
+
+
+	protected void updateDoctype(EditDoctypeDialog dialog, DocumentType doctype) {
+		if (doctype instanceof IDOMDocumentType) {
+			IDOMDocumentType doctypeImpl = (IDOMDocumentType) doctype;
+			if (doctypeImpl.getName().equals(dialog.getName())) {
+				doctypeImpl.setPublicId(dialog.getPublicId());
+				doctypeImpl.setSystemId(dialog.getSystemId());
+			}
+			else {
+				// we need to create a new one and remove the old
+				//                  
+				Document document = doctype.getOwnerDocument();
+				DocumentType newDoctype = createDoctype(dialog, document);
+				document.insertBefore(newDoctype, doctype);
+				document.removeChild(doctype);
+				// manager.reformat(newDoctype, false);
+			}
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/EditElementAction.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/EditElementAction.java
new file mode 100644
index 0000000..21b55fe
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/EditElementAction.java
@@ -0,0 +1,119 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2009 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.actions;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
+import org.eclipse.wst.xml.ui.internal.XMLUIPlugin;
+import org.eclipse.wst.xml.ui.internal.dialogs.EditElementDialog;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImageHelper;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImages;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+public class EditElementAction extends NodeAction {
+
+	protected static ImageDescriptor imageDescriptor;
+
+	public static ImageDescriptor createImageDescriptor() {
+		if (imageDescriptor == null) {
+			imageDescriptor = XMLEditorPluginImageHelper.getInstance().getImageDescriptor(XMLEditorPluginImages.IMG_OBJ_ELEMENT);
+		}
+		return imageDescriptor;
+	}
+
+	protected Element element;
+	protected int insertionIndex = -1;
+	protected AbstractNodeActionManager manager;
+	protected Node parent;
+	protected String title;
+
+	public EditElementAction(AbstractNodeActionManager manager, Element element, String actionLabel, String dialogTitle) {
+		this(manager, element.getParentNode(), -1, element, actionLabel, dialogTitle);
+	}
+
+	protected EditElementAction(AbstractNodeActionManager manager, Node parent, int index, Element element, String actionLabel, String title) {
+		this.manager = manager;
+		this.parent = parent;
+		this.insertionIndex = index;
+		this.element = element;
+		this.title = title;
+		setText(actionLabel);
+		if (element == null) {
+			setImageDescriptor(createImageDescriptor());
+		}
+	}
+
+	public EditElementAction(AbstractNodeActionManager manager, Node parent, int index, String actionLabel, String title) {
+		this(manager, parent, index, null, actionLabel, title);
+	}
+
+	public String getUndoDescription() {
+		return title;
+	}
+
+	public void run() {
+		Shell shell = XMLUIPlugin.getInstance().getWorkbench().getActiveWorkbenchWindow().getShell();
+		if (validateEdit(manager.getModel(), shell)) {
+			manager.beginNodeAction(this);
+			EditElementDialog dialog = new EditElementDialog(shell, element);
+			dialog.create();
+			dialog.getShell().setText(title);
+			dialog.setBlockOnOpen(true);
+			dialog.open();
+	
+			if (dialog.getReturnCode() == Window.OK) {
+				Document document = parent.getNodeType() == Node.DOCUMENT_NODE ? (Document) parent : parent.getOwnerDocument();
+				if (element != null) {
+					// here we need to do a rename... which seems to be quite hard
+					// to do :-(
+					if (element instanceof IDOMElement) {
+						IDOMElement elementImpl = (IDOMElement) element;
+						IDOMModel model = elementImpl.getModel();
+						String oldName = elementImpl.getNodeName();
+						String newName = dialog.getElementName();
+						setStructuredDocumentRegionElementName(model, elementImpl.getStartStructuredDocumentRegion(), oldName, newName);
+						setStructuredDocumentRegionElementName(model, elementImpl.getEndStructuredDocumentRegion(), oldName, newName);
+					}
+				}
+				else {
+					Element newElement = document.createElement(dialog.getElementName());
+					NodeList nodeList = parent.getChildNodes();
+					int nodeListLength = nodeList.getLength();
+					Node refChild = (insertionIndex < nodeListLength) && (insertionIndex >= 0) ? nodeList.item(insertionIndex) : null;
+					parent.insertBefore(newElement, refChild);
+					manager.reformat(newElement, false);
+					manager.setViewerSelection(newElement);
+				}
+			}
+			manager.endNodeAction(this);
+		}
+	}
+
+	protected void setStructuredDocumentRegionElementName(IDOMModel model, IStructuredDocumentRegion flatNode, String oldName, String newName) {
+		if (flatNode != null) {
+			String string = flatNode.getText();
+			int index = string.indexOf(oldName);
+			if (index != -1) {
+				index += flatNode.getStart();
+				model.getStructuredDocument().replaceText(this, index, oldName.length(), newName);
+			}
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/EditProcessingInstructionAction.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/EditProcessingInstructionAction.java
new file mode 100644
index 0000000..5578cf2
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/EditProcessingInstructionAction.java
@@ -0,0 +1,98 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2009 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.actions;
+
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+import org.eclipse.wst.xml.ui.internal.XMLUIPlugin;
+import org.eclipse.wst.xml.ui.internal.dialogs.EditProcessingInstructionDialog;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.ProcessingInstruction;
+
+/**
+ * EditProcessingInstructionAction
+ */
+public class EditProcessingInstructionAction extends NodeAction {
+	protected Node childRef;
+	protected AbstractNodeActionManager manager;
+	protected Node parent;
+	protected ProcessingInstruction pi;
+	protected String title;
+
+	/**
+	 * This constructor is used to add a new ProcessingInstruction
+	 */
+	public EditProcessingInstructionAction(AbstractNodeActionManager manager, Node parent, Node childRef, String actionLabel, String title) {
+		setText(actionLabel);
+		this.manager = manager;
+		this.parent = parent;
+		this.childRef = childRef;
+		this.title = title;
+	}
+
+	/**
+	 * This constructor is used to edit a ProcessingInstruction
+	 */
+	public EditProcessingInstructionAction(AbstractNodeActionManager manager, ProcessingInstruction pi, String actionLabel, String title) {
+		setText(actionLabel);
+		this.manager = manager;
+		this.pi = pi;
+		this.parent = pi.getParentNode();
+		this.title = title;
+	}
+
+	public String getUndoDescription() {
+		return title;
+	}
+
+	public void run() {
+		Shell shell = XMLUIPlugin.getInstance().getWorkbench().getActiveWorkbenchWindow().getShell();
+		if (validateEdit(manager.getModel(), shell)) {
+			manager.beginNodeAction(this);
+			
+	
+			EditProcessingInstructionDialog dialog = null;
+			if (pi != null) {
+				dialog = new EditProcessingInstructionDialog(shell, pi);
+			}
+			else {
+				dialog = new EditProcessingInstructionDialog(shell, XMLUIMessages._UI_PI_TARGET_VALUE, XMLUIMessages._UI_PI_DATA_VALUE);
+			}
+	
+			dialog.create();
+			dialog.getShell().setText(title);
+			dialog.setBlockOnOpen(true);
+			dialog.open();
+	
+			if (dialog.getReturnCode() == Window.OK) {
+				if (pi != null) {
+					childRef = pi;
+				}
+	
+				Document document = parent.getNodeType() == Node.DOCUMENT_NODE ? (Document) parent : parent.getOwnerDocument();
+				Node newNode = document.createProcessingInstruction(dialog.getTarget(), dialog.getData());
+				parent.insertBefore(newNode, childRef);
+	
+				if (pi != null) {
+					parent.removeChild(pi);
+				}
+	
+				manager.reformat(newNode, false);
+				manager.setViewerSelection(newNode);
+			}
+			manager.endNodeAction(this);
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/EditSchemaInfoAction.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/EditSchemaInfoAction.java
new file mode 100644
index 0000000..c07557a
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/EditSchemaInfoAction.java
@@ -0,0 +1,168 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2009 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.actions;
+
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.DOMNamespaceInfoManager;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.NamespaceInfo;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+import org.eclipse.wst.xml.ui.internal.XMLUIPlugin;
+import org.eclipse.wst.xml.ui.internal.dialogs.EditSchemaInfoDialog;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * EditDoctypeAction
+ */
+public class EditSchemaInfoAction extends NodeAction {
+	protected AbstractNodeActionManager manager;
+	protected DOMNamespaceInfoManager namespaceInfoManager = new DOMNamespaceInfoManager();
+	protected Node node;
+	protected String resourceLocation;
+	protected String title;
+
+	public EditSchemaInfoAction(AbstractNodeActionManager manager, Node node, String resourceLocation, String title) {
+		this.manager = manager;
+		this.node = node;
+		setText(title);
+		this.resourceLocation = resourceLocation;
+		this.title = title;
+	}
+
+	protected Map createPrefixMapping(List oldList, List newList) {
+		Map map = new Hashtable();
+
+		Hashtable oldURIToPrefixTable = new Hashtable();
+		for (Iterator i = oldList.iterator(); i.hasNext();) {
+			NamespaceInfo oldInfo = (NamespaceInfo) i.next();
+			oldURIToPrefixTable.put(oldInfo.uri, oldInfo);
+		}
+
+		for (Iterator i = newList.iterator(); i.hasNext();) {
+			NamespaceInfo newInfo = (NamespaceInfo) i.next();
+			NamespaceInfo oldInfo = (NamespaceInfo) oldURIToPrefixTable.get(newInfo.uri != null ? newInfo.uri : ""); //$NON-NLS-1$
+
+
+			// if oldInfo is non null ... there's a matching URI in the old
+			// set
+			// we can use its prefix to detemine out mapping
+			//
+			// if oldInfo is null ... we use the 'oldCopy' we stashed away
+			// assuming that the user changed the URI and the prefix
+			if (oldInfo == null) {
+				oldInfo = (NamespaceInfo) newInfo.getProperty("oldCopy"); //$NON-NLS-1$
+			}
+
+			if (oldInfo != null) {
+				String newPrefix = newInfo.prefix != null ? newInfo.prefix : ""; //$NON-NLS-1$
+				String oldPrefix = oldInfo.prefix != null ? oldInfo.prefix : ""; //$NON-NLS-1$
+				if (!oldPrefix.equals(newPrefix)) {
+					map.put(oldPrefix, newPrefix);
+				}
+			}
+		}
+		return map;
+	}
+
+	public Element getElement(Node node) {
+		Element result = null;
+		if (node.getNodeType() == Node.ELEMENT_NODE) {
+			result = (Element) node;
+		}
+		else if (node.getNodeType() == Node.DOCUMENT_NODE) {
+			result = getRootElement((Document) node);
+		}
+		return result;
+	}
+
+
+	public Element getRootElement(Document document) {
+		Element rootElement = null;
+		NodeList nodeList = document.getChildNodes();
+		int nodeListLength = nodeList.getLength();
+		for (int i = 0; i < nodeListLength; i++) {
+			Node childNode = nodeList.item(i);
+			if (childNode.getNodeType() == Node.ELEMENT_NODE) {
+				rootElement = (Element) childNode;
+				break;
+			}
+		}
+		return rootElement;
+	}
+
+	public String getUndoDescription() {
+		return title;
+	}
+
+	public void run() {
+		Shell shell = XMLUIPlugin.getInstance().getWorkbench().getActiveWorkbenchWindow().getShell();
+		if (validateEdit(manager.getModel(), shell)) {
+			manager.beginNodeAction(this);
+	
+			// todo... change constructor to take an element
+			Element element = getElement(node);
+			if (element != null) {
+				EditSchemaInfoDialog dialog = new EditSchemaInfoDialog(shell, new Path(resourceLocation));
+	
+				List namespaceInfoList = namespaceInfoManager.getNamespaceInfoList(element);
+				List oldNamespaceInfoList = NamespaceInfo.cloneNamespaceInfoList(namespaceInfoList);
+	
+				// here we store a copy of the old info for each NamespaceInfo
+				// this info will be used in createPrefixMapping() to figure out
+				// how to update the document
+				// in response to these changes
+				for (Iterator i = namespaceInfoList.iterator(); i.hasNext();) {
+					NamespaceInfo info = (NamespaceInfo) i.next();
+					NamespaceInfo oldCopy = new NamespaceInfo(info);
+					info.setProperty("oldCopy", oldCopy); //$NON-NLS-1$
+				}
+	
+				dialog.setNamespaceInfoList(namespaceInfoList);
+				dialog.create();
+				// dialog.getShell().setSize(500, 300);
+				dialog.getShell().setText(XMLUIMessages._UI_MENU_EDIT_SCHEMA_INFORMATION_TITLE);
+				dialog.setBlockOnOpen(true);
+				dialog.open();
+	
+				if (dialog.getReturnCode() == Window.OK) {
+					List newInfoList = dialog.getNamespaceInfoList();
+					namespaceInfoManager.removeNamespaceInfo(element);
+					namespaceInfoManager.addNamespaceInfo(element, newInfoList, false);
+	
+					// see if we need to rename any prefixes
+					Map prefixMapping = createPrefixMapping(oldNamespaceInfoList, namespaceInfoList);
+					if (prefixMapping.size() > 0) {
+						try {
+							manager.getModel().aboutToChangeModel();
+							ReplacePrefixAction replacePrefixAction = new ReplacePrefixAction(manager, element, prefixMapping);
+							replacePrefixAction.run();
+						}
+						finally {
+							manager.getModel().changedModel();
+						}
+					}
+				}
+			}
+			manager.endNodeAction(this);
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/GoToMatchingTagAction.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/GoToMatchingTagAction.java
new file mode 100644
index 0000000..5d7e7a3
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/GoToMatchingTagAction.java
@@ -0,0 +1,301 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.xml.ui.internal.actions;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.ResourceBundle;
+
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.TextSelection;
+import org.eclipse.jface.text.source.Annotation;
+import org.eclipse.jface.text.source.IAnnotationModel;
+import org.eclipse.jface.text.source.IAnnotationModelExtension;
+import org.eclipse.jface.viewers.IPostSelectionProvider;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.ui.texteditor.IDocumentProvider;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.ui.texteditor.TextEditorAction;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Node;
+
+/**
+ * Moves the cursor to the end tag if it is in a start tag, and vice versa.
+ * Also updates the matching tag annotation in the active editor.
+ * 
+ * @author nitin
+ * 
+ */
+class GoToMatchingTagAction extends TextEditorAction {
+
+	private class UpdateListener implements ISelectionChangedListener {
+		public void selectionChanged(SelectionChangedEvent event) {
+			updateFor(event.getSelection());
+		}
+	}
+
+	private static final String ANNOTATION_TYPE = "org.eclipse.wst.xml.ui.matching.tag"; //$NON-NLS-1$
+	private ISelectionChangedListener fUpdateListener = null;
+	static final boolean DEBUG = false;
+
+	/**
+	 * @param bundle
+	 * @param prefix
+	 * @param editor
+	 * @param style
+	 */
+	GoToMatchingTagAction(ResourceBundle bundle, String prefix, ITextEditor editor) {
+		super(bundle, prefix, editor);
+		fUpdateListener = new UpdateListener();
+	}
+
+	void removeAnnotation(boolean allMatching) {
+		ITextEditor textEditor = getTextEditor();
+		if (textEditor == null) {
+			if (DEBUG) {
+				System.out.println("no editor"); //$NON-NLS-1$
+			}
+			return;
+		}
+		IDocumentProvider documentProvider = textEditor.getDocumentProvider();
+		if (documentProvider == null) {
+			if (DEBUG) {
+				System.out.println("no document provider"); //$NON-NLS-1$
+			}
+			return;
+		}
+		IAnnotationModel annotationModel = documentProvider.getAnnotationModel(textEditor.getEditorInput());
+		if (annotationModel == null) {
+			if (DEBUG) {
+				System.out.println("no annotation model"); //$NON-NLS-1$
+			}
+			return;
+		}
+
+		Iterator annotationIterator = annotationModel.getAnnotationIterator();
+		List oldAnnotations = new ArrayList();
+		while (annotationIterator.hasNext()) {
+			Annotation annotation = (Annotation) annotationIterator.next();
+			if (ANNOTATION_TYPE.equals(annotation.getType())) {
+				annotation.markDeleted(true);
+				/**
+				 * Sometimes it is supported, sometime's it is not. Confusing.
+				 */
+				try {
+					annotationIterator.remove();
+				}
+				catch (UnsupportedOperationException e) {
+					oldAnnotations.add(annotation);
+				}
+				if (DEBUG) {
+					System.out.println("removed " + annotation); //$NON-NLS-1$
+				}
+				if (!allMatching)
+					break;
+			}
+		}
+		if (!oldAnnotations.isEmpty()) {
+			int size = oldAnnotations.size();
+			for (int i = 0; i < size; i++) {
+				annotationModel.removeAnnotation((Annotation) oldAnnotations.get(i));
+			}
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.action.Action#runWithEvent(org.eclipse.swt.widgets.Event)
+	 */
+	public void runWithEvent(Event event) {
+		super.runWithEvent(event);
+		if (getTextEditor() == null)
+			return;
+
+		ISelection selection = getTextEditor().getSelectionProvider().getSelection();
+		if (!selection.isEmpty() && selection instanceof IStructuredSelection && selection instanceof ITextSelection) {
+			Object o = ((IStructuredSelection) selection).getFirstElement();
+			if (o instanceof IDOMNode) {
+				int offset = ((ITextSelection) selection).getOffset();
+				IStructuredDocumentRegion matchRegion = null;
+				if (((Node) o).getNodeType() == Node.ATTRIBUTE_NODE) {
+					o = ((Attr) o).getOwnerElement();
+				}
+
+				int targetOffset = -1;
+				if (o instanceof IDOMNode) {
+					IDOMNode node = (IDOMNode) o;
+					IStructuredDocumentRegion startStructuredDocumentRegion = node.getStartStructuredDocumentRegion();
+					if (startStructuredDocumentRegion != null && startStructuredDocumentRegion.containsOffset(offset)) {
+						matchRegion = ((IDOMNode) o).getEndStructuredDocumentRegion();
+						if (matchRegion != null)
+							targetOffset = matchRegion.getStartOffset() + 2;
+					}
+					else {
+						IStructuredDocumentRegion endStructuredDocumentRegion = node.getEndStructuredDocumentRegion();
+						if (endStructuredDocumentRegion != null && endStructuredDocumentRegion.containsOffset(offset)) {
+							matchRegion = ((IDOMNode) o).getStartStructuredDocumentRegion();
+							if (matchRegion != null)
+								targetOffset = matchRegion.getStartOffset() + 1;
+						}
+					}
+				}
+
+				if (targetOffset >= 0) {
+					getTextEditor().getSelectionProvider().setSelection(new TextSelection(targetOffset, 0));
+				}
+			}
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.ui.texteditor.TextEditorAction#setEditor(org.eclipse.ui.texteditor.ITextEditor)
+	 */
+	public void setEditor(ITextEditor editor) {
+		ITextEditor textEditor = getTextEditor();
+		if (textEditor != null) {
+			removeAnnotation(true);
+
+			ISelectionProvider selectionProvider = textEditor.getSelectionProvider();
+			if (selectionProvider instanceof IPostSelectionProvider) {
+				((IPostSelectionProvider) selectionProvider).removePostSelectionChangedListener(fUpdateListener);
+			}
+		}
+		super.setEditor(editor);
+		if (editor != null) {
+			ISelectionProvider selectionProvider = editor.getSelectionProvider();
+			if (selectionProvider instanceof IPostSelectionProvider) {
+				((IPostSelectionProvider) selectionProvider).addPostSelectionChangedListener(fUpdateListener);
+			}
+
+			updateFor(selectionProvider.getSelection());
+		}
+	}
+
+	public void update() {
+		setEnabled(true);
+
+	}
+
+	void updateFor(ISelection selection) {
+		ITextEditor textEditor = getTextEditor();
+		if (textEditor == null) {
+			if (DEBUG) {
+				System.out.println("no editor"); //$NON-NLS-1$
+			}
+			return;
+		}
+		IDocumentProvider documentProvider = textEditor.getDocumentProvider();
+		if (documentProvider == null) {
+			if (DEBUG) {
+				System.out.println("no document provider"); //$NON-NLS-1$
+			}
+			return;
+		}
+		IAnnotationModel annotationModel = documentProvider.getAnnotationModel(textEditor.getEditorInput());
+		if (annotationModel == null || !(annotationModel instanceof IAnnotationModelExtension)) {
+			if (DEBUG) {
+				System.out.println("no annotation model"); //$NON-NLS-1$
+			}
+			return;
+		}
+
+		List oldAnnotations = new ArrayList(2);
+		Iterator annotationIterator = annotationModel.getAnnotationIterator();
+		while (annotationIterator.hasNext()) {
+			Annotation annotation = (Annotation) annotationIterator.next();
+			if (ANNOTATION_TYPE.equals(annotation.getType())) {
+				annotation.markDeleted(true);
+				if (DEBUG) {
+					System.out.println("removing " + annotation); //$NON-NLS-1$
+				}
+				oldAnnotations.add(annotation);
+			}
+		}
+
+		Map newAnnotations = new HashMap();
+		if (!selection.isEmpty() && selection instanceof IStructuredSelection && selection instanceof ITextSelection) {
+			Object o = ((IStructuredSelection) selection).getFirstElement();
+			if (o instanceof IDOMNode) {
+				int offset = ((ITextSelection) selection).getOffset();
+				IStructuredDocumentRegion matchRegion = null;
+				if (((Node) o).getNodeType() == Node.ATTRIBUTE_NODE) {
+					o = ((Attr) o).getOwnerElement();
+				}
+
+				Position pStart = null;
+				Position pEnd = null;
+				String tag = ""; //$NON-NLS-1$
+				if (o instanceof IDOMNode) {
+					IDOMNode node = (IDOMNode) o;
+					IStructuredDocumentRegion startStructuredDocumentRegion = node.getStartStructuredDocumentRegion();
+					if (startStructuredDocumentRegion != null && startStructuredDocumentRegion.containsOffset(offset)) {
+						if (startStructuredDocumentRegion.getNumberOfRegions() > 1) {
+							ITextRegion nameRegion = startStructuredDocumentRegion.getRegions().get(1);
+							pStart = new Position(startStructuredDocumentRegion.getStartOffset(nameRegion), nameRegion.getTextLength());
+							tag = startStructuredDocumentRegion.getText(nameRegion);
+						}
+						matchRegion = ((IDOMNode) o).getEndStructuredDocumentRegion();
+						if (matchRegion != null && matchRegion.getNumberOfRegions() > 1) {
+							ITextRegion nameRegion = matchRegion.getRegions().get(1);
+							pEnd = new Position(matchRegion.getStartOffset(nameRegion), nameRegion.getTextLength());
+						}
+					}
+					else {
+						IStructuredDocumentRegion endStructuredDocumentRegion = node.getEndStructuredDocumentRegion();
+						if (endStructuredDocumentRegion != null && endStructuredDocumentRegion.containsOffset(offset)) {
+							if (endStructuredDocumentRegion.getNumberOfRegions() > 1) {
+								ITextRegion nameRegion = endStructuredDocumentRegion.getRegions().get(1);
+								pEnd = new Position(endStructuredDocumentRegion.getStartOffset(nameRegion), nameRegion.getTextLength());
+								tag = endStructuredDocumentRegion.getText(nameRegion);
+							}
+							matchRegion = ((IDOMNode) o).getStartStructuredDocumentRegion();
+							if (matchRegion != null && matchRegion.getNumberOfRegions() > 1) {
+								ITextRegion nameRegion = matchRegion.getRegions().get(1);
+								pStart = new Position(matchRegion.getStartOffset(nameRegion), nameRegion.getTextLength());
+							}
+						}
+					}
+				}
+				if (pStart != null && pEnd != null) {
+					Annotation annotation = new Annotation(ANNOTATION_TYPE, false, NLS.bind(XMLUIMessages.gotoMatchingTag_start, tag));
+					newAnnotations.put(annotation, pStart);
+					if (DEBUG) {
+						System.out.println("adding " + annotation); //$NON-NLS-1$
+					}
+					annotation = new Annotation(ANNOTATION_TYPE, false, NLS.bind(XMLUIMessages.gotoMatchingTag_end, tag));
+					newAnnotations.put(annotation, pEnd);
+					if (DEBUG) {
+						System.out.println("adding " + annotation); //$NON-NLS-1$
+					}
+				}
+			}
+		}
+		((IAnnotationModelExtension) annotationModel).replaceAnnotations((Annotation[]) oldAnnotations.toArray(new Annotation[oldAnnotations.size()]), newAnnotations);
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/MenuBuilder.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/MenuBuilder.java
new file mode 100644
index 0000000..78f3ceb
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/MenuBuilder.java
@@ -0,0 +1,146 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+
+
+package org.eclipse.wst.xml.ui.internal.actions;
+
+import com.ibm.icu.text.Collator;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.List;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.MenuManager;
+
+
+public class MenuBuilder {
+
+
+	protected Comparator comparator = new Comparator() {
+
+		public int compare(Object o1, Object o2) {
+			return Collator.getInstance().compare(getSortKey(o1), getSortKey(o2));
+		}
+
+		protected String getSortKey(Object o) {
+			String result = ""; //$NON-NLS-1$
+			if (o instanceof IAction) {
+				IAction action = (IAction) o;
+				result = action.getText();
+			}
+			// else if (o instanceof MenuData)
+			// {
+			// result = "z" + ((MenuData)o).name;
+			// }
+			return result;
+		}
+	};
+
+
+	protected void createAlphebeticalGrouping(IMenuManager menu, List actionList) {
+		Object[] array = actionList.toArray();
+		if (array.length > 0) {
+			Arrays.sort(array, comparator);
+		}
+
+		int groupSize = 15;
+		int minGroupSize = 5;
+		int numberOfGroups = (array.length / groupSize) + ((array.length % groupSize > minGroupSize) ? 1 : 0);
+
+		for (int i = 0; i < numberOfGroups; i++) {
+			boolean isLastGroup = (i == (numberOfGroups - 1));
+			int firstIndex = i * groupSize;
+			int lastIndex = isLastGroup ? array.length - 1 : i * groupSize + groupSize - 1;
+			Action firstAction = (Action) array[firstIndex];
+			Action lastAction = (Action) array[lastIndex];
+			MenuManager submenu = new MenuManager(firstAction.getText() + " - " + lastAction.getText()); //$NON-NLS-1$
+			menu.add(submenu);
+			for (int j = firstIndex; j <= lastIndex; j++) {
+				submenu.add((Action) array[j]);
+			}
+		}
+	}
+
+
+	public void populateMenu(IMenuManager menu, List actionList, boolean createTiered) {
+		// sort the actions
+		if (actionList.size() < 25) {
+			Object[] array = actionList.toArray();
+			if (array.length > 0) {
+				Arrays.sort(array, comparator);
+			}
+			for (int i = 0; i < array.length; i++) {
+				menu.add((Action) array[i]);
+			}
+		}
+		else {
+			createAlphebeticalGrouping(menu, actionList);
+		}
+	}
+
+	/*
+	 * protected void createPropertyGrouping(IMenuManager menu, List
+	 * actionList) { MenuDataTable menuDataTable = new MenuDataTable();
+	 * 
+	 * for (Iterator i = actionList.iterator(); i.hasNext(); ) { String
+	 * groupName = null; Action action = (Action)i.next(); if (action
+	 * instanceof NodeAction) { groupName =
+	 * ((NodeAction)action).getGroupName(); } if (groupName == null) {
+	 * groupName = ""; } MenuData menuData =
+	 * menuDataTable.lookupOrCreate(groupName, "");
+	 * menuData.childList.add(action); } populateMenu(menu,
+	 * menuDataTable.getRoot()); }
+	 * 
+	 * 
+	 * protected void populateMenu(MenuManager menuManager, MenuData menuData) {
+	 * for (Iterator i = menuData.childList.iterator(); i.hasNext(); ) {
+	 * Object o = i.next(); if (o instanceof Action) {
+	 * menuManager.add((Action)o); } else if (o instanceof MenuData) {
+	 * MenuData childMenuData = (MenuData)o; MenuManager childMenuManager =
+	 * new MenuManager(childMenuData.name); menuManager.add(childMenuManager);
+	 * populateMenu(childMenuManager, childMenuData); } } }
+	 * 
+	 * 
+	 * public MenuDataTable { protected Hashtable table = new Hashtable();
+	 * protected MenuData root;
+	 * 
+	 * public MenuDataTable() { root = lookupOrCreateMenuData(null, null); }
+	 * 
+	 * protected MenuData lookupMenuData(String name) { String key = name !=
+	 * null ? name : ""; return (MenuData)menuDataTable.get(key); }
+	 * 
+	 * protected MenuData lookupOrCreateMenuData(String name, String
+	 * parentName) { String key = name != null ? name : ""; MenuData menuData =
+	 * (MenuData)menuDataTable.get(key); if (menuData == null) { menuData =
+	 * new MenuData(name, parentName); menuDataTable.put(key, menuData); }
+	 * return menuData; }
+	 * 
+	 * public MenuData getRoot() { return root; } }
+	 * 
+	 * 
+	 * protected class MenuData { public String name; public String
+	 * parentName; public List childList = new Vector();
+	 * 
+	 * MenuData(String name, String parentName) { this.name = name;
+	 * this.parentName = parentName; }
+	 * 
+	 * protected void sort() { Object[] array = childList.toArray(); if
+	 * (array.length > 0 ) { Arrays.sort(array, comparator); } childList =
+	 * Arrays.asList(array);
+	 * 
+	 * for (Iterator i = childList.iterator(); i.hasNext(); ) { Object o =
+	 * i.next(); if (o instanceof MenuData) { ((MenuData)o).sort(); } } } }
+	 */
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/NodeAction.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/NodeAction.java
new file mode 100644
index 0000000..1ce764a
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/NodeAction.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2009 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+
+
+package org.eclipse.wst.xml.ui.internal.actions;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jface.action.Action;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+
+public abstract class NodeAction extends Action {
+
+	public String getSortKey() {
+		return null;
+	}
+
+	/**
+	 * Checks that the resource backing the model is writeable utilizing <code>validateEdit</code>
+	 * on a given <tt>IWorkspace</tt>.
+	 * 
+	 * @param model the model to be checked
+	 * @param context the shell context for which <code>validateEdit</code> will be run
+	 * @return boolean result of checking <code>validateEdit</code>. If the resource is unwriteable, <code>status.isOK()</code>
+	 * will return true; otherwise, false.
+	 */
+	protected final boolean validateEdit(IStructuredModel model, Shell context) {
+		if (model != null && model.getBaseLocation() != null) {
+			IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(model.getBaseLocation()));
+			return !file.isAccessible() || ResourcesPlugin.getWorkspace().validateEdit(new IFile[] {file}, context).isOK();
+		}
+		return false; //$NON-NLS-1$
+	}
+
+	public abstract String getUndoDescription();
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/RemoveBlockCommentActionXMLDelegate.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/RemoveBlockCommentActionXMLDelegate.java
new file mode 100644
index 0000000..473e5f2
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/RemoveBlockCommentActionXMLDelegate.java
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+
+package org.eclipse.wst.xml.ui.internal.actions;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
+import org.eclipse.wst.xml.core.internal.document.CommentImpl;
+import org.eclipse.wst.xml.ui.internal.Logger;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+
+/**
+ * Remove block comment action delegate for XML editor
+ */
+public class RemoveBlockCommentActionXMLDelegate extends AbstractCommentActionXMLDelegate {
+
+	void processAction(IDocument document, ITextSelection textSelection) {
+		IStructuredModel model = StructuredModelManager.getModelManager().getExistingModelForEdit(document);
+		if (model != null) {
+			try {
+				IndexedRegion selectionStartIndexedRegion = model.getIndexedRegion(textSelection.getOffset());
+				IndexedRegion selectionEndIndexedRegion = model.getIndexedRegion(textSelection.getOffset() + textSelection.getLength());
+
+				if ((selectionStartIndexedRegion == null) || (selectionEndIndexedRegion == null)) {
+					return;
+				}
+
+				int openCommentOffset = selectionStartIndexedRegion.getStartOffset();
+				int closeCommentOffset = selectionEndIndexedRegion.getEndOffset() - OPEN_COMMENT.length() - CLOSE_COMMENT.length();
+
+				model.beginRecording(this, XMLUIMessages.RemoveBlockComment_tooltip);
+				model.aboutToChangeModel();
+
+				try {
+					if (textSelection.getLength() == 0) {
+						if (selectionStartIndexedRegion instanceof CommentImpl) {
+							document.replace(openCommentOffset, OPEN_COMMENT.length(), ""); //$NON-NLS-1$
+							document.replace(closeCommentOffset, CLOSE_COMMENT.length(), ""); //$NON-NLS-1$
+						}
+					}
+					else {
+						if (selectionStartIndexedRegion instanceof CommentImpl) {
+							document.replace(openCommentOffset, OPEN_COMMENT.length(), ""); //$NON-NLS-1$
+						}
+
+						if (selectionEndIndexedRegion instanceof CommentImpl) {
+							document.replace(closeCommentOffset, CLOSE_COMMENT.length(), ""); //$NON-NLS-1$
+						}
+					}
+					removeOpenCloseComments(document, openCommentOffset + OPEN_COMMENT.length(), closeCommentOffset - openCommentOffset - CLOSE_COMMENT.length());
+				}
+				catch (BadLocationException e) {
+					Logger.log(Logger.WARNING_DEBUG, e.getMessage(), e);
+				}
+				finally {
+					model.changedModel();
+					model.endRecording(this);
+				}
+			}
+			finally {
+				model.releaseFromEdit();
+			}
+		}
+	}
+
+	public void init(IAction action) {
+		if (action != null) {
+			action.setText(XMLUIMessages.RemoveBlockComment_label);
+			action.setToolTipText(XMLUIMessages.RemoveBlockComment_tooltip);
+			action.setDescription(XMLUIMessages.RemoveBlockComment_description);
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/ReplacePrefixAction.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/ReplacePrefixAction.java
new file mode 100644
index 0000000..18599bd
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/ReplacePrefixAction.java
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2009 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.actions;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Vector;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.DOMVisitor;
+import org.eclipse.wst.xml.ui.internal.XMLUIPlugin;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+
+
+public class ReplacePrefixAction extends NodeAction {
+
+	class NodeCollectingDOMVisitor extends DOMVisitor {
+		public List list = new Vector();
+
+		protected boolean isPrefixChangedNeeded(Node node) {
+			String key = node.getPrefix() != null ? node.getPrefix() : ""; //$NON-NLS-1$
+			return prefixMapping.get(key) != null;
+		}
+
+		public void visitAttr(Attr attr) {
+			/*
+			 * if (isPrefixChangedNeeded(element)) { list.add(attr); }
+			 */
+		}
+
+		protected void visitElement(Element element) {
+			super.visitElement(element);
+			if (isPrefixChangedNeeded(element)) {
+				list.add(element);
+			}
+		}
+	}
+
+	protected static ImageDescriptor imageDescriptor;
+	protected Element element;
+	protected AbstractNodeActionManager manager;
+	protected Map prefixMapping;
+
+	public ReplacePrefixAction(AbstractNodeActionManager manager, Element element, Map prefixMapping) {
+		this.manager = manager;
+		this.element = element;
+		this.prefixMapping = prefixMapping;
+	}
+
+	public String getUndoDescription() {
+		return ""; //$NON-NLS-1$
+	}
+
+	public void run() {
+		Shell shell = XMLUIPlugin.getInstance().getWorkbench().getActiveWorkbenchWindow().getShell();
+		if (validateEdit(manager.getModel(), shell)) {
+			NodeCollectingDOMVisitor visitor = new NodeCollectingDOMVisitor();
+			visitor.visitNode(element);
+			for (Iterator i = visitor.list.iterator(); i.hasNext();) {
+				Node node = (Node) i.next();
+				String key = node.getPrefix() != null ? node.getPrefix() : ""; //$NON-NLS-1$
+				String newPrefix = (String) prefixMapping.get(key);
+				if (newPrefix != null) {
+					node.setPrefix(newPrefix);
+				}
+			}
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/SiblingNavigationAction.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/SiblingNavigationAction.java
new file mode 100644
index 0000000..a08b44f
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/SiblingNavigationAction.java
@@ -0,0 +1,110 @@
+/*******************************************************************************
+ * Copyright (c) 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.xml.ui.internal.actions;
+
+import java.util.ResourceBundle;
+
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.ui.texteditor.TextEditorAction;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Node;
+
+/**
+ * Provides navigation to next/previous DOM sibling Nodes
+ * 
+ * @author nitin
+ * 
+ */
+class SiblingNavigationAction extends TextEditorAction {
+
+	private boolean fForward;
+
+	/**
+	 * @param bundle
+	 * @param prefix
+	 * @param editor
+	 */
+	SiblingNavigationAction(ResourceBundle bundle, String prefix, ITextEditor editor, boolean forward) {
+		super(bundle, prefix, editor);
+		fForward = forward;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.action.Action#runWithEvent(org.eclipse.swt.widgets.Event)
+	 */
+	public void runWithEvent(Event event) {
+		super.runWithEvent(event);
+		if (getTextEditor() == null)
+			return;
+
+		ISelection selection = getTextEditor().getSelectionProvider().getSelection();
+		if (!selection.isEmpty() && selection instanceof IStructuredSelection) {
+			Object o = ((IStructuredSelection) selection).getFirstElement();
+			if (o instanceof Node) {
+				Node sibling = null;
+
+				if (((Node) o).getNodeType() == Node.ATTRIBUTE_NODE) {
+					o = ((Attr) o).getOwnerElement();
+				}
+				if (fForward) {
+					sibling = ((Node) o).getNextSibling();
+					while (sibling != null && sibling.getNodeType() == Node.TEXT_NODE && sibling.getNodeValue().trim().length() == 0) {
+						sibling = sibling.getNextSibling();
+					}
+					if (sibling == null) {
+						sibling = ((Node) o).getParentNode().getFirstChild();
+						while (sibling != null && sibling.getNodeType() == Node.TEXT_NODE && sibling.getNodeValue().trim().length() == 0) {
+							sibling = sibling.getNextSibling();
+						}
+					}
+				}
+				else {
+					sibling = ((Node) o).getPreviousSibling();
+					while (sibling != null && sibling.getNodeType() == Node.TEXT_NODE && sibling.getNodeValue().trim().length() == 0) {
+						sibling = sibling.getPreviousSibling();
+					}
+					if (sibling == null) {
+						sibling = ((Node) o).getParentNode().getLastChild();
+						while (sibling != null && sibling.getNodeType() == Node.TEXT_NODE && sibling.getNodeValue().trim().length() == 0) {
+							sibling = sibling.getPreviousSibling();
+						}
+					}
+				}
+
+				// The only child is a Text Node, go to the parent Node
+				if (((Node) o).getNodeType() == Node.TEXT_NODE && o.equals(sibling)) {
+					sibling = ((Node) o).getParentNode();
+				}
+
+
+				if (sibling != null) {
+					getTextEditor().getSelectionProvider().setSelection(new StructuredSelection(sibling));
+				}
+			}
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.ui.texteditor.TextEditorAction#update()
+	 */
+	public void update() {
+
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/ToggleCommentActionXMLDelegate.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/ToggleCommentActionXMLDelegate.java
new file mode 100644
index 0000000..09d81d1
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/ToggleCommentActionXMLDelegate.java
@@ -0,0 +1,174 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+
+package org.eclipse.wst.xml.ui.internal.actions;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.TextSelection;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.xml.ui.internal.Logger;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+
+/**
+ * Toggle comment action delegate for XML editor
+ */
+public class ToggleCommentActionXMLDelegate extends AbstractCommentActionXMLDelegate {
+	public void init(IAction action) {
+		if (action != null) {
+			action.setText(XMLUIMessages.ToggleComment_label);
+			action.setToolTipText(XMLUIMessages.ToggleComment_tooltip);
+			action.setDescription(XMLUIMessages.ToggleComment_description);
+		}
+	}
+
+	void processAction(IDocument document, ITextSelection textSelection) {
+		// get text selection lines info
+		int selectionStartLine = textSelection.getStartLine();
+		int selectionEndLine = textSelection.getEndLine();
+		try {
+			int selectionEndLineOffset = document.getLineOffset(selectionEndLine);
+			int selectionEndOffset = textSelection.getOffset() + textSelection.getLength();
+
+			// adjust selection end line
+			if ((selectionEndLine > selectionStartLine) && (selectionEndLineOffset == selectionEndOffset)) {
+				selectionEndLine--;
+			}
+
+		}
+		catch (BadLocationException e) {
+			Logger.log(Logger.WARNING_DEBUG, e.getMessage(), e);
+		}
+
+		// save the selection position since it will be changing
+		Position selectionPosition = null;
+		boolean updateStartOffset = false;
+		try {
+			selectionPosition = new Position(textSelection.getOffset(), textSelection.getLength());
+			document.addPosition(selectionPosition);
+
+			// extra check if commenting from beginning of line
+			int selectionStartLineOffset = document.getLineOffset(selectionStartLine);
+			if ((textSelection.getLength() > 0) && (selectionStartLineOffset == textSelection.getOffset()) && !isCommentLine(document, selectionStartLine)) {
+				updateStartOffset = true;
+			}
+		}
+		catch (BadLocationException e) {
+			Logger.log(Logger.WARNING_DEBUG, e.getMessage(), e);
+		}
+
+		processAction(document, selectionStartLine, selectionEndLine);
+
+		updateCurrentSelection(selectionPosition, document, updateStartOffset);
+	}
+
+	private void processAction(IDocument document, int selectionStartLine, int selectionEndLine) {
+		IStructuredModel model = StructuredModelManager.getModelManager().getExistingModelForEdit(document);
+		if (model != null) {
+			try {
+				model.beginRecording(this, XMLUIMessages.ToggleComment_tooltip);
+				model.aboutToChangeModel();
+
+				for (int i = selectionStartLine; i <= selectionEndLine; i++) {
+					try {
+						if (document.getLineLength(i) > 0) {
+							if (isCommentLine(document, i)) {
+								int lineOffset = document.getLineOffset(i);
+								IRegion region = document.getLineInformation(i);
+								String string = document.get(region.getOffset(), region.getLength());
+								int openCommentOffset = lineOffset + string.indexOf(OPEN_COMMENT);
+								int closeCommentOffset = lineOffset + string.indexOf(CLOSE_COMMENT) - OPEN_COMMENT.length();
+								uncomment(document, openCommentOffset, closeCommentOffset);
+							}
+							else {
+								int openCommentOffset = document.getLineOffset(i);
+								int lineDelimiterLength = document.getLineDelimiter(i) == null ? 0 : document.getLineDelimiter(i).length();
+								int closeCommentOffset = openCommentOffset + document.getLineLength(i) - lineDelimiterLength + OPEN_COMMENT.length();
+								comment(document, openCommentOffset, closeCommentOffset);
+							}
+						}
+					}
+					catch (BadLocationException e) {
+						Logger.log(Logger.WARNING_DEBUG, e.getMessage(), e);
+					}
+				}
+			}
+			finally {
+				model.changedModel();
+				model.endRecording(this);
+				model.releaseFromEdit();
+			}
+		}
+	}
+
+	private boolean isCommentLine(IDocument document, int line) {
+		boolean isComment = false;
+
+		try {
+			IRegion region = document.getLineInformation(line);
+			String string = document.get(region.getOffset(), region.getLength()).trim();
+			isComment = (string.length() >= OPEN_COMMENT.length() + CLOSE_COMMENT.length()) && string.startsWith(OPEN_COMMENT) && string.endsWith(CLOSE_COMMENT);
+		}
+		catch (BadLocationException e) {
+			Logger.log(Logger.WARNING_DEBUG, e.getMessage(), e);
+		}
+		return isComment;
+	}
+
+	private void comment(IDocument document, int openCommentOffset, int closeCommentOffset) {
+		try {
+			document.replace(openCommentOffset, 0, OPEN_COMMENT);
+			document.replace(closeCommentOffset, 0, CLOSE_COMMENT);
+			removeOpenCloseComments(document, openCommentOffset + OPEN_COMMENT.length(), closeCommentOffset - openCommentOffset - CLOSE_COMMENT.length());
+		}
+		catch (BadLocationException e) {
+			Logger.log(Logger.WARNING_DEBUG, e.getMessage(), e);
+		}
+	}
+
+	private void uncomment(IDocument document, int openCommentOffset, int closeCommentOffset) {
+		try {
+			document.replace(openCommentOffset, OPEN_COMMENT.length(), ""); //$NON-NLS-1$
+			document.replace(closeCommentOffset, CLOSE_COMMENT.length(), ""); //$NON-NLS-1$
+		}
+		catch (BadLocationException e) {
+			Logger.log(Logger.WARNING_DEBUG, e.getMessage(), e);
+		}
+	}
+
+	private void updateCurrentSelection(Position selectionPosition, IDocument document, boolean updateStartOffset) {
+		if (fEditor instanceof ITextEditor) {
+			// update the selection if text selection changed
+			if (selectionPosition != null) {
+				ITextSelection selection = null;
+				if (updateStartOffset) {
+					selection = new TextSelection(document, selectionPosition.getOffset() - OPEN_COMMENT.length(), selectionPosition.getLength() + OPEN_COMMENT.length());
+				}
+				else {
+					selection = new TextSelection(document, selectionPosition.getOffset(), selectionPosition.getLength());
+				}
+				ISelectionProvider provider = ((ITextEditor) fEditor).getSelectionProvider();
+				if (provider != null) {
+					provider.setSelection(selection);
+				}
+				document.removePosition(selectionPosition);
+			}
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/autoedit/AutoEditStrategyForTabs.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/autoedit/AutoEditStrategyForTabs.java
new file mode 100644
index 0000000..1b416cc
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/autoedit/AutoEditStrategyForTabs.java
@@ -0,0 +1,200 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.autoedit;
+
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.ConfigurableLineTracker;
+import org.eclipse.jface.text.DocumentCommand;
+import org.eclipse.jface.text.IAutoEditStrategy;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ILineTracker;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.TextUtilities;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.ui.texteditor.ITextEditorExtension3;
+import org.eclipse.wst.xml.core.internal.XMLCorePlugin;
+import org.eclipse.wst.xml.core.internal.preferences.XMLCorePreferenceNames;
+import org.eclipse.wst.xml.ui.internal.Logger;
+
+/**
+ * AutoEditStrategy to handle characters inserted when Tab key is pressed
+ */
+public class AutoEditStrategyForTabs implements IAutoEditStrategy {
+	private final String TAB_CHARACTER = "\t"; //$NON-NLS-1$
+
+	public void customizeDocumentCommand(IDocument document, DocumentCommand command) {
+		// if not in smart insert mode just ignore
+		if (!isSmartInsertMode()) {
+			return;
+		}
+
+		// spaces for tab character
+		if ((command.length == 0) && (command.text != null) && (command.text.length() > 0) && (command.text.indexOf(TAB_CHARACTER) != -1)) {
+			smartInsertForTab(command, document);
+		}
+	}
+
+	/**
+	 * Insert spaces for tabs
+	 * 
+	 * @param command
+	 */
+	private void smartInsertForTab(DocumentCommand command, IDocument document) {
+		// tab key was pressed. now check preferences to see if need to insert
+		// spaces instead of tab
+		int indentationWidth = getIndentationWidth();
+		if (indentationWidth > -1) {
+			String originalText = command.text;
+			StringBuffer newText = new StringBuffer(originalText);
+
+			// determine where in line this command begins
+			int lineOffset = -1;
+			try {
+				IRegion lineInfo = document.getLineInformationOfOffset(command.offset);
+				lineOffset = command.offset - lineInfo.getOffset();
+			}
+			catch (BadLocationException e) {
+				Logger.log(Logger.WARNING_DEBUG, e.getMessage(), e);
+			}
+
+			ILineTracker lineTracker = getLineTracker(document, originalText);
+
+			int startIndex = 0;
+			int index = newText.indexOf(TAB_CHARACTER);
+			while (index != -1) {
+				String indent = getIndentString(indentationWidth, lineOffset, lineTracker, index);
+
+				// replace \t character with spaces
+				newText.replace(index, index + 1, indent);
+				if (lineTracker != null) {
+					try {
+						lineTracker.replace(index, 1, indent);
+					}
+					catch (BadLocationException e) {
+						// if something goes wrong with replacing text, just
+						// reset to current string
+						lineTracker.set(newText.toString());
+						Logger.log(Logger.WARNING_DEBUG, e.getMessage(), e);
+					}
+				}
+
+				startIndex = index + indent.length();
+				index = newText.indexOf(TAB_CHARACTER, startIndex);
+			}
+			command.text = newText.toString();
+		}
+	}
+
+	/**
+	 * Calculate number of spaces for next tab stop
+	 */
+	private String getIndentString(int indentationWidth, int lineOffset, ILineTracker lineTracker, int index) {
+		int indentSize = indentationWidth;
+		int offsetInLine = -1;
+		if (lineTracker != null) {
+			try {
+				IRegion lineInfo = lineTracker.getLineInformationOfOffset(index);
+				if ((lineInfo.getOffset() == 0) && (lineOffset > -1)) {
+					offsetInLine = lineOffset + index;
+				}
+				else {
+					offsetInLine = index - lineInfo.getOffset();
+				}
+			}
+			catch (BadLocationException e) {
+				Logger.log(Logger.WARNING_DEBUG, e.getMessage(), e);
+			}
+		}
+		else {
+			if (lineOffset > -1) {
+				offsetInLine = lineOffset + index;
+			}
+		}
+		if ((offsetInLine > -1) && (indentationWidth > 0)) {
+			int remainder = offsetInLine % indentationWidth;
+			indentSize = indentationWidth - remainder;
+		}
+
+		StringBuffer indent = new StringBuffer();
+		for (int i = 0; i < indentSize; i++) {
+			indent.append(' ');
+		}
+		return indent.toString();
+	}
+
+	/**
+	 * Set up a line tracker for text within command if text is multi-line
+	 */
+	private ILineTracker getLineTracker(IDocument document, String originalText) {
+		ConfigurableLineTracker lineTracker = null;
+		int[] delims = TextUtilities.indexOf(document.getLegalLineDelimiters(), originalText, 0);
+		if ((delims[0] != -1) || (delims[1] != -1)) {
+			lineTracker = new ConfigurableLineTracker(document.getLegalLineDelimiters());
+			lineTracker.set(originalText);
+		}
+		return lineTracker;
+	}
+
+	/**
+	 * Return true if active editor is in smart insert mode, false otherwise
+	 * 
+	 * @return boolean
+	 */
+	private boolean isSmartInsertMode() {
+		boolean isSmartInsertMode = false;
+
+		ITextEditor textEditor = null;
+		IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+		if (window != null) {
+			IWorkbenchPage page = window.getActivePage();
+			if (page != null) {
+				IEditorPart editor = page.getActiveEditor();
+				if (editor != null) {
+					if (editor instanceof ITextEditor) {
+						textEditor = (ITextEditor) editor;
+					}
+					else {
+						textEditor = (ITextEditor) editor.getAdapter(ITextEditor.class);
+					}
+				}
+			}
+		}
+
+		// check if smart insert mode
+		if ((textEditor instanceof ITextEditorExtension3) && (((ITextEditorExtension3) textEditor).getInsertMode() == ITextEditorExtension3.SMART_INSERT)) {
+			isSmartInsertMode = true;
+		}
+		return isSmartInsertMode;
+	}
+
+	/**
+	 * Returns indentation width if using spaces for indentation, -1 otherwise
+	 * 
+	 * @return int
+	 */
+	private int getIndentationWidth() {
+		int width = -1;
+
+		Preferences preferences = XMLCorePlugin.getDefault().getPluginPreferences();
+		if (XMLCorePreferenceNames.SPACE.equals(preferences.getString(XMLCorePreferenceNames.INDENTATION_CHAR))) {
+			width = preferences.getInt(XMLCorePreferenceNames.INDENTATION_SIZE);
+		}
+
+		return width;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/autoedit/StructuredAutoEditStrategyXML.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/autoedit/StructuredAutoEditStrategyXML.java
new file mode 100644
index 0000000..3dc10be
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/autoedit/StructuredAutoEditStrategyXML.java
@@ -0,0 +1,284 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.autoedit;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.DocumentCommand;
+import org.eclipse.jface.text.IAutoEditStrategy;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.ui.texteditor.ITextEditorExtension3;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+import org.eclipse.wst.xml.ui.internal.Logger;
+import org.eclipse.wst.xml.ui.internal.XMLUIPlugin;
+import org.eclipse.wst.xml.ui.internal.preferences.XMLUIPreferenceNames;
+import org.w3c.dom.Node;
+
+/**
+ * Automatically inserts closing comment tag or end tag when appropriate.
+ */
+public class StructuredAutoEditStrategyXML implements IAutoEditStrategy {
+	/*
+	 * NOTE: copies of this class exists in
+	 * org.eclipse.wst.xml.ui.internal.autoedit
+	 * org.eclipse.wst.html.ui.internal.autoedit
+	 */
+	public void customizeDocumentCommand(IDocument document, DocumentCommand command) {
+		Object textEditor = getActiveTextEditor();
+		if (!((textEditor instanceof ITextEditorExtension3) && (((ITextEditorExtension3) textEditor).getInsertMode() == ITextEditorExtension3.SMART_INSERT))) {
+			return;
+		}
+
+		IStructuredModel model = null;
+		try {
+			model = StructuredModelManager.getModelManager().getExistingModelForRead(document);
+			if (model != null) {
+				if (command.text != null) {
+					smartInsertCloseElement(command, document, model);
+					smartInsertForComment(command, document, model);
+					smartInsertForEndTag(command, document, model);
+					smartRemoveEndTag(command, document, model);
+				}
+			}
+		}
+		finally {
+			if (model != null) {
+				model.releaseFromRead();
+			}
+		}
+	}
+
+	private boolean isPreferenceEnabled(String key) {
+		return (key != null && XMLUIPlugin.getDefault().getPreferenceStore().getBoolean(key));
+	}
+
+	private boolean isCommentNode(IDOMNode node) {
+		return ((node != null) && (node instanceof IDOMElement) && ((IDOMElement) node).isCommentTag());
+	}
+
+	private boolean isDocumentNode(IDOMNode node) {
+		return ((node != null) && (node.getNodeType() == Node.DOCUMENT_NODE));
+	}
+
+	/**
+	 * Attempts to clean up an end-tag if a start-tag is converted into an empty-element
+	 * tag (e.g., <node />) and the original element was empty.
+	 * 
+	 * @param command the document command describing the change
+	 * @param document the document that will be changed
+	 * @param model the model based on the document
+	 */
+	private void smartRemoveEndTag(DocumentCommand command, IDocument document, IStructuredModel model) {
+		try {
+			// An opening tag is now a self-terminated end-tag
+			if ("/".equals(command.text) && ">".equals(document.get(command.offset, 1)) && command.length == 0 && isPreferenceEnabled(XMLUIPreferenceNames.TYPING_REMOVE_END_TAGS)) { //$NON-NLS-1$ //$NON-NLS-2$
+				IDOMNode node = (IDOMNode) model.getIndexedRegion(command.offset);
+				if (node != null && !node.hasChildNodes()) {
+					IStructuredDocumentRegion region = node.getFirstStructuredDocumentRegion();
+					if(region.getFirstRegion().getType() == DOMRegionContext.XML_TAG_OPEN && command.offset <= region.getEnd()) {
+						
+						/* if the region before the command offset is a an attribute value region
+						 * check to see if it has both and opening and closing quote
+						 */
+						ITextRegion prevTextRegion = region.getRegionAtCharacterOffset(command.offset-1);
+						boolean inUnclosedAttValueRegion = false;
+						if(prevTextRegion.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
+							//get the text of the attribute value region
+							String prevText = region.getText(prevTextRegion);
+							inUnclosedAttValueRegion = (prevText.startsWith("'") && ((prevText.length() == 1) || !prevText.endsWith("'"))) ||
+								(prevText.startsWith("\"") && ((prevText.length() == 1) || !prevText.endsWith("\"")));
+						} 
+						//if command offset is in an unclosed attribute value region then done remove the end tag
+						if(!inUnclosedAttValueRegion) {
+							region = node.getEndStructuredDocumentRegion();
+							if (region != null && region.isEnded()) {
+								document.replace(region.getStartOffset(), region.getLength(), ""); //$NON-NLS-1$
+							}
+						}
+					}
+				}
+			}
+		}
+		catch (BadLocationException e) {
+			Logger.logException(e);
+		}
+	}
+
+	private void smartInsertForComment(DocumentCommand command, IDocument document, IStructuredModel model) {
+		try {
+			if (command.text.equals("-") && (document.getLength() >= 3) && document.get(command.offset - 3, 3).equals("<!-") && isPreferenceEnabled(XMLUIPreferenceNames.TYPING_COMPLETE_COMMENTS)) { //$NON-NLS-1$ //$NON-NLS-2$
+				command.text += "  -->"; //$NON-NLS-1$
+				command.shiftsCaret = false;
+				command.caretOffset = command.offset + 2;
+				command.doit = false;
+			}
+		}
+		catch (BadLocationException e) {
+			Logger.logException(e);
+		}
+
+	}
+	
+	/**
+	 * Attempts to insert the end tag when completing a start-tag with the '&gt;' character.
+	 * 
+	 * @param command
+	 * @param document
+	 * @param model
+	 */
+	private void smartInsertCloseElement(DocumentCommand command, IDocument document, IStructuredModel model) {
+		try {
+			// Check terminating start tag, but ignore empty-element tags
+			if (command.text.equals(">") && document.getLength() > 0 && document.getChar(command.offset - 1) != '/' && isPreferenceEnabled(XMLUIPreferenceNames.TYPING_COMPLETE_ELEMENTS)) { //$NON-NLS-1$
+				IDOMNode node = (IDOMNode) model.getIndexedRegion(command.offset - 1);
+				boolean isClosedByParent = false;
+				// Only insert an end-tag if necessary. Because of the way the document is parsed, it is possible for a child tag with the same
+				// name as an ancestor to be paired with the end-tag of an ancestor, so the ancestors must be checked for an unclosed tag.
+				if (node != null && node.getNodeType() == Node.ELEMENT_NODE && (!node.isClosed() || (isClosedByParent = hasUnclosedAncestor(node)))) {
+					IStructuredDocumentRegion region = node.getEndStructuredDocumentRegion();
+					if (region != null && region.getRegions().size() > 0 && region.getRegions().get(0).getType() == DOMRegionContext.XML_END_TAG_OPEN && !isClosedByParent)
+						return;
+					command.text += "</" + getElementName(node, command.offset) + ">"; //$NON-NLS-1$ //$NON-NLS-2$
+					command.shiftsCaret = false;
+					command.caretOffset = command.offset + 1;
+				}
+				
+			}
+		} catch (BadLocationException e) {
+			e.printStackTrace();
+		}
+	}
+
+	/**
+	 * Get the element name that will be created by closing the start tag. Defaults
+	 * to the node's nodeName.
+	 * @param node the node that is being edited
+	 * @param offset the offset in the document where the start tag is closed
+	 * @return The element name of the tag
+	 */
+	private String getElementName(IDOMNode node, int offset) {
+		String name = null;
+		
+		IStructuredDocumentRegion region = node.getFirstStructuredDocumentRegion();
+		ITextRegion textRegion = region.getRegionAtCharacterOffset(offset);
+		if (textRegion != null && textRegion.getType() == DOMRegionContext.XML_TAG_NAME) {
+			int nameStart = region.getStartOffset(textRegion);
+			String regionText = region.getText(textRegion);
+			int length = offset - nameStart;
+			if (length <= regionText.length())
+				name = regionText.substring(0, length);
+		}
+		
+		// Default to the node name
+		if (name == null)
+			name = node.getNodeName();
+		return name;
+	}
+
+	private void smartInsertForEndTag(DocumentCommand command, IDocument document, IStructuredModel model) {
+		try {
+			if (command.text.equals("/") && (document.getLength() >= 1) && document.get(command.offset - 1, 1).equals("<") && isPreferenceEnabled(XMLUIPreferenceNames.TYPING_COMPLETE_END_TAGS)) { //$NON-NLS-1$ //$NON-NLS-2$
+				IDOMNode parentNode = (IDOMNode) ((IDOMNode) model.getIndexedRegion(command.offset - 1)).getParentNode();
+				if (isCommentNode(parentNode)) {
+					// loop and find non comment node parent
+					while ((parentNode != null) && isCommentNode(parentNode)) {
+						parentNode = (IDOMNode) parentNode.getParentNode();
+					}
+				}
+
+				if (!isDocumentNode(parentNode)) {
+					// only add end tag if one does not already exist or if
+					// add '/' does not create one already
+					IStructuredDocumentRegion endTagStructuredDocumentRegion = parentNode.getEndStructuredDocumentRegion();
+					IDOMNode ancestor = parentNode;
+					boolean smartInsertForEnd = false;
+					if(endTagStructuredDocumentRegion != null) {
+						// Look for ancestors by the same name that are missing end tags
+						while((ancestor = (IDOMNode) ancestor.getParentNode()) != null) {
+							if(ancestor.getEndStructuredDocumentRegion() == null && parentNode.getNodeName().equals(ancestor.getNodeName())) {
+								smartInsertForEnd = true;
+								break;
+							}
+						}
+					}
+					if (endTagStructuredDocumentRegion == null || smartInsertForEnd) {
+						StringBuffer toAdd = new StringBuffer(parentNode.getNodeName());
+						if (toAdd.length() > 0) {
+							toAdd.append(">"); //$NON-NLS-1$
+							String suffix = toAdd.toString();
+							if ((document.getLength() < command.offset + suffix.length()) || (!suffix.equals(document.get(command.offset, suffix.length())))) {
+								command.text += suffix;
+							}
+						}
+					}
+				}
+			}
+		}
+		catch (BadLocationException e) {
+			Logger.logException(e);
+		}
+	}
+	
+	/**
+	 * Checks if <code>node</code> has an unclosed ancestor by the same name
+	 * 
+	 * @param node the node to check
+	 * @return true if <code>node</code> has an unclosed parent with the same node name
+	 */
+	private boolean hasUnclosedAncestor(IDOMNode node) {
+		IDOMNode parent = (IDOMNode) node.getParentNode();
+		while (parent != null && parent.getNodeType() != Node.DOCUMENT_NODE && parent.getNodeName().equals(node.getNodeName())) {
+			if (!parent.isClosed())
+				return true;
+			parent = (IDOMNode) parent.getParentNode();
+		}
+		return false;
+	}
+
+	/**
+	 * Return the active text editor if possible, otherwise the active editor
+	 * part.
+	 * 
+	 * @return Object
+	 */
+	private Object getActiveTextEditor() {
+		IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+		if (window != null) {
+			IWorkbenchPage page = window.getActivePage();
+			if (page != null) {
+				IEditorPart editor = page.getActiveEditor();
+				if (editor != null) {
+					if (editor instanceof ITextEditor) {
+						return editor;
+					}
+					ITextEditor textEditor = (ITextEditor) editor.getAdapter(ITextEditor.class);
+					if (textEditor != null) {
+						return textEditor;
+					}
+					return editor;
+				}
+			}
+		}
+		return null;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/AbstractContentAssistProcessor.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/AbstractContentAssistProcessor.java
new file mode 100644
index 0000000..c103fbf
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/AbstractContentAssistProcessor.java
@@ -0,0 +1,2509 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.contentassist;
+
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Vector;
+
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
+import org.eclipse.jface.text.contentassist.IContextInformation;
+import org.eclipse.jface.text.contentassist.IContextInformationValidator;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.encoding.ContentTypeEncodingPreferences;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
+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.ITextRegionContainer;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList;
+import org.eclipse.wst.sse.core.internal.util.Debug;
+import org.eclipse.wst.sse.ui.contentassist.ICompletionProposalComputer;
+import org.eclipse.wst.sse.ui.contentassist.StructuredContentAssistProcessor;
+import org.eclipse.wst.sse.ui.internal.IReleasable;
+import org.eclipse.wst.sse.ui.internal.contentassist.ContentAssistUtils;
+import org.eclipse.wst.sse.ui.internal.contentassist.CustomCompletionProposal;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMContent;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMEntityDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNodeList;
+import org.eclipse.wst.xml.core.internal.contentmodel.basic.CMNamedNodeMapImpl;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQueryAction;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.DOMNamespaceHelper;
+import org.eclipse.wst.xml.core.internal.document.AttrImpl;
+import org.eclipse.wst.xml.core.internal.modelquery.ModelQueryUtil;
+import org.eclipse.wst.xml.core.internal.provisional.contenttype.ContentTypeIdForXML;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
+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 org.eclipse.wst.xml.ui.internal.Logger;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+import org.eclipse.wst.xml.ui.internal.XMLUIPlugin;
+import org.eclipse.wst.xml.ui.internal.editor.CMImageUtil;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImageHelper;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImages;
+import org.eclipse.wst.xml.ui.internal.preferences.XMLUIPreferenceNames;
+import org.eclipse.wst.xml.ui.internal.taginfo.MarkupTagInfoProvider;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * @deprecated This class is no longer used locally and will be removed in the future.
+ * Implementers of this class should now use the <code>org.eclipse.wst.sse.ui.completionProposal</code>
+ * extension point in conjunction with the {@link ICompletionProposalComputer} interface.
+ * 
+ * @see StructuredContentAssistProcessor
+ */
+abstract public class AbstractContentAssistProcessor implements IContentAssistProcessor, IReleasable {
+	/**
+	 * ISSUE: this is a bit of hidden JSP knowledge that was implemented this
+	 * way for expedency. Should be evolved in future to depend on
+	 * "nestedContext".
+	 */
+	private class DOMJSPRegionContextsPrivateCopy {
+		private static final String JSP_CLOSE = "JSP_CLOSE"; //$NON-NLS-1$
+		private static final String JSP_COMMENT_CLOSE = "JSP_COMMENT_CLOSE"; //$NON-NLS-1$
+
+		private static final String JSP_COMMENT_OPEN = "JSP_COMMENT_OPEN"; //$NON-NLS-1$
+		private static final String JSP_DECLARATION_OPEN = "JSP_DECLARATION_OPEN"; //$NON-NLS-1$
+		private static final String JSP_DIRECTIVE_CLOSE = "JSP_DIRECTIVE_CLOSE"; //$NON-NLS-1$
+		private static final String JSP_DIRECTIVE_NAME = "JSP_DIRECTIVE_NAME"; //$NON-NLS-1$
+
+		private static final String JSP_DIRECTIVE_OPEN = "JSP_DIRECTIVE_OPEN"; //$NON-NLS-1$
+		private static final String JSP_EXPRESSION_OPEN = "JSP_EXPRESSION_OPEN"; //$NON-NLS-1$
+
+		private static final String JSP_ROOT_TAG_NAME = "JSP_ROOT_TAG_NAME"; //$NON-NLS-1$
+
+		private static final String JSP_SCRIPTLET_OPEN = "JSP_SCRIPTLET_OPEN"; //$NON-NLS-1$
+
+	}
+
+	protected static final String INTERNALERROR = XMLUIMessages.SEVERE_internal_error_occu_UI_;
+	protected static final String UNKNOWN_ATTR = XMLUIMessages.No_known_attribute__UI_;
+	protected static final String UNKNOWN_CONTEXT = XMLUIMessages.Content_Assist_not_availab_UI_;
+	protected char completionProposalAutoActivationCharacters[] = null;
+	protected char contextInformationAutoActivationCharacters[] = null;
+	private AttributeContextInformationPresenter fContextInformationPresenter = null;
+
+	protected String fErrorMessage = null;
+	protected XMLContentModelGenerator fGenerator;
+	// protected IResource resource = null;
+	protected MarkupTagInfoProvider fInfoProvider = null;
+	protected ITextViewer fTextViewer = null;
+
+	private final boolean showValues = true;
+
+	public AbstractContentAssistProcessor() {
+		init();
+	}
+
+	protected void addAttributeNameProposals(ContentAssistRequest contentAssistRequest) {
+		IDOMNode node = (IDOMNode) contentAssistRequest.getNode();
+		IStructuredDocumentRegion sdRegion = contentAssistRequest.getDocumentRegion();
+		// retrieve the list of attributes
+		CMElementDeclaration elementDecl = getCMElementDeclaration(node);
+		if (elementDecl != null) {
+			CMNamedNodeMap attributes = elementDecl.getAttributes();
+			
+			CMNamedNodeMapImpl allAttributes = new CMNamedNodeMapImpl(attributes);
+			if (node.getNodeType() == Node.ELEMENT_NODE) {
+				List nodes = ModelQueryUtil.getModelQuery(node.getOwnerDocument()).getAvailableContent((Element) node, elementDecl, ModelQuery.INCLUDE_ATTRIBUTES);
+				for (int k = 0; k < nodes.size(); k++) {
+					CMNode cmnode = (CMNode) nodes.get(k);
+					if (cmnode.getNodeType() == CMNode.ATTRIBUTE_DECLARATION) {
+						allAttributes.put(cmnode);
+					}
+				}
+			}
+			attributes = allAttributes;
+
+			String matchString = contentAssistRequest.getMatchString();
+
+			// check whether an attribute really exists for the replacement
+			// offsets AND if it possesses a value
+			boolean attrAtLocationHasValue = false;
+			NamedNodeMap attrs = node.getAttributes();
+			for (int i = 0; i < attrs.getLength(); i++) {
+				AttrImpl existingAttr = (AttrImpl) attrs.item(i);
+				ITextRegion name = existingAttr.getNameRegion();
+
+				if ((sdRegion.getStartOffset(name) <= contentAssistRequest.getReplacementBeginPosition()) && (sdRegion.getStartOffset(name) + name.getLength() >= contentAssistRequest.getReplacementBeginPosition() + contentAssistRequest.getReplacementLength()) && (existingAttr.getValueRegion() != null)) {
+					attrAtLocationHasValue = true;
+					break;
+				}
+			}
+
+			// only add proposals for the attributes whose names begin with
+			// the matchstring
+			if (attributes != null) {
+				for (int i = 0; i < attributes.getLength(); i++) {
+					CMAttributeDeclaration attrDecl = (CMAttributeDeclaration) attributes.item(i);
+
+					int isRequired = 0;
+					if (attrDecl.getUsage() == CMAttributeDeclaration.REQUIRED) {
+						isRequired = XMLRelevanceConstants.R_REQUIRED;
+					}
+
+					boolean showAttribute = true;
+					showAttribute = showAttribute && beginsWith(getRequiredName(node, attrDecl), matchString.trim());
+					AttrImpl attr = (AttrImpl) node.getAttributes().getNamedItem(getRequiredName(node, attrDecl));
+					ITextRegion nameRegion = attr != null ? attr.getNameRegion() : null;
+					// nameRegion.getEndOffset() + 1 is required to allow for
+					// matches against the full name of an existing Attr
+					showAttribute = showAttribute && ((attr == null) || ((nameRegion != null) && (sdRegion.getStartOffset(nameRegion) <= contentAssistRequest.getReplacementBeginPosition()) && (sdRegion.getStartOffset(nameRegion) + nameRegion.getLength() >= contentAssistRequest.getReplacementBeginPosition() + contentAssistRequest.getReplacementLength())));
+					if (showAttribute) {
+						Image attrImage = CMImageUtil.getImage(attrDecl);
+						if (attrImage == null) {
+							if (isRequired > 0) {
+								attrImage = XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_ATT_REQ_OBJ);
+							}
+							else {
+								attrImage = XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_ATTRIBUTE);
+							}
+						}
+
+						String proposedText = null;
+						String proposedInfo = getAdditionalInfo(elementDecl, attrDecl);
+						CustomCompletionProposal proposal = null;
+						// attribute is at this location and already exists
+						if (attrAtLocationHasValue) {
+							// only propose the name
+							proposedText = getRequiredName(node, attrDecl);
+							proposal = new CustomCompletionProposal(proposedText, contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), proposedText.length(), attrImage, proposedText, null, proposedInfo, XMLRelevanceConstants.R_XML_ATTRIBUTE_NAME + isRequired, true);
+						}
+						// no attribute exists or is elsewhere, generate
+						// minimally
+						else {
+							Attr existingAttrNode = (Attr) node.getAttributes().getNamedItem(getRequiredName(node, attrDecl));
+							String value = null;
+							if (existingAttrNode != null) {
+								value = existingAttrNode.getNodeValue();
+							}
+							if ((value != null) && (value.length() > 0)) {
+								proposedText = getRequiredName(node, attrDecl);
+							}
+							else {
+								proposedText = getRequiredText(node, attrDecl);
+							}
+							proposal = new CustomCompletionProposal(proposedText, contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), attrDecl.getNodeName().length() + 2, attrImage,
+							// if the value isn't empty (no empty set of
+										// quotes), show it
+							// BUG 203494, content strings may have "", but not be empty
+							// An empty string is when there's no content between double quotes
+							// and there is no single quote that may be encasing a double quote
+										(showValues && (proposedText.lastIndexOf('\"') - proposedText.indexOf('\"') ==  1 && proposedText.indexOf('\'') == -1)) ? getRequiredName(node, attrDecl) : proposedText,
+										null, proposedInfo, XMLRelevanceConstants.R_XML_ATTRIBUTE_NAME + isRequired);
+						}
+						contentAssistRequest.addProposal(proposal);
+					}
+				}
+			}
+		}
+		else {
+			setErrorMessage(NLS.bind(XMLUIMessages.Element__is_unknown, (new Object[]{node.getNodeName()})));
+		}
+	}
+
+	protected void addAttributeValueProposals(ContentAssistRequest contentAssistRequest) {
+
+		IDOMNode node = (IDOMNode) contentAssistRequest.getNode();
+
+		// Find the attribute region and name for which this position should
+		// have a value proposed
+		IStructuredDocumentRegion open = node.getFirstStructuredDocumentRegion();
+		ITextRegionList openRegions = open.getRegions();
+		int i = openRegions.indexOf(contentAssistRequest.getRegion());
+		if (i < 0) {
+			return;
+		}
+		ITextRegion nameRegion = null;
+		while (i >= 0) {
+			nameRegion = openRegions.get(i--);
+			if (nameRegion.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) {
+				break;
+			}
+		}
+
+		// the name region is REQUIRED to do anything useful
+		if (nameRegion != null) {
+			// Retrieve the declaration
+			CMElementDeclaration elementDecl = getCMElementDeclaration(node);
+
+			// String attributeName = nameRegion.getText();
+			String attributeName = open.getText(nameRegion);
+
+			CMAttributeDeclaration attrDecl = null;
+
+			// No CMElementDeclaration means no attribute metadata, but
+			// retrieve the
+			// declaration for the attribute otherwise
+			if (elementDecl != null) {
+				CMNamedNodeMap attributes = elementDecl.getAttributes();
+
+				CMNamedNodeMapImpl allAttributes = new CMNamedNodeMapImpl(attributes) {
+					private Map caseInsensitive;
+					
+					private Map getCaseInsensitiveMap() {
+						if(caseInsensitive == null)
+							caseInsensitive = new HashMap();
+						return caseInsensitive;
+					}
+
+					public CMNode getNamedItem(String name) {
+						CMNode node = super.getNamedItem(name);
+						if (node == null) {
+							node = (CMNode) getCaseInsensitiveMap().get(name.toLowerCase(Locale.US));
+						}
+						return node;
+					}
+
+					public void put(CMNode cmNode) {
+						super.put(cmNode);
+						getCaseInsensitiveMap().put(cmNode.getNodeName().toLowerCase(Locale.US), cmNode);
+					}
+				};
+				if (node.getNodeType() == Node.ELEMENT_NODE) {
+					List nodes = ModelQueryUtil.getModelQuery(node.getOwnerDocument()).getAvailableContent((Element) node, elementDecl, ModelQuery.INCLUDE_ATTRIBUTES);
+					for (int k = 0; k < nodes.size(); k++) {
+						CMNode cmnode = (CMNode) nodes.get(k);
+						if (cmnode.getNodeType() == CMNode.ATTRIBUTE_DECLARATION) {
+							allAttributes.put(cmnode);
+						}
+					}
+				}
+				attributes = allAttributes;
+
+				String noprefixName = DOMNamespaceHelper.getUnprefixedName(attributeName);
+				if (attributes != null) {
+					attrDecl = (CMAttributeDeclaration) attributes.getNamedItem(noprefixName);
+					if (attrDecl == null) {
+						attrDecl = (CMAttributeDeclaration) attributes.getNamedItem(attributeName);
+					}
+				}
+				if (attrDecl == null) {
+					setErrorMessage(UNKNOWN_ATTR, attributeName);
+				}
+			}
+
+			String currentValue = node.getAttributes().getNamedItem(attributeName).getNodeValue();
+			String proposedInfo = null;
+			Image image = CMImageUtil.getImage(attrDecl);
+			if (image == null) {
+				if ((attrDecl != null) && (attrDecl.getUsage() == CMAttributeDeclaration.REQUIRED)) {
+					image = XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_ATT_REQ_OBJ);
+				}
+				else {
+					image = XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_ATTRIBUTE);
+				}
+			}
+
+			if ((attrDecl != null) && (attrDecl.getAttrType() != null)) {
+				// attribute is known, prompt with values from the declaration
+				proposedInfo = getAdditionalInfo(elementDecl, attrDecl);
+				List possibleValues = getPossibleDataTypeValues(node, attrDecl);
+				String defaultValue = attrDecl.getAttrType().getImpliedValue();
+				if (possibleValues.size() > 0 || defaultValue != null) {
+					// ENUMERATED VALUES
+					String matchString = contentAssistRequest.getMatchString();
+					if (matchString == null) {
+						matchString = ""; //$NON-NLS-1$
+					}
+					if ((matchString.length() > 0) && (matchString.startsWith("\"") || matchString.startsWith("'"))) {
+						matchString = matchString.substring(1);
+					}
+					boolean currentValid = false;
+
+					// d210858, if the region's a container, don't suggest the
+					// enumerated values as they probably won't help
+					boolean existingComplicatedValue = (contentAssistRequest.getRegion() != null) && (contentAssistRequest.getRegion() instanceof ITextRegionContainer);
+					if (!existingComplicatedValue) {
+						int rOffset = contentAssistRequest.getReplacementBeginPosition();
+						int rLength = contentAssistRequest.getReplacementLength();
+						for (Iterator j = possibleValues.iterator(); j.hasNext();) {
+							String possibleValue = (String) j.next();
+							if(!possibleValue.equals(defaultValue)) {
+								currentValid = currentValid || possibleValue.equals(currentValue);
+								if ((matchString.length() == 0) || possibleValue.startsWith(matchString)) {
+									String rString = "\"" + possibleValue + "\""; //$NON-NLS-2$//$NON-NLS-1$
+									CustomCompletionProposal proposal = new CustomCompletionProposal(rString, rOffset, rLength, possibleValue.length() + 1, XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_ENUM), rString, null, proposedInfo, XMLRelevanceConstants.R_XML_ATTRIBUTE_VALUE);
+									contentAssistRequest.addProposal(proposal);
+								}
+							}
+						}
+						if(defaultValue != null && ((matchString.length() == 0) || defaultValue.startsWith(matchString))) {
+							String rString = "\"" + defaultValue + "\""; //$NON-NLS-2$//$NON-NLS-1$
+							CustomCompletionProposal proposal = new CustomCompletionProposal(rString, rOffset, rLength, defaultValue.length() + 1, XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_DEFAULT), rString, null, proposedInfo, XMLRelevanceConstants.R_XML_ATTRIBUTE_VALUE);
+							contentAssistRequest.addProposal(proposal);
+						}
+					}
+				}
+				else if (((attrDecl.getUsage() == CMAttributeDeclaration.FIXED) || (attrDecl.getAttrType().getImpliedValueKind() == CMDataType.IMPLIED_VALUE_FIXED)) && (attrDecl.getAttrType().getImpliedValue() != null)) {
+					// FIXED values
+					String value = attrDecl.getAttrType().getImpliedValue();
+					if ((value != null) && (value.length() > 0)) {
+						String rValue = "\"" + value + "\"";//$NON-NLS-2$//$NON-NLS-1$
+						CustomCompletionProposal proposal = new CustomCompletionProposal(rValue, contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), rValue.length() + 1, image, rValue, null, proposedInfo, XMLRelevanceConstants.R_XML_ATTRIBUTE_VALUE);
+						contentAssistRequest.addProposal(proposal);
+						if ((currentValue.length() > 0) && !value.equals(currentValue)) {
+							rValue = "\"" + currentValue + "\""; //$NON-NLS-2$//$NON-NLS-1$
+							proposal = new CustomCompletionProposal(rValue, contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), rValue.length() + 1, image, rValue, null, proposedInfo, XMLRelevanceConstants.R_XML_ATTRIBUTE_VALUE);
+							contentAssistRequest.addProposal(proposal);
+						}
+					}
+				}
+			}
+			else {
+				// unknown attribute, so supply nice empty values
+				proposedInfo = getAdditionalInfo(null, elementDecl);
+				CustomCompletionProposal proposal = null;
+				if ((currentValue != null) && (currentValue.length() > 0)) {
+					String rValue = "\"" + currentValue + "\""; //$NON-NLS-2$//$NON-NLS-1$
+					proposal = new CustomCompletionProposal(rValue, contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), 1, image, rValue, null, proposedInfo, XMLRelevanceConstants.R_XML_ATTRIBUTE_VALUE);
+					contentAssistRequest.addProposal(proposal);
+				}
+			}
+		}
+		else {
+			setErrorMessage(UNKNOWN_CONTEXT);
+		}
+	}
+
+	protected void addCommentProposal(ContentAssistRequest contentAssistRequest) {
+		contentAssistRequest.addProposal(new CustomCompletionProposal("<!--  -->", //$NON-NLS-1$
+					contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), 5, XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_COMMENT), NLS.bind(XMLUIMessages.Comment__, (new Object[]{" <!--  -->"})), //$NON-NLS-1$
+					null, null, XMLRelevanceConstants.R_COMMENT));
+	}
+
+	/**
+	 * Add all of the element declarations int the CMContent object into one
+	 * big list.
+	 */
+	protected void addContent(List contentList, CMContent content) {
+		if (content == null) {
+			return;
+		}
+		if (content instanceof CMGroup) {
+			CMNodeList children = ((CMGroup) content).getChildNodes();
+			if (children == null) {
+				return;
+			}
+			for (int i = 0; i < children.getLength(); i++) {
+				CMNode child = children.item(i);
+				if (child.getNodeType() == CMNode.ELEMENT_DECLARATION) {
+					contentList.add(child);
+				}
+				else {
+					if (child.getNodeType() == CMNode.GROUP) {
+						addContent(contentList, (CMContent) child);
+					}
+					else {
+						throw new IllegalArgumentException("Unknown content child: " + child); //$NON-NLS-1$
+					}
+				}
+			}
+		}
+		else {
+			contentList.add(content);
+		}
+	}
+
+	protected void addDocTypeProposal(ContentAssistRequest contentAssistRequest) {
+		// if a DocumentElement exists, use that for the root Element name
+		String rootname = "unspecified"; //$NON-NLS-1$
+		if (contentAssistRequest.getNode().getOwnerDocument().getDocumentElement() != null) {
+			rootname = contentAssistRequest.getNode().getOwnerDocument().getDocumentElement().getNodeName();
+		}
+
+		String proposedText = "<!DOCTYPE " + rootname + " PUBLIC \"//UNKNOWN/\" \"unknown.dtd\">"; //$NON-NLS-1$ //$NON-NLS-2$
+		ICompletionProposal proposal = new CustomCompletionProposal(proposedText, contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), 10, XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_DOCTYPE), "<!DOCTYPE ... >", //$NON-NLS-1$
+					null, null, XMLRelevanceConstants.R_DOCTYPE);
+		// TODO provide special documentation on doc type
+		contentAssistRequest.addProposal(proposal);
+	}
+
+	/**
+	 * Add the proposals for a completely empty document
+	 */
+	protected void addEmptyDocumentProposals(ContentAssistRequest contentAssistRequest) {
+		// nothing
+	}
+
+	/**
+	 * Add the proposals for the name in an end tag
+	 */
+	protected void addEndTagNameProposals(ContentAssistRequest contentAssistRequest) {
+
+		if (contentAssistRequest.getStartOffset() + contentAssistRequest.getRegion().getTextLength() < contentAssistRequest.getReplacementBeginPosition()) {
+			CustomCompletionProposal proposal = new CustomCompletionProposal(">", //$NON-NLS-1$
+						contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), 1, XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TAG_GENERIC), NLS.bind(XMLUIMessages.Close_with__, (new Object[]{" '>'"})), //$NON-NLS-1$
+						null, null, XMLRelevanceConstants.R_END_TAG_NAME);
+			contentAssistRequest.addProposal(proposal);
+		}
+		else {
+			IDOMNode node = (IDOMNode) contentAssistRequest.getNode();
+			ModelQuery modelQuery = ModelQueryUtil.getModelQuery(node.getOwnerDocument());
+			Node aNode = contentAssistRequest.getNode();
+			String matchString = contentAssistRequest.getMatchString();
+			if (matchString.startsWith("</")) {
+				matchString = matchString.substring(2);
+			}
+			while (aNode != null) {
+				if (aNode.getNodeType() == Node.ELEMENT_NODE) {
+					if (aNode.getNodeName().startsWith(matchString)) {
+						IDOMNode aXMLNode = (IDOMNode) aNode;
+						CMElementDeclaration ed = modelQuery.getCMElementDeclaration((Element) aNode);
+						if ((aXMLNode.getEndStructuredDocumentRegion() == null) && ((ed == null) || (ed.getContentType() != CMElementDeclaration.EMPTY))) {
+							String replacementText = aNode.getNodeName();
+							String displayText = replacementText;
+							String proposedInfo = (ed != null) ? getAdditionalInfo(null, ed) : null;
+							if(!contentAssistRequest.getDocumentRegion().isEnded()) {
+								replacementText += ">"; //$NON-NLS-1$
+							}
+							CustomCompletionProposal proposal = null;
+							// double check to see if the region acted upon is
+							// a tag name; replace it if so
+							Image image = CMImageUtil.getImage(ed);
+							if (image == null) {
+								image = XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TAG_GENERIC);
+							}
+							if (contentAssistRequest.getRegion().getType() == DOMRegionContext.XML_TAG_NAME) {
+								proposal = new CustomCompletionProposal(replacementText, contentAssistRequest.getStartOffset(), contentAssistRequest.getRegion().getTextLength(), replacementText.length(), image, displayText, null, proposedInfo, XMLRelevanceConstants.R_END_TAG_NAME);
+							}
+							else {
+								proposal = new CustomCompletionProposal(replacementText, contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), replacementText.length(), image, NLS.bind(XMLUIMessages.Close_with__, (new Object[]{"'" + displayText + "'"})), //$NON-NLS-1$ //$NON-NLS-2$
+											null, proposedInfo, XMLRelevanceConstants.R_END_TAG_NAME);
+							}
+							contentAssistRequest.addProposal(proposal);
+						}
+					}
+				}
+				aNode = aNode.getParentNode();
+			}
+		}
+	}
+
+	/**
+	 * Prompt for end tags to a non-empty Node that hasn't ended Handles these
+	 * cases: <br>
+	 * <tagOpen>| <br>
+	 * <tagOpen>< |<br>
+	 * <tagOpen></ |
+	 * 
+	 * @param contentAssistRequest
+	 */
+	protected void addEndTagProposals(ContentAssistRequest contentAssistRequest) {
+		IDOMNode node = (IDOMNode) contentAssistRequest.getParent();
+
+		if (isCommentNode(node)) {
+			// loop and find non comment node parent
+			while ((node != null) && isCommentNode(node)) {
+				node = (IDOMNode) node.getParentNode();
+			}
+		}
+
+		// node is already closed
+		if (node.isClosed()) {
+			// loop and find non comment unclose node parent
+			while ((node != null) && node.isClosed()) {
+				node = (IDOMNode) node.getParentNode();
+			}
+		}
+		// there were no unclosed tags
+		if (node == null) {
+			return;
+		}
+
+		// data to create a CustomCompletionProposal
+		String replaceText = node.getNodeName() + ">"; //$NON-NLS-1$
+		int replaceBegin = contentAssistRequest.getReplacementBeginPosition();
+		int replaceLength = contentAssistRequest.getReplacementLength();
+		int cursorOffset = node.getNodeName().length() + 1;
+		String displayString = ""; //$NON-NLS-1$
+		String proposedInfo = ""; //$NON-NLS-1$
+		Image image = XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TAG_GENERIC);
+
+		setErrorMessage(null);
+		boolean addProposal = false;
+
+		if (node.getNodeType() == Node.ELEMENT_NODE) {
+			// ////////////////////////////////////////////////////////////////////////////////////
+			IStructuredDocument sDoc = (IStructuredDocument) fTextViewer.getDocument();
+			IStructuredDocumentRegion xmlEndTagOpen = sDoc.getRegionAtCharacterOffset(contentAssistRequest.getReplacementBeginPosition());
+			// skip backward to "<", "</", or the (unclosed) start tag, null
+			// if not found
+			String type = ""; //$NON-NLS-1$
+			while ((xmlEndTagOpen != null) && ((type = xmlEndTagOpen.getType()) != DOMRegionContext.XML_END_TAG_OPEN) && (type != DOMRegionContext.XML_TAG_CLOSE) && !needsEndTag(xmlEndTagOpen) && (type != DOMRegionContext.XML_TAG_OPEN)) {
+				xmlEndTagOpen = xmlEndTagOpen.getPrevious();
+			}
+
+			if (xmlEndTagOpen == null) {
+				return;
+			}
+
+			node = (IDOMNode) node.getModel().getIndexedRegion(xmlEndTagOpen.getStartOffset());
+			node = (IDOMNode) node.getParentNode();
+
+			if (isStartTag(xmlEndTagOpen)) {
+				// this is the case for a start tag w/out end tag
+				// eg:
+				// <p>
+				// <% String test = "test"; %>
+				// |
+				if (needsEndTag(xmlEndTagOpen)) {
+					String tagName = getTagName(xmlEndTagOpen);
+					xmlEndTagOpen.getTextEndOffset();
+					replaceLength = 0;
+					replaceText = "</" + tagName + ">"; //$NON-NLS-1$ //$NON-NLS-2$ $NON-NLS-2$
+					// replaceText = "</" + node.getNodeName() + ">";
+					// //$NON-NLS-1$ $NON-NLS-2$
+					cursorOffset = tagName.length() + 3;
+					displayString = NLS.bind(XMLUIMessages.End_with__, (new Object[]{tagName}));
+					addProposal = true;
+				}
+			}
+			else if (type == DOMRegionContext.XML_END_TAG_OPEN) {
+				// this is the case for: <tag> </ |
+				// possibly <tag> </ |<anotherTag>
+				// should only be replacing white space...
+				replaceLength = (replaceBegin > xmlEndTagOpen.getTextEndOffset()) ? replaceBegin - xmlEndTagOpen.getTextEndOffset() : 0;
+				replaceText = node.getNodeName() + ">"; //$NON-NLS-1$
+				cursorOffset = replaceText.length();
+				replaceBegin = xmlEndTagOpen.getTextEndOffset();
+				displayString = NLS.bind(XMLUIMessages.End_with_, (new Object[]{node.getNodeName()}));
+				addProposal = true;
+			}
+			else if (type == DOMRegionContext.XML_TAG_OPEN) {
+				// this is the case for: <tag> < |
+				replaceText = "/" + node.getNodeName() + ">"; //$NON-NLS-1$ //$NON-NLS-2$ $NON-NLS-2$
+				cursorOffset = replaceText.length();
+				// replaceText = "/" + node.getNodeName() + ">"; //$NON-NLS-1$
+				// $NON-NLS-2$
+				// should only be replacing white space...
+				replaceLength = (replaceBegin > xmlEndTagOpen.getTextEndOffset()) ? replaceBegin - xmlEndTagOpen.getTextEndOffset() : 0;
+				replaceBegin = xmlEndTagOpen.getTextEndOffset();
+				displayString = NLS.bind(XMLUIMessages.End_with_, (new Object[]{"/" + node.getNodeName()})); //$NON-NLS-1$
+				addProposal = true;
+			}
+		}
+		// ////////////////////////////////////////////////////////////////////////////////////
+		// sometimes the node is not null, but
+		// getNodeValue() is null, put in a null check
+		else if ((node.getNodeValue() != null) && (node.getNodeValue().indexOf("</") != -1)) { //$NON-NLS-1$
+			// the case where "</" is started, but the nodes comes in as a
+			// text node (instead of element)
+			// like this: <tag> </|
+			Node parent = node.getParentNode();
+			if ((parent != null) && (parent.getNodeType() != Node.DOCUMENT_NODE)) {
+				replaceText = parent.getNodeName() + ">"; //$NON-NLS-1$
+				cursorOffset = replaceText.length();
+				displayString = NLS.bind(XMLUIMessages.End_with__, (new Object[]{parent.getNodeName()}));
+				setErrorMessage(null);
+				addProposal = true;
+			}
+		}
+		// ////////////////////////////////////////////////////////////////////////////////////
+		else if (node.getNodeType() == Node.DOCUMENT_NODE) {
+			setErrorMessage(UNKNOWN_CONTEXT);
+		}
+		if (addProposal == true) {
+			CustomCompletionProposal proposal = new CustomCompletionProposal(replaceText, replaceBegin, replaceLength, cursorOffset, image, displayString, null, proposedInfo, XMLRelevanceConstants.R_END_TAG);
+			contentAssistRequest.addProposal(proposal);
+		}
+	}
+
+	protected void addEntityProposals(ContentAssistRequest contentAssistRequest, int documentPosition, ITextRegion completionRegion, IDOMNode treeNode) {
+		ICompletionProposal[] eps = computeEntityReferenceProposals(documentPosition, completionRegion, treeNode);
+		for (int i = 0; (eps != null) && (i < eps.length); i++) {
+			contentAssistRequest.addProposal(eps[i]);
+		}
+	}
+
+	protected void addEntityProposals(Vector proposals, Properties map, String key, int nodeOffset, IStructuredDocumentRegion sdRegion, ITextRegion completionRegion) {
+		if (map == null) {
+			return;
+		}
+		String entityName = ""; //$NON-NLS-1$
+		String entityValue = ""; //$NON-NLS-1$
+		Image entityIcon = XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_ENTITY_REFERENCE);
+		String replacementText = ""; //$NON-NLS-1$
+		String displayString = ""; //$NON-NLS-1$
+		Enumeration keys = map.keys();
+
+		while ((keys != null) && keys.hasMoreElements()) {
+			entityName = (String) keys.nextElement();
+			entityValue = map.getProperty(entityName);
+			// filter based on partial entity string...
+			if (entityName.toLowerCase().startsWith(key.toLowerCase()) || key.trim().equals("")) //$NON-NLS-1$
+			{
+				// figure out selection...if text is selected, add it to
+				// selection length
+				int selectionLength = nodeOffset;
+				if (fTextViewer != null) {
+					selectionLength += fTextViewer.getSelectedRange().y;
+				}
+				// create a new proposal for entity string...
+				replacementText = "&" + entityName + ";"; //$NON-NLS-1$ //$NON-NLS-2$ 
+				displayString = "&" + entityName + "; (" + entityValue + ")"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+				ICompletionProposal cp = new CustomCompletionProposal(replacementText, sdRegion.getStartOffset(completionRegion), selectionLength, replacementText.length(), entityIcon, displayString, null, null, XMLRelevanceConstants.R_ENTITY);
+				if (cp != null) {
+					proposals.add(cp);
+				}
+			}
+		}
+	}
+
+	protected void addPCDATAProposal(String nodeName, ContentAssistRequest contentAssistRequest) {
+		CustomCompletionProposal proposal = new CustomCompletionProposal("<![CDATA[]]>", //$NON-NLS-1$
+					contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), 9, XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_CDATASECTION), "CDATA Section", //$NON-NLS-1$
+					null, null, XMLRelevanceConstants.R_CDATA);
+		contentAssistRequest.addProposal(proposal);
+
+		proposal = new CustomCompletionProposal(nodeName, contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), nodeName.length(), XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TXTEXT), "#PCDATA", //$NON-NLS-1$
+					null, null, XMLRelevanceConstants.R_CDATA);
+		contentAssistRequest.addProposal(proposal);
+	}
+
+	protected void addStartDocumentProposals(ContentAssistRequest contentAssistRequest) {
+		Node aNode = contentAssistRequest.getNode();
+		boolean xmlpiFound = false;
+		Document owningDocument = aNode.getOwnerDocument();
+		// ==> // int xmlpiNodePosition = -1;
+
+		// make sure xmlpi is root element
+		// don't want doctype proposal if XMLPI isn't first element...
+		Node first = owningDocument.getFirstChild();
+		boolean xmlpiIsFirstElement = ((first != null) && (first.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE));
+		boolean insertDoctype = xmlpiIsFirstElement;
+
+		for (Node child = owningDocument.getFirstChild(); child != null; child = child.getNextSibling()) {
+			boolean xmlpi = ((child.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE) && child.getNodeName().equals("xml")); //$NON-NLS-1$
+			xmlpiFound = xmlpiFound || xmlpi;
+			if (xmlpiFound) {
+				if (child instanceof IDOMNode) {
+					// ==> // int xmlpiNodePosition =
+					// ((XMLNode)child).getEndOffset();
+				}
+				// skip white space and text
+				while (((child = child.getNextSibling()) != null) && (child.getNodeType() == Node.TEXT_NODE)) {
+					// just skipping
+				}
+				// check if theres a node inbetween XMLPI and cursor position
+				if ((child != null) && (child instanceof IDOMNode)) {
+					if ((contentAssistRequest.getReplacementBeginPosition() >= ((IDOMNode) child).getEndOffset()) || !xmlpiIsFirstElement) {
+						insertDoctype = false;
+					}
+				}
+				break;
+			}
+		}
+
+		if (xmlpiFound && (owningDocument.getDoctype() == null) && isCursorAfterXMLPI(contentAssistRequest) && insertDoctype) {
+			addDocTypeProposal(contentAssistRequest);
+		}
+	}
+
+	/**
+	 * Close an unclosed start tag
+	 */
+	protected void addTagCloseProposals(ContentAssistRequest contentAssistRequest) {
+		IDOMNode node = (IDOMNode) contentAssistRequest.getParent();
+		if (node.getNodeType() == Node.ELEMENT_NODE) {
+
+			CMElementDeclaration elementDecl = getCMElementDeclaration(node);
+			String proposedInfo = (elementDecl != null) ? getAdditionalInfo(null, elementDecl) : null;
+			int contentType = (elementDecl != null) ? elementDecl.getContentType() : CMElementDeclaration.ANY;
+			// if it's XML and content doesn't HAVE to be element, add "/>"
+			// proposal.
+			boolean endWithSlashBracket = (getXML(node) && (contentType != CMElementDeclaration.ELEMENT));
+
+			Image image = CMImageUtil.getImage(elementDecl);
+			if (image == null) {
+				image = XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TAG_GENERIC);
+			}
+
+			// is the start tag ended properly?
+			if ((contentAssistRequest.getDocumentRegion() == node.getFirstStructuredDocumentRegion()) && !(node.getFirstStructuredDocumentRegion()).isEnded()) {
+				setErrorMessage(null);
+				// Is this supposed to be an empty tag? Note that if we can't
+				// tell, we assume it's not.
+				if ((elementDecl != null) && (elementDecl.getContentType() == CMElementDeclaration.EMPTY)) {
+					// prompt with a self-closing end character if needed
+					CustomCompletionProposal proposal = new CustomCompletionProposal(getContentGenerator().getStartTagClose(node, elementDecl), contentAssistRequest.getReplacementBeginPosition(),
+					// this is one of the few times to ignore the length --
+								// always insert
+								// contentAssistRequest.getReplacementLength(),
+								0, getContentGenerator().getStartTagClose(node, elementDecl).length(), image, NLS.bind(XMLUIMessages.Close_with___, (new Object[]{getContentGenerator().getStartTagClose(node, elementDecl)})), null, proposedInfo, XMLRelevanceConstants.R_CLOSE_TAG);
+					contentAssistRequest.addProposal(proposal);
+				}
+				else {
+					// prompt with a close for the start tag
+					CustomCompletionProposal proposal = new CustomCompletionProposal(">", //$NON-NLS-1$
+								contentAssistRequest.getReplacementBeginPosition(),
+								// this is one of the few times to ignore the
+								// length -- always insert
+								// contentAssistRequest.getReplacementLength(),
+								0, 1, image, NLS.bind(XMLUIMessages.Close_with__, (new Object[]{" '>'"})), //$NON-NLS-1$
+								null, proposedInfo, XMLRelevanceConstants.R_CLOSE_TAG);
+					contentAssistRequest.addProposal(proposal);
+
+					// prompt with the closer for the start tag and an end tag
+					// if one is not present
+					if (node.getEndStructuredDocumentRegion() == null) {
+						// make sure tag name is actually what it thinks it
+						// is...(eg. <%@ vs. <jsp:directive)
+						IStructuredDocumentRegion sdr = contentAssistRequest.getDocumentRegion();
+						String openingTagText = (sdr != null) ? sdr.getFullText() : ""; //$NON-NLS-1$
+						if ((openingTagText != null) && (openingTagText.indexOf(node.getNodeName()) != -1)) {
+							proposal = new CustomCompletionProposal("></" + node.getNodeName() + ">", //$NON-NLS-2$//$NON-NLS-1$
+										contentAssistRequest.getReplacementBeginPosition(),
+										// this is one of the few times to
+										// ignore the length -- always insert
+										// contentAssistRequest.getReplacementLength(),
+										0, 1, image, NLS.bind(XMLUIMessages.Close_with____, (new Object[]{node.getNodeName()})), null, proposedInfo, XMLRelevanceConstants.R_CLOSE_TAG);
+							contentAssistRequest.addProposal(proposal);
+						}
+					}
+					// prompt with slash bracket "/>" incase if it's a self
+					// ending tag
+					if (endWithSlashBracket) {
+						proposal = new CustomCompletionProposal("/>", //$NON-NLS-1$
+									contentAssistRequest.getReplacementBeginPosition(),
+									// this is one of the few times to ignore
+									// the length -- always insert
+									// contentAssistRequest.getReplacementLength(),
+									0, 2, image, NLS.bind(XMLUIMessages.Close_with__, (new Object[]{" \"/>\""})), //$NON-NLS-1$
+									null, proposedInfo, XMLRelevanceConstants.R_CLOSE_TAG + 1); // +1
+						// to
+						// bring
+						// to
+						// top
+						// of
+						// list
+						contentAssistRequest.addProposal(proposal);
+					}
+				}
+			}
+			else if ((contentAssistRequest.getDocumentRegion() == node.getLastStructuredDocumentRegion()) && !node.getLastStructuredDocumentRegion().isEnded()) {
+				setErrorMessage(null);
+				// prompt with a closing end character for the end tag
+				CustomCompletionProposal proposal = new CustomCompletionProposal(">", //$NON-NLS-1$
+							contentAssistRequest.getReplacementBeginPosition(),
+							// this is one of the few times to ignore the
+							// length -- always insert
+							// contentAssistRequest.getReplacementLength(),
+							0, 1, image, NLS.bind(XMLUIMessages.Close_with__, (new Object[]{" '>'"})), //$NON-NLS-1$
+							null, proposedInfo, XMLRelevanceConstants.R_CLOSE_TAG);
+				contentAssistRequest.addProposal(proposal);
+			}
+		}
+		else if (node.getNodeType() == Node.DOCUMENT_NODE) {
+			setErrorMessage(UNKNOWN_CONTEXT);
+		}
+	}
+
+	protected void addTagInsertionProposals(ContentAssistRequest contentAssistRequest, int childPosition) {
+		List cmnodes = null;
+		Node parent = contentAssistRequest.getParent();
+		String error = null;
+
+		// (nsd) This is only valid at the document element level
+		// only valid if it's XML (check added 2/17/2004)
+		if ((parent != null) && (parent.getNodeType() == Node.DOCUMENT_NODE) && ((IDOMDocument) parent).isXMLType() && !isCursorAfterXMLPI(contentAssistRequest)) {
+			return;
+		}
+		// only want proposals if cursor is after doctype...
+		if (!isCursorAfterDoctype(contentAssistRequest)) {
+			return;
+		}
+
+		// fix for meta-info comment nodes.. they currently "hide" other
+		// proposals because the don't
+		// have a content model (so can't propose any children..)
+		if ((parent != null) && (parent instanceof IDOMNode) && isCommentNode((IDOMNode) parent)) {
+			// loop and find non comment node?
+			while ((parent != null) && isCommentNode((IDOMNode) parent)) {
+				parent = parent.getParentNode();
+			}
+		}
+
+		if (parent.getNodeType() == Node.ELEMENT_NODE) {
+			CMElementDeclaration parentDecl = getCMElementDeclaration(parent);
+			if (parentDecl != null) {
+				// XSD-specific ability - no filtering
+				CMDataType childType = parentDecl.getDataType();
+				if (childType != null) {
+					String[] childStrings = childType.getEnumeratedValues();
+					String defaultValue = childType.getImpliedValue();
+					if (childStrings != null || defaultValue != null) {
+						// the content string is the sole valid child...so
+						// replace the rest
+						int begin = contentAssistRequest.getReplacementBeginPosition();
+						int length = contentAssistRequest.getReplacementLength();
+						if (parent instanceof IDOMNode) {
+							if (((IDOMNode) parent).getLastStructuredDocumentRegion() != ((IDOMNode) parent).getFirstStructuredDocumentRegion()) {
+								begin = ((IDOMNode) parent).getFirstStructuredDocumentRegion().getEndOffset();
+								length = ((IDOMNode) parent).getLastStructuredDocumentRegion().getStartOffset() - begin;
+							}
+						}
+						String proposedInfo = getAdditionalInfo(parentDecl, childType);
+						for (int i = 0; i < childStrings.length; i++) {
+							if(!childStrings[i].equals(defaultValue))
+							{
+								CustomCompletionProposal textProposal = new CustomCompletionProposal(childStrings[i], begin, length, childStrings[i].length(), XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_ENUM), childStrings[i], null, proposedInfo, XMLRelevanceConstants.R_TAG_INSERTION);
+								contentAssistRequest.addProposal(textProposal);
+							}
+						}
+						if(defaultValue != null) {
+							CustomCompletionProposal textProposal = new CustomCompletionProposal(defaultValue, begin, length, defaultValue.length(), XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_DEFAULT), defaultValue, null, proposedInfo, XMLRelevanceConstants.R_TAG_INSERTION);
+							contentAssistRequest.addProposal(textProposal);
+						}
+					}
+				}
+			}
+			if ((parentDecl != null) && (parentDecl.getContentType() == CMElementDeclaration.PCDATA)) {
+				addPCDATAProposal(parentDecl.getNodeName(), contentAssistRequest);
+			}
+			else {
+				// retrieve the list of all possible children within this
+				// parent context
+				cmnodes = getAvailableChildElementDeclarations((Element) parent, childPosition, ModelQueryAction.INSERT);
+
+				// retrieve the list of the possible children within this
+				// parent context and at this index
+				List strictCMNodeSuggestions = null;
+				if (XMLUIPreferenceNames.SUGGESTION_STRATEGY_VALUE_STRICT.equals(XMLUIPlugin.getInstance().getPreferenceStore().getString(XMLUIPreferenceNames.SUGGESTION_STRATEGY))) {
+					strictCMNodeSuggestions = getValidChildElementDeclarations((Element) parent, childPosition, ModelQueryAction.INSERT);
+				}
+				Iterator nodeIterator = cmnodes.iterator();
+				if (!nodeIterator.hasNext()) {
+					if (getCMElementDeclaration(parent) != null) {
+						error = NLS.bind(XMLUIMessages._Has_no_available_child, (new Object[]{parent.getNodeName()}));
+					}
+					else {
+						error = NLS.bind(XMLUIMessages.Element__is_unknown, (new Object[]{parent.getNodeName()}));
+					}
+				}
+				String matchString = contentAssistRequest.getMatchString();
+				// chop off any leading <'s and whitespace from the
+				// matchstring
+				while ((matchString.length() > 0) && (Character.isWhitespace(matchString.charAt(0)) || beginsWith(matchString, "<"))) {
+					//$NON-NLS-1$
+					matchString = matchString.substring(1);
+				}
+				while (nodeIterator.hasNext()) {
+					Object o = nodeIterator.next();
+					if (o instanceof CMElementDeclaration) {
+						CMElementDeclaration elementDecl = (CMElementDeclaration) o;
+						// only add proposals for the child element's that
+						// begin with the matchstring
+						String tagname = getRequiredName(parent, elementDecl);
+						boolean isStrictCMNodeSuggestion = strictCMNodeSuggestions != null ? strictCMNodeSuggestions.contains(elementDecl) : false;
+
+						Image image = CMImageUtil.getImage(elementDecl);
+
+						if (image == null) {
+							if (strictCMNodeSuggestions != null) {
+								image = isStrictCMNodeSuggestion ? XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TAG_GENERIC_EMPHASIZED) : XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TAG_GENERIC_DEEMPHASIZED);
+							}
+							else {
+								image = XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TAG_GENERIC);
+							}
+
+						}
+
+						// int markupAdjustment =
+						// getContentGenerator().getMinimalStartTagLength(parent,
+						// elementDecl);
+						if (beginsWith(tagname, matchString)) {
+							String proposedText = getRequiredText(parent, elementDecl);
+
+							// https://bugs.eclipse.org/bugs/show_bug.cgi?id=89811
+							// place cursor in first empty quotes
+							int markupAdjustment = getCursorPositionForProposedText(proposedText);
+
+							String proposedInfo = getAdditionalInfo(parentDecl, elementDecl);
+							int relevance = isStrictCMNodeSuggestion ? XMLRelevanceConstants.R_STRICTLY_VALID_TAG_INSERTION : XMLRelevanceConstants.R_TAG_INSERTION;
+							CustomCompletionProposal proposal = new CustomCompletionProposal(proposedText, contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), markupAdjustment, image, tagname, null, proposedInfo, relevance);
+							contentAssistRequest.addProposal(proposal);
+						}
+					}
+				}
+				if (contentAssistRequest.getProposals().size() == 0) {
+					if (error != null) {
+						setErrorMessage(error);
+					}
+					else if ((contentAssistRequest.getMatchString() != null) && (contentAssistRequest.getMatchString().length() > 0)) {
+						setErrorMessage(NLS.bind(XMLUIMessages.No_known_child_tag, (new Object[]{parent.getNodeName(), contentAssistRequest.getMatchString()})));
+						//$NON-NLS-1$ = "No known child tag names of <{0}> begin with \"{1}\"."
+					}
+					else {
+						setErrorMessage(NLS.bind(XMLUIMessages.__Has_no_known_child, (new Object[]{parent.getNodeName()})));
+					}
+				}
+			}
+		}
+		else if (parent.getNodeType() == Node.DOCUMENT_NODE) {
+			// Can only prompt with elements if the cursor position is past
+			// the XML processing
+			// instruction and DOCTYPE declaration
+			boolean xmlpiFound = false;
+			boolean doctypeFound = false;
+			int minimumOffset = -1;
+
+			for (Node child = parent.getFirstChild(); child != null; child = child.getNextSibling()) {
+
+				boolean xmlpi = ((child.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE) && child.getNodeName().equals("xml")); //$NON-NLS-1$
+				boolean doctype = child.getNodeType() == Node.DOCUMENT_TYPE_NODE;
+				if (xmlpi || (doctype && (minimumOffset < 0))) {
+					minimumOffset = ((IDOMNode) child).getFirstStructuredDocumentRegion().getStartOffset() + ((IDOMNode) child).getFirstStructuredDocumentRegion().getTextLength();
+				}
+				xmlpiFound = xmlpiFound || xmlpi;
+				doctypeFound = doctypeFound || doctype;
+			}
+
+			if (contentAssistRequest.getReplacementBeginPosition() >= minimumOffset) {
+				List childDecls = getAvailableRootChildren((Document) parent, childPosition);
+				for (int i = 0; i < childDecls.size(); i++) {
+					CMElementDeclaration ed = (CMElementDeclaration) childDecls.get(i);
+					if (ed != null) {
+						Image image = CMImageUtil.getImage(ed);
+						if (image == null) {
+							image = XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TAG_GENERIC);
+						}
+						String proposedText = getRequiredText(parent, ed);
+						String tagname = getRequiredName(parent, ed);
+						// account for the &lt; and &gt;
+						int markupAdjustment = getContentGenerator().getMinimalStartTagLength(parent, ed);
+						String proposedInfo = getAdditionalInfo(null, ed);
+						CustomCompletionProposal proposal = new CustomCompletionProposal(proposedText, contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), markupAdjustment, image, tagname, null, proposedInfo, XMLRelevanceConstants.R_TAG_INSERTION);
+						contentAssistRequest.addProposal(proposal);
+					}
+				}
+			}
+		}
+	}
+
+	protected void addTagNameProposals(ContentAssistRequest contentAssistRequest, int childPosition) {
+		List cmnodes = null;
+		Node parent = contentAssistRequest.getParent();
+		IDOMNode node = (IDOMNode) contentAssistRequest.getNode();
+		String error = null;
+		String matchString = contentAssistRequest.getMatchString();
+		if (parent.getNodeType() == Node.ELEMENT_NODE) {
+			// retrieve the list of children
+			// validActions = getAvailableChildrenAtIndex((Element) parent,
+			// childPosition);
+			cmnodes = getAvailableChildElementDeclarations((Element) parent, childPosition, ModelQueryAction.INSERT);
+			Iterator nodeIterator = cmnodes.iterator();
+			// chop off any leading <'s and whitespace from the matchstring
+			while ((matchString.length() > 0) && (Character.isWhitespace(matchString.charAt(0)) || beginsWith(matchString, "<"))) {
+				//$NON-NLS-1$
+				matchString = matchString.substring(1);
+			}
+			if (!nodeIterator.hasNext()) {
+				error = NLS.bind(XMLUIMessages.__Has_no_known_child, (new Object[]{parent.getNodeName()}));
+			}
+			while (nodeIterator.hasNext()) {
+				CMNode elementDecl = (CMNode) nodeIterator.next();
+				if (elementDecl != null) {
+					// only add proposals for the child element's that begin
+					// with the matchstring
+					String proposedText = null;
+					int cursorAdjustment = 0;
+
+					// do a check to see if partial attributes of partial tag
+					// names are in list
+					if (((node != null) && (node.getAttributes() != null) && (node.getAttributes().getLength() > 0) && attributeInList(node, parent, elementDecl)) || ((node.getNodeType() != Node.TEXT_NODE) && node.getFirstStructuredDocumentRegion().isEnded())) {
+
+						proposedText = getRequiredName(parent, elementDecl);
+						cursorAdjustment = proposedText.length();
+					}
+					else {
+						proposedText = getRequiredName(parent, elementDecl);
+						cursorAdjustment = proposedText.length();
+						if (elementDecl instanceof CMElementDeclaration) {
+							CMElementDeclaration ed = (CMElementDeclaration) elementDecl;
+							// https://bugs.eclipse.org/bugs/show_bug.cgi?id=89811
+							StringBuffer sb = new StringBuffer();
+							getContentGenerator().generateTag(parent, ed, sb);
+							// since it's a name proposal, assume '<' is
+							// already there
+							// only return the rest of the tag
+							proposedText = sb.toString().substring(1);
+							cursorAdjustment = getCursorPositionForProposedText(proposedText);
+
+							// cursorAdjustment = proposedText.length() +
+							// 1;
+							// proposedText += "></" +
+							// getRequiredName(parent, elementDecl) + ">";
+							// //$NON-NLS-2$//$NON-NLS-1$
+						}
+					}
+					if (beginsWith(proposedText, matchString)) {
+						Image image = CMImageUtil.getImage(elementDecl);
+						if (image == null) {
+							image = XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TAG_GENERIC);
+						}
+						String proposedInfo = getAdditionalInfo(getCMElementDeclaration(parent), elementDecl);
+						CustomCompletionProposal proposal = new CustomCompletionProposal(proposedText, contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), cursorAdjustment, image, getRequiredName(parent, elementDecl), null, proposedInfo, XMLRelevanceConstants.R_TAG_NAME);
+						contentAssistRequest.addProposal(proposal);
+					}
+				}
+			}
+			if (contentAssistRequest.getProposals().size() == 0) {
+				if (error != null) {
+					setErrorMessage(error);
+				}
+				else if ((contentAssistRequest.getMatchString() != null) && (contentAssistRequest.getMatchString().length() > 0)) {
+					setErrorMessage(NLS.bind(XMLUIMessages.No_known_child_tag_names, (new Object[]{parent.getNodeName(), contentAssistRequest.getMatchString()})));
+					//$NON-NLS-1$ = "No known child tag names of <{0}> begin with \"{1}\""
+				}
+				else {
+					setErrorMessage(NLS.bind(XMLUIMessages.__Has_no_known_child, (new Object[]{parent.getNodeName()})));
+				}
+			}
+		}
+		else if (parent.getNodeType() == Node.DOCUMENT_NODE) {
+			List childElements = getAvailableRootChildren((Document) parent, childPosition);
+			for (int i = 0; i < childElements.size(); i++) {
+				CMNode ed = (CMNode) childElements.get(i);
+				if (ed == null) {
+					continue;
+				}
+				String proposedText = null;
+				int cursorAdjustment = 0;
+				if (ed instanceof CMElementDeclaration) {
+					// proposedText = getRequiredName(parent, ed);
+					StringBuffer sb = new StringBuffer();
+					getContentGenerator().generateTag(parent, (CMElementDeclaration) ed, sb);
+					// tag starts w/ '<', but we want to compare to name
+					proposedText = sb.toString().substring(1);
+
+					if (!beginsWith(proposedText, matchString)) {
+						continue;
+					}
+
+					cursorAdjustment = getCursorPositionForProposedText(proposedText);
+
+					String proposedInfo = getAdditionalInfo(null, ed);
+					Image image = CMImageUtil.getImage(ed);
+					if (image == null) {
+						image = XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TAG_GENERIC);
+					}
+					CustomCompletionProposal proposal = new CustomCompletionProposal(proposedText, contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), cursorAdjustment, image, getRequiredName(parent, ed), null, proposedInfo, XMLRelevanceConstants.R_TAG_NAME);
+					contentAssistRequest.addProposal(proposal);
+				}
+			}
+		}
+	}
+
+	/**
+	 * this is the position the cursor should be in after the proposal is
+	 * applied
+	 * 
+	 * @param proposedText
+	 * @return the position the cursor should be in after the proposal is
+	 *         applied
+	 */
+	private int getCursorPositionForProposedText(String proposedText) {
+		int cursorAdjustment;
+		cursorAdjustment = proposedText.indexOf("\"\"") + 1; //$NON-NLS-1$
+		// otherwise, after the first tag
+		if (cursorAdjustment == 0) {
+			cursorAdjustment = proposedText.indexOf('>') + 1;
+		}
+		if (cursorAdjustment == 0) {
+			cursorAdjustment = proposedText.length() + 1;
+		}
+
+		return cursorAdjustment;
+	}
+
+	/**
+	 * @deprecated XML proposal is added via xml declaration template instead
+	 */
+	protected void addXMLProposal(ContentAssistRequest contentAssistRequest) {
+		String proposedText = "<?xml version=\"1.0\" encoding=\"" + ContentTypeEncodingPreferences.getUserPreferredCharsetName(ContentTypeIdForXML.ContentTypeID_XML) + "\"?>"; //$NON-NLS-2$//$NON-NLS-1$
+		ICompletionProposal proposal = new CustomCompletionProposal(proposedText, contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), proposedText.length(), XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_PROCESSINGINSTRUCTION), proposedText, null, null, XMLRelevanceConstants.R_XML_DECLARATION);
+		// TODO add special XML proposal info
+		contentAssistRequest.addProposal(proposal);
+	}
+
+	/**
+	 * This method determines if any of the attributes in the proposed XMLNode
+	 * node, are possible values of attributes from possible Elements at this
+	 * point in the document according to the Content Model.
+	 * 
+	 * @param node
+	 *            the element with attributes that you would like to test if
+	 *            are possible for possible Elements at this point
+	 * @param cmnode
+	 *            possible element at this point in the document (depending on
+	 *            what 'node' is) true if any attributes of 'node' match any
+	 *            possible attributes from 'cmnodes' list.
+	 */
+	protected boolean attributeInList(IDOMNode node, Node parent, CMNode cmnode) {
+		if ((node == null) || (parent == null) || (cmnode == null)) {
+			return false;
+		}
+		String elementMatchString = node.getNodeName();
+		String cmnodeName = getRequiredName(parent, cmnode);// cmnode.getNodeName();
+		if (node instanceof Element) {
+			NamedNodeMap map = ((Element) node).getAttributes();
+			String attrMatchString = ""; //$NON-NLS-1$
+			CMNamedNodeMap cmattrMap = null;
+			// iterate attribute possibilities for partially started node
+			for (int i = 0; (map != null) && (i < map.getLength()); i++) {
+				attrMatchString = map.item(i).getNodeName();
+				// filter on whatever user typed for element name already
+				if (beginsWith(cmnodeName, elementMatchString)) {
+					if (cmnode.getNodeType() == CMNode.ELEMENT_DECLARATION) {
+						cmattrMap = ((CMElementDeclaration) cmnode).getAttributes();
+
+						CMNamedNodeMapImpl allAttributes = new CMNamedNodeMapImpl(cmattrMap);
+						List nodes = ModelQueryUtil.getModelQuery(node.getOwnerDocument()).getAvailableContent((Element) node, (CMElementDeclaration) cmnode, ModelQuery.INCLUDE_ATTRIBUTES);
+						for (int k = 0; k < nodes.size(); k++) {
+							CMNode adnode = (CMNode) nodes.get(k);
+							if (adnode.getNodeType() == CMNode.ATTRIBUTE_DECLARATION) {
+								allAttributes.put(adnode);
+							}
+						}
+						cmattrMap = allAttributes;
+						
+						// iterate possible attributes from a cmnode in
+						// proposal list
+						for (int k = 0; (cmattrMap != null) && (k < cmattrMap.getLength()); k++) {
+							// check if name matches
+							if (cmattrMap.item(k).getNodeName().equals(attrMatchString)) {
+								return true;
+							}
+						}
+					}
+				}
+			}
+		}
+		return false;
+	}
+
+	protected boolean beginsWith(String aString, String prefix) {
+		if ((aString == null) || (prefix == null)) {
+			return true;
+		}
+		// (pa) matching independent of case to be consistant with Java
+		// editor CA
+		return aString.toLowerCase().startsWith(prefix.toLowerCase());
+	}
+
+	protected ContentAssistRequest computeAttributeProposals(int documentPosition, String matchString, ITextRegion completionRegion, IDOMNode nodeAtOffset, IDOMNode node) {
+		ContentAssistRequest contentAssistRequest = null;
+		IStructuredDocumentRegion sdRegion = getStructuredDocumentRegion(documentPosition);
+		if (documentPosition < sdRegion.getStartOffset(completionRegion)) {
+			// setup to insert new attributes
+			contentAssistRequest = newContentAssistRequest(nodeAtOffset, node, sdRegion, completionRegion, documentPosition, 0, matchString);
+		}
+		else {
+			// Setup to replace an existing attribute name
+			contentAssistRequest = newContentAssistRequest(nodeAtOffset, node, sdRegion, completionRegion, sdRegion.getStartOffset(completionRegion), completionRegion.getTextLength(), matchString);
+		}
+		addAttributeNameProposals(contentAssistRequest);
+		contentAssistRequest.setReplacementBeginPosition(documentPosition);
+		contentAssistRequest.setReplacementLength(0);
+		if ((node.getFirstStructuredDocumentRegion() != null) && (!node.getFirstStructuredDocumentRegion().isEnded())) {
+			addTagCloseProposals(contentAssistRequest);
+		}
+		return contentAssistRequest;
+	}
+
+	protected ContentAssistRequest computeAttributeValueProposals(int documentPosition, String matchString, ITextRegion completionRegion, IDOMNode nodeAtOffset, IDOMNode node) {
+		ContentAssistRequest contentAssistRequest = null;
+		IStructuredDocumentRegion sdRegion = getStructuredDocumentRegion(documentPosition);
+		if ((documentPosition > sdRegion.getStartOffset(completionRegion) + completionRegion.getTextLength()) && (sdRegion.getStartOffset(completionRegion) + completionRegion.getTextLength() != sdRegion.getStartOffset(completionRegion) + completionRegion.getLength())) {
+			// setup to add a new attribute at the documentPosition
+			IDOMNode actualNode = (IDOMNode) node.getModel().getIndexedRegion(sdRegion.getStartOffset(completionRegion));
+			contentAssistRequest = newContentAssistRequest(actualNode, actualNode, sdRegion, completionRegion, documentPosition, 0, matchString);
+			addAttributeNameProposals(contentAssistRequest);
+			if ((actualNode.getFirstStructuredDocumentRegion() != null) && !actualNode.getFirstStructuredDocumentRegion().isEnded()) {
+				addTagCloseProposals(contentAssistRequest);
+			}
+		}
+		else {
+			// setup to replace the existing value
+			if (!nodeAtOffset.getFirstStructuredDocumentRegion().isEnded() && (documentPosition < sdRegion.getStartOffset(completionRegion))) {
+				// if the IStructuredDocumentRegion isn't closed and the
+				// cursor is in front of the value, add
+				contentAssistRequest = newContentAssistRequest(nodeAtOffset, node, sdRegion, completionRegion, documentPosition, 0, matchString);
+				addAttributeNameProposals(contentAssistRequest);
+			}
+			else {
+				contentAssistRequest = newContentAssistRequest(nodeAtOffset, node, sdRegion, completionRegion, sdRegion.getStartOffset(completionRegion), completionRegion.getTextLength(), matchString);
+				addAttributeValueProposals(contentAssistRequest);
+			}
+		}
+		return contentAssistRequest;
+	}
+
+	protected ContentAssistRequest computeCompletionProposals(int documentPosition, String matchString, ITextRegion completionRegion, IDOMNode treeNode, IDOMNode xmlnode) {
+		ContentAssistRequest contentAssistRequest = null;
+		String regionType = completionRegion.getType();
+		IStructuredDocumentRegion sdRegion = getStructuredDocumentRegion(documentPosition);
+
+		// Handle the most common and best supported cases
+		if ((xmlnode.getNodeType() == Node.ELEMENT_NODE) || (xmlnode.getNodeType() == Node.DOCUMENT_NODE)) {
+			if (regionType == DOMRegionContext.XML_TAG_OPEN) {
+				contentAssistRequest = computeTagOpenProposals(documentPosition, matchString, completionRegion, treeNode, xmlnode);
+			}
+			else if (regionType == DOMRegionContext.XML_TAG_NAME) {
+				contentAssistRequest = computeTagNameProposals(documentPosition, matchString, completionRegion, treeNode, xmlnode);
+			}
+			else if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) {
+				contentAssistRequest = computeAttributeProposals(documentPosition, matchString, completionRegion, treeNode, xmlnode);
+			}
+			else if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_EQUALS) {
+				contentAssistRequest = computeEqualsProposals(documentPosition, matchString, completionRegion, treeNode, xmlnode);
+			}
+			else if ((regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) && (documentPosition == sdRegion.getTextEndOffset()) && (sdRegion.getText(completionRegion).endsWith("\"") || sdRegion.getText(completionRegion).endsWith("\'"))) //$NON-NLS-1$ //$NON-NLS-2$
+			{
+				// this is for when the cursor is at the end of the closing
+				// quote for an attribute..
+				IDOMNode actualNode = (IDOMNode) xmlnode.getModel().getIndexedRegion(sdRegion.getStartOffset(completionRegion));
+				contentAssistRequest = newContentAssistRequest(actualNode, actualNode, sdRegion, completionRegion, documentPosition, 0, matchString);
+				addTagCloseProposals(contentAssistRequest);
+			}
+			else if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
+				contentAssistRequest = computeAttributeValueProposals(documentPosition, matchString, completionRegion, treeNode, xmlnode);
+			}
+			else if ((regionType == DOMRegionContext.XML_TAG_CLOSE) || (regionType == DOMRegionContext.XML_EMPTY_TAG_CLOSE) || (regionType.equals(DOMJSPRegionContextsPrivateCopy.JSP_DIRECTIVE_CLOSE))) {
+				contentAssistRequest = computeTagCloseProposals(documentPosition, matchString, completionRegion, treeNode, xmlnode);
+			}
+			else if (regionType == DOMRegionContext.XML_END_TAG_OPEN) {
+				contentAssistRequest = computeEndTagOpenProposals(documentPosition, matchString, completionRegion, treeNode, xmlnode);
+			}
+			else if ((regionType == DOMRegionContext.XML_CONTENT) || (regionType == DOMRegionContext.XML_CHAR_REFERENCE) || (regionType == DOMRegionContext.XML_ENTITY_REFERENCE) || (regionType == DOMRegionContext.XML_PE_REFERENCE)) {
+				contentAssistRequest = computeContentProposals(documentPosition, matchString, completionRegion, treeNode, xmlnode);
+			}
+
+			// These ITextRegion types begin DOM Elements as well and although
+			// internally harder to assist,
+			// text insertions directly before them can be made
+			else if ((documentPosition == sdRegion.getStartOffset(completionRegion)) && (regionType.equals(DOMJSPRegionContextsPrivateCopy.JSP_COMMENT_OPEN) || regionType.equals(DOMJSPRegionContextsPrivateCopy.JSP_DECLARATION_OPEN) || regionType.equals(DOMJSPRegionContextsPrivateCopy.JSP_DIRECTIVE_OPEN) || regionType.equals(DOMJSPRegionContextsPrivateCopy.JSP_EXPRESSION_OPEN) || regionType.equals(DOMJSPRegionContextsPrivateCopy.JSP_SCRIPTLET_OPEN) || (regionType == DOMRegionContext.XML_DECLARATION_OPEN) || (regionType == DOMRegionContext.XML_PI_OPEN) || (regionType == DOMRegionContext.XML_COMMENT_OPEN) || (regionType == DOMRegionContext.XML_CDATA_OPEN))) {
+				contentAssistRequest = newContentAssistRequest(treeNode, xmlnode.getParentNode(), sdRegion, completionRegion, documentPosition, 0, matchString);
+				addTagInsertionProposals(contentAssistRequest, getElementPositionForModelQuery(treeNode));
+				addStartDocumentProposals(contentAssistRequest);
+			}
+		}
+		// Not a Document or Element? (odd cases go here for now)
+		else if (isCloseRegion(completionRegion)) {
+			contentAssistRequest = newContentAssistRequest(treeNode, xmlnode.getParentNode(), sdRegion, completionRegion, sdRegion.getStartOffset(completionRegion) + completionRegion.getLength(), 0, matchString);
+			addStartDocumentProposals(contentAssistRequest);
+			if (documentPosition >= sdRegion.getTextEndOffset(completionRegion)) {
+				addTagInsertionProposals(contentAssistRequest, getElementPositionForModelQuery(treeNode) + 1);
+			}
+		}
+		else if ((documentPosition == sdRegion.getStartOffset(completionRegion)) && (regionType.equals(DOMJSPRegionContextsPrivateCopy.JSP_COMMENT_OPEN) || regionType.equals(DOMJSPRegionContextsPrivateCopy.JSP_DECLARATION_OPEN) || regionType.equals(DOMJSPRegionContextsPrivateCopy.JSP_DIRECTIVE_OPEN) || regionType.equals(DOMJSPRegionContextsPrivateCopy.JSP_EXPRESSION_OPEN) || regionType.equals(DOMJSPRegionContextsPrivateCopy.JSP_SCRIPTLET_OPEN) || (regionType == DOMRegionContext.XML_DECLARATION_OPEN) || (regionType == DOMRegionContext.XML_PI_OPEN) || (regionType == DOMRegionContext.XML_COMMENT_OPEN) || (regionType == DOMRegionContext.XML_CDATA_OPEN))) {
+			contentAssistRequest = newContentAssistRequest(treeNode, xmlnode.getParentNode(), sdRegion, completionRegion, documentPosition, 0, matchString);
+			addTagInsertionProposals(contentAssistRequest, getElementPositionForModelQuery(treeNode));
+			addStartDocumentProposals(contentAssistRequest);
+		}
+		return contentAssistRequest;
+	}
+
+	/**
+	 * CONTENT ASSIST STARTS HERE
+	 * 
+	 * Return a list of proposed code completions based on the specified
+	 * location within the document that corresponds to the current cursor
+	 * position within the text-editor control.
+	 * 
+	 * @param textViewer
+	 * @param documentPosition -
+	 *            the cursor location within the document
+	 * 
+	 * an array of ICompletionProposals
+	 */
+	public ICompletionProposal[] computeCompletionProposals(ITextViewer textViewer, int documentPosition) {
+
+		setErrorMessage(null);
+
+		fTextViewer = textViewer;
+
+		IndexedRegion treeNode = ContentAssistUtils.getNodeAt(textViewer, documentPosition);
+
+		Node node = (Node) treeNode;
+		while ((node != null) && (node.getNodeType() == Node.TEXT_NODE) && (node.getParentNode() != null)) {
+			node = node.getParentNode();
+		}
+		IDOMNode xmlnode = (IDOMNode) node;
+
+		ContentAssistRequest contentAssistRequest = null;
+
+		IStructuredDocumentRegion sdRegion = getStructuredDocumentRegion(documentPosition);
+		ITextRegion completionRegion = getCompletionRegion(documentPosition, node);
+
+		String matchString = getMatchString(sdRegion, completionRegion, documentPosition);
+
+		// Handle empty Documents
+		if (completionRegion == null) {
+			if (((treeNode == null) || (((Node) treeNode).getNodeType() == Node.DOCUMENT_NODE)) && (completionRegion == null) && ((xmlnode == null) || (xmlnode.getChildNodes() == null) || (xmlnode.getChildNodes().getLength() == 0))) {
+				IStructuredModel sModel = StructuredModelManager.getModelManager().getExistingModelForRead(textViewer.getDocument());
+				try {
+					if (sModel != null) {
+						IDOMDocument docNode = ((IDOMModel) sModel).getDocument();
+						contentAssistRequest = newContentAssistRequest(docNode, docNode, sdRegion, completionRegion, documentPosition, 0, null);
+						addEmptyDocumentProposals(contentAssistRequest);
+					}
+				}
+				finally {
+					if (sModel != null) {
+						sModel.releaseFromRead();
+					}
+				}
+				if (contentAssistRequest == null) {
+					Logger.logException(new IllegalStateException("problem getting model")); //$NON-NLS-1$
+					return new ICompletionProposal[0];
+				}
+				return contentAssistRequest.getCompletionProposals();
+			}
+			// MASSIVE ERROR CONDITION
+			Logger.logException(new IllegalStateException("completion region was null")); //$NON-NLS-1$
+			setErrorMessage(INTERNALERROR);
+			contentAssistRequest = newContentAssistRequest((Node) treeNode, node.getParentNode(), sdRegion, completionRegion, documentPosition, 0, ""); //$NON-NLS-1$
+			return contentAssistRequest.getCompletionProposals();
+		}
+
+
+		// catch documents where no region can be determined
+		if ((xmlnode.getNodeType() == Node.DOCUMENT_NODE) && ((completionRegion == null) || (xmlnode.getChildNodes() == null) || (xmlnode.getChildNodes().getLength() == 0))) {
+			contentAssistRequest = computeStartDocumentProposals(documentPosition, matchString, completionRegion, (IDOMNode) treeNode, xmlnode);
+			return contentAssistRequest.getCompletionProposals();
+		}
+
+		// compute normal proposals
+		contentAssistRequest = computeCompletionProposals(documentPosition, matchString, completionRegion, (IDOMNode) treeNode, xmlnode);
+		if (contentAssistRequest == null) {
+			contentAssistRequest = newContentAssistRequest((Node) treeNode, node.getParentNode(), sdRegion, completionRegion, documentPosition, 0, ""); //$NON-NLS-1$
+			if (Debug.displayWarnings) {
+				System.out.println(UNKNOWN_CONTEXT + " " + completionRegion.getType() + "@" + documentPosition); //$NON-NLS-2$//$NON-NLS-1$
+			}
+			setErrorMessage(UNKNOWN_CONTEXT);
+		}
+
+		/* 
+		 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=123892
+		 * Only set this error message if nothing else was already set 
+		 **/
+		if (contentAssistRequest.getProposals().size() == 0 && getErrorMessage() == null) {
+			setErrorMessage(UNKNOWN_CONTEXT);
+		}
+
+		return contentAssistRequest.getCompletionProposals();
+	}
+
+	protected ContentAssistRequest computeContentProposals(int documentPosition, String matchString, ITextRegion completionRegion, IDOMNode nodeAtOffset, IDOMNode node) {
+		ContentAssistRequest contentAssistRequest = null;
+
+		// setup to add children at the content node's position
+		contentAssistRequest = newContentAssistRequest(nodeAtOffset, node, getStructuredDocumentRegion(documentPosition), completionRegion, documentPosition, 0, matchString);
+		if ((node != null) && (node.getNodeType() == Node.DOCUMENT_NODE) && (((Document) node).getDoctype() == null)) {
+			addStartDocumentProposals(contentAssistRequest);
+		}
+		addTagInsertionProposals(contentAssistRequest, getElementPositionForModelQuery(nodeAtOffset));
+		if (node.getNodeType() != Node.DOCUMENT_NODE) {
+			addEndTagProposals(contentAssistRequest);
+		}
+		// entities?
+		addEntityProposals(contentAssistRequest, documentPosition, completionRegion, node);
+		// addEntityProposals(contentAssistRequest);
+		return contentAssistRequest;
+	}
+
+	/**
+	 * Returns information about possible contexts based on the specified
+	 * location within the document that corresponds to the current cursor
+	 * position within the text viewer.
+	 * 
+	 * @param viewer
+	 *            the viewer whose document is used to compute the possible
+	 *            contexts an array of context information objects or
+	 *            <code>null</code> if no context could be found
+	 */
+	public IContextInformation[] computeContextInformation(ITextViewer viewer, int documentOffset) {
+		return new IContextInformation[0];
+	}
+
+	protected ContentAssistRequest computeEndTagOpenProposals(int documentPosition, String matchString, ITextRegion completionRegion, IDOMNode nodeAtOffset, IDOMNode node) {
+		ContentAssistRequest contentAssistRequest = null;
+		IStructuredDocumentRegion sdRegion = getStructuredDocumentRegion(documentPosition);
+		int completionRegionStart = sdRegion.getStartOffset(completionRegion);
+		int completionRegionLength = completionRegion.getLength();
+		IStructuredDocumentRegion sdRegionAtCompletionOffset = node.getStructuredDocument().getRegionAtCharacterOffset(completionRegionStart + completionRegionLength);
+		ITextRegion regionAtEndOfCompletion = sdRegionAtCompletionOffset.getRegionAtCharacterOffset(completionRegionStart + completionRegionLength);
+
+		if ((documentPosition != completionRegionStart) && (regionAtEndOfCompletion != null) && (regionAtEndOfCompletion.getType() == DOMRegionContext.XML_TAG_NAME)) {
+			ITextRegion nameRegion = regionAtEndOfCompletion;
+			contentAssistRequest = newContentAssistRequest(nodeAtOffset, nodeAtOffset.getParentNode(), sdRegion, completionRegion, sdRegion.getStartOffset(nameRegion), nameRegion.getTextLength(), matchString);
+		}
+		else {
+			if (nodeAtOffset.getFirstStructuredDocumentRegion() == sdRegion) {
+				// abnormal case, this unmatched end tag will be a sibling
+				contentAssistRequest = newContentAssistRequest(nodeAtOffset, nodeAtOffset.getParentNode(), sdRegion, completionRegion, documentPosition, 0, matchString);
+			}
+			else {
+				// normal case, this end tag is the parent
+				contentAssistRequest = newContentAssistRequest(nodeAtOffset, nodeAtOffset, sdRegion, completionRegion, documentPosition, 0, matchString);
+			}
+		}
+		// if (documentPosition >= sdRegion.getStartOffset(completionRegion) +
+		// completionRegion.getTextLength())
+		addEndTagProposals(contentAssistRequest);
+		// else
+		if (completionRegionStart == documentPosition) {
+			// positioned at start of end tag
+			addTagInsertionProposals(contentAssistRequest, node.getChildNodes().getLength());
+		}
+		return contentAssistRequest;
+	}
+
+	/**
+	 * return all possible EntityReferenceProposals (according to current
+	 * position in doc)
+	 */
+	protected ICompletionProposal[] computeEntityReferenceProposals(int documentPosition, ITextRegion completionRegion, IDOMNode treeNode) {
+		// only handle XML content for now
+		Vector proposals = new Vector(); // ICompletionProposals
+		IStructuredDocumentRegion sdRegion = getStructuredDocumentRegion(documentPosition);
+		if ((completionRegion != null) && (completionRegion.getType() == DOMRegionContext.XML_CONTENT)) {
+			int nodeOffset = documentPosition - sdRegion.getStartOffset(completionRegion);
+			String regionText = sdRegion.getFullText(completionRegion);
+
+			// if directly to the right of a &, region will be null, need to
+			// move to
+			// the previous region...there might be a better way to do this
+			if ((regionText != null) && regionText.trim().equals("") && (documentPosition > 0)) { //$NON-NLS-1$
+				IStructuredDocumentRegion prev = treeNode.getStructuredDocument().getRegionAtCharacterOffset(documentPosition - 1);
+				if ((prev != null) && prev.getText().equals("&")) { //$NON-NLS-1$
+					// https://bugs.eclipse.org/bugs/show_bug.cgi?id=206680
+					// examine previous region
+					sdRegion = prev;
+					completionRegion = prev.getLastRegion();
+					regionText = prev.getFullText();
+					nodeOffset = 1;
+				}
+			}
+
+			// string must start w/ &
+			if ((regionText != null) && regionText.startsWith("&")) { //$NON-NLS-1$						 		
+				String key = (nodeOffset > 0) ? regionText.substring(1, nodeOffset) : ""; //$NON-NLS-1$
+
+				// get entity proposals, passing in the appropriate start
+				// string
+				ModelQuery mq = ModelQueryUtil.getModelQuery(((Node) treeNode).getOwnerDocument());
+				if (mq != null) {
+					CMDocument xmlDoc = mq.getCorrespondingCMDocument(treeNode);
+					CMNamedNodeMap cmmap = null;
+					Properties entities = null;
+					if (xmlDoc != null) {
+						cmmap = xmlDoc.getEntities();
+					}
+					if (cmmap != null) {
+						entities = mapToProperties(cmmap);
+					}
+					else // 224787 in absence of content model, just use
+					// minimal 5 entities
+					{
+						entities = new Properties();
+						entities.put("quot", "\""); //$NON-NLS-1$ //$NON-NLS-2$
+						entities.put("apos", "'"); //$NON-NLS-1$ //$NON-NLS-2$
+						entities.put("amp", "&"); //$NON-NLS-1$ //$NON-NLS-2$
+						entities.put("lt", "<"); //$NON-NLS-1$ //$NON-NLS-2$
+						entities.put("gt", ">"); //$NON-NLS-1$ //$NON-NLS-2$	
+						entities.put("nbsp", " "); //$NON-NLS-1$ //$NON-NLS-2$									
+					}
+					addEntityProposals(proposals, entities, key, nodeOffset, sdRegion, completionRegion);
+				}
+			}
+		}
+		return (ICompletionProposal[]) ((proposals.size() > 0) ? proposals.toArray(new ICompletionProposal[proposals.size()]) : null);
+	}
+
+	protected ContentAssistRequest computeEqualsProposals(int documentPosition, String matchString, ITextRegion completionRegion, IDOMNode nodeAtOffset, IDOMNode node) {
+		ContentAssistRequest contentAssistRequest = null;
+		IStructuredDocumentRegion sdRegion = getStructuredDocumentRegion(documentPosition);
+		ITextRegion valueRegion = node.getStartStructuredDocumentRegion().getRegionAtCharacterOffset(sdRegion.getStartOffset(completionRegion) + completionRegion.getLength());
+		if ((valueRegion != null) && (valueRegion.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) && (sdRegion.getStartOffset(valueRegion) <= documentPosition)) {
+			// replace the adjacent attribute value
+			contentAssistRequest = newContentAssistRequest(nodeAtOffset, node, sdRegion, valueRegion, sdRegion.getStartOffset(valueRegion), valueRegion.getTextLength(), matchString);
+		}
+		else {
+			// append an attribute value after the '='
+			contentAssistRequest = newContentAssistRequest(nodeAtOffset, node, sdRegion, completionRegion, documentPosition, 0, matchString);
+		}
+		addAttributeValueProposals(contentAssistRequest);
+		return contentAssistRequest;
+	}
+
+	protected ContentAssistRequest computeStartDocumentProposals(int documentPosition, String matchString, ITextRegion completionRegion, IDOMNode nodeAtOffset, IDOMNode node) {
+		// setup for a non-empty document, but one that hasn't been formally
+		// started
+		ContentAssistRequest contentAssistRequest = null;
+		contentAssistRequest = newContentAssistRequest(nodeAtOffset, node, getStructuredDocumentRegion(documentPosition), completionRegion, documentPosition, 0, matchString);
+		addStartDocumentProposals(contentAssistRequest);
+		return contentAssistRequest;
+	}
+
+	protected ContentAssistRequest computeTagCloseProposals(int documentPosition, String matchString, ITextRegion completionRegion, IDOMNode nodeAtOffset, IDOMNode node) {
+		ContentAssistRequest contentAssistRequest = null;
+		IStructuredDocumentRegion sdRegion = getStructuredDocumentRegion(documentPosition);
+
+		if ((node.getNodeType() == Node.DOCUMENT_NODE) || (documentPosition >= sdRegion.getEndOffset())) {
+			// this is a content request as the documentPosition is AFTER the
+			// end of the closing region
+			if ((node == nodeAtOffset) && (node.getParentNode() != null)) {
+				node = (IDOMNode) node.getParentNode();
+			}
+			contentAssistRequest = newContentAssistRequest(nodeAtOffset, node, sdRegion, completionRegion, documentPosition, 0, matchString);
+			addTagInsertionProposals(contentAssistRequest, getElementPositionForModelQuery(nodeAtOffset));
+			if ((node.getNodeType() != Node.DOCUMENT_NODE) && (node.getEndStructuredDocumentRegion() == null)) {
+				addEndTagProposals(contentAssistRequest);
+			}
+		}
+		else {
+			// at the start of the tag's close or within it
+			ITextRegion closeRegion = sdRegion.getLastRegion();
+			boolean insideTag = !sdRegion.isEnded() || (documentPosition <= sdRegion.getStartOffset(closeRegion));
+			if (insideTag) {
+				// this is a request for completions within a tag
+				contentAssistRequest = newContentAssistRequest(nodeAtOffset, node, sdRegion, completionRegion, documentPosition, 0, matchString);
+				if ((node.getNodeType() != Node.DOCUMENT_NODE) && (node.getEndStructuredDocumentRegion() != null)) {
+					addTagCloseProposals(contentAssistRequest);
+				}
+				if (sdRegion == nodeAtOffset.getFirstStructuredDocumentRegion()) {
+					contentAssistRequest.setReplacementBeginPosition(documentPosition);
+					contentAssistRequest.setReplacementLength(0);
+					addAttributeNameProposals(contentAssistRequest);
+				}
+			}
+		}
+		return contentAssistRequest;
+	}
+
+	protected ContentAssistRequest computeTagNameProposals(int documentPosition, String matchString, ITextRegion completionRegion, IDOMNode nodeAtOffset, IDOMNode node) {
+		ContentAssistRequest contentAssistRequest = null;
+		IStructuredDocumentRegion sdRegion = getStructuredDocumentRegion(documentPosition);
+
+		if (sdRegion != nodeAtOffset.getFirstStructuredDocumentRegion()) {
+			// completing the *first* tag in "<tagname1 |<tagname2"
+			IDOMNode actualNode = (IDOMNode) node.getModel().getIndexedRegion(sdRegion.getStartOffset(completionRegion));
+			if (actualNode != null) {
+				if (actualNode.getFirstStructuredDocumentRegion() == sdRegion) {
+					// start tag
+					if (documentPosition > sdRegion.getStartOffset(completionRegion) + completionRegion.getLength()) {
+						// it's attributes
+						contentAssistRequest = newContentAssistRequest(actualNode, actualNode, sdRegion, completionRegion, documentPosition - matchString.length(), matchString.length(), matchString);
+						if (node.getStructuredDocument().getRegionAtCharacterOffset(sdRegion.getStartOffset(completionRegion) - 1).getRegionAtCharacterOffset(sdRegion.getStartOffset(completionRegion) - 1).getType() == DOMRegionContext.XML_TAG_OPEN) {
+							addAttributeNameProposals(contentAssistRequest);
+						}
+						addTagCloseProposals(contentAssistRequest);
+					}
+					else {
+						// it's name
+						contentAssistRequest = newContentAssistRequest(actualNode, actualNode.getParentNode(), sdRegion, completionRegion, documentPosition - matchString.length(), matchString.length(), matchString);
+						addTagNameProposals(contentAssistRequest, getElementPositionForModelQuery(actualNode));
+					}
+				}
+				else {
+					if (documentPosition >= sdRegion.getStartOffset(completionRegion) + completionRegion.getLength()) {
+						// insert name
+						contentAssistRequest = newContentAssistRequest(actualNode, actualNode.getParentNode(), sdRegion, completionRegion, documentPosition, 0, matchString);
+					}
+					else {
+						// replace name
+						contentAssistRequest = newContentAssistRequest(actualNode, actualNode.getParentNode(), sdRegion, completionRegion, sdRegion.getStartOffset(completionRegion), completionRegion.getTextLength(), matchString);
+					}
+					addEndTagNameProposals(contentAssistRequest);
+				}
+			}
+		}
+		else {
+			if (documentPosition > sdRegion.getStartOffset(completionRegion) + completionRegion.getTextLength()) {
+				// unclosed tag with only a name; should prompt for attributes
+				// and a close instead
+				contentAssistRequest = newContentAssistRequest(nodeAtOffset, node, sdRegion, completionRegion, documentPosition - matchString.length(), matchString.length(), matchString);
+				addAttributeNameProposals(contentAssistRequest);
+				addTagCloseProposals(contentAssistRequest);
+			}
+			else {
+				if (sdRegion.getRegions().get(0).getType() != DOMRegionContext.XML_END_TAG_OPEN) {
+					int replaceLength = documentPosition - sdRegion.getStartOffset(completionRegion);
+					contentAssistRequest = newContentAssistRequest(node, node.getParentNode(), sdRegion, completionRegion, sdRegion.getStartOffset(completionRegion), replaceLength, matchString);
+					addTagNameProposals(contentAssistRequest, getElementPositionForModelQuery(nodeAtOffset));
+				}
+				else {
+					IDOMNode actualNode = (IDOMNode) node.getModel().getIndexedRegion(documentPosition);
+					if (actualNode != null) {
+						if (documentPosition >= sdRegion.getStartOffset(completionRegion) + completionRegion.getTextLength()) {
+							contentAssistRequest = newContentAssistRequest(actualNode, actualNode.getParentNode(), sdRegion, completionRegion, documentPosition, 0, matchString);
+						}
+						else {
+							contentAssistRequest = newContentAssistRequest(actualNode, actualNode.getParentNode(), sdRegion, completionRegion, sdRegion.getStartOffset(completionRegion), completionRegion.getTextLength(), matchString);
+						}
+						addEndTagNameProposals(contentAssistRequest);
+					}
+				}
+			}
+		}
+		return contentAssistRequest;
+	}
+
+	protected ContentAssistRequest computeTagOpenProposals(int documentPosition, String matchString, ITextRegion completionRegion, IDOMNode nodeAtOffset, IDOMNode node) {
+		ContentAssistRequest contentAssistRequest = null;
+		IStructuredDocumentRegion sdRegion = getStructuredDocumentRegion(documentPosition);
+		if (sdRegion != nodeAtOffset.getFirstStructuredDocumentRegion() || sdRegion.getPrevious() != null && sdRegion.getPrevious().getLastRegion().getType() == DOMRegionContext.XML_TAG_OPEN) {
+			// completing the *first* XML_TAG_OPEN in "<<tagname"
+			IDOMNode actualNode = (IDOMNode) node.getModel().getIndexedRegion(sdRegion.getStartOffset(completionRegion));
+			if (actualNode != null) {
+				if(sdRegion.getFirstRegion().getType() == DOMRegionContext.XML_END_TAG_OPEN) {
+					contentAssistRequest = newContentAssistRequest(actualNode, actualNode, sdRegion, completionRegion, documentPosition, 0, matchString);
+					if(actualNode.hasChildNodes())
+						addTagNameProposals(contentAssistRequest, getElementPositionForModelQuery(actualNode.getLastChild()));
+					else
+						addTagNameProposals(contentAssistRequest, 0);
+				}
+				else {
+					contentAssistRequest = newContentAssistRequest(actualNode, actualNode.getParentNode(), sdRegion, completionRegion, documentPosition, 0, matchString);
+					addTagNameProposals(contentAssistRequest, getElementPositionForModelQuery(actualNode));
+				}
+				addEndTagProposals(contentAssistRequest); // (pa) 220850
+			}
+		}
+		else {
+			if (documentPosition == sdRegion.getStartOffset(completionRegion)) {
+				if (node.getNodeType() == Node.ELEMENT_NODE) {
+					// at the start of an existing tag, right before the '<'
+					contentAssistRequest = newContentAssistRequest(nodeAtOffset, node.getParentNode(), sdRegion, completionRegion, documentPosition, 0, matchString);
+					addTagInsertionProposals(contentAssistRequest, getElementPositionForModelQuery(nodeAtOffset));
+					addEndTagProposals(contentAssistRequest);
+				}
+				else if (node.getNodeType() == Node.DOCUMENT_NODE) {
+					// at the opening of the VERY first tag with a '<'
+					contentAssistRequest = newContentAssistRequest(nodeAtOffset, node.getParentNode(), sdRegion, completionRegion, sdRegion.getStartOffset(completionRegion), completionRegion.getTextLength(), matchString);
+					addStartDocumentProposals(contentAssistRequest);
+				}
+			}
+			else {
+				// within the white space
+				ITextRegion name = getNameRegion(node.getStartStructuredDocumentRegion());
+				// (pa) ITextRegion refactor
+				// if (name != null && name.containsOffset(documentPosition))
+				// {
+				if ((name != null) && ((sdRegion.getStartOffset(name) <= documentPosition) && (sdRegion.getEndOffset(name) >= documentPosition)) && (sdRegion.getLastRegion().getType() == DOMRegionContext.XML_TAG_CLOSE || sdRegion.getLastRegion().getType() == DOMRegionContext.XML_EMPTY_TAG_CLOSE)){ 
+					// replace the existing name
+					contentAssistRequest = newContentAssistRequest(node, node.getParentNode(), sdRegion, completionRegion, sdRegion.getStartOffset(name), name.getTextLength(), matchString);
+				}
+				else {
+					// insert a valid new name, or possibly an end tag
+					contentAssistRequest = newContentAssistRequest(nodeAtOffset, ((Node) nodeAtOffset).getParentNode(), sdRegion, completionRegion, documentPosition, 0, matchString);
+					addEndTagProposals(contentAssistRequest);
+					contentAssistRequest.setReplacementBeginPosition(documentPosition);
+					contentAssistRequest.setReplacementLength(0);
+				}
+				addTagNameProposals(contentAssistRequest, getElementPositionForModelQuery(nodeAtOffset));
+			}
+		}
+		return contentAssistRequest;
+	}
+
+	/**
+	 * Retreives cmnode's documentation to display in the completion
+	 * proposal's additional info. If no documentation exists for cmnode, try
+	 * displaying parentOrOwner's documentation
+	 * 
+	 * String any documentation information to display for cmnode.
+	 * <code>null</code> if there is nothing to display.
+	 */
+	protected String getAdditionalInfo(CMNode parentOrOwner, CMNode cmnode) {
+		String addlInfo = null;
+
+		if (cmnode == null) {
+			if (Debug.displayWarnings) {
+				new IllegalArgumentException("Null declaration!").printStackTrace(); //$NON-NLS-1$
+			}
+			return null;
+		}
+
+		addlInfo = getInfoProvider().getInfo(cmnode);
+		if ((addlInfo == null) && (parentOrOwner != null)) {
+			addlInfo = getInfoProvider().getInfo(parentOrOwner);
+		}
+		return addlInfo;
+	}
+
+	// returns a list of ModelQueryActions
+	protected List getAvailableChildrenAtIndex(Element parent, int index, int validityChecking) {
+		List list = new ArrayList();
+		CMElementDeclaration parentDecl = getCMElementDeclaration(parent);
+		if (parentDecl != null) {
+			ModelQuery modelQuery = ModelQueryUtil.getModelQuery(parent.getOwnerDocument());
+			// taken from ActionManagers
+			// int editMode = modelQuery.getEditMode();
+			int editMode = ModelQuery.EDIT_MODE_UNCONSTRAINED;
+			int ic = (editMode == ModelQuery.EDIT_MODE_CONSTRAINED_STRICT) ? ModelQuery.INCLUDE_CHILD_NODES | ModelQuery.INCLUDE_SEQUENCE_GROUPS : ModelQuery.INCLUDE_CHILD_NODES;
+			modelQuery.getInsertActions(parent, parentDecl, index, ic, validityChecking, list);
+		}
+		return list;
+	}
+
+	// returns a list of CMElementDeclarations
+	protected List getAvailableRootChildren(Document document, int childIndex) {
+		List list = null;
+
+		// extract the valid 'root' node name from the DocumentType Node
+		DocumentType docType = document.getDoctype();
+		String rootName = null;
+		if (docType != null) {
+			rootName = docType.getNodeName();
+		}
+		if (rootName == null) {
+			return new ArrayList(0);
+		}
+
+		for (Node child = document.getFirstChild(); child != null; child = child.getNextSibling()) {
+			// make sure the "root" Element isn't already present
+			// is it required to be an Element?
+			if ((child.getNodeType() == Node.ELEMENT_NODE) && stringsEqual(child.getNodeName(), rootName)) {
+				// if the node is missing either the start or end tag, don't
+				// count it as present
+				if ((child instanceof IDOMNode) && ((((IDOMNode) child).getStartStructuredDocumentRegion() == null) || (((IDOMNode) child).getEndStructuredDocumentRegion() == null))) {
+					continue;
+				}
+				if (Debug.displayInfo) {
+					System.out.println(rootName + " already present!"); //$NON-NLS-1$
+				}
+				setErrorMessage(NLS.bind(XMLUIMessages.The_document_element__, (new Object[]{rootName})));
+				return new ArrayList(0);
+			}
+		}
+
+		list = new ArrayList(1);
+		ModelQuery modelQuery = ModelQueryUtil.getModelQuery(document);
+		if (modelQuery != null) {
+			CMDocument cmdoc = modelQuery.getCorrespondingCMDocument(document);
+			if (cmdoc != null) {
+				if (rootName != null) {
+					CMElementDeclaration rootDecl = (CMElementDeclaration) cmdoc.getElements().getNamedItem(rootName);
+					if (rootDecl != null) {
+						list.add(rootDecl);
+					}
+					else {
+						// supply the given document name anyway, even if it
+						// is an error
+						list.add(new SimpleCMElementDeclaration(rootName));
+						if (Debug.displayInfo || Debug.displayWarnings) {
+							System.out.println("No definition found for " + rootName + " in " + docType.getPublicId() + "/" + docType.getSystemId()); //$NON-NLS-3$//$NON-NLS-2$//$NON-NLS-1$
+						}
+						String location = "" + (docType.getPublicId() != null ? docType.getPublicId() + "/" : "") + (docType.getSystemId() != null ? docType.getSystemId() : ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+						//$NON-NLS-4$//$NON-NLS-3$//$NON-NLS-2$//$NON-NLS-1$
+						//$NON-NLS-4$//$NON-NLS-3$//$NON-NLS-2$//$NON-NLS-1$
+						if (location.length() > 0) {
+							setErrorMessage(NLS.bind(XMLUIMessages.No_definition_for_in, (new Object[]{rootName, location})));
+						}
+						else {
+							setErrorMessage(NLS.bind(XMLUIMessages.No_definition_for, (new Object[]{rootName})));
+						}
+					}
+				}
+			}
+			else {
+				if (Debug.displayInfo || Debug.displayWarnings) {
+					System.out.println("No content model found."); //$NON-NLS-1$
+				}
+				//$NON-NLS-1$
+				//$NON-NLS-1$
+				String location = "" + (docType.getPublicId() != null ? docType.getPublicId() + "/" : "") + (docType.getSystemId() != null ? docType.getSystemId() : ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+				//$NON-NLS-4$//$NON-NLS-3$//$NON-NLS-2$//$NON-NLS-1$
+				//$NON-NLS-4$//$NON-NLS-3$//$NON-NLS-2$//$NON-NLS-1$
+				if (location.length() > 0) {
+					setErrorMessage(NLS.bind(XMLUIMessages.No_content_model_for, (new Object[]{location})));
+				}
+				else {
+					setErrorMessage(XMLUIMessages.No_content_model_found_UI_);
+				}
+			}
+		}
+
+		return list;
+	}
+
+	protected CMElementDeclaration getCMElementDeclaration(Node node) {
+		CMElementDeclaration result = null;
+		if (node.getNodeType() == Node.ELEMENT_NODE) {
+			ModelQuery modelQuery = ModelQueryUtil.getModelQuery(node.getOwnerDocument());
+			if (modelQuery != null) {
+				result = modelQuery.getCMElementDeclaration((Element) node);
+			}
+		}
+		return result;
+	}
+
+	/**
+	 * Returns the characters which when entered by the user should
+	 * automatically trigger the presentation of possible completions.
+	 * 
+	 * the auto activation characters for completion proposal or
+	 * <code>null</code> if no auto activation is desired
+	 */
+	public char[] getCompletionProposalAutoActivationCharacters() {
+		return completionProposalAutoActivationCharacters;
+	}
+
+	protected ITextRegion getCompletionRegion(int offset, IStructuredDocumentRegion sdRegion) {
+		ITextRegion region = sdRegion.getRegionAtCharacterOffset(offset);
+		if (region == null) {
+			return null;
+		}
+
+		if (sdRegion.getStartOffset(region) == offset) {
+			// The offset is at the beginning of the region
+			if ((sdRegion.getStartOffset(region) == sdRegion.getStartOffset()) && (sdRegion.getPrevious() != null) && (!sdRegion.getPrevious().isEnded())) {
+				// Is the region also the start of the node? If so, the
+				// previous IStructuredDocumentRegion is
+				// where to look for a useful region.
+				region = sdRegion.getPrevious().getRegionAtCharacterOffset(offset - 1);
+			}
+			else {
+				// Is there no separating whitespace from the previous region?
+				// If not,
+				// then that region is the important one
+				ITextRegion previousRegion = sdRegion.getRegionAtCharacterOffset(offset - 1);
+				if ((previousRegion != null) && (previousRegion != region) && (previousRegion.getTextLength() == previousRegion.getLength())) {
+					region = previousRegion;
+				}
+			}
+		}
+		else {
+			// The offset is NOT at the beginning of the region
+			if (offset > sdRegion.getStartOffset(region) + region.getTextLength()) {
+				// Is the offset within the whitespace after the text in this
+				// region?
+				// If so, use the next region
+				ITextRegion nextRegion = sdRegion.getRegionAtCharacterOffset(sdRegion.getStartOffset(region) + region.getLength());
+				if (nextRegion != null) {
+					region = nextRegion;
+				}
+			}
+			else {
+				// Is the offset within the important text for this region?
+				// If so, then we've already got the right one.
+			}
+		}
+
+		// valid WHITE_SPACE region handler (#179924)
+		if ((region != null) && (region.getType() == DOMRegionContext.WHITE_SPACE)) {
+			ITextRegion previousRegion = sdRegion.getRegionAtCharacterOffset(sdRegion.getStartOffset(region) - 1);
+			if (previousRegion != null) {
+				region = previousRegion;
+			}
+		}
+
+		return region;
+	}
+
+	/**
+	 * Return the region whose content's require completion. This is something
+	 * of a misnomer as sometimes the user wants to be prompted for contents
+	 * of a non-existant ITextRegion, such as for enumerated attribute values
+	 * following an '=' sign.
+	 */
+	protected ITextRegion getCompletionRegion(int documentPosition, Node domnode) {
+		if (domnode == null) {
+			return null;
+		}
+
+		ITextRegion region = null;
+		int offset = documentPosition;
+		IStructuredDocumentRegion flatNode = null;
+		IDOMNode node = (IDOMNode) domnode;
+
+		if (node.getNodeType() == Node.DOCUMENT_NODE) {
+			if (node.getStructuredDocument().getLength() == 0) {
+				return null;
+			}
+			ITextRegion result = node.getStructuredDocument().getRegionAtCharacterOffset(offset).getRegionAtCharacterOffset(offset);
+			while (result == null) {
+				offset--;
+				result = node.getStructuredDocument().getRegionAtCharacterOffset(offset).getRegionAtCharacterOffset(offset);
+			}
+			return result;
+		}
+
+		IStructuredDocumentRegion startTag = node.getStartStructuredDocumentRegion();
+		IStructuredDocumentRegion endTag = node.getEndStructuredDocumentRegion();
+
+		// Determine if the offset is within the start
+		// IStructuredDocumentRegion, end IStructuredDocumentRegion, or
+		// somewhere within the Node's XML content.
+		if ((startTag != null) && (startTag.getStartOffset() <= offset) && (offset < startTag.getStartOffset() + startTag.getLength())) {
+			flatNode = startTag;
+		}
+		else if ((endTag != null) && (endTag.getStartOffset() <= offset) && (offset < endTag.getStartOffset() + endTag.getLength())) {
+			flatNode = endTag;
+		}
+
+		if (flatNode != null) {
+			// the offset is definitely within the start or end tag, continue
+			// on and find the region
+			region = getCompletionRegion(offset, flatNode);
+		}
+		else {
+			// the docPosition is neither within the start nor the end, so it
+			// must be content
+			flatNode = node.getStructuredDocument().getRegionAtCharacterOffset(offset);
+			// (pa) ITextRegion refactor
+			// if (flatNode.contains(documentPosition)) {
+			if ((flatNode.getStartOffset() <= documentPosition) && (flatNode.getEndOffset() >= documentPosition)) {
+				// we're interesting in completing/extending the previous
+				// IStructuredDocumentRegion if the current
+				// IStructuredDocumentRegion isn't plain content or if it's
+				// preceded by an orphan '<'
+				if ((offset == flatNode.getStartOffset()) && (flatNode.getPrevious() != null) && (((flatNode.getRegionAtCharacterOffset(documentPosition) != null) && (flatNode.getRegionAtCharacterOffset(documentPosition).getType() != DOMRegionContext.XML_CONTENT)) || (flatNode.getPrevious().getLastRegion().getType() == DOMRegionContext.XML_TAG_OPEN) || (flatNode.getPrevious().getLastRegion().getType() == DOMRegionContext.XML_END_TAG_OPEN))) {
+					// Is the region also the start of the node? If so, the
+					// previous IStructuredDocumentRegion is
+					// where to look for a useful region.
+					region = flatNode.getPrevious().getLastRegion();
+				}
+				else if (flatNode.getEndOffset() == documentPosition) {
+					region = flatNode.getLastRegion();
+				}
+				else {
+					region = flatNode.getFirstRegion();
+				}
+			}
+			else {
+				// catch end of document positions where the docPosition isn't
+				// in a IStructuredDocumentRegion
+				region = flatNode.getLastRegion();
+			}
+		}
+
+		return region;
+	}
+
+	/**
+	 * Provided by default. Subclasses may override with their own
+	 * implementations.
+	 * 
+	 * @see AbstractContentAssistProcessor#getContentGenerator()
+	 */
+	public XMLContentModelGenerator getContentGenerator() {
+		if (fGenerator == null) {
+			fGenerator = new XMLContentModelGenerator();
+		}
+		return fGenerator;
+	}
+
+	/**
+	 * Returns the characters which when entered by the user should
+	 * automatically trigger the presentation of context information.
+	 * 
+	 * the auto activation characters for presenting context information or
+	 * <code>null</code> if no auto activation is desired
+	 */
+	public char[] getContextInformationAutoActivationCharacters() {
+		return contextInformationAutoActivationCharacters;
+	}
+
+	/**
+	 * Returns a validator used to determine when displayed context
+	 * information should be dismissed. May only return <code>null</code> if
+	 * the processor is incapable of computing context information.
+	 * 
+	 * a context information validator, or <code>null</code> if the
+	 * processor is incapable of computing context information
+	 */
+	public IContextInformationValidator getContextInformationValidator() {
+		if (fContextInformationPresenter == null) {
+			fContextInformationPresenter = new AttributeContextInformationPresenter();
+		}
+		return fContextInformationPresenter;
+	}
+
+	protected int getElementPosition(Node child) {
+		Node parent = child.getParentNode();
+		if (parent == null) {
+			return 0;
+		}
+
+		NodeList children = parent.getChildNodes();
+		if (children == null) {
+			return 0;
+		}
+		int count = 0;
+
+		for (int i = 0; i < children.getLength(); i++) {
+			if (children.item(i) == child) {
+				return count;
+			}
+			else {
+				// if (children.item(i).getNodeType() == Node.ELEMENT_NODE)
+				count++;
+			}
+		}
+		return 0;
+	}
+
+	private int getElementPositionForModelQuery(Node child) {
+		return getElementPosition(child);
+		// return -1;
+	}
+
+	/**
+	 * Return the reason why computeProposals was not able to find any
+	 * completions.
+	 * 
+	 * an error message or null if no error occurred
+	 */
+	public String getErrorMessage() {
+		return fErrorMessage;
+	}
+
+	/**
+	 * @param iResource
+	 */
+	// public void initialize(IResource iResource) {
+	// this.resource = iResource;
+	// }
+	/**
+	 * Gets the infoProvider.
+	 * 
+	 * fInfoProvider and if fInfoProvider was <code>null</code> create a new
+	 * instance
+	 */
+	public MarkupTagInfoProvider getInfoProvider() {
+		if (fInfoProvider == null) {
+			fInfoProvider = new MarkupTagInfoProvider();
+		}
+		return fInfoProvider;
+	}
+
+	protected String getMatchString(IStructuredDocumentRegion parent, ITextRegion aRegion, int offset) {
+		if ((aRegion == null) || isCloseRegion(aRegion)) {
+			return ""; //$NON-NLS-1$
+		}
+		String matchString = null;
+		String regionType = aRegion.getType();
+		if ((regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_EQUALS) || (regionType == DOMRegionContext.XML_TAG_OPEN) || (offset > parent.getStartOffset(aRegion) + aRegion.getTextLength())) {
+			matchString = ""; //$NON-NLS-1$
+		}
+		else if (regionType == DOMRegionContext.XML_CONTENT) {
+			matchString = ""; //$NON-NLS-1$
+		}
+		else {
+			if ((parent.getText(aRegion).length() > 0) && (parent.getStartOffset(aRegion) < offset)) {
+				matchString = parent.getText(aRegion).substring(0, offset - parent.getStartOffset(aRegion));
+			}
+			else {
+				matchString = ""; //$NON-NLS-1$
+			}
+		}
+		return matchString;
+	}
+
+	protected ITextRegion getNameRegion(IStructuredDocumentRegion flatNode) {
+		if (flatNode == null) {
+			return null;
+		}
+		Iterator regionList = flatNode.getRegions().iterator();
+		while (regionList.hasNext()) {
+			ITextRegion region = (ITextRegion) regionList.next();
+			if (isNameRegion(region)) {
+				return region;
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * Retrieves all of the possible valid values for this attribute
+	 * declaration
+	 */
+	protected List getPossibleDataTypeValues(Node node, CMAttributeDeclaration ad) {
+		List list = null;
+		if (node.getNodeType() == Node.ELEMENT_NODE) {
+			Element element = (Element) node;
+			String[] dataTypeValues = null;
+			// The ModelQuery may not be available if the corresponding
+			// adapter
+			// is absent
+			ModelQuery modelQuery = ModelQueryUtil.getModelQuery(element.getOwnerDocument());
+			if (modelQuery != null) {
+				dataTypeValues = modelQuery.getPossibleDataTypeValues(element, ad);
+			}
+			else {
+				if (ad.getAttrType() != null) {
+					dataTypeValues = ad.getAttrType().getEnumeratedValues();
+				}
+			}
+			if (dataTypeValues != null) {
+				list = new ArrayList(dataTypeValues.length);
+				for (int i = 0; i < dataTypeValues.length; i++) {
+					list.add(dataTypeValues[i]);
+				}
+			}
+		}
+		if (list == null) {
+			list = new ArrayList(0);
+		}
+		return list;
+	}
+
+	protected String getRequiredName(Node parentOrOwner, CMNode cmnode) {
+		if ((cmnode == null) || (parentOrOwner == null)) {
+			if (Debug.displayWarnings) {
+				new IllegalArgumentException("Null declaration!").printStackTrace(); //$NON-NLS-1$
+			}
+			return ""; //$NON-NLS-1$
+		}
+		return getContentGenerator().getRequiredName(parentOrOwner, cmnode);
+	}
+
+	protected String getRequiredText(Node parentOrOwner, CMAttributeDeclaration attrDecl) {
+		if (attrDecl == null) {
+			if (Debug.displayWarnings) {
+				new IllegalArgumentException("Null attribute declaration!").printStackTrace(); //$NON-NLS-1$
+			}
+			return ""; //$NON-NLS-1$
+		}
+		StringBuffer buff = new StringBuffer();
+		getContentGenerator().generateRequiredAttribute(parentOrOwner, attrDecl, buff);
+		return buff.toString();
+	}
+
+	protected String getRequiredText(Node parentOrOwner, CMElementDeclaration elementDecl) {
+		if (elementDecl == null) {
+			if (Debug.displayWarnings) {
+				new IllegalArgumentException("Null attribute declaration!").printStackTrace(); //$NON-NLS-1$
+			}
+			return ""; //$NON-NLS-1$
+		}
+		StringBuffer buff = new StringBuffer();
+		getContentGenerator().generateTag(parentOrOwner, elementDecl, buff);
+		return buff.toString();
+	}
+
+	/**
+	 * StructuredTextViewer must be set before using this.
+	 */
+	public IStructuredDocumentRegion getStructuredDocumentRegion(int pos) {
+		// (pa) ITextRegion refactor defect 245190
+		// return
+		// (IStructuredDocumentRegion)ContentAssistUtils.getNodeAt((StructuredTextViewer)fTextViewer,
+		// pos);
+		return ContentAssistUtils.getStructuredDocumentRegion(fTextViewer, pos);
+	}
+
+	private String getTagName(IStructuredDocumentRegion sdRegion) {
+		ITextRegionList regions = sdRegion.getRegions();
+		ITextRegion region = null;
+		String name = ""; //$NON-NLS-1$
+		for (int i = 0; i < regions.size(); i++) {
+			region = regions.get(i);
+			if (region.getType() == DOMRegionContext.XML_TAG_NAME) {
+				name = sdRegion.getText(region);
+				break;
+			}
+		}
+		return name;
+	}
+
+	// returns a list of CMNodes that are available within this parent context
+	// Given the grammar shown below and a snippet of XML code (where the '|'
+	// indicated the cursor position)
+	// the list would return all of the element declarations that are
+	// potential child elements of Foo.
+	//
+	// grammar : Foo -> (A, B, C)
+	// snippet : <Foo><A>|
+	// result : {A, B, C}
+	// 
+	// TODO cs... do we need to pass in the 'kindOfAction'? Seems to me we
+	// could assume it's always an insert.
+	protected List getAvailableChildElementDeclarations(Element parent, int childPosition, int kindOfAction) {
+		List modelQueryActions = getAvailableChildrenAtIndex(parent, childPosition, ModelQuery.VALIDITY_NONE);
+		Iterator iterator = modelQueryActions.iterator();
+		List cmnodes = new Vector();
+		while (iterator.hasNext()) {
+			ModelQueryAction action = (ModelQueryAction) iterator.next();
+			if ((childPosition < 0) || (((action.getStartIndex() <= childPosition) && (childPosition <= action.getEndIndex())) && (action.getKind() == kindOfAction))) {
+				CMNode actionCMNode = action.getCMNode();
+				if ((actionCMNode != null) && !cmnodes.contains(actionCMNode)) {
+					cmnodes.add(actionCMNode);
+				}
+			}
+		}
+		return cmnodes;
+	}
+
+	// returns a list of CMNodes that can be validly inserted at this
+	// childPosition
+	// Given the grammar shown below and a snippet of XML code (where the '|'
+	// indicated the cursor position)
+	// the list would return only the element declarations can be inserted
+	// while maintaing validity of the content.
+	//
+	// grammar : Foo -> (A, B, C)
+	// snippet : <Foo><A>|
+	// result : {B}
+	//    
+	protected List getValidChildElementDeclarations(Element parent, int childPosition, int kindOfAction) {
+		List modelQueryActions = getAvailableChildrenAtIndex(parent, childPosition, ModelQuery.VALIDITY_STRICT);
+		Iterator iterator = modelQueryActions.iterator();
+		List cmnodes = new Vector();
+		while (iterator.hasNext()) {
+			ModelQueryAction action = (ModelQueryAction) iterator.next();
+			if ((childPosition < 0) || (((action.getStartIndex() <= childPosition) && (childPosition <= action.getEndIndex())) && (action.getKind() == kindOfAction))) {
+				CMNode actionCMNode = action.getCMNode();
+				if ((actionCMNode != null) && !cmnodes.contains(actionCMNode)) {
+					cmnodes.add(actionCMNode);
+				}
+			}
+		}
+		return cmnodes;
+	}
+
+	/**
+	 * Similar to the call in HTMLContentAssistProcessor. Pass in a node, it
+	 * tells you if the document is XML type.
+	 * 
+	 * @param node
+	 * 
+	 */
+	protected boolean getXML(Node node) {
+		if (node == null) {
+			return false;
+		}
+
+		Document doc = null;
+		doc = (node.getNodeType() != Node.DOCUMENT_NODE) ? node.getOwnerDocument() : ((Document) node);
+
+		return (doc instanceof IDOMDocument) && ((IDOMDocument) doc).isXMLType();
+	}
+
+	// Initialize local settings
+	protected void init() {
+		// implement in subclasses
+	}
+
+	protected boolean isCloseRegion(ITextRegion region) {
+		String type = region.getType();
+		return ((type == DOMRegionContext.XML_PI_CLOSE) || (type == DOMRegionContext.XML_TAG_CLOSE) || (type == DOMRegionContext.XML_EMPTY_TAG_CLOSE) || (type == DOMRegionContext.XML_CDATA_CLOSE) || (type == DOMRegionContext.XML_COMMENT_CLOSE) || (type == DOMRegionContext.XML_ATTLIST_DECL_CLOSE) || (type == DOMRegionContext.XML_ELEMENT_DECL_CLOSE) || (type == DOMRegionContext.XML_DOCTYPE_DECLARATION_CLOSE) || (type == DOMJSPRegionContextsPrivateCopy.JSP_CLOSE) || (type == DOMJSPRegionContextsPrivateCopy.JSP_COMMENT_CLOSE) || (type.equals(DOMJSPRegionContextsPrivateCopy.JSP_DIRECTIVE_CLOSE)) || (type == DOMRegionContext.XML_DECLARATION_CLOSE));
+	}
+
+	/*
+	 * This is to determine if a tag is a special meta-info comment tag that
+	 * shows up as an ELEMENT
+	 */
+	private boolean isCommentNode(IDOMNode node) {
+		return ((node != null) && (node instanceof IDOMElement) && ((IDOMElement) node).isCommentTag());
+	}
+
+	/**
+	 * Checks if cursor position is after doctype tag...
+	 * 
+	 * @param car
+	 * 
+	 */
+	protected boolean isCursorAfterDoctype(ContentAssistRequest car) {
+		Node aNode = car.getNode();
+		Document parent = aNode.getOwnerDocument();
+		int xmldoctypeNodePosition = -1;
+		boolean isAfterDoctype = true;
+
+		if (parent == null) {
+			return true; // blank document case
+		}
+
+		for (Node child = parent.getFirstChild(); child != null; child = child.getNextSibling()) {
+			if (child instanceof IDOMNode) {
+				if (child.getNodeType() == Node.DOCUMENT_TYPE_NODE) {
+					xmldoctypeNodePosition = ((IDOMNode) child).getEndOffset();
+					isAfterDoctype = (car.getReplacementBeginPosition() >= xmldoctypeNodePosition);
+					break;
+				}
+			}
+		}
+		return isAfterDoctype;
+	}
+
+	/**
+	 * This method can check if the cursor is after the XMLPI
+	 * 
+	 * @param car
+	 * 
+	 */
+	protected boolean isCursorAfterXMLPI(ContentAssistRequest car) {
+		Node aNode = car.getNode();
+		boolean xmlpiFound = false;
+		Document parent = aNode.getOwnerDocument();
+		int xmlpiNodePosition = -1;
+		boolean isAfterXMLPI = false;
+
+		if (parent == null) {
+			return true; // blank document case
+		}
+
+		for (Node child = parent.getFirstChild(); child != null; child = child.getNextSibling()) {
+			boolean xmlpi = ((child.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE) && child.getNodeName().equals("xml")); //$NON-NLS-1$
+			xmlpiFound = xmlpiFound || xmlpi;
+			if (xmlpiFound) {
+				if (child instanceof IDOMNode) {
+					xmlpiNodePosition = ((IDOMNode) child).getEndOffset();
+					isAfterXMLPI = (car.getReplacementBeginPosition() >= xmlpiNodePosition);
+				}
+				break;
+			}
+		}
+		return isAfterXMLPI;
+	}
+
+	protected boolean isNameRegion(ITextRegion region) {
+		String type = region.getType();
+		return ((type == DOMRegionContext.XML_TAG_NAME) || (type == DOMJSPRegionContextsPrivateCopy.JSP_DIRECTIVE_NAME) || (type == DOMRegionContext.XML_ELEMENT_DECL_NAME) || (type == DOMRegionContext.XML_DOCTYPE_NAME) || (type == DOMRegionContext.XML_ATTLIST_DECL_NAME) || (type == DOMJSPRegionContextsPrivateCopy.JSP_ROOT_TAG_NAME) || type.equals(DOMJSPRegionContextsPrivateCopy.JSP_DIRECTIVE_NAME));
+	}
+
+	protected boolean isQuote(String string) {
+		String trimmed = string.trim();
+		if (trimmed.length() > 0) {
+			return (trimmed.charAt(0) == '\'') || (trimmed.charAt(0) == '"');
+		}
+		return false;
+	}
+
+	private boolean isSelfClosed(IStructuredDocumentRegion startTag) {
+		ITextRegionList regions = startTag.getRegions();
+		return regions.get(regions.size() - 1).getType() == DOMRegionContext.XML_EMPTY_TAG_CLOSE;
+	}
+
+	private boolean isStartTag(IStructuredDocumentRegion sdRegion) {
+		boolean result = false;
+		if (sdRegion.getRegions().size() > 0) {
+			ITextRegion r = sdRegion.getRegions().get(0);
+			result = (r.getType() == DOMRegionContext.XML_TAG_OPEN) && sdRegion.isEnded();
+		}
+		return result;
+	}
+
+	protected Properties mapToProperties(CMNamedNodeMap map) {
+		Properties p = new Properties();
+		for (int i = 0; i < map.getLength(); i++) {
+			CMEntityDeclaration decl = (CMEntityDeclaration) map.item(i);
+			p.put(decl.getName(), decl.getValue());
+		}
+		return p;
+	}
+
+	/**
+	 * Gets the corresponding XMLNode, and checks if it's closed.
+	 * 
+	 * @param startTag
+	 * 
+	 */
+	private boolean needsEndTag(IStructuredDocumentRegion startTag) {
+		boolean result = false;
+		IStructuredModel sModel = StructuredModelManager.getModelManager().getExistingModelForRead(fTextViewer.getDocument());
+		try {
+			if (sModel != null) {
+				IDOMNode xmlNode = (IDOMNode) sModel.getIndexedRegion(startTag.getStart());
+				if (!isStartTag(startTag)) {
+					result = false;
+				}
+				else if (isSelfClosed(startTag)) {
+					result = false;
+				}
+				else if (!xmlNode.isContainer()) {
+					result = false;
+				}
+				else {
+					result = xmlNode.getEndStructuredDocumentRegion() == null;
+				}
+			}
+		}
+		finally {
+			if (sModel != null) {
+				sModel.releaseFromRead();
+			}
+		}
+		return result;
+	}
+
+	protected ContentAssistRequest newContentAssistRequest(Node node, Node possibleParent, IStructuredDocumentRegion documentRegion, ITextRegion completionRegion, int begin, int length, String filter) {
+		return new ContentAssistRequest(node, possibleParent, documentRegion, completionRegion, begin, length, filter);
+	}
+
+	public void release() {
+		fGenerator = null;
+	}
+
+	/**
+	 * Set the reason why computeProposals was not able to find any
+	 * completions.
+	 */
+	public void setErrorMessage(String errorMessage) {
+		fErrorMessage = errorMessage;
+	}
+
+	/**
+	 * Set the reason why computeProposals was not able to find any
+	 * completions.
+	 */
+	protected void setErrorMessage(String errorMessage, String append) {
+		setErrorMessage(errorMessage + append);
+	}
+
+	/**
+	 * Set the reason why computeProposals was not able to find any
+	 * completions.
+	 */
+	protected void setErrorMessage(String errorMessage, String prepend, String append) {
+		setErrorMessage(prepend + errorMessage + append);
+	}
+
+	protected boolean stringsEqual(String a, String b) {
+		// (pa) 221190 matching independent of case to be consistant with Java
+		// editor CA
+		return a.equalsIgnoreCase(b);
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/AbstractContentModelGenerator.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/AbstractContentModelGenerator.java
new file mode 100644
index 0000000..7884482
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/AbstractContentModelGenerator.java
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.contentassist;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.DOMNamespaceHelper;
+import org.w3c.dom.Node;
+
+
+public abstract class AbstractContentModelGenerator {
+
+	public static boolean generateChildren = false;
+
+	public AbstractContentModelGenerator() {
+		super();
+	}
+
+	public abstract void generateAttribute(CMAttributeDeclaration attrDecl, StringBuffer buffer);
+
+	protected void generateAttributes(CMElementDeclaration elementDecl, StringBuffer buffer) {
+		CMNamedNodeMap attributes = elementDecl.getAttributes();
+		if (attributes == null) {
+			return;
+		}
+		for (int i = 0; i < attributes.getLength(); i++) {
+			generateAttribute((CMAttributeDeclaration) attributes.item(i), buffer);
+		}
+		return;
+	}
+
+	protected abstract void generateEndTag(String tagName, Node parentNode, CMElementDeclaration elementDecl, StringBuffer buffer);
+
+	public void generateRequiredChildren(Node parentNode, CMElementDeclaration elementDecl, StringBuffer buffer) {
+		if (generateChildren) {
+		}
+		return;
+	}
+
+	protected abstract void generateStartTag(String tagName, Node parentNode, CMElementDeclaration elementDecl, StringBuffer buffer);
+
+	public void generateTag(Node parent, CMElementDeclaration elementDecl, StringBuffer buffer) {
+		if ((elementDecl == null) || (buffer == null)) {
+			return;
+		}
+
+		String tagName = getRequiredName(parent, elementDecl);
+
+		generateStartTag(tagName, parent, elementDecl, buffer);
+		generateRequiredChildren(parent, elementDecl, buffer);
+		generateEndTag(tagName, parent, elementDecl, buffer);
+		return;
+	}
+
+	public abstract int getMinimalStartTagLength(Node node, CMElementDeclaration elementDecl);
+
+	public String getRequiredName(Node ownerNode, CMNode cmnode) {
+		if (ownerNode != null) {
+			return DOMNamespaceHelper.computeName(cmnode, ownerNode, null);
+		}
+		return cmnode.getNodeName();
+	}
+
+	public abstract String getStartTagClose(Node parentNode, CMElementDeclaration elementDecl);
+
+	protected boolean requiresAttributes(CMElementDeclaration ed) {
+		CMNamedNodeMap attributes = ed.getAttributes();
+		if (attributes == null) {
+			return false;
+		}
+		for (int i = 0; i < attributes.getLength(); i++) {
+			if (((CMAttributeDeclaration) attributes.item(i)).getUsage() == CMAttributeDeclaration.REQUIRED) {
+				return true;
+			}
+		}
+		return false;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/AbstractXMLCompletionProposalComputer.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/AbstractXMLCompletionProposalComputer.java
new file mode 100644
index 0000000..dd21a18
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/AbstractXMLCompletionProposalComputer.java
@@ -0,0 +1,1112 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.contentassist;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Properties;
+import java.util.Vector;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
+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.ITextRegionContainer;
+import org.eclipse.wst.sse.ui.contentassist.CompletionProposalInvocationContext;
+import org.eclipse.wst.sse.ui.contentassist.ICompletionProposalComputer;
+import org.eclipse.wst.sse.ui.internal.contentassist.ContentAssistUtils;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
+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 org.eclipse.wst.xml.ui.internal.Logger;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * <p>Implements the framework for making proposals in XML type documents.  Deals with
+ * all the nastiness needed to figure out where in an XML type document the content
+ * assist was invoked and then calls one of many abstract methods depending on the
+ * area the content assist was invoked.  In this way implementers only have to worry about
+ * implementing what to do in each situation while not having to deal with figuring out
+ * which situation the content assist was invoked in.</p>
+ * 
+ * @base org.eclipse.wst.xml.ui.internal.contentassist.AbstractContentAssistProcessor
+ * @see DefaultXMLCompletionProposalComputer
+ */
+public abstract class AbstractXMLCompletionProposalComputer implements ICompletionProposalComputer {
+	/**
+	 * ISSUE: this is a bit of hidden JSP knowledge that was implemented this
+	 * way for expedency. Should be evolved in future to depend on
+	 * "nestedContext".
+	 */
+	private class DOMJSPRegionContextsPrivateCopy {
+		private static final String JSP_CLOSE = "JSP_CLOSE"; //$NON-NLS-1$
+		private static final String JSP_COMMENT_CLOSE = "JSP_COMMENT_CLOSE"; //$NON-NLS-1$
+
+		private static final String JSP_COMMENT_OPEN = "JSP_COMMENT_OPEN"; //$NON-NLS-1$
+		private static final String JSP_DECLARATION_OPEN = "JSP_DECLARATION_OPEN"; //$NON-NLS-1$
+		private static final String JSP_DIRECTIVE_CLOSE = "JSP_DIRECTIVE_CLOSE"; //$NON-NLS-1$
+		private static final String JSP_DIRECTIVE_NAME = "JSP_DIRECTIVE_NAME"; //$NON-NLS-1$
+
+		private static final String JSP_DIRECTIVE_OPEN = "JSP_DIRECTIVE_OPEN"; //$NON-NLS-1$
+		private static final String JSP_EXPRESSION_OPEN = "JSP_EXPRESSION_OPEN"; //$NON-NLS-1$
+
+		private static final String JSP_ROOT_TAG_NAME = "JSP_ROOT_TAG_NAME"; //$NON-NLS-1$
+
+		private static final String JSP_SCRIPTLET_OPEN = "JSP_SCRIPTLET_OPEN"; //$NON-NLS-1$
+	}
+
+	private String fErrorMessage;
+	private ITextViewer fTextViewer;
+
+	public AbstractXMLCompletionProposalComputer() {
+		fErrorMessage = null;
+		fTextViewer = null;
+	}
+	
+	/**
+	 * <p>Return a list of proposed code completions based on the specified
+	 * location within the document that corresponds to the current cursor
+	 * position within the text-editor control.</p>
+	 * 
+	 * @see org.eclipse.wst.sse.ui.contentassist.ICompletionProposalComputer#computeCompletionProposals(org.eclipse.wst.sse.ui.contentassist.CompletionProposalInvocationContext, org.eclipse.core.runtime.IProgressMonitor)
+	 */
+	public List computeCompletionProposals(
+			CompletionProposalInvocationContext context,
+			IProgressMonitor monitor) {
+		
+		ITextViewer textViewer = context.getViewer();
+		int documentPosition = context.getInvocationOffset();
+
+		setErrorMessage(null);
+
+		fTextViewer = textViewer;
+
+		IndexedRegion treeNode = ContentAssistUtils.getNodeAt(textViewer, documentPosition);
+
+		Node node = (Node) treeNode;
+		while ((node != null) && (node.getNodeType() == Node.TEXT_NODE) && (node.getParentNode() != null)) {
+			node = node.getParentNode();
+		}
+		IDOMNode xmlnode = (IDOMNode) node;
+
+		ContentAssistRequest contentAssistRequest = null;
+
+		IStructuredDocumentRegion sdRegion = getStructuredDocumentRegion(documentPosition);
+		ITextRegion completionRegion = getCompletionRegion(documentPosition, node);
+
+		String matchString = getMatchString(sdRegion, completionRegion, documentPosition);
+
+		// Handle empty Documents
+		if (completionRegion == null) {
+			if (((treeNode == null) || (((Node) treeNode).getNodeType() == Node.DOCUMENT_NODE)) && (completionRegion == null) &&
+					((xmlnode == null) || (xmlnode.getChildNodes() == null) || (xmlnode.getChildNodes().getLength() == 0))) {
+				
+				IStructuredModel sModel = null;
+				try {
+					if(textViewer.getDocument() instanceof IStructuredDocument) {
+						sModel = StructuredModelManager.getModelManager().getModelForRead((IStructuredDocument)textViewer.getDocument());
+					}
+					if (sModel != null) {
+						IDOMDocument docNode = ((IDOMModel) sModel).getDocument();
+						contentAssistRequest = new ContentAssistRequest(docNode, docNode, sdRegion, completionRegion, documentPosition, 0, null);
+						addEmptyDocumentProposals(contentAssistRequest, context);
+					}
+				}
+				finally {
+					if (sModel != null) {
+						sModel.releaseFromRead();
+					}
+				}
+				if (contentAssistRequest == null) {
+					Logger.logException(new IllegalStateException("problem getting model")); //$NON-NLS-1$
+					return new ArrayList(0);
+				}
+				
+				ICompletionProposal[] props = contentAssistRequest.getCompletionProposals();
+				return (props != null) ? Arrays.asList(props) : new ArrayList(0);
+			}
+			// MASSIVE ERROR CONDITION
+			Logger.logException(new IllegalStateException("completion region was null")); //$NON-NLS-1$
+			setErrorMessage(XMLUIMessages.SEVERE_internal_error_occu_UI_);
+			contentAssistRequest = new ContentAssistRequest((Node) treeNode, node.getParentNode(), sdRegion, completionRegion, documentPosition, 0, ""); //$NON-NLS-1$
+			ICompletionProposal[] props = contentAssistRequest.getCompletionProposals();
+			return (props != null) ? Arrays.asList(props) : new ArrayList(0);
+		}
+
+
+		// catch documents where no region can be determined
+		if ((xmlnode.getNodeType() == Node.DOCUMENT_NODE) && ((completionRegion == null) ||
+				(xmlnode.getChildNodes() == null) || (xmlnode.getChildNodes().getLength() == 0))) {
+			
+			contentAssistRequest = computeStartDocumentProposals(matchString, completionRegion,
+					(IDOMNode) treeNode,xmlnode, context);
+			ICompletionProposal[] props = contentAssistRequest.getCompletionProposals();
+			return (props != null) ? Arrays.asList(props) : new ArrayList(0);
+		}
+
+		// compute normal proposals
+		contentAssistRequest = computeCompletionProposals(matchString, completionRegion, (IDOMNode) treeNode, xmlnode, context);
+		if (contentAssistRequest == null) {
+			contentAssistRequest = new ContentAssistRequest((Node) treeNode, node.getParentNode(), sdRegion, completionRegion, documentPosition, 0, ""); //$NON-NLS-1$
+			setErrorMessage(XMLUIMessages.Content_Assist_not_availab_UI_);
+		}
+
+		/* 
+		 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=123892
+		 * Only set this error message if nothing else was already set 
+		 **/
+		if (contentAssistRequest.getProposals().size() == 0 && getErrorMessage() == null) {
+			setErrorMessage(XMLUIMessages.Content_Assist_not_availab_UI_);
+		}
+
+		ICompletionProposal[] props = contentAssistRequest.getCompletionProposals();
+		return (props != null) ? Arrays.asList(props) : new ArrayList(0);
+	}
+	
+	/**
+	 * <p>Returns information about possible contexts based on the specified
+	 * location within the document that corresponds to the current cursor
+	 * position within the text viewer.</p>
+	 * 
+	 * @see org.eclipse.wst.sse.ui.contentassist.ICompletionProposalComputer#computeContextInformation(org.eclipse.wst.sse.ui.contentassist.CompletionProposalInvocationContext, org.eclipse.core.runtime.IProgressMonitor)
+	 */
+	public List computeContextInformation(
+			CompletionProposalInvocationContext context,
+			IProgressMonitor monitor) {
+		
+		//no default context info
+		return Collections.EMPTY_LIST;
+	}
+	
+	/**
+	 * @see org.eclipse.wst.sse.ui.contentassist.ICompletionProposalComputer#getErrorMessage()
+	 */
+	public String getErrorMessage() {
+		return fErrorMessage;
+	}
+
+	/**
+	 * Add proposals for attribute names
+	 * 
+	 * @param contentAssistRequest
+	 * @param context
+	 */
+	protected abstract void addAttributeNameProposals(ContentAssistRequest contentAssistRequest,
+			CompletionProposalInvocationContext context);
+
+	/**
+	 * Add proposals for attribute values
+	 * 
+	 * @param contentAssistRequest
+	 * @param context
+	 */
+	protected abstract void addAttributeValueProposals(ContentAssistRequest contentAssistRequest,
+			CompletionProposalInvocationContext context);
+
+	/**
+	 * Add comment proposals
+	 * 
+	 * @param contentAssistRequest
+	 * @param context
+	 */
+	protected abstract void addCommentProposal(ContentAssistRequest contentAssistRequest,
+			CompletionProposalInvocationContext context);
+
+	/**
+	 * Add the proposals for a completely empty document
+	 * 
+	 * @param contentAssistRequest
+	 * @param context
+	 */
+	protected abstract void addEmptyDocumentProposals(ContentAssistRequest contentAssistRequest,
+			CompletionProposalInvocationContext context);
+	
+	/**
+	 * Add the proposals for the name in an end tag
+	 * 
+	 * @param contentAssistRequest
+	 * @param context
+	 */
+	protected abstract void addEndTagNameProposals(ContentAssistRequest contentAssistRequest,
+			CompletionProposalInvocationContext context);
+	
+	/**
+	 * Prompt for end tags to a non-empty Node that hasn't ended Handles these
+	 * cases: <br>
+	 * <tagOpen>| <br>
+	 * <tagOpen>< |<br>
+	 * <tagOpen></ |
+	 * 
+	 * @param contentAssistRequest
+	 * @param context
+	 */
+	protected abstract void addEndTagProposals(ContentAssistRequest contentAssistRequest,
+			CompletionProposalInvocationContext context);
+	
+	/**
+	 * Add entity proposals
+	 * 
+	 * @param contentAssistRequest
+	 * @param completionRegion
+	 * @param treeNode
+	 * @param context
+	 */
+	protected abstract void addEntityProposals(ContentAssistRequest contentAssistRequest,
+			ITextRegion completionRegion, IDOMNode treeNode, CompletionProposalInvocationContext context);
+
+	/**
+	 * add entity proposals
+	 * 
+	 * @param proposals
+	 * @param map
+	 * @param key
+	 * @param nodeOffset
+	 * @param sdRegion
+	 * @param completionRegion
+	 * @param context
+	 */
+	protected abstract void addEntityProposals(Vector proposals, Properties map, String key,
+			int nodeOffset, IStructuredDocumentRegion sdRegion, ITextRegion completionRegion,
+			CompletionProposalInvocationContext context);
+
+	/**
+	 * Add PCData proposals
+	 * 
+	 * @param nodeName
+	 * @param contentAssistRequest
+	 * @param context
+	 */
+	protected abstract void addPCDATAProposal(String nodeName, ContentAssistRequest contentAssistRequest,
+			CompletionProposalInvocationContext context);
+
+	/**
+	 * Add start document proposals
+	 * 
+	 * @param contentAssistRequest
+	 * @param context
+	 */
+	protected abstract void addStartDocumentProposals(ContentAssistRequest contentAssistRequest,
+			CompletionProposalInvocationContext context);
+
+	/**
+	 * Close an unclosed start tag
+	 * 
+	 * @param contentAssistRequest
+	 * @param context
+	 */
+	protected abstract void addTagCloseProposals(ContentAssistRequest contentAssistRequest,
+			CompletionProposalInvocationContext context);
+
+	/**
+	 * Add tag insertion proposals
+	 * 
+	 * @param contentAssistRequest
+	 * @param childPosition
+	 * @param context
+	 */
+	protected abstract void addTagInsertionProposals(ContentAssistRequest contentAssistRequest,
+			int childPosition, CompletionProposalInvocationContext context);
+
+	/**
+	 * Add tag name proposals
+	 * 
+	 * @param contentAssistRequest
+	 * @param childPosition
+	 * @param context
+	 */
+	protected abstract void addTagNameProposals(ContentAssistRequest contentAssistRequest,
+			int childPosition, CompletionProposalInvocationContext context);
+	
+	/**
+	 * @param errorMessage the reason why computeProposals was not able to find any
+	 * completions.
+	 */
+	protected void setErrorMessage(String errorMessage) {
+		fErrorMessage = errorMessage;
+	}
+	
+	/**
+	 * <p>This does all the magic of figuring out where in the XML type document
+	 * the content assist was invoked and then calling the corresponding method
+	 * to add the correct proposals</p>
+	 * 
+	 * <p><b>NOTE: </b>if overriding be sure to make super call back to this method otherwise
+	 * you will loose all of the proposals generated by this method</p>
+	 * 
+	 * @param matchString
+	 * @param completionRegion
+	 * @param treeNode
+	 * @param xmlnode
+	 * @param context
+	 * 
+	 * @return {@link ContentAssistRequest} that now has all the proposals in it
+	 */
+	protected ContentAssistRequest computeCompletionProposals(String matchString, ITextRegion completionRegion,
+			IDOMNode treeNode, IDOMNode xmlnode, CompletionProposalInvocationContext context) {
+		
+		int documentPosition = context.getInvocationOffset();
+		
+		ContentAssistRequest contentAssistRequest = null;
+		String regionType = completionRegion.getType();
+		IStructuredDocumentRegion sdRegion = getStructuredDocumentRegion(documentPosition);
+
+		// Handle the most common and best supported cases
+		if ((xmlnode.getNodeType() == Node.ELEMENT_NODE) || (xmlnode.getNodeType() == Node.DOCUMENT_NODE)) {
+			if (regionType == DOMRegionContext.XML_TAG_OPEN) {
+				contentAssistRequest = computeTagOpenProposals(matchString, completionRegion, treeNode, xmlnode, context);
+			}
+			else if (regionType == DOMRegionContext.XML_TAG_NAME) {
+				contentAssistRequest = computeTagNameProposals(matchString, completionRegion,
+						treeNode, xmlnode, context);
+			}
+			else if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) {
+				contentAssistRequest = computeAttributeProposals(matchString, completionRegion, treeNode, xmlnode, context);
+			}
+			else if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_EQUALS) {
+				contentAssistRequest = computeEqualsProposals(matchString, completionRegion,
+						treeNode, xmlnode, context);
+			}
+			else if ((regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) && (documentPosition == sdRegion.getTextEndOffset()) &&
+					(sdRegion.getText(completionRegion).endsWith("\"") || sdRegion.getText(completionRegion).endsWith("\'"))) { //$NON-NLS-1$ //$NON-NLS-2$ 
+				// this is for when the cursor is at the end of the closing
+				// quote for an attribute..
+				IDOMNode actualNode = (IDOMNode) xmlnode.getModel().getIndexedRegion(sdRegion.getStartOffset(completionRegion));
+				contentAssistRequest = new ContentAssistRequest(actualNode, actualNode, sdRegion, completionRegion, documentPosition, 0, matchString);
+				addTagCloseProposals(contentAssistRequest, context);
+			}
+			else if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
+				contentAssistRequest = computeAttributeValueProposals(matchString, completionRegion, treeNode, xmlnode, context);
+			}
+			else if ((regionType == DOMRegionContext.XML_TAG_CLOSE) || (regionType == DOMRegionContext.XML_EMPTY_TAG_CLOSE) ||
+					(regionType.equals(DOMJSPRegionContextsPrivateCopy.JSP_DIRECTIVE_CLOSE))) {
+				
+				contentAssistRequest = computeTagCloseProposals(matchString, completionRegion, treeNode, xmlnode, context);
+			}
+			else if (regionType == DOMRegionContext.XML_END_TAG_OPEN) {
+				contentAssistRequest = computeEndTagOpenProposals(matchString, completionRegion,
+						treeNode, xmlnode, context);
+			}
+			else if ((regionType == DOMRegionContext.XML_CONTENT) || (regionType == DOMRegionContext.XML_CHAR_REFERENCE) ||
+					(regionType == DOMRegionContext.XML_ENTITY_REFERENCE) || (regionType == DOMRegionContext.XML_PE_REFERENCE)) {
+				
+				contentAssistRequest = computeContentProposals(matchString, completionRegion,
+						treeNode, xmlnode, context);
+			}
+
+			// These ITextRegion types begin DOM Elements as well and although
+			// internally harder to assist,
+			// text insertions directly before them can be made
+			else if ((documentPosition == sdRegion.getStartOffset(completionRegion)) &&
+					(regionType.equals(DOMJSPRegionContextsPrivateCopy.JSP_COMMENT_OPEN) ||
+							regionType.equals(DOMJSPRegionContextsPrivateCopy.JSP_DECLARATION_OPEN) ||
+							regionType.equals(DOMJSPRegionContextsPrivateCopy.JSP_DIRECTIVE_OPEN) ||
+							regionType.equals(DOMJSPRegionContextsPrivateCopy.JSP_EXPRESSION_OPEN) ||
+							regionType.equals(DOMJSPRegionContextsPrivateCopy.JSP_SCRIPTLET_OPEN) ||
+							(regionType == DOMRegionContext.XML_DECLARATION_OPEN) ||
+							(regionType == DOMRegionContext.XML_PI_OPEN) ||
+							(regionType == DOMRegionContext.XML_COMMENT_OPEN) ||
+							(regionType == DOMRegionContext.XML_CDATA_OPEN))) {
+				
+				contentAssistRequest = new ContentAssistRequest(treeNode, xmlnode.getParentNode(), sdRegion, completionRegion, documentPosition, 0, matchString);
+				addTagInsertionProposals(contentAssistRequest, getElementPosition(treeNode), context);
+				addStartDocumentProposals(contentAssistRequest, context);
+			}
+		}
+		// Not a Document or Element? (odd cases go here for now)
+		else if (isCloseRegion(completionRegion)) {
+			contentAssistRequest = new ContentAssistRequest(treeNode, xmlnode.getParentNode(), sdRegion, completionRegion, sdRegion.getStartOffset(completionRegion) + completionRegion.getLength(), 0, matchString);
+			addStartDocumentProposals(contentAssistRequest, context);
+			if (documentPosition >= sdRegion.getTextEndOffset(completionRegion)) {
+				addTagInsertionProposals(contentAssistRequest, getElementPosition(treeNode) + 1, context);
+			}
+		}
+		else if ((documentPosition == sdRegion.getStartOffset(completionRegion)) &&
+				(regionType.equals(DOMJSPRegionContextsPrivateCopy.JSP_COMMENT_OPEN) ||
+						regionType.equals(DOMJSPRegionContextsPrivateCopy.JSP_DECLARATION_OPEN) ||
+						regionType.equals(DOMJSPRegionContextsPrivateCopy.JSP_DIRECTIVE_OPEN) ||
+						regionType.equals(DOMJSPRegionContextsPrivateCopy.JSP_EXPRESSION_OPEN) ||
+						regionType.equals(DOMJSPRegionContextsPrivateCopy.JSP_SCRIPTLET_OPEN) ||
+						(regionType == DOMRegionContext.XML_DECLARATION_OPEN) ||
+						(regionType == DOMRegionContext.XML_PI_OPEN) ||
+						(regionType == DOMRegionContext.XML_COMMENT_OPEN) ||
+						(regionType == DOMRegionContext.XML_CDATA_OPEN))) {
+			
+			contentAssistRequest = new ContentAssistRequest(treeNode, xmlnode.getParentNode(), sdRegion, completionRegion, documentPosition, 0, matchString);
+			addTagInsertionProposals(contentAssistRequest, getElementPosition(treeNode), context);
+			addStartDocumentProposals(contentAssistRequest, context);
+		}
+		return contentAssistRequest;
+	}
+	
+	/**
+	 * <p>Similar to {@link #computeCompletionProposals(CompletionProposalInvocationContext, IProgressMonitor)} only specificly for
+	 * attribute proposals</p>
+	 * 
+	 * <p>Implementers should not override this method, it is made available to implementers so that if they override
+	 * {@link #computeCompletionProposals(String, ITextRegion, IDOMNode, IDOMNode, CompletionProposalInvocationContext)}
+	 * they can call this method if needed</p>
+	 * 
+	 * @param matchString
+	 * @param completionRegion
+	 * @param nodeAtOffset
+	 * @param node
+	 * @param context
+	 * @return
+	 */
+	protected final ContentAssistRequest computeAttributeProposals(String matchString, ITextRegion completionRegion,
+			IDOMNode nodeAtOffset, IDOMNode node, CompletionProposalInvocationContext context) {
+		
+		int documentPosition = context.getInvocationOffset();
+		ITextViewer viewer = context.getViewer();
+		ContentAssistRequest contentAssistRequest = null;
+		IStructuredDocumentRegion sdRegion = getStructuredDocumentRegion(documentPosition);
+		// if the attribute name is selected, replace it instead of creating a new attribute
+		if (documentPosition <= sdRegion.getStartOffset(completionRegion) && (viewer != null && viewer.getSelectedRange().y != (sdRegion.getEndOffset(completionRegion) - sdRegion.getStartOffset(completionRegion)))) {
+			// setup to insert new attributes
+			contentAssistRequest = new ContentAssistRequest(nodeAtOffset, node, sdRegion, completionRegion, documentPosition, 0, matchString);
+		}
+		else {
+			// Setup to replace an existing attribute name
+			contentAssistRequest = new ContentAssistRequest(nodeAtOffset, node, sdRegion, completionRegion, sdRegion.getStartOffset(completionRegion), completionRegion.getTextLength(), matchString);
+		}
+		addAttributeNameProposals(contentAssistRequest, context);
+		contentAssistRequest.setReplacementBeginPosition(documentPosition);
+		contentAssistRequest.setReplacementLength(0);
+		if ((node.getFirstStructuredDocumentRegion() != null) && (!node.getFirstStructuredDocumentRegion().isEnded())) {
+			addTagCloseProposals(contentAssistRequest, context);
+		}
+		return contentAssistRequest;
+	}
+	
+	/**
+	 * <p>this is the position the cursor should be in after the proposal is
+	 * applied</p>
+	 * 
+	 * @param proposedText
+	 * @return the position the cursor should be in after the proposal is
+	 *         applied
+	 */
+	protected static int getCursorPositionForProposedText(String proposedText) {
+		int cursorAdjustment;
+		cursorAdjustment = proposedText.indexOf("\"\"") + 1; //$NON-NLS-1$
+		// otherwise, after the first tag
+		if (cursorAdjustment == 0) {
+			cursorAdjustment = proposedText.indexOf('>') + 1;
+		}
+		if (cursorAdjustment == 0) {
+			cursorAdjustment = proposedText.length() + 1;
+		}
+
+		return cursorAdjustment;
+	}
+	
+	/**
+	 * <p>helpful utility method for determining if one string starts with another one.
+	 * This is case insensitive. If either are null then result is <code>true</code></p>
+	 * 
+	 * @param aString the string to check to see if it starts with the given prefix
+	 * @param prefix check that the given string starts with this prefix
+	 * 
+	 * @return <code>true</code> if the given string starts with the given prefix,
+	 * <code>false</code> otherwise
+	 */
+	protected static boolean beginsWith(String aString, String prefix) {
+		if ((aString == null) || (prefix == null)) {
+			return true;
+		}
+		return aString.toLowerCase().startsWith(prefix.toLowerCase());
+	}
+
+	private ContentAssistRequest computeAttributeValueProposals(String matchString, ITextRegion completionRegion,
+			IDOMNode nodeAtOffset, IDOMNode node, CompletionProposalInvocationContext context) {
+		
+		int documentPosition = context.getInvocationOffset();
+		
+		ContentAssistRequest contentAssistRequest = null;
+		IStructuredDocumentRegion sdRegion = getStructuredDocumentRegion(documentPosition);
+		if ((documentPosition > sdRegion.getStartOffset(completionRegion) + completionRegion.getTextLength()) && (sdRegion.getStartOffset(completionRegion) + completionRegion.getTextLength() != sdRegion.getStartOffset(completionRegion) + completionRegion.getLength())) {
+			// setup to add a new attribute at the documentPosition
+			IDOMNode actualNode = (IDOMNode) node.getModel().getIndexedRegion(sdRegion.getStartOffset(completionRegion));
+			contentAssistRequest = new ContentAssistRequest(actualNode, actualNode, sdRegion, completionRegion, documentPosition, 0, matchString);
+			addAttributeNameProposals(contentAssistRequest, context);
+			if ((actualNode.getFirstStructuredDocumentRegion() != null) && !actualNode.getFirstStructuredDocumentRegion().isEnded()) {
+				addTagCloseProposals(contentAssistRequest, context);
+			}
+		}
+		else {
+			// setup to replace the existing value
+			if (!nodeAtOffset.getFirstStructuredDocumentRegion().isEnded() && (documentPosition < sdRegion.getStartOffset(completionRegion))) {
+				// if the IStructuredDocumentRegion isn't closed and the
+				// cursor is in front of the value, add
+				contentAssistRequest = new ContentAssistRequest(nodeAtOffset, node, sdRegion, completionRegion, documentPosition, 0, matchString);
+				addAttributeNameProposals(contentAssistRequest, context);
+			}
+			else {
+				int replaceLength = completionRegion.getTextLength();
+				
+				//if container region, be sure replace length is only the attribute value region not the entire container
+				if(completionRegion instanceof ITextRegionContainer){
+					ITextRegion openRegion = ((ITextRegionContainer) completionRegion).getFirstRegion();
+					ITextRegion closeRegion = ((ITextRegionContainer) completionRegion).getLastRegion();
+					
+					/*
+					 * check to see if the container is opened the same way its closed.
+					 * Such as:
+					 * <img src=' '
+					 * But not:
+					 * <img src='
+					 * 
+					 * </body>
+					 * </html>
+					 * In the latter case we only want to replace the opening text of the container
+					 * Admittedly crude test, but effective.
+					 */
+					if(openRegion.getType() != closeRegion.getType()) {
+						replaceLength = openRegion.getTextLength();
+					}
+				} 
+				
+				contentAssistRequest = new ContentAssistRequest(nodeAtOffset, node, sdRegion,
+						completionRegion, sdRegion.getStartOffset(completionRegion),
+						replaceLength, matchString);
+				
+				addAttributeValueProposals(contentAssistRequest, context);
+			}
+		}
+		return contentAssistRequest;
+	}
+
+	private ContentAssistRequest computeContentProposals(String matchString, ITextRegion completionRegion,
+			IDOMNode nodeAtOffset, IDOMNode node, CompletionProposalInvocationContext context) {
+		
+		int documentPosition = context.getInvocationOffset();
+		ContentAssistRequest contentAssistRequest = null;
+
+		// setup to add children at the content node's position
+		contentAssistRequest = new ContentAssistRequest(nodeAtOffset, node, getStructuredDocumentRegion(documentPosition), completionRegion, documentPosition, 0, matchString);
+		if ((node != null) && (node.getNodeType() == Node.DOCUMENT_NODE) && (((Document) node).getDoctype() == null)) {
+			addStartDocumentProposals(contentAssistRequest, context);
+		}
+		addTagInsertionProposals(contentAssistRequest, getElementPosition(nodeAtOffset), context);
+		if (node.getNodeType() != Node.DOCUMENT_NODE) {
+			addEndTagProposals(contentAssistRequest, context);
+		}
+		// entities?
+		addEntityProposals(contentAssistRequest, completionRegion, node, context);
+		// addEntityProposals(contentAssistRequest);
+		return contentAssistRequest;
+	}
+
+	private ContentAssistRequest computeEndTagOpenProposals(String matchString, ITextRegion completionRegion,
+			IDOMNode nodeAtOffset, IDOMNode node, CompletionProposalInvocationContext context) {
+		
+		int documentPosition = context.getInvocationOffset();
+		ContentAssistRequest contentAssistRequest = null;
+		IStructuredDocumentRegion sdRegion = getStructuredDocumentRegion(documentPosition);
+		int completionRegionStart = sdRegion.getStartOffset(completionRegion);
+		int completionRegionLength = completionRegion.getLength();
+		IStructuredDocumentRegion sdRegionAtCompletionOffset = node.getStructuredDocument().getRegionAtCharacterOffset(completionRegionStart + completionRegionLength);
+		ITextRegion regionAtEndOfCompletion = sdRegionAtCompletionOffset.getRegionAtCharacterOffset(completionRegionStart + completionRegionLength);
+
+		if ((documentPosition != completionRegionStart) && (regionAtEndOfCompletion != null) && (regionAtEndOfCompletion.getType() == DOMRegionContext.XML_TAG_NAME)) {
+			ITextRegion nameRegion = regionAtEndOfCompletion;
+			contentAssistRequest = new ContentAssistRequest(nodeAtOffset, nodeAtOffset.getParentNode(), sdRegion, completionRegion, sdRegion.getStartOffset(nameRegion), nameRegion.getTextLength(), matchString);
+		}
+		else {
+			if (nodeAtOffset.getFirstStructuredDocumentRegion() == sdRegion) {
+				// abnormal case, this unmatched end tag will be a sibling
+				contentAssistRequest = new ContentAssistRequest(nodeAtOffset, nodeAtOffset.getParentNode(), sdRegion, completionRegion, documentPosition, 0, matchString);
+			}
+			else {
+				// normal case, this end tag is the parent
+				contentAssistRequest = new ContentAssistRequest(nodeAtOffset, nodeAtOffset, sdRegion, completionRegion, documentPosition, 0, matchString);
+			}
+		}
+		// if (documentPosition >= sdRegion.getStartOffset(completionRegion) +
+		// completionRegion.getTextLength())
+		addEndTagProposals(contentAssistRequest, context);
+		// else
+		if (completionRegionStart == documentPosition) {
+			// positioned at start of end tag
+			addTagInsertionProposals(contentAssistRequest, node.getChildNodes().getLength(), context);
+		}
+		return contentAssistRequest;
+	}
+
+
+	private ContentAssistRequest computeEqualsProposals(String matchString, ITextRegion completionRegion,
+			IDOMNode nodeAtOffset, IDOMNode node, CompletionProposalInvocationContext context) {
+		
+		int documentPosition = context.getInvocationOffset();
+		ContentAssistRequest contentAssistRequest = null;
+		IStructuredDocumentRegion sdRegion = getStructuredDocumentRegion(documentPosition);
+		ITextRegion valueRegion = node.getStartStructuredDocumentRegion().getRegionAtCharacterOffset(sdRegion.getStartOffset(completionRegion) + completionRegion.getLength());
+		if ((valueRegion != null) && (valueRegion.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) && (sdRegion.getStartOffset(valueRegion) <= documentPosition)) {
+			// replace the adjacent attribute value
+			contentAssistRequest = new ContentAssistRequest(nodeAtOffset, node, sdRegion, valueRegion, sdRegion.getStartOffset(valueRegion), valueRegion.getTextLength(), matchString);
+		}
+		else {
+			// append an attribute value after the '='
+			contentAssistRequest = new ContentAssistRequest(nodeAtOffset, node, sdRegion, completionRegion, documentPosition, 0, matchString);
+		}
+		addAttributeValueProposals(contentAssistRequest, context);
+		return contentAssistRequest;
+	}
+
+	private ContentAssistRequest computeStartDocumentProposals(String matchString, ITextRegion completionRegion,
+			IDOMNode nodeAtOffset, IDOMNode node, CompletionProposalInvocationContext context) {
+		
+		int documentPosition = context.getInvocationOffset();
+		
+		// setup for a non-empty document, but one that hasn't been formally
+		// started
+		ContentAssistRequest contentAssistRequest = null;
+		contentAssistRequest = new ContentAssistRequest(nodeAtOffset, node,
+				getStructuredDocumentRegion(documentPosition), completionRegion,
+				documentPosition, 0, matchString);
+		addStartDocumentProposals(contentAssistRequest, context);
+		return contentAssistRequest;
+	}
+
+	private ContentAssistRequest computeTagCloseProposals(String matchString, ITextRegion completionRegion,
+			IDOMNode nodeAtOffset, IDOMNode node, CompletionProposalInvocationContext context) {
+		
+		int documentPosition = context.getInvocationOffset();
+		ContentAssistRequest contentAssistRequest = null;
+		IStructuredDocumentRegion sdRegion = getStructuredDocumentRegion(documentPosition);
+
+		if ((node.getNodeType() == Node.DOCUMENT_NODE) || (documentPosition >= sdRegion.getEndOffset())) {
+			// this is a content request as the documentPosition is AFTER the
+			// end of the closing region
+			if ((node == nodeAtOffset) && (node.getParentNode() != null)) {
+				node = (IDOMNode) node.getParentNode();
+			}
+			contentAssistRequest = new ContentAssistRequest(nodeAtOffset, node, sdRegion, completionRegion, documentPosition, 0, matchString);
+			addTagInsertionProposals(contentAssistRequest, getElementPosition(nodeAtOffset), context);
+			if ((node.getNodeType() != Node.DOCUMENT_NODE) && (node.getEndStructuredDocumentRegion() == null)) {
+				addEndTagProposals(contentAssistRequest, context);
+			}
+		}
+		else {
+			// at the start of the tag's close or within it
+			ITextRegion closeRegion = sdRegion.getLastRegion();
+			boolean insideTag = !sdRegion.isEnded() || (documentPosition <= sdRegion.getStartOffset(closeRegion));
+			if (insideTag) {
+				// this is a request for completions within a tag
+				contentAssistRequest = new ContentAssistRequest(nodeAtOffset, node, sdRegion, completionRegion, documentPosition, 0, matchString);
+				if ((node.getNodeType() != Node.DOCUMENT_NODE) && (node.getEndStructuredDocumentRegion() != null)) {
+					addTagCloseProposals(contentAssistRequest, context);
+				}
+				if (sdRegion == nodeAtOffset.getFirstStructuredDocumentRegion()) {
+					contentAssistRequest.setReplacementBeginPosition(documentPosition);
+					contentAssistRequest.setReplacementLength(0);
+					addAttributeNameProposals(contentAssistRequest, context);
+				}
+			}
+		}
+		return contentAssistRequest;
+	}
+
+	private ContentAssistRequest computeTagNameProposals(String matchString, ITextRegion completionRegion,
+			IDOMNode nodeAtOffset, IDOMNode node, CompletionProposalInvocationContext context) {
+		
+		int documentPosition = context.getInvocationOffset();
+		ContentAssistRequest contentAssistRequest = null;
+		IStructuredDocumentRegion sdRegion = getStructuredDocumentRegion(documentPosition);
+
+		if (sdRegion != nodeAtOffset.getFirstStructuredDocumentRegion()) {
+			// completing the *first* tag in "<tagname1 |<tagname2"
+			IDOMNode actualNode = (IDOMNode) node.getModel().getIndexedRegion(sdRegion.getStartOffset(completionRegion));
+			if (actualNode != null) {
+				if (actualNode.getFirstStructuredDocumentRegion() == sdRegion) {
+					// start tag
+					if (documentPosition > sdRegion.getStartOffset(completionRegion) + completionRegion.getLength()) {
+						// it's attributes
+						contentAssistRequest = new ContentAssistRequest(actualNode, actualNode, sdRegion, completionRegion, documentPosition - matchString.length(), matchString.length(), matchString);
+						if (node.getStructuredDocument().getRegionAtCharacterOffset(sdRegion.getStartOffset(completionRegion) - 1).getRegionAtCharacterOffset(sdRegion.getStartOffset(completionRegion) - 1).getType() == DOMRegionContext.XML_TAG_OPEN) {
+							addAttributeNameProposals(contentAssistRequest, context);
+						}
+						addTagCloseProposals(contentAssistRequest, context);
+					}
+					else {
+						// it's name
+						contentAssistRequest = new ContentAssistRequest(actualNode, actualNode.getParentNode(),
+								sdRegion, completionRegion, documentPosition - matchString.length(),
+								matchString.length(), matchString);
+						addTagNameProposals(contentAssistRequest, getElementPosition(actualNode),
+								context);
+					}
+				}
+				else {
+					if (documentPosition >= sdRegion.getStartOffset(completionRegion) + completionRegion.getLength()) {
+						// insert name
+						contentAssistRequest = new ContentAssistRequest(actualNode, actualNode.getParentNode(),
+								sdRegion, completionRegion, documentPosition, 0, matchString);
+					}
+					else {
+						// replace name
+						contentAssistRequest = new ContentAssistRequest(actualNode, actualNode.getParentNode(),
+								sdRegion, completionRegion, sdRegion.getStartOffset(completionRegion),
+								completionRegion.getTextLength(), matchString);
+					}
+					addEndTagNameProposals(contentAssistRequest, context);
+				}
+			}
+		}
+		else {
+			if (documentPosition > sdRegion.getStartOffset(completionRegion) + completionRegion.getTextLength()) {
+				// unclosed tag with only a name; should prompt for attributes
+				// and a close instead
+				contentAssistRequest = new ContentAssistRequest(nodeAtOffset, node, sdRegion, completionRegion,
+						documentPosition - matchString.length(), matchString.length(), matchString);
+				addAttributeNameProposals(contentAssistRequest, context);
+				addTagCloseProposals(contentAssistRequest, context);
+			}
+			else {
+				if (sdRegion.getRegions().get(0).getType() != DOMRegionContext.XML_END_TAG_OPEN) {
+					int replaceLength = documentPosition - sdRegion.getStartOffset(completionRegion);
+					contentAssistRequest = new ContentAssistRequest(node, node.getParentNode(), sdRegion,
+							completionRegion, sdRegion.getStartOffset(completionRegion), replaceLength, matchString);
+					addTagNameProposals(contentAssistRequest, getElementPosition(nodeAtOffset), context);
+				}
+				else {
+					IDOMNode actualNode = (IDOMNode) node.getModel().getIndexedRegion(documentPosition);
+					if (actualNode != null) {
+						if (documentPosition >= sdRegion.getStartOffset(completionRegion) + completionRegion.getTextLength()) {
+							contentAssistRequest = new ContentAssistRequest(actualNode, actualNode.getParentNode(),
+									sdRegion, completionRegion, documentPosition, 0, matchString);
+						}
+						else {
+							contentAssistRequest = new ContentAssistRequest(actualNode, actualNode.getParentNode(),
+									sdRegion, completionRegion, sdRegion.getStartOffset(completionRegion),
+									completionRegion.getTextLength(), matchString);
+						}
+						addEndTagNameProposals(contentAssistRequest, context);
+					}
+				}
+			}
+		}
+		return contentAssistRequest;
+	}
+
+	private ContentAssistRequest computeTagOpenProposals(String matchString, ITextRegion completionRegion,
+			IDOMNode nodeAtOffset, IDOMNode node, CompletionProposalInvocationContext context) {
+		
+		int documentPosition = context.getInvocationOffset();
+		ContentAssistRequest contentAssistRequest = null;
+		IStructuredDocumentRegion sdRegion = getStructuredDocumentRegion(documentPosition);
+		if (sdRegion != nodeAtOffset.getFirstStructuredDocumentRegion() || sdRegion.getPrevious() != null && sdRegion.getPrevious().getLastRegion().getType() == DOMRegionContext.XML_TAG_OPEN) {
+			// completing the *first* XML_TAG_OPEN in "<<tagname"
+			IDOMNode actualNode = (IDOMNode) node.getModel().getIndexedRegion(sdRegion.getStartOffset(completionRegion));
+			if (actualNode != null) {
+				if(sdRegion.getFirstRegion().getType() == DOMRegionContext.XML_END_TAG_OPEN) {
+					contentAssistRequest = new ContentAssistRequest(actualNode, actualNode, sdRegion, completionRegion, documentPosition, 0, matchString);
+					if(actualNode.hasChildNodes())
+						addTagNameProposals(contentAssistRequest,
+								getElementPosition(actualNode.getLastChild()), context);
+					else
+						addTagNameProposals(contentAssistRequest, 0, context);
+				}
+				else {
+					contentAssistRequest = new ContentAssistRequest(actualNode, actualNode.getParentNode(), sdRegion, completionRegion, documentPosition, 0, matchString);
+					addTagNameProposals(contentAssistRequest, getElementPosition(actualNode), context);
+				}
+				addEndTagProposals(contentAssistRequest, context); // (pa) 220850
+			}
+		}
+		else {
+			if (documentPosition == sdRegion.getStartOffset(completionRegion)) {
+				if (node.getNodeType() == Node.ELEMENT_NODE) {
+					// at the start of an existing tag, right before the '<'
+					contentAssistRequest = new ContentAssistRequest(nodeAtOffset, node.getParentNode(), sdRegion,
+							completionRegion, documentPosition, 0, matchString);
+					addTagInsertionProposals(contentAssistRequest, getElementPosition(nodeAtOffset), context);
+					addEndTagProposals(contentAssistRequest, context);
+				}
+				else if (node.getNodeType() == Node.DOCUMENT_NODE) {
+					// at the opening of the VERY first tag with a '<'
+					contentAssistRequest = new ContentAssistRequest(nodeAtOffset, node.getParentNode(), sdRegion,
+							completionRegion, sdRegion.getStartOffset(completionRegion), completionRegion.getTextLength(), matchString);
+					addStartDocumentProposals(contentAssistRequest, context);
+				}
+			}
+			else {
+				// within the white space
+				ITextRegion name = getNameRegion(node.getStartStructuredDocumentRegion());
+				// (pa) ITextRegion refactor
+				// if (name != null && name.containsOffset(documentPosition))
+				// {
+				if ((name != null) &&
+						((sdRegion.getStartOffset(name) <= documentPosition) && (sdRegion.getEndOffset(name) >= documentPosition)) &&
+						(sdRegion.getLastRegion().getType() == DOMRegionContext.XML_TAG_CLOSE || sdRegion.getLastRegion().getType() == DOMRegionContext.XML_EMPTY_TAG_CLOSE)){ 
+					
+					// replace the existing name
+					contentAssistRequest = new ContentAssistRequest(node, node.getParentNode(), sdRegion, completionRegion, sdRegion.getStartOffset(name), name.getTextLength(), matchString);
+				}
+				else {
+					// insert a valid new name, or possibly an end tag
+					contentAssistRequest = new ContentAssistRequest(nodeAtOffset, ((Node) nodeAtOffset).getParentNode(), sdRegion, completionRegion, documentPosition, 0, matchString);
+					addEndTagProposals(contentAssistRequest, context);
+					contentAssistRequest.setReplacementBeginPosition(documentPosition);
+					contentAssistRequest.setReplacementLength(0);
+				}
+				addTagNameProposals(contentAssistRequest, getElementPosition(nodeAtOffset), context);
+			}
+		}
+		return contentAssistRequest;
+	}
+
+	private ITextRegion getCompletionRegion(int offset, IStructuredDocumentRegion sdRegion) {
+		ITextRegion region = sdRegion.getRegionAtCharacterOffset(offset);
+		if (region == null) {
+			return null;
+		}
+
+		if (sdRegion.getStartOffset(region) == offset) {
+			// The offset is at the beginning of the region
+			if ((sdRegion.getStartOffset(region) == sdRegion.getStartOffset()) && (sdRegion.getPrevious() != null) && (!sdRegion.getPrevious().isEnded())) {
+				// Is the region also the start of the node? If so, the
+				// previous IStructuredDocumentRegion is
+				// where to look for a useful region.
+				region = sdRegion.getPrevious().getRegionAtCharacterOffset(offset - 1);
+			}
+			else {
+				// Is there no separating whitespace from the previous region?
+				// If not,
+				// then that region is the important one
+				ITextRegion previousRegion = sdRegion.getRegionAtCharacterOffset(offset - 1);
+				if ((previousRegion != null) && (previousRegion != region) && (previousRegion.getTextLength() == previousRegion.getLength())) {
+					region = previousRegion;
+				}
+			}
+		}
+		else {
+			// The offset is NOT at the beginning of the region
+			if (offset > sdRegion.getStartOffset(region) + region.getTextLength()) {
+				// Is the offset within the whitespace after the text in this
+				// region?
+				// If so, use the next region
+				ITextRegion nextRegion = sdRegion.getRegionAtCharacterOffset(sdRegion.getStartOffset(region) + region.getLength());
+				if (nextRegion != null) {
+					region = nextRegion;
+				}
+			}
+			else {
+				// Is the offset within the important text for this region?
+				// If so, then we've already got the right one.
+			}
+		}
+
+		// valid WHITE_SPACE region handler (#179924)
+		if ((region != null) && (region.getType() == DOMRegionContext.WHITE_SPACE)) {
+			ITextRegion previousRegion = sdRegion.getRegionAtCharacterOffset(sdRegion.getStartOffset(region) - 1);
+			if (previousRegion != null) {
+				region = previousRegion;
+			}
+		}
+
+		return region;
+	}
+
+	/**
+	 * Return the region whose content's require completion. This is something
+	 * of a misnomer as sometimes the user wants to be prompted for contents
+	 * of a non-existant ITextRegion, such as for enumerated attribute values
+	 * following an '=' sign.
+	 */
+	private ITextRegion getCompletionRegion(int documentPosition, Node domnode) {
+		if (domnode == null) {
+			return null;
+		}
+
+		ITextRegion region = null;
+		int offset = documentPosition;
+		IStructuredDocumentRegion flatNode = null;
+		IDOMNode node = (IDOMNode) domnode;
+
+		if (node.getNodeType() == Node.DOCUMENT_NODE) {
+			if (node.getStructuredDocument().getLength() == 0) {
+				return null;
+			}
+			ITextRegion result = node.getStructuredDocument().getRegionAtCharacterOffset(offset).getRegionAtCharacterOffset(offset);
+			while (result == null) {
+				offset--;
+				result = node.getStructuredDocument().getRegionAtCharacterOffset(offset).getRegionAtCharacterOffset(offset);
+			}
+			return result;
+		}
+
+		IStructuredDocumentRegion startTag = node.getStartStructuredDocumentRegion();
+		IStructuredDocumentRegion endTag = node.getEndStructuredDocumentRegion();
+
+		// Determine if the offset is within the start
+		// IStructuredDocumentRegion, end IStructuredDocumentRegion, or
+		// somewhere within the Node's XML content.
+		if ((startTag != null) && (startTag.getStartOffset() <= offset) && (offset < startTag.getStartOffset() + startTag.getLength())) {
+			flatNode = startTag;
+		}
+		else if ((endTag != null) && (endTag.getStartOffset() <= offset) && (offset < endTag.getStartOffset() + endTag.getLength())) {
+			flatNode = endTag;
+		}
+
+		if (flatNode != null) {
+			// the offset is definitely within the start or end tag, continue
+			// on and find the region
+			region = getCompletionRegion(offset, flatNode);
+		}
+		else {
+			// the docPosition is neither within the start nor the end, so it
+			// must be content
+			flatNode = node.getStructuredDocument().getRegionAtCharacterOffset(offset);
+			// (pa) ITextRegion refactor
+			// if (flatNode.contains(documentPosition)) {
+			if ((flatNode.getStartOffset() <= documentPosition) && (flatNode.getEndOffset() >= documentPosition)) {
+				// we're interesting in completing/extending the previous
+				// IStructuredDocumentRegion if the current
+				// IStructuredDocumentRegion isn't plain content or if it's
+				// preceded by an orphan '<'
+				if ((offset == flatNode.getStartOffset()) &&
+						(flatNode.getPrevious() != null) &&
+						(((flatNode.getRegionAtCharacterOffset(documentPosition) != null) &&
+								(flatNode.getRegionAtCharacterOffset(documentPosition).getType() != DOMRegionContext.XML_CONTENT)) ||
+								(flatNode.getPrevious().getLastRegion().getType() == DOMRegionContext.XML_TAG_OPEN) ||
+								(flatNode.getPrevious().getLastRegion().getType() == DOMRegionContext.XML_END_TAG_OPEN))) {
+					
+					// Is the region also the start of the node? If so, the
+					// previous IStructuredDocumentRegion is
+					// where to look for a useful region.
+					region = flatNode.getPrevious().getLastRegion();
+				}
+				else if (flatNode.getEndOffset() == documentPosition) {
+					region = flatNode.getLastRegion();
+				}
+				else {
+					region = flatNode.getFirstRegion();
+				}
+			}
+			else {
+				// catch end of document positions where the docPosition isn't
+				// in a IStructuredDocumentRegion
+				region = flatNode.getLastRegion();
+			}
+		}
+
+		return region;
+	}
+
+	private int getElementPosition(Node child) {
+		Node parent = child.getParentNode();
+		if (parent == null) {
+			return 0;
+		}
+
+		NodeList children = parent.getChildNodes();
+		if (children == null) {
+			return 0;
+		}
+		int count = 0;
+
+		for (int i = 0; i < children.getLength(); i++) {
+			if (children.item(i) == child) {
+				return count;
+			}
+			else {
+				// if (children.item(i).getNodeType() == Node.ELEMENT_NODE)
+				count++;
+			}
+		}
+		return 0;
+	}
+
+	private String getMatchString(IStructuredDocumentRegion parent, ITextRegion aRegion, int offset) {
+		if ((aRegion == null) || isCloseRegion(aRegion)) {
+			return ""; //$NON-NLS-1$
+		}
+		String matchString = null;
+		String regionType = aRegion.getType();
+		if ((regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_EQUALS) || (regionType == DOMRegionContext.XML_TAG_OPEN) || (offset > parent.getStartOffset(aRegion) + aRegion.getTextLength())) {
+			matchString = ""; //$NON-NLS-1$
+		}
+		else if (regionType == DOMRegionContext.XML_CONTENT) {
+			matchString = ""; //$NON-NLS-1$
+		}
+		else {
+			if ((parent.getText(aRegion).length() > 0) && (parent.getStartOffset(aRegion) < offset)) {
+				matchString = parent.getText(aRegion).substring(0, offset - parent.getStartOffset(aRegion));
+			}
+			else {
+				matchString = ""; //$NON-NLS-1$
+			}
+		}
+		return matchString;
+	}
+
+	private ITextRegion getNameRegion(IStructuredDocumentRegion flatNode) {
+		if (flatNode == null) {
+			return null;
+		}
+		Iterator regionList = flatNode.getRegions().iterator();
+		while (regionList.hasNext()) {
+			ITextRegion region = (ITextRegion) regionList.next();
+			if (isNameRegion(region)) {
+				return region;
+			}
+		}
+		return null;
+	}
+
+	private boolean isCloseRegion(ITextRegion region) {
+		String type = region.getType();
+		return ((type == DOMRegionContext.XML_PI_CLOSE) ||
+				(type == DOMRegionContext.XML_TAG_CLOSE) ||
+				(type == DOMRegionContext.XML_EMPTY_TAG_CLOSE) ||
+				(type == DOMRegionContext.XML_CDATA_CLOSE) ||
+				(type == DOMRegionContext.XML_COMMENT_CLOSE) ||
+				(type == DOMRegionContext.XML_ATTLIST_DECL_CLOSE) ||
+				(type == DOMRegionContext.XML_ELEMENT_DECL_CLOSE) ||
+				(type == DOMRegionContext.XML_DOCTYPE_DECLARATION_CLOSE) ||
+				(type == DOMJSPRegionContextsPrivateCopy.JSP_CLOSE) ||
+				(type == DOMJSPRegionContextsPrivateCopy.JSP_COMMENT_CLOSE) ||
+				(type.equals(DOMJSPRegionContextsPrivateCopy.JSP_DIRECTIVE_CLOSE)) ||
+				(type == DOMRegionContext.XML_DECLARATION_CLOSE));
+	}
+
+	private boolean isNameRegion(ITextRegion region) {
+		String type = region.getType();
+		return ((type == DOMRegionContext.XML_TAG_NAME) ||
+				(type == DOMJSPRegionContextsPrivateCopy.JSP_DIRECTIVE_NAME) ||
+				(type == DOMRegionContext.XML_ELEMENT_DECL_NAME) ||
+				(type == DOMRegionContext.XML_DOCTYPE_NAME) ||
+				(type == DOMRegionContext.XML_ATTLIST_DECL_NAME) ||
+				(type == DOMJSPRegionContextsPrivateCopy.JSP_ROOT_TAG_NAME) ||
+				type.equals(DOMJSPRegionContextsPrivateCopy.JSP_DIRECTIVE_NAME));
+	}
+	
+	/**
+	 * StructuredTextViewer must be set before using this.
+	 */
+	private IStructuredDocumentRegion getStructuredDocumentRegion(int pos) {
+		return ContentAssistUtils.getStructuredDocumentRegion(fTextViewer, pos);
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/AbstractXMLModelQueryCompletionProposalComputer.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/AbstractXMLModelQueryCompletionProposalComputer.java
new file mode 100644
index 0000000..303104a
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/AbstractXMLModelQueryCompletionProposalComputer.java
@@ -0,0 +1,1855 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.contentassist;
+
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Vector;
+
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+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.ITextRegionList;
+import org.eclipse.wst.sse.core.internal.util.Debug;
+import org.eclipse.wst.sse.ui.contentassist.CompletionProposalInvocationContext;
+import org.eclipse.wst.sse.ui.internal.contentassist.ContentAssistUtils;
+import org.eclipse.wst.sse.ui.internal.contentassist.CustomCompletionProposal;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMEntityDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.contentmodel.basic.CMNamedNodeMapImpl;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQueryAction;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.DOMNamespaceHelper;
+import org.eclipse.wst.xml.core.internal.document.AttrImpl;
+import org.eclipse.wst.xml.core.internal.modelquery.ModelQueryUtil;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+import org.eclipse.wst.xml.ui.internal.XMLUIPlugin;
+import org.eclipse.wst.xml.ui.internal.editor.CMImageUtil;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImageHelper;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImages;
+import org.eclipse.wst.xml.ui.internal.preferences.XMLUIPreferenceNames;
+import org.eclipse.wst.xml.ui.internal.taginfo.MarkupTagInfoProvider;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+
+/**
+ * <p>Implementation of an {@link AbstractXMLCompletionProposalComputer} that uses {@link ModelQuery}s
+ * to make its proposals.</p>
+ * 
+ * @base org.eclipse.wst.xml.ui.internal.contentassist.AbstractContentAssistProcessor
+ */
+public abstract class AbstractXMLModelQueryCompletionProposalComputer extends AbstractXMLCompletionProposalComputer {
+	
+	private static MarkupTagInfoProvider infoProvider = new MarkupTagInfoProvider();
+	
+	/**
+	 * <p>Default constructor</p>
+	 */
+	public AbstractXMLModelQueryCompletionProposalComputer() {
+	}
+	
+	/**
+	 * <p>default is to do nothing</p>
+	 * 
+	 * @see org.eclipse.wst.sse.ui.contentassist.ICompletionProposalComputer#sessionEnded()
+	 */
+	public void sessionEnded() {
+		//default is to do nothing
+	}
+
+	/**
+	 * <p>default is to do nothing</p>
+	 * 
+	 * @see org.eclipse.wst.sse.ui.contentassist.ICompletionProposalComputer#sessionStarted()
+	 */
+	public void sessionStarted() {
+		//default is to do nothing
+	}
+	
+	/**
+	 * @return {@link XMLContentModelGenerator} used to generate proposals
+	 */
+	protected abstract XMLContentModelGenerator getContentGenerator();
+	
+	/**
+	 * <p>Given a {@link CMNode} generated by a model query should decide if the
+	 * action is valid for this implementation of the model query proposal computer</p>
+	 * 
+	 * <p>This is needed because {@link ModelQuery}s return a lot of {@link CMNode}s that
+	 * can come from multiple sources and a particular computer may not want to propose
+	 * all of the actions as content assist proposals</p>
+	 * 
+	 * @param action {@link CMNode} to decide if it is valid as a result
+	 * for this model query proposal computer
+	 * 
+	 * @return <code>true</code> if the given {@link CMNode} is valid for this
+	 * computer, <code>false</code> otherwise
+	 */
+	protected abstract boolean validModelQueryNode(CMNode node);
+	
+	protected void addAttributeNameProposals(
+			ContentAssistRequest contentAssistRequest,
+			CompletionProposalInvocationContext context) {
+		
+		IDOMNode node = (IDOMNode) contentAssistRequest.getNode();
+		IStructuredDocumentRegion sdRegion = contentAssistRequest.getDocumentRegion();
+		// retrieve the list of attributes
+		CMElementDeclaration elementDecl = getCMElementDeclaration(node);
+		if (elementDecl != null) {
+			CMNamedNodeMapImpl attributes = new CMNamedNodeMapImpl(elementDecl.getAttributes());
+			addModelQueryAttributeDeclarations(node, elementDecl,attributes);
+
+			String matchString = contentAssistRequest.getMatchString();
+			int cursorOffset = context.getInvocationOffset();
+			// check whether an attribute really exists for the replacement
+			// offsets AND if it possesses a value
+			boolean attrAtLocationHasValue = false;
+			boolean proposalNeedsSpace = false;
+			NamedNodeMap attrs = node.getAttributes();
+			for (int i = 0; i < attrs.getLength(); i++) {
+				AttrImpl existingAttr = (AttrImpl) attrs.item(i);
+				ITextRegion name = existingAttr.getNameRegion();
+				
+				if ((sdRegion.getStartOffset(name) <= contentAssistRequest.getReplacementBeginPosition()) &&
+						(sdRegion.getStartOffset(name) + name.getLength() >= contentAssistRequest.getReplacementBeginPosition() + contentAssistRequest.getReplacementLength()) &&
+						(existingAttr.getValueRegion() != null)) {
+					// selected region is attribute name
+					if (cursorOffset >= sdRegion.getStartOffset(name) && contentAssistRequest.getReplacementLength() != 0)
+						attrAtLocationHasValue = true;
+					// propose new attribute, cursor is at the start of another attribute name
+					else if (cursorOffset == sdRegion.getStartOffset(name))
+						proposalNeedsSpace = true;
+					break;
+				}
+			}
+
+			// only add proposals for the attributes whose names begin with the matchstring
+			if (attributes != null) {
+				for (int i = 0; i < attributes.getLength(); i++) {
+					CMAttributeDeclaration attrDecl = (CMAttributeDeclaration) attributes.item(i);
+
+					if(validModelQueryNode(attrDecl)) {
+						int isRequired = 0;
+						if (attrDecl.getUsage() == CMAttributeDeclaration.REQUIRED) {
+							isRequired = XMLRelevanceConstants.R_REQUIRED;
+						}
+	
+						boolean showAttribute = true;
+						showAttribute = showAttribute && beginsWith(getRequiredName(node, attrDecl), matchString.trim());
+						AttrImpl attr = (AttrImpl) node.getAttributes().getNamedItem(getRequiredName(node, attrDecl));
+						ITextRegion nameRegion = attr != null ? attr.getNameRegion() : null;
+						// nameRegion.getEndOffset() + 1 is required to allow for
+						// matches against the full name of an existing Attr
+						showAttribute = showAttribute && ((attr == null) ||
+								((nameRegion != null) &&
+										(sdRegion.getStartOffset(nameRegion) <
+											contentAssistRequest.getReplacementBeginPosition()) &&
+										(sdRegion.getStartOffset(nameRegion) + nameRegion.getLength() >=
+											(contentAssistRequest.getReplacementBeginPosition() +
+											contentAssistRequest.getReplacementLength()) )));
+						if (showAttribute) {
+							//get the proposal image
+							Image attrImage = CMImageUtil.getImage(attrDecl);
+							if (attrImage == null) {
+								if (isRequired > 0) {
+									attrImage = this.getRequiredAttributeImage();
+								} else {
+									attrImage = this.getNotRequiredAttributeImage();
+								}
+							}
+	
+							String proposedText = null;
+							String proposedInfo = getAdditionalInfo(elementDecl, attrDecl);
+							CustomCompletionProposal proposal = null;
+							// attribute is at this location and already exists
+							if (attrAtLocationHasValue) {
+								// only propose the name
+								proposedText = getRequiredName(node, attrDecl);
+								proposal = new CustomCompletionProposal(
+										proposedText, contentAssistRequest.getReplacementBeginPosition(),
+										contentAssistRequest.getReplacementLength(), proposedText.length(),
+										attrImage, proposedText, null, proposedInfo,
+										XMLRelevanceConstants.R_XML_ATTRIBUTE_NAME + isRequired, true);
+							}
+							// no attribute exists or is elsewhere, generate
+							// minimally
+							else {
+								Attr existingAttrNode = (Attr) node.getAttributes().getNamedItem(getRequiredName(node, attrDecl));
+								String value = null;
+								if (existingAttrNode != null) {
+									value = existingAttrNode.getNodeValue();
+								}
+								if ((value != null) && (value.length() > 0)) {
+									proposedText = getRequiredName(node, attrDecl);
+								}
+								else {
+									proposedText = getRequiredText(node, attrDecl);
+								}
+								if (proposalNeedsSpace)
+									proposedText += " "; //$NON-NLS-1$
+								proposal = new CustomCompletionProposal(proposedText,
+										contentAssistRequest.getReplacementBeginPosition(),
+										contentAssistRequest.getReplacementLength(),
+										attrDecl.getNodeName().length() + 2, attrImage,
+								// if the value isn't empty (no empty set of quotes), show it
+								// BUG 203494, content strings may have "", but not be empty
+								// An empty string is when there's no content between double quotes
+								// and there is no single quote that may be encasing a double quote
+										((proposedText.lastIndexOf('\"') - proposedText.indexOf('\"') ==  1 &&
+												proposedText.indexOf('\'') == -1)) ? getRequiredName(node, attrDecl) : proposedText,
+										null, proposedInfo, XMLRelevanceConstants.R_XML_ATTRIBUTE_NAME + isRequired);
+							}
+							contentAssistRequest.addProposal(proposal);
+						}
+					}
+				}
+			}
+		}
+		else {
+			setErrorMessage(NLS.bind(XMLUIMessages.Element__is_unknown, (new Object[]{node.getNodeName()})));
+		}
+	}
+	
+	protected void addAttributeValueProposals(
+			ContentAssistRequest contentAssistRequest,
+			CompletionProposalInvocationContext context) {
+		
+		IDOMNode node = (IDOMNode) contentAssistRequest.getNode();
+
+		// Find the attribute region and name for which this position should
+		// have a value proposed
+		IStructuredDocumentRegion open = node.getFirstStructuredDocumentRegion();
+		ITextRegionList openRegions = open.getRegions();
+		int i = openRegions.indexOf(contentAssistRequest.getRegion());
+		if (i < 0) {
+			return;
+		}
+		ITextRegion nameRegion = null;
+		while (i >= 0) {
+			nameRegion = openRegions.get(i--);
+			if (nameRegion.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) {
+				break;
+			}
+		}
+
+		// the name region is REQUIRED to do anything useful
+		if (nameRegion != null) {
+			// Retrieve the declaration
+			CMElementDeclaration elementDecl = getCMElementDeclaration(node);
+
+			// String attributeName = nameRegion.getText();
+			String attributeName = open.getText(nameRegion);
+
+			CMAttributeDeclaration attrDecl = null;
+
+			// No CMElementDeclaration means no attribute metadata, but retrieve the
+			// declaration for the attribute otherwise
+			if (elementDecl != null) {
+				CMNamedNodeMapImpl allAttributes = new CMNamedNodeMapImpl(elementDecl.getAttributes()) {
+					private Map caseInsensitive;
+					
+					private Map getCaseInsensitiveMap() {
+						if(caseInsensitive == null)
+							caseInsensitive = new HashMap();
+						return caseInsensitive;
+					}
+
+					public CMNode getNamedItem(String name) {
+						CMNode node = super.getNamedItem(name);
+						if (node == null) {
+							node = (CMNode) getCaseInsensitiveMap().get(name.toLowerCase(Locale.US));
+						}
+						return node;
+					}
+
+					public void put(CMNode cmNode) {
+						super.put(cmNode);
+						getCaseInsensitiveMap().put(cmNode.getNodeName().toLowerCase(Locale.US), cmNode);
+					}
+				};
+				this.addModelQueryAttributeDeclarations(node, elementDecl, allAttributes);
+
+				String noprefixName = DOMNamespaceHelper.getUnprefixedName(attributeName);
+				if (allAttributes != null) {
+					attrDecl = (CMAttributeDeclaration) allAttributes.getNamedItem(attributeName);
+					if (attrDecl == null) {
+						attrDecl = (CMAttributeDeclaration) allAttributes.getNamedItem(noprefixName);
+					}
+				}
+				if (attrDecl == null) {
+					setErrorMessage(XMLUIMessages.No_known_attribute__UI_ + attributeName);
+				}
+			}
+
+			String currentValue = node.getAttributes().getNamedItem(attributeName).getNodeValue();
+			String proposedInfo = null;
+			//get proposal image
+			Image image = CMImageUtil.getImage(attrDecl);
+			if (image == null) {
+				if ((attrDecl != null) && (attrDecl.getUsage() == CMAttributeDeclaration.REQUIRED)) {
+					image = this.getRequiredAttributeImage();
+				} else {
+					image = this.getNotRequiredAttributeImage();
+				}
+			}
+
+			if ((attrDecl != null) && (attrDecl.getAttrType() != null)) {
+				// attribute is known, prompt with values from the declaration
+				proposedInfo = getAdditionalInfo(elementDecl, attrDecl);
+				List possibleValues = getPossibleDataTypeValues(node, attrDecl);
+				String defaultValue = attrDecl.getAttrType().getImpliedValue();
+				String qualifiedDelimiter = (String) attrDecl.getProperty("qualified-delimiter"); //$NON-NLS-1$
+				if (possibleValues.size() > 0 || defaultValue != null) {
+					// ENUMERATED VALUES
+					String matchString = contentAssistRequest.getMatchString();
+					if (matchString == null) {
+						matchString = ""; //$NON-NLS-1$
+					}
+					if ((matchString.length() > 0) && (matchString.startsWith("\"") || matchString.startsWith("'"))) { //$NON-NLS-1$ //$NON-NLS-2$
+						matchString = matchString.substring(1);
+					}
+					boolean currentValid = false;
+
+					//create suggestions for enumerated values
+					int rOffset = contentAssistRequest.getReplacementBeginPosition();
+					int rLength = contentAssistRequest.getReplacementLength();
+					for (Iterator j = possibleValues.iterator(); j.hasNext();) {
+						String possibleValue = (String) j.next();
+						String alternateMatch = null;
+						if (qualifiedDelimiter != null) {
+							int delimiter = possibleValue.lastIndexOf(qualifiedDelimiter);
+							if (delimiter >= 0 && delimiter < possibleValue.length() - 1) {
+								alternateMatch = possibleValue.substring(delimiter + 1);
+							}
+						}
+						if(!possibleValue.equals(defaultValue)) {
+							currentValid = currentValid || possibleValue.equals(currentValue);
+							if ((matchString.length() == 0) || possibleValue.startsWith(matchString)) {
+								String rString = "\"" + possibleValue + "\""; //$NON-NLS-1$ //$NON-NLS-2$
+								alternateMatch = "\"" + alternateMatch; //$NON-NLS-1$
+								CustomCompletionProposal proposal = new CustomCompletionProposal(
+										rString, rOffset, rLength, possibleValue.length() + 1,
+										XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_ENUM),
+										rString, alternateMatch, null, proposedInfo, XMLRelevanceConstants.R_XML_ATTRIBUTE_VALUE, true);
+								contentAssistRequest.addProposal(proposal);
+							}
+						}
+					}
+					if(defaultValue != null && ((matchString.length() == 0) || defaultValue.startsWith(matchString))) {
+						String rString = "\"" + defaultValue + "\""; //$NON-NLS-1$ //$NON-NLS-2$
+						CustomCompletionProposal proposal = new CustomCompletionProposal(
+								rString, rOffset, rLength, defaultValue.length() + 1,
+								XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_DEFAULT),
+								rString, null, proposedInfo, XMLRelevanceConstants.R_XML_ATTRIBUTE_VALUE);
+						contentAssistRequest.addProposal(proposal);
+					}
+				}
+				else if (((attrDecl.getUsage() == CMAttributeDeclaration.FIXED) ||
+						(attrDecl.getAttrType().getImpliedValueKind() == CMDataType.IMPLIED_VALUE_FIXED)) &&
+						(attrDecl.getAttrType().getImpliedValue() != null)) {
+					
+					// FIXED values
+					String value = attrDecl.getAttrType().getImpliedValue();
+					if ((value != null) && (value.length() > 0)) {
+						String rValue = "\"" + value + "\"";//$NON-NLS-2$//$NON-NLS-1$
+						CustomCompletionProposal proposal = new CustomCompletionProposal(
+								rValue, contentAssistRequest.getReplacementBeginPosition(),
+								contentAssistRequest.getReplacementLength(), rValue.length() + 1,
+								image, rValue, null, proposedInfo,
+								XMLRelevanceConstants.R_XML_ATTRIBUTE_VALUE);
+						contentAssistRequest.addProposal(proposal);
+						if ((currentValue.length() > 0) && !value.equals(currentValue)) {
+							rValue = "\"" + currentValue + "\""; //$NON-NLS-2$//$NON-NLS-1$
+							proposal = new CustomCompletionProposal(rValue, contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), rValue.length() + 1, image, rValue, null, proposedInfo, XMLRelevanceConstants.R_XML_ATTRIBUTE_VALUE);
+							contentAssistRequest.addProposal(proposal);
+						}
+					}
+				}
+			}
+			else {
+				// unknown attribute, so supply nice empty values
+				proposedInfo = getAdditionalInfo(null, elementDecl);
+				CustomCompletionProposal proposal = null;
+				if ((currentValue != null) && (currentValue.length() > 0)) {
+					String rValue = "\"" + currentValue + "\""; //$NON-NLS-2$//$NON-NLS-1$
+					proposal = new CustomCompletionProposal(rValue,
+							contentAssistRequest.getReplacementBeginPosition(),
+							contentAssistRequest.getReplacementLength(), 1, image,
+							rValue, null, proposedInfo,
+							XMLRelevanceConstants.R_XML_ATTRIBUTE_VALUE);
+					contentAssistRequest.addProposal(proposal);
+				}
+			}
+		}
+		else {
+			setErrorMessage(XMLUIMessages.Content_Assist_not_availab_UI_);
+		}
+	}
+	
+	protected void addCommentProposal(
+			ContentAssistRequest contentAssistRequest,
+			CompletionProposalInvocationContext context) {
+		
+		contentAssistRequest.addProposal(new CustomCompletionProposal("<!--  -->", //$NON-NLS-1$
+				contentAssistRequest.getReplacementBeginPosition(),
+				contentAssistRequest.getReplacementLength(), 5,
+				XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_COMMENT),
+				NLS.bind(XMLUIMessages.Comment__, (new Object[]{" <!--  -->"})), //$NON-NLS-1$
+				null, null, XMLRelevanceConstants.R_COMMENT));
+	}
+	
+	
+
+	/**
+	 * Add the proposals for the name in an end tag
+	 */
+	protected void addEndTagNameProposals(ContentAssistRequest contentAssistRequest,
+			CompletionProposalInvocationContext context) {
+
+		if (contentAssistRequest.getStartOffset() + contentAssistRequest.getRegion().getTextLength() < contentAssistRequest.getReplacementBeginPosition()) {
+			CustomCompletionProposal proposal = new CustomCompletionProposal(">", //$NON-NLS-1$
+						contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), 1, XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TAG_GENERIC), NLS.bind(XMLUIMessages.Close_with__, (new Object[]{" '>'"})), //$NON-NLS-1$
+						null, null, XMLRelevanceConstants.R_END_TAG_NAME);
+			contentAssistRequest.addProposal(proposal);
+		}
+		else {
+			Node aNode = contentAssistRequest.getNode();
+			String matchString = contentAssistRequest.getMatchString();
+			if (matchString.startsWith("</")) { //$NON-NLS-1$
+				matchString = matchString.substring(2);
+			}
+			while (aNode != null) {
+				if (aNode.getNodeType() == Node.ELEMENT_NODE) {
+					if (aNode.getNodeName().startsWith(matchString)) {
+						IDOMNode aXMLNode = (IDOMNode) aNode;
+						CMElementDeclaration ed = getCMElementDeclaration(aNode);
+						//declaration must be valid for this computer to make proposal
+						if ((aXMLNode.getEndStructuredDocumentRegion() == null) && (ed == null || (validModelQueryNode(ed) && ed.getContentType() != CMElementDeclaration.EMPTY))) {
+							String replacementText = aNode.getNodeName();
+							String displayText = replacementText;
+							String proposedInfo = (ed != null) ? getAdditionalInfo(null, ed) : null;
+							if(!contentAssistRequest.getDocumentRegion().isEnded()) {
+								replacementText += ">"; //$NON-NLS-1$
+							}
+							CustomCompletionProposal proposal = null;
+							// double check to see if the region acted upon is
+							// a tag name; replace it if so
+							Image image = CMImageUtil.getImage(ed);
+							if (image == null) {
+								image = this.getGenericTagImage();
+							}
+							if (contentAssistRequest.getRegion().getType() == DOMRegionContext.XML_TAG_NAME) {
+								proposal = new CustomCompletionProposal(
+										replacementText, contentAssistRequest.getStartOffset(),
+										contentAssistRequest.getRegion().getTextLength(),
+										replacementText.length(), image, displayText, null,
+										proposedInfo, XMLRelevanceConstants.R_END_TAG_NAME);
+							}
+							else {
+								proposal = new CustomCompletionProposal(
+										replacementText,
+										contentAssistRequest.getReplacementBeginPosition(),
+										contentAssistRequest.getReplacementLength(),
+										replacementText.length(), image,
+										NLS.bind(XMLUIMessages.Close_with__,
+												(new Object[]{"'" + displayText + "'"})), //$NON-NLS-1$ //$NON-NLS-2$
+										null, proposedInfo, XMLRelevanceConstants.R_END_TAG_NAME);
+							}
+							contentAssistRequest.addProposal(proposal);
+						}
+					}
+				}
+				aNode = aNode.getParentNode();
+			}
+		}
+	}
+
+	/**
+	 * Prompt for end tags to a non-empty Node that hasn't ended Handles these
+	 * cases: <br>
+	 * <tagOpen>| <br>
+	 * <tagOpen>< |<br>
+	 * <tagOpen></ |
+	 * 
+	 * @param contentAssistRequest
+	 */
+	protected void addEndTagProposals(
+			ContentAssistRequest contentAssistRequest,
+			CompletionProposalInvocationContext context) {
+		
+		IDOMNode node = (IDOMNode) contentAssistRequest.getParent();
+
+		if (isCommentNode(node)) {
+			// loop and find non comment node parent
+			while ((node != null) && isCommentNode(node)) {
+				node = (IDOMNode) node.getParentNode();
+			}
+		}
+
+		// node is already closed
+		if (node.isClosed()) {
+			// loop and find non comment unclose node parent
+			while ((node != null) && node.isClosed()) {
+				node = (IDOMNode) node.getParentNode();
+			}
+		}
+		// there were no unclosed tags
+		if (node == null) {
+			return;
+		}
+
+		// data to create a CustomCompletionProposal
+		String replaceText = node.getNodeName() + ">"; //$NON-NLS-1$
+		int replaceBegin = contentAssistRequest.getReplacementBeginPosition();
+		int replaceLength = contentAssistRequest.getReplacementLength();
+		int cursorOffset = node.getNodeName().length() + 1;
+		String displayString = ""; //$NON-NLS-1$
+		String proposedInfo = ""; //$NON-NLS-1$
+		Image image = this.getGenericTagImage();
+
+		setErrorMessage(null);
+		boolean addProposal = false;
+
+		if (node.getNodeType() == Node.ELEMENT_NODE) {
+			// ////////////////////////////////////////////////////////////////////////////////////
+			IStructuredDocument sDoc = (IStructuredDocument) context.getDocument();
+			IStructuredDocumentRegion xmlEndTagOpen = sDoc.getRegionAtCharacterOffset(contentAssistRequest.getReplacementBeginPosition());
+			// skip backward to "<", "</", or the (unclosed) start tag, null if not found
+			String type = ""; //$NON-NLS-1$
+			while ((xmlEndTagOpen != null) &&
+					((type = xmlEndTagOpen.getType()) != DOMRegionContext.XML_END_TAG_OPEN) &&
+					(type != DOMRegionContext.XML_TAG_CLOSE) && !needsEndTag(xmlEndTagOpen, context) &&
+					(type != DOMRegionContext.XML_TAG_OPEN)) {
+				
+				xmlEndTagOpen = xmlEndTagOpen.getPrevious();
+			}
+
+			if (xmlEndTagOpen == null) {
+				return;
+			}
+
+			node = (IDOMNode) node.getModel().getIndexedRegion(xmlEndTagOpen.getStartOffset());
+			node = (IDOMNode) node.getParentNode();
+
+			if (isStartTag(xmlEndTagOpen)) {
+				// this is the case for a start tag w/out end tag
+				// eg:
+				// <p>
+				// <% String test = "test"; %>
+				// |
+				if (needsEndTag(xmlEndTagOpen, context)) {
+					String tagName = getTagName(xmlEndTagOpen);
+					xmlEndTagOpen.getTextEndOffset();
+					replaceLength = 0;
+					replaceText = "</" + tagName + ">"; //$NON-NLS-1$ //$NON-NLS-2$ $NON-NLS-2$
+					cursorOffset = tagName.length() + 3;
+					displayString = NLS.bind(XMLUIMessages.End_with__, (new Object[]{tagName}));
+					addProposal = true;
+				}
+			}
+			else if (type == DOMRegionContext.XML_END_TAG_OPEN) {
+				// this is the case for: <tag> </ |
+				// possibly <tag> </ |<anotherTag>
+				// should only be replacing white space...
+				replaceLength = (replaceBegin > xmlEndTagOpen.getTextEndOffset()) ? replaceBegin - xmlEndTagOpen.getTextEndOffset() : 0;
+				replaceText = node.getNodeName() + ">"; //$NON-NLS-1$
+				cursorOffset = replaceText.length();
+				replaceBegin = xmlEndTagOpen.getTextEndOffset();
+				displayString = NLS.bind(XMLUIMessages.End_with_, (new Object[]{node.getNodeName()}));
+				addProposal = true;
+			}
+			else if (type == DOMRegionContext.XML_TAG_OPEN) {
+				// this is the case for: <tag> < |
+				replaceText = "/" + node.getNodeName() + ">"; //$NON-NLS-1$ //$NON-NLS-2$ $NON-NLS-2$
+				cursorOffset = replaceText.length();
+
+				// should only be replacing white space...
+				replaceLength = (replaceBegin > xmlEndTagOpen.getTextEndOffset()) ? replaceBegin - xmlEndTagOpen.getTextEndOffset() : 0;
+				replaceBegin = xmlEndTagOpen.getTextEndOffset();
+				displayString = NLS.bind(XMLUIMessages.End_with_, (new Object[]{"/" + node.getNodeName()})); //$NON-NLS-1$
+				addProposal = true;
+			}
+		}
+		// ////////////////////////////////////////////////////////////////////////////////////
+		// sometimes the node is not null, but
+		// getNodeValue() is null, put in a null check
+		else if ((node.getNodeValue() != null) && (node.getNodeValue().indexOf("</") != -1)) { //$NON-NLS-1$
+			// the case where "</" is started, but the nodes comes in as a
+			// text node (instead of element)
+			// like this: <tag> </|
+			Node parent = node.getParentNode();
+			if ((parent != null) && (parent.getNodeType() != Node.DOCUMENT_NODE)) {
+				replaceText = parent.getNodeName() + ">"; //$NON-NLS-1$
+				cursorOffset = replaceText.length();
+				displayString = NLS.bind(XMLUIMessages.End_with__, (new Object[]{parent.getNodeName()}));
+				setErrorMessage(null);
+				addProposal = true;
+			}
+		}
+		// ////////////////////////////////////////////////////////////////////////////////////
+		else if (node.getNodeType() == Node.DOCUMENT_NODE) {
+			setErrorMessage(XMLUIMessages.Content_Assist_not_availab_UI_);
+		}
+		if (addProposal == true) {
+			CustomCompletionProposal proposal = new CustomCompletionProposal(replaceText, replaceBegin, replaceLength, cursorOffset, image, displayString, null, proposedInfo, XMLRelevanceConstants.R_END_TAG);
+			contentAssistRequest.addProposal(proposal);
+		}
+	}
+	
+	protected void addEntityProposals(
+			ContentAssistRequest contentAssistRequest,
+			ITextRegion completionRegion, IDOMNode treeNode,
+			CompletionProposalInvocationContext context) {
+		
+		ICompletionProposal[] eps = computeEntityReferenceProposals(completionRegion,
+				treeNode, context);
+		for (int i = 0; (eps != null) && (i < eps.length); i++) {
+			contentAssistRequest.addProposal(eps[i]);
+		}
+	}
+	
+	protected void addEntityProposals(Vector proposals, Properties map,
+			String key, int nodeOffset, IStructuredDocumentRegion sdRegion,
+			ITextRegion completionRegion,
+			CompletionProposalInvocationContext context) {
+		
+		if (map == null) {
+			return;
+		}
+		String entityName = ""; //$NON-NLS-1$
+		String entityValue = ""; //$NON-NLS-1$
+		Image entityIcon = this.getEntityReferenceImage();
+		String replacementText = ""; //$NON-NLS-1$
+		String displayString = ""; //$NON-NLS-1$
+		Enumeration keys = map.keys();
+
+		while ((keys != null) && keys.hasMoreElements()) {
+			entityName = (String) keys.nextElement();
+			entityValue = map.getProperty(entityName);
+			// filter based on partial entity string...
+			if (entityName.toLowerCase().startsWith(key.toLowerCase()) || key.trim().equals("")) //$NON-NLS-1$
+			{
+				// figure out selection...if text is selected, add it to
+				// selection length
+				int selectionLength = nodeOffset;
+				if (context.getViewer() != null) {
+					selectionLength += context.getViewer().getSelectedRange().y;
+				}
+				// create a new proposal for entity string...
+				replacementText = "&" + entityName + ";"; //$NON-NLS-1$ //$NON-NLS-2$ 
+				displayString = "&" + entityName + "; (" + entityValue + ")"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+				ICompletionProposal cp = new CustomCompletionProposal(replacementText, sdRegion.getStartOffset(completionRegion), selectionLength, replacementText.length(), entityIcon, displayString, null, null, XMLRelevanceConstants.R_ENTITY);
+				if (cp != null) {
+					proposals.add(cp);
+				}
+			}
+		}
+	}
+	
+	protected void addPCDATAProposal(String nodeName,
+			ContentAssistRequest contentAssistRequest,
+			CompletionProposalInvocationContext context) {
+		
+		CustomCompletionProposal proposal = new CustomCompletionProposal("<![CDATA[]]>", //$NON-NLS-1$
+					contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), 9, XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_CDATASECTION), "CDATA Section", //$NON-NLS-1$
+					null, null, XMLRelevanceConstants.R_CDATA);
+		contentAssistRequest.addProposal(proposal);
+
+		proposal = new CustomCompletionProposal(nodeName, contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), nodeName.length(), XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TXTEXT), "#PCDATA", //$NON-NLS-1$
+					null, null, XMLRelevanceConstants.R_CDATA);
+		contentAssistRequest.addProposal(proposal);
+	}
+	
+	protected void addStartDocumentProposals(
+			ContentAssistRequest contentAssistRequest,
+			CompletionProposalInvocationContext context) {
+		
+		//determine if XMLPI is first element
+		Node aNode = contentAssistRequest.getNode();
+		Document owningDocument = aNode.getOwnerDocument();
+		Node first = owningDocument.getFirstChild();
+		boolean xmlpiIsFirstElement = ((first != null) && (first.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE));
+		
+		// make sure xmlpi is root element don't want doctype proposal if XMLPI isn't first element...
+		if (xmlpiIsFirstElement && (owningDocument.getDoctype() == null) &&
+				isCursorAfterXMLPI(contentAssistRequest)) {
+			
+			addDocTypeProposal(contentAssistRequest, context);
+		}
+	}
+	
+	/**
+	 * Close an unclosed start tag
+	 */
+	protected void addTagCloseProposals(
+			ContentAssistRequest contentAssistRequest,
+			CompletionProposalInvocationContext context) {
+		
+		IDOMNode node = (IDOMNode) contentAssistRequest.getParent();
+		if (node.getNodeType() == Node.ELEMENT_NODE) {
+
+			CMElementDeclaration elementDecl = getCMElementDeclaration(node);
+			String proposedInfo = (elementDecl != null) ? getAdditionalInfo(null, elementDecl) : null;
+			int contentType = (elementDecl != null) ? elementDecl.getContentType() : CMElementDeclaration.ANY;
+			// if it's XML and content doesn't HAVE to be element, add "/>" proposal.
+			boolean endWithSlashBracket = (isXMLNode(node) && (contentType != CMElementDeclaration.ELEMENT));
+
+			//get the image
+			Image image = CMImageUtil.getImage(elementDecl);
+			if (image == null) {
+				image = this.getGenericTagImage();
+			}
+
+			// is the start tag ended properly?
+			if ((contentAssistRequest.getDocumentRegion() == node.getFirstStructuredDocumentRegion()) && !(node.getFirstStructuredDocumentRegion()).isEnded()) {
+				setErrorMessage(null);
+				// Is this supposed to be an empty tag? Note that if we can't
+				// tell, we assume it's not.
+				if ((elementDecl != null) && (elementDecl.getContentType() == CMElementDeclaration.EMPTY)) {
+					// prompt with a self-closing end character if needed
+					// this is one of the few times to ignore the length -- always insert
+					// contentAssistRequest.getReplacementLength()
+					CustomCompletionProposal proposal = new CustomCompletionProposal(
+							getContentGenerator().getStartTagClose(node, elementDecl),
+							contentAssistRequest.getReplacementBeginPosition(), 0,
+							getContentGenerator().getStartTagClose(node, elementDecl).length(), image,
+							NLS.bind(XMLUIMessages.Close_with___,(new Object[]{getContentGenerator().getStartTagClose(node, elementDecl)})),
+							null, proposedInfo, XMLRelevanceConstants.R_CLOSE_TAG);
+					contentAssistRequest.addProposal(proposal);
+				}
+				else {
+					// prompt with a close for the start tag
+					CustomCompletionProposal proposal = new CustomCompletionProposal(">", //$NON-NLS-1$
+								contentAssistRequest.getReplacementBeginPosition(),
+								// this is one of the few times to ignore the
+								// length -- always insert
+								// contentAssistRequest.getReplacementLength(),
+								0, 1, image, NLS.bind(XMLUIMessages.Close_with__, (new Object[]{" '>'"})), //$NON-NLS-1$
+								null, proposedInfo, XMLRelevanceConstants.R_CLOSE_TAG);
+					contentAssistRequest.addProposal(proposal);
+
+					// prompt with the closer for the start tag and an end tag if one is not present
+					if (node.getEndStructuredDocumentRegion() == null) {
+						// make sure tag name is actually what it thinks it
+						// is...(eg. <%@ vs. <jsp:directive)
+						IStructuredDocumentRegion sdr = contentAssistRequest.getDocumentRegion();
+						String openingTagText = (sdr != null) ? sdr.getFullText() : ""; //$NON-NLS-1$
+						if ((openingTagText != null) && (openingTagText.indexOf(node.getNodeName()) != -1)) {
+							proposal = new CustomCompletionProposal("></" + node.getNodeName() + ">", //$NON-NLS-2$//$NON-NLS-1$
+										contentAssistRequest.getReplacementBeginPosition(),
+										// this is one of the few times to
+										// ignore the length -- always insert
+										// contentAssistRequest.getReplacementLength(),
+										0, 1, image, NLS.bind(XMLUIMessages.Close_with____, (new Object[]{node.getNodeName()})), null, proposedInfo, XMLRelevanceConstants.R_CLOSE_TAG);
+							contentAssistRequest.addProposal(proposal);
+						}
+					}
+					// prompt with slash bracket "/>" incase if it's a self ending tag
+					if (endWithSlashBracket) {
+						proposal = new CustomCompletionProposal("/>", //$NON-NLS-1$
+									contentAssistRequest.getReplacementBeginPosition(),
+									// this is one of the few times to ignore
+									// the length -- always insert
+									// contentAssistRequest.getReplacementLength(),
+									0, 2, image, NLS.bind(XMLUIMessages.Close_with__, (new Object[]{" \"/>\""})), //$NON-NLS-1$
+									null, proposedInfo, XMLRelevanceConstants.R_CLOSE_TAG + 1); // +1
+						// to bring to top of list
+						contentAssistRequest.addProposal(proposal);
+					}
+				}
+			}
+			else if ((contentAssistRequest.getDocumentRegion() == node.getLastStructuredDocumentRegion()) && !node.getLastStructuredDocumentRegion().isEnded()) {
+				setErrorMessage(null);
+				// prompt with a closing end character for the end tag
+				CustomCompletionProposal proposal = new CustomCompletionProposal(">", //$NON-NLS-1$
+							contentAssistRequest.getReplacementBeginPosition(),
+							// this is one of the few times to ignore the length -- always insert
+							// contentAssistRequest.getReplacementLength(),
+							0, 1, image, NLS.bind(XMLUIMessages.Close_with__, (new Object[]{" '>'"})), //$NON-NLS-1$
+							null, proposedInfo, XMLRelevanceConstants.R_CLOSE_TAG);
+				contentAssistRequest.addProposal(proposal);
+			}
+		}
+		else if (node.getNodeType() == Node.DOCUMENT_NODE) {
+			setErrorMessage(XMLUIMessages.Content_Assist_not_availab_UI_);
+		}
+	}
+	
+	protected void addTagInsertionProposals(
+			ContentAssistRequest contentAssistRequest, int childPosition,
+			CompletionProposalInvocationContext context) {
+		
+		List cmnodes = null;
+		Node parent = contentAssistRequest.getParent();
+		String error = null;
+
+		// (nsd) This is only valid at the document element level
+		// only valid if it's XML (check added 2/17/2004)
+		if ((parent != null) && (parent.getNodeType() == Node.DOCUMENT_NODE) &&
+				((IDOMDocument) parent).isXMLType() && !isCursorAfterXMLPI(contentAssistRequest)) {
+			return;
+		}
+		// only want proposals if cursor is after doctype...
+		if (!isCursorAfterDoctype(contentAssistRequest)) {
+			return;
+		}
+
+		// fix for meta-info comment nodes.. they currently "hide" other
+		// proposals because the don't
+		// have a content model (so can't propose any children..)
+		if ((parent != null) && (parent instanceof IDOMNode) && isCommentNode((IDOMNode) parent)) {
+			// loop and find non comment node?
+			while ((parent != null) && isCommentNode((IDOMNode) parent)) {
+				parent = parent.getParentNode();
+			}
+		}
+
+		if (parent.getNodeType() == Node.ELEMENT_NODE) {
+			CMElementDeclaration parentDecl = getCMElementDeclaration(parent);
+			if (parentDecl != null) {
+				// XSD-specific ability - no filtering
+				CMDataType childType = parentDecl.getDataType();
+				if (childType != null) {
+					String[] childStrings = childType.getEnumeratedValues();
+					String defaultValue = childType.getImpliedValue();
+					if (childStrings != null || defaultValue != null) {
+						// the content string is the sole valid child...so replace the rest
+						int begin = contentAssistRequest.getReplacementBeginPosition();
+						int length = contentAssistRequest.getReplacementLength();
+						if (parent instanceof IDOMNode) {
+							if (((IDOMNode) parent).getLastStructuredDocumentRegion() != ((IDOMNode) parent).getFirstStructuredDocumentRegion()) {
+								begin = ((IDOMNode) parent).getFirstStructuredDocumentRegion().getEndOffset();
+								length = ((IDOMNode) parent).getLastStructuredDocumentRegion().getStartOffset() - begin;
+							}
+						}
+						String proposedInfo = getAdditionalInfo(parentDecl, childType);
+						for (int i = 0; i < childStrings.length; i++) {
+							if(!childStrings[i].equals(defaultValue)) {
+								CustomCompletionProposal textProposal = new CustomCompletionProposal(
+										childStrings[i],begin, length, childStrings[i].length(),
+										XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_ENUM),
+										childStrings[i], null, proposedInfo, XMLRelevanceConstants.R_TAG_INSERTION);
+								contentAssistRequest.addProposal(textProposal);
+							}
+						}
+						if(defaultValue != null) {
+							CustomCompletionProposal textProposal = new CustomCompletionProposal(
+									defaultValue, begin, length, defaultValue.length(),
+									XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_DEFAULT),
+									defaultValue, null, proposedInfo, XMLRelevanceConstants.R_TAG_INSERTION);
+							contentAssistRequest.addProposal(textProposal);
+						}
+					}
+				}
+			}
+			if ((parentDecl != null) && (parentDecl.getContentType() == CMElementDeclaration.PCDATA)) {
+				addPCDATAProposal(parentDecl.getNodeName(), contentAssistRequest, context);
+			}
+			else {
+				// retrieve the list of all possible children within this parent context
+				cmnodes = getAvailableChildElementDeclarations((Element) parent, childPosition,ModelQueryAction.INSERT);
+
+				// retrieve the list of the possible children within this
+				// parent context and at this index
+				List strictCMNodeSuggestions = null;
+				if (XMLUIPreferenceNames.SUGGESTION_STRATEGY_VALUE_STRICT.equals(XMLUIPlugin.getInstance().getPreferenceStore().getString(XMLUIPreferenceNames.SUGGESTION_STRATEGY))) {
+					strictCMNodeSuggestions = getValidChildElementDeclarations((Element) parent, childPosition, ModelQueryAction.INSERT);
+				}
+				Iterator nodeIterator = cmnodes.iterator();
+				if (!nodeIterator.hasNext()) {
+					if (getCMElementDeclaration(parent) != null) {
+						error = NLS.bind(XMLUIMessages._Has_no_available_child, (new Object[]{parent.getNodeName()}));
+					}
+					else {
+						error = NLS.bind(XMLUIMessages.Element__is_unknown, (new Object[]{parent.getNodeName()}));
+					}
+				}
+				String matchString = contentAssistRequest.getMatchString();
+				// chop off any leading <'s and whitespace from the matchstring
+				while ((matchString.length() > 0) &&
+						(Character.isWhitespace(matchString.charAt(0)) || beginsWith(matchString, "<"))) { //$NON-NLS-1$
+					
+					matchString = matchString.substring(1);
+				}
+				while (nodeIterator.hasNext()) {
+					Object o = nodeIterator.next();
+					if (o instanceof CMElementDeclaration) {
+						CMElementDeclaration elementDecl =(CMElementDeclaration) o;
+						// only add proposals for the child element's that
+						// begin with the matchstring
+						String tagname = getRequiredName(parent, elementDecl);
+						boolean isStrictCMNodeSuggestion =
+							strictCMNodeSuggestions != null ? strictCMNodeSuggestions.contains(elementDecl) : false;
+
+						//get the proposal image
+						Image image = CMImageUtil.getImage(elementDecl);
+						if (image == null) {
+							if (strictCMNodeSuggestions != null) {
+								image = isStrictCMNodeSuggestion ? this.getEmphasizedTagImage() : this.getDeemphasizedTagImage();
+							} else {
+								image = this.getGenericTagImage();
+							}
+						}
+
+						if (beginsWith(tagname, matchString)) {
+							String proposedText = getRequiredText(parent, elementDecl);
+
+							// https://bugs.eclipse.org/bugs/show_bug.cgi?id=89811
+							// place cursor in first empty quotes
+							int markupAdjustment = getCursorPositionForProposedText(proposedText);
+
+							String proposedInfo = getAdditionalInfo(parentDecl, elementDecl);
+							int relevance = isStrictCMNodeSuggestion ? XMLRelevanceConstants.R_STRICTLY_VALID_TAG_INSERTION : XMLRelevanceConstants.R_TAG_INSERTION;
+							CustomCompletionProposal proposal = new CustomCompletionProposal(
+									proposedText, contentAssistRequest.getReplacementBeginPosition(),
+									contentAssistRequest.getReplacementLength(), markupAdjustment,
+									image, tagname, null, proposedInfo, relevance);
+							contentAssistRequest.addProposal(proposal);
+						}
+					}
+				}
+				if (contentAssistRequest.getProposals().size() == 0) {
+					if (error != null) {
+						setErrorMessage(error);
+					}
+					else if ((contentAssistRequest.getMatchString() != null) &&
+							(contentAssistRequest.getMatchString().length() > 0)) {
+						
+						setErrorMessage(NLS.bind(
+								XMLUIMessages.No_known_child_tag,
+								(new Object[]{parent.getNodeName(), contentAssistRequest.getMatchString()})));
+					}
+					else {
+						setErrorMessage(NLS.bind(
+								XMLUIMessages.__Has_no_known_child,
+								(new Object[]{parent.getNodeName()})));
+					}
+				}
+			}
+		}
+		else if (parent.getNodeType() == Node.DOCUMENT_NODE) {
+			// Can only prompt with elements if the cursor position is past
+			// the XML processing
+			// instruction and DOCTYPE declaration
+			boolean xmlpiFound = false;
+			boolean doctypeFound = false;
+			int minimumOffset = -1;
+
+			for (Node child = parent.getFirstChild(); child != null; child = child.getNextSibling()) {
+
+				boolean xmlpi = ((child.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE) && child.getNodeName().equals("xml")); //$NON-NLS-1$
+				boolean doctype = child.getNodeType() == Node.DOCUMENT_TYPE_NODE;
+				if (xmlpi || (doctype && (minimumOffset < 0))) {
+					minimumOffset = ((IDOMNode) child).getFirstStructuredDocumentRegion().getStartOffset() + ((IDOMNode) child).getFirstStructuredDocumentRegion().getTextLength();
+				}
+				xmlpiFound = xmlpiFound || xmlpi;
+				doctypeFound = doctypeFound || doctype;
+			}
+
+			if (contentAssistRequest.getReplacementBeginPosition() >= minimumOffset) {
+				List childDecls = getAvailableRootChildren((Document) parent, childPosition);
+				for (int i = 0; i < childDecls.size(); i++) {
+					CMElementDeclaration ed = (CMElementDeclaration) childDecls.get(i);
+					if (ed != null) {
+						Image image = CMImageUtil.getImage(ed);
+						if (image == null) {
+							image = this.getGenericTagImage();
+						}
+						String proposedText = getRequiredText(parent, ed);
+						String tagname = getRequiredName(parent, ed);
+						// account for the &lt; and &gt;
+						int markupAdjustment = getContentGenerator().getMinimalStartTagLength(parent, ed);
+						String proposedInfo = getAdditionalInfo(null, ed);
+						CustomCompletionProposal proposal = new CustomCompletionProposal(
+								proposedText, contentAssistRequest.getReplacementBeginPosition(),
+								contentAssistRequest.getReplacementLength(), markupAdjustment, image,
+								tagname, null, proposedInfo, XMLRelevanceConstants.R_TAG_INSERTION);
+						contentAssistRequest.addProposal(proposal);
+					}
+				}
+			}
+		}
+	}
+
+	protected void addTagNameProposals(
+			ContentAssistRequest contentAssistRequest, int childPosition,
+			CompletionProposalInvocationContext context) {
+		
+		List cmnodes = null;
+		Node parent = contentAssistRequest.getParent();
+		IDOMNode node = (IDOMNode) contentAssistRequest.getNode();
+		String error = null;
+		String matchString = contentAssistRequest.getMatchString();
+		if (parent.getNodeType() == Node.ELEMENT_NODE) {
+			// retrieve the list of children
+			// validActions = getAvailableChildrenAtIndex((Element) parent,
+			// childPosition);
+			cmnodes = getAvailableChildElementDeclarations((Element) parent, childPosition, ModelQueryAction.INSERT);
+			List strictCMNodeSuggestions = null;
+			if (XMLUIPreferenceNames.SUGGESTION_STRATEGY_VALUE_STRICT.equals(XMLUIPlugin.getInstance().getPreferenceStore().getString(XMLUIPreferenceNames.SUGGESTION_STRATEGY))) {
+				strictCMNodeSuggestions = getValidChildElementDeclarations((Element) parent, childPosition, ModelQueryAction.INSERT);
+			}
+			
+			Iterator nodeIterator = cmnodes.iterator();
+			// chop off any leading <'s and whitespace from the matchstring
+			while ((matchString.length() > 0) &&
+					(Character.isWhitespace(matchString.charAt(0)) || beginsWith(matchString, "<"))) { //$NON-NLS-1$
+				
+				matchString = matchString.substring(1);
+			}
+			if (!nodeIterator.hasNext()) {
+				error = NLS.bind(XMLUIMessages.__Has_no_known_child, (new Object[]{parent.getNodeName()}));
+			}
+			while (nodeIterator.hasNext()) {
+				CMNode elementDecl = (CMNode) nodeIterator.next();
+				if (elementDecl != null) {
+					// only add proposals for the child element's that begin with the matchstring
+					String proposedText = null;
+					int cursorAdjustment = 0;
+					
+					//determine if strict suggestion
+					boolean isStrictCMNodeSuggestion =
+						strictCMNodeSuggestions != null ? strictCMNodeSuggestions.contains(elementDecl) : false;
+
+					// do a check to see if partial attributes of partial tag names are in list
+					if (((node != null) && (node.getAttributes() != null) &&
+							(node.getAttributes().getLength() > 0) &&
+							attributeInList(node, parent, elementDecl)) ||
+							((node.getNodeType() != Node.TEXT_NODE) &&
+									node.getFirstStructuredDocumentRegion().isEnded())) {
+
+						proposedText = getRequiredName(parent, elementDecl);
+						cursorAdjustment = proposedText.length();
+					}
+					else {
+						proposedText = getRequiredName(parent, elementDecl);
+						
+						cursorAdjustment = proposedText.length();
+						if (elementDecl instanceof CMElementDeclaration) {
+							CMElementDeclaration ed = (CMElementDeclaration) elementDecl;
+							// https://bugs.eclipse.org/bugs/show_bug.cgi?id=89811
+							StringBuffer sb = new StringBuffer();
+							getContentGenerator().generateTag(parent, ed, sb);
+							// since it's a name proposal, assume '<' is already there
+							// only return the rest of the tag
+							proposedText = sb.toString().substring(1);
+							cursorAdjustment = getCursorPositionForProposedText(proposedText);
+						}
+					}
+					if (beginsWith(proposedText, matchString)) {
+						//get the proposal image
+						Image image = CMImageUtil.getImage(elementDecl);
+						if (image == null) {
+							if (strictCMNodeSuggestions != null) {
+								image = isStrictCMNodeSuggestion ? this.getEmphasizedTagImage() : this.getDeemphasizedTagImage();
+							} else {
+								image = this.getGenericTagImage();
+							}
+						}
+						int relevance = isStrictCMNodeSuggestion ? XMLRelevanceConstants.R_STRICTLY_VALID_TAG_NAME : XMLRelevanceConstants.R_TAG_NAME;
+						String proposedInfo = getAdditionalInfo(getCMElementDeclaration(parent), elementDecl);
+						CustomCompletionProposal proposal = new CustomCompletionProposal(
+								proposedText, contentAssistRequest.getReplacementBeginPosition(),
+								contentAssistRequest.getReplacementLength(), cursorAdjustment, image,
+								getRequiredName(parent, elementDecl), null, proposedInfo,
+								relevance);
+						contentAssistRequest.addProposal(proposal);
+					}
+				}
+			}
+			if (contentAssistRequest.getProposals().size() == 0) {
+				if (error != null) {
+					setErrorMessage(error);
+				}
+				else if ((contentAssistRequest.getMatchString() != null) && (contentAssistRequest.getMatchString().length() > 0)) {
+					setErrorMessage(NLS.bind(
+							XMLUIMessages.No_known_child_tag_names,
+							(new Object[]{parent.getNodeName(), contentAssistRequest.getMatchString()})));
+				}
+				else {
+					setErrorMessage(NLS.bind(
+							XMLUIMessages.__Has_no_known_child,
+							(new Object[]{parent.getNodeName()})));
+				}
+			}
+		}
+		else if (parent.getNodeType() == Node.DOCUMENT_NODE) {
+			List childElements = getAvailableRootChildren((Document) parent, childPosition);
+			if ( childElements.size() == 0) {
+				//No doctype available , treat it as empty document
+				addEmptyDocumentProposals(contentAssistRequest, context);
+			}
+			for (int i = 0; i < childElements.size(); i++) {
+				CMNode ed = (CMNode) childElements.get(i);
+				if (ed == null) {
+					continue;
+				}
+				String proposedText = null;
+				int cursorAdjustment = 0;
+				if (ed instanceof CMElementDeclaration) {
+					// proposedText = getRequiredName(parent, ed);
+					StringBuffer sb = new StringBuffer();
+					getContentGenerator().generateTag(parent, (CMElementDeclaration) ed, sb);
+					// tag starts w/ '<', but we want to compare to name
+					proposedText = sb.toString().substring(1);
+
+					if (!beginsWith(proposedText, matchString)) {
+						continue;
+					}
+
+					cursorAdjustment = getCursorPositionForProposedText(proposedText);
+
+					String proposedInfo = getAdditionalInfo(null, ed);
+					Image image = CMImageUtil.getImage(ed);
+					if (image == null) {
+						image = this.getGenericTagImage();
+					}
+					CustomCompletionProposal proposal = new CustomCompletionProposal(
+							proposedText, contentAssistRequest.getReplacementBeginPosition(),
+							contentAssistRequest.getReplacementLength(), cursorAdjustment, image,
+							getRequiredName(parent, ed), null, proposedInfo, XMLRelevanceConstants.R_TAG_NAME);
+					contentAssistRequest.addProposal(proposal);
+				}
+			}
+		}
+	}
+	
+	protected void addEmptyDocumentProposals(
+			ContentAssistRequest contentAssistRequest,
+			CompletionProposalInvocationContext context) {
+		
+		//by default do nothing
+	}
+	
+	/**
+	 * <p>Implementers are allowed to override</p>
+	 * 
+	 * @return the proposal image to display for generic tag proposals
+	 */
+	protected Image getGenericTagImage() {
+		return XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TAG_GENERIC);
+	}
+	
+	/**
+	 * <p>Implementers are allowed to override</p>
+	 * 
+	 * @return the proposal image to display for emphasized tag proposals
+	 */
+	protected Image getEmphasizedTagImage() {
+		return XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TAG_GENERIC_EMPHASIZED);
+	}
+	
+	/**
+	 * <p>Implementers are allowed to override</p>
+	 * 
+	 * @return the proposal image to display for de-emphasized tag proposals
+	 */
+	protected Image getDeemphasizedTagImage() {
+		return XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TAG_GENERIC_DEEMPHASIZED);
+	}
+	
+	/**
+	 * <p>Implementers are allowed to override</p>
+	 * 
+	 * @return the proposal image to display for entity reference proposals
+	 */
+	protected Image getEntityReferenceImage() {
+		return XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_ENTITY_REFERENCE);
+	}
+	
+	/**
+	 * <p>Implementers are allowed to override</p>
+	 * 
+	 * @return the proposal image to display for not required attributes
+	 */
+	protected Image getNotRequiredAttributeImage() {
+		return XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_ATTRIBUTE);
+	}
+	
+	/**
+	 * <p>Implementers are allowed to override</p>
+	 * 
+	 * @return the proposal image to display for required attributes
+	 */
+	protected Image getRequiredAttributeImage() {
+		return XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_ATT_REQ_OBJ);
+	}
+	
+	/**
+	 * This method can check if the cursor is after the XMLPI
+	 * 
+	 * @param car
+	 */
+	protected boolean isCursorAfterXMLPI(ContentAssistRequest car) {
+		Node aNode = car.getNode();
+		boolean xmlpiFound = false;
+		Document parent = aNode.getOwnerDocument();
+		int xmlpiNodePosition = -1;
+		boolean isAfterXMLPI = false;
+
+		if (parent == null) {
+			return true; // blank document case
+		}
+
+		for (Node child = parent.getFirstChild(); child != null; child = child.getNextSibling()) {
+			boolean xmlpi = ((child.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE) && child.getNodeName().equals("xml")); //$NON-NLS-1$
+			xmlpiFound = xmlpiFound || xmlpi;
+			if (xmlpiFound) {
+				if (child instanceof IDOMNode) {
+					xmlpiNodePosition = ((IDOMNode) child).getEndOffset();
+					isAfterXMLPI = (car.getReplacementBeginPosition() >= xmlpiNodePosition);
+				}
+				break;
+			}
+		}
+		return isAfterXMLPI;
+	}
+	
+	protected String getRequiredName(Node parentOrOwner, CMNode cmnode) {
+		if ((cmnode == null) || (parentOrOwner == null)) {
+			if (Debug.displayWarnings) {
+				new IllegalArgumentException("Null declaration!").printStackTrace(); //$NON-NLS-1$
+			}
+			return ""; //$NON-NLS-1$
+		}
+		return getContentGenerator().getRequiredName(parentOrOwner, cmnode);
+	}
+	
+	private String getRequiredText(Node parentOrOwner, CMAttributeDeclaration attrDecl) {
+		if (attrDecl == null) {
+			if (Debug.displayWarnings) {
+				new IllegalArgumentException("Null attribute declaration!").printStackTrace(); //$NON-NLS-1$
+			}
+			return ""; //$NON-NLS-1$
+		}
+		StringBuffer buff = new StringBuffer();
+		getContentGenerator().generateRequiredAttribute(parentOrOwner, attrDecl, buff);
+		return buff.toString();
+	}
+	
+	protected String getRequiredText(Node parentOrOwner, CMElementDeclaration elementDecl) {
+		if (elementDecl == null) {
+			if (Debug.displayWarnings) {
+				new IllegalArgumentException("Null attribute declaration!").printStackTrace(); //$NON-NLS-1$
+			}
+			return ""; //$NON-NLS-1$
+		}
+		StringBuffer buff = new StringBuffer();
+		getContentGenerator().generateTag(parentOrOwner, elementDecl, buff);
+		return buff.toString();
+	}
+	
+	/**
+	 * Retrieves all of the possible valid values for this attribute
+	 * declaration
+	 */
+	private List getPossibleDataTypeValues(Node node, CMAttributeDeclaration ad) {
+		List list = null;
+		if (node.getNodeType() == Node.ELEMENT_NODE) {
+			Element element = (Element) node;
+			String[] dataTypeValues = null;
+			// The ModelQuery may not be available if the corresponding
+			// adapter
+			// is absent
+			ModelQuery modelQuery = ModelQueryUtil.getModelQuery(element.getOwnerDocument());
+			if (modelQuery != null) {
+				dataTypeValues = modelQuery.getPossibleDataTypeValues(element, ad);
+			}
+			else {
+				if (ad.getAttrType() != null) {
+					dataTypeValues = ad.getAttrType().getEnumeratedValues();
+				}
+			}
+			if (dataTypeValues != null) {
+				list = new ArrayList(dataTypeValues.length);
+				for (int i = 0; i < dataTypeValues.length; i++) {
+					list.add(dataTypeValues[i]);
+				}
+			}
+		}
+		if (list == null) {
+			list = new ArrayList(0);
+		}
+		return list;
+	}
+	
+	/**
+	 * This is to determine if a tag is a special meta-info comment tag that
+	 * shows up as an ELEMENT
+	 * 
+	 * @param node
+	 * @return
+	 */
+	private boolean isCommentNode(IDOMNode node) {
+		return ((node != null) && (node instanceof IDOMElement) && ((IDOMElement) node).isCommentTag());
+	}
+	
+	private boolean isStartTag(IStructuredDocumentRegion sdRegion) {
+		boolean result = false;
+		if (sdRegion.getRegions().size() > 0) {
+			ITextRegion r = sdRegion.getRegions().get(0);
+			result = (r.getType() == DOMRegionContext.XML_TAG_OPEN) && sdRegion.isEnded();
+		}
+		return result;
+	}
+	
+	/**
+	 * Gets the corresponding XMLNode, and checks if it's closed.
+	 * 
+	 * @param startTag
+	 * 
+	 */
+	private boolean needsEndTag(IStructuredDocumentRegion startTag,
+			CompletionProposalInvocationContext context) {
+		
+		boolean result = false;
+		IStructuredModel sModel =
+			StructuredModelManager.getModelManager().getExistingModelForRead(context.getDocument());
+		try {
+			if (sModel != null) {
+				IDOMNode xmlNode = (IDOMNode) sModel.getIndexedRegion(startTag.getStart());
+				if (!isStartTag(startTag)) {
+					result = false;
+				}
+				else if (isSelfClosed(startTag)) {
+					result = false;
+				}
+				else if (!xmlNode.isContainer()) {
+					result = false;
+				}
+				else {
+					result = xmlNode.getEndStructuredDocumentRegion() == null;
+				}
+			}
+		}
+		finally {
+			if (sModel != null) {
+				sModel.releaseFromRead();
+			}
+		}
+		return result;
+	}
+	
+	private boolean isSelfClosed(IStructuredDocumentRegion startTag) {
+		ITextRegionList regions = startTag.getRegions();
+		return regions.get(regions.size() - 1).getType() == DOMRegionContext.XML_EMPTY_TAG_CLOSE;
+	}
+	
+	private String getTagName(IStructuredDocumentRegion sdRegion) {
+		ITextRegionList regions = sdRegion.getRegions();
+		ITextRegion region = null;
+		String name = ""; //$NON-NLS-1$
+		for (int i = 0; i < regions.size(); i++) {
+			region = regions.get(i);
+			if (region.getType() == DOMRegionContext.XML_TAG_NAME) {
+				name = sdRegion.getText(region);
+				break;
+			}
+		}
+		return name;
+	}
+	
+	/**
+	 * return all possible EntityReferenceProposals (according to current
+	 * position in doc)
+	 */
+	private ICompletionProposal[] computeEntityReferenceProposals(ITextRegion completionRegion,
+			IDOMNode treeNode,CompletionProposalInvocationContext context) {
+		
+		// only handle XML content for now
+		int documentPosition = context.getInvocationOffset();
+		Vector proposals = new Vector(); // ICompletionProposals
+		IStructuredDocumentRegion sdRegion =
+			ContentAssistUtils.getStructuredDocumentRegion(context.getViewer(), context.getInvocationOffset());
+		if ((completionRegion != null) && (completionRegion.getType() == DOMRegionContext.XML_CONTENT)) {
+			int nodeOffset = documentPosition - sdRegion.getStartOffset(completionRegion);
+			String regionText = sdRegion.getFullText(completionRegion);
+
+			// if directly to the right of a &, region will be null, need to
+			// move to
+			// the previous region...there might be a better way to do this
+			if ((regionText != null) && regionText.trim().equals("") && (documentPosition > 0)) { //$NON-NLS-1$
+				IStructuredDocumentRegion prev = treeNode.getStructuredDocument().getRegionAtCharacterOffset(documentPosition - 1);
+				if ((prev != null) && prev.getText().equals("&")) { //$NON-NLS-1$
+					// https://bugs.eclipse.org/bugs/show_bug.cgi?id=206680
+					// examine previous region
+					sdRegion = prev;
+					completionRegion = prev.getLastRegion();
+					regionText = prev.getFullText();
+					nodeOffset = 1;
+				}
+			}
+
+			// string must start w/ &
+			if ((regionText != null) && regionText.startsWith("&")) { //$NON-NLS-1$						 		
+				String key = (nodeOffset > 0) ? regionText.substring(1, nodeOffset) : ""; //$NON-NLS-1$
+
+				// get entity proposals, passing in the appropriate start
+				// string
+				ModelQuery mq = ModelQueryUtil.getModelQuery(((Node) treeNode).getOwnerDocument());
+				if (mq != null) {
+					CMDocument xmlDoc = mq.getCorrespondingCMDocument(treeNode);
+					CMNamedNodeMap cmmap = null;
+					Properties entities = null;
+					if (xmlDoc != null) {
+						cmmap = xmlDoc.getEntities();
+					}
+					if (cmmap != null) {
+						entities = mapToProperties(cmmap);
+					}
+					else // 224787 in absence of content model, just use
+					// minimal 5 entities
+					{
+						entities = new Properties();
+						entities.put("quot", "\""); //$NON-NLS-1$ //$NON-NLS-2$
+						entities.put("apos", "'"); //$NON-NLS-1$ //$NON-NLS-2$
+						entities.put("amp", "&"); //$NON-NLS-1$ //$NON-NLS-2$
+						entities.put("lt", "<"); //$NON-NLS-1$ //$NON-NLS-2$
+						entities.put("gt", ">"); //$NON-NLS-1$ //$NON-NLS-2$	
+						entities.put("nbsp", " "); //$NON-NLS-1$ //$NON-NLS-2$									
+					}
+					addEntityProposals(proposals, entities, key,
+							nodeOffset, sdRegion, completionRegion, context);
+				}
+			}
+		}
+		return (ICompletionProposal[]) ((proposals.size() > 0) ? proposals.toArray(new ICompletionProposal[proposals.size()]) : null);
+	}
+	
+	/**
+	 * Similar to the call in HTMLContentAssistProcessor. Pass in a node, it
+	 * tells you if the document is XML type.
+	 * 
+	 * @param node
+	 * 
+	 */
+	private boolean isXMLNode(Node node) {
+		if (node == null) {
+			return false;
+		}
+
+		Document doc = null;
+		doc = (node.getNodeType() != Node.DOCUMENT_NODE) ? node.getOwnerDocument() : ((Document) node);
+
+		return (doc instanceof IDOMDocument) && ((IDOMDocument) doc).isXMLType();
+	}
+	
+	/**
+	 * Checks if cursor position is after doctype tag...
+	 * 
+	 * @param car
+	 * 
+	 */
+	private boolean isCursorAfterDoctype(ContentAssistRequest car) {
+		Node aNode = car.getNode();
+		Document parent = aNode.getOwnerDocument();
+		int xmldoctypeNodePosition = -1;
+		boolean isAfterDoctype = true;
+
+		if (parent == null) {
+			return true; // blank document case
+		}
+
+		for (Node child = parent.getFirstChild(); child != null; child = child.getNextSibling()) {
+			if (child instanceof IDOMNode) {
+				if (child.getNodeType() == Node.DOCUMENT_TYPE_NODE) {
+					xmldoctypeNodePosition = ((IDOMNode) child).getEndOffset();
+					isAfterDoctype = (car.getReplacementBeginPosition() >= xmldoctypeNodePosition);
+					break;
+				}
+			}
+		}
+		return isAfterDoctype;
+	}
+	
+	/**
+	 * returns a list of CMElementDeclarations
+	 * 
+	 * @param document
+	 * @param childIndex
+	 * @return
+	 */
+	private List getAvailableRootChildren(Document document, int childIndex) {
+		List list = null;
+
+		// extract the valid 'root' node name from the DocumentType Node
+		DocumentType docType = document.getDoctype();
+		String rootName = null;
+		if (docType != null) {
+			rootName = docType.getNodeName();
+		}
+		if (rootName == null) {
+			return new ArrayList(0);
+		}
+
+		for (Node child = document.getFirstChild(); child != null; child = child.getNextSibling()) {
+			// make sure the "root" Element isn't already present
+			// is it required to be an Element?
+			if ((child.getNodeType() == Node.ELEMENT_NODE) && child.getNodeName().equalsIgnoreCase(rootName)) {
+				// if the node is missing either the start or end tag, don't
+				// count it as present
+				if ((child instanceof IDOMNode) && ((((IDOMNode) child).getStartStructuredDocumentRegion() == null) || (((IDOMNode) child).getEndStructuredDocumentRegion() == null))) {
+					continue;
+				}
+				if (Debug.displayInfo) {
+					System.out.println(rootName + " already present!"); //$NON-NLS-1$
+				}
+				setErrorMessage(NLS.bind(XMLUIMessages.The_document_element__, (new Object[]{rootName})));
+				return new ArrayList(0);
+			}
+		}
+
+		list = new ArrayList(1);
+		ModelQuery modelQuery = ModelQueryUtil.getModelQuery(document);
+		if (modelQuery != null) {
+			CMDocument cmdoc = modelQuery.getCorrespondingCMDocument(document);
+			if (cmdoc != null) {
+				if (rootName != null) {
+					CMElementDeclaration rootDecl = (CMElementDeclaration) cmdoc.getElements().getNamedItem(rootName);
+					if (rootDecl != null) {
+						list.add(rootDecl);
+					}
+					else {
+						// supply the given document name anyway, even if it
+						// is an error
+						list.add(new SimpleCMElementDeclaration(rootName));
+
+						String location = "" + (docType.getPublicId() != null ? docType.getPublicId() + "/" : "") + (docType.getSystemId() != null ? docType.getSystemId() : ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+						if (location.length() > 0) {
+							setErrorMessage(NLS.bind(
+									XMLUIMessages.No_definition_for_in,
+									(new Object[]{rootName, location})));
+						}
+						else {
+							setErrorMessage(NLS.bind(
+									XMLUIMessages.No_definition_for,
+									(new Object[]{rootName})));
+						}
+					}
+				}
+			}
+			else {
+				String location = "" + (docType.getPublicId() != null ? docType.getPublicId() + "/" : "") + (docType.getSystemId() != null ? docType.getSystemId() : ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+				if (location.length() > 0) {
+					setErrorMessage(NLS.bind(
+							XMLUIMessages.No_content_model_for,
+							(new Object[]{location})));
+				}
+				else {
+					setErrorMessage(XMLUIMessages.No_content_model_found_UI_);
+				}
+			}
+		}
+
+		return list;
+	}
+	
+	/**
+	 * This method determines if any of the attributes in the proposed XMLNode
+	 * node, are possible values of attributes from possible Elements at this
+	 * point in the document according to the Content Model.
+	 * 
+	 * @param node
+	 *            the element with attributes that you would like to test if
+	 *            are possible for possible Elements at this point
+	 * @param cmnode
+	 *            possible element at this point in the document (depending on
+	 *            what 'node' is) true if any attributes of 'node' match any
+	 *            possible attributes from 'cmnodes' list.
+	 */
+	private boolean attributeInList(IDOMNode node, Node parent, CMNode cmnode) {
+		if ((node == null) || (parent == null) || (cmnode == null)) {
+			return false;
+		}
+		String elementMatchString = node.getNodeName();
+		String cmnodeName = getRequiredName(parent, cmnode);// cmnode.getNodeName();
+		if (node instanceof Element) {
+			NamedNodeMap map = ((Element) node).getAttributes();
+			String attrMatchString = ""; //$NON-NLS-1$
+			// iterate attribute possibilities for partially started node
+			for (int i = 0; (map != null) && (i < map.getLength()); i++) {
+				attrMatchString = map.item(i).getNodeName();
+				// filter on whatever user typed for element name already
+				if (beginsWith(cmnodeName, elementMatchString)) {
+					if (cmnode.getNodeType() == CMNode.ELEMENT_DECLARATION) {
+						CMNamedNodeMapImpl attributes = new CMNamedNodeMapImpl(((CMElementDeclaration) cmnode).getAttributes());
+						this.addModelQueryAttributeDeclarations(
+								node,((CMElementDeclaration) cmnode),attributes);
+	
+						// iterate possible attributes from a cmnode in
+						// proposal list
+						for (int k = 0; (attributes != null) && (k < attributes.getLength()); k++) {
+							// check if name matches
+							if (attributes.item(k).getNodeName().equals(attrMatchString)) {
+								return true;
+							}
+						}
+					}
+				}
+			}
+		}
+		return false;
+	}
+	
+	private Properties mapToProperties(CMNamedNodeMap map) {
+		Properties p = new Properties();
+		for (int i = 0; i < map.getLength(); i++) {
+			CMEntityDeclaration decl = (CMEntityDeclaration) map.item(i);
+			p.put(decl.getName(), decl.getValue());
+		}
+		return p;
+	}
+	
+	/**
+	 * <p>Adds model query attribute declaration proposals</p>
+	 * 
+	 * @param node
+	 * @param elementDecl
+	 * @param allAttributes
+	 */
+	private void addModelQueryAttributeDeclarations(IDOMNode node,
+			CMElementDeclaration elementDecl, CMNamedNodeMapImpl allAttributes) {
+		
+		if (node.getNodeType() == Node.ELEMENT_NODE) {
+			List nodes = ModelQueryUtil.getModelQuery(node.getOwnerDocument()).getAvailableContent((Element) node, elementDecl, ModelQuery.INCLUDE_ATTRIBUTES);
+			nodes = filterAvailableModelQueryCMNodes(nodes);
+			for (int k = 0; k < nodes.size(); k++) {
+				CMNode cmnode = (CMNode) nodes.get(k);
+				if (cmnode.getNodeType() == CMNode.ATTRIBUTE_DECLARATION) {
+					allAttributes.put(cmnode);
+				}
+			}
+		}
+	}
+	
+	/**
+	 * returns a list of CMNodes that are available within this parent context
+	 * Given the grammar shown below and a snippet of XML code (where the '|'
+	 * indicated the cursor position)
+	 * the list would return all of the element declarations that are
+	 * potential child elements of Foo.
+	 *
+	 * grammar : Foo -> (A, B, C)
+	 * snippet : <Foo><A>|
+	 * result : {A, B, C}
+	 * 
+	 * TODO cs... do we need to pass in the 'kindOfAction'? Seems to me we
+	 * could assume it's always an insert.
+	 *
+	 * @param parent
+	 * @param childPosition
+	 * @param kindOfAction
+	 * @return
+	 */
+	private List getAvailableChildElementDeclarations(Element parent, int childPosition, int kindOfAction) {
+		List modelQueryActions = getAvailableModelQueryActionsAtIndex(parent, childPosition, ModelQuery.VALIDITY_NONE);
+		Iterator iterator = modelQueryActions.iterator();
+		List cmnodes = new Vector();
+		while (iterator.hasNext()) {
+			ModelQueryAction action = (ModelQueryAction) iterator.next();
+			if ((childPosition < 0) || (((action.getStartIndex() <= childPosition) && (childPosition <= action.getEndIndex())) && (action.getKind() == kindOfAction))) {
+				CMNode actionCMNode = action.getCMNode();
+				if ((actionCMNode != null) && !cmnodes.contains(actionCMNode)) {
+					cmnodes.add(actionCMNode);
+				}
+			}
+		}
+		return cmnodes;
+	}
+	
+	/**
+	 * returns a list of CMNodes that can be validly inserted at this
+	 * childPosition
+	 * Given the grammar shown below and a snippet of XML code (where the '|'
+	 * indicated the cursor position)
+	 * the list would return only the element declarations can be inserted
+	 * while maintaing validity of the content.
+	 *
+	 * grammar : Foo -> (A, B, C)
+	 * snippet : <Foo><A>|
+	 * result : {B}
+	 *    
+	 * @param parent
+	 * @param childPosition
+	 * @param kindOfAction
+	 * @return
+	 */
+	private List getValidChildElementDeclarations(Element parent, int childPosition, int kindOfAction) {
+		List modelQueryActions = getAvailableModelQueryActionsAtIndex(parent, childPosition, ModelQuery.VALIDITY_STRICT);
+		Iterator iterator = modelQueryActions.iterator();
+		List cmnodes = new Vector();
+		while (iterator.hasNext()) {
+			ModelQueryAction action = (ModelQueryAction) iterator.next();
+			if ((childPosition < 0) || (((action.getStartIndex() <= childPosition) && (childPosition <= action.getEndIndex())) && (action.getKind() == kindOfAction))) {
+				CMNode actionCMNode = action.getCMNode();
+				if ((actionCMNode != null) && !cmnodes.contains(actionCMNode)) {
+					cmnodes.add(actionCMNode);
+				}
+			}
+		}
+		return cmnodes;
+	}
+	
+	/**
+	 * returns a list of ModelQueryActions
+	 * 
+	 * @param parent
+	 * @param index
+	 * @param validityChecking
+	 * @return
+	 */
+	private List getAvailableModelQueryActionsAtIndex(Element parent, int index, int validityChecking) {
+		List list = new ArrayList();
+		CMElementDeclaration parentDecl = getCMElementDeclaration(parent);
+		if (parentDecl != null) {
+			ModelQuery modelQuery = ModelQueryUtil.getModelQuery(parent.getOwnerDocument());
+			// taken from ActionManagers
+			// int editMode = modelQuery.getEditMode();
+			int editMode = ModelQuery.EDIT_MODE_UNCONSTRAINED;
+			int ic = (editMode == ModelQuery.EDIT_MODE_CONSTRAINED_STRICT) ? ModelQuery.INCLUDE_CHILD_NODES | ModelQuery.INCLUDE_SEQUENCE_GROUPS : ModelQuery.INCLUDE_CHILD_NODES;
+			modelQuery.getInsertActions(parent, parentDecl, index, ic, validityChecking, list);
+		}
+		
+		list = filterAvailableModelQueryActions(list);
+		return list;
+	}
+	
+	/**
+	 * <p>Filters out any model query actions that are not valid for this
+	 * implementation of the model query computer based on the {@link CMNode}
+	 * of the action.</p>
+	 * 
+	 * @param modelQueryActions
+	 * @return the filtered list of {@link ModelQueryAction}s
+	 */
+	private List filterAvailableModelQueryActions(List modelQueryActions) {
+		List filtered = new ArrayList(modelQueryActions.size());
+	
+		Iterator iterator = modelQueryActions.iterator();
+		while (iterator.hasNext()) {
+			ModelQueryAction action = (ModelQueryAction) iterator.next();
+			if(validModelQueryNode(action.getCMNode())) {
+				filtered.add(action);
+			}
+		}
+		
+		return filtered;
+	}
+	
+	/**
+	 * <p>Filters out any model query {@link CMNode}s that are not valid for this
+	 * implementation of the model query computer</p>
+	 * 
+	 * @param modelQueryNodes
+	 * @return the filtered list of {@link CMNode}s
+	 */
+	private List filterAvailableModelQueryCMNodes(List modelQueryNodes) {
+		List filtered = new ArrayList(modelQueryNodes.size());
+	
+		Iterator iterator = modelQueryNodes.iterator();
+		while (iterator.hasNext()) {
+			CMNode node = (CMNode) iterator.next();
+			if(validModelQueryNode(node)) {
+				filtered.add(node);
+			}
+		}
+		
+		return filtered;
+	}
+	
+	/**
+	 * <p>Adds a generic doc type proposal</p>
+	 * 
+	 * @param contentAssistRequest
+	 * @param context
+	 */
+	private void addDocTypeProposal(
+			ContentAssistRequest contentAssistRequest,
+			CompletionProposalInvocationContext context) {
+		
+		// if a DocumentElement exists, use that for the root Element name
+		String rootname = "unspecified"; //$NON-NLS-1$
+		if (contentAssistRequest.getNode().getOwnerDocument().getDocumentElement() != null) {
+			rootname = contentAssistRequest.getNode().getOwnerDocument().getDocumentElement().getNodeName();
+		}
+
+		String proposedText = "<!DOCTYPE " + rootname + " PUBLIC \"//UNKNOWN/\" \"unknown.dtd\">"; //$NON-NLS-1$ //$NON-NLS-2$
+		ICompletionProposal proposal = new CustomCompletionProposal(
+				proposedText, contentAssistRequest.getReplacementBeginPosition(),
+				contentAssistRequest.getReplacementLength(), 10,
+				XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_DOCTYPE),
+				"<!DOCTYPE ... >", //$NON-NLS-1$
+				null, null, XMLRelevanceConstants.R_DOCTYPE);
+		// TODO provide special documentation on doc type
+		contentAssistRequest.addProposal(proposal);
+	}
+	
+	public static CMElementDeclaration getCMElementDeclaration(Node node) {
+		CMElementDeclaration result = null;
+		if (node.getNodeType() == Node.ELEMENT_NODE) {
+			ModelQuery modelQuery = ModelQueryUtil.getModelQuery(node.getOwnerDocument());
+			if (modelQuery != null) {
+				result = modelQuery.getCMElementDeclaration((Element) node);
+			}
+		}
+		return result;
+	}
+	
+	/**
+	 * Retrieves cmnode's documentation to display in the completion
+	 * proposal's additional info. If no documentation exists for cmnode, try
+	 * displaying parentOrOwner's documentation
+	 * 
+	 * String any documentation information to display for cmnode.
+	 * <code>null</code> if there is nothing to display.
+	 */
+	public static String getAdditionalInfo(CMNode parentOrOwner, CMNode cmnode) {
+		String addlInfo = null;
+
+		if (cmnode == null) {
+			if (Debug.displayWarnings) {
+				new IllegalArgumentException("Null declaration!").printStackTrace(); //$NON-NLS-1$
+			}
+			return null;
+		}
+
+		addlInfo = infoProvider.getInfo(cmnode);
+		if ((addlInfo == null) && (parentOrOwner != null)) {
+			addlInfo = infoProvider.getInfo(parentOrOwner);
+		}
+		return addlInfo;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/AttributeContextInformation.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/AttributeContextInformation.java
new file mode 100644
index 0000000..66e514a
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/AttributeContextInformation.java
@@ -0,0 +1,115 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.contentassist;
+
+import java.util.HashMap;
+
+import org.eclipse.jface.text.contentassist.IContextInformation;
+import org.eclipse.jface.text.contentassist.IContextInformationExtension;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.wst.sse.ui.internal.util.Assert;
+
+
+/**
+ * Implementation of IContextInformation. Adds knowledge about the information
+ * display string such as required attributes for this context.
+ * 
+ * @author pavery
+ */
+public class AttributeContextInformation implements IContextInformation, IContextInformationExtension {
+	private HashMap fAttr2RangeMap;
+	/** The name of the context */
+	private String fContextDisplayString;
+	/** The image to be displayed */
+	private Image fImage;
+	/** The information to be displayed */
+	private String fInformationDisplayString;
+	private int fPosition = -1;
+
+	/**
+	 * Creates a new context information with an image.
+	 * 
+	 * @param image
+	 *            the image to display when presenting the context information
+	 * @param contextDisplayString
+	 *            the string to be used when presenting the context
+	 * @param informationDisplayString
+	 *            the string to be displayed when presenting the context
+	 *            information, may not be <code>null</code>
+	 */
+	public AttributeContextInformation(Image image, String contextDisplayString, String informationDisplayString, HashMap attr2RangeMap) {
+		Assert.isNotNull(informationDisplayString, "illegal argument: informationDisplayString can not be null"); //$NON-NLS-1$
+
+		fImage = image;
+		fContextDisplayString = contextDisplayString;
+		fInformationDisplayString = informationDisplayString;
+		fAttr2RangeMap = attr2RangeMap;
+	}
+
+	/**
+	 * Creates a new context information without an image.
+	 * 
+	 * @param contextDisplayString
+	 *            the string to be used when presenting the context
+	 * @param informationDisplayString
+	 *            the string to be displayed when presenting the context
+	 *            information
+	 */
+	public AttributeContextInformation(String contextDisplayString, String informationDisplayString, HashMap attr2RangeMap) {
+		this(null, contextDisplayString, informationDisplayString, attr2RangeMap);
+	}
+
+	/**
+	 * Maps (String -> Position). The attribute name to the Text position.
+	 * 
+	 * 
+	 */
+	public HashMap getAttr2RangeMap() {
+		return fAttr2RangeMap;
+	}
+
+	/**
+	 * @see org.eclipse.jface.text.contentassist.IContextInformation#getContextDisplayString()
+	 */
+	public String getContextDisplayString() {
+		if (fContextDisplayString != null) {
+			return fContextDisplayString;
+		}
+		return fInformationDisplayString;
+	}
+
+	/**
+	 * @see org.eclipse.jface.text.contentassist.IContextInformationExtension#getContextInformationPosition()
+	 */
+	public int getContextInformationPosition() {
+		return fPosition;
+	}
+
+	/**
+	 * @see org.eclipse.jface.text.contentassist.IContextInformation#getImage()
+	 */
+	public Image getImage() {
+		return fImage;
+	}
+
+	/**
+	 * @see org.eclipse.jface.text.contentassist.IContextInformation#getInformationDisplayString()
+	 */
+	public String getInformationDisplayString() {
+		return fInformationDisplayString;
+	}
+
+	public void setContextInformationPosition(int position) {
+		fPosition = position;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/AttributeContextInformationPresenter.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/AttributeContextInformationPresenter.java
new file mode 100644
index 0000000..9871c79
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/AttributeContextInformationPresenter.java
@@ -0,0 +1,104 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.contentassist;
+
+import java.util.HashMap;
+
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.TextPresentation;
+import org.eclipse.jface.text.contentassist.IContextInformation;
+import org.eclipse.jface.text.contentassist.IContextInformationPresenter;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StyleRange;
+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.ITextRegionList;
+import org.eclipse.wst.sse.ui.internal.contentassist.ContextInformationValidator;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+
+
+/**
+ * Responsible for the presentation of the context info popup. This includes
+ * text style, and when the window should close.
+ * 
+ * @author pavery
+ */
+public class AttributeContextInformationPresenter extends ContextInformationValidator implements IContextInformationPresenter {
+
+	private IContextInformation fInfo = null;
+	private ContextInfoModelUtil fModelUtil = null;
+
+	public AttributeContextInformationPresenter() {
+		super();
+	}
+	
+	/**
+	 * @see org.eclipse.wst.sse.ui.internal.contentassist.ContextInformationValidator#install(org.eclipse.jface.text.contentassist.IContextInformation, org.eclipse.jface.text.ITextViewer, int)
+	 */
+	public void install(IContextInformation info, ITextViewer viewer, int documentPosition) {
+		super.install(info, viewer, documentPosition);
+		this.fInfo = info;
+		this.fModelUtil = new ContextInfoModelUtil((IStructuredDocument) viewer.getDocument());
+	}
+
+	/**
+	 * @see org.eclipse.jface.text.contentassist.IContextInformationPresenter#updatePresentation(int,
+	 *      org.eclipse.jface.text.TextPresentation)
+	 */
+	public boolean updatePresentation(int documentPosition, TextPresentation presentation) {
+		presentation.clear();
+
+		if (!(fInfo instanceof AttributeContextInformation)) {
+			return false;
+		}
+
+		// iterate existing attributes from current node
+		IDOMNode xmlNode = fModelUtil.getXMLNode(documentPosition);
+		if (xmlNode == null)
+			return false;
+		
+		IStructuredDocumentRegion sdRegion = xmlNode.getFirstStructuredDocumentRegion();
+		ITextRegionList regions = sdRegion.getRegions();
+		ITextRegion r = null;
+		String attrName = ""; //$NON-NLS-1$
+		Object temp = null;
+		Position p = null;
+		HashMap map = ((AttributeContextInformation) fInfo).getAttr2RangeMap();
+
+		// so we can add ranges in order
+		StyleRange[] sorted = new StyleRange[fInfo.getInformationDisplayString().length()];
+		for (int i = 0; i < regions.size(); i++) {
+			r = regions.get(i);
+			if (r.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) {
+				attrName = sdRegion.getText(r);
+				temp = map.get(attrName);
+				if (temp != null) {
+					p = (Position) temp;
+					sorted[p.offset] = new StyleRange(p.offset, p.length, null, null, SWT.BOLD);
+				}
+			}
+		}
+		// style ranges need to be added in order
+		StyleRange sr = null;
+		for (int i = 0; i < sorted.length; i++) {
+			sr = sorted[i];
+			if (sr != null) {
+				presentation.addStyleRange(sr);
+			}
+		}
+		return true;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/AttributeContextInformationProvider.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/AttributeContextInformationProvider.java
new file mode 100644
index 0000000..f18d7c8
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/AttributeContextInformationProvider.java
@@ -0,0 +1,231 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.contentassist;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.contentassist.ContextInformation;
+import org.eclipse.jface.text.contentassist.IContextInformation;
+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.ITextRegionList;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMContent;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNodeList;
+import org.eclipse.wst.xml.core.internal.contentmodel.basic.CMNamedNodeMapImpl;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.modelquery.ModelQueryUtil;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+
+/**
+ * Calculates attribute context information based on a StructuedDocument and
+ * document position.
+ * 
+ * @author pavery
+ */
+public class AttributeContextInformationProvider {
+	private final IContextInformation[] EMPTY_CONTEXT_INFO = new IContextInformation[0];
+	private Comparator fComparator;
+
+	private IStructuredDocument fDocument = null;
+	private ContextInfoModelUtil fModelUtil = null;
+
+	public AttributeContextInformationProvider(IStructuredDocument doc, AttributeContextInformationPresenter presenter) {
+		fDocument = doc;
+		fModelUtil = new ContextInfoModelUtil(fDocument);
+	}
+
+	/**
+	 * @param sdRegion
+	 * 
+	 */
+	private boolean canProposeInfo(IStructuredDocumentRegion sdRegion) {
+		if ((sdRegion != null) && isEndTag(sdRegion)) {
+			return false;
+		}
+		else {
+			return true;
+		}
+	}
+
+	public IContextInformation[] getAttributeInformation(int offset) {
+		/*
+		 * need to take care of special cases w/ ambiguous regions <tag>|
+		 * </tag> also end tags..
+		 */
+		IContextInformation[] results = EMPTY_CONTEXT_INFO;
+
+		IStructuredDocumentRegion sdRegion = fModelUtil.getDocument().getRegionAtCharacterOffset(offset);
+		if (!canProposeInfo(sdRegion)) {
+			return EMPTY_CONTEXT_INFO;
+		}
+
+		IDOMNode node = fModelUtil.getXMLNode(offset);
+		if (node != null) {
+			switch (node.getNodeType()) {
+				case Node.ELEMENT_NODE :
+					results = getInfoForElement(node);
+					break;
+				// future...
+				// case Node.TEXT_NODE :
+				// results = getInfoForText(node);
+				// break;
+			}
+		}
+		return results;
+	}
+
+	/**
+	 * Returns a comparator that compares CMAttributeDeclaration names.
+	 * 
+	 * the comparator
+	 */
+	private Comparator getCMAttributeComparator() {
+		if (fComparator == null) {
+			fComparator = new Comparator() {
+				public int compare(Object o1, Object o2) {
+					return ((CMAttributeDeclaration) o1).getAttrName().compareTo(((CMAttributeDeclaration) o2).getAttrName());
+				}
+			};
+		}
+		return fComparator;
+	}
+
+	/**
+	 * @param node
+	 * 
+	 */
+	private IContextInformation[] getInfoForElement(IDOMNode node) {
+		IContextInformation[] results = EMPTY_CONTEXT_INFO;
+		CMElementDeclaration decl = fModelUtil.getModelQuery().getCMElementDeclaration((Element) node);
+		if (decl != null) {
+			CMNamedNodeMap attributes = decl.getAttributes();
+
+			CMNamedNodeMapImpl allAttributes = new CMNamedNodeMapImpl(attributes);
+			List nodes = ModelQueryUtil.getModelQuery(node.getOwnerDocument()).getAvailableContent((Element) node, decl, ModelQuery.INCLUDE_ATTRIBUTES);
+			for (int k = 0; k < nodes.size(); k++) {
+				CMNode cmnode = (CMNode) nodes.get(k);
+				if (cmnode.getNodeType() == CMNode.ATTRIBUTE_DECLARATION) {
+					allAttributes.put(cmnode);
+				}
+			}
+			attributes = allAttributes;
+			
+			String attrContextString = node.getNodeName();
+			StringBuffer attrInfo = new StringBuffer(" "); //$NON-NLS-1$
+			String name = ""; //$NON-NLS-1$
+			HashMap attrPosMap = new HashMap();
+			int pos = 0;
+			int length = 0;
+			int numPerLine = 8;
+
+			CMAttributeDeclaration[] sortedAttrs = getSortedAttributes(attributes);
+
+			for (int i = 0; i < sortedAttrs.length; i++) {
+				name = sortedAttrs[i].getAttrName();
+				length = name.length();
+				pos = attrInfo.length();
+
+				attrInfo.append(name);
+
+				if (sortedAttrs[i].getUsage() == CMAttributeDeclaration.REQUIRED) {
+					attrInfo.append("*"); //$NON-NLS-1$
+					length++;
+				}
+				if (i < attributes.getLength() - 1) {
+					attrInfo.append(" "); //$NON-NLS-1$
+					if ((i != 0) && (i % numPerLine == 0)) {
+						attrInfo.append("\n "); //$NON-NLS-1$
+					}
+				}
+				attrPosMap.put(name, new Position(pos, length));
+			}
+			if (!attrInfo.toString().trim().equals("")) {
+				return new IContextInformation[]{new AttributeContextInformation(attrContextString, attrInfo.toString(), attrPosMap)};
+			}
+		}
+		return results;
+	}
+
+	/**
+	 * @param node
+	 * 
+	 */
+	IContextInformation[] getInfoForText(IDOMNode node) {
+		Node parent = node.getParentNode();
+		String contextString = node.getNodeName();
+		StringBuffer info = new StringBuffer(" "); //$NON-NLS-1$
+		if ((parent != null) && (parent.getNodeType() == Node.ELEMENT_NODE)) {
+			CMElementDeclaration decl = fModelUtil.getModelQuery().getCMElementDeclaration((Element) parent);
+			CMContent content = decl.getContent();
+			if (content instanceof CMGroup) {
+				CMGroup cmGroup = (CMGroup) content;
+				CMNodeList children = cmGroup.getChildNodes();
+				CMNode cmNode = null;
+				for (int i = 0; i < children.getLength(); i++) {
+					cmNode = children.item(i);
+					contextString = cmNode.getNodeName();
+					if (contextString != null) {
+						info.append("<" + cmNode.getNodeName() + ">"); //$NON-NLS-1$ //$NON-NLS-2$
+						if (i < children.getLength() - 1) {
+							info.append(" "); //$NON-NLS-1$
+						}
+					}
+				}
+			}
+		}
+		if (!info.toString().trim().equals("")) {
+			return new IContextInformation[]{new ContextInformation(contextString, info.toString())};
+		}
+		else {
+			return EMPTY_CONTEXT_INFO;
+		}
+	}
+
+	/**
+	 * Returns sorted array of CMAttributeDeclarations.
+	 * 
+	 * @param attributes
+	 * 
+	 */
+	private CMAttributeDeclaration[] getSortedAttributes(CMNamedNodeMap attributes) {
+		List sorted = new ArrayList();
+		for (int i = 0; i < attributes.getLength(); i++) {
+			sorted.add(attributes.item(i));
+		}
+		Collections.sort(sorted, getCMAttributeComparator());
+		return (CMAttributeDeclaration[]) sorted.toArray(new CMAttributeDeclaration[sorted.size()]);
+	}
+
+	/**
+	 * @param sdRegion
+	 * 
+	 */
+	private boolean isEndTag(IStructuredDocumentRegion sdRegion) {
+		ITextRegionList regions = sdRegion.getRegions();
+		return regions.get(0).getType() == DOMRegionContext.XML_END_TAG_OPEN;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/ContentAssistRequest.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/ContentAssistRequest.java
new file mode 100644
index 0000000..6a1d3af
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/ContentAssistRequest.java
@@ -0,0 +1,260 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.contentassist;
+
+
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+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.utils.StringUtils;
+import org.w3c.dom.Node;
+
+
+public class ContentAssistRequest {
+	protected IStructuredDocumentRegion documentRegion = null;
+	protected List macros = new ArrayList();
+	protected String matchString;
+	protected Node node = null;
+	protected Node parent = null;
+	protected List proposals = new ArrayList();
+	protected ITextRegion region = null;
+	protected int replacementBeginPosition;
+	protected int replacementLength;
+
+	// private Boolean separate = null; // (pa) not used
+	// private Boolean sort = null; // (pa) not used
+	/**
+	 * XMLContentAssistRequest constructor comment.
+	 */
+	public ContentAssistRequest(Node node, Node parent, IStructuredDocumentRegion documentRegion, ITextRegion completionRegion, int begin, int length, String filter) {
+		super();
+		setNode(node);
+		setParent(parent);
+		setDocumentRegion(documentRegion);
+		setRegion(completionRegion);
+		setMatchString(filter);
+		setReplacementBeginPosition(begin);
+		setReplacementLength(length);
+	}
+
+	public void addMacro(ICompletionProposal newProposal) {
+		macros.add(newProposal);
+	}
+
+	public void addProposal(ICompletionProposal newProposal) {
+		proposals.add(newProposal);
+	}
+
+	public ICompletionProposal[] getCompletionProposals() {
+		ICompletionProposal results[] = null;
+		if ((getProposals().size() > 0) || (getMacros().size() > 0)) {
+			List allProposals = new ArrayList();
+			if (!shouldSeparate()) {
+				allProposals.addAll(getProposals());
+				// should be empty, as all macros should have gone into the
+				// proposal list
+				allProposals.addAll(getMacros());
+				allProposals = sortProposals(allProposals);
+			}
+			else {
+				allProposals.addAll(sortProposals(getProposals()));
+				allProposals.addAll(sortProposals(getMacros()));
+			}
+
+			results = new ICompletionProposal[allProposals.size()];
+			for (int i = 0; i < allProposals.size(); i++) {
+				results[i] = (ICompletionProposal) allProposals.get(i);
+			}
+		}
+		return results;
+	}
+
+
+	public IStructuredDocumentRegion getDocumentRegion() {
+		return documentRegion;
+	}
+
+	/**
+	 * 
+	 * @return java.util.List
+	 */
+	public java.util.List getMacros() {
+		return macros;
+	}
+
+	/**
+	 * 
+	 * @return java.lang.String
+	 */
+	public java.lang.String getMatchString() {
+		return matchString;
+	}
+
+	/**
+	 * 
+	 * @return org.w3c.dom.Node
+	 */
+	public org.w3c.dom.Node getNode() {
+		return node;
+	}
+
+	/**
+	 * 
+	 * @return org.w3c.dom.Node
+	 */
+	public org.w3c.dom.Node getParent() {
+		return parent;
+	}
+
+	/**
+	 * 
+	 * @return java.util.List
+	 */
+	public java.util.List getProposals() {
+		return proposals;
+	}
+
+	public ITextRegion getRegion() {
+		return region;
+	}
+
+	/**
+	 * 
+	 * @return int
+	 */
+	public int getReplacementBeginPosition() {
+		return replacementBeginPosition;
+	}
+
+	/**
+	 * @return int
+	 */
+	public int getReplacementLength() {
+		return replacementLength;
+	}
+
+	public int getStartOffset() {
+		if ((getDocumentRegion() != null) && (getRegion() != null)) {
+			return ((ITextRegionCollection) getDocumentRegion()).getStartOffset(getRegion());
+		}
+		return -1;
+	}
+
+	public String getText() {
+		if ((getDocumentRegion() != null) && (getRegion() != null)) {
+			return ((ITextRegionCollection) getDocumentRegion()).getText(getRegion());
+		}
+		return ""; //$NON-NLS-1$
+	}
+
+	public int getTextEndOffset() {
+		if ((getDocumentRegion() != null) && (getRegion() != null)) {
+			return ((ITextRegionCollection) getDocumentRegion()).getTextEndOffset(getRegion());
+		}
+		return -1;
+	}
+
+	/**
+	 * @param region
+	 */
+	public void setDocumentRegion(IStructuredDocumentRegion region) {
+		documentRegion = region;
+	}
+
+	/**
+	 * 
+	 * @param newMatchString
+	 *            java.lang.String
+	 */
+	public void setMatchString(java.lang.String newMatchString) {
+		matchString = newMatchString;
+	}
+
+	/**
+	 * 
+	 * @param newNode
+	 *            org.w3c.dom.Node
+	 */
+	public void setNode(org.w3c.dom.Node newNode) {
+		node = newNode;
+	}
+
+	/**
+	 * 
+	 * @param newParent
+	 *            org.w3c.dom.Node
+	 */
+	public void setParent(org.w3c.dom.Node newParent) {
+		parent = newParent;
+	}
+
+	/**
+	 * 
+	 * @param newRegion
+	 */
+	public void setRegion(ITextRegion newRegion) {
+		region = newRegion;
+	}
+
+	/**
+	 * 
+	 * @param newReplacementBeginPosition
+	 *            int
+	 */
+	public void setReplacementBeginPosition(int newReplacementBeginPosition) {
+		replacementBeginPosition = newReplacementBeginPosition;
+	}
+
+
+	public void setReplacementLength(int newReplacementLength) {
+		replacementLength = newReplacementLength;
+	}
+
+	public boolean shouldSeparate() {
+		/*
+		 * if (separate == null) { PreferenceManager manager =
+		 * getPreferenceManager(); if(manager == null) { separate =
+		 * Boolean.FALSE; } else { Element caSettings =
+		 * manager.getElement(PreferenceNames.CONTENT_ASSIST); separate = new
+		 * Boolean(caSettings.getAttribute(PreferenceNames.SEPARATE).equals(PreferenceNames.TRUE)); } }
+		 * return separate.booleanValue();
+		 */
+		return false;
+	}
+
+	protected List sortProposals(List proposalsIn) {
+		Collections.sort(proposalsIn, new ProposalComparator());
+		return proposalsIn;
+
+	}
+
+	/**
+	 * 
+	 * @return java.lang.String
+	 */
+	public java.lang.String toString() {
+		return "Node: " + getNode() //$NON-NLS-1$
+					+ "\nParent: " + getParent() //$NON-NLS-1$
+					+ "\nStructuredDocumentRegion: " + StringUtils.escape(getDocumentRegion().toString()) //$NON-NLS-1$
+					+ "\nRegion: " + getRegion() //$NON-NLS-1$
+					+ "\nMatch string: '" + StringUtils.escape(getMatchString()) + "'" //$NON-NLS-2$//$NON-NLS-1$
+					+ "\nOffsets: [" + getReplacementBeginPosition() + "-" + (getReplacementBeginPosition() + getReplacementLength()) + "]\n"; //$NON-NLS-3$//$NON-NLS-2$//$NON-NLS-1$
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/ContextInfoModelUtil.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/ContextInfoModelUtil.java
new file mode 100644
index 0000000..a0c1c81
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/ContextInfoModelUtil.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.contentassist;
+
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.modelquery.ModelQueryUtil;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+
+
+/**
+ * @author pavery
+ */
+public class ContextInfoModelUtil {
+	IStructuredDocument fDocument = null;
+
+	ContextInfoModelUtil(IStructuredDocument doc) {
+		fDocument = doc;
+	}
+
+	public IStructuredDocument getDocument() {
+		return fDocument;
+	}
+
+	public ModelQuery getModelQuery() {
+		ModelQuery mq = null;
+
+		IStructuredModel xmlModel = null;
+		try {
+			xmlModel = StructuredModelManager.getModelManager().getExistingModelForRead(getDocument());
+			mq = ModelQueryUtil.getModelQuery(xmlModel);
+		}
+		finally {
+			if (xmlModel != null) {
+				xmlModel.releaseFromRead();
+			}
+		}
+		return mq;
+	}
+
+	public IDOMNode getXMLNode(int offset) {
+		IStructuredModel xmlModel = null;
+		IDOMNode xmlNode = null;
+		try {
+			xmlModel = StructuredModelManager.getModelManager().getExistingModelForRead(getDocument());
+			if (xmlModel != null) {
+				xmlNode = (IDOMNode) xmlModel.getIndexedRegion(offset);
+			}
+		}
+		finally {
+			if (xmlModel != null)
+				xmlModel.releaseFromRead();
+		}
+		return xmlNode;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/CustomTemplateProposal.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/CustomTemplateProposal.java
new file mode 100644
index 0000000..f19dd90
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/CustomTemplateProposal.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.contentassist;
+
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.templates.Template;
+import org.eclipse.jface.text.templates.TemplateContext;
+import org.eclipse.jface.text.templates.TemplateProposal;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.wst.sse.core.utils.StringUtils;
+import org.eclipse.wst.sse.ui.internal.contentassist.IRelevanceCompletionProposal;
+
+/**
+ * Purpose of this class is to make the additional proposal info into content
+ * fit for an HTML viewer (by escaping characters)
+ */
+class CustomTemplateProposal extends TemplateProposal implements IRelevanceCompletionProposal {
+	// copies of this class exist in:
+	// org.eclipse.jst.jsp.ui.internal.contentassist
+	// org.eclipse.wst.html.ui.internal.contentassist
+	// org.eclipse.wst.xml.ui.internal.contentassist
+
+	public CustomTemplateProposal(Template template, TemplateContext context, IRegion region, Image image, int relevance) {
+		super(template, context, region, image, relevance);
+	}
+
+	public String getAdditionalProposalInfo() {
+		String additionalInfo = super.getAdditionalProposalInfo();
+		return StringUtils.convertToHTMLContent(additionalInfo);
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/DefaultXMLCompletionProposalComputer.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/DefaultXMLCompletionProposalComputer.java
new file mode 100644
index 0000000..5b4024f
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/DefaultXMLCompletionProposalComputer.java
@@ -0,0 +1,200 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.contentassist;
+
+import java.util.Properties;
+import java.util.Vector;
+
+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.ui.contentassist.CompletionProposalInvocationContext;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+
+/**
+ * <p>Default implementation of the {@link AbstractXMLCompletionProposalComputer}, defaults are to do nothing</p>
+ */
+public class DefaultXMLCompletionProposalComputer extends
+		AbstractXMLCompletionProposalComputer {
+
+	/**
+	 * Default behavior is do to nothing.
+	 * 
+	 * @see org.eclipse.wst.sse.ui.contentassist.ICompletionProposalComputer#sessionEnded()
+	 */
+	public void sessionEnded() {
+		//default behavior is to do nothing
+	}
+
+	/**
+	 * Default behavior is do to nothing.
+	 * 
+	 * @see org.eclipse.wst.sse.ui.contentassist.ICompletionProposalComputer#sessionStarted()
+	 */
+	public void sessionStarted() {
+		//default behavior is to do nothing
+	}
+	
+	/**
+	 * Default behavior is do to nothing.
+	 * 
+	 * @see org.eclipse.wst.xml.ui.internal.contentassist.AbstractXMLCompletionProposalComputer#addAttributeNameProposals(org.eclipse.wst.xml.ui.internal.contentassist.ContentAssistRequest, org.eclipse.wst.sse.ui.contentassist.CompletionProposalInvocationContext)
+	 */
+	protected void addAttributeNameProposals(
+			ContentAssistRequest contentAssistRequest,
+			CompletionProposalInvocationContext context) {
+		//default behavior is to do nothing
+	}
+
+	/**
+	 * Default behavior is do to nothing.
+	 * 
+	 * @see org.eclipse.wst.xml.ui.internal.contentassist.AbstractXMLCompletionProposalComputer#addAttributeValueProposals(org.eclipse.wst.xml.ui.internal.contentassist.ContentAssistRequest, org.eclipse.wst.sse.ui.contentassist.CompletionProposalInvocationContext)
+	 */
+	protected void addAttributeValueProposals(
+			ContentAssistRequest contentAssistRequest,
+			CompletionProposalInvocationContext context) {
+		//default behavior is to do nothing
+	}
+
+	/**
+	 * Default behavior is do to nothing.
+	 * 
+	 * @see org.eclipse.wst.xml.ui.internal.contentassist.AbstractXMLCompletionProposalComputer#addCommentProposal(org.eclipse.wst.xml.ui.internal.contentassist.ContentAssistRequest, org.eclipse.wst.sse.ui.contentassist.CompletionProposalInvocationContext)
+	 */
+	protected void addCommentProposal(
+			ContentAssistRequest contentAssistRequest,
+			CompletionProposalInvocationContext context) {
+		//default behavior is to do nothing
+	}
+
+	/**
+	 * Default behavior is do to nothing.
+	 * 
+	 * @see org.eclipse.wst.xml.ui.internal.contentassist.AbstractXMLCompletionProposalComputer#addDocTypeProposal(org.eclipse.wst.xml.ui.internal.contentassist.ContentAssistRequest, org.eclipse.wst.sse.ui.contentassist.CompletionProposalInvocationContext)
+	 */
+	protected void addDocTypeProposal(
+			ContentAssistRequest contentAssistRequest,
+			CompletionProposalInvocationContext context) {
+		//default behavior is to do nothing
+	}
+
+	/**
+	 * Default behavior is do to nothing.
+	 * 
+	 * @see org.eclipse.wst.xml.ui.internal.contentassist.AbstractXMLCompletionProposalComputer#addEmptyDocumentProposals(org.eclipse.wst.xml.ui.internal.contentassist.ContentAssistRequest, org.eclipse.wst.sse.ui.contentassist.CompletionProposalInvocationContext)
+	 */
+	protected void addEmptyDocumentProposals(
+			ContentAssistRequest contentAssistRequest,
+			CompletionProposalInvocationContext context) {
+		//default behavior is to do nothing
+	}
+
+	/**
+	 * Default behavior is do to nothing.
+	 * 
+	 * @see org.eclipse.wst.xml.ui.internal.contentassist.AbstractXMLCompletionProposalComputer#addEndTagNameProposals(org.eclipse.wst.xml.ui.internal.contentassist.ContentAssistRequest, org.eclipse.wst.sse.ui.contentassist.CompletionProposalInvocationContext)
+	 */
+	protected void addEndTagNameProposals(
+			ContentAssistRequest contentAssistRequest,
+			CompletionProposalInvocationContext context) {
+		//default behavior is to do nothing
+	}
+
+	/**
+	 * Default behavior is do to nothing.
+	 * 
+	 * @see org.eclipse.wst.xml.ui.internal.contentassist.AbstractXMLCompletionProposalComputer#addEndTagProposals(org.eclipse.wst.xml.ui.internal.contentassist.ContentAssistRequest, org.eclipse.wst.sse.ui.contentassist.CompletionProposalInvocationContext)
+	 */
+	protected void addEndTagProposals(
+			ContentAssistRequest contentAssistRequest,
+			CompletionProposalInvocationContext context) {
+		//default behavior is to do nothing
+	}
+
+	/**
+	 * Default behavior is do to nothing.
+	 * 
+	 * @see org.eclipse.wst.xml.ui.internal.contentassist.AbstractXMLCompletionProposalComputer#addEntityProposals(org.eclipse.wst.xml.ui.internal.contentassist.ContentAssistRequest, org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion, org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode, org.eclipse.wst.sse.ui.contentassist.CompletionProposalInvocationContext)
+	 */
+	protected void addEntityProposals(
+			ContentAssistRequest contentAssistRequest,
+			ITextRegion completionRegion, IDOMNode treeNode,
+			CompletionProposalInvocationContext context) {
+		//default behavior is to do nothing
+	}
+
+	/**
+	 * Default behavior is do to nothing.
+	 * 
+	 * @see org.eclipse.wst.xml.ui.internal.contentassist.AbstractXMLCompletionProposalComputer#addEntityProposals(java.util.Vector, java.util.Properties, java.lang.String, int, org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion, org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion, org.eclipse.wst.sse.ui.contentassist.CompletionProposalInvocationContext)
+	 */
+	protected void addEntityProposals(Vector proposals, Properties map,
+			String key, int nodeOffset, IStructuredDocumentRegion sdRegion,
+			ITextRegion completionRegion,
+			CompletionProposalInvocationContext context) {
+		//default behavior is to do nothing
+	}
+
+	/**
+	 * Default behavior is do to nothing.
+	 * 
+	 * @see org.eclipse.wst.xml.ui.internal.contentassist.AbstractXMLCompletionProposalComputer#addPCDATAProposal(java.lang.String, org.eclipse.wst.xml.ui.internal.contentassist.ContentAssistRequest, org.eclipse.wst.sse.ui.contentassist.CompletionProposalInvocationContext)
+	 */
+	protected void addPCDATAProposal(String nodeName,
+			ContentAssistRequest contentAssistRequest,
+			CompletionProposalInvocationContext context) {
+		//default behavior is to do nothing
+	}
+
+	/**
+	 * Default behavior is do to nothing.
+	 * 
+	 * @see org.eclipse.wst.xml.ui.internal.contentassist.AbstractXMLCompletionProposalComputer#addStartDocumentProposals(org.eclipse.wst.xml.ui.internal.contentassist.ContentAssistRequest, org.eclipse.wst.sse.ui.contentassist.CompletionProposalInvocationContext)
+	 */
+	protected void addStartDocumentProposals(
+			ContentAssistRequest contentAssistRequest,
+			CompletionProposalInvocationContext context) {
+		//default behavior is to do nothing
+	}
+
+	/**
+	 * Default behavior is do to nothing.
+	 * 
+	 * @see org.eclipse.wst.xml.ui.internal.contentassist.AbstractXMLCompletionProposalComputer#addTagCloseProposals(org.eclipse.wst.xml.ui.internal.contentassist.ContentAssistRequest, org.eclipse.wst.sse.ui.contentassist.CompletionProposalInvocationContext)
+	 */
+	protected void addTagCloseProposals(
+			ContentAssistRequest contentAssistRequest,
+			CompletionProposalInvocationContext context) {
+		//default behavior is to do nothing
+	}
+
+	/**
+	 * Default behavior is do to nothing.
+	 * 
+	 * @see org.eclipse.wst.xml.ui.internal.contentassist.AbstractXMLCompletionProposalComputer#addTagInsertionProposals(org.eclipse.wst.xml.ui.internal.contentassist.ContentAssistRequest, int, org.eclipse.wst.sse.ui.contentassist.CompletionProposalInvocationContext)
+	 */
+	protected void addTagInsertionProposals(
+			ContentAssistRequest contentAssistRequest, int childPosition,
+			CompletionProposalInvocationContext context) {
+		//default behavior is to do nothing
+	}
+
+	/**
+	 * Default behavior is do to nothing.
+	 * 
+	 * @see org.eclipse.wst.xml.ui.internal.contentassist.AbstractXMLCompletionProposalComputer#addTagNameProposals(org.eclipse.wst.xml.ui.internal.contentassist.ContentAssistRequest, int, org.eclipse.wst.sse.ui.contentassist.CompletionProposalInvocationContext)
+	 */
+	protected void addTagNameProposals(
+			ContentAssistRequest contentAssistRequest, int childPosition,
+			CompletionProposalInvocationContext context) {
+		//default behavior is to do nothing
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/NoRegionContentAssistProcessor.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/NoRegionContentAssistProcessor.java
new file mode 100644
index 0000000..c713a22
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/NoRegionContentAssistProcessor.java
@@ -0,0 +1,275 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.contentassist;
+
+
+
+import java.util.HashMap;
+import java.util.Iterator;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.ITypedRegion;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
+import org.eclipse.jface.text.contentassist.IContextInformation;
+import org.eclipse.jface.text.contentassist.IContextInformationValidator;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.ui.internal.IReleasable;
+import org.eclipse.wst.sse.ui.internal.StructuredTextViewer;
+import org.eclipse.wst.sse.ui.internal.contentassist.ContentAssistUtils;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+import org.eclipse.wst.xml.core.text.IXMLPartitions;
+
+
+/**
+ * ContentAssistProcessor to handle special cases in content assist where the
+ * partitioner cannot determine a partition type at the current cursor
+ * position (usually at EOF).
+ * 
+ * @author pavery
+ * @deprecated This class is no longer used locally and will be removed in the future
+ */
+public class NoRegionContentAssistProcessor implements IContentAssistProcessor, IReleasable {
+
+	private static final boolean DEBUG = false;
+	protected char completionProposalAutoActivationCharacters[] = null;
+	protected char contextInformationAutoActivationCharacters[] = null;
+
+	private final ICompletionProposal[] EMPTY_PROPOSAL_SET = new ICompletionProposal[0];
+	protected String fErrorMessage = null;
+	private HashMap fNameToProcessorMap = null;
+	private HashMap fPartitionToProcessorMap = null;
+
+	public NoRegionContentAssistProcessor() {
+		super();
+	}
+
+	protected void addPartitionProcessor(String key, IContentAssistProcessor processor) {
+		addProcessor(getPartitionToProcessorMap(), key, processor);
+	}
+
+	protected void addNameProcessor(String key, IContentAssistProcessor processor) {
+		addProcessor(getNameToProcessorMap(), key, processor);
+	}
+
+	protected IContentAssistProcessor getPartitionProcessor(String key) {
+		return (IContentAssistProcessor) getPartitionToProcessorMap().get(key);
+	}
+
+	/**
+	 * Ensures release if it's a duplicate partition type.
+	 * 
+	 * @param map
+	 * @param key
+	 * @param processor
+	 */
+	private void addProcessor(HashMap map, String key, IContentAssistProcessor processor) {
+		Object o = map.remove(key);
+		if (o != null) {
+			if (o instanceof IReleasable) {
+				((IReleasable) o).release();
+			}
+		}
+		map.put(key, processor);
+	}
+
+	/**
+	 * Figures out what the correct ICompletionProposalProcessor is and
+	 * computesCompletionProposals on that.
+	 * 
+	 * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#computeCompletionProposals(org.eclipse.jface.text.ITextViewer,
+	 *      int)
+	 */
+	public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int documentOffset) {
+		IContentAssistProcessor p = null;
+		ICompletionProposal[] results = EMPTY_PROPOSAL_SET;
+
+		p = guessContentAssistProcessor(viewer, documentOffset);
+		if (p != null) {
+			results = p.computeCompletionProposals(viewer, documentOffset);
+		}
+
+		return (results != null) ? results : EMPTY_PROPOSAL_SET;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#computeContextInformation(org.eclipse.jface.text.ITextViewer,
+	 *      int)
+	 */
+	public IContextInformation[] computeContextInformation(ITextViewer viewer, int documentOffset) {
+		// get context info from processor that we end up using...
+		return null;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getCompletionProposalAutoActivationCharacters()
+	 */
+	public char[] getCompletionProposalAutoActivationCharacters() {
+		return completionProposalAutoActivationCharacters;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getContextInformationAutoActivationCharacters()
+	 */
+	public char[] getContextInformationAutoActivationCharacters() {
+		return contextInformationAutoActivationCharacters;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getContextInformationValidator()
+	 */
+	public IContextInformationValidator getContextInformationValidator() {
+		// return the validator for the content assist processor that we
+		// used...
+		return null;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getErrorMessage()
+	 */
+	public String getErrorMessage() {
+		return fErrorMessage;
+	}
+	
+	private HashMap getNameToProcessorMap() {
+		if (fNameToProcessorMap == null) {
+			fNameToProcessorMap = new HashMap();
+			initNameToProcessorMap();
+		}
+		return fNameToProcessorMap;
+	}
+	
+	private HashMap getPartitionToProcessorMap() {
+		if (fPartitionToProcessorMap == null) {
+			fPartitionToProcessorMap = new HashMap();
+			initPartitionToProcessorMap();
+		}
+		return fPartitionToProcessorMap;
+	}
+
+	/**
+	 * Gives you the document partition type (String) for the given
+	 * StructuredTextViewer and documentPosition.
+	 * 
+	 * @param viewer
+	 * @param documentPosition
+	 * @return String
+	 */
+	protected String getPartitionType(StructuredTextViewer viewer, int documentPosition) {
+		IDocument document = viewer.getDocument();
+		String partitionType = null;
+		ITypedRegion partition = null;
+		try {
+			partition = document.getPartition(documentPosition);
+			partitionType = partition.getType();
+		}
+		catch (BadLocationException e) {
+			partitionType = null;
+		}
+		return partitionType;
+	}
+
+	/**
+	 * Guesses a ContentAssistProcessor based on the TextViewer and
+	 * documentOffset.
+	 * 
+	 * @param viewer
+	 * @param documentOffset
+	 */
+	protected IContentAssistProcessor guessContentAssistProcessor(ITextViewer viewer, int documentOffset) {
+		// mapping logic here...
+		// look @ previous region
+		// look @ previous doc partition type
+		// look @ page language
+		IContentAssistProcessor p = null;
+		IStructuredDocumentRegion sdRegion = ContentAssistUtils.getStructuredDocumentRegion(viewer, documentOffset);
+		if (sdRegion != null) {
+			String currentRegionType = sdRegion.getType();
+			// System.out.println("current region type is >> " +
+			// currentRegionType);
+			if (currentRegionType == DOMRegionContext.UNDEFINED) {
+				IStructuredDocumentRegion sdPrev = sdRegion.getPrevious();
+				if (sdPrev != null) {
+					if (DEBUG) {
+						String prevRegionType = sdPrev.getType();
+						System.out.println("previous region type is >> " + prevRegionType); //$NON-NLS-1$
+					}
+				}
+			}
+		}
+		// working w/ viewer & document partition
+		if ((p == null) && (viewer.getDocument().getLength() > 0)) {
+			String prevPartitionType = getPartitionType((StructuredTextViewer) viewer, documentOffset - 1);
+			// System.out.println("previous partition type is > " +
+			// prevPartitionType);
+			p = (IContentAssistProcessor) getPartitionToProcessorMap().get(prevPartitionType);
+		}
+		return p;
+	}
+
+	/**
+	 * Inits map for extra ContentAssistProcessors (useBean, get/setProperty)
+	 */
+	protected void initNameToProcessorMap() {
+		// nothing to do in this case
+	}
+
+	/**
+	 * Adds all relevent ContentAssistProcessors to the partition to processor
+	 * map (just XML here)
+	 */
+	protected void initPartitionToProcessorMap() {
+		XMLContentAssistProcessor xmlProcessor = new XMLContentAssistProcessor();
+		addProcessor(getPartitionToProcessorMap(), IXMLPartitions.XML_DEFAULT, xmlProcessor);
+	}
+
+	public void release() {
+		releasePartitionToProcessorMap();
+		releaseNameToProcessorMap();
+	}
+
+	protected void releaseMap(HashMap map) {
+		if ((map != null) && !map.isEmpty()) {
+			Iterator it = map.keySet().iterator();
+			Object key = null;
+			while (it.hasNext()) {
+				key = it.next();
+				if (map.get(key) instanceof IReleasable) {
+					((IReleasable) map.get(key)).release();
+				}
+			}
+			map.clear();
+			map = null;
+		}
+	}
+
+	protected void releaseNameToProcessorMap() {
+		releaseMap(fNameToProcessorMap);
+	}
+
+	protected void releasePartitionToProcessorMap() {
+		releaseMap(fPartitionToProcessorMap);
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/NonValidatingModelQueryAction.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/NonValidatingModelQueryAction.java
new file mode 100644
index 0000000..24a397d
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/NonValidatingModelQueryAction.java
@@ -0,0 +1,159 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.contentassist;
+
+
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+public class NonValidatingModelQueryAction implements org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQueryAction {
+
+	protected CMNode cmnode = null;
+	protected int endIndex = 0;
+	protected int kind = INSERT;
+	protected int startIndex = 0;
+	protected Object userData = null;
+
+	/**
+	 * NonValidatingModelQueryAction constructor comment.
+	 */
+	protected NonValidatingModelQueryAction() {
+		super();
+	}
+
+	/**
+	 * NonValidatingModelQueryAction constructor comment.
+	 */
+	public NonValidatingModelQueryAction(CMNode newChild, int newKind, int newStart, int newEnd, Object newUserData) {
+		super();
+		cmnode = newChild;
+		kind = newKind;
+		startIndex = newStart;
+		endIndex = newEnd;
+		userData = newUserData;
+	}
+
+	/**
+	 * getCMNode method comment.
+	 */
+	public org.eclipse.wst.xml.core.internal.contentmodel.CMNode getCMNode() {
+		return cmnode;
+	}
+
+	/**
+	 * 
+	 * @return int
+	 */
+	public int getEndIndex() {
+		return endIndex;
+	}
+
+	/**
+	 * 
+	 * @return int
+	 */
+	public int getKind() {
+		return kind;
+	}
+
+	/**
+	 * getParent method comment.
+	 */
+	public org.w3c.dom.Node getParent() {
+		return null;
+	}
+
+	/**
+	 * 
+	 * @return int
+	 */
+	public int getStartIndex() {
+		return startIndex;
+	}
+
+	/**
+	 * getUserData method comment.
+	 */
+	public Object getUserData() {
+		return null;
+	}
+
+	/**
+	 * performAction method comment.
+	 */
+	public void performAction() {
+	}
+
+	/**
+	 * setCMNode method comment.
+	 */
+	protected void setCMNode(org.eclipse.wst.xml.core.internal.contentmodel.CMNode newNode) {
+		cmnode = newNode;
+	}
+
+	/**
+	 * 
+	 * @param newEndIndex
+	 *            int
+	 */
+	protected void setEndIndex(int newEndIndex) {
+		endIndex = newEndIndex;
+	}
+
+	/**
+	 * 
+	 * @param newKind
+	 *            int
+	 */
+	protected void setKind(int newKind) {
+		kind = newKind;
+	}
+
+	/**
+	 * 
+	 * @param newStartIndex
+	 *            int
+	 */
+	protected void setStartIndex(int newStartIndex) {
+		startIndex = newStartIndex;
+	}
+
+	/**
+	 * setUserData method comment.
+	 */
+	public void setUserData(Object object) {
+	}
+
+	/**
+	 * 
+	 * @return java.lang.String
+	 */
+	public String toString() {
+		String actionName = null;
+		switch (kind) {
+			case INSERT :
+				actionName = "INSERT";//$NON-NLS-1$
+				break;
+			case REMOVE :
+				actionName = "REMOVE";//$NON-NLS-1$
+				break;
+			case REPLACE :
+				actionName = "REPLACE";//$NON-NLS-1$
+				break;
+			default :
+				actionName = "UNKNOWN ACTION ";//$NON-NLS-1$
+		}
+		String nodeName = (cmnode != null) ? getCMNode().getNodeName() : "(unknown)";//$NON-NLS-1$
+		return actionName + "=" + nodeName + "(" + startIndex + "..." + endIndex + ")";//$NON-NLS-4$//$NON-NLS-3$//$NON-NLS-2$//$NON-NLS-1$
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/ProposalComparator.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/ProposalComparator.java
new file mode 100644
index 0000000..ee6e8e8
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/ProposalComparator.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.contentassist;
+
+
+
+import java.util.Comparator;
+
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.wst.sse.ui.internal.contentassist.IRelevanceCompletionProposal;
+
+
+public class ProposalComparator implements Comparator {
+
+
+	public int compare(Object o1, Object o2) {
+		int relevance = 0;
+		if ((o1 instanceof IRelevanceCompletionProposal) && (o2 instanceof IRelevanceCompletionProposal)) {
+			// sort based on relevance
+			IRelevanceCompletionProposal cp1 = (IRelevanceCompletionProposal) o1;
+			IRelevanceCompletionProposal cp2 = (IRelevanceCompletionProposal) o2;
+
+			relevance = cp2.getRelevance() - cp1.getRelevance();
+
+			// if same relevance, secondary sort (lexigraphically)
+			if ((relevance == 0) && (o1 instanceof ICompletionProposal) && (o2 instanceof ICompletionProposal)) {
+				String displayString1 = ((ICompletionProposal) o1).getDisplayString();
+				String displayString2 = ((ICompletionProposal) o2).getDisplayString();
+				if ((displayString1 != null) && (displayString2 != null)) {
+					// relevance = displayString1.compareTo(displayString2);
+					// // this didn't mix caps w/ lowercase
+					relevance = com.ibm.icu.text.Collator.getInstance().compare(displayString1, displayString2);
+				}
+			}
+		}
+		// otherwise if it's not ISEDRelevanceCompletionProposal, don't sort
+		return relevance;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/ReplaceNameTemplateContext.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/ReplaceNameTemplateContext.java
new file mode 100644
index 0000000..fefb8a3
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/ReplaceNameTemplateContext.java
@@ -0,0 +1,113 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 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
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.contentassist;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.templates.DocumentTemplateContext;
+import org.eclipse.jface.text.templates.Template;
+import org.eclipse.jface.text.templates.TemplateBuffer;
+import org.eclipse.jface.text.templates.TemplateContextType;
+import org.eclipse.jface.text.templates.TemplateException;
+import org.eclipse.jface.text.templates.TemplateVariable;
+
+/**
+ * Just like DocumentTemplateContext except if an insert offset is passed in,
+ * during evaluation, the "prefix" before the template will be checked to see
+ * if it matches the template name. If so, overwrite the template name.
+ * Otherwise, just insert the template at the insert offset location (by not
+ * overwriting the prefix text)
+ */
+public class ReplaceNameTemplateContext extends DocumentTemplateContext {
+	private int fInsertOffset = -1;
+
+	/**
+	 * Creates a document template context.
+	 * 
+	 * @param type
+	 *            the context type
+	 * @param document
+	 *            the document this context applies to
+	 * @param offset
+	 *            the offset of the document region
+	 * @param length
+	 *            the length of the document region
+	 */
+	public ReplaceNameTemplateContext(TemplateContextType type, IDocument document, int offset, int length) {
+		this(type, document, new Position(offset, length));
+	}
+
+	/**
+	 * Creates a document template context. The supplied <code>Position</code>
+	 * will be queried to compute the <code>getStart</code> and
+	 * <code>getEnd</code> methods, which will therefore answer updated
+	 * position data if it is registered with the document.
+	 * 
+	 * @param type
+	 *            the context type
+	 * @param document
+	 *            the document this context applies to
+	 * @param position
+	 *            the position describing the area of the document which forms
+	 *            the template context
+	 * @since 3.1
+	 */
+	public ReplaceNameTemplateContext(TemplateContextType type, IDocument document, Position position) {
+		super(type, document, position);
+	}
+
+	/**
+	 * Creates a document template context.
+	 * 
+	 * @param type
+	 *            the context type
+	 * @param document
+	 *            the document this context applies to
+	 * @param offset
+	 *            the offset of the document region
+	 * @param length
+	 *            the length of the document region
+	 * @param insertOffset
+	 *            the offset of the document region where insert was
+	 *            originally requested
+	 */
+	public ReplaceNameTemplateContext(TemplateContextType type, IDocument document, int offset, int length, int insertOffset) {
+		this(type, document, new Position(offset, length));
+		fInsertOffset = insertOffset;
+	}
+
+	/*
+	 * @see org.eclipse.jface.text.templates.TemplateContext#evaluate(org.eclipse.jface.text.templates.Template)
+	 */
+	public TemplateBuffer evaluate(Template template) throws BadLocationException, TemplateException {
+		TemplateBuffer buffer = super.evaluate(template);
+		if (buffer != null) {
+			if ((fInsertOffset > -1) && (fInsertOffset > getStart())) {
+				String prefix = getDocument().get(getStart(), fInsertOffset - getStart());
+				if (!template.getName().startsWith(prefix)) {
+					// generate a new buffer that actually contains the
+					// text that was going to be overwritten
+					int prefixSize = prefix.length();
+					TemplateVariable[] newTemplateVar = buffer.getVariables();
+					for (int i =0; i < newTemplateVar.length; i++ ){
+						int[] offsets = newTemplateVar[i].getOffsets();
+						for (int j=0; j<offsets.length ;j++){
+							offsets[j] += prefixSize;
+						}
+					}
+					buffer = new TemplateBuffer(prefix + buffer.getString(), newTemplateVar);
+				}
+			}
+		}
+		return buffer;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/SimpleCMElementDeclaration.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/SimpleCMElementDeclaration.java
new file mode 100644
index 0000000..41a607a
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/SimpleCMElementDeclaration.java
@@ -0,0 +1,170 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.contentassist;
+
+
+
+public class SimpleCMElementDeclaration implements org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration {
+
+	String fNodeName;
+
+	/**
+	 * SimpleCMELementDeclaration constructor comment.
+	 */
+	public SimpleCMElementDeclaration() {
+		super();
+	}
+
+	public SimpleCMElementDeclaration(String nodeName) {
+		super();
+		setNodeName(nodeName);
+	}
+
+	/**
+	 * getAttributes method
+	 * 
+	 * @return CMNamedNodeMap
+	 * 
+	 * Returns CMNamedNodeMap of AttributeDeclaration
+	 */
+	public org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap getAttributes() {
+		return null;
+	}
+
+	/**
+	 * getCMContent method
+	 * 
+	 * @return CMContent
+	 * 
+	 * Returns the root node of this element's content model. This can be an
+	 * CMElementDeclaration or a CMGroup
+	 */
+	public org.eclipse.wst.xml.core.internal.contentmodel.CMContent getContent() {
+		return null;
+	}
+
+	/**
+	 * getContentType method
+	 * 
+	 * @return int
+	 * 
+	 * Returns one of : ANY, EMPTY, ELEMENT, MIXED, PCDATA, CDATA.
+	 */
+	public int getContentType() {
+		return 0;
+	}
+
+	/**
+	 * getDataType method
+	 * 
+	 * @return java.lang.String
+	 */
+	public org.eclipse.wst.xml.core.internal.contentmodel.CMDataType getDataType() {
+		return null;
+	}
+
+	/**
+	 * getElementName method
+	 * 
+	 * @return java.lang.String
+	 */
+	public String getElementName() {
+		return null;
+	}
+
+	/**
+	 * getLocalElements method
+	 * 
+	 * @return CMNamedNodeMap
+	 * 
+	 * Returns a list of locally defined elements.
+	 */
+	public org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap getLocalElements() {
+		return null;
+	}
+
+	/**
+	 * getMaxOccur method
+	 * 
+	 * @return int
+	 * 
+	 * If -1, it's UNBOUNDED.
+	 */
+	public int getMaxOccur() {
+		return 0;
+	}
+
+	/**
+	 * getMinOccur method
+	 * 
+	 * @return int
+	 * 
+	 * If 0, it's OPTIONAL. If 1, it's REQUIRED.
+	 */
+	public int getMinOccur() {
+		return 0;
+	}
+
+	/**
+	 * 
+	 * @return java.lang.String
+	 */
+	public java.lang.String getNodeName() {
+		return fNodeName;
+	}
+
+	/**
+	 * getNodeType method
+	 * 
+	 * @return int
+	 * 
+	 * Returns one of :
+	 * 
+	 */
+	public int getNodeType() {
+		return 0;
+	}
+
+	/**
+	 * getProperty method
+	 * 
+	 * @return java.lang.Object
+	 * 
+	 * Returns the object property desciped by the propertyName
+	 * 
+	 */
+	public Object getProperty(String propertyName) {
+		return null;
+	}
+
+	/**
+	 * 
+	 * @param newNodeName
+	 *            java.lang.String
+	 */
+	public void setNodeName(java.lang.String newNodeName) {
+		fNodeName = newNodeName;
+	}
+
+	/**
+	 * supports method
+	 * 
+	 * @return boolean
+	 * 
+	 * Returns true if the CMNode supports a specified property
+	 * 
+	 */
+	public boolean supports(String propertyName) {
+		return false;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/SourceEditorImageHelper.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/SourceEditorImageHelper.java
new file mode 100644
index 0000000..fe16777
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/SourceEditorImageHelper.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.contentassist;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.eclipse.wst.xml.ui.internal.XMLUIPlugin;
+
+
+/**
+ * @deprecated use internal XMLEditorPluginImageHelper or external
+ *             SharedXMLEditorPluginImageHelper instead
+ */
+public class SourceEditorImageHelper {
+
+	public SourceEditorImageHelper() {
+		super();
+	}
+
+	public Image createImage(String resource) {
+		ImageDescriptor desc = AbstractUIPlugin.imageDescriptorFromPlugin(XMLUIPlugin.ID, resource);
+		Image image = desc.createImage();
+		JFaceResources.getImageRegistry().put(resource, image);
+		return image;
+	}
+
+	public Image getImage(String resource) {
+		Image image = JFaceResources.getImageRegistry().get(resource);
+		if (image == null) {
+			image = createImage(resource);
+		}
+		return image;
+	}
+
+
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/XMLContentAssistProcessor.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/XMLContentAssistProcessor.java
new file mode 100644
index 0000000..20d4451
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/XMLContentAssistProcessor.java
@@ -0,0 +1,170 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.contentassist;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.eclipse.wst.xml.ui.internal.XMLUIPlugin;
+import org.eclipse.wst.xml.ui.internal.preferences.XMLUIPreferenceNames;
+import org.eclipse.wst.xml.ui.internal.templates.TemplateContextTypeIdsXML;
+
+/**
+ * @deprecated This class is no longer used locally and will be removed in the future
+ * @see XMLStructuredContentAssistProcessor
+ */
+public class XMLContentAssistProcessor extends AbstractContentAssistProcessor implements IPropertyChangeListener {
+
+	protected IPreferenceStore fPreferenceStore = null;
+	protected IResource fResource = null;
+	private XMLTemplateCompletionProcessor fTemplateProcessor = null;
+	private List fTemplateContexts = new ArrayList();
+
+	public XMLContentAssistProcessor() {
+		super();
+	}
+
+	protected void addAttributeNameProposals(ContentAssistRequest contentAssistRequest) {
+		addTemplates(contentAssistRequest, TemplateContextTypeIdsXML.ATTRIBUTE);
+		super.addAttributeNameProposals(contentAssistRequest);
+	}
+
+	protected void addAttributeValueProposals(ContentAssistRequest contentAssistRequest) {
+		addTemplates(contentAssistRequest, TemplateContextTypeIdsXML.ATTRIBUTE_VALUE);
+		super.addAttributeValueProposals(contentAssistRequest);
+	}
+
+	protected void addEmptyDocumentProposals(ContentAssistRequest contentAssistRequest) {
+		addTemplates(contentAssistRequest, TemplateContextTypeIdsXML.NEW);
+		super.addEmptyDocumentProposals(contentAssistRequest);
+	}
+
+	protected void addTagInsertionProposals(ContentAssistRequest contentAssistRequest, int childPosition) {
+		addTemplates(contentAssistRequest, TemplateContextTypeIdsXML.TAG);
+		super.addTagInsertionProposals(contentAssistRequest, childPosition);
+	}
+
+	/**
+	 * Adds templates to the list of proposals
+	 * 
+	 * @param contentAssistRequest
+	 * @param context
+	 */
+	private void addTemplates(ContentAssistRequest contentAssistRequest, String context) {
+		addTemplates(contentAssistRequest, context, contentAssistRequest.getReplacementBeginPosition());
+	}
+
+	/**
+	 * Adds templates to the list of proposals
+	 * 
+	 * @param contentAssistRequest
+	 * @param context
+	 * @param startOffset
+	 */
+	private void addTemplates(ContentAssistRequest contentAssistRequest, String context, int startOffset) {
+		if (contentAssistRequest == null) {
+			return;
+		}
+
+		// if already adding template proposals for a certain context type, do
+		// not add again
+		if (!fTemplateContexts.contains(context)) {
+			fTemplateContexts.add(context);
+			boolean useProposalList = !contentAssistRequest.shouldSeparate();
+
+			if (getTemplateCompletionProcessor() != null) {
+				getTemplateCompletionProcessor().setContextType(context);
+				ICompletionProposal[] proposals = getTemplateCompletionProcessor().computeCompletionProposals(fTextViewer, startOffset);
+				for (int i = 0; i < proposals.length; ++i) {
+					if (useProposalList) {
+						contentAssistRequest.addProposal(proposals[i]);
+					}
+					else {
+						contentAssistRequest.addMacro(proposals[i]);
+					}
+				}
+			}
+		}
+	}
+
+	protected ContentAssistRequest computeCompletionProposals(int documentPosition, String matchString, ITextRegion completionRegion, IDOMNode treeNode, IDOMNode xmlnode) {
+		ContentAssistRequest request = super.computeCompletionProposals(documentPosition, matchString, completionRegion, treeNode, xmlnode);
+		// bug115927 use original document position for all/any region
+		// templates
+		addTemplates(request, TemplateContextTypeIdsXML.ALL, documentPosition);
+		return request;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.wst.xml.ui.contentassist.AbstractContentAssistProcessor#computeCompletionProposals(org.eclipse.jface.text.ITextViewer,
+	 *      int)
+	 */
+	public ICompletionProposal[] computeCompletionProposals(ITextViewer textViewer, int documentPosition) {
+		fTemplateContexts.clear();
+		return super.computeCompletionProposals(textViewer, documentPosition);
+	}
+
+	protected IPreferenceStore getPreferenceStore() {
+		if (fPreferenceStore == null) {
+			fPreferenceStore = XMLUIPlugin.getDefault().getPreferenceStore();
+		}
+		return fPreferenceStore;
+	}
+
+	private XMLTemplateCompletionProcessor getTemplateCompletionProcessor() {
+		if (fTemplateProcessor == null) {
+			fTemplateProcessor = new XMLTemplateCompletionProcessor();
+		}
+		return fTemplateProcessor;
+	}
+
+	protected void init() {
+		getPreferenceStore().addPropertyChangeListener(this);
+		reinit();
+	}
+
+	public void propertyChange(PropertyChangeEvent event) {
+		String property = event.getProperty();
+
+		if ((property.compareTo(XMLUIPreferenceNames.AUTO_PROPOSE) == 0) || (property.compareTo(XMLUIPreferenceNames.AUTO_PROPOSE_CODE) == 0)) {
+			reinit();
+		}
+	}
+
+	protected void reinit() {
+		String key = XMLUIPreferenceNames.AUTO_PROPOSE;
+		boolean doAuto = getPreferenceStore().getBoolean(key);
+		if (doAuto) {
+			key = XMLUIPreferenceNames.AUTO_PROPOSE_CODE;
+			completionProposalAutoActivationCharacters = getPreferenceStore().getString(key).toCharArray();
+		}
+		else {
+			completionProposalAutoActivationCharacters = null;
+		}
+	}
+
+	public void release() {
+		super.release();
+		getPreferenceStore().removePropertyChangeListener(this);
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/XMLContentAssistUtilities.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/XMLContentAssistUtilities.java
new file mode 100644
index 0000000..4aa4b34
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/XMLContentAssistUtilities.java
@@ -0,0 +1,516 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.contentassist;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
+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.ITextRegionContainer;
+import org.eclipse.wst.sse.core.internal.util.ScriptLanguageKeys;
+import org.eclipse.wst.sse.ui.internal.contentassist.ContentAssistUtils;
+import org.eclipse.wst.sse.ui.internal.contentassist.CustomCompletionProposal;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImageHelper;
+import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+/**
+ * @author pavery
+ */
+public class XMLContentAssistUtilities extends ContentAssistUtils {
+
+	/**
+	 * ISSUE: this is a bit of hidden JSP knowledge that was implemented this
+	 * way for expedency. Should be evolved in future to depend on
+	 * "nestedContext".
+	 */
+	private class DOMJSPRegionContextsPrivateCopy {
+		private static final String JSP_CLOSE = "JSP_CLOSE"; //$NON-NLS-1$
+		private static final String JSP_DECLARATION_OPEN = "JSP_DECLARATION_OPEN"; //$NON-NLS-1$
+		private static final String JSP_SCRIPTLET_OPEN = "JSP_SCRIPTLET_OPEN"; //$NON-NLS-1$
+		private static final String JSP_EXPRESSION_OPEN = "JSP_EXPRESSION_OPEN"; //$NON-NLS-1$
+
+	}
+
+
+	public static final String CONTENT = "Content"; //$NON-NLS-1$
+	public static final String CONTENT_SCRIPT_TYPE = "Content-Script-Type"; //$NON-NLS-1$
+	public static final String HEAD = "HEAD"; //$NON-NLS-1$
+	public static final String HTML = "HTML"; //$NON-NLS-1$
+	public static final String HTTP_EQUIV = "HTTP-EQUIV"; //$NON-NLS-1$
+	public static final String META = "META"; //$NON-NLS-1$
+
+	/**
+	 * A convenience method for getting the closing proposal given the
+	 * contents (IndexedRegion) of a tag that is started, but possibly not
+	 * ended
+	 * 
+	 * @param viewer
+	 *            the text viewer
+	 * @param documentPosition
+	 *            the cursor position in the viewer
+	 * @param indexedNode
+	 *            the contents of the tag that is started but possibly not
+	 *            ended
+	 * @param parentTagName
+	 *            the tag on which you are checkin for an ending tag
+	 * @param imagePath
+	 *            content assist image relative path
+	 * @return ICompletionProposal
+	 */
+	public static ICompletionProposal computeJSPEndTagProposal(ITextViewer viewer, int documentPosition, IndexedRegion indexedNode, String parentTagName, String imagePath) {
+		ICompletionProposal p = null;
+
+		// check if tag is closed
+		boolean hasEndTag = true;
+		boolean isJSPTag = false;
+		IDOMNode xnode = null;
+		String tagName = ""; //$NON-NLS-1$
+		if (indexedNode instanceof IDOMNode) {
+			xnode = ((IDOMNode) indexedNode);
+			// it's ended already...
+			if (xnode.getEndStructuredDocumentRegion() != null) {
+				return null;
+			}
+			IDOMNode openNode = null;
+			if (!xnode.getNodeName().equalsIgnoreCase(parentTagName)) {
+				openNode = (IDOMNode) xnode.getParentNode();
+			}
+			if (openNode != null) {
+				if (openNode instanceof IDOMElement) {
+					isJSPTag = ((IDOMElement) openNode).isJSPTag();
+				}
+				tagName = openNode.getNodeName();
+				hasEndTag = (openNode.getEndStructuredDocumentRegion() != null);
+			}
+		}
+
+		// it's closed, don't add close tag proposal
+		if (!hasEndTag && !isJSPTag) {
+
+			// create appropriate close tag text
+			String proposedText = "</" + tagName; //$NON-NLS-1$
+			String viewerText = viewer.getTextWidget().getText();
+			if ((viewerText.length() >= documentPosition) && (viewerText.length() >= 2) && (documentPosition >= 2)) {
+				String last2chars = viewerText.substring(documentPosition - 2, documentPosition);
+				if (last2chars.endsWith("</")) {
+					proposedText = tagName;
+				}
+				else if (last2chars.endsWith("<")) {
+					proposedText = "/" + tagName; //$NON-NLS-1$
+				}
+			}
+
+			// create proposal
+			p = new CustomCompletionProposal(proposedText + ">", //$NON-NLS-1$
+						documentPosition, 0, proposedText.length() + 1, XMLEditorPluginImageHelper.getInstance().getImage(imagePath), NLS.bind(XMLUIMessages.End_with_, (new Object[]{proposedText})), null, null, XMLRelevanceConstants.R_END_TAG);
+		}
+		else if (!hasEndTag && isJSPTag) {
+
+			// create appropriate close tag text
+			String proposedText = "%"; //$NON-NLS-1$
+			String viewerText = viewer.getTextWidget().getText();
+
+			// TODO (pa) make it smarter to add "%>" or just ">" if % is
+			// already there...
+			if ((viewerText.length() >= documentPosition) && (viewerText.length() >= 2)) {
+				String last2chars = viewerText.substring(documentPosition - 2, documentPosition);
+				String lastchar = viewerText.substring(documentPosition - 1, documentPosition);
+				if (lastchar.equals("%")) //$NON-NLS-1$
+				{
+					if (last2chars.endsWith("<%")) {
+						proposedText = "%"; //$NON-NLS-1$
+					}
+					else {
+						proposedText = ""; //$NON-NLS-1$
+					}
+				}
+			}
+
+			// create proposal
+			p = new CustomCompletionProposal(proposedText + ">", //$NON-NLS-1$
+						documentPosition, 0, proposedText.length() + 1, XMLEditorPluginImageHelper.getInstance().getImage(imagePath), NLS.bind(XMLUIMessages.End_with_, (new Object[]{proposedText})), null, null, XMLRelevanceConstants.R_END_TAG);
+		}
+
+		return p;
+	}
+
+
+	/**
+	 * A convenience method for getting the closing proposal given the
+	 * contents (IndexedRegion) of a tag that is started, but possibly not
+	 * ended
+	 * 
+	 * @param viewer
+	 *            the text viewer
+	 * @param documentPosition
+	 *            the cursor position in the viewer
+	 * @param indexedNode
+	 *            the contents of the tag that is started but possibly not
+	 *            ended
+	 * @param parentTagName
+	 *            the tag on which you are checkin for an ending tag
+	 * @param imagePath
+	 *            content assist relative image path
+	 * @return ICompletionProposal
+	 */
+	public static ICompletionProposal computeXMLEndTagProposal(ITextViewer viewer, int documentPosition, IndexedRegion indexedNode, String parentTagName, String imagePath) {
+		ICompletionProposal p = null;
+
+		// check if tag is closed
+		boolean hasEndTag = true;
+		IDOMNode xnode = null;
+		String tagName = ""; //$NON-NLS-1$
+		if (indexedNode instanceof IDOMNode) {
+			xnode = ((IDOMNode) indexedNode);
+			// it's ended already...
+			if (xnode.getEndStructuredDocumentRegion() != null) {
+				return null;
+			}
+			IDOMNode styleNode = null;
+			if (!xnode.getNodeName().equalsIgnoreCase(parentTagName)) {
+				styleNode = (IDOMNode) xnode.getParentNode();
+			}
+			if (styleNode != null) {
+				tagName = styleNode.getNodeName();
+				hasEndTag = (styleNode.getEndStructuredDocumentRegion() != null);
+			}
+		}
+
+		// it's closed, don't add close tag proposal
+		if (!hasEndTag) {
+
+			// create appropriate close tag text
+			String proposedText = "</" + tagName; //$NON-NLS-1$
+			String viewerText = viewer.getTextWidget().getText();
+			if ((viewerText.length() >= documentPosition) && (viewerText.length() >= 2) && (documentPosition >= 2)) {
+				String last2chars = viewerText.substring(documentPosition - 2, documentPosition);
+				if (last2chars.endsWith("</")) {
+					proposedText = tagName;
+				}
+				else if (last2chars.endsWith("<")) {
+					proposedText = "/" + tagName; //$NON-NLS-1$
+				}
+			}
+
+			// create proposal
+			p = new CustomCompletionProposal(proposedText + ">", //$NON-NLS-1$
+						documentPosition, 0, proposedText.length() + 1, XMLEditorPluginImageHelper.getInstance().getImage(imagePath), NLS.bind(XMLUIMessages.End_with_, (new Object[]{proposedText})), null, null, XMLRelevanceConstants.R_END_TAG);
+		}
+		return p;
+	}
+
+	private static String getMetaScriptType(Document doc) {
+		// Can not just do a Document.getElementsByTagName(String) as this
+		// needs
+		// to be relatively fast.
+		List metas = new ArrayList();
+		// check for META tags under the Document
+		Node html = null;
+		Node head = null;
+		Node child = null;
+		// ----------------------------------------------------------------------
+		// (pa) 20021217
+		// cmvc defect 235554
+		// performance enhancement: using child.getNextSibling() rather than
+		// nodeList(item) for O(n) vs. O(n*n)
+		// ----------------------------------------------------------------------
+
+		for (child = doc.getFirstChild(); child != null; child = child.getNextSibling()) {
+			if (child.getNodeType() != Node.ELEMENT_NODE) {
+				continue;
+			}
+			if (child.getNodeName().equalsIgnoreCase(META)) {
+				metas.add(child);
+			}
+			else if (child.getNodeName().equalsIgnoreCase(HTML)) {
+				html = child;
+			}
+		}
+		// NodeList children = doc.getChildNodes();
+		// for(int i = 0; i < children.getLength(); i++) {
+		// child = children.item(i);
+		// if(child.getNodeType() != Node.ELEMENT_NODE)
+		// continue;
+		// if(child.getNodeName().equalsIgnoreCase(META))
+		// metas.add(child);
+		// else if(child.getNodeName().equalsIgnoreCase(HTML))
+		// html = child;
+		// }
+
+		// check for META tags under HEAD
+		if (html != null) {
+			for (child = html.getFirstChild(); (child != null) && (head == null); child = child.getNextSibling()) {
+				if (child.getNodeType() != Node.ELEMENT_NODE) {
+					continue;
+				}
+				if (child.getNodeName().equalsIgnoreCase(HEAD)) {
+					head = child;
+				}
+			}
+			// children = html.getChildNodes();
+			// for(int i = 0; i < children.getLength() && head == null; i++) {
+			// child = children.item(i);
+			// if(child.getNodeType() != Node.ELEMENT_NODE)
+			// continue;
+			// if(child.getNodeName().equalsIgnoreCase(HEAD))
+			// head = child;
+			// }
+		}
+
+		if (head != null) {
+			for (head.getFirstChild(); child != null; child = child.getNextSibling()) {
+				if (child.getNodeType() != Node.ELEMENT_NODE) {
+					continue;
+				}
+				if (child.getNodeName().equalsIgnoreCase(META)) {
+					metas.add(child);
+				}
+			}
+			// children = head.getChildNodes();
+			// for(int i = 0 ; i < children.getLength(); i++) {
+			// child = children.item(i);
+			// if(child.getNodeType() != Node.ELEMENT_NODE)
+			// continue;
+			// if(child.getNodeName().equalsIgnoreCase(META))
+			// metas.add(child);
+			// }
+		}
+
+		return getMetaScriptType(metas);
+	}
+
+	private static String getMetaScriptType(List metaNodeList) {
+		Node meta = null;
+		NamedNodeMap attributes = null;
+		boolean httpEquiv = false;
+		String contentScriptType = null;
+
+		for (int i = metaNodeList.size() - 1; i >= 0; i--) {
+			meta = (Node) metaNodeList.get(i);
+			attributes = meta.getAttributes();
+			httpEquiv = false;
+			contentScriptType = null;
+			for (int j = 0; j < attributes.getLength(); j++) {
+				if (attributes.item(j).getNodeName().equalsIgnoreCase(HTTP_EQUIV)) {
+					httpEquiv = attributes.item(j).getNodeValue().equalsIgnoreCase(CONTENT_SCRIPT_TYPE);
+				}
+				else if (attributes.item(j).getNodeName().equalsIgnoreCase(CONTENT)) {
+					contentScriptType = attributes.item(j).getNodeValue();
+				}
+			}
+			if (httpEquiv && (contentScriptType != null)) {
+				return contentScriptType;
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * Returns the scripting language the scriptNode is in Currently returns
+	 * javascript unless some unknown type or language is specified. Then the
+	 * unknown type/language is returned
+	 * 
+	 * @param scriptNode
+	 */
+	public static String getScriptLanguage(Node scriptNode) {
+		Node attr = null;
+
+		boolean specified = false;
+		// try to find a scripting adapter for 'type'
+		if ((scriptNode == null) || (scriptNode.getAttributes() == null)) {
+			return null;
+		}
+
+		attr = scriptNode.getAttributes().getNamedItem("type");//$NON-NLS-1$
+		if (attr != null) {
+			specified = true;
+			String type = attr.getNodeValue();
+			return lookupScriptType(type);
+		}
+		// now try to find a scripting adapter for 'language' (deprecated by
+		// HTML specifications)
+		attr = scriptNode.getAttributes().getNamedItem("language");//$NON-NLS-1$
+		if (attr != null) {
+			specified = true;
+			String language = attr.getNodeValue();
+			return lookupScriptLanguage(language);
+		}
+		// check if one is specified by a META tag at the root level or inside
+		// of HEAD
+		String type = null;
+		if (!specified) {
+			type = getMetaScriptType(scriptNode.getOwnerDocument());
+		}
+		if (type != null) {
+			specified = true;
+			return lookupScriptType(type);
+		}
+		// return default
+		if (!specified) {
+			return ScriptLanguageKeys.JAVASCRIPT;
+		}
+		return null;
+	}
+
+	/**
+	 * Tells you if the flatnode is the %> delimiter
+	 * 
+	 * ISSUE: this is a bit of hidden JSP knowledge that was implemented this
+	 * way for expedency. Should be evolved in future to depend on
+	 * "nestedContext".
+	 */
+	public static boolean isJSPCloseDelimiter(IStructuredDocumentRegion fn) {
+		if (fn == null) {
+			return false;
+		}
+		return isJSPCloseDelimiter(fn.getType());
+	}
+
+	/**
+	 * ISSUE: this is a bit of hidden JSP knowledge that was implemented this
+	 * way for expedency. Should be evolved in future to depend on
+	 * "nestedContext".
+	 */
+	public static boolean isJSPCloseDelimiter(String type) {
+		if (type == null) {
+			return false;
+		}
+		return (type.equals(DOMJSPRegionContextsPrivateCopy.JSP_CLOSE) || type.equals(DOMRegionContext.XML_TAG_CLOSE));
+	}
+
+	/**
+	 * Tells you if the flatnode is the JSP region <%%>, <%=%>, <%!%>
+	 * 
+	 * ISSUE: this is a bit of hidden JSP knowledge that was implemented this
+	 * way for expedency. Should be evolved in future to depend on
+	 * "nestedContext".
+	 */
+	public static boolean isJSPDelimiter(IStructuredDocumentRegion fn) {
+		boolean isDelimiter = false;
+		String type = fn.getType();
+		if (type != null) {
+			isDelimiter = isJSPDelimiter(type);
+		}
+		return isDelimiter;
+	}
+
+	/**
+	 * ISSUE: this is a bit of hidden JSP knowledge that was implemented this
+	 * way for expedency. Should be evolved in future to depend on
+	 * "nestedContext".
+	 */
+	public static boolean isJSPDelimiter(String type) {
+		if (type == null) {
+			return false;
+		}
+		return (isJSPOpenDelimiter(type) || isJSPCloseDelimiter(type));
+	}
+
+	/**
+	 * Tells you if the flatnode is <%, <%=, or <%! ISSUE: this is a bit of
+	 * hidden JSP knowledge that was implemented this way for expedency.
+	 * Should be evolved in future to depend on "nestedContext".
+	 */
+	public static boolean isJSPOpenDelimiter(IStructuredDocumentRegion fn) {
+		if (fn == null) {
+			return false;
+		}
+		return isJSPOpenDelimiter(fn.getType());
+	}
+
+	/**
+	 * ISSUE: this is a bit of hidden JSP knowledge that was implemented this
+	 * way for expedency. Should be evolved in future to depend on
+	 * "nestedContext".
+	 */
+	public static boolean isJSPOpenDelimiter(String type) {
+		if (type == null) {
+			return false;
+		}
+		return (type.equals(DOMJSPRegionContextsPrivateCopy.JSP_SCRIPTLET_OPEN) || type.equals(DOMJSPRegionContextsPrivateCopy.JSP_DECLARATION_OPEN) || type.equals(DOMJSPRegionContextsPrivateCopy.JSP_EXPRESSION_OPEN));
+	}
+
+	/**
+	 * Tells you if the flatnode is the <jsp:scriptlet>, <jsp:expression>, or
+	 * <jsp:declaration>tag
+	 * 
+	 * ISSUE: this is a bit of hidden JSP knowledge that was implemented this
+	 * way for expedency. Should be evolved in future to depend on
+	 * "nestedContext".
+	 */
+	public static boolean isXMLJSPDelimiter(IStructuredDocumentRegion fn) {
+		boolean isDelimiter = false;
+		if ((fn != null) && (fn instanceof ITextRegionContainer)) {
+			Object[] regions = ((ITextRegionContainer) fn).getRegions().toArray();
+			ITextRegion temp = null;
+			String regionText = ""; //$NON-NLS-1$
+			for (int i = 0; i < regions.length; i++) {
+				temp = (ITextRegion) regions[i];
+				if (temp.getType() == DOMRegionContext.XML_TAG_NAME) {
+					regionText = fn.getText(temp);
+					if (regionText.equalsIgnoreCase("jsp:scriptlet") || regionText.equalsIgnoreCase("jsp:expression") || regionText.equalsIgnoreCase("jsp:declaration")) {
+						isDelimiter = true;
+					}
+				}
+			}
+		}
+		return isDelimiter;
+	}
+
+	/**
+	 * Returns "javascript" if language attribute is some form of javascript,
+	 * "java" if language attribute is some form of java. Otherwise, just
+	 * returns type.
+	 * 
+	 * @param language
+	 */
+	public static String lookupScriptLanguage(String language) {
+		for (int i = 0; i < ScriptLanguageKeys.JAVASCRIPT_LANGUAGE_KEYS.length; i++) {
+			if (ScriptLanguageKeys.JAVASCRIPT_LANGUAGE_KEYS[i].equalsIgnoreCase(language)) {
+				return ScriptLanguageKeys.JAVASCRIPT;
+			}
+		}
+		for (int i = 0; i < ScriptLanguageKeys.JAVA_LANGUAGE_KEYS.length; i++) {
+			if (ScriptLanguageKeys.JAVA_LANGUAGE_KEYS[i].equalsIgnoreCase(language)) {
+				return ScriptLanguageKeys.JAVA;
+			}
+		}
+		return language;
+	}
+
+	/**
+	 * Returns "javascript" if type (used in <script type="xxx"> is actually
+	 * javascript type. Otherwise, just returns type
+	 * 
+	 * @param type
+	 */
+	public static String lookupScriptType(String type) {
+		for (int i = 0; i < ScriptLanguageKeys.JAVASCRIPT_MIME_TYPE_KEYS.length; i++) {
+			if (ScriptLanguageKeys.JAVASCRIPT_MIME_TYPE_KEYS[i].equalsIgnoreCase(type)) {
+				return ScriptLanguageKeys.JAVASCRIPT;
+			}
+		}
+		return type;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/XMLContentModelGenerator.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/XMLContentModelGenerator.java
new file mode 100644
index 0000000..2896432
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/XMLContentModelGenerator.java
@@ -0,0 +1,154 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2008 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.contentassist;
+
+
+
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.w3c.dom.Node;
+
+
+public class XMLContentModelGenerator extends AbstractContentModelGenerator {
+
+	/**
+	 * ISSUE: this is a bit of hidden JSP knowledge that was implemented this
+	 * way for expedency. Should be evolved in future to depend on
+	 * "nestedContext".
+	 */
+	private class DOMJSPRegionContextsPrivateCopy {
+		private static final String JSP_DIRECTIVE_OPEN = "JSP_DIRECTIVE_OPEN"; //$NON-NLS-1$
+	}
+
+	/**
+	 * XMLContentModelGenerator constructor comment.
+	 */
+	public XMLContentModelGenerator() {
+		super();
+	}
+
+	public void generateAttribute(CMAttributeDeclaration attrDecl, StringBuffer buffer) {
+		if ((attrDecl == null) || (buffer == null)) {
+			return;
+		}
+		int usage = attrDecl.getUsage();
+		if (usage == CMAttributeDeclaration.REQUIRED) {
+			buffer.append(" "); //$NON-NLS-1$
+			generateRequiredAttribute(null, attrDecl, buffer); // todo pass
+			// ownerNode as
+			// 1st param
+		}
+		return;
+	}
+
+	protected void generateEndTag(String tagName, Node parentNode, CMElementDeclaration elementDecl, StringBuffer buffer) {
+		if (elementDecl == null) {
+			return;
+		}
+		if (elementDecl.getContentType() != CMElementDeclaration.EMPTY) {
+			buffer.append("</" + tagName + ">");//$NON-NLS-2$//$NON-NLS-1$
+		}
+		return;
+	}
+
+	public void generateRequiredAttribute(Node ownerNode, CMAttributeDeclaration attrDecl, StringBuffer buffer) {
+		if ((attrDecl == null) || (buffer == null)) {
+			return;
+		}
+
+		// attribute name
+		String attributeName = getRequiredName(ownerNode, attrDecl);
+		CMDataType attrType = attrDecl.getAttrType();
+		String defaultValue = null;
+		// = sign
+		buffer.append(attributeName + "="); //$NON-NLS-1$
+		// attribute value
+		if (attrType != null) {
+			// insert any value that is implied
+			if ((attrType.getImpliedValueKind() != CMDataType.IMPLIED_VALUE_NONE) && (attrType.getImpliedValue() != null)) {
+				defaultValue = attrType.getImpliedValue();
+			}
+			// otherwise, if an enumerated list of values exists, use the
+			// first value
+			else if ((attrType.getEnumeratedValues() != null) && (attrType.getEnumeratedValues().length > 0)) {
+				defaultValue = attrType.getEnumeratedValues()[0];
+			}
+		}
+		
+		char attrQuote = '\"';
+		// Found a double quote, wrap the attribute in single quotes
+		if(defaultValue != null && defaultValue.indexOf(attrQuote) >= 0) {
+			attrQuote = '\'';
+		}
+		
+		buffer.append(attrQuote);
+		buffer.append(((defaultValue != null) ? defaultValue : "")); //$NON-NLS-1$
+		buffer.append(attrQuote);
+		return;
+	}
+
+	protected void generateStartTag(String tagName, Node parentNode, CMElementDeclaration elementDecl, StringBuffer buffer) {
+		if ((elementDecl == null) || (buffer == null)) {
+			return;
+		}
+		buffer.append("<" + tagName);//$NON-NLS-1$
+		generateAttributes(elementDecl, buffer);
+		buffer.append(getStartTagClose(parentNode, elementDecl));
+		return;
+	}
+
+	public int getMinimalStartTagLength(Node node, CMElementDeclaration elementDecl) {
+		if (elementDecl == null) {
+			return 0;
+		}
+		if (requiresAttributes(elementDecl)) {
+			return getRequiredName(node, elementDecl).length() + 2; // < +
+			// name +
+			// space
+		}
+		else {
+			return 1 + getRequiredName(node, elementDecl).length() + getStartTagClose(node, elementDecl).length(); // < +
+			// name
+			// +
+			// appropriate
+			// close
+		}
+	}
+
+	protected String getOtherClose(Node notATagNode) {
+		if (notATagNode instanceof IDOMNode) {
+			IStructuredDocumentRegion node = ((IDOMNode) notATagNode).getStartStructuredDocumentRegion();
+			if ((node != null) && (node.getNumberOfRegions() > 1) && node.getRegions().get(0).getType().equals(DOMJSPRegionContextsPrivateCopy.JSP_DIRECTIVE_OPEN)) {
+				return "%>"; //$NON-NLS-1$
+			}
+		}
+		return null;
+	}
+
+	public String getStartTagClose(Node parentNode, CMElementDeclaration elementDecl) {
+		String other = getOtherClose(parentNode);
+		if (other != null) {
+			return other;
+		}
+		if (elementDecl == null) {
+			return ">";//$NON-NLS-1$
+		}
+		if (elementDecl.getContentType() == CMElementDeclaration.EMPTY) {
+			return "/>"; //$NON-NLS-1$
+		}
+		return ">"; //$NON-NLS-1$
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/XMLRelevanceConstants.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/XMLRelevanceConstants.java
new file mode 100644
index 0000000..8fc1457
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/XMLRelevanceConstants.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.contentassist;
+
+import org.eclipse.wst.sse.ui.internal.contentassist.IRelevanceConstants;
+
+
+
+/**
+ * some relevance constants for content assist higher relevance means it shows
+ * up higher on the list
+ */
+public interface XMLRelevanceConstants extends IRelevanceConstants {
+
+	int R_CDATA = 400;
+	int R_CLOSE_TAG = 1500;
+
+	int R_COMMENT = 100;
+
+	// moved this above macros
+	int R_DOCTYPE = 600;
+	int R_END_TAG = 1400;
+	int R_END_TAG_NAME = 1100;
+	int R_ENTITY = 1000;
+	int R_JSP = 500;
+
+	int R_JSP_ATTRIBUTE_VALUE = 700;
+
+	// (pa) make these the same relevance so proposals are same order for V501
+	int R_MACRO = 500;
+
+	// add this onto "required" attrs, elements, etc to bubble them up on
+	// sorting...
+	// CMVC 246618
+	int R_REQUIRED = 10;
+	int R_TAG_INSERTION = 500;
+	int R_STRICTLY_VALID_TAG_INSERTION = 600;
+	int R_TAG_NAME = 1200;
+	int R_STRICTLY_VALID_TAG_NAME = 1250;
+	int R_XML_ATTRIBUTE_NAME = 900;
+	int R_XML_ATTRIBUTE_VALUE = 800;
+	int R_XML_DECLARATION = 1300;
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/XMLStructuredContentAssistProcessor.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/XMLStructuredContentAssistProcessor.java
new file mode 100644
index 0000000..69d040b
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/XMLStructuredContentAssistProcessor.java
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.contentassist;
+
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.contentassist.ContentAssistant;
+import org.eclipse.jface.text.contentassist.IContextInformationValidator;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.wst.sse.ui.contentassist.StructuredContentAssistProcessor;
+import org.eclipse.wst.xml.ui.internal.XMLUIPlugin;
+import org.eclipse.wst.xml.ui.internal.preferences.XMLUIPreferenceNames;
+
+/**
+ * <p>Implementation of {@link StructuredContentAssistProcessor} for XML documents</p>
+ * 
+ * <p>This implementation will react to user preference changes for auto activation
+ * characters for XML pages</p>
+ * 
+ * @see StructuredContentAssistProcessor
+ */
+public class XMLStructuredContentAssistProcessor extends StructuredContentAssistProcessor {
+	/** the auto activation characters for this processor, set by user preference */
+	private char[] fCompletionProposalAutoActivationCharacters;
+	
+	/** the context information validator for this processor */
+	private IContextInformationValidator fContextInformationValidator;
+	
+	/**
+	 * <p>Constructor</p>
+	 * 
+	 * @param assistant {@link ContentAssistant} to use
+	 * @param partitionTypeID the partition type this processor is for
+	 * @param viewer {@link ITextViewer} this processor is acting in
+	 */
+	public XMLStructuredContentAssistProcessor(ContentAssistant assistant,
+			String partitionTypeID, ITextViewer viewer) {
+		
+		super(assistant, partitionTypeID, viewer, XMLUIPlugin.getDefault().getPreferenceStore());
+		getAutoActivationCharacterPreferences();
+	}
+
+	/**
+	 * @see org.eclipse.wst.sse.ui.contentassist.StructuredContentAssistProcessor#getContextInformationValidator()
+	 */
+	public IContextInformationValidator getContextInformationValidator() {
+		if (this.fContextInformationValidator == null) {
+			this.fContextInformationValidator = new AttributeContextInformationPresenter();
+		}
+		return this.fContextInformationValidator;
+	}
+
+	/**
+	 * @see org.eclipse.wst.sse.ui.contentassist.StructuredContentAssistProcessor#getCompletionProposalAutoActivationCharacters()
+	 */
+	public char[] getCompletionProposalAutoActivationCharacters() {
+		return super.getCompletionProposalAutoActivationCharacters() != null ? super.getCompletionProposalAutoActivationCharacters() : this.fCompletionProposalAutoActivationCharacters;
+	}
+	
+	/**
+	 * @see org.eclipse.wst.sse.ui.contentassist.StructuredContentAssistProcessor#propertyChange(
+	 * 	org.eclipse.jface.util.PropertyChangeEvent)
+	 */
+	public void propertyChange(PropertyChangeEvent event) {
+		if(event.getProperty().equals(XMLUIPreferenceNames.AUTO_PROPOSE) ||
+				event.getProperty().equals(XMLUIPreferenceNames.AUTO_PROPOSE_CODE)) {
+			getAutoActivationCharacterPreferences();
+		}
+	}
+	
+
+	protected void getAutoActivationCharacterPreferences() {
+		String key = XMLUIPreferenceNames.AUTO_PROPOSE;
+		boolean doAuto = getPreferenceStore().getBoolean(key);
+		if (doAuto) {
+			key = XMLUIPreferenceNames.AUTO_PROPOSE_CODE;
+			fCompletionProposalAutoActivationCharacters = getPreferenceStore().getString(key).toCharArray();
+		}
+		else {
+			fCompletionProposalAutoActivationCharacters = null;
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/XMLTagsCompletionProposalComputer.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/XMLTagsCompletionProposalComputer.java
new file mode 100644
index 0000000..ae03566
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/XMLTagsCompletionProposalComputer.java
@@ -0,0 +1,94 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.contentassist;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.text.contentassist.IContextInformationValidator;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+import org.eclipse.wst.sse.ui.contentassist.CompletionProposalInvocationContext;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+/**
+ * <p>{@link AbstractXMLModelQueryCompletionProposalComputer} used to
+ * generate XML tag content assist proposals</p>
+ * 
+ * <p><b>NOTE:</b> Currently this computer does not filter out any of the 
+ * model query results so it will return all proposals from the model query
+ * for the current content type.  In the future this may need to change.</p>
+ */
+public class XMLTagsCompletionProposalComputer extends
+		AbstractXMLModelQueryCompletionProposalComputer {
+
+	/** the generated used to generate the proposals */
+	protected XMLContentModelGenerator fGenerator;
+	
+	/** the context information validator for this computer */
+	private IContextInformationValidator fContextInformationValidator;
+	
+	/**
+	 * <p>Default constructor</p>
+	 */
+	public XMLTagsCompletionProposalComputer() {
+		this.fContextInformationValidator = null;
+	}
+	
+	/**
+	 * @see org.eclipse.wst.xml.ui.internal.contentassist.AbstractXMLModelQueryCompletionProposalComputer#getContentGenerator()
+	 */
+	protected XMLContentModelGenerator getContentGenerator() {
+		if (fGenerator == null) {
+			fGenerator = new XMLContentModelGenerator();
+		}
+		return fGenerator;
+	}
+	
+	/**
+	 * @see org.eclipse.wst.xml.ui.internal.contentassist.AbstractXMLCompletionProposalComputer#computeContextInformation(org.eclipse.wst.sse.ui.contentassist.CompletionProposalInvocationContext, org.eclipse.core.runtime.IProgressMonitor)
+	 */
+	public List computeContextInformation(
+			CompletionProposalInvocationContext context,
+			IProgressMonitor monitor) {
+		
+		AttributeContextInformationProvider attributeInfoProvider =
+			new AttributeContextInformationProvider((IStructuredDocument)context.getDocument(),
+					(AttributeContextInformationPresenter) getContextInformationValidator());
+		return Arrays.asList(attributeInfoProvider.getAttributeInformation(context.getInvocationOffset()));
+	}
+	
+	/**
+	 * <p>Filters out any model query actions that are not specific to XML</p>
+	 * <p><b>NOTE:</b> Currently nothing is filtered so this computer returns all
+	 * results from the model query for the current content type</p>
+	 * 
+	 * @see org.eclipse.wst.xml.ui.internal.contentassist.AbstractXMLModelQueryCompletionProposalComputer#validModelQueryNode(org.eclipse.wst.xml.core.internal.contentmodel.CMNode)
+	 */
+	protected boolean validModelQueryNode(CMNode node) {
+		return true;
+	}
+	
+	/**
+	 * Returns a validator used to determine when displayed context
+	 * information should be dismissed. May only return <code>null</code> if
+	 * the processor is incapable of computing context information.
+	 * 
+	 * a context information validator, or <code>null</code> if the
+	 * processor is incapable of computing context information
+	 */
+	private IContextInformationValidator getContextInformationValidator() {
+		if (fContextInformationValidator == null) {
+			fContextInformationValidator = new AttributeContextInformationPresenter();
+		}
+		return fContextInformationValidator;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/XMLTemplateCompletionProcessor.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/XMLTemplateCompletionProcessor.java
new file mode 100644
index 0000000..d0bb83c
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/XMLTemplateCompletionProcessor.java
@@ -0,0 +1,168 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.contentassist;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.jface.text.templates.ContextTypeRegistry;
+import org.eclipse.jface.text.templates.Template;
+import org.eclipse.jface.text.templates.TemplateCompletionProcessor;
+import org.eclipse.jface.text.templates.TemplateContext;
+import org.eclipse.jface.text.templates.TemplateContextType;
+import org.eclipse.jface.text.templates.TemplateException;
+import org.eclipse.jface.text.templates.TemplateProposal;
+import org.eclipse.jface.text.templates.persistence.TemplateStore;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.wst.xml.ui.internal.XMLUIPlugin;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImageHelper;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImages;
+
+
+/**
+ * <p>Completion computer for XML templates</p>
+ */
+class XMLTemplateCompletionProcessor extends TemplateCompletionProcessor {
+	private static final class ProposalComparator implements Comparator {
+		public int compare(Object o1, Object o2) {
+			return ((TemplateProposal) o2).getRelevance() - ((TemplateProposal) o1).getRelevance();
+		}
+	}
+
+	private static final Comparator fgProposalComparator = new ProposalComparator();
+	private String fContextTypeId = null;
+
+	/*
+	 * Copied from super class except instead of calling createContext(viewer,
+	 * region) call createContext(viewer, region, offset) instead
+	 */
+	public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int offset) {
+
+		ITextSelection selection = (ITextSelection) viewer.getSelectionProvider().getSelection();
+
+		// adjust offset to end of normalized selection
+		if (selection.getOffset() == offset) {
+			offset = selection.getOffset() + selection.getLength();
+		}
+
+		String prefix = extractPrefix(viewer, offset);
+		Region region = new Region(offset - prefix.length(), prefix.length());
+		TemplateContext context = createContext(viewer, region, offset);
+		if (context == null) {
+			return new ICompletionProposal[0];
+		}
+
+		// name of the selection variables {line, word}_selection
+		context.setVariable("selection", selection.getText()); //$NON-NLS-1$
+
+		Template[] templates = getTemplates(context.getContextType().getId());
+
+		List matches = new ArrayList();
+		for (int i = 0; i < templates.length; i++) {
+			Template template = templates[i];
+			try {
+				context.getContextType().validate(template.getPattern());
+			}
+			catch (TemplateException e) {
+				continue;
+			}
+			if (template.matches(prefix, context.getContextType().getId())) {
+				matches.add(createProposal(template, context, (IRegion) region, getRelevance(template, prefix)));
+			}
+		}
+
+		Collections.sort(matches, fgProposalComparator);
+
+		return (ICompletionProposal[]) matches.toArray(new ICompletionProposal[matches.size()]);
+	}
+
+	/**
+	 * Creates a concrete template context for the given region in the
+	 * document. This involves finding out which context type is valid at the
+	 * given location, and then creating a context of this type. The default
+	 * implementation returns a <code>SmartReplaceTemplateContext</code> for
+	 * the context type at the given location. This takes the offset at which
+	 * content assist was invoked into consideration.
+	 * 
+	 * @param viewer
+	 *            the viewer for which the context is created
+	 * @param region
+	 *            the region into <code>document</code> for which the
+	 *            context is created
+	 * @param offset
+	 *            the original offset where content assist was invoked
+	 * @return a template context that can handle template insertion at the
+	 *         given location, or <code>null</code>
+	 */
+	private TemplateContext createContext(ITextViewer viewer, IRegion region, int offset) {
+		// pretty much same code as super.createContext except create
+		// SmartReplaceTemplateContext
+		TemplateContextType contextType = getContextType(viewer, region);
+		if (contextType != null) {
+			IDocument document = viewer.getDocument();
+			return new ReplaceNameTemplateContext(contextType, document, region.getOffset(), region.getLength(), offset);
+		}
+		return null;
+	}
+
+	protected ICompletionProposal createProposal(Template template, TemplateContext context, IRegion region, int relevance) {
+		return new CustomTemplateProposal(template, context, region, getImage(template), relevance);
+	}
+
+	protected TemplateContextType getContextType(ITextViewer viewer, IRegion region) {
+		TemplateContextType type = null;
+
+		ContextTypeRegistry registry = getTemplateContextRegistry();
+		if (registry != null) {
+			type = registry.getContextType(fContextTypeId);
+		}
+
+		return type;
+	}
+
+	protected Image getImage(Template template) {
+		// just return the same image for now
+		return XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TAG_MACRO);
+	}
+
+	private ContextTypeRegistry getTemplateContextRegistry() {
+		return XMLUIPlugin.getDefault().getTemplateContextRegistry();
+	}
+
+	protected Template[] getTemplates(String contextTypeId) {
+		Template templates[] = null;
+
+		TemplateStore store = getTemplateStore();
+		if (store != null) {
+			templates = store.getTemplates(contextTypeId);
+		}
+
+		return templates;
+	}
+
+	private TemplateStore getTemplateStore() {
+		return XMLUIPlugin.getDefault().getTemplateStore();
+	}
+
+	void setContextType(String contextTypeId) {
+		fContextTypeId = contextTypeId;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/XMLTemplatesCompletionProposalComputer.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/XMLTemplatesCompletionProposalComputer.java
new file mode 100644
index 0000000..287baaa
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/XMLTemplatesCompletionProposalComputer.java
@@ -0,0 +1,124 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.contentassist;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.wst.sse.ui.contentassist.CompletionProposalInvocationContext;
+import org.eclipse.wst.xml.ui.internal.templates.TemplateContextTypeIdsXML;
+
+/**
+ * <p>Proposal computer used to computer XML template content assist
+ * proposals</p>
+ */
+public class XMLTemplatesCompletionProposalComputer extends
+		DefaultXMLCompletionProposalComputer {
+
+	/** <p>The template processor used to create the proposals</p> */
+	private XMLTemplateCompletionProcessor fTemplateProcessor = null;
+
+	/**
+	 * Create the computer
+	 */
+	public XMLTemplatesCompletionProposalComputer() {
+		super();
+		fTemplateProcessor = new XMLTemplateCompletionProcessor();
+	}
+
+	/**
+	 * @see org.eclipse.wst.xml.ui.internal.contentassist.DefaultXMLCompletionProposalComputer#addAttributeNameProposals(org.eclipse.wst.xml.ui.internal.contentassist.ContentAssistRequest, org.eclipse.wst.sse.ui.contentassist.CompletionProposalInvocationContext)
+	 */
+	protected void addAttributeNameProposals(
+			ContentAssistRequest contentAssistRequest,
+			CompletionProposalInvocationContext context) {
+		
+		addTemplates(contentAssistRequest, TemplateContextTypeIdsXML.ATTRIBUTE, context);
+	}
+
+	/**
+	 * @see org.eclipse.wst.xml.ui.internal.contentassist.DefaultXMLCompletionProposalComputer#addAttributeValueProposals(org.eclipse.wst.xml.ui.internal.contentassist.ContentAssistRequest, org.eclipse.wst.sse.ui.contentassist.CompletionProposalInvocationContext)
+	 */
+	protected void addAttributeValueProposals(
+			ContentAssistRequest contentAssistRequest,
+			CompletionProposalInvocationContext context) {
+		
+		addTemplates(contentAssistRequest, TemplateContextTypeIdsXML.ATTRIBUTE_VALUE, context);
+	}
+	
+	/**
+	 * @see org.eclipse.wst.xml.ui.internal.contentassist.DefaultXMLCompletionProposalComputer#addEmptyDocumentProposals(org.eclipse.wst.xml.ui.internal.contentassist.ContentAssistRequest, org.eclipse.wst.sse.ui.contentassist.CompletionProposalInvocationContext)
+	 */
+	protected void addEmptyDocumentProposals(
+			ContentAssistRequest contentAssistRequest,
+			CompletionProposalInvocationContext context) {
+		
+		addTemplates(contentAssistRequest, TemplateContextTypeIdsXML.NEW, context);
+	}
+	
+	/**
+	 * @see org.eclipse.wst.xml.ui.internal.contentassist.DefaultXMLCompletionProposalComputer#addTagInsertionProposals(org.eclipse.wst.xml.ui.internal.contentassist.ContentAssistRequest, int, org.eclipse.wst.sse.ui.contentassist.CompletionProposalInvocationContext)
+	 */
+	protected void addTagInsertionProposals(
+			ContentAssistRequest contentAssistRequest, int childPosition,
+			CompletionProposalInvocationContext context) {
+		
+		addTemplates(contentAssistRequest, TemplateContextTypeIdsXML.TAG, context);
+	}
+	
+	/**
+	 * <p>Adds templates to the list of proposals</p>
+	 * 
+	 * @param contentAssistRequest
+	 * @param templateContext
+	 * @param context
+	 */
+	private void addTemplates(ContentAssistRequest contentAssistRequest, String templateContext,
+			CompletionProposalInvocationContext context) {
+		
+		if (contentAssistRequest != null) {
+
+			boolean useProposalList = !contentAssistRequest.shouldSeparate();
+	
+			if (fTemplateProcessor != null) {
+				fTemplateProcessor.setContextType(templateContext);
+				ICompletionProposal[] proposals =
+					fTemplateProcessor.computeCompletionProposals(
+							context.getViewer(), context.getInvocationOffset());
+				for (int i = 0; i < proposals.length; ++i) {
+					if (useProposalList) {
+						contentAssistRequest.addProposal(proposals[i]);
+					}
+					else {
+						contentAssistRequest.addMacro(proposals[i]);
+					}
+				}
+			}
+		}
+	}
+
+	public List computeCompletionProposals(CompletionProposalInvocationContext context, IProgressMonitor monitor) {
+		List list = new ArrayList(super.computeCompletionProposals(context, monitor));
+
+		if (fTemplateProcessor != null) {
+			fTemplateProcessor.setContextType(TemplateContextTypeIdsXML.ALL);
+			ICompletionProposal[] proposals = fTemplateProcessor.computeCompletionProposals(context.getViewer(), context.getInvocationOffset());
+			if (proposals != null) {
+				for (int i = 0; i < proposals.length; i++) {
+					list.add(proposals[i]);
+				}
+			}
+		}
+		return list;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentoutline/JFaceNodeAdapter.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentoutline/JFaceNodeAdapter.java
new file mode 100644
index 0000000..0ea3570
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentoutline/JFaceNodeAdapter.java
@@ -0,0 +1,257 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.contentoutline;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jface.viewers.StructuredViewer;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.sse.ui.internal.contentoutline.IJFaceNodeAdapter;
+import org.eclipse.wst.xml.ui.internal.editor.CMImageUtil;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImageHelper;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImages;
+import org.w3c.dom.Node;
+
+/**
+ * Adapts a DOM node to a JFace viewer.
+ */
+public class JFaceNodeAdapter implements IJFaceNodeAdapter {
+
+	final static Class ADAPTER_KEY = IJFaceNodeAdapter.class;
+
+	/**
+	 * debug .option
+	 */
+	private static final boolean DEBUG = getDebugValue();
+
+	private static boolean getDebugValue() {
+		String value = Platform.getDebugOption("org.eclipse.wst.sse.ui/debug/outline"); //$NON-NLS-1$
+		boolean result = (value != null) && value.equalsIgnoreCase("true"); //$NON-NLS-1$
+		return result;
+	}
+
+	JFaceNodeAdapterFactory fAdapterFactory;
+	RefreshStructureJob fRefreshJob = null;
+
+	public JFaceNodeAdapter(JFaceNodeAdapterFactory adapterFactory) {
+		super();
+		this.fAdapterFactory = adapterFactory;
+	}
+
+	protected Image createImage(Object object) {
+		Image image = null;
+		Node node = (Node) object;
+		switch (node.getNodeType()) {
+			case Node.ELEMENT_NODE : {
+				image = createXMLImageDescriptor(XMLEditorPluginImages.IMG_OBJ_ELEMENT);
+				break;
+			}
+			case Node.ATTRIBUTE_NODE : {
+				image = createXMLImageDescriptor(XMLEditorPluginImages.IMG_OBJ_ATTRIBUTE);
+				break;
+			}
+			case Node.TEXT_NODE : { // actually, TEXT should never be seen in
+				// the tree
+				image = createXMLImageDescriptor(XMLEditorPluginImages.IMG_OBJ_TXTEXT);
+				break;
+			}
+			case Node.CDATA_SECTION_NODE : {
+				image = createXMLImageDescriptor(XMLEditorPluginImages.IMG_OBJ_CDATASECTION);
+				break;
+			}
+			case Node.ENTITY_REFERENCE_NODE :
+			case Node.ENTITY_NODE : {
+				image = createXMLImageDescriptor(XMLEditorPluginImages.IMG_OBJ_ENTITY);
+				break;
+			}
+			case Node.PROCESSING_INSTRUCTION_NODE : {
+				image = createXMLImageDescriptor(XMLEditorPluginImages.IMG_OBJ_PROCESSINGINSTRUCTION);
+				break;
+			}
+			case Node.COMMENT_NODE : {
+				image = createXMLImageDescriptor(XMLEditorPluginImages.IMG_OBJ_COMMENT);
+				break;
+			}
+			case Node.DOCUMENT_TYPE_NODE : {
+				image = createXMLImageDescriptor(XMLEditorPluginImages.IMG_OBJ_DOCTYPE);
+				break;
+			}
+			case Node.NOTATION_NODE : {
+				image = createXMLImageDescriptor(XMLEditorPluginImages.IMG_OBJ_NOTATION);
+				break;
+			}
+			default : {
+				image = createXMLImageDescriptor(XMLEditorPluginImages.IMG_OBJ_TXTEXT);
+				break;
+			}
+		}
+		return image;
+	}
+
+	protected Image createXMLImageDescriptor(String imageResourceName) {
+		return XMLEditorPluginImageHelper.getInstance().getImage(imageResourceName);
+	}
+
+	public Object[] getChildren(Object object) {
+
+		// (pa) 20021217
+		// cmvc defect 235554
+		// performance enhancement: using child.getNextSibling() rather than
+		// nodeList(item) for O(n) vs. O(n*n)
+		//
+		ArrayList v = new ArrayList();
+		if (object instanceof Node) {
+			Node node = (Node) object;
+			for (Node child = node.getFirstChild(); child != null; child = child.getNextSibling()) {
+				Node n = child;
+				if (n.getNodeType() != Node.TEXT_NODE) {
+					v.add(n);
+				}
+			}
+		}
+		return v.toArray();
+	}
+
+	/**
+	 * Returns an enumeration with the elements belonging to the passed
+	 * element. These are the top level items in a list, tree, table, etc...
+	 */
+	public Object[] getElements(Object node) {
+		return getChildren(node);
+	}
+
+	/**
+	 * Fetches the label image specific to this object instance.
+	 */
+	public Image getLabelImage(Object node) {
+		Image image = null;
+		if (node instanceof Node) {
+			// check for an image from the content model
+			image = CMImageUtil.getImage(CMImageUtil.getDeclaration((Node) node));
+			if (image == null) {
+				/*
+				 * Create/get image based on Node type. Images are cached
+				 * transparently in this class, subclasses must do this for
+				 * themselves if they're going to return their own results.
+				 */
+				image = createImage(node);
+			}
+		}
+		return image;
+	}
+
+	/**
+	 * Fetches the label text specific to this object instance.
+	 */
+	public String getLabelText(Object node) {
+		return getNodeName(node);
+	}
+
+	private String getNodeName(Object object) {
+		StringBuffer nodeName = new StringBuffer();
+		if (object instanceof Node) {
+			Node node = (Node) object;
+			nodeName.append(node.getNodeName());
+
+			if (node.getNodeType() == Node.DOCUMENT_TYPE_NODE) {
+				nodeName.insert(0, "DOCTYPE:"); //$NON-NLS-1$
+			}
+
+		}
+		return nodeName.toString();
+	}
+
+
+	public Object getParent(Object object) {
+		if (object instanceof Node) {
+			Node node = (Node) object;
+			return node.getParentNode();
+		}
+		return null;
+	}
+
+	private synchronized RefreshStructureJob getRefreshJob() {
+		if (fRefreshJob == null) {
+			fRefreshJob = new RefreshStructureJob();
+		}
+		return fRefreshJob;
+	}
+
+
+	public boolean hasChildren(Object object) {
+		// (pa) 20021217
+		// cmvc defect 235554 > use child.getNextSibling() instead of
+		// nodeList(item) for O(n) vs. O(n*n)
+		Node node = (Node) object;
+		for (Node child = node.getFirstChild(); child != null; child = child.getNextSibling()) {
+			if (child.getNodeType() != Node.TEXT_NODE) {
+				return true;
+			}
+		}
+		return false;
+	}
+
+	/**
+	 * Allowing the INodeAdapter to compare itself against the type allows it
+	 * to return true in more than one case.
+	 */
+	public boolean isAdapterForType(Object type) {
+		if (type == null) {
+			return false;
+		}
+		return type.equals(ADAPTER_KEY);
+	}
+
+	/**
+	 * Called by the object being adapter (the notifier) when something has
+	 * changed.
+	 */
+	public void notifyChanged(INodeNotifier notifier, int eventType, Object changedFeature, Object oldValue, Object newValue, int pos) {
+		// future_TODO: the 'uijobs' used in this method were added to solve
+		// threading problems when the dom
+		// is updated in the background while the editor is open. They may be
+		// a bit overkill and not that useful.
+		// (That is, may be be worthy of job manager management). If they are
+		// found to be important enough to leave in,
+		// there's probably some optimization that can be done.
+		if (notifier instanceof Node) {
+			Collection listeners = fAdapterFactory.getListeners();
+			Iterator iterator = listeners.iterator();
+
+			while (iterator.hasNext()) {
+				Object listener = iterator.next();
+				// https://bugs.eclipse.org/bugs/show_bug.cgi?id=90637
+				// if (notifier instanceof Node && (listener instanceof
+				// StructuredViewer) && (eventType ==
+				// INodeNotifier.STRUCTURE_CHANGED || (eventType ==
+				// INodeNotifier.CHANGE && changedFeature == null))) {
+				if ((listener instanceof StructuredViewer) && ((eventType == INodeNotifier.STRUCTURE_CHANGED) || (eventType == INodeNotifier.CONTENT_CHANGED) || (eventType == INodeNotifier.CHANGE))) {
+					if (DEBUG) {
+						System.out.println("JFaceNodeAdapter notified on event type > " + eventType); //$NON-NLS-1$
+					}
+
+					// refresh on structural and "unknown" changes
+					StructuredViewer structuredViewer = (StructuredViewer) listener;
+					// https://w3.opensource.ibm.com/bugzilla/show_bug.cgi?id=5230
+					if (structuredViewer.getControl() != null) {
+						getRefreshJob().refresh(structuredViewer, (Node) notifier);
+					}
+				}
+			}
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentoutline/JFaceNodeAdapterFactory.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentoutline/JFaceNodeAdapterFactory.java
new file mode 100644
index 0000000..3943403
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentoutline/JFaceNodeAdapterFactory.java
@@ -0,0 +1,183 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.contentoutline;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jface.viewers.StructuredViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.ui.progress.UIJob;
+import org.eclipse.wst.sse.core.internal.provisional.AbstractAdapterFactory;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapter;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapterFactory;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.sse.core.internal.util.Assert;
+import org.eclipse.wst.sse.ui.internal.contentoutline.IJFaceNodeAdapter;
+import org.eclipse.wst.sse.ui.internal.contentoutline.IJFaceNodeAdapterFactory;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.CMDocumentManager;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.CMDocumentManagerListener;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.CMDocumentCache;
+import org.eclipse.wst.xml.core.internal.ssemodelquery.ModelQueryAdapter;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+
+
+/**
+ * An adapter factory to create JFaceNodeAdapters. Use this adapter factory
+ * with a JFaceAdapterContentProvider to display DOM nodes in a tree.
+ */
+public class JFaceNodeAdapterFactory extends AbstractAdapterFactory implements IJFaceNodeAdapterFactory {
+	public class CMDocumentManagerListenerImpl implements CMDocumentManagerListener {
+		private static final int UPDATE_DELAY = 200;
+
+		public void cacheCleared(CMDocumentCache cache) {
+			// nothing to do
+		}
+
+		public void cacheUpdated(CMDocumentCache cache, final String uri, int oldStatus, int newStatus, CMDocument cmDocument) {
+			if ((newStatus == CMDocumentCache.STATUS_LOADED) || (newStatus == CMDocumentCache.STATUS_ERROR)) {
+				refreshViewers();
+			}
+		}
+
+		public void propertyChanged(CMDocumentManager cmDocumentManager, String propertyName) {
+			if (cmDocumentManager.getPropertyEnabled(CMDocumentManager.PROPERTY_AUTO_LOAD)) {
+				refreshViewers();
+			}
+		}
+
+		private void refreshViewers() {
+			Object[] listeners = getListeners().toArray();
+			for (int i = 0; i < listeners.length; i++) {
+				if (listeners[i] instanceof StructuredViewer) {
+					final StructuredViewer viewer = (StructuredViewer) listeners[i];
+					Job refresh = new UIJob(XMLUIMessages.refreshoutline_0) {
+						public IStatus runInUIThread(IProgressMonitor monitor) {
+							Control refreshControl = viewer.getControl();
+							if ((refreshControl != null) && !refreshControl.isDisposed()) {
+								viewer.refresh(true);
+							}
+							return Status.OK_STATUS;
+						}
+					};
+					refresh.setSystem(true);
+					refresh.setPriority(Job.SHORT);
+					refresh.schedule(UPDATE_DELAY);
+				}
+				else if (listeners[i] instanceof Viewer) {
+					final Viewer viewer = (Viewer) listeners[i];
+					Job refresh = new UIJob(XMLUIMessages.refreshoutline_0) {
+						public IStatus runInUIThread(IProgressMonitor monitor) {
+							Control refreshControl = viewer.getControl();
+							if ((refreshControl != null) && !refreshControl.isDisposed()) {
+								viewer.refresh();
+							}
+							return Status.OK_STATUS;
+						}
+					};
+					refresh.setSystem(true);
+					refresh.setPriority(Job.SHORT);
+					refresh.schedule(UPDATE_DELAY);
+				}
+			}
+		}
+	}
+
+	private CMDocumentManager cmDocumentManager;
+	private CMDocumentManagerListenerImpl fCMDocumentManagerListener = null;
+	/**
+	 * This keeps track of all the listeners.
+	 */
+	private Set fListeners = new HashSet();
+
+	protected INodeAdapter singletonAdapter;
+
+	public JFaceNodeAdapterFactory() {
+		this(IJFaceNodeAdapter.class, true);
+	}
+
+	public JFaceNodeAdapterFactory(Object adapterKey, boolean registerAdapters) {
+		super(adapterKey, registerAdapters);
+	}
+
+	public synchronized void addListener(Object listener) {
+		fListeners.add(listener);
+	}
+
+	public INodeAdapterFactory copy() {
+		return new JFaceNodeAdapterFactory(getAdapterKey(), isShouldRegisterAdapter());
+	}
+
+	/**
+	 * Create a new JFace adapter for the DOM node passed in
+	 */
+	protected INodeAdapter createAdapter(INodeNotifier node) {
+		if (singletonAdapter == null) {
+			// create the JFaceNodeAdapter
+			singletonAdapter = new JFaceNodeAdapter(this);
+			initAdapter(singletonAdapter, node);
+		}
+		return singletonAdapter;
+	}
+
+
+	/**
+	 * returns "copy" so no one can modify our list. It is a shallow copy.
+	 */
+	public synchronized Collection getListeners() {
+		return new ArrayList(fListeners);
+	}
+
+	protected void initAdapter(INodeAdapter adapter, INodeNotifier node) {
+		Assert.isTrue(cmDocumentManager == null);
+		Assert.isTrue(fCMDocumentManagerListener == null);
+
+		// register for CMDocumentManager events
+		ModelQueryAdapter mqadapter = (ModelQueryAdapter) node.getAdapterFor(ModelQueryAdapter.class);
+		if (mqadapter != null) {
+			ModelQuery mquery = mqadapter.getModelQuery();
+			if ((mquery != null) && (mquery.getCMDocumentManager() != null)) {
+				cmDocumentManager = mquery.getCMDocumentManager();
+				fCMDocumentManagerListener = new CMDocumentManagerListenerImpl();
+				cmDocumentManager.addListener(fCMDocumentManagerListener);
+			}
+		}
+	}
+
+	public void release() {
+		// deregister from CMDocumentManager events
+		if ((cmDocumentManager != null) && (fCMDocumentManagerListener != null)) {
+			cmDocumentManager.removeListener(fCMDocumentManagerListener);
+		}
+		fListeners.clear();
+		if (singletonAdapter != null && singletonAdapter instanceof JFaceNodeAdapter) {
+			RefreshStructureJob refreshJob = ((JFaceNodeAdapter) singletonAdapter).fRefreshJob;
+			if (refreshJob != null) {
+				refreshJob.cancel();
+			}
+		}
+	}
+
+	public synchronized void removeListener(Object listener) {
+		fListeners.remove(listener);
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentoutline/JFaceNodeContentProvider.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentoutline/JFaceNodeContentProvider.java
new file mode 100644
index 0000000..f3c5452
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentoutline/JFaceNodeContentProvider.java
@@ -0,0 +1,120 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.contentoutline;
+
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapter;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.ui.internal.contentoutline.IJFaceNodeAdapter;
+import org.eclipse.wst.sse.ui.internal.contentoutline.IJFaceNodeAdapterFactory;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
+
+
+/**
+ * An ITreeContentProvider for a TreeViewers used to display DOM nodes. This
+ * content provider takes an adapter factory to create JFace adapters for the
+ * nodes in the tree.
+ */
+public class JFaceNodeContentProvider implements ITreeContentProvider {
+
+	public JFaceNodeContentProvider() {
+		super();
+	}
+
+	/**
+	 * The visual part that is using this content provider is about to be
+	 * disposed. Deallocate all allocated SWT resources.
+	 */
+	public void dispose() {
+	}
+
+	/**
+	 * Returns the JFace adapter for the specified object.
+	 * 
+	 * @param adaptable
+	 *            java.lang.Object The object to get the adapter for
+	 */
+	protected IJFaceNodeAdapter getAdapter(Object adaptable) {
+		if (adaptable instanceof INodeNotifier) {
+			INodeAdapter adapter = ((INodeNotifier) adaptable).getAdapterFor(IJFaceNodeAdapter.class);
+			if (adapter instanceof IJFaceNodeAdapter) {
+				return (IJFaceNodeAdapter) adapter;
+			}
+		}
+		return null;
+	}
+
+	public Object[] getChildren(Object object) {
+		IJFaceNodeAdapter adapter = getAdapter(object);
+
+		if (adapter != null) {
+			return adapter.getChildren(object);
+		}
+
+		return new Object[0];
+	}
+
+	public Object[] getElements(Object object) {
+		// The root is usually an instance of an XMLStructuredModel in
+		// which case we want to extract the document.
+		Object topNode = object;
+		if (object instanceof IDOMModel) {
+			topNode = ((IDOMModel) object).getDocument();
+		}
+
+		IJFaceNodeAdapter adapter = getAdapter(topNode);
+
+		if (adapter != null) {
+			return adapter.getElements(topNode);
+		}
+
+		return new Object[0];
+	}
+
+	public Object getParent(Object object) {
+		IJFaceNodeAdapter adapter = getAdapter(object);
+
+		if (adapter != null) {
+			return adapter.getParent(object);
+		}
+
+		return null;
+	}
+
+	public boolean hasChildren(Object object) {
+		IJFaceNodeAdapter adapter = getAdapter(object);
+
+		if (adapter != null) {
+			return adapter.hasChildren(object);
+		}
+
+		return false;
+	}
+
+	public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+		if ((oldInput != null) && (oldInput instanceof IStructuredModel)) {
+			IJFaceNodeAdapterFactory factory = (IJFaceNodeAdapterFactory) ((IStructuredModel) oldInput).getFactoryRegistry().getFactoryFor(IJFaceNodeAdapter.class);
+			if (factory != null) {
+				factory.removeListener(viewer);
+			}
+		}
+		if ((newInput != null) && (newInput instanceof IStructuredModel)) {
+			IJFaceNodeAdapterFactory factory = (IJFaceNodeAdapterFactory) ((IStructuredModel) newInput).getFactoryRegistry().getFactoryFor(IJFaceNodeAdapter.class);
+			if (factory != null) {
+				factory.addListener(viewer);
+			}
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentoutline/JFaceNodeLabelProvider.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentoutline/JFaceNodeLabelProvider.java
new file mode 100644
index 0000000..6168dde
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentoutline/JFaceNodeLabelProvider.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2008 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.contentoutline;
+
+import org.eclipse.jface.viewers.ColumnLabelProvider;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapter;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.sse.ui.internal.contentoutline.IJFaceNodeAdapter;
+
+/**
+ * A (column) label provider backed by JFaceNodeAdapters.
+ */
+public class JFaceNodeLabelProvider extends ColumnLabelProvider {
+	/**
+	 * JFaceNodeLabelProvider constructor comment.
+	 */
+	public JFaceNodeLabelProvider() {
+		super();
+	}
+
+	/**
+	 * Returns the JFace adapter for the specified object.
+	 * 
+	 * @param adaptable
+	 *            java.lang.Object The object to get the adapter for
+	 */
+	protected IJFaceNodeAdapter getAdapter(Object adaptable) {
+		if (adaptable instanceof INodeNotifier) {
+			INodeAdapter adapter = ((INodeNotifier) adaptable).getAdapterFor(IJFaceNodeAdapter.class);
+			if (adapter instanceof IJFaceNodeAdapter) {
+				return (IJFaceNodeAdapter) adapter;
+			}
+		}
+		return null;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.viewers.ILabelProvider#getImage(java.lang.Object)
+	 */
+	public Image getImage(Object element) {
+		IJFaceNodeAdapter adapter = getAdapter(element);
+		if (adapter != null)
+			return adapter.getLabelImage(element);
+		return super.getImage(element);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.viewers.ILabelProvider#getText(java.lang.Object)
+	 */
+	public String getText(Object element) {
+		IJFaceNodeAdapter adapter = getAdapter(element);
+		if (adapter != null)
+			return adapter.getLabelText(element);
+		return super.getText(element);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.viewers.IBaseLabelProvider#isLabelProperty(java.lang.Object,
+	 *      java.lang.String)
+	 */
+	public boolean isLabelProperty(Object element, String property) {
+		return false;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentoutline/RefreshStructureJob.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentoutline/RefreshStructureJob.java
new file mode 100644
index 0000000..55c9390
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentoutline/RefreshStructureJob.java
@@ -0,0 +1,368 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.contentoutline;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jface.viewers.StructuredViewer;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+/**
+ * This job holds a queue of updates (affected nodes) for multiple structured
+ * viewers. When a new request comes in, the current run is cancelled, the new
+ * request is added to the queue, then the job is re-scheduled. Support for
+ * multiple structured viewers is required because refresh updates are usually
+ * triggered by model changes, and the model may be visible in more than one
+ * viewer.
+ * 
+ * @author pavery
+ */
+class RefreshStructureJob extends Job {
+
+	/** debug flag */
+	static final boolean DEBUG;
+	private static final long UPDATE_DELAY = 300;
+	static {
+		String value = Platform.getDebugOption("org.eclipse.wst.sse.ui/debug/refreshStructure"); //$NON-NLS-1$
+		DEBUG = (value != null) && value.equalsIgnoreCase("true"); //$NON-NLS-1$
+	}
+	/** List of refresh requests (Nodes) */
+	private final List fRefreshes;
+	/** List of update requests (Nodes) */
+	private final List fUpdates;
+	/** List of update requests (Nodes) */
+	private final List fUpdateProperties;
+	/** the structured viewers */
+	Set fRefreshViewers = new HashSet(3);
+	Set fUpdateViewers = new HashSet(3);
+
+	public RefreshStructureJob() {
+		super(XMLUIMessages.refreshoutline_0);
+		setPriority(Job.LONG);
+		setSystem(true);
+		fRefreshes = new ArrayList(5);
+		fUpdates = new ArrayList(5);
+		fUpdateProperties = new ArrayList(5);
+	}
+
+	private synchronized void addUpdateRequest(Node newNodeRequest, String[] updateProperties) {
+		/*
+		 * If we get to here, either from existing request list being zero
+		 * length, or no exisitng requests "matched" new request, then add the
+		 * new request.
+		 */
+		fUpdates.add(newNodeRequest);
+		fUpdateProperties.add(updateProperties);
+	}
+
+	private synchronized void addUpdateViewer(StructuredViewer viewer) {
+		fUpdateViewers.add(viewer);
+	}
+
+	private synchronized void addRefreshRequest(Node newNodeRequest) {
+		/*
+		 * note: the caller must NOT pass in null node request (which, since
+		 * private method, we do not need to gaurd against here, as long as we
+		 * gaurd against it in calling method.
+		 */
+		int size = fRefreshes.size();
+		for (int i = 0; i < size; i++) {
+			Node existingNodeRequest = (Node) fRefreshes.get(i);
+			/*
+			 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=157427 If we
+			 * already have a request which equals the new request, discard
+			 * the new request
+			 */
+			if (existingNodeRequest.equals(newNodeRequest)) {
+				return;
+			}
+			/*
+			 * If we already have a request which contains the new request,
+			 * discard the new request
+			 */
+			if (contains(existingNodeRequest, newNodeRequest)) {
+				return;
+			}
+			/*
+			 * If new request contains any existing requests, replace it with
+			 * new request. ISSUE: technically, we should replace ALL
+			 * contained, existing requests (such as if many siblings already
+			 * que'd up when their common parent is then requested, but, I'm
+			 * not sure if that occurs much, in practice, or if there's an
+			 * algorithm to quickly find them all. Actually, I guess we could
+			 * just go through the _rest_ of the list (i+1 to size) and remove
+			 * any that are contained by new request ... in future :) .
+			 */
+			if (contains(newNodeRequest, existingNodeRequest)) {
+				fRefreshes.set(i, newNodeRequest);
+				return;
+			}
+		}
+		/*
+		 * If we get to here, either from existing request list being zero
+		 * length, or no exisitng requests "matched" new request, then add the
+		 * new request.
+		 */
+		fRefreshes.add(newNodeRequest);
+	}
+
+	private synchronized void addRefreshViewer(StructuredViewer viewer) {
+		fRefreshViewers.add(viewer);
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.core.runtime.jobs.Job#canceling()
+	 */
+	protected void canceling() {
+		fUpdates.clear();
+		fUpdateViewers.clear();
+		super.canceling();
+	}
+
+	/**
+	 * Simple hierarchical containment relationship. Note, this method returns
+	 * "false" if the two nodes are equal!
+	 * 
+	 * @param root
+	 * @param possible
+	 * @return if the root is parent of possible, return true, otherwise
+	 *         return false
+	 */
+	private boolean contains(Node root, Node possible) {
+		if (DEBUG) {
+			System.out.println("=============================================================================================================="); //$NON-NLS-1$
+			System.out.println("recursive call w/ root: " + root.getNodeName() + " and possible: " + possible); //$NON-NLS-1$ //$NON-NLS-2$
+			System.out.println("--------------------------------------------------------------------------------------------------------------"); //$NON-NLS-1$
+		}
+
+		// the following checks are important
+		// #document node will break the algorithm otherwise
+
+		// can't contain the child if it's null
+		if (root == null) {
+			if (DEBUG) {
+				System.out.println("returning false: root is null"); //$NON-NLS-1$
+			}
+			return false;
+		}
+		// nothing can be parent of Document node
+		if (possible instanceof Document) {
+			if (DEBUG) {
+				System.out.println("returning false: possible is Document node"); //$NON-NLS-1$
+			}
+			return false;
+		}
+		// document contains everything
+		if (root instanceof Document) {
+			if (DEBUG) {
+				System.out.println("returning true: root is Document node"); //$NON-NLS-1$
+			}
+			return true;
+		}
+
+		// check parentage
+		Node current = possible;
+		// loop parents
+		while ((current != null) && (current.getNodeType() != Node.DOCUMENT_NODE)) {
+			// found it
+			if (root.equals(current)) {
+				if (DEBUG) {
+					System.out.println("   !!! found: " + possible.getNodeName() + " in subelement of: " + root.getNodeName()); //$NON-NLS-1$ //$NON-NLS-2$
+				}
+				return true;
+			}
+			current = current.getParentNode();
+		}
+		// never found it
+		return false;
+	}
+
+	/**
+	 * Refresh must be on UI thread because it's on a SWT widget.
+	 * 
+	 * @param node
+	 */
+	private void doRefresh(final Node node, final StructuredViewer[] viewers) {
+		final Display display = PlatformUI.getWorkbench().getDisplay();
+		display.asyncExec(new Runnable() {
+			public void run() {
+				if (DEBUG) {
+					System.out.println("refresh on: [" + node.getNodeName() + "]"); //$NON-NLS-1$ //$NON-NLS-2$
+				}
+
+				for (int i = 0; i < viewers.length; i++) {
+					if (!viewers[i].getControl().isDisposed()) {
+						if (node.getNodeType() == Node.DOCUMENT_NODE) {
+							viewers[i].refresh(true);
+						}
+						else {
+							viewers[i].refresh(node, true);
+						}
+					}
+					else {
+						if (DEBUG) {
+							System.out.println("   !!! skipped refreshing disposed viewer: " + viewers[i]); //$NON-NLS-1$
+						}
+					}
+				}
+			}
+		});
+	}
+
+	/**
+	 * Update must be on UI thread because it's on a SWT widget.
+	 * 
+	 * @param node
+	 */
+	private void doUpdate(final StructuredViewer[] viewers, final Node node, final String[] properties) {
+		final Display display = PlatformUI.getWorkbench().getDisplay();
+		display.asyncExec(new Runnable() {
+			public void run() {
+				if (DEBUG) {
+					System.out.println("refresh on: [" + node.getNodeName() + "]"); //$NON-NLS-1$ //$NON-NLS-2$
+				}
+
+				for (int i = 0; i < viewers.length; i++) {
+					if (!viewers[i].getControl().isDisposed()) {
+						viewers[i].update(node, properties);
+					}
+					else {
+						if (DEBUG) {
+							System.out.println("   !!! skipped refreshing disposed viewer: " + viewers[i]); //$NON-NLS-1$
+						}
+					}
+				}
+			}
+		});
+	}
+
+	/**
+	 * This method also synchronized because it accesses the fRefreshes queue
+	 * and fRefreshViewers list
+	 * 
+	 * @return an array containing and array of the currently requested Nodes
+	 *         to refresh and the viewers in which to refresh them
+	 */
+	private synchronized Object[] getRefreshRequests() {
+		Node[] toRefresh = (Node[]) fRefreshes.toArray(new Node[fRefreshes.size()]);
+		fRefreshes.clear();
+
+		StructuredViewer[] viewers = (StructuredViewer[]) fRefreshViewers.toArray(new StructuredViewer[fRefreshViewers.size()]);
+		fRefreshViewers.clear();
+
+		return new Object[]{toRefresh, viewers};
+	}
+
+	/**
+	 * This method also synchronized because it accesses the fUpdates queue
+	 * and fUpdateViewers list
+	 * 
+	 * @return an array containing and array of the currently requested Nodes
+	 *         to refresh and the viewers in which to refresh them
+	 */
+	private synchronized Object[] getUpdateRequests() {
+		Node[] toUpdate = (Node[]) fUpdates.toArray(new Node[fUpdates.size()]);
+		fUpdates.clear();
+
+		StructuredViewer[] viewers = (StructuredViewer[]) fUpdateViewers.toArray(new StructuredViewer[fUpdateViewers.size()]);
+		fUpdateViewers.clear();
+
+		String[][] properties = (String[][]) fUpdateProperties.toArray(new String[fUpdateProperties.size()][]);
+		fUpdateProperties.clear();
+
+		return new Object[]{toUpdate, viewers, properties};
+	}
+
+	/**
+	 * Invoke a refresh on the viewer on the given node.
+	 * 
+	 * @param node
+	 */
+	public void refresh(StructuredViewer viewer, Node node) {
+		if (node == null) {
+			return;
+		}
+
+		addRefreshViewer(viewer);
+		addRefreshRequest(node);
+		schedule(UPDATE_DELAY);
+	}
+
+	/**
+	 * Invoke a refresh on the viewer on the given node.
+	 * 
+	 * @param node
+	 */
+	public void update(StructuredViewer viewer, Node node, String[] properties) {
+		if (node == null) {
+			return;
+		}
+
+		addUpdateViewer(viewer);
+		addUpdateRequest(node, properties);
+		schedule(UPDATE_DELAY);
+	}
+
+	protected IStatus run(IProgressMonitor monitor) {
+		IStatus status = Status.OK_STATUS;
+		try {
+			performUpdates();
+			
+			performRefreshes(monitor);
+		}
+		finally {
+			monitor.done();
+		}
+		return status;
+	}
+
+	private void performRefreshes(IProgressMonitor monitor) {
+		// Retrieve BOTH viewers and Nodes on one block
+		Object[] requests = getRefreshRequests();
+		Node[] nodes = (Node[]) requests[0];
+		StructuredViewer[] viewers = (StructuredViewer[]) requests[1];
+
+		for (int i = 0; i < nodes.length; i++) {
+			if (monitor.isCanceled()) {
+				throw new OperationCanceledException();
+			}
+			doRefresh(nodes[i], viewers);
+		}
+	}
+
+	private void performUpdates() {
+		// Retrieve BOTH viewers and Nodes on one block
+		Object[] requests = getUpdateRequests();
+		Node[] nodes = (Node[]) requests[0];
+		StructuredViewer[] viewers = (StructuredViewer[]) requests[1];
+		String[][] properties = (String[][]) requests[2];
+
+		for (int i = 0; i < nodes.length; i++) {
+			doUpdate(viewers, nodes[i], properties[i]);
+		}
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentoutline/XMLNodeActionManager.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentoutline/XMLNodeActionManager.java
new file mode 100644
index 0000000..f858071
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentoutline/XMLNodeActionManager.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.contentoutline;
+
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.wst.sse.core.internal.format.IStructuredFormatProcessor;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.modelquery.ModelQueryUtil;
+import org.eclipse.wst.xml.core.internal.provisional.format.FormatProcessorXML;
+import org.eclipse.wst.xml.ui.internal.actions.AbstractNodeActionManager;
+import org.w3c.dom.Node;
+
+
+public class XMLNodeActionManager extends AbstractNodeActionManager {
+	public XMLNodeActionManager(IStructuredModel model, Viewer viewer) {
+		super(model, ModelQueryUtil.getModelQuery(model), viewer);
+	}
+
+	public void reformat(Node newElement, boolean deep) {
+		try {
+			// tell the model that we are about to make a big model change
+			fModel.aboutToChangeModel();
+
+			// format selected node
+			IStructuredFormatProcessor formatProcessor = new FormatProcessorXML();
+			formatProcessor.formatNode(newElement);
+		}
+		finally {
+			// tell the model that we are done with the big model change
+			fModel.changedModel();
+		}
+	}
+
+	public void setModel(IStructuredModel newModel) {
+		fModel = newModel;
+		setModelQuery(ModelQueryUtil.getModelQuery(newModel));
+	}
+
+	protected void setModelQuery(ModelQuery newModelQuery) {
+		modelQuery = newModelQuery;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/CorrectionAssistantProviderXML.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/CorrectionAssistantProviderXML.java
new file mode 100644
index 0000000..2c11048
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/CorrectionAssistantProviderXML.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.correction;
+
+import org.eclipse.jface.text.contentassist.ContentAssistant;
+import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
+import org.eclipse.jface.text.contentassist.IContentAssistant;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.wst.sse.ui.internal.correction.CorrectionAssistantProvider;
+import org.eclipse.wst.xml.core.text.IXMLPartitions;
+
+/**
+ * Correction assistant for XML
+ * 
+ * @deprecated since 2.0 RC0 Use
+ *             org.eclipse.jface.text.quickassist.IQuickAssistProcessor;
+ */
+public class CorrectionAssistantProviderXML extends CorrectionAssistantProvider {
+
+	public IContentAssistant getCorrectionAssistant(ISourceViewer sourceViewer) {
+		IContentAssistant ca = null;
+
+		if (sourceViewer != null) {
+			ContentAssistant assistant = new ContentAssistant();
+
+			if (sourceViewer != null) {
+				IContentAssistProcessor correctionProcessor = new CorrectionProcessorXML(sourceViewer);
+				assistant.setContentAssistProcessor(correctionProcessor, IXMLPartitions.XML_DEFAULT);
+				assistant.setContentAssistProcessor(correctionProcessor, IXMLPartitions.XML_CDATA);
+				assistant.setContentAssistProcessor(correctionProcessor, IXMLPartitions.XML_COMMENT);
+				assistant.setContentAssistProcessor(correctionProcessor, IXMLPartitions.XML_DECLARATION);
+				assistant.setContentAssistProcessor(correctionProcessor, IXMLPartitions.XML_PI);
+				assistant.setContentAssistProcessor(correctionProcessor, IXMLPartitions.DTD_SUBSET);
+			}
+			ca = assistant;
+		}
+
+		return ca;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/CorrectionProcessorXML.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/CorrectionProcessorXML.java
new file mode 100644
index 0000000..97e73e7
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/CorrectionProcessorXML.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.correction;
+
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.wst.sse.ui.internal.correction.IQuickAssistProcessor;
+import org.eclipse.wst.sse.ui.internal.correction.IQuickFixProcessor;
+import org.eclipse.wst.sse.ui.internal.correction.StructuredCorrectionProcessor;
+
+/**
+ * @deprecated since 2.0 RC0 Use
+ *             org.eclipse.jface.text.quickassist.IQuickAssistProcessor;
+ */
+public class CorrectionProcessorXML extends StructuredCorrectionProcessor {
+	protected IQuickAssistProcessor fQuickAssistProcessor;
+	protected IQuickFixProcessor fQuickFixProcessor;
+
+	public CorrectionProcessorXML(ISourceViewer sourceViewer) {
+		super(sourceViewer);
+	}
+
+	protected IQuickAssistProcessor getQuickAssistProcessor() {
+		if (fQuickAssistProcessor == null) {
+			fQuickAssistProcessor = new QuickAssistProcessorXML();
+		}
+
+		return fQuickAssistProcessor;
+	}
+
+	protected IQuickFixProcessor getQuickFixProcessor() {
+		if (fQuickFixProcessor == null) {
+			fQuickFixProcessor = new QuickFixProcessorXML();
+		}
+
+		return fQuickFixProcessor;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/InsertRequiredAttrsQuickAssistProposal.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/InsertRequiredAttrsQuickAssistProposal.java
new file mode 100644
index 0000000..74947ed
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/InsertRequiredAttrsQuickAssistProposal.java
@@ -0,0 +1,180 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.correction;
+
+import java.util.List;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.DocumentEvent;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.jface.text.contentassist.ICompletionProposalExtension2;
+import org.eclipse.jface.text.contentassist.IContextInformation;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.text.edits.InsertEdit;
+import org.eclipse.text.edits.MultiTextEdit;
+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.ui.internal.contentassist.ContentAssistUtils;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+import org.eclipse.wst.xml.ui.internal.Logger;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImageHelper;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImages;
+
+public class InsertRequiredAttrsQuickAssistProposal implements ICompletionProposal, ICompletionProposalExtension2 {
+	private final List fRequiredAttrs;
+
+	/**
+	 * @param requiredAttrs
+	 */
+	public InsertRequiredAttrsQuickAssistProposal(List requiredAttrs) {
+		fRequiredAttrs = requiredAttrs;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.contentassist.ICompletionProposal#apply(org.eclipse.jface.text.IDocument)
+	 */
+	public void apply(IDocument document) {
+		// not implemented?
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#apply(org.eclipse.jface.text.ITextViewer,
+	 *      char, int, int)
+	 */
+	public void apply(ITextViewer viewer, char trigger, int stateMask, int offset) {
+		IDOMNode node = (IDOMNode) ContentAssistUtils.getNodeAt(viewer, offset);
+		IStructuredDocumentRegion startStructuredDocumentRegion = node.getStartStructuredDocumentRegion();
+		int index = startStructuredDocumentRegion.getEndOffset();
+		ITextRegion lastRegion = startStructuredDocumentRegion.getLastRegion();
+		if (lastRegion.getType() == DOMRegionContext.XML_TAG_CLOSE) {
+			index--;
+			lastRegion = startStructuredDocumentRegion.getRegionAtCharacterOffset(index - 1);
+		}
+		else if (lastRegion.getType() == DOMRegionContext.XML_EMPTY_TAG_CLOSE) {
+			index = index - 2;
+			lastRegion = startStructuredDocumentRegion.getRegionAtCharacterOffset(index - 1);
+		}
+		MultiTextEdit multiTextEdit = new MultiTextEdit();
+		try {
+			for (int i = 0; i < fRequiredAttrs.size(); i++) {
+				CMAttributeDeclaration attrDecl = (CMAttributeDeclaration) fRequiredAttrs.get(i);
+				String requiredAttributeName = attrDecl.getAttrName();
+				String defaultValue = attrDecl.getDefaultValue();
+				if (defaultValue == null) {
+					defaultValue = ""; //$NON-NLS-1$
+				}
+				String nameAndDefaultValue = " "; //$NON-NLS-1$
+				if ((i == 0) && (lastRegion.getLength() > lastRegion.getTextLength())) {
+					nameAndDefaultValue = ""; //$NON-NLS-1$
+				}
+				nameAndDefaultValue += requiredAttributeName + "=\"" + defaultValue + "\""; //$NON-NLS-1$//$NON-NLS-2$
+				multiTextEdit.addChild(new InsertEdit(index, nameAndDefaultValue));
+				// BUG3381: MultiTextEdit applies all child TextEdit's basing
+				// on offsets
+				// in the document before the first TextEdit, not after each
+				// child TextEdit. Therefore, do not need to advance the
+				// index.
+				// index += nameAndDefaultValue.length();
+			}
+			multiTextEdit.apply(viewer.getDocument());
+		}
+		catch (BadLocationException e) {
+			// log, for now, unless we find there's reasons why we get some
+			// here.
+			Logger.log(Logger.INFO, e.getMessage());
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getAdditionalProposalInfo()
+	 */
+	public String getAdditionalProposalInfo() {
+		return XMLUIMessages.InsertRequiredAttrsQuickAssistProposal_0;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getContextInformation()
+	 */
+	public IContextInformation getContextInformation() {
+		return null;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getDisplayString()
+	 */
+	public String getDisplayString() {
+		return XMLUIMessages.InsertRequiredAttrsQuickAssistProposal_1;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getImage()
+	 */
+	public Image getImage() {
+		// return JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_LOCAL);
+		return XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_ADD_CORRECTION);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getSelection(org.eclipse.jface.text.IDocument)
+	 */
+	public Point getSelection(IDocument document) {
+		return null;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#selected(org.eclipse.jface.text.ITextViewer,
+	 *      boolean)
+	 */
+	public void selected(ITextViewer viewer, boolean smartToggle) {
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#unselected(org.eclipse.jface.text.ITextViewer)
+	 */
+	public void unselected(ITextViewer viewer) {
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#validate(org.eclipse.jface.text.IDocument,
+	 *      int, org.eclipse.jface.text.DocumentEvent)
+	 */
+	public boolean validate(IDocument document, int offset, DocumentEvent event) {
+		return false;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/ProblemIDsXML.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/ProblemIDsXML.java
new file mode 100644
index 0000000..8bebba4
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/ProblemIDsXML.java
@@ -0,0 +1,16 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.correction;
+
+public interface ProblemIDsXML extends org.eclipse.wst.xml.core.internal.validation.ProblemIDsXML {
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/QuickAssistProcessorXML.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/QuickAssistProcessorXML.java
new file mode 100644
index 0000000..486c6c9
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/QuickAssistProcessorXML.java
@@ -0,0 +1,192 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2009 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.correction;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+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.ui.internal.StructuredTextViewer;
+import org.eclipse.wst.sse.ui.internal.contentassist.ContentAssistUtils;
+import org.eclipse.wst.sse.ui.internal.correction.IQuickAssistProcessor;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.contentmodel.basic.CMNamedNodeMapImpl;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.modelquery.ModelQueryUtil;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+/**
+ * @deprecated since 2.0 RC0 Use
+ *             org.eclipse.jface.text.quickassist.IQuickAssistProcessor and XMLQuickAssistProcessor
+ */
+public class QuickAssistProcessorXML implements IQuickAssistProcessor {
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.wst.sse.ui.correction.IQuickAssistProcessor#canAssist(org.eclipse.wst.sse.core.text.IStructuredDocument,
+	 *      int)
+	 */
+	public boolean canAssist(StructuredTextViewer viewer, int offset) {
+		return true;
+	}
+
+	/**
+	 * @param proposals
+	 * @param viewer
+	 * @param offset
+	 */
+	protected void getInsertRequiredAttrs(ArrayList proposals, StructuredTextViewer viewer, int offset) {
+		IDOMNode node = (IDOMNode) ContentAssistUtils.getNodeAt(viewer, offset);
+		if ((node != null) && (node.getNodeType() == Node.ELEMENT_NODE)) {
+			IStructuredDocumentRegion startStructuredDocumentRegion = node.getStartStructuredDocumentRegion();
+			if ((startStructuredDocumentRegion != null) && startStructuredDocumentRegion.containsOffset(offset)) {
+				IDOMNode cursorNode = (IDOMNode) ContentAssistUtils.getNodeAt(viewer, offset);
+				List requiredAttrs = getRequiredAttrs(cursorNode);
+				if (requiredAttrs.size() > 0) {
+					NamedNodeMap currentAttrs = node.getAttributes();
+					List insertAttrs = new ArrayList();
+					if (currentAttrs.getLength() == 0) {
+						insertAttrs.addAll(requiredAttrs);
+					}
+					else {
+						for (int i = 0; i < requiredAttrs.size(); i++) {
+							String requiredAttrName = ((CMAttributeDeclaration) requiredAttrs.get(i)).getAttrName();
+							boolean found = false;
+							for (int j = 0; j < currentAttrs.getLength(); j++) {
+								String currentAttrName = currentAttrs.item(j).getNodeName();
+								if (requiredAttrName.compareToIgnoreCase(currentAttrName) == 0) {
+									found = true;
+									break;
+								}
+							}
+							if (!found) {
+								insertAttrs.add(requiredAttrs.get(i));
+							}
+						}
+					}
+					if (insertAttrs.size() > 0) {
+						proposals.add(new InsertRequiredAttrsQuickAssistProposal(insertAttrs));
+					}
+				}
+			}
+		}
+	}
+
+	/**
+	 * @param proposals
+	 * @param viewer
+	 * @param offset
+	 */
+	protected void getLocalRenameQuickAssistProposal(ArrayList proposals, StructuredTextViewer viewer, int offset) {
+		IDOMNode node = (IDOMNode) ContentAssistUtils.getNodeAt(viewer, offset);
+		IStructuredDocumentRegion startStructuredDocumentRegion = node == null ? null : node.getStartStructuredDocumentRegion();
+		IStructuredDocumentRegion endStructuredDocumentRegion = node == null ? null : node.getEndStructuredDocumentRegion();
+
+		ITextRegion region = null;
+		int regionTextEndOffset = 0;
+		if ((startStructuredDocumentRegion != null) && startStructuredDocumentRegion.containsOffset(offset)) {
+			region = startStructuredDocumentRegion.getRegionAtCharacterOffset(offset);
+			regionTextEndOffset = startStructuredDocumentRegion.getTextEndOffset(region);
+		}
+		else if ((endStructuredDocumentRegion != null) && endStructuredDocumentRegion.containsOffset(offset)) {
+			region = endStructuredDocumentRegion.getRegionAtCharacterOffset(offset);
+			regionTextEndOffset = endStructuredDocumentRegion.getTextEndOffset(region);
+		}
+
+		if ((region != null) && ((region.getType() == DOMRegionContext.XML_TAG_NAME) || (region.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME)) && (offset <= regionTextEndOffset)) {
+			proposals.add(new RenameInFileQuickAssistProposal());
+		}
+	}
+
+	protected ModelQuery getModelQuery(Node node) {
+		if (node.getNodeType() == Node.DOCUMENT_NODE) {
+			return ModelQueryUtil.getModelQuery((Document) node);
+		}
+		else {
+			return ModelQueryUtil.getModelQuery(node.getOwnerDocument());
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.wst.sse.ui.correction.IQuickAssistProcessor#getProposals(org.eclipse.wst.sse.core.text.IStructuredDocument,
+	 *      int)
+	 */
+	public ICompletionProposal[] getProposals(StructuredTextViewer viewer, int offset) throws CoreException {
+		ArrayList proposals = new ArrayList();
+
+		getLocalRenameQuickAssistProposal(proposals, viewer, offset);
+		getSurroundWithNewElementQuickAssistProposal(proposals, viewer, offset);
+		getInsertRequiredAttrs(proposals, viewer, offset);
+
+		return (ICompletionProposal[]) proposals.toArray(new ICompletionProposal[proposals.size()]);
+	}
+
+	protected List getRequiredAttrs(Node node) {
+		List result = new ArrayList();
+
+		ModelQuery modelQuery = getModelQuery(node);
+		if (modelQuery != null) {
+			CMElementDeclaration elementDecl = modelQuery.getCMElementDeclaration((Element) node);
+			if (elementDecl != null) {
+				CMNamedNodeMap attrMap = elementDecl.getAttributes();
+
+				CMNamedNodeMapImpl allAttributes = new CMNamedNodeMapImpl(attrMap);
+				List nodes = ModelQueryUtil.getModelQuery(node.getOwnerDocument()).getAvailableContent((Element)node, elementDecl, ModelQuery.INCLUDE_ATTRIBUTES);
+				for (int k = 0; k < nodes.size(); k++) {
+					CMNode cmnode = (CMNode) nodes.get(k);
+					if (cmnode.getNodeType() == CMNode.ATTRIBUTE_DECLARATION) {
+						allAttributes.put(cmnode);
+					}
+				}
+				attrMap = allAttributes;
+				
+				Iterator it = attrMap.iterator();
+				CMAttributeDeclaration attr = null;
+				while (it.hasNext()) {
+					attr = (CMAttributeDeclaration) it.next();
+					if (attr.getUsage() == CMAttributeDeclaration.REQUIRED) {
+						result.add(attr);
+					}
+				}
+			}
+		}
+
+		return result;
+	}
+
+	/**
+	 * @param proposals
+	 * @param viewer
+	 * @param offset
+	 */
+	protected void getSurroundWithNewElementQuickAssistProposal(ArrayList proposals, StructuredTextViewer viewer, int offset) {
+		IDOMNode node = (IDOMNode) ContentAssistUtils.getNodeAt(viewer, offset);
+		if (node != null) {
+			proposals.add(new SurroundWithNewElementQuickAssistProposal());
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/QuickFixProcessorXML.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/QuickFixProcessorXML.java
new file mode 100644
index 0000000..600824f
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/QuickFixProcessorXML.java
@@ -0,0 +1,152 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.correction;
+
+import java.util.ArrayList;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.text.contentassist.CompletionProposal;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.jface.text.source.Annotation;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.wst.sse.ui.internal.correction.IQuickFixProcessor;
+import org.eclipse.wst.sse.ui.internal.reconcile.TemporaryAnnotation;
+import org.eclipse.wst.xml.core.internal.validation.ProblemIDsXML;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImageHelper;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImages;
+
+/**
+ * @deprecated since 2.0 RC0 Use
+ *             org.eclipse.jface.text.quickassist.IQuickAssistProcessor;
+ */
+public class QuickFixProcessorXML implements IQuickFixProcessor {
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.wst.sse.ui.correction.IQuickFixProcessor#canFix(int)
+	 */
+	public boolean canFix(Annotation annotation) {
+		boolean result = false;
+
+		if (annotation instanceof TemporaryAnnotation) {
+			TemporaryAnnotation tempAnnotation = (TemporaryAnnotation) annotation;
+			int problemID = tempAnnotation.getProblemID();
+			switch (problemID) {
+				case ProblemIDsXML.EmptyTag :
+				case ProblemIDsXML.MissingEndTag :
+				case ProblemIDsXML.AttrsInEndTag :
+				case ProblemIDsXML.MissingAttrValue :
+				case ProblemIDsXML.NoAttrValue :
+				case ProblemIDsXML.SpacesBeforeTagName :
+				case ProblemIDsXML.SpacesBeforePI :
+				case ProblemIDsXML.NamespaceInPI :
+				case ProblemIDsXML.UnknownElement :
+				case ProblemIDsXML.UnknownAttr :
+				case ProblemIDsXML.InvalidAttrValue :
+				case ProblemIDsXML.MissingRequiredAttr :
+				case ProblemIDsXML.AttrValueNotQuoted :
+				case ProblemIDsXML.MissingClosingBracket :
+					result = true;
+			}
+		}
+
+		return result;
+	}
+
+	public Image getImage() {
+		// return
+		// JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
+		return XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_CORRECTION_CHANGE);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.wst.sse.ui.correction.IQuickFixProcessor#getProposals(org.eclipse.wst.sse.ui.internal.reconcile.TemporaryAnnotation)
+	 */
+	public ICompletionProposal[] getProposals(Annotation annotation) throws CoreException {
+		ArrayList proposals = new ArrayList();
+
+		if (annotation instanceof TemporaryAnnotation) {
+			TemporaryAnnotation tempAnnotation = (TemporaryAnnotation) annotation;
+			int problemID = tempAnnotation.getProblemID();
+			switch (problemID) {
+				case ProblemIDsXML.EmptyTag :
+					proposals.add(new CompletionProposal("", tempAnnotation.getPosition().getOffset(), tempAnnotation.getPosition().getLength(), 0, getImage(), XMLUIMessages.QuickFixProcessorXML_0, null, "")); //$NON-NLS-1$ //$NON-NLS-2$ 
+					break;
+				case ProblemIDsXML.MissingEndTag :
+					String tagName = (String) ((Object[]) tempAnnotation.getAdditionalFixInfo())[0];
+					String tagClose = (String) ((Object[]) tempAnnotation.getAdditionalFixInfo())[1];
+					int tagCloseOffset = ((Integer) ((Object[]) tempAnnotation.getAdditionalFixInfo())[2]).intValue();
+					int startTagEndOffset = ((Integer) ((Object[]) tempAnnotation.getAdditionalFixInfo())[3]).intValue();
+					int firstChildStartOffset = ((Integer) ((Object[]) tempAnnotation.getAdditionalFixInfo())[4]).intValue();
+					int endOffset = ((Integer) ((Object[]) tempAnnotation.getAdditionalFixInfo())[5]).intValue();
+					proposals.add(new CompletionProposal(tagClose, tagCloseOffset, 0, 0, getImage(), XMLUIMessages.QuickFixProcessorXML_1, null, "")); //$NON-NLS-1$ 
+					proposals.add(new CompletionProposal("", tempAnnotation.getPosition().getOffset(), startTagEndOffset - tempAnnotation.getPosition().getOffset(), 0, getImage(), XMLUIMessages.QuickFixProcessorXML_2, null, "")); //$NON-NLS-1$ //$NON-NLS-2$ 
+					proposals.add(new CompletionProposal("</" + tagName + ">", firstChildStartOffset, 0, 0, getImage(), XMLUIMessages.QuickFixProcessorXML_3, null, "")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ 
+					proposals.add(new CompletionProposal("</" + tagName + ">", endOffset, 0, 0, getImage(), XMLUIMessages.QuickFixProcessorXML_4, null, "")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ 
+					break;
+				case ProblemIDsXML.AttrsInEndTag :
+					proposals.add(new CompletionProposal("", tempAnnotation.getPosition().getOffset(), tempAnnotation.getPosition().getLength(), 0, getImage(), XMLUIMessages.QuickFixProcessorXML_5, null, "")); //$NON-NLS-1$ //$NON-NLS-2$ 
+					break;
+				case ProblemIDsXML.MissingAttrValue :
+					String defaultAttrValue = (String) ((Object[]) tempAnnotation.getAdditionalFixInfo())[0];
+					int insertOffset = ((Integer) ((Object[]) tempAnnotation.getAdditionalFixInfo())[1]).intValue();
+					proposals.add(new CompletionProposal("\"" + defaultAttrValue + "\"", tempAnnotation.getPosition().getOffset() + tempAnnotation.getPosition().getLength() + insertOffset, 0, defaultAttrValue.length() + 2, getImage(), XMLUIMessages.QuickFixProcessorXML_6, null, "")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ 
+					proposals.add(new CompletionProposal("", tempAnnotation.getPosition().getOffset(), tempAnnotation.getPosition().getLength(), 0, getImage(), XMLUIMessages.QuickFixProcessorXML_7, null, "")); //$NON-NLS-1$ //$NON-NLS-2$ 
+					break;
+				case ProblemIDsXML.NoAttrValue :
+					defaultAttrValue = (String) tempAnnotation.getAdditionalFixInfo();
+					proposals.add(new CompletionProposal("=\"" + defaultAttrValue + "\"", tempAnnotation.getPosition().getOffset() + tempAnnotation.getPosition().getLength(), 0, defaultAttrValue.length() + 3, getImage(), XMLUIMessages.QuickFixProcessorXML_6, null, "")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ 
+					proposals.add(new CompletionProposal("", tempAnnotation.getPosition().getOffset(), tempAnnotation.getPosition().getLength(), 0, getImage(), XMLUIMessages.QuickFixProcessorXML_7, null, "")); //$NON-NLS-1$ //$NON-NLS-2$ 
+					break;
+				case ProblemIDsXML.SpacesBeforeTagName :
+					proposals.add(new CompletionProposal("", tempAnnotation.getPosition().getOffset(), tempAnnotation.getPosition().getLength(), 0, getImage(), XMLUIMessages.QuickFixProcessorXML_8, null, "")); //$NON-NLS-1$ //$NON-NLS-2$ 
+					break;
+				case ProblemIDsXML.SpacesBeforePI :
+					proposals.add(new CompletionProposal("", tempAnnotation.getPosition().getOffset(), tempAnnotation.getPosition().getLength(), 0, getImage(), XMLUIMessages.QuickFixProcessorXML_9, null, "")); //$NON-NLS-1$ //$NON-NLS-2$ 
+					break;
+				case ProblemIDsXML.NamespaceInPI :
+					proposals.add(new CompletionProposal("", tempAnnotation.getPosition().getOffset(), tempAnnotation.getPosition().getLength(), 0, getImage(), XMLUIMessages.QuickFixProcessorXML_10, null, "")); //$NON-NLS-1$ //$NON-NLS-2$ 
+					break;
+				case ProblemIDsXML.UnknownElement :
+					proposals.add(new RemoveUnknownElementQuickFixProposal(tempAnnotation.getAdditionalFixInfo(), getImage(), XMLUIMessages.QuickFixProcessorXML_11));
+					proposals.add(new RenameInFileQuickAssistProposal());
+					break;
+				case ProblemIDsXML.UnknownAttr :
+					proposals.add(new CompletionProposal("", tempAnnotation.getPosition().getOffset(), tempAnnotation.getPosition().getLength(), 0, getImage(), XMLUIMessages.QuickFixProcessorXML_7, null, "")); //$NON-NLS-1$ //$NON-NLS-2$ 
+					proposals.add(new RenameInFileQuickAssistProposal());
+					break;
+				case ProblemIDsXML.InvalidAttrValue :
+					proposals.add(new CompletionProposal("", tempAnnotation.getPosition().getOffset(), tempAnnotation.getPosition().getLength(), 0, getImage(), XMLUIMessages.QuickFixProcessorXML_12, null, "")); //$NON-NLS-1$ //$NON-NLS-2$ 
+					break;
+				case ProblemIDsXML.MissingRequiredAttr :
+					String requiredAttr = (String) ((Object[]) tempAnnotation.getAdditionalFixInfo())[0];
+					insertOffset = ((Integer) ((Object[]) tempAnnotation.getAdditionalFixInfo())[1]).intValue();
+					proposals.add(new CompletionProposal(requiredAttr, tempAnnotation.getPosition().getOffset() + insertOffset, 0, requiredAttr.length(), getImage(), XMLUIMessages.QuickFixProcessorXML_13, null, "")); //$NON-NLS-1$ 
+					break;
+				case ProblemIDsXML.AttrValueNotQuoted :
+					String attrValue = (String) tempAnnotation.getAdditionalFixInfo();
+					proposals.add(new CompletionProposal("\"" + attrValue + "\"", tempAnnotation.getPosition().getOffset(), tempAnnotation.getPosition().getLength(), attrValue.length() + 2, getImage(), XMLUIMessages.QuickFixProcessorXML_14, null, "")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ 
+					break;
+				case ProblemIDsXML.MissingClosingBracket :
+					proposals.add(new CompletionProposal(">", tempAnnotation.getPosition().getOffset() + tempAnnotation.getPosition().getLength(), 0, 1, getImage(), XMLUIMessages.QuickFixProcessorXML_15, null, "")); //$NON-NLS-1$ //$NON-NLS-2$ 
+					break;
+			}
+		}
+
+		return (ICompletionProposal[]) proposals.toArray(new ICompletionProposal[proposals.size()]);
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/RemoveUnknownElementQuickFixProposal.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/RemoveUnknownElementQuickFixProposal.java
new file mode 100644
index 0000000..b87a2c9
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/RemoveUnknownElementQuickFixProposal.java
@@ -0,0 +1,162 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.correction;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.DocumentEvent;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.jface.text.contentassist.ICompletionProposalExtension2;
+import org.eclipse.jface.text.contentassist.IContextInformation;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.text.edits.DeleteEdit;
+import org.eclipse.text.edits.MalformedTreeException;
+import org.eclipse.text.edits.MultiTextEdit;
+import org.eclipse.wst.xml.ui.internal.Logger;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+
+public class RemoveUnknownElementQuickFixProposal implements ICompletionProposal, ICompletionProposalExtension2 {
+	private Object fAdditionalFixInfo = null;
+	private String fDisplayString;
+	private Image fImage;
+	private Point fSelection; // initialized by apply()
+
+	public RemoveUnknownElementQuickFixProposal(Object additionalFixInfo, Image image, String displayString) {
+		fAdditionalFixInfo = additionalFixInfo;
+		fImage = image;
+		fDisplayString = displayString;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.contentassist.ICompletionProposal#apply(org.eclipse.jface.text.IDocument)
+	 */
+	public void apply(IDocument document) {
+		// not implemented?
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#apply(org.eclipse.jface.text.ITextViewer,
+	 *      char, int, int)
+	 */
+	public void apply(ITextViewer viewer, char trigger, int stateMask, int offset) {
+		int startTagOffset = ((Integer) ((Object[]) fAdditionalFixInfo)[0]).intValue();
+		int startTagLength = ((Integer) ((Object[]) fAdditionalFixInfo)[1]).intValue();
+		int endTagOffset = ((Integer) ((Object[]) fAdditionalFixInfo)[2]).intValue();
+		int endTagLength = ((Integer) ((Object[]) fAdditionalFixInfo)[3]).intValue();
+
+		MultiTextEdit multiTextEdit = new MultiTextEdit();
+		if (endTagOffset != -1) {
+			multiTextEdit.addChild(new DeleteEdit(endTagOffset, endTagLength));
+			fSelection = new Point(endTagOffset, 0);
+		}
+		if (startTagOffset != -1) {
+			multiTextEdit.addChild(new DeleteEdit(startTagOffset, startTagLength));
+			fSelection = new Point(startTagOffset, 0);
+		}
+
+		try {
+			multiTextEdit.apply(viewer.getDocument());
+		}
+		catch (MalformedTreeException e) {
+			// log for now, unless find reasons not to.
+			Logger.log(Logger.INFO, e.getMessage());
+		}
+		catch (BadLocationException e) {
+			// log for now, unless find reasons not to.
+			Logger.log(Logger.INFO, e.getMessage());
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getAdditionalProposalInfo()
+	 */
+	public String getAdditionalProposalInfo() {
+		return null;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getContextInformation()
+	 */
+	public IContextInformation getContextInformation() {
+		return null;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getDisplayString()
+	 */
+	public String getDisplayString() {
+		if (fDisplayString == null) {
+			fDisplayString = XMLUIMessages.QuickFixProcessorXML_11;
+		}
+
+		return fDisplayString;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getImage()
+	 */
+	public Image getImage() {
+		return fImage;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getSelection(org.eclipse.jface.text.IDocument)
+	 */
+	public Point getSelection(IDocument document) {
+		return fSelection;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#selected(org.eclipse.jface.text.ITextViewer,
+	 *      boolean)
+	 */
+	public void selected(ITextViewer viewer, boolean smartToggle) {
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#unselected(org.eclipse.jface.text.ITextViewer)
+	 */
+	public void unselected(ITextViewer viewer) {
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#validate(org.eclipse.jface.text.IDocument,
+	 *      int, org.eclipse.jface.text.DocumentEvent)
+	 */
+	public boolean validate(IDocument document, int offset, DocumentEvent event) {
+		return false;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/RenameInFileQuickAssistProposal.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/RenameInFileQuickAssistProposal.java
new file mode 100644
index 0000000..d299f25
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/RenameInFileQuickAssistProposal.java
@@ -0,0 +1,187 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.correction;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.DocumentEvent;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.ITextViewerExtension;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.jface.text.contentassist.ICompletionProposalExtension2;
+import org.eclipse.jface.text.contentassist.IContextInformation;
+import org.eclipse.jface.text.link.LinkedModeModel;
+import org.eclipse.jface.text.link.LinkedModeUI;
+import org.eclipse.jface.text.link.LinkedPosition;
+import org.eclipse.jface.text.link.LinkedPositionGroup;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.ui.texteditor.link.EditorLinkedModeUI;
+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.ui.internal.contentassist.ContentAssistUtils;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+import org.eclipse.wst.xml.ui.internal.Logger;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImageHelper;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImages;
+
+public class RenameInFileQuickAssistProposal implements ICompletionProposal, ICompletionProposalExtension2 {
+	protected IRegion fSelectedRegion; // initialized by apply()
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.contentassist.ICompletionProposal#apply(org.eclipse.jface.text.IDocument)
+	 */
+	public void apply(IDocument document) {
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#apply(org.eclipse.jface.text.ITextViewer,
+	 *      char, int, int)
+	 */
+	public void apply(ITextViewer viewer, char trigger, int stateMask, int offset) {
+		IDocument document = viewer.getDocument();
+		LinkedPositionGroup group = new LinkedPositionGroup();
+		try {
+				IDOMNode node = (IDOMNode) ContentAssistUtils.getNodeAt(viewer, offset);
+				IStructuredDocumentRegion startStructuredDocumentRegion = node.getStartStructuredDocumentRegion();
+				ITextRegion region = (startStructuredDocumentRegion == null) ? null : startStructuredDocumentRegion.getRegionAtCharacterOffset(offset);
+				if (region != null) {
+					group.addPosition(new LinkedPosition(document, startStructuredDocumentRegion.getStartOffset() + region.getStart(), region.getTextLength(), 0));
+
+					if ((region.getType() == DOMRegionContext.XML_TAG_NAME) && (node.getEndStructuredDocumentRegion() != null)) {
+						region = node.getEndStructuredDocumentRegion().getRegions().get(1);
+						if (region != null) {
+							group.addPosition(new LinkedPosition(document, node.getEndStructuredDocumentRegion().getStartOffset() + region.getStart(), region.getTextLength(), 1));
+						}
+					}
+				}
+				else {
+					IStructuredDocumentRegion endStructuredDocumentRegion = node.getEndStructuredDocumentRegion();
+					region = (endStructuredDocumentRegion == null) ? null : endStructuredDocumentRegion.getRegionAtCharacterOffset(offset);
+					if (region != null) {
+						if ((region.getType() == DOMRegionContext.XML_TAG_NAME) && (node.getStartStructuredDocumentRegion() != null)) {
+							ITextRegion startTagNameRegion = node.getStartStructuredDocumentRegion().getRegions().get(1);
+							if (region != null) {
+								group.addPosition(new LinkedPosition(document, node.getStartStructuredDocumentRegion().getStartOffset() + startTagNameRegion.getStart(), startTagNameRegion.getTextLength(), 0));
+								group.addPosition(new LinkedPosition(document, endStructuredDocumentRegion.getStartOffset() + region.getStart(), region.getTextLength(), 1));
+							}
+						}
+						else {
+							group.addPosition(new LinkedPosition(document, endStructuredDocumentRegion.getStartOffset() + region.getStart(), region.getTextLength(), 0));
+						}
+					}
+				}
+
+				// TODO CompletionProposalPopup#insertProposal() calls
+				// IRewriteTarget.beginCompoundChange()
+				// which disables redraw in ITextViewer. Workaround for now.
+				if(viewer instanceof ITextViewerExtension)
+					((ITextViewerExtension) viewer).setRedraw(true);
+
+			LinkedModeModel linkedModeModel = new LinkedModeModel();
+			linkedModeModel.addGroup(group);
+			linkedModeModel.forceInstall();
+
+			LinkedModeUI ui = new EditorLinkedModeUI(linkedModeModel, viewer);
+			ui.setExitPosition(viewer, offset, 0, LinkedPositionGroup.NO_STOP);
+			ui.enter();
+
+			fSelectedRegion = ui.getSelectedRegion();
+		}
+		catch (BadLocationException e) {
+			// log for now, unless find reason not to
+			Logger.log(Logger.INFO, e.getMessage());
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getAdditionalProposalInfo()
+	 */
+	public String getAdditionalProposalInfo() {
+		return XMLUIMessages.RenameInFileQuickAssistProposal_0;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getContextInformation()
+	 */
+	public IContextInformation getContextInformation() {
+		return null;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getDisplayString()
+	 */
+	public String getDisplayString() {
+		return XMLUIMessages.RenameInFileQuickAssistProposal_1;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getImage()
+	 */
+	public Image getImage() {
+		// return JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_LOCAL);
+		return XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_LOCAL_VARIABLE);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getSelection(org.eclipse.jface.text.IDocument)
+	 */
+	public Point getSelection(IDocument document) {
+		return new Point(fSelectedRegion.getOffset(), fSelectedRegion.getLength());
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#selected(org.eclipse.jface.text.ITextViewer,
+	 *      boolean)
+	 */
+	public void selected(ITextViewer viewer, boolean smartToggle) {
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#unselected(org.eclipse.jface.text.ITextViewer)
+	 */
+	public void unselected(ITextViewer viewer) {
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#validate(org.eclipse.jface.text.IDocument,
+	 *      int, org.eclipse.jface.text.DocumentEvent)
+	 */
+	public boolean validate(IDocument document, int offset, DocumentEvent event) {
+		return false;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/SurroundWithNewElementQuickAssistProposal.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/SurroundWithNewElementQuickAssistProposal.java
new file mode 100644
index 0000000..7baffc8
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/SurroundWithNewElementQuickAssistProposal.java
@@ -0,0 +1,111 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.correction;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.text.edits.InsertEdit;
+import org.eclipse.text.edits.MalformedTreeException;
+import org.eclipse.text.edits.MultiTextEdit;
+import org.eclipse.wst.sse.core.internal.format.IStructuredFormatProcessor;
+import org.eclipse.wst.sse.ui.internal.contentassist.ContentAssistUtils;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.eclipse.wst.xml.core.internal.provisional.format.FormatProcessorXML;
+import org.eclipse.wst.xml.ui.internal.Logger;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImageHelper;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImages;
+import org.w3c.dom.Node;
+
+public class SurroundWithNewElementQuickAssistProposal extends RenameInFileQuickAssistProposal {
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#apply(org.eclipse.jface.text.ITextViewer,
+	 *      char, int, int)
+	 */
+	public void apply(ITextViewer viewer, char trigger, int stateMask, int offset) {
+		try {
+			int startTagOffset = offset;
+			int endTagOffset = offset + viewer.getSelectedRange().y;
+
+			// surround the node if no selection
+			if (startTagOffset == endTagOffset) {
+				IDOMNode cursorNode = (IDOMNode) ContentAssistUtils.getNodeAt(viewer, offset);
+				// use parent node if text node is empty
+				if ((cursorNode.getNodeType() == Node.TEXT_NODE) && (cursorNode.getNodeValue().trim().length() == 0)) {
+					cursorNode = (IDOMNode) cursorNode.getParentNode();
+				}
+
+				startTagOffset = cursorNode.getStartOffset();
+				endTagOffset = cursorNode.getEndOffset();
+			}
+
+			// insert new element
+			MultiTextEdit multiTextEdit = new MultiTextEdit();
+			// element tag name cannot be DBCS, do not translate "<element>"
+			// and "</element>"
+			multiTextEdit.addChild(new InsertEdit(startTagOffset, "<element>")); //$NON-NLS-1$
+			multiTextEdit.addChild(new InsertEdit(endTagOffset, "</element>")); //$NON-NLS-1$
+			multiTextEdit.apply(viewer.getDocument());
+
+			// get new element node
+			IDOMNode newElementNode = (IDOMNode) ContentAssistUtils.getNodeAt(viewer, startTagOffset);
+
+			// format new element
+			IStructuredFormatProcessor formatProcessor = new FormatProcessorXML();
+			formatProcessor.formatNode(newElementNode);
+
+			// rename new element
+			super.apply(viewer, trigger, stateMask, newElementNode.getStartOffset() + 1);
+		}
+		catch (MalformedTreeException e) {
+			// log for now, unless find reason not to
+			Logger.log(Logger.INFO, e.getMessage());
+		}
+		catch (BadLocationException e) {
+			// log for now, unless find reason not to
+			Logger.log(Logger.INFO, e.getMessage());
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getAdditionalProposalInfo()
+	 */
+	public String getAdditionalProposalInfo() {
+		return XMLUIMessages.SurroundWithNewElementQuickAssistProposal_0;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getDisplayString()
+	 */
+	public String getDisplayString() {
+		return XMLUIMessages.SurroundWithNewElementQuickAssistProposal_1;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getImage()
+	 */
+	public Image getImage() {
+		// return JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_LOCAL);
+		return XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_ADD_CORRECTION);
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/XMLQuickAssistProcessor.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/XMLQuickAssistProcessor.java
new file mode 100644
index 0000000..4649e94
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/XMLQuickAssistProcessor.java
@@ -0,0 +1,212 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.correction;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.jface.text.quickassist.IQuickAssistInvocationContext;
+import org.eclipse.jface.text.quickassist.IQuickAssistProcessor;
+import org.eclipse.jface.text.source.Annotation;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.IModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.contentmodel.basic.CMNamedNodeMapImpl;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.modelquery.ModelQueryUtil;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+public class XMLQuickAssistProcessor implements IQuickAssistProcessor {
+
+	public boolean canAssist(IQuickAssistInvocationContext invocationContext) {
+		return true;
+	}
+
+	public boolean canFix(Annotation annotation) {
+		return false;
+	}
+
+	public ICompletionProposal[] computeQuickAssistProposals(IQuickAssistInvocationContext invocationContext) {
+		List proposals = new ArrayList();
+
+		getLocalRenameQuickAssistProposal(proposals, invocationContext.getSourceViewer(), invocationContext.getOffset());
+		getSurroundWithNewElementQuickAssistProposal(proposals, invocationContext.getSourceViewer(), invocationContext.getOffset());
+		getInsertRequiredAttrs(proposals, invocationContext.getSourceViewer(), invocationContext.getOffset());
+
+		return (ICompletionProposal[]) proposals.toArray(new ICompletionProposal[proposals.size()]);
+	}
+
+	public String getErrorMessage() {
+		return null;
+	}
+
+	private void getInsertRequiredAttrs(List proposals, ISourceViewer viewer, int offset) {
+		IDOMNode node = (IDOMNode) getNodeAt(viewer, offset);
+		if ((node != null) && (node.getNodeType() == Node.ELEMENT_NODE)) {
+			IStructuredDocumentRegion startStructuredDocumentRegion = node.getStartStructuredDocumentRegion();
+			if ((startStructuredDocumentRegion != null) && startStructuredDocumentRegion.containsOffset(offset)) {
+				IDOMNode cursorNode = (IDOMNode) getNodeAt(viewer, offset);
+				List requiredAttrs = getRequiredAttrs(cursorNode);
+				if (requiredAttrs.size() > 0) {
+					NamedNodeMap currentAttrs = node.getAttributes();
+					List insertAttrs = new ArrayList();
+					if (currentAttrs.getLength() == 0) {
+						insertAttrs.addAll(requiredAttrs);
+					}
+					else {
+						for (int i = 0; i < requiredAttrs.size(); i++) {
+							String requiredAttrName = ((CMAttributeDeclaration) requiredAttrs.get(i)).getAttrName();
+							boolean found = false;
+							for (int j = 0; j < currentAttrs.getLength(); j++) {
+								String currentAttrName = currentAttrs.item(j).getNodeName();
+								if (requiredAttrName.compareToIgnoreCase(currentAttrName) == 0) {
+									found = true;
+									break;
+								}
+							}
+							if (!found) {
+								insertAttrs.add(requiredAttrs.get(i));
+							}
+						}
+					}
+					if (insertAttrs.size() > 0) {
+						proposals.add(new InsertRequiredAttrsQuickAssistProposal(insertAttrs));
+					}
+				}
+			}
+		}
+	}
+
+	private void getLocalRenameQuickAssistProposal(List proposals, ISourceViewer viewer, int offset) {
+		IDOMNode node = (IDOMNode) getNodeAt(viewer, offset);
+		IStructuredDocumentRegion startStructuredDocumentRegion = node == null ? null : node.getStartStructuredDocumentRegion();
+		IStructuredDocumentRegion endStructuredDocumentRegion = node == null ? null : node.getEndStructuredDocumentRegion();
+
+		ITextRegion region = null;
+		int regionTextEndOffset = 0;
+		if ((startStructuredDocumentRegion != null) && startStructuredDocumentRegion.containsOffset(offset)) {
+			region = startStructuredDocumentRegion.getRegionAtCharacterOffset(offset);
+			regionTextEndOffset = startStructuredDocumentRegion.getTextEndOffset(region);
+		}
+		else if ((endStructuredDocumentRegion != null) && endStructuredDocumentRegion.containsOffset(offset)) {
+			region = endStructuredDocumentRegion.getRegionAtCharacterOffset(offset);
+			regionTextEndOffset = endStructuredDocumentRegion.getTextEndOffset(region);
+		}
+
+		if ((region != null) && ((region.getType() == DOMRegionContext.XML_TAG_NAME) || (region.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME)) && (offset <= regionTextEndOffset)) {
+			proposals.add(new RenameInFileQuickAssistProposal());
+		}
+	}
+
+	private ModelQuery getModelQuery(Node node) {
+		if (node.getNodeType() == Node.DOCUMENT_NODE) {
+			return ModelQueryUtil.getModelQuery((Document) node);
+		}
+		else {
+			return ModelQueryUtil.getModelQuery(node.getOwnerDocument());
+		}
+	}
+
+	private List getRequiredAttrs(Node node) {
+		List result = new ArrayList();
+
+		ModelQuery modelQuery = getModelQuery(node);
+		if (modelQuery != null) {
+			CMElementDeclaration elementDecl = modelQuery.getCMElementDeclaration((Element) node);
+			if (elementDecl != null) {
+				CMNamedNodeMap attrMap = elementDecl.getAttributes();
+
+				CMNamedNodeMapImpl allAttributes = new CMNamedNodeMapImpl(attrMap);
+				List nodes = ModelQueryUtil.getModelQuery(node.getOwnerDocument()).getAvailableContent((Element) node, elementDecl, ModelQuery.INCLUDE_ATTRIBUTES);
+				for (int k = 0; k < nodes.size(); k++) {
+					CMNode cmnode = (CMNode) nodes.get(k);
+					if (cmnode.getNodeType() == CMNode.ATTRIBUTE_DECLARATION) {
+						allAttributes.put(cmnode);
+					}
+				}
+				attrMap = allAttributes;
+				
+				Iterator it = attrMap.iterator();
+				CMAttributeDeclaration attr = null;
+				while (it.hasNext()) {
+					attr = (CMAttributeDeclaration) it.next();
+					if (attr.getUsage() == CMAttributeDeclaration.REQUIRED) {
+						result.add(attr);
+					}
+				}
+			}
+		}
+
+		return result;
+	}
+
+	private void getSurroundWithNewElementQuickAssistProposal(List proposals, ISourceViewer viewer, int offset) {
+		IDOMNode node = (IDOMNode) getNodeAt(viewer, offset);
+		if (node != null) {
+			proposals.add(new SurroundWithNewElementQuickAssistProposal());
+		}
+	}
+
+	/**
+	 * Returns the closest IndexedRegion for the offset and viewer allowing
+	 * for differences between viewer offsets and model positions. note: this
+	 * method returns an IndexedRegion for read only
+	 * 
+	 * @param viewer
+	 *            the viewer whose document is used to compute the proposals
+	 * @param documentOffset
+	 *            an offset within the document for which completions should
+	 *            be computed
+	 * @return an IndexedRegion
+	 */
+	private IndexedRegion getNodeAt(ITextViewer viewer, int documentOffset) {
+		// copied from ContentAssistUtils.getNodeAt()
+		if (viewer == null)
+			return null;
+
+		IndexedRegion node = null;
+		IModelManager mm = StructuredModelManager.getModelManager();
+		IStructuredModel model = null;
+		if (mm != null)
+			model = mm.getExistingModelForRead(viewer.getDocument());
+		try {
+			if (model != null) {
+				int lastOffset = documentOffset;
+				node = model.getIndexedRegion(documentOffset);
+				while (node == null && lastOffset >= 0) {
+					lastOffset--;
+					node = model.getIndexedRegion(lastOffset);
+				}
+			}
+		}
+		finally {
+			if (model != null)
+				model.releaseFromRead();
+		}
+		return node;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/dialogs/EditAttributeDialog.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/dialogs/EditAttributeDialog.java
new file mode 100644
index 0000000..e95af80
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/dialogs/EditAttributeDialog.java
@@ -0,0 +1,172 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.dialogs;
+
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+import org.eclipse.wst.xml.ui.internal.util.XMLCommonUIContextIds;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+
+public class EditAttributeDialog extends Dialog implements ModifyListener {
+	protected Attr attribute;
+	protected String attributeName;
+	protected Text attributeNameField;
+	protected String attributeValue;
+	protected Text attributeValueField;
+	protected Label errorMessageLabel;
+	protected Button okButton;
+	protected Element ownerElement;
+
+	public EditAttributeDialog(Shell parentShell, Element ownerElement, Attr attribute) {
+		super(parentShell);
+		setShellStyle(getShellStyle() | SWT.RESIZE);
+		this.ownerElement = ownerElement;
+		this.attribute = attribute;
+	}
+
+	protected void buttonPressed(int buttonId) {
+		if (buttonId == IDialogConstants.OK_ID) {
+			attributeName = getModelValue(attributeNameField.getText());
+			attributeValue = attributeValueField.getText();
+		}
+		super.buttonPressed(buttonId);
+	}
+
+	protected void createButtonsForButtonBar(Composite parent) {
+		okButton = createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
+		createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false);
+	}
+
+	protected Control createContents(Composite parent) {
+		Control control = super.createContents(parent);
+		attributeNameField.forceFocus();
+		attributeNameField.selectAll();
+		updateErrorMessage();
+		return control;
+	}
+
+
+	protected Control createDialogArea(Composite parent) {
+		Composite dialogArea = (Composite) super.createDialogArea(parent);
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(dialogArea, XMLCommonUIContextIds.XCUI_ATTRIBUTE_DIALOG);
+
+		Composite composite = new Composite(dialogArea, SWT.NONE);
+		GridLayout layout = new GridLayout();
+		layout.numColumns = 2;
+		layout.marginWidth = 0;
+		composite.setLayout(layout);
+
+		//
+		// Style convenience constants
+		composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+		Label attributeNameLabel = new Label(composite, SWT.NONE);
+		attributeNameLabel.setText(XMLUIMessages._UI_LABEL_NAME_COLON);
+
+		attributeNameField = new Text(composite, SWT.SINGLE | SWT.BORDER);
+		GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+		gd.widthHint = 300;
+		attributeNameField.setLayoutData(gd);
+		attributeNameField.setText(getDisplayValue(attribute != null ? attribute.getName() : "")); //$NON-NLS-1$
+		attributeNameField.addModifyListener(this);
+
+		Label attributeValueLabel = new Label(composite, SWT.NONE);
+		attributeValueLabel.setText(XMLUIMessages._UI_LABEL_VALUE_COLON);
+
+		String value = attribute != null ? attribute.getValue() : ""; //$NON-NLS-1$
+		int style = SWT.SINGLE | SWT.BORDER;
+		if (value.indexOf("\n") != -1) { //$NON-NLS-1$
+			style = SWT.MULTI | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL;
+		}
+
+		attributeValueField = new Text(composite, style);
+		gd = new GridData(GridData.FILL_HORIZONTAL);
+		gd.widthHint = 300;
+		attributeValueField.setLayoutData(gd);
+		attributeValueField.setText(getDisplayValue(attribute != null ? attribute.getValue() : "")); //$NON-NLS-1$
+
+		// error message
+		errorMessageLabel = new Label(composite, SWT.WRAP);
+		errorMessageLabel.setText(XMLUIMessages.error_message_goes_here);
+		gd = new GridData(GridData.FILL_HORIZONTAL);
+		gd.widthHint = 200;
+		gd.heightHint = Math.max(30, errorMessageLabel.computeSize(0, 0, false).y * 2);
+		gd.horizontalSpan = 2;
+		errorMessageLabel.setLayoutData(gd);
+		Color color = new Color(errorMessageLabel.getDisplay(), 200, 0, 0);
+		errorMessageLabel.setForeground(color);
+
+		return dialogArea;
+	}
+
+	public String getAttributeName() {
+		return attributeName;
+	}
+
+	public String getAttributeValue() {
+		return attributeValue;
+	}
+
+	protected String getDisplayValue(String string) {
+		return string != null ? string : ""; //$NON-NLS-1$
+	}
+
+	protected String getModelValue(String string) {
+		String result = null;
+		if ((string != null) && (string.trim().length() > 0)) {
+			result = string;
+		}
+		return result;
+	}
+
+	public void modifyText(ModifyEvent e) {
+		updateErrorMessage();
+	}
+
+	protected void updateErrorMessage() {
+		String errorMessage = null;
+		String name = attributeNameField.getText().trim();
+		if (name.length() > 0) {
+			Attr matchingAttribute = ownerElement.getAttributeNode(name);
+			if ((matchingAttribute != null) && (matchingAttribute != attribute)) {
+				errorMessage = XMLUIMessages._ERROR_XML_ATTRIBUTE_ALREADY_EXISTS;
+			}
+			else {
+				// TODO get checkName from Model
+				// errorMessage = ValidateHelper.checkXMLName(name);
+			}
+		}
+		else {
+			errorMessage = ""; //$NON-NLS-1$
+		}
+
+		errorMessageLabel.setText(errorMessage != null ? errorMessage : ""); //$NON-NLS-1$
+		errorMessageLabel.getParent().layout();
+		okButton.setEnabled(errorMessage == null);
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/dialogs/EditDoctypeDialog.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/dialogs/EditDoctypeDialog.java
new file mode 100644
index 0000000..6e071ba
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/dialogs/EditDoctypeDialog.java
@@ -0,0 +1,235 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *	   David Schneider, david.schneider@unisys.com - [142500] WTP properties pages fonts don't follow Eclipse preferences
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.dialogs;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+import org.eclipse.wst.xml.ui.internal.util.XMLCommonUIContextIds;
+import org.w3c.dom.DocumentType;
+
+public class EditDoctypeDialog extends Dialog {
+	protected boolean computeSystemId;
+	protected String[] doctypeData;
+	protected boolean errorChecking;
+	protected Label errorMessageLabel;
+	protected Button okButton;
+	protected Button publicIdBrowseButton;
+	protected Text publicIdField;
+	protected IPath resourceLocation;
+	protected Text rootElementNameField;
+	protected Button systemIdBrowseButton;
+	protected Text systemIdField;
+
+	public EditDoctypeDialog(Shell parentShell, DocumentType doctype) {
+		this(parentShell, doctype.getName(), doctype.getPublicId(), doctype.getSystemId());
+	}
+
+	public EditDoctypeDialog(Shell parentShell, String name, String publicId, String systemId) {
+		super(parentShell);
+		setShellStyle(getShellStyle() | SWT.RESIZE);
+		doctypeData = new String[3];
+		doctypeData[0] = name;
+		doctypeData[1] = publicId;
+		doctypeData[2] = systemId;
+	}
+
+	protected void buttonPressed(int buttonId) {
+		doctypeData[0] = getModelValue(rootElementNameField.getText());
+		doctypeData[1] = getModelValue(publicIdField.getText());
+		doctypeData[2] = getModelValue(systemIdField.getText());
+		super.buttonPressed(buttonId);
+	}
+
+	protected void createButtonsForButtonBar(Composite parent) {
+		okButton = createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
+		createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false);
+	}
+
+
+	protected Control createContents(Composite parent) {
+		Control control = super.createContents(parent);
+		updateErrorMessage();
+		return control;
+	}
+
+	protected Control createDialogArea(Composite parent) {
+		Composite dialogControl = (Composite) super.createDialogArea(parent);
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(dialogControl, XMLCommonUIContextIds.XCUI_DOCTYPE_DIALOG);
+
+		Composite composite = new Composite(dialogControl, SWT.NONE);
+		GridLayout layout = new GridLayout();
+		layout.numColumns = 3;
+		layout.marginWidth = 0;
+		composite.setLayout(layout);
+		composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+
+		ModifyListener modifyListener = new ModifyListener() {
+			public void modifyText(ModifyEvent e) {
+				if (e.widget == systemIdField) {
+					computeSystemId = false;
+				}
+				updateErrorMessage();
+			}
+		};
+
+		// row 1
+		//
+		Label rootElementNameLabel = new Label(composite, SWT.NONE);
+		rootElementNameLabel.setText(XMLUIMessages._UI_LABEL_ROOT_ELEMENT_NAME_COLON);
+
+		rootElementNameField = new Text(composite, SWT.SINGLE | SWT.BORDER);
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(rootElementNameField, XMLCommonUIContextIds.XCUI_DOCTYPE_ROOT);
+		GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+		gd.widthHint = 200;
+		rootElementNameField.setLayoutData(gd);
+		rootElementNameField.setText(getDisplayValue(doctypeData[0]));
+		rootElementNameField.addModifyListener(modifyListener);
+
+		Label placeHolder = new Label(composite, SWT.NONE);
+		placeHolder.setLayoutData(new GridData());
+
+		// row 2
+		//
+		Label publicIdLabel = new Label(composite, SWT.NONE);
+		publicIdLabel.setText(XMLUIMessages._UI_LABEL_PUBLIC_ID_COLON);
+
+		publicIdField = new Text(composite, SWT.SINGLE | SWT.BORDER);
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(publicIdField, XMLCommonUIContextIds.XCUI_DOCTYPE_PUBLIC);
+		publicIdField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+		publicIdField.setText(getDisplayValue(doctypeData[1]));
+
+		SelectionListener selectionListener = new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				EditEntityHelper helper = new EditEntityHelper();
+				if (e.widget == publicIdBrowseButton) {
+					helper.performBrowseForPublicId(getShell(), publicIdField, computeSystemId ? systemIdField : null);
+				}
+				else if (e.widget == systemIdBrowseButton) {
+					helper.performBrowseForSystemId(getShell(), systemIdField, resourceLocation);
+				}
+			}
+		};
+
+		publicIdBrowseButton = new Button(composite, SWT.NONE);
+		publicIdBrowseButton.setText(XMLUIMessages._UI_LABEL_BROWSE);
+		publicIdBrowseButton.addSelectionListener(selectionListener);
+
+		// row 3
+		Label systemIdLabel = new Label(composite, SWT.NONE);
+		systemIdLabel.setText(XMLUIMessages._UI_LABEL_SYSTEM_ID_COLON);
+
+		systemIdField = new Text(composite, SWT.SINGLE | SWT.BORDER);
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(systemIdField, XMLCommonUIContextIds.XCUI_DOCTYPE_SYSTEM);
+		systemIdField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+		systemIdField.setText(getDisplayValue(doctypeData[2]));
+		systemIdField.addModifyListener(modifyListener);
+
+
+		systemIdBrowseButton = new Button(composite, SWT.NONE);
+		systemIdBrowseButton.setText(XMLUIMessages._UI_LABEL_BROWSE);
+		systemIdBrowseButton.addSelectionListener(selectionListener);
+
+		// error message
+		errorMessageLabel = new Label(dialogControl, SWT.NONE);
+		errorMessageLabel.setText(""); //$NON-NLS-1$
+		errorMessageLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+		Color color = new Color(errorMessageLabel.getDisplay(), 200, 0, 0);
+		errorMessageLabel.setForeground(color);
+
+		Dialog.applyDialogFont(parent);
+		return dialogControl;
+	}
+
+
+	protected Label createMessageArea(Composite composite) {
+		Label label = new Label(composite, SWT.NONE);
+		// label.setText(message);
+		return label;
+	}
+
+
+	protected String getDisplayValue(String string) {
+		return string != null ? string : ""; //$NON-NLS-1$
+	}
+
+	public boolean getErrorChecking() {
+		return errorChecking;
+	}
+
+
+	protected String getModelValue(String string) {
+		String result = null;
+		if ((string != null) && (string.trim().length() > 0)) {
+			result = string;
+		}
+		return result;
+	}
+
+	public String getName() {
+		return doctypeData[0];
+	}
+
+	public String getPublicId() {
+		return doctypeData[1];
+	}
+
+	public String getSystemId() {
+		return doctypeData[2];
+	}
+
+	public void setComputeSystemId(boolean computeSystemId) {
+		this.computeSystemId = computeSystemId;
+	}
+
+	public void setErrorChecking(boolean errorChecking) {
+		this.errorChecking = errorChecking;
+	}
+
+	public void setResourceLocation(IPath path) {
+		resourceLocation = path;
+	}
+
+	public void updateErrorMessage() {
+		if (errorChecking) {
+			String errorMessage = null;
+			if (getModelValue(systemIdField.getText()) == null) {
+				errorMessage = XMLUIMessages._UI_WARNING_SYSTEM_ID_MUST_BE_SPECIFIED;
+			}
+			else if (getModelValue(rootElementNameField.getText()) == null) {
+				errorMessage = XMLUIMessages._UI_WARNING_ROOT_ELEMENT_MUST_BE_SPECIFIED;
+			}
+
+			errorMessageLabel.setText(errorMessage != null ? errorMessage : ""); //$NON-NLS-1$
+			okButton.setEnabled(errorMessage == null);
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/dialogs/EditElementDialog.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/dialogs/EditElementDialog.java
new file mode 100644
index 0000000..adad381
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/dialogs/EditElementDialog.java
@@ -0,0 +1,141 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.dialogs;
+
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.wst.xml.core.internal.provisional.NameValidator;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+import org.eclipse.wst.xml.ui.internal.util.XMLCommonUIContextIds;
+import org.w3c.dom.Element;
+
+public class EditElementDialog extends Dialog implements ModifyListener {
+	protected Element element;
+	protected String elementName;
+	protected Text elementNameField;
+	protected Label errorMessageLabel;
+	protected Button okButton;
+
+	public EditElementDialog(Shell parentShell, Element element) {
+		super(parentShell);
+		setShellStyle(getShellStyle() | SWT.RESIZE);
+		this.element = element;
+	}
+
+	protected void buttonPressed(int buttonId) {
+		if (buttonId == IDialogConstants.OK_ID) {
+			elementName = getModelValue(elementNameField.getText());
+		}
+		super.buttonPressed(buttonId);
+	}
+
+
+	protected void createButtonsForButtonBar(Composite parent) {
+		okButton = createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
+		createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false);
+	}
+
+	protected Control createContents(Composite parent) {
+		Control control = super.createContents(parent);
+		elementNameField.forceFocus();
+		elementNameField.selectAll();
+		updateErrorMessage();
+		return control;
+	}
+
+
+	protected Control createDialogArea(Composite parent) {
+		Composite dialogArea = (Composite) super.createDialogArea(parent);
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(dialogArea, XMLCommonUIContextIds.XCUI_ELEMENT_DIALOG);
+
+		Composite composite = new Composite(dialogArea, SWT.NONE);
+		GridLayout layout = new GridLayout();
+		layout.numColumns = 2;
+		layout.marginWidth = 0;
+		composite.setLayout(layout);
+		composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+		Label elementNameLabel = new Label(composite, SWT.NONE);
+		elementNameLabel.setText(XMLUIMessages._UI_LABEL_ELEMENT_NAME);
+
+		elementNameField = new Text(composite, SWT.SINGLE | SWT.BORDER);
+		GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+		gd.widthHint = 200;
+		elementNameField.setLayoutData(gd);
+		elementNameField.setText(getDisplayValue(element != null ? element.getNodeName() : "")); //$NON-NLS-1$
+		elementNameField.addModifyListener(this);
+
+		// error message
+		errorMessageLabel = new Label(composite, SWT.NONE);
+		errorMessageLabel.setText(XMLUIMessages.error_message_goes_here);
+		gd = new GridData(GridData.FILL_HORIZONTAL);
+		gd.horizontalSpan = 2;
+		errorMessageLabel.setLayoutData(gd);
+		Color color = new Color(errorMessageLabel.getDisplay(), 200, 0, 0);
+		errorMessageLabel.setForeground(color);
+
+		return dialogArea;
+	}
+
+	protected String getDisplayValue(String string) {
+		return string != null ? string : ""; //$NON-NLS-1$
+	}
+
+	public String getElementName() {
+		return elementName;
+	}
+
+	protected String getModelValue(String string) {
+		String result = null;
+		if ((string != null) && (string.trim().length() > 0)) {
+			result = string;
+		}
+		return result;
+	}
+
+	public void modifyText(ModifyEvent e) {
+		updateErrorMessage();
+	}
+
+	protected void updateErrorMessage() {
+		String errorMessage = null;
+		String name = elementNameField.getText();
+		// String name = elementNameField.getText().trim();
+		if (name.length() > 0) {
+			// TODO use checkName from model level
+			// errorMessage = ValidateHelper.checkXMLName(name);
+			if (!NameValidator.isValid(name)) {
+				errorMessage = XMLUIMessages._UI_INVALID_NAME;
+			}
+		}
+		else {
+			errorMessage = ""; //$NON-NLS-1$
+		}
+
+		errorMessageLabel.setText(errorMessage != null ? errorMessage : ""); //$NON-NLS-1$
+		okButton.setEnabled(errorMessage == null);
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/dialogs/EditEntityHelper.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/dialogs/EditEntityHelper.java
new file mode 100644
index 0000000..25eb64d
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/dialogs/EditEntityHelper.java
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.dialogs;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.wst.common.uriresolver.internal.util.URIHelper;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalogEntry;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+
+public class EditEntityHelper {
+
+	public void performBrowseForPublicId(Shell parentShell, Text publicIdField) {
+		performBrowseForPublicId(parentShell, publicIdField, null);
+	}
+
+	public void performBrowseForPublicId(Shell parentShell, Text publicIdField, Text systemIdField) {
+		String[] extensions = {"dtd", "txt"}; //$NON-NLS-1$ //$NON-NLS-2$
+		SelectXMLCatalogIdDialog dialog = new SelectXMLCatalogIdDialog(parentShell, extensions);
+		dialog.create();
+		dialog.getShell().setText(XMLUIMessages._UI_LABEL_SELECT_XML_CATALOG_ENTRY);
+		dialog.setBlockOnOpen(true);
+		dialog.open();
+		if (dialog.getReturnCode() == Window.OK) {
+			String id = dialog.getId();
+			if (id != null) {
+				publicIdField.setText(id);
+				if ((systemIdField != null) && (dialog.getSystemId() != null)) {
+					systemIdField.setText(dialog.getSystemId());
+				}
+			}
+		}
+	}
+
+	public void performBrowseForSystemId(Shell parentShell, Text systemIdField, IPath resourceLocation) {
+		String[] extensions = {"dtd"}; //$NON-NLS-1$
+		SelectFileOrXMLCatalogIdDialog dialog = new SelectFileOrXMLCatalogIdDialog(parentShell, extensions, ICatalogEntry.ENTRY_TYPE_SYSTEM);
+		dialog.create();
+		dialog.getShell().setText(XMLUIMessages._UI_LABEL_SPECIFY_SYSTEM_ID);
+		dialog.setBlockOnOpen(true);
+		dialog.open();
+		if (dialog.getReturnCode() == Window.OK) {
+			String id = dialog.getId();
+			IFile file = dialog.getFile();
+			if (id != null) {
+				systemIdField.setText(id);
+			}
+			else if (file != null) {
+				String uri = null;
+				if (resourceLocation != null) {
+					uri = URIHelper.getRelativeURI(file.getLocation(), resourceLocation);
+				}
+				else {
+					uri = file.getLocation().toOSString();
+				}
+				systemIdField.setText(uri);
+			}
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/dialogs/EditNamespaceInfoDialog.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/dialogs/EditNamespaceInfoDialog.java
new file mode 100644
index 0000000..844ac60
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/dialogs/EditNamespaceInfoDialog.java
@@ -0,0 +1,274 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2008 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.dialogs;
+
+import java.util.List;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.wst.common.uriresolver.internal.provisional.URIResolver;
+import org.eclipse.wst.common.uriresolver.internal.provisional.URIResolverPlugin;
+import org.eclipse.wst.common.uriresolver.internal.util.URIHelper;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.contentmodel.ContentModelManager;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.NamespaceInfo;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+import org.eclipse.wst.xml.ui.internal.util.XMLCommonUIContextIds;
+
+public class EditNamespaceInfoDialog extends Dialog {
+
+	public static EditNamespaceInfoDialog invokeDialog(Shell shell, String title, NamespaceInfo info, IPath resourceLocation) {
+		EditNamespaceInfoDialog dialog = new EditNamespaceInfoDialog(shell, info);
+		dialog.create();
+		dialog.getShell().setText(title);
+		dialog.setBlockOnOpen(true);
+		dialog.setResourceLocation(resourceLocation);
+		dialog.open();
+		return dialog;
+	}
+
+	protected Button browseButton;
+	protected String errorMessage;
+
+	protected Label errorMessageLabel;
+	protected NamespaceInfo fInfo;
+	protected Text locationHintField;
+
+	protected Button okButton;
+	protected Text prefixField;
+	protected IPath resourceLocation;
+	protected Text uriField;
+
+	public EditNamespaceInfoDialog(Shell parentShell, NamespaceInfo info) {
+		super(parentShell);
+		setShellStyle(getShellStyle() | SWT.RESIZE);
+		this.fInfo = info;
+	}
+
+	protected void buttonPressed(int buttonId) {
+		if (buttonId == IDialogConstants.OK_ID) {
+			fInfo.uri = uriField.getText();
+			fInfo.prefix = prefixField.getText();
+			fInfo.locationHint = locationHintField.getText();
+		}
+		super.buttonPressed(buttonId);
+	}
+
+	protected void computeErrorMessage() {
+		errorMessage = null;
+	}
+
+	protected void createButtonsForButtonBar(Composite parent) {
+		okButton = createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
+		okButton.setEnabled(false);
+		createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false);
+		updateWidgets();
+	}
+
+	protected Control createDialogArea(Composite parent) {
+		Composite dialogsubArea = (Composite) super.createDialogArea(parent);
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(dialogsubArea, XMLCommonUIContextIds.XCUI_NAMESPACE_DIALOG);
+
+		Composite composite = new Composite(dialogsubArea, SWT.NONE);
+		GridLayout layout = new GridLayout();
+		layout.numColumns = 3;
+		layout.marginWidth = 0;
+		composite.setLayout(layout);
+
+		GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+		gd.widthHint = 350;
+		composite.setLayoutData(gd);
+
+		ModifyListener modifyListener = new ModifyListener() {
+			public void modifyText(ModifyEvent e) {
+				updateWidgets();
+			}
+		};
+
+
+		// row 1
+		//
+		Label uriLabel = new Label(composite, SWT.NONE);
+		uriLabel.setText(XMLUIMessages._UI_LABEL_NAMESPACE_NAME_COLON);
+
+		uriField = new Text(composite, SWT.SINGLE | SWT.BORDER);
+		gd = new GridData(GridData.FILL_HORIZONTAL);
+		gd.grabExcessHorizontalSpace = true;
+		uriField.setLayoutData(gd);
+		uriField.setText(getDisplayValue(fInfo.uri));
+		uriField.addModifyListener(modifyListener);
+		uriField.setEnabled(fInfo.getProperty("uri-readOnly") == null); //$NON-NLS-1$
+
+		// never read
+		Label placeHolder1 = new Label(composite, SWT.NONE);
+		placeHolder1.setText(""); //$NON-NLS-1$
+
+		// row 2
+		//
+		Label prefixLabel = new Label(composite, SWT.NONE);
+		prefixLabel.setText(XMLUIMessages._UI_LABEL_PREFIX_COLON);
+
+		prefixField = new Text(composite, SWT.SINGLE | SWT.BORDER);
+		gd = new GridData(GridData.FILL_HORIZONTAL);
+		gd.grabExcessHorizontalSpace = true;
+		prefixField.setLayoutData(gd);
+		prefixField.setText(getDisplayValue(fInfo.prefix));
+		prefixField.addModifyListener(modifyListener);
+		prefixField.setEnabled(fInfo.getProperty("prefix-readOnly") == null); //$NON-NLS-1$
+
+		// never read
+		Label placeHolder2 = new Label(composite, SWT.NONE);
+		placeHolder2.setText(""); //$NON-NLS-1$
+
+		// row 3
+		//
+		Label locationHintLabel = new Label(composite, SWT.NONE);
+		locationHintLabel.setText(XMLUIMessages._UI_LABEL_LOCATION_HINT_COLON);
+
+		locationHintField = new Text(composite, SWT.SINGLE | SWT.BORDER);
+		gd = new GridData(GridData.FILL_HORIZONTAL);
+		gd.grabExcessHorizontalSpace = true;
+		locationHintField.setLayoutData(gd);
+		locationHintField.setText(getDisplayValue(fInfo.locationHint));
+		locationHintField.addModifyListener(modifyListener);
+		locationHintField.setEnabled(fInfo.getProperty("locationHint-readOnly") == null); //$NON-NLS-1$
+
+		SelectionListener selectionListener = new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				performBrowse();
+			}
+		};
+
+		browseButton = new Button(composite, SWT.NONE);
+		browseButton.setText(XMLUIMessages._UI_LABEL_BROWSE);
+		browseButton.addSelectionListener(selectionListener);
+		browseButton.setEnabled(locationHintField.getEnabled());
+
+		// error message
+		errorMessageLabel = new Label(dialogsubArea, SWT.NONE);
+		errorMessageLabel.setText(XMLUIMessages.error_message_goes_here);
+		errorMessageLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+		Color color = new Color(errorMessageLabel.getDisplay(), 200, 0, 0);
+		errorMessageLabel.setForeground(color);
+
+		return dialogsubArea;
+	}
+
+	protected String getDisplayValue(String string) {
+		return string != null ? string : ""; //$NON-NLS-1$
+	}
+
+	protected void performBrowse() {
+		String[] extensions = {".xsd"}; //$NON-NLS-1$
+		SelectFileOrXMLCatalogIdDialog dialog = new SelectFileOrXMLCatalogIdDialog(getShell(), extensions);
+		dialog.create();
+		dialog.getShell().setText(XMLUIMessages._UI_LABEL_SELECT_FILE);
+		dialog.setBlockOnOpen(true);
+		dialog.open();
+
+		if (dialog.getReturnCode() == Window.OK) {
+			String grammarURI = null;
+			IFile file = dialog.getFile();
+			String id = dialog.getId();
+			if (file != null) {
+				String uri = null;
+				if (resourceLocation != null) {
+					IResource resource = ResourcesPlugin.getWorkspace().getRoot().findMember(resourceLocation);
+					if (resource != null) {
+						IPath location = resource.getLocation();
+						if (location != null) {
+							uri = URIHelper.getRelativeURI(file.getLocation(), location);
+						}
+					}
+					else {
+					  uri = URIHelper.getRelativeURI(file.getLocation(), resourceLocation);
+					}
+					grammarURI = file.getLocation().toOSString();
+				}
+				else {
+					uri = file.getLocation().toOSString();
+					grammarURI = uri;
+				}
+				locationHintField.setText(uri);
+			}
+			else if (id != null) {
+				locationHintField.setText(id);
+				URIResolver resolver = URIResolverPlugin.createResolver();
+				grammarURI = resolver.resolve(null, id, id);
+			}
+
+
+			CMDocument document = ContentModelManager.getInstance().createCMDocument(URIHelper.getURIForFilePath(grammarURI), "xsd"); //$NON-NLS-1$
+			if(document != null) {
+				List namespaceInfoList = (List) document.getProperty("http://org.eclipse.wst/cm/properties/namespaceInfo"); //$NON-NLS-1$
+				if(namespaceInfoList != null) {
+					NamespaceInfo info = (NamespaceInfo) namespaceInfoList.get(0);
+					if(info != null) {
+						if ((uriField.getText().trim().length() == 0) && (info.uri != null)) {
+							uriField.setText(info.uri);
+						}
+						if ((prefixField.getText().trim().length() == 0) && (info.prefix != null)) {
+							prefixField.setText(info.prefix);
+						}
+					}
+				}
+			}
+		}
+	}
+
+	public void setResourceLocation(IPath path) {
+		resourceLocation = path;
+	}
+
+	protected void updateErrorMessageLabel() {
+		errorMessageLabel.setText(errorMessage != null ? errorMessage : ""); //$NON-NLS-1$
+	}
+
+	protected void updateOKButtonState() {
+		if (okButton != null) {
+			if ((uriField.getText().trim().length() == 0) && (prefixField.getText().trim().length() == 0) && (locationHintField.getText().trim().length() == 0)) {
+				okButton.setEnabled(false);
+			}
+			else {
+				okButton.setEnabled(errorMessage == null);
+			}
+		}
+	}
+
+	protected void updateWidgets() {
+		computeErrorMessage();
+		updateErrorMessageLabel();
+		updateOKButtonState();
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/dialogs/EditProcessingInstructionDialog.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/dialogs/EditProcessingInstructionDialog.java
new file mode 100644
index 0000000..6742855
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/dialogs/EditProcessingInstructionDialog.java
@@ -0,0 +1,116 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.dialogs;
+
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+import org.eclipse.wst.xml.ui.internal.util.XMLCommonUIContextIds;
+import org.w3c.dom.ProcessingInstruction;
+
+public class EditProcessingInstructionDialog extends Dialog {
+	protected String data;
+	protected Text dataField;
+	protected String target;
+	protected Text targetField;
+
+	public EditProcessingInstructionDialog(Shell parentShell, ProcessingInstruction pi) {
+		this(parentShell, pi.getTarget(), pi.getData());
+	}
+
+	public EditProcessingInstructionDialog(Shell parentShell, String target, String data) {
+		super(parentShell);
+		setShellStyle(getShellStyle() | SWT.RESIZE);
+		this.target = target;
+		this.data = data;
+	}
+
+	protected void buttonPressed(int buttonId) {
+		target = getModelValue(targetField.getText());
+		data = getModelValue(dataField.getText());
+		super.buttonPressed(buttonId);
+	}
+
+	protected void createButtonsForButtonBar(Composite parent) {
+		createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
+		createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false);
+	}
+
+	protected Control createDialogArea(Composite parent) {
+		Composite dialogArea1 = (Composite) super.createDialogArea(parent);
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(dialogArea1, XMLCommonUIContextIds.XCUI_PROCESSING_DIALOG);
+
+		Composite composite = new Composite(dialogArea1, SWT.NONE);
+		GridLayout layout = new GridLayout();
+		layout.numColumns = 2;
+		layout.marginWidth = 0;
+		composite.setLayout(layout);
+		composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+
+		GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+		gd.widthHint = 250;
+
+		Label targetLabel = new Label(composite, SWT.NONE);
+		targetLabel.setText(XMLUIMessages._UI_LABEL_TARGET_COLON);
+
+		targetField = new Text(composite, SWT.SINGLE | SWT.BORDER);
+		targetField.setLayoutData(gd);
+		targetField.setText(getDisplayValue(target));
+
+		Label dataLabel = new Label(composite, SWT.NONE);
+		dataLabel.setText(XMLUIMessages._UI_LABEL_DATA_COLON);
+
+		dataField = new Text(composite, SWT.SINGLE | SWT.BORDER);
+		dataField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+		dataField.setText(getDisplayValue(data));
+
+		return dialogArea1;
+	}
+
+	protected Label createMessageArea(Composite composite) {
+		Label label = new Label(composite, SWT.NONE);
+		// label.setText(message);
+		return label;
+	}
+
+	public String getData() {
+		return data;
+	}
+
+	protected String getDisplayValue(String string) {
+		return string != null ? string : ""; //$NON-NLS-1$
+	}
+
+	protected String getModelValue(String string) {
+		String result = null;
+		if ((string != null) && (string.trim().length() > 0)) {
+			result = string;
+		}
+		return result;
+	}
+
+
+	public String getTarget() {
+		return target;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/dialogs/EditSchemaInfoDialog.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/dialogs/EditSchemaInfoDialog.java
new file mode 100644
index 0000000..d445809
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/dialogs/EditSchemaInfoDialog.java
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.dialogs;
+
+import java.util.List;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+import org.eclipse.wst.xml.ui.internal.nsedit.CommonEditNamespacesDialog;
+import org.eclipse.wst.xml.ui.internal.util.XMLCommonUIContextIds;
+
+public class EditSchemaInfoDialog extends Dialog implements UpdateListener {
+	// protected NamespaceInfoTable namespaceInfoTable;
+	protected Label errorMessageLabel;
+	protected List namespaceInfoList;
+	protected IPath resourceLocation;
+
+	public EditSchemaInfoDialog(Shell parentShell, IPath resourceLocation) {
+		super(parentShell);
+		setShellStyle(getShellStyle() | SWT.RESIZE);
+		this.resourceLocation = resourceLocation;
+	}
+
+	protected void createButtonsForButtonBar(Composite parent) {
+		createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
+		createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false);
+	}
+
+	protected Control createDialogArea(Composite parent) {
+		Composite dialogArea = (Composite) super.createDialogArea(parent);
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(dialogArea, XMLCommonUIContextIds.XCUI_SCHEMA_INFO_DIALOG);
+
+		CommonEditNamespacesDialog editNamespacesControl = new CommonEditNamespacesDialog(dialogArea, resourceLocation, XMLUIMessages._UI_NAMESPACE_DECLARATIONS, false, true);
+		editNamespacesControl.setNamespaceInfoList(namespaceInfoList);
+
+		editNamespacesControl.updateErrorMessage(namespaceInfoList);
+
+		return dialogArea;
+	}
+
+	protected Control getDialogArea(Composite parent) {
+		return super.createDialogArea(parent);
+	}
+
+	public List getNamespaceInfoList() {
+		return namespaceInfoList;
+	}
+
+	public void setNamespaceInfoList(List list) {
+		namespaceInfoList = list;
+	}
+
+	public void updateErrorMessage(List namespaceInfoList) {
+		NamespaceInfoErrorHelper helper = new NamespaceInfoErrorHelper();
+		String errorMessage = helper.computeErrorMessage(namespaceInfoList, null);
+		errorMessageLabel.setText(errorMessage != null ? errorMessage : ""); //$NON-NLS-1$
+	}
+
+	public void updateOccured(Object object, Object arg) {
+		updateErrorMessage((List) arg);
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/dialogs/NamespaceInfoErrorHelper.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/dialogs/NamespaceInfoErrorHelper.java
new file mode 100644
index 0000000..540df93
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/dialogs/NamespaceInfoErrorHelper.java
@@ -0,0 +1,104 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.dialogs;
+
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.wst.common.uriresolver.internal.provisional.URIResolver;
+import org.eclipse.wst.common.uriresolver.internal.util.URIHelper;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.DOMNamespaceInfoManager;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.NamespaceInfo;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+
+public class NamespaceInfoErrorHelper {
+
+	protected List errorList;
+
+	public NamespaceInfoErrorHelper() {
+	}
+
+	public String computeErrorMessage(List namespaceInfoList, URIResolver idResolver) {
+		String result = null;
+		Hashtable prefixTable = new Hashtable();
+		Hashtable uriTable = new Hashtable();
+		for (Iterator iterator = namespaceInfoList.iterator(); iterator.hasNext();) {
+			NamespaceInfo nsInfo = (NamespaceInfo) iterator.next();
+			nsInfo.normalize();
+
+			String urikey = nsInfo.uri != null ? nsInfo.uri : ""; //$NON-NLS-1$
+			NamespaceInfo nsInfo2 = null;
+			if ((nsInfo2 = (NamespaceInfo) uriTable.get(urikey)) != null) {
+				if ((nsInfo.uri != null) && nsInfo.uri.equals(nsInfo2.uri)) {
+					result = XMLUIMessages._UI_WARNING_MORE_THAN_ONE_NS_WITH_NAME + "'" + nsInfo.uri + "'"; //$NON-NLS-1$ //$NON-NLS-2$ 
+				}
+				else {
+					result = XMLUIMessages._UI_WARNING_MORE_THAN_ONE_NS_WITHOUT_NAME;
+				}
+				break;
+			}
+			else {
+				uriTable.put(urikey, nsInfo);
+			}
+
+			if (nsInfo.uri != null) {
+				String key = nsInfo.prefix != null ? nsInfo.prefix : ""; //$NON-NLS-1$
+				if (prefixTable.get(key) != null) {
+					if (nsInfo.prefix != null) {
+						result = XMLUIMessages._UI_WARNING_MORE_THAN_ONE_NS_WITH_PREFIX + "'" + nsInfo.prefix + "'"; //$NON-NLS-1$ //$NON-NLS-2$ 
+						break;
+					}
+					else {
+						result = XMLUIMessages._UI_WARNING_MORE_THAN_ONE_NS_WITHOUT_PREFIX;
+						break;
+					}
+				}
+				else {
+					prefixTable.put(key, nsInfo);
+				}
+
+				if ((nsInfo.locationHint != null) && (idResolver != null)) {
+					String grammarURI = idResolver.resolve(null, nsInfo.locationHint, nsInfo.locationHint);
+					if (!URIHelper.isReadableURI(grammarURI, false)) {
+						result = XMLUIMessages._UI_WARNING_SCHEMA_CAN_NOT_BE_LOCATED + " '" + nsInfo.locationHint + "'"; //$NON-NLS-1$ //$NON-NLS-2$ 
+						break;
+					}
+				}
+				if ((idResolver != null) && (nsInfo.locationHint == null) && !nsInfo.uri.equals(DOMNamespaceInfoManager.XSI_URI)) {
+					result = XMLUIMessages._UI_WARNING_LOCATION_HINT_NOT_SPECIFIED + " '" + nsInfo.uri + "'"; //$NON-NLS-1$ //$NON-NLS-2$ 
+					break;
+				}
+			}
+			else {
+				if (nsInfo.prefix != null) {
+					result = XMLUIMessages._UI_WARNING_NAMESPACE_NAME_NOT_SPECIFIED + " '" + nsInfo.prefix + "'"; //$NON-NLS-1$ //$NON-NLS-2$ 
+					break;
+				}
+			}
+		}
+		// additional tests
+		if (result == null) {
+			for (Iterator iterator = namespaceInfoList.iterator(); iterator.hasNext();) {
+				NamespaceInfo nsInfo = (NamespaceInfo) iterator.next();
+				nsInfo.normalize();
+				if ((nsInfo.uri != null) && nsInfo.isPrefixRequired && (nsInfo.prefix == null)) {
+					result = XMLUIMessages._UI_WARNING_PREFIX_NOT_SPECIFIED + " '" + nsInfo.uri + "'"; //$NON-NLS-1$ //$NON-NLS-2$ 
+					break;
+				}
+			}
+		}
+
+		return result;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/dialogs/NamespaceInfoTable.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/dialogs/NamespaceInfoTable.java
new file mode 100644
index 0000000..8a438dc
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/dialogs/NamespaceInfoTable.java
@@ -0,0 +1,398 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.dialogs;
+
+import java.util.List;
+import java.util.Vector;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jface.viewers.CellEditor;
+import org.eclipse.jface.viewers.ColumnWeightData;
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.TableLayout;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.TextCellEditor;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.MouseAdapter;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.NamespaceInfo;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+import org.eclipse.wst.xml.ui.internal.XMLUIPlugin;
+
+public class NamespaceInfoTable extends Composite {
+
+	/**
+	 * NamespaceInfoTableLabelProvider
+	 */
+	protected class NamespaceInfoTableLabelProvider implements ITableLabelProvider, IStructuredContentProvider {
+
+		public void addListener(ILabelProviderListener listener) {
+		}
+
+		public void dispose() {
+		}
+
+		public Image getColumnImage(Object object, int columnIndex) {
+			return null;
+		}
+
+		public String getColumnText(Object object, int column) {
+			NamespaceInfo info = (NamespaceInfo) object;
+			String result = null;
+			switch (column) {
+				case 0 : {
+					result = info.uri;
+					break;
+				}
+				case 1 : {
+					result = info.prefix;
+					break;
+				}
+				case 2 : {
+					result = info.locationHint;
+					break;
+				}
+			}
+			result = result != null ? result : ""; //$NON-NLS-1$
+			if (result.equals("")) { //$NON-NLS-1$
+				switch (column) {
+					case 0 : {
+						result = XMLUIMessages._UI_NO_NAMESPACE_NAME;
+						break;
+					}
+					case 1 : {
+						result = XMLUIMessages._UI_NO_PREFIX;
+						break;
+					}
+				}
+			}
+			return result;
+		}
+
+		String getDefaultPrefix() {
+			String defaultPrefix = "p"; //$NON-NLS-1$
+			if (namespaceInfoList == null) {
+				return defaultPrefix;
+			}
+			Vector v = new Vector();
+			for (int i = 0; i < namespaceInfoList.size(); i++) {
+				NamespaceInfo nsinfo = (NamespaceInfo) namespaceInfoList.get(i);
+				if (nsinfo.prefix != null) {
+					v.addElement(nsinfo.prefix);
+				}
+			}
+			if (v.contains(defaultPrefix)) {
+				String s = defaultPrefix;
+				for (int j = 0; v.contains(s); j++) {
+					s = defaultPrefix + Integer.toString(j);
+				}
+				return s;
+			}
+			else {
+				return defaultPrefix;
+			}
+		}
+
+		public Object[] getElements(Object inputElement) {
+			return namespaceInfoList.toArray();
+		}
+
+		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+		}
+
+		public boolean isDeleted(Object element) {
+			return false;
+		}
+
+		public boolean isLabelProperty(Object object, Object property) {
+			return false;
+		}
+
+		public boolean isLabelProperty(Object element, String property) {
+			return false;
+		}
+
+		public void removeListener(ILabelProviderListener listener) {
+		}
+	}
+
+	protected static final String LOCATION_HINT = XMLUIMessages._UI_LABEL_LOCATION_HINT;
+	protected static final String NAMESPACE_URI = XMLUIMessages._UI_LABEL_NAMESPACE_NAME;
+	protected static final String PREFIX = XMLUIMessages._UI_LABEL_PREFIX;
+	protected Button deleteButton;
+	protected boolean dummyRowsRemoved = false;
+	protected Button editButton;
+	protected List namespaceInfoList = new Vector();
+	protected Button newButton;
+	protected NamespaceInfoTableLabelProvider provider;
+	protected IPath resourceLocation;
+	protected TableViewer tableViewer;
+	protected UpdateListener updateListener;
+	protected int visibleRows = -1;
+
+	public NamespaceInfoTable(Composite parent) {
+		this(parent, -1, -1, -1);
+	}
+
+	public NamespaceInfoTable(Composite parent, int visibleRows) {
+		this(parent, -1, -1, visibleRows);
+	}
+
+	public NamespaceInfoTable(Composite parent, int widthHint, int heightHint) {
+		this(parent, widthHint, heightHint, -1);
+	}
+
+	public NamespaceInfoTable(Composite parent, int widthHint, int heightHint, int visibleRows) {
+		super(parent, SWT.NONE);
+		setLayout(createGridLayout());
+		setLayoutData(new GridData(GridData.FILL_BOTH));
+		Group namespaceInfoGroup = new Group(this, SWT.NONE);
+		namespaceInfoGroup.setText(XMLUIMessages._UI_LABEL_XML_SCHEMA_INFORMATION);
+		namespaceInfoGroup.setLayout(new GridLayout());
+		GridData gd = new GridData(GridData.FILL_BOTH);
+		if (widthHint != -1) {
+			gd.widthHint = widthHint;
+		}
+		if (heightHint != -1) {
+			gd.heightHint = heightHint;
+		}
+		namespaceInfoGroup.setLayoutData(gd);
+		// WorkbenchHelp.setHelp(namespaceInfoGroup, new
+		// ControlContextComputer(namespaceInfoGroup,
+		// XMLBuilderContextIds.XMLC_NAMESPACE_GROUP));
+		String[] titleArray = {NAMESPACE_URI, PREFIX, LOCATION_HINT};
+		tableViewer = new TableViewer(namespaceInfoGroup, SWT.FULL_SELECTION);
+		provider = new NamespaceInfoTableLabelProvider();
+		tableViewer.setContentProvider(provider);
+		tableViewer.setLabelProvider(provider);
+		tableViewer.setColumnProperties(titleArray);
+		Table table = tableViewer.getTable();
+		table.setHeaderVisible(true);
+		table.setLayoutData(new GridData(GridData.FILL_BOTH));
+		int[] widthArray = {50, 20, 30};
+		TableLayout layout = new TableLayout();
+		for (int i = 0; i < titleArray.length; i++) {
+			TableColumn column = new TableColumn(table, i);
+			column.setText(titleArray[i]);
+			column.setAlignment(SWT.LEFT);
+			layout.addColumnData(new ColumnWeightData(widthArray[i], true));
+		}
+		this.visibleRows = visibleRows;
+		for (int i = 0; i < visibleRows; i++) {
+			TableItem item = new TableItem(table, SWT.NONE);
+			item.setText("#######"); //$NON-NLS-1$
+		}
+		table.setLayout(layout);
+		CellEditor[] cellEditors = new CellEditor[titleArray.length];
+		cellEditors[1] = new TextCellEditor(table);
+		cellEditors[2] = new TextCellEditor(table);
+		tableViewer.setCellEditors(cellEditors);
+		MouseAdapter mouseAdapter = new MouseAdapter() {
+			public void mouseDoubleClick(MouseEvent e) {
+				if (tableViewer.getTable().getItem(new Point(e.x, e.y)) != null) {
+					performEdit();
+				}
+			}
+		};
+		table.addMouseListener(mouseAdapter);
+		createButtons(namespaceInfoGroup);
+		ISelectionChangedListener selectionChangedListener = new ISelectionChangedListener() {
+			public void selectionChanged(SelectionChangedEvent event) {
+				updateButtonEnabledState();
+			}
+		};
+		tableViewer.addSelectionChangedListener(selectionChangedListener);
+	}
+
+	protected void createButtons(Composite parent) {
+		Composite composite = new Composite(parent, SWT.NONE);
+		composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+		GridLayout gridLayout = new GridLayout();
+		gridLayout.numColumns = 2;
+		gridLayout.marginHeight = 0;
+		gridLayout.marginWidth = 0;
+		composite.setLayout(gridLayout);
+		Button hiddenButton = new Button(composite, SWT.NONE);
+		hiddenButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+		hiddenButton.setVisible(false);
+		hiddenButton.setEnabled(false);
+		SelectionListener selectionListener = new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				if (e.widget == newButton) {
+					performNew();
+				}
+				else if (e.widget == editButton) {
+					performEdit();
+				}
+				else if (e.widget == deleteButton) {
+					performDelete();
+				}
+			}
+		};
+		// create a composite to hold the three buttons
+		Composite buttonComposite = new Composite(composite, SWT.NONE);
+		buttonComposite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+		GridLayout buttonGridLayout = new GridLayout();
+		buttonGridLayout.numColumns = 3;
+		buttonGridLayout.makeColumnsEqualWidth = true;
+		buttonComposite.setLayout(buttonGridLayout);
+		// add the New button
+		//
+		newButton = new Button(buttonComposite, SWT.NONE);
+		newButton.setText(XMLUIMessages._UI_BUTTON_NEW);
+		newButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+		newButton.addSelectionListener(selectionListener);
+		// add the Edit button
+		//
+		editButton = new Button(buttonComposite, SWT.NONE);
+		editButton.setText(XMLUIMessages._UI_BUTTON_EDIT);
+		editButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+		editButton.addSelectionListener(selectionListener);
+		// add the Delete button
+		//
+		deleteButton = new Button(buttonComposite, SWT.NONE);
+		deleteButton.setText(XMLUIMessages._UI_BUTTON_DELETE);
+		deleteButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+		deleteButton.addSelectionListener(selectionListener);
+	}
+
+	public GridLayout createGridLayout() {
+		GridLayout gridLayout = new GridLayout();
+		gridLayout.marginWidth = 0;
+		gridLayout.horizontalSpacing = 0;
+		return gridLayout;
+	}
+
+	public List getNamespaceInfoList() {
+		return namespaceInfoList;
+	}
+
+	protected NamespaceInfo getTargetNamespaceInfo() {
+		return ((namespaceInfoList != null) && (namespaceInfoList.size() > 0)) ? (NamespaceInfo) namespaceInfoList.get(0) : null;
+	}
+
+	protected EditNamespaceInfoDialog invokeDialog(String title, NamespaceInfo info) {
+		Shell shell = XMLUIPlugin.getInstance().getWorkbench().getActiveWorkbenchWindow().getShell();
+		EditNamespaceInfoDialog dialog = new EditNamespaceInfoDialog(shell, info);
+		dialog.create();
+		dialog.getShell().setText(title);
+		dialog.setBlockOnOpen(true);
+		dialog.setResourceLocation(resourceLocation);
+		dialog.open();
+		return dialog;
+	}
+
+	protected void performDelayedUpdate() {
+		Runnable delayedUpdate = new Runnable() {
+			public void run() {
+				update();
+			}
+		};
+		getDisplay().asyncExec(delayedUpdate);
+		if (updateListener != null) {
+			updateListener.updateOccured(this, namespaceInfoList);
+		}
+	}
+
+	public void performDelete() {
+		ISelection selection = tableViewer.getSelection();
+		Object selectedObject = (selection instanceof IStructuredSelection) ? ((IStructuredSelection) selection).getFirstElement() : null;
+		if (selectedObject != null) {
+			namespaceInfoList.remove(selectedObject);
+			performDelayedUpdate();
+		}
+	}
+
+	public void performEdit() {
+		ISelection selection = tableViewer.getSelection();
+		Object selectedObject = (selection instanceof IStructuredSelection) ? ((IStructuredSelection) selection).getFirstElement() : null;
+		if (selectedObject instanceof NamespaceInfo) {
+			invokeDialog(XMLUIMessages._UI_LABEL_NEW_NAMESPACE_INFORMATION, (NamespaceInfo) selectedObject);
+			performDelayedUpdate();
+		}
+	}
+
+	public void performNew() {
+		NamespaceInfo info = new NamespaceInfo();
+		EditNamespaceInfoDialog dialog = invokeDialog(XMLUIMessages._UI_LABEL_NEW_NAMESPACE_INFORMATION, info);
+		if (dialog.getReturnCode() == Window.OK) {
+			namespaceInfoList.add(info);
+			performDelayedUpdate();
+		}
+	}
+
+	public void setNamespaceInfoList(List namespaceInfoList) {
+		this.namespaceInfoList = namespaceInfoList;
+		update();
+	}
+
+	public void setResourceLocation(IPath resourceLocation) {
+		this.resourceLocation = resourceLocation;
+	}
+
+	public void setUpdateListener(UpdateListener updateListener) {
+		this.updateListener = updateListener;
+	}
+
+	public void update() {
+		updateHelper(namespaceInfoList);
+	}
+
+	public void updateButtonEnabledState() {
+		ISelection selection = tableViewer.getSelection();
+		Object selectedObject = (selection instanceof IStructuredSelection) ? ((IStructuredSelection) selection).getFirstElement() : null;
+		NamespaceInfo info = (NamespaceInfo) selectedObject;
+		editButton.setEnabled(info != null);
+		deleteButton.setEnabled((info != null) && (info.getProperty("unremovable") == null)); //$NON-NLS-1$
+	}
+
+	public void updateHelper(List namespaceInfoList) {
+		if ((visibleRows != -1) && !dummyRowsRemoved) {
+			dummyRowsRemoved = true;
+			tableViewer.getTable().removeAll();
+		}
+		ISelection selection = tableViewer.getSelection();
+		tableViewer.setInput(namespaceInfoList);
+		if (selection.isEmpty()) {
+			if (namespaceInfoList.size() > 0) {
+				tableViewer.setSelection(new StructuredSelection(namespaceInfoList.get(0)));
+			}
+		}
+		else {
+			tableViewer.setSelection(selection);
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/dialogs/SelectFileOrXMLCatalogIdDialog.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/dialogs/SelectFileOrXMLCatalogIdDialog.java
new file mode 100644
index 0000000..d36cf7b
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/dialogs/SelectFileOrXMLCatalogIdDialog.java
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.dialogs;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+
+
+public class SelectFileOrXMLCatalogIdDialog extends Dialog {
+	protected int catalogEntryType;
+	protected String[] extensions;
+	protected IFile file;
+	protected String id;
+	protected Button okButton;
+	protected SelectFileOrXMLCatalogIdPanel panel;
+
+	public SelectFileOrXMLCatalogIdDialog(Shell parentShell, String[] extensions) {
+		this(parentShell, extensions, 0);
+	}
+
+	public SelectFileOrXMLCatalogIdDialog(Shell parentShell, String[] extensions, int catalogEntryType) {
+		super(parentShell);
+		setShellStyle(getShellStyle() | SWT.RESIZE);
+		this.extensions = extensions;
+		this.catalogEntryType = catalogEntryType;
+	}
+
+
+	protected void buttonPressed(int buttonId) {
+		if (buttonId == IDialogConstants.OK_ID) {
+			file = panel.getFile();
+			id = panel.getXMLCatalogId();
+		}
+		super.buttonPressed(buttonId);
+	}
+
+	protected void createButtonsForButtonBar(Composite parent) {
+		okButton = createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
+		okButton.setEnabled(false);
+		createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false);
+	}
+
+	protected Control createDialogArea(Composite parent) {
+		Composite dialogArea = (Composite) super.createDialogArea(parent);
+
+		panel = new SelectFileOrXMLCatalogIdPanel(dialogArea);
+		panel.setCatalogEntryType(catalogEntryType);
+		panel.setFilterExtensions(extensions);
+		panel.setVisibleHelper(true);
+		SelectFileOrXMLCatalogIdPanel.Listener listener = new SelectFileOrXMLCatalogIdPanel.Listener() {
+			public void completionStateChanged() {
+				updateButtonState();
+			}
+		};
+		panel.setListener(listener);
+
+		return dialogArea;
+	}
+
+	public IFile getFile() {
+		return file;
+	}
+
+	public String getId() {
+		return id;
+	}
+
+	protected void updateButtonState() {
+		okButton.setEnabled((panel.getFile() != null) || (panel.getXMLCatalogId() != null));
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/dialogs/SelectFileOrXMLCatalogIdPanel.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/dialogs/SelectFileOrXMLCatalogIdPanel.java
new file mode 100644
index 0000000..2987b04
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/dialogs/SelectFileOrXMLCatalogIdPanel.java
@@ -0,0 +1,184 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *	   David Schneider, david.schneider@unisys.com - [142500] WTP properties pages fonts don't follow Eclipse preferences
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.dialogs;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.ui.part.PageBook;
+import org.eclipse.wst.common.ui.internal.viewers.SelectSingleFileView;
+import org.eclipse.wst.xml.core.internal.XMLCorePlugin;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalog;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalogEntry;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+
+
+public class SelectFileOrXMLCatalogIdPanel extends Composite implements SelectionListener {
+
+	/**
+	 * TODO: Change the name of this interface; "Listener" is used by SWT.
+	 */
+	public interface Listener {
+		void completionStateChanged();
+	}
+
+	protected class MySelectSingleFileView extends SelectSingleFileView implements SelectSingleFileView.Listener {
+		protected Control control;
+
+		public MySelectSingleFileView(Composite parent) {
+			super(null, true);
+			// String[] ext = {".dtd"};
+			// addFilterExtensions(ext);
+			control = createControl(parent);
+			control.setLayoutData(new GridData(GridData.FILL_BOTH));
+			MySelectSingleFileView.this.setListener(this);
+		}
+
+		public Control getControl() {
+			return control;
+		}
+
+		public void setControlComplete(boolean isComplete) {
+			updateCompletionStateChange();
+		}
+
+		public void setVisibleHelper(boolean isVisible) {
+			super.setVisibleHelper(isVisible);
+		}
+	}
+
+	protected Listener listener;
+	protected PageBook pageBook;
+
+	protected Button[] radioButton;
+	protected MySelectSingleFileView selectSingleFileView;
+	protected SelectXMLCatalogIdPanel selectXMLCatalogIdPanel;
+
+	public SelectFileOrXMLCatalogIdPanel(Composite parent) {
+		super(parent, SWT.NONE);
+
+		// container group
+		setLayout(new GridLayout());
+		GridData gd = new GridData(GridData.FILL_BOTH);
+		gd.heightHint = 400;
+		gd.widthHint = 400;
+		setLayoutData(gd);
+
+		radioButton = new Button[2];
+		radioButton[0] = new Button(this, SWT.RADIO);
+		radioButton[0].setText(XMLUIMessages._UI_RADIO_BUTTON_SELECT_FROM_WORKSPACE);
+		radioButton[0].setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+		radioButton[0].setSelection(true);
+		radioButton[0].addSelectionListener(this);
+
+		radioButton[1] = new Button(this, SWT.RADIO);
+		radioButton[1].setText(XMLUIMessages._UI_RADIO_BUTTON_SELECT_FROM_CATALOG);
+		radioButton[1].setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+		radioButton[1].addSelectionListener(this);
+
+		pageBook = new PageBook(this, SWT.NONE);
+		pageBook.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+		selectSingleFileView = new MySelectSingleFileView(pageBook);
+
+		ICatalog xmlCatalog = XMLCorePlugin.getDefault().getDefaultXMLCatalog();
+		selectXMLCatalogIdPanel = new SelectXMLCatalogIdPanel(pageBook, xmlCatalog);
+		selectXMLCatalogIdPanel.getTableViewer().addSelectionChangedListener(new ISelectionChangedListener() {
+			public void selectionChanged(SelectionChangedEvent event) {
+				updateCompletionStateChange();
+			}
+		});
+		Dialog.applyDialogFont(parent);
+		pageBook.showPage(selectSingleFileView.getControl());
+
+	}
+
+	public IFile getFile() {
+		IFile result = null;
+		if (radioButton[0].getSelection()) {
+			result = selectSingleFileView.getFile();
+		}
+		return result;
+	}
+
+	public ICatalogEntry getXMLCatalogEntry() {
+		ICatalogEntry result = null;
+		if (radioButton[1].getSelection()) {
+			result = selectXMLCatalogIdPanel.getXMLCatalogEntry();
+		}
+		return result;
+	}
+
+	public String getXMLCatalogId() {
+		String result = null;
+		if (radioButton[1].getSelection()) {
+			result = selectXMLCatalogIdPanel.getId();
+		}
+		return result;
+	}
+
+	public String getXMLCatalogURI() {
+		String result = null;
+		if (radioButton[1].getSelection()) {
+			result = selectXMLCatalogIdPanel.getURI();
+		}
+		return result;
+	}
+
+	public void setCatalogEntryType(int catalogEntryType) {
+		selectXMLCatalogIdPanel.setCatalogEntryType(catalogEntryType);
+	}
+
+	public void setFilterExtensions(String[] filterExtensions) {
+		selectSingleFileView.resetFilters();
+		selectSingleFileView.addFilterExtensions(filterExtensions);
+
+		selectXMLCatalogIdPanel.getTableViewer().setFilterExtensions(filterExtensions);
+	}
+
+	public void setListener(Listener listener) {
+		this.listener = listener;
+	}
+
+	public void setVisibleHelper(boolean isVisible) {
+		selectSingleFileView.setVisibleHelper(isVisible);
+	}
+
+	public void updateCompletionStateChange() {
+		if (listener != null) {
+			listener.completionStateChanged();
+		}
+	}
+
+	public void widgetDefaultSelected(SelectionEvent e) {
+	}
+
+	public void widgetSelected(SelectionEvent e) {
+		if (e.widget == radioButton[0]) {
+			pageBook.showPage(selectSingleFileView.getControl());
+		}
+		else {
+			pageBook.showPage(selectXMLCatalogIdPanel);
+		}
+		updateCompletionStateChange();
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/dialogs/SelectXMLCatalogIdDialog.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/dialogs/SelectXMLCatalogIdDialog.java
new file mode 100644
index 0000000..624c96a
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/dialogs/SelectXMLCatalogIdDialog.java
@@ -0,0 +1,111 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+
+
+package org.eclipse.wst.xml.ui.internal.dialogs;
+
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.wst.xml.core.internal.XMLCorePlugin;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalog;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalogEntry;
+import org.eclipse.wst.xml.ui.internal.util.XMLCommonUIContextIds;
+
+
+
+public class SelectXMLCatalogIdDialog extends Dialog {
+	protected String[] extensions;
+	protected Button okButton;
+	protected SelectXMLCatalogIdPanel panel;
+	protected String publicId;
+	protected String systemId;
+
+	public SelectXMLCatalogIdDialog(Shell parentShell, String[] extensions) {
+		super(parentShell);
+		setShellStyle(getShellStyle() | SWT.RESIZE);
+		this.extensions = extensions;
+	}
+
+
+	protected void buttonPressed(int buttonId) {
+		if (buttonId == IDialogConstants.OK_ID) {
+			ISelection selection = panel.getTableViewer().getSelection();
+			Object selectedObject = (selection instanceof IStructuredSelection) ? ((IStructuredSelection) selection).getFirstElement() : null;
+
+			if (selectedObject instanceof ICatalogEntry) {
+				ICatalogEntry mappingInfo = (ICatalogEntry) selectedObject;
+				publicId = mappingInfo.getKey();
+				systemId = computeDefaultSystemId(mappingInfo);
+			}
+		}
+		super.buttonPressed(buttonId);
+	}
+
+	protected String computeDefaultSystemId(ICatalogEntry mappingInfo) {
+		String result = mappingInfo.getAttributeValue(ICatalogEntry.ATTR_WEB_URL);
+		if ((result == null) && (mappingInfo.getURI() != null)) {
+			int index = mappingInfo.getURI().lastIndexOf("/"); //$NON-NLS-1$
+			String lastSegment = index != -1 ? mappingInfo.getURI().substring(index + 1) : mappingInfo.getURI();
+			result = lastSegment;
+		}
+		return result;
+	}
+
+	protected void createButtonsForButtonBar(Composite parent) {
+		okButton = createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
+		okButton.setEnabled(false);
+		createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false);
+	}
+
+	protected Control createDialogArea(Composite parent) {
+		Composite dialogArea = (Composite) super.createDialogArea(parent);
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(dialogArea, XMLCommonUIContextIds.XCUI_CATALOG_DIALOG);
+
+		ICatalog xmlCatalog = XMLCorePlugin.getDefault().getDefaultXMLCatalog();
+		panel = new SelectXMLCatalogIdPanel(dialogArea, xmlCatalog);
+
+		ISelectionChangedListener listener = new ISelectionChangedListener() {
+			public void selectionChanged(SelectionChangedEvent event) {
+				updateButtonState();
+			}
+		};
+		panel.getTableViewer().setFilterExtensions(extensions);
+		panel.getTableViewer().addSelectionChangedListener(listener);
+		return dialogArea;
+	}
+
+
+
+	public String getId() {
+		return publicId;
+	}
+
+	public String getSystemId() {
+		return systemId;
+	}
+
+	protected void updateButtonState() {
+		ISelection selection = panel.getTableViewer().getSelection();
+		okButton.setEnabled(!selection.isEmpty());
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/dialogs/SelectXMLCatalogIdPanel.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/dialogs/SelectXMLCatalogIdPanel.java
new file mode 100644
index 0000000..c1d5114
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/dialogs/SelectXMLCatalogIdPanel.java
@@ -0,0 +1,147 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.dialogs;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Vector;
+
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.wst.xml.core.internal.XMLCorePlugin;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalog;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalogEntry;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.INextCatalog;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+
+
+public class SelectXMLCatalogIdPanel extends Composite {
+	protected int catalogEntryType;
+	protected boolean doTableSizeHack = false;
+
+	protected XMLCatalogTableViewer tableViewer;
+	protected ICatalog fXmlCatalog;
+
+	public SelectXMLCatalogIdPanel(Composite parent, ICatalog xmlCatalog) {
+		super(parent, SWT.NONE);
+		this.fXmlCatalog = xmlCatalog;
+
+		GridLayout gridLayout = new GridLayout();
+		this.setLayout(gridLayout);
+		GridData gd = new GridData(GridData.FILL_BOTH);
+		gd.heightHint = 200;
+		gd.widthHint = 700;
+		this.setLayoutData(gd);
+
+		Label label = new Label(this, SWT.NONE);
+		label.setText(XMLUIMessages._UI_LABEL_XML_CATALOG_COLON);
+
+		tableViewer = createTableViewer(this);
+		tableViewer.getControl().setLayoutData(new GridData(GridData.FILL_BOTH));
+		tableViewer.setInput("dummy"); //$NON-NLS-1$
+	}
+
+	protected XMLCatalogTableViewer createTableViewer(Composite parent) {
+		String headings[] = new String[2];
+		headings[0] = XMLUIMessages._UI_LABEL_KEY;
+		headings[1] = XMLUIMessages._UI_LABEL_URI;
+
+		XMLCatalogTableViewer theTableViewer = new XMLCatalogTableViewer(parent, headings) {
+
+			protected void addXMLCatalogEntries(List list, ICatalogEntry[] entries) {
+				for (int i = 0; i < entries.length; i++) {
+					ICatalogEntry entry = entries[i];
+					if (catalogEntryType == 0) {
+						list.add(entry);
+					}
+					else if (catalogEntryType == entry.getEntryType()) {
+						list.add(entry);
+					}
+				}
+			}
+
+			public Collection getXMLCatalogEntries() {
+				List result = null;
+
+				if ((fXmlCatalog == null) || doTableSizeHack) {
+					// this lets us create a table with an initial height of
+					// 10 rows
+					// otherwise we get stuck with 0 row heigh table... that's
+					// too small
+					doTableSizeHack = false;
+					result = new Vector();
+					for (int i = 0; i < 6; i++) {
+						result.add(""); //$NON-NLS-1$
+					}
+				}
+				else {
+					result = new Vector();
+					INextCatalog[] nextCatalogs = fXmlCatalog.getNextCatalogs();
+					for (int i = 0; i < nextCatalogs.length; i++) {
+						INextCatalog catalog = nextCatalogs[i];
+						ICatalog referencedCatalog = catalog.getReferencedCatalog();
+						if (referencedCatalog != null) {
+							if (XMLCorePlugin.SYSTEM_CATALOG_ID.equals(referencedCatalog.getId())) {
+								ICatalog systemCatalog = referencedCatalog;
+								addXMLCatalogEntries(result, systemCatalog.getCatalogEntries());
+
+							}
+							else if (XMLCorePlugin.USER_CATALOG_ID.equals(referencedCatalog.getId())) {
+								ICatalog userCatalog = referencedCatalog;
+								addXMLCatalogEntries(result, userCatalog.getCatalogEntries());
+
+							}
+						}
+					}
+				}
+				return result;
+			}
+		};
+		return theTableViewer;
+	}
+
+
+	public String getId() {
+		ICatalogEntry entry = getXMLCatalogEntry();
+		return entry != null ? entry.getKey() : null;
+	}
+
+	public XMLCatalogTableViewer getTableViewer() {
+		return tableViewer;
+	}
+
+	public String getURI() {
+		ICatalogEntry entry = getXMLCatalogEntry();
+		return entry != null ? entry.getURI() : null;
+	}
+
+	public ICatalogEntry getXMLCatalogEntry() {
+		ICatalogEntry result = null;
+		ISelection selection = tableViewer.getSelection();
+		Object selectedObject = (selection instanceof IStructuredSelection) ? ((IStructuredSelection) selection).getFirstElement() : null;
+		if (selectedObject instanceof ICatalogEntry) {
+			result = (ICatalogEntry) selectedObject;
+		}
+		return result;
+	}
+
+	public void setCatalogEntryType(int catalogEntryType) {
+		this.catalogEntryType = catalogEntryType;
+		tableViewer.refresh();
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/dialogs/UpdateListener.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/dialogs/UpdateListener.java
new file mode 100644
index 0000000..607270a
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/dialogs/UpdateListener.java
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+
+
+package org.eclipse.wst.xml.ui.internal.dialogs;
+
+public interface UpdateListener {
+
+	public void updateOccured(Object object, Object arg);
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/dialogs/XMLCatalogTableViewer.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/dialogs/XMLCatalogTableViewer.java
new file mode 100644
index 0000000..ada8759
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/dialogs/XMLCatalogTableViewer.java
@@ -0,0 +1,201 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+
+
+package org.eclipse.wst.xml.ui.internal.dialogs;
+
+import com.ibm.icu.text.Collator;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Comparator;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.viewers.ColumnWeightData;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.TableLayout;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerFilter;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.wst.common.uriresolver.internal.util.URIHelper;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalogEntry;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImageHelper;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImages;
+
+
+public class XMLCatalogTableViewer extends TableViewer {
+
+
+	public class CatalogEntryContentProvider implements IStructuredContentProvider {
+
+		public void dispose() {
+		}
+
+		public Object[] getElements(Object element) {
+			Object[] array = getXMLCatalogEntries().toArray();
+			Comparator comparator = new Comparator() {
+				public int compare(Object o1, Object o2) {
+					int result = 0;
+					if ((o1 instanceof ICatalogEntry) && (o2 instanceof ICatalogEntry)) {
+						ICatalogEntry mappingInfo1 = (ICatalogEntry) o1;
+						ICatalogEntry mappingInfo2 = (ICatalogEntry) o2;
+						result = Collator.getInstance().compare(mappingInfo1.getKey(), mappingInfo2.getKey());
+					}
+					return result;
+				}
+			};
+			Arrays.sort(array, comparator);
+			return array;
+		}
+
+		public void inputChanged(Viewer viewer, Object old, Object newobj) {
+		}
+
+		public boolean isDeleted(Object object) {
+			return false;
+		}
+	}
+
+	public class CatalogEntryLabelProvider extends LabelProvider implements ITableLabelProvider {
+
+		public Image getColumnImage(Object object, int columnIndex) {
+			Image result = null;
+			if (columnIndex == 0) {
+				Image base = null;
+				if (object instanceof ICatalogEntry) {
+					ICatalogEntry catalogEntry = (ICatalogEntry) object;
+					String uri = catalogEntry.getURI();
+					if (uri.endsWith("dtd")) { //$NON-NLS-1$
+						base = dtdFileImage;
+					}
+					else if (uri.endsWith("xsd")) { //$NON-NLS-1$
+						base = xsdFileImage;
+					}
+					else {
+						base = unknownFileImage;
+					}
+
+					if (base != null) {
+						if (URIHelper.isReadableURI(uri, false)) {
+							result = base;
+						}
+						else {
+							// TODO... SSE port
+							result = base;// imageFactory.createCompositeImage(base,
+							// errorImage,
+							// ImageFactory.BOTTOM_LEFT);
+						}
+					}
+				}
+			}
+			return result;
+		}
+
+		public String getColumnText(Object object, int columnIndex) {
+			String result = null;
+			if (object instanceof ICatalogEntry) {
+				ICatalogEntry catalogEntry = (ICatalogEntry) object;
+				result = columnIndex == 0 ? catalogEntry.getKey() : catalogEntry.getURI();
+				result = URIHelper.removePlatformResourceProtocol(result);
+			}
+			return result != null ? result : ""; //$NON-NLS-1$
+		}
+	}
+
+
+	class XMLCatalogTableViewerFilter extends ViewerFilter {
+		protected String[] extensions;
+
+		public XMLCatalogTableViewerFilter(String[] extensions) {
+			this.extensions = extensions;
+		}
+
+		public boolean isFilterProperty(Object element, Object property) {
+			return false;
+		}
+
+		public boolean select(Viewer viewer, Object parent, Object element) {
+			boolean result = false;
+			if (element instanceof ICatalogEntry) {
+				ICatalogEntry catalogEntry = (ICatalogEntry) element;
+				for (int i = 0; i < extensions.length; i++) {
+					if (catalogEntry.getURI().endsWith(extensions[i])) {
+						result = true;
+						break;
+					}
+				}
+			}
+			return result;
+		}
+	}
+
+	protected static Image dtdFileImage = XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_DTDFILE);
+
+	protected static String ERROR_STATE_KEY = "errorstatekey"; //$NON-NLS-1$
+	protected static Image errorImage = XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OVR_ERROR);
+
+	protected static Image unknownFileImage = XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TXTEXT);
+	protected static Image xsdFileImage = XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_XSDFILE);
+
+	// protected ImageFactory imageFactory = new ImageFactory();
+
+	public XMLCatalogTableViewer(Composite parent, String[] columnProperties) {
+		super(parent, SWT.FULL_SELECTION);
+
+		Table table = getTable();
+		table.setLinesVisible(true);
+		table.setHeaderVisible(true);
+		table.setLinesVisible(true);
+
+		TableLayout layout = new TableLayout();
+		for (int i = 0; i < columnProperties.length; i++) {
+			TableColumn column = new TableColumn(table, i);
+			column.setText(columnProperties[i]);
+			column.setAlignment(SWT.LEFT);
+			layout.addColumnData(new ColumnWeightData(50, true));
+		}
+		table.setLayout(layout);
+		table.setLinesVisible(false);
+
+		setColumnProperties(columnProperties);
+
+		setContentProvider(new CatalogEntryContentProvider());
+		setLabelProvider(new CatalogEntryLabelProvider());
+	}
+
+	public Collection getXMLCatalogEntries() {
+		return null;
+	}
+
+
+	public void menuAboutToShow(IMenuManager menuManager) {
+		Action action = new Action("hello") { //$NON-NLS-1$
+			public void run() {
+				System.out.println("run!"); //$NON-NLS-1$
+			}
+		};
+		menuManager.add(action);
+	}
+
+	public void setFilterExtensions(String[] extensions) {
+		resetFilters();
+		addFilter(new XMLCatalogTableViewerFilter(extensions));
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/dnd/DragNodeCommand.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/dnd/DragNodeCommand.java
new file mode 100644
index 0000000..736fc55
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/dnd/DragNodeCommand.java
@@ -0,0 +1,312 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.dnd;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.swt.dnd.DND;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.wst.common.ui.internal.dnd.DefaultDragAndDropCommand;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.eclipse.wst.xml.ui.internal.Logger;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+import org.w3c.dom.Attr;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+public class DragNodeCommand extends DefaultDragAndDropCommand {
+	private List fSelections;
+	private TreeViewer fTreeViewer;
+
+	public DragNodeCommand(Object target, float location, int operations, int operation, Collection sources, TreeViewer treeViewer) {
+		super(target, location, operations, operation, sources);
+		fTreeViewer = treeViewer;
+		fSelections = new ArrayList();
+	}
+
+	private void beginModelChange(Node node, boolean batchUpdate) {
+		IStructuredModel structuredModel = getStructuredModel(node);
+		if (structuredModel != null) {
+			String undoDesc = new String();
+			if (getOperation() == DND.DROP_MOVE) {
+				undoDesc = XMLUIMessages.DragNodeCommand_0;
+			}
+			else if (getOperation() == DND.DROP_COPY) {
+				undoDesc = XMLUIMessages.DragNodeCommand_1;
+			}
+
+			structuredModel.beginRecording(this, undoDesc);
+			if (batchUpdate) {
+				// structuredModel.aboutToChangeModel();
+			}
+		}
+	}
+
+	public boolean canExecute() {
+		return executeHelper(true);
+	}
+
+	private boolean doModify(Node source, Node parentNode, Node refChild, boolean testOnly) {
+		boolean result = false;
+		if (source.getNodeType() == Node.ATTRIBUTE_NODE) {
+			Attr sourceAttribute = (Attr) source;
+			Element sourceAttributeOwnerElement = sourceAttribute.getOwnerElement();
+			if ((parentNode.getNodeType() == Node.ELEMENT_NODE) && (sourceAttributeOwnerElement != parentNode)) {
+				result = true;
+				if (!testOnly) {
+					try {
+						if (getOperation() == DND.DROP_MOVE) {
+							Element targetElement = (Element) parentNode;
+							sourceAttributeOwnerElement.removeAttributeNode(sourceAttribute);
+							targetElement.getAttributes().setNamedItem(sourceAttribute);
+							fSelections.add(sourceAttribute);
+							}
+						else if (getOperation() == DND.DROP_COPY) {
+							Attr cloneAttribute = (Attr) sourceAttribute.cloneNode(false);
+							Element targetElement = (Element) parentNode;
+							targetElement.getAttributes().setNamedItem(cloneAttribute);
+							fSelections.add(cloneAttribute);
+						}
+					}
+					catch (Exception e) {
+						Logger.log(Logger.WARNING_DEBUG, e.getMessage(), e);
+					}
+				}
+			}
+		}
+		else {
+			if (((parentNode.getNodeType() == Node.ELEMENT_NODE) || (parentNode.getNodeType() == Node.DOCUMENT_NODE)) && !(refChild instanceof Attr)) {
+				result = true;
+
+				if (!testOnly) {
+					try {
+						if (isAncestor(source, parentNode)) {
+							// System.out.println("can not perform this drag drop
+							// operation.... todo... pop up dialog");
+						}
+						else {
+							// defect 221055 this test is required or else the
+							// node will
+							// be removed from the tree and the insert will fail
+							if (source != refChild) {
+								if (getOperation() == DND.DROP_MOVE) {
+									Node oldParent = source.getParentNode();
+									Node oldSibling = source.getNextSibling();
+									oldParent.removeChild(source);
+									try {
+										parentNode.insertBefore(source, refChild);
+									} catch (DOMException e) {
+										// bug151692 - if unable to move node to new location, reinsert back to old location
+										oldParent.insertBefore(source, oldSibling);
+									}
+									fSelections.add(source);
+								}
+								else if (getOperation() == DND.DROP_COPY) {
+									Node nodeClone = source.cloneNode(true);
+									parentNode.insertBefore(nodeClone, refChild);
+									fSelections.add(nodeClone);
+								}
+							}
+						}
+					}
+					catch (Exception e) {
+						Logger.log(Logger.WARNING_DEBUG, e.getMessage(), e);
+					}
+				}
+			}
+		}
+		return result;
+	}
+
+	private void endModelChange(Node node, boolean batchUpdate) {
+		IStructuredModel structuredModel = getStructuredModel(node);
+		if (structuredModel != null) {
+			structuredModel.endRecording(this);
+			if (batchUpdate) {
+				// structuredModel.changedModel();
+			}
+		}
+	}
+
+	public void execute() {
+		executeHelper(false);
+
+		// Make our selection if the treeViewer != null
+		if (fTreeViewer != null) {
+			StructuredSelection structuredSelection = new StructuredSelection(fSelections);
+			fTreeViewer.setSelection(structuredSelection);
+		}
+	}
+
+	private boolean executeHelper(boolean testOnly) {
+		boolean result = true;
+		if (target instanceof Node) {
+			Node targetNode = (Node) target;
+			if (!testOnly && fTreeViewer != null && !validateEdit(getStructuredModel(targetNode), fTreeViewer.getControl().getShell()))
+				return false;
+
+			Node parentNode = getParentForDropPosition(targetNode);
+			Node refChild = getRefChild(targetNode);
+
+			Vector sourcesList = new Vector();
+			sourcesList.addAll(sources);
+
+			removeMemberDescendants(sourcesList);
+			boolean performBatchUpdate = sourcesList.size() > 5;
+
+			if (!testOnly) {
+				beginModelChange(targetNode, performBatchUpdate);
+			}
+			for (Iterator i = sourcesList.iterator(); i.hasNext();) {
+				Object source = i.next();
+				if (source instanceof Node) {
+					if (!((refChild == null) && (targetNode instanceof Attr)) && (parentNode != null)) {
+						result = doModify((Node) source, parentNode, refChild, testOnly);
+					}
+					else {
+						result = false;
+					}
+					if (!result) {
+						break;
+					}
+				}
+			}
+			if (!testOnly) {
+				endModelChange(targetNode, performBatchUpdate);
+			}
+		}
+		else {
+			result = false;
+		}
+		return result;
+	}
+
+	/**
+	 * Checks that the resource backing the model is writeable utilizing <code>validateEdit</code>
+	 * on a given <tt>IWorkspace</tt>.
+	 * 
+	 * @param model the model to be checked
+	 * @param context the shell context for which <code>validateEdit</code> will be run
+	 * @return boolean result of checking <code>validateEdit</code>. If the resource is unwriteable, <code>status.isOK()</code>
+	 * will return true; otherwise, false.
+	 */
+	private boolean validateEdit(IStructuredModel model, Shell context) {
+		if (model != null && model.getBaseLocation() != null) {
+			IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(model.getBaseLocation()));
+			return !file.isAccessible() || ResourcesPlugin.getWorkspace().validateEdit(new IFile[] {file}, context).isOK();
+		}
+		return false; //$NON-NLS-1$
+	}
+
+	public int getFeedback() {
+		int result = DND.FEEDBACK_SELECT;
+		if (location > 0.75) {
+			result = DND.FEEDBACK_INSERT_AFTER;
+		}
+		else if (location < 0.25) {
+			result = DND.FEEDBACK_INSERT_BEFORE;
+		}
+		return result;
+	}
+
+	private Node getParentForDropPosition(Node node) {
+		Node result = null;
+
+		int feedback = getFeedback();
+		if (feedback == DND.FEEDBACK_SELECT) {
+			result = node;
+		}
+		else {
+			result = getParentOrOwner(node);
+		}
+		return result;
+	}
+
+
+	private Node getParentOrOwner(Node node) {
+		return (node.getNodeType() == Node.ATTRIBUTE_NODE) ? ((Attr) node).getOwnerElement() : node.getParentNode();
+	}
+
+
+	private Node getRefChild(Node node) {
+		Node result = null;
+
+		int feedback = getFeedback();
+
+		if (feedback == DND.FEEDBACK_INSERT_BEFORE) {
+			result = node;
+		}
+		else if (feedback == DND.FEEDBACK_INSERT_AFTER) {
+			result = node.getNextSibling();
+		}
+		return result;
+	}
+
+	private IStructuredModel getStructuredModel(Node node) {
+		IStructuredModel result = null;
+		if (node instanceof IDOMNode) {
+			result = ((IDOMNode) node).getModel();
+		}
+		return result;
+	}
+
+	// returns true if a is an ancestore of b
+	//
+	private boolean isAncestor(Node a, Node b) {
+		boolean result = false;
+		for (Node parent = b; parent != null; parent = parent.getParentNode()) {
+			if (parent == a) {
+				result = true;
+				break;
+			}
+		}
+		return result;
+	}
+
+
+	/**
+	 * This method removes members of the list that have ancestors that are
+	 * also members of the list.
+	 */
+	private void removeMemberDescendants(List list) {
+		Hashtable table = new Hashtable();
+		for (Iterator i = list.iterator(); i.hasNext();) {
+			Object node = i.next();
+			table.put(node, node);
+		}
+
+		for (int i = list.size() - 1; i >= 0; i--) {
+			Object node =  list.get(i); 
+			if (node instanceof Node){
+				for (Node parent = getParentOrOwner((Node)node); parent != null; parent = getParentOrOwner(parent)) {
+					if (table.get(parent) != null) {
+						list.remove(i);
+						break;
+					}
+				}
+			}
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/dnd/XMLDragAndDropManager.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/dnd/XMLDragAndDropManager.java
new file mode 100644
index 0000000..48097a8
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/dnd/XMLDragAndDropManager.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+
+
+package org.eclipse.wst.xml.ui.internal.dnd;
+
+import java.util.Collection;
+
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.swt.dnd.DND;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.wst.common.ui.internal.dnd.DragAndDropCommand;
+import org.eclipse.wst.common.ui.internal.dnd.DragAndDropManager;
+import org.eclipse.wst.common.ui.internal.dnd.ObjectTransfer;
+import org.eclipse.wst.common.ui.internal.dnd.ViewerDragAdapter;
+import org.eclipse.wst.common.ui.internal.dnd.ViewerDropAdapter;
+import org.w3c.dom.Node;
+
+public class XMLDragAndDropManager implements DragAndDropManager {
+	private TreeViewer fViewer;
+
+	public static void addDragAndDropSupport(TreeViewer viewer) {
+		int dndOperations = DND.DROP_COPY | DND.DROP_MOVE | DND.DROP_LINK;
+		Transfer[] transfers = new Transfer[]{ObjectTransfer.getInstance()};
+		viewer.addDragSupport(dndOperations, transfers, new ViewerDragAdapter(viewer));
+		viewer.addDropSupport(dndOperations, transfers, new ViewerDropAdapter(viewer, new XMLDragAndDropManager(viewer)));
+	}
+
+	public XMLDragAndDropManager() {
+		super();
+	}
+
+	public XMLDragAndDropManager(TreeViewer viewer) {
+		fViewer = viewer;
+	}
+
+	public DragAndDropCommand createCommand(Object target, float location, int operations, int operation, Collection source) {
+		DragAndDropCommand result = null;
+		if (target instanceof Node) {
+			result = new DragNodeCommand(target, location, operations, operation, source, fViewer);
+		}
+		return result;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/doubleclick/XMLDoubleClickStrategy.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/doubleclick/XMLDoubleClickStrategy.java
new file mode 100644
index 0000000..4d35d87
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/doubleclick/XMLDoubleClickStrategy.java
@@ -0,0 +1,324 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.doubleclick;
+
+import org.eclipse.jface.text.DefaultTextDoubleClickStrategy;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+import org.w3c.dom.Node;
+
+
+public class XMLDoubleClickStrategy extends DefaultTextDoubleClickStrategy {
+	protected static final char DOUBLE_QUOTE = '\"';
+	protected static final char SINGLE_QUOTE = '\'';
+	protected static final char SPACE = ' ';
+	protected int fCaretPosition = -1;
+	protected int fDoubleClickCount = 0;
+	protected Node fNode = null;
+	protected IStructuredDocumentRegion fStructuredDocumentRegion = null;
+	protected String fStructuredDocumentRegionText = ""; //$NON-NLS-1$
+	protected IStructuredModel fStructuredModel = null;
+	protected ITextViewer fTextViewer;
+	protected ITextRegion fTextRegion = null;
+
+	public void doubleClicked(ITextViewer textViewer) {
+			fTextViewer = textViewer;
+			try {
+				fStructuredModel = StructuredModelManager.getModelManager().getExistingModelForRead(fTextViewer.getDocument());
+
+				if (fStructuredModel != null) {
+					int caretPosition = textViewer.getSelectedRange().x;
+					if (caretPosition < 0) {
+						return;
+					}
+
+					fNode = (Node) fStructuredModel.getIndexedRegion(caretPosition);
+					if (fNode == null) {
+						return;
+					}
+
+					updateDoubleClickCount(caretPosition);
+					updateStructuredDocumentRegion();
+					updateTextRegion();
+
+					if (fNode.getNodeType() == Node.TEXT_NODE) {
+						processTextDoubleClicked();
+					}
+					else {
+						processElementDoubleClicked();
+					}
+				}
+			}
+			finally {
+				if (fStructuredModel != null) {
+					fStructuredModel.releaseFromRead();
+				}
+			}
+	}
+
+	protected Point getWord(String string, int cursor) {
+		if (string == null) {
+			return null;
+		}
+
+		int wordStart = 0;
+		int wordEnd = string.length();
+
+		wordStart = string.lastIndexOf(SPACE, cursor - 1);
+		int temp = string.lastIndexOf(SINGLE_QUOTE, cursor - 1);
+		wordStart = Math.max(wordStart, temp);
+		temp = string.lastIndexOf(DOUBLE_QUOTE, cursor - 1);
+		wordStart = Math.max(wordStart, temp);
+		if (wordStart == -1) {
+			wordStart = cursor;
+		}
+		else {
+			wordStart++;
+		}
+
+		wordEnd = string.indexOf(SPACE, cursor);
+		if (wordEnd == -1) {
+			wordEnd = string.length();
+		}
+		temp = string.indexOf(SINGLE_QUOTE, cursor);
+		if (temp == -1) {
+			temp = string.length();
+		}
+		wordEnd = Math.min(wordEnd, temp);
+		temp = string.indexOf(DOUBLE_QUOTE, cursor);
+		if (temp == -1) {
+			temp = string.length();
+		}
+		wordEnd = Math.min(wordEnd, temp);
+		if (wordEnd == string.length()) {
+			wordEnd = cursor;
+		}
+
+		if ((wordStart == wordEnd) && !isQuoted(string)) {
+			wordStart = 0;
+			wordEnd = string.length();
+		}
+
+		return new Point(wordStart, wordEnd);
+	}
+
+	protected boolean isQuoted(String string) {
+		if ((string == null) || (string.length() < 2)) {
+			return false;
+		}
+
+		int lastIndex = string.length() - 1;
+		char firstChar = string.charAt(0);
+		char lastChar = string.charAt(lastIndex);
+
+		return (((firstChar == SINGLE_QUOTE) && (lastChar == SINGLE_QUOTE)) || ((firstChar == DOUBLE_QUOTE) && (lastChar == DOUBLE_QUOTE)));
+	}
+
+	protected void processElementAttrEqualsDoubleClicked2Times() {
+		int prevRegionOffset = fStructuredDocumentRegion.getStartOffset(fTextRegion) - 1;
+		ITextRegion prevRegion = fStructuredDocumentRegion.getRegionAtCharacterOffset(prevRegionOffset);
+		int nextRegionOffset = fStructuredDocumentRegion.getEndOffset(fTextRegion);
+		ITextRegion nextRegion = fStructuredDocumentRegion.getRegionAtCharacterOffset(nextRegionOffset);
+
+		if ((prevRegion != null) && (prevRegion.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) && (nextRegion != null) && (nextRegion.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE)) {
+			fTextViewer.setSelectedRange(fStructuredDocumentRegion.getStartOffset(prevRegion), nextRegion.getTextEnd() - prevRegion.getStart());
+		}
+	}
+
+	protected void processElementAttrNameDoubleClicked2Times() {
+		int nextRegionOffset = fStructuredDocumentRegion.getEndOffset(fTextRegion);
+		ITextRegion nextRegion = fStructuredDocumentRegion.getRegionAtCharacterOffset(nextRegionOffset);
+
+		if (nextRegion != null) {
+			nextRegionOffset = fStructuredDocumentRegion.getEndOffset(nextRegion);
+			nextRegion = fStructuredDocumentRegion.getRegionAtCharacterOffset(nextRegionOffset);
+			if ((nextRegion != null) && (nextRegion.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE)) {
+				fTextViewer.setSelectedRange(fStructuredDocumentRegion.getStartOffset(fTextRegion), nextRegion.getTextEnd() - fTextRegion.getStart());
+			}
+			else {
+				// attribute has no value
+				fTextViewer.setSelectedRange(fStructuredDocumentRegion.getStart(), fStructuredDocumentRegion.getLength());
+				fDoubleClickCount = 0;
+			}
+		}
+	}
+
+	protected void processElementAttrValueDoubleClicked() {
+		String regionText = fStructuredDocumentRegion.getText(fTextRegion);
+
+		if (fDoubleClickCount == 1) {
+			Point word = getWord(regionText, fCaretPosition - fStructuredDocumentRegion.getStartOffset(fTextRegion));
+			if (word.x == word.y) { // no word found; select whole region
+				fTextViewer.setSelectedRange(fStructuredDocumentRegion.getStartOffset(fTextRegion), regionText.length());
+				fDoubleClickCount++;
+			}
+			else {
+				fTextViewer.setSelectedRange(fStructuredDocumentRegion.getStartOffset(fTextRegion) + word.x, word.y - word.x);
+			}
+		}
+		else if (fDoubleClickCount == 2) {
+			if (isQuoted(regionText)) {
+				// ==> // Point word = getWord(regionText, fCaretPosition -
+				// fStructuredDocumentRegion.getStartOffset(fTextRegion));
+				fTextViewer.setSelectedRange(fStructuredDocumentRegion.getStartOffset(fTextRegion), regionText.length());
+			}
+			else {
+				processElementAttrValueDoubleClicked2Times();
+			}
+		}
+		else if (fDoubleClickCount == 3) {
+			if (isQuoted(regionText)) {
+				processElementAttrValueDoubleClicked2Times();
+			}
+			else {
+				fTextViewer.setSelectedRange(fStructuredDocumentRegion.getStart(), fStructuredDocumentRegion.getLength());
+				fDoubleClickCount = 0;
+			}
+		}
+		else { // fDoubleClickCount == 4
+			fTextViewer.setSelectedRange(fStructuredDocumentRegion.getStart(), fStructuredDocumentRegion.getLength());
+			fDoubleClickCount = 0;
+		}
+	}
+
+	protected void processElementAttrValueDoubleClicked2Times() {
+		int prevRegionOffset = fStructuredDocumentRegion.getStartOffset(fTextRegion) - 1;
+		ITextRegion prevRegion = fStructuredDocumentRegion.getRegionAtCharacterOffset(prevRegionOffset);
+
+		if (prevRegion != null) {
+			prevRegionOffset = fStructuredDocumentRegion.getStartOffset(prevRegion) - 1;
+			prevRegion = fStructuredDocumentRegion.getRegionAtCharacterOffset(prevRegionOffset);
+			if ((prevRegion != null) && (prevRegion.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME)) {
+				fTextViewer.setSelectedRange(fStructuredDocumentRegion.getStartOffset(prevRegion), fTextRegion.getTextEnd() - prevRegion.getStart());
+			}
+		}
+	}
+
+	protected void processElementDoubleClicked() {
+		if (fTextRegion.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
+			processElementAttrValueDoubleClicked(); // special handling for
+		}
+		else {
+			if (fDoubleClickCount == 1) {
+				fTextViewer.setSelectedRange(fStructuredDocumentRegion.getStart() + fTextRegion.getStart(), fTextRegion.getTextLength());
+			}
+			else if (fDoubleClickCount == 2) {
+				if (fTextRegion.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) {
+					processElementAttrNameDoubleClicked2Times();
+				}
+				else if (fTextRegion.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_EQUALS) {
+					processElementAttrEqualsDoubleClicked2Times();
+				}
+				else {
+					fTextViewer.setSelectedRange(fStructuredDocumentRegion.getStart(), fStructuredDocumentRegion.getLength());
+					fDoubleClickCount = 0;
+				}
+			}
+			else { // fDoubleClickCount == 3
+				fTextViewer.setSelectedRange(fStructuredDocumentRegion.getStart(), fStructuredDocumentRegion.getLength());
+				fDoubleClickCount = 0;
+			}
+		}
+	}
+
+	protected void processTextDoubleClicked() {
+		if (fDoubleClickCount == 1) {
+			super.doubleClicked(fTextViewer);
+
+			Point selectedRange = fTextViewer.getSelectedRange();
+			if ((selectedRange.x == fStructuredDocumentRegion.getStartOffset(fTextRegion)) && (selectedRange.y == fTextRegion.getTextLength())) {
+				// only one word in region, skip one level of double click
+				// selection
+				fDoubleClickCount++;
+			}
+		}
+		else if (fDoubleClickCount == 2) {
+			if (fTextRegion.getType() == DOMRegionContext.UNDEFINED) {
+				fTextViewer.setSelectedRange(fStructuredDocumentRegion.getStart(), fStructuredDocumentRegion.getLength());
+				fDoubleClickCount = 0;
+			}
+			else {
+				if (isQuoted(fStructuredDocumentRegion.getFullText(fTextRegion))) {
+					fTextViewer.setSelectedRange(fStructuredDocumentRegion.getStartOffset(fTextRegion) + 1, fTextRegion.getTextLength() - 2);
+				}
+				else {
+					fTextViewer.setSelectedRange(fStructuredDocumentRegion.getStartOffset(fTextRegion), fTextRegion.getTextLength());
+				}
+			}
+		}
+		else {
+			if ((fDoubleClickCount == 3) && isQuoted(fStructuredDocumentRegion.getFullText(fTextRegion))) {
+				fTextViewer.setSelectedRange(fStructuredDocumentRegion.getStartOffset(fTextRegion), fTextRegion.getTextLength());
+			}
+			else {
+				if ((fDoubleClickCount == 3) && isQuoted(fStructuredDocumentRegionText)) {
+					fTextViewer.setSelectedRange(fStructuredDocumentRegion.getStart() + 1, fStructuredDocumentRegion.getLength() - 2);
+				}
+				else {
+					fTextViewer.setSelectedRange(fStructuredDocumentRegion.getStart(), fStructuredDocumentRegion.getLength());
+					fDoubleClickCount = 0;
+				}
+			}
+		}
+	}
+
+	public void setModel(IStructuredModel structuredModel) {
+		fStructuredModel = structuredModel;
+	}
+
+	protected void updateDoubleClickCount(int caretPosition) {
+		if (fCaretPosition == caretPosition) {
+			if (fStructuredDocumentRegion != null) {
+				fDoubleClickCount++;
+			}
+			else {
+				fDoubleClickCount = 1;
+			}
+		}
+		else {
+			fCaretPosition = caretPosition;
+			fDoubleClickCount = 1;
+		}
+	}
+
+	protected void updateStructuredDocumentRegion() {
+		fStructuredDocumentRegion = fStructuredModel.getStructuredDocument().getRegionAtCharacterOffset(fCaretPosition);
+		if (fStructuredDocumentRegion != null) {
+			fStructuredDocumentRegionText = fStructuredDocumentRegion.getText();
+		}
+		else {
+			fStructuredDocumentRegionText = ""; //$NON-NLS-1$
+		}
+	}
+
+	protected void updateTextRegion() {
+		if (fStructuredDocumentRegion != null) {
+			fTextRegion = fStructuredDocumentRegion.getRegionAtCharacterOffset(fCaretPosition);
+			// if fTextRegion is null, it means we are at just past the last
+			// fStructuredDocumentRegion,
+			// at the very end of the document, so we'll use the last text
+			// region in the document
+			if (fTextRegion == null) {
+				fTextRegion = fStructuredDocumentRegion.getRegionAtCharacterOffset(fCaretPosition - 1);
+			}
+		}
+		else {
+			fTextRegion = null;
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/editor/CMImageUtil.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/editor/CMImageUtil.java
new file mode 100644
index 0000000..7fa80c8
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/editor/CMImageUtil.java
@@ -0,0 +1,134 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.editor;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.resource.ImageRegistry;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.wst.sse.core.internal.util.JarUtilities;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.modelquery.ModelQueryUtil;
+import org.eclipse.wst.xml.ui.internal.XMLUIPlugin;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+/**
+ * @author nsd
+ */
+public class CMImageUtil {
+
+	public static String SMALL_ICON_URL = "small-icon"; //$NON-NLS-1$
+
+	public static CMNode getDeclaration(Node node) {
+		CMNode decl = null;
+		ModelQuery mq = null;
+		switch (node.getNodeType()) {
+			case Node.ATTRIBUTE_NODE : {
+				mq = ModelQueryUtil.getModelQuery(((Attr) node).getOwnerDocument());
+				decl = mq.getCMAttributeDeclaration((Attr) node);
+			}
+				break;
+			case Node.ELEMENT_NODE : {
+				mq = ModelQueryUtil.getModelQuery(node.getOwnerDocument());
+				decl = mq.getCMElementDeclaration((Element) node);
+			}
+				break;
+		}
+		return decl;
+	}
+
+	public static Image getImage(CMNode cmnode) {
+		if (cmnode == null) {
+			return null;
+		}
+		Image image = null;
+		// cache CM-specified images with the XML UI plugin
+		String imageURLString = (String) cmnode.getProperty(SMALL_ICON_URL);
+		if ((imageURLString != null) && (imageURLString.length() > 0)) {
+			/* First ensure that the descriptor itself is cached */
+			ImageDescriptor imageDescriptor = getImageDescriptor(imageURLString);
+			if (imageDescriptor != null) {
+				/*
+				 * Then obtain the image from the registry so that it is both
+				 * cached and properly disposed of later
+				 */
+				image = getImageRegistry().get(imageURLString);
+			}
+		}
+		return image;
+	}
+
+	public static ImageDescriptor getImageDescriptor(CMNode cmnode) {
+		if (cmnode == null) {
+			return null;
+		}
+		// cache CM-specified images with the XML UI plugin
+		String imageURLString = (String) cmnode.getProperty(SMALL_ICON_URL);
+		ImageDescriptor descriptor = null;
+		if ((imageURLString != null) && (imageURLString.length() > 0)) {
+			descriptor = getImageDescriptor(imageURLString);
+		}
+		return descriptor;
+	}
+
+	private static ImageDescriptor getImageDescriptor(String imageURLString) {
+		ImageDescriptor descriptor = getImageRegistry().getDescriptor(imageURLString);
+		if (descriptor == null) {
+			try {
+				URL imageURL = new URL(imageURLString);
+				InputStream inputStream = JarUtilities.getInputStream(imageURL);
+				try {
+					if (inputStream != null) {
+						ImageData data = new ImageData(inputStream);
+						descriptor = ImageDescriptor.createFromImageData(data);
+						getImageRegistry().put(imageURLString, descriptor);
+					}
+				}
+				catch (SWTException e) {
+					/*
+					 * There was a problem loading image from stream
+					 * (corrupt, missing, etc.)
+					 */
+					if (inputStream != null)
+						inputStream.close();
+				}
+			}
+			catch (MalformedURLException e) {
+				descriptor = null;
+			}
+			catch (IOException e) {
+				descriptor = null;
+			}
+		}
+		return descriptor;
+	}
+
+	private static final ImageRegistry getImageRegistry() {
+		return XMLUIPlugin.getInstance().getImageRegistry();
+	}
+
+	/**
+	 * 
+	 */
+	private CMImageUtil() {
+		super();
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/editor/DOMSelectionConvertorFactory.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/editor/DOMSelectionConvertorFactory.java
new file mode 100644
index 0000000..0f0988b
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/editor/DOMSelectionConvertorFactory.java
@@ -0,0 +1,86 @@
+/*******************************************************************************

+ * Copyright (c) 2008 IBM Corporation and others.

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ * 

+ * Contributors:

+ *     IBM Corporation - initial API and implementation

+ *******************************************************************************/

+

+package org.eclipse.wst.xml.ui.internal.editor;

+

+import org.eclipse.core.runtime.IAdapterFactory;

+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;

+import org.eclipse.wst.sse.ui.internal.editor.SelectionConvertor;

+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMAttr;

+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;

+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;

+import org.w3c.dom.NamedNodeMap;

+

+/**

+ * @author nitin

+ * 

+ */

+public class DOMSelectionConvertorFactory implements IAdapterFactory {

+

+	private static final Class[] ADAPTER_LIST = new Class[]{SelectionConvertor.class};

+

+	private static class XMLSelectionConvertor extends SelectionConvertor {

+		/* (non-Javadoc)

+		 * @see org.eclipse.wst.sse.ui.internal.editor.SelectionConvertor#getElements(org.eclipse.wst.sse.core.internal.provisional.IStructuredModel, int, int)

+		 */

+		public Object[] getElements(IStructuredModel model, int start, int end) {

+			Object[] objects = super.getElements(model, start, end);

+			// narrow single selected Elements into Attrs if possible

+			if (objects.length == 1) {

+				if (objects[0] instanceof IDOMNode) {

+					IDOMNode node = (IDOMNode) objects[0];

+					NamedNodeMap attributes = node.getAttributes();

+					if (attributes != null) {

+						for (int i = 0; i < attributes.getLength(); i++) {

+							IDOMAttr attribute = (IDOMAttr) attributes.item(i);

+							if (attribute.contains(start) && attribute.contains(end)) {

+								objects[0] = attribute;

+								break;

+							}

+						}

+					}

+				}

+			}

+			return objects;

+		}

+	}

+

+	private static final Object selectionConvertor = new XMLSelectionConvertor();

+

+	/**

+	 * 

+	 */

+	public DOMSelectionConvertorFactory() {

+	}

+

+	/*

+	 * (non-Javadoc)

+	 * 

+	 * @see

+	 * org.eclipse.core.runtime.IAdapterFactory#getAdapter(java.lang.Object,

+	 * java.lang.Class)

+	 */

+	public Object getAdapter(Object adaptableObject, Class adapterType) {

+		if (adaptableObject instanceof IDOMModel && SelectionConvertor.class.equals(adapterType))

+			return selectionConvertor;

+		return null;

+	}

+

+	/*

+	 * (non-Javadoc)

+	 * 

+	 * @see org.eclipse.core.runtime.IAdapterFactory#getAdapterList()

+	 */

+	public Class[] getAdapterList() {

+		return ADAPTER_LIST;

+	}

+

+}

diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/editor/IHelpContextIds.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/editor/IHelpContextIds.java
new file mode 100644
index 0000000..f7542e3
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/editor/IHelpContextIds.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2009 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.editor;
+
+import org.eclipse.wst.xml.ui.internal.XMLUIPlugin;
+
+/**
+ * Help context ids for the XML Source Editor.
+ * <p>
+ * This interface contains constants only; it is not intended to be
+ * implemented.
+ * </p>
+ * 
+ */
+public interface IHelpContextIds {
+	// org.eclipse.wst.xml.ui.
+	public static final String PREFIX = XMLUIPlugin.ID + "."; //$NON-NLS-1$
+
+	// figured out on the fly
+	// // XML Source page editor
+	// public static final String XML_SOURCEVIEW_HELPID =
+	// ContentTypeIdForXML.ContentTypeID_XML +"_source_HelpId"; //$NON-NLS-1$
+
+	// XML Files Preference page
+	public static final String XML_PREFWEBX_FILES_HELPID = PREFIX + "webx0060"; //$NON-NLS-1$
+	// XML Source Preference page
+	public static final String XML_PREFWEBX_SOURCE_HELPID = PREFIX + "webx0061"; //$NON-NLS-1$
+	// XML Styles Preference page
+	public static final String XML_PREFWEBX_STYLES_HELPID = PREFIX + "webx0062"; //$NON-NLS-1$
+	// XML Templates Preference page
+	public static final String XML_PREFWEBX_TEMPLATES_HELPID = PREFIX + "webx0063"; //$NON-NLS-1$
+    // XML Validator Preference page
+    public static final String XML_PREFWEBX_VALIDATOR_HELPID = PREFIX + "webx0064"; //$NON-NLS-1$
+
+	// XML Cleanup dialog
+	public static final String CLEANUP_XML_HELPID = PREFIX + "xmlm1200"; //$NON-NLS-1$
+
+	// XML New File Wizard - Template Page
+	public static final String XML_NEWWIZARD_TEMPLATE_HELPID = PREFIX + "xmlw0010"; //$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/editor/XMLEditorPluginImageHelper.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/editor/XMLEditorPluginImageHelper.java
new file mode 100644
index 0000000..73b6736
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/editor/XMLEditorPluginImageHelper.java
@@ -0,0 +1,159 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.editor;
+
+import java.util.HashMap;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.resource.ImageRegistry;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.eclipse.wst.xml.ui.internal.XMLUIPlugin;
+
+
+/**
+ * Helper class to handle images provided by this plug-in.
+ * 
+ * NOTE: For internal use only. For images used externally, please use the
+ * Shared***ImageHelper class instead.
+ * 
+ * @author amywu
+ */
+public class XMLEditorPluginImageHelper {
+	private static XMLEditorPluginImageHelper instance = null;
+
+	/**
+	 * Gets the instance.
+	 * 
+	 * @return Returns a XMLEditorPluginImageHelper
+	 */
+	public synchronized static XMLEditorPluginImageHelper getInstance() {
+		if (instance == null) {
+			instance = new XMLEditorPluginImageHelper();
+		}
+		return instance;
+	}
+
+	// save a descriptor for each image
+	private HashMap fImageDescRegistry = null;
+	private final String PLUGINID = XMLUIPlugin.ID;
+
+	/**
+	 * Creates an image from the given resource and adds the image to the
+	 * image registry.
+	 * 
+	 * @param resource
+	 * @return Image
+	 */
+	private Image createImage(String resource) {
+		ImageDescriptor desc = getImageDescriptor(resource);
+		Image image = null;
+
+		if (desc != null) {
+			image = desc.createImage();
+			// dont add the missing image descriptor image to the image
+			// registry
+			if (!desc.equals(ImageDescriptor.getMissingImageDescriptor())) {
+				getImageRegistry().put(resource, image);
+			}
+		}
+		return image;
+	}
+
+	/**
+	 * Creates an image descriptor from the given imageFilePath and adds the
+	 * image descriptor to the image descriptor registry. If an image
+	 * descriptor could not be created, the default "missing" image descriptor
+	 * is returned but not added to the image descriptor registry.
+	 * 
+	 * @param imageFilePath
+	 * @return ImageDescriptor image descriptor for imageFilePath or default
+	 *         "missing" image descriptor if resource could not be found
+	 */
+	private ImageDescriptor createImageDescriptor(String imageFilePath) {
+		ImageDescriptor imageDescriptor = AbstractUIPlugin.imageDescriptorFromPlugin(PLUGINID, imageFilePath);
+		if (imageDescriptor != null) {
+			getImageDescriptorRegistry().put(imageFilePath, imageDescriptor);
+		}
+		else {
+			imageDescriptor = ImageDescriptor.getMissingImageDescriptor();
+		}
+
+		return imageDescriptor;
+	}
+
+	/**
+	 * Retrieves the image associated with resource from the image registry.
+	 * If the image cannot be retrieved, attempt to find and load the image at
+	 * the location specified in resource.
+	 * 
+	 * @param resource
+	 *            the image to retrieve
+	 * @return Image the image associated with resource or null if one could
+	 *         not be found
+	 */
+	public Image getImage(String resource) {
+		Image image = getImageRegistry().get(resource);
+		if (image == null) {
+			// create an image
+			image = createImage(resource);
+		}
+		return image;
+	}
+
+	/**
+	 * Retrieves the image descriptor associated with resource from the image
+	 * descriptor registry. If the image descriptor cannot be retrieved,
+	 * attempt to find and load the image descriptor at the location specified
+	 * in resource.
+	 * 
+	 * @param resource
+	 *            the image descriptor to retrieve
+	 * @return ImageDescriptor the image descriptor assocated with resource or
+	 *         the default "missing" image descriptor if one could not be
+	 *         found
+	 */
+	public ImageDescriptor getImageDescriptor(String resource) {
+		ImageDescriptor imageDescriptor = null;
+		Object o = getImageDescriptorRegistry().get(resource);
+		if (o == null) {
+			// create a descriptor
+			imageDescriptor = createImageDescriptor(resource);
+		}
+		else {
+			imageDescriptor = (ImageDescriptor) o;
+		}
+		return imageDescriptor;
+	}
+
+	/**
+	 * Returns the image descriptor registry for this plugin.
+	 * 
+	 * @return HashMap - image descriptor registry for this plugin
+	 */
+	private HashMap getImageDescriptorRegistry() {
+		if (fImageDescRegistry == null) {
+			fImageDescRegistry = new HashMap();
+		}
+		return fImageDescRegistry;
+	}
+
+	/**
+	 * Returns the image registry for this plugin.
+	 * 
+	 * @return ImageRegistry - image registry for this plugin
+	 */
+	private ImageRegistry getImageRegistry() {
+		return XMLUIPlugin.getDefault().getImageRegistry();
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/editor/XMLEditorPluginImages.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/editor/XMLEditorPluginImages.java
new file mode 100644
index 0000000..52c379a
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/editor/XMLEditorPluginImages.java
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.editor;
+
+/**
+ * Bundle of most images used by the XML Source Editor plug-in.
+ */
+public class XMLEditorPluginImages {
+
+	public static final String IMG_DTOOL_CONSTRAINOFF = "icons/full/dtool16/constrainoff.gif"; //$NON-NLS-1$
+	public static final String IMG_DTOOL_CONSTRAINON = "icons/full/dtool16/constrainon.gif"; //$NON-NLS-1$
+	public static final String IMG_DTOOL_RLDGRMR = "icons/full/dtool16/rldgrmr.gif"; //$NON-NLS-1$
+	public static final String IMG_DTOOL_VALIDATE = "icons/full/dtool16/validate.gif"; //$NON-NLS-1$
+	public static final String IMG_ETOOL_CONSTRAINOFF = "icons/full/etool16/constrainoff.gif"; //$NON-NLS-1$
+	public static final String IMG_ETOOL_CONSTRAINON = "icons/full/etool16/constrainon.gif"; //$NON-NLS-1$
+	public static final String IMG_ETOOL_RLDGRMR = "icons/full/etool16/rldgrmr.gif"; //$NON-NLS-1$
+	public static final String IMG_ETOOL_VALIDATE = "icons/full/etool16/validate.gif"; //$NON-NLS-1$
+	public static final String IMG_OBJ_ADD_CORRECTION = "icons/full/obj16/add_correction.gif"; //$NON-NLS-1$
+	public static final String IMG_OBJ_ATT_REQ_OBJ = "icons/full/obj16/att_req_obj.gif"; //$NON-NLS-1$
+
+	public static final String IMG_OBJ_ATTRIBUTE = "icons/full/obj16/attribute_obj.gif"; //$NON-NLS-1$
+	public static final String IMG_OBJ_CDATASECTION = "icons/full/obj16/cdatasection.gif"; //$NON-NLS-1$
+	public static final String IMG_OBJ_COMMENT = "icons/full/obj16/comment_obj.gif"; //$NON-NLS-1$
+	public static final String IMG_OBJ_CORRECTION_CHANGE = "icons/full/obj16/correction_change.gif"; //$NON-NLS-1$
+	public static final String IMG_OBJ_DOCTYPE = "icons/full/obj16/doctype.gif"; //$NON-NLS-1$
+	public static final String IMG_OBJ_DTDFILE = "icons/full/obj16/dtdfile.gif"; //$NON-NLS-1$	
+	public static final String IMG_OBJ_ELEMENT = "icons/full/obj16/element_obj.gif"; //$NON-NLS-1$
+	public static final String IMG_OBJ_ENTITY = "icons/full/obj16/entity.gif"; //$NON-NLS-1$
+	public static final String IMG_OBJ_ENTITY_REFERENCE = "icons/full/obj16/entity_reference.gif"; //$NON-NLS-1$
+	public static final String IMG_OBJ_ENUM = "icons/full/obj16/enum.gif"; //$NON-NLS-1$
+	public static final String IMG_OBJ_LOCAL_VARIABLE = "icons/full/obj16/localvariable_obj.gif"; //$NON-NLS-1$
+	public static final String IMG_OBJ_NOTATION = "icons/full/obj16/notation.gif"; //$NON-NLS-1$
+	public static final String IMG_OBJ_PROCESSINGINSTRUCTION = "icons/full/obj16/proinst_obj.gif"; //$NON-NLS-1$
+	public static final String IMG_OBJ_SORT = "icons/full/obj16/sort.gif"; //$NON-NLS-1$
+	public static final String IMG_OBJ_TAG_GENERIC = "icons/full/obj16/tag-generic.gif"; //$NON-NLS-1$
+	public static final String IMG_OBJ_TAG_GENERIC_DEEMPHASIZED = "icons/full/obj16/tag_generic_deemphasized_obj.gif"; //$NON-NLS-1$    
+	public static final String IMG_OBJ_TAG_GENERIC_EMPHASIZED = "icons/full/obj16/tag_generic_emphasized_obj.gif"; //$NON-NLS-1$        
+	public static final String IMG_OBJ_TAG_MACRO = "icons/full/obj16/tag-macro.gif"; //$NON-NLS-1$
+	public static final String IMG_OBJ_TXTEXT = "icons/full/obj16/text.gif"; //$NON-NLS-1$
+	public static final String IMG_OBJ_WARNING_OBJ = "icons/full/obj16/warning_obj.gif"; //$NON-NLS-1$
+	public static final String IMG_OBJ_XSDFILE = "icons/full/obj16/XSDFile.gif"; //$NON-NLS-1$
+
+	public static final String IMG_OVR_ERROR = "icons/full/ovr16/error_ovr.gif"; //$NON-NLS-1$
+	public static final String IMG_OVR_STALE_ERROR = "icons/full/ovr16/stale_error_ovr.gif"; //$NON-NLS-1$
+	public static final String IMG_OVR_WARN = "icons/full/ovr16/warn_ovr.gif"; //$NON-NLS-1$
+
+	public static final String IMG_WIZBAN_GENERATEXML = "icons/full/wizban/generatexml_wiz.png"; //$NON-NLS-1$
+	
+	public static final String IMG_OBJ_DEFAULT = "icons/full/obj16/default.gif"; //$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/handlers/AbstractSiblingNavigationHandler.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/handlers/AbstractSiblingNavigationHandler.java
new file mode 100644
index 0000000..4e0565b
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/handlers/AbstractSiblingNavigationHandler.java
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ * Copyright (c) 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.handlers;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.handlers.HandlerUtil;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Node;
+
+/**
+ * Provides navigation to next/previous DOM sibling Nodes
+ */
+abstract public class AbstractSiblingNavigationHandler extends AbstractHandler {
+
+	public Object execute(ExecutionEvent event) throws ExecutionException {
+		IEditorPart editor = HandlerUtil.getActiveEditor(event);
+		ITextEditor textEditor = null;
+		if (editor instanceof ITextEditor)
+			textEditor = (ITextEditor) editor;
+		else {
+			Object o = editor.getAdapter(ITextEditor.class);
+			if (o != null)
+				textEditor = (ITextEditor) o;
+		}
+		if (textEditor != null) {
+
+			ISelection selection = textEditor.getSelectionProvider().getSelection();
+			if (!selection.isEmpty() && selection instanceof IStructuredSelection) {
+				Object o = ((IStructuredSelection) selection).getFirstElement();
+				if (o instanceof Node) {
+					Node sibling = null;
+
+					if (((Node) o).getNodeType() == Node.ATTRIBUTE_NODE) {
+						o = ((Attr) o).getOwnerElement();
+					}
+					if (moveForward()) {
+						sibling = ((Node) o).getNextSibling();
+						while (sibling != null && sibling.getNodeType() == Node.TEXT_NODE && sibling.getNodeValue().trim().length() == 0) {
+							sibling = sibling.getNextSibling();
+						}
+						if (sibling == null) {
+							sibling = ((Node) o).getParentNode().getFirstChild();
+							while (sibling != null && sibling.getNodeType() == Node.TEXT_NODE && sibling.getNodeValue().trim().length() == 0) {
+								sibling = sibling.getNextSibling();
+							}
+						}
+					}
+					else {
+						sibling = ((Node) o).getPreviousSibling();
+						while (sibling != null && sibling.getNodeType() == Node.TEXT_NODE && sibling.getNodeValue().trim().length() == 0) {
+							sibling = sibling.getPreviousSibling();
+						}
+						if (sibling == null) {
+							sibling = ((Node) o).getParentNode().getLastChild();
+							while (sibling != null && sibling.getNodeType() == Node.TEXT_NODE && sibling.getNodeValue().trim().length() == 0) {
+								sibling = sibling.getPreviousSibling();
+							}
+						}
+					}
+
+					// The only child is a Text Node, go to the parent Node
+					if (((Node) o).getNodeType() == Node.TEXT_NODE && o.equals(sibling)) {
+						sibling = ((Node) o).getParentNode();
+					}
+
+
+					if (sibling != null) {
+						textEditor.getSelectionProvider().setSelection(new StructuredSelection(sibling));
+					}
+				}
+			}
+		}
+		return null;
+	}
+
+	abstract protected boolean moveForward();
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/handlers/AddBlockCommentHandler.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/handlers/AddBlockCommentHandler.java
new file mode 100644
index 0000000..475f37a
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/handlers/AddBlockCommentHandler.java
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Standards for Technology in Automotive Retail 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:
+ *     David Carver - initial API and implementation, bug 212330
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.handlers;
+
+import org.eclipse.core.commands.IHandler;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
+import org.eclipse.wst.xml.core.internal.document.CommentImpl;
+import org.eclipse.wst.xml.ui.internal.Logger;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+
+public class AddBlockCommentHandler extends CommentHandler implements IHandler {
+
+	public AddBlockCommentHandler() {
+		super();
+	}
+
+	void processAction(ITextEditor textEditor, IDocument document, ITextSelection textSelection) {
+		IStructuredModel model = StructuredModelManager.getModelManager().getExistingModelForEdit(document);
+		if (model != null) {
+			try {
+				IndexedRegion selectionStartIndexedRegion = model.getIndexedRegion(textSelection.getOffset());
+				IndexedRegion selectionEndIndexedRegion = model.getIndexedRegion(textSelection.getOffset() + textSelection.getLength());
+
+				if (selectionStartIndexedRegion == null) {
+					return;
+				}
+				if ((selectionEndIndexedRegion == null) && (textSelection.getLength() > 0)) {
+					selectionEndIndexedRegion = model.getIndexedRegion(textSelection.getOffset() + textSelection.getLength() - 1);
+				}
+				if (selectionEndIndexedRegion == null) {
+					return;
+				}
+
+				int openCommentOffset = selectionStartIndexedRegion.getStartOffset();
+				int closeCommentOffset = selectionEndIndexedRegion.getEndOffset() + OPEN_COMMENT.length();
+
+				if ((textSelection.getLength() == 0) && (selectionStartIndexedRegion instanceof CommentImpl)) {
+					return;
+				}
+
+				model.beginRecording(this, XMLUIMessages.AddBlockComment_tooltip);
+				model.aboutToChangeModel();
+
+				try {
+					document.replace(openCommentOffset, 0, OPEN_COMMENT);
+					document.replace(closeCommentOffset, 0, CLOSE_COMMENT);
+					super.removeOpenCloseComments(document, openCommentOffset + OPEN_COMMENT.length(), closeCommentOffset - openCommentOffset - CLOSE_COMMENT.length());
+				}
+				catch (BadLocationException e) {
+					Logger.log(Logger.WARNING_DEBUG, e.getMessage(), e);
+				}
+				finally {
+					model.changedModel();
+					model.endRecording(this);
+				}
+			}
+			finally {
+				model.releaseFromEdit();
+			}
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/handlers/CleanupdocumentHandler.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/handlers/CleanupdocumentHandler.java
new file mode 100644
index 0000000..0d46a0e
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/handlers/CleanupdocumentHandler.java
@@ -0,0 +1,119 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Standards for Technology in Automotive Retail 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:
+ *     David Carver - initial API and implementation - bug 212330 -
+ *                    Based off CleanupActionXMLDelegate
+ *******************************************************************************/
+
+package org.eclipse.wst.xml.ui.internal.handlers;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.commands.IHandler;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.custom.BusyIndicator;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.handlers.HandlerUtil;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.cleanup.IStructuredCleanupProcessor;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.ui.internal.SSEUIMessages;
+import org.eclipse.wst.xml.core.internal.cleanup.CleanupProcessorXML;
+import org.eclipse.wst.xml.ui.internal.actions.CleanupDialogXML;
+
+public class CleanupdocumentHandler extends AbstractHandler implements IHandler {
+	private IStructuredCleanupProcessor fCleanupProcessor;
+
+	public void dispose() {
+		// nulling out just in case
+		fCleanupProcessor = null;
+	}
+
+	public Object execute(ExecutionEvent event) throws ExecutionException {
+		IEditorPart editor = HandlerUtil.getActiveEditor(event);
+		ITextEditor textEditor = null;
+		if (editor instanceof ITextEditor)
+			textEditor = (ITextEditor) editor;
+		else {
+			Object o = editor.getAdapter(ITextEditor.class);
+			if (o != null)
+				textEditor = (ITextEditor) o;
+		}
+		if (textEditor != null) {
+			final ITextEditor finalTextEditor = textEditor;
+			Dialog cleanupDialog = new CleanupDialogXML(editor.getSite().getShell());
+			if (cleanupDialog.open() == Window.OK) {
+				// setup runnable
+				Runnable runnable = new Runnable() {
+					public void run() {
+						IStructuredCleanupProcessor cleanupProcessor = getCleanupProcessor();
+						if (cleanupProcessor != null) {
+							IStructuredModel model = null;
+							try {
+								model = StructuredModelManager.getModelManager().getExistingModelForEdit(finalTextEditor.getDocumentProvider().getDocument(finalTextEditor.getEditorInput()));
+								if (model != null) {
+									cleanupProcessor.cleanupModel(model);
+								}
+							}
+							finally {
+								if (model != null) {
+									model.releaseFromEdit();
+								}
+							}
+						}
+					}
+				};
+
+				// TODO: make independent of 'model'.
+				IStructuredModel model = null;
+				try {
+					model = StructuredModelManager.getModelManager().getExistingModelForEdit(textEditor.getDocumentProvider().getDocument(textEditor.getEditorInput()));
+					if (model != null) {
+						// begin recording
+						ITextSelection selection = (ITextSelection) textEditor.getSelectionProvider().getSelection();
+						model.beginRecording(this, SSEUIMessages.Cleanup_Document_UI_, SSEUIMessages.Cleanup_Document_UI_, selection.getOffset(), selection.getLength());
+
+						// tell the model that we are about to make a big
+						// model change
+						model.aboutToChangeModel();
+
+						// run
+						BusyIndicator.showWhile(textEditor.getEditorSite().getWorkbenchWindow().getShell().getDisplay(), runnable);
+					}
+				}
+				finally {
+					if (model != null) {
+						// tell the model that we are done with the big
+						// model
+						// change
+						model.changedModel();
+
+						// end recording
+						ITextSelection selection = (ITextSelection) textEditor.getSelectionProvider().getSelection();
+						model.endRecording(this, selection.getOffset(), selection.getLength());
+						model.releaseFromEdit();
+					}
+				}
+			}
+		}
+
+		return null;
+	}
+
+	IStructuredCleanupProcessor getCleanupProcessor() {
+		if (fCleanupProcessor == null) {
+			fCleanupProcessor = new CleanupProcessorXML();
+		}
+
+		return fCleanupProcessor;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/handlers/CollapseAllHandler.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/handlers/CollapseAllHandler.java
new file mode 100644
index 0000000..60c644b
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/handlers/CollapseAllHandler.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Standards for Technology in Automotive Retail 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:
+ *     David Carver - initial API and implementation, bug 212330
+ *     
+ *******************************************************************************/
+
+package org.eclipse.wst.xml.ui.internal.handlers;
+
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.commands.IHandler;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+public class CollapseAllHandler extends ExpandCollapseAllHandler implements IHandler {
+
+	/**
+	 * 
+	 */
+	public CollapseAllHandler() {
+		super();
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.core.commands.AbstractHandler#execute(org.eclipse.core.commands.ExecutionEvent)
+	 */
+	public Object execute(ExecutionEvent event) throws ExecutionException {
+		IEditorPart editorPart = HandlerUtil.getActiveEditor(event);
+		
+		viewer = getTableTreeViewerForEditorPart(editorPart);
+		
+		if (viewer != null) {
+			// temporarily set the visibility to false
+			// this has a HUGE performance benefit
+			boolean isVisible = viewer.getControl().getVisible();
+			viewer.getControl().setVisible(false);
+			viewer.collapseAll();
+
+			// restore the previous visibility state
+			// 
+			viewer.getControl().setVisible(isVisible);
+		}		
+		
+		return null;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/handlers/CommentHandler.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/handlers/CommentHandler.java
new file mode 100644
index 0000000..fb94ac6
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/handlers/CommentHandler.java
@@ -0,0 +1,116 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 Standards for Technology in Automotive Retail 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:
+ *     David Carver - initial API and implementation, bug 212330
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.handlers;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.commands.IHandler;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.text.TextSelection;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.handlers.HandlerUtil;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.ui.texteditor.ITextEditorExtension;
+import org.eclipse.ui.texteditor.ITextEditorExtension2;
+import org.eclipse.wst.xml.ui.internal.Logger;
+
+public class CommentHandler extends AbstractHandler implements IHandler {
+	static final String CLOSE_COMMENT = "-->"; //$NON-NLS-1$
+	static final String OPEN_COMMENT = "<!--"; //$NON-NLS-1$
+
+	public CommentHandler() {
+		super();
+	}
+
+	public Object execute(ExecutionEvent event) throws ExecutionException {
+		IEditorPart editor = HandlerUtil.getActiveEditor(event);
+		ITextEditor textEditor = null;
+		if (editor instanceof ITextEditor)
+			textEditor = (ITextEditor) editor;
+		else {
+			Object o = editor.getAdapter(ITextEditor.class);
+			if (o != null)
+				textEditor = (ITextEditor) o;
+		}
+		if (textEditor != null && validateEditorInput(textEditor)) {
+			IDocument document = textEditor.getDocumentProvider().getDocument(textEditor.getEditorInput());
+			if (document != null) {
+				// get current text selection
+				ITextSelection textSelection = getCurrentSelection(textEditor);
+				if (textSelection.isEmpty()) {
+					return null;
+				}
+
+				processAction(textEditor, document, textSelection);
+			}
+		}
+
+		return null;
+	}
+
+	protected boolean validateEditorInput(ITextEditor textEditor) {
+		if (textEditor instanceof ITextEditorExtension2)
+			return ((ITextEditorExtension2)textEditor).validateEditorInputState();
+		else if (textEditor instanceof ITextEditorExtension)
+			return ((ITextEditorExtension)textEditor).isEditorInputReadOnly();
+		else if (textEditor != null)
+			return textEditor.isEditable();
+		return true;
+		
+	}
+
+	protected ITextSelection getCurrentSelection(ITextEditor textEditor) {
+		ISelectionProvider provider = textEditor.getSelectionProvider();
+		if (provider != null) {
+			ISelection selection = provider.getSelection();
+			if (selection instanceof ITextSelection) {
+				return (ITextSelection) selection;
+			}
+		}
+		return TextSelection.emptySelection();
+	}
+
+	void processAction(ITextEditor textEditor, IDocument document, ITextSelection textSelection) {
+		// Implementations to over ride.
+	}
+
+	protected void removeOpenCloseComments(IDocument document, int offset, int length) {
+		try {
+			int adjusted_length = length;
+
+			// remove open comments
+			String string = document.get(offset, length);
+			int index = string.lastIndexOf(OPEN_COMMENT);
+			while (index != -1) {
+				document.replace(offset + index, OPEN_COMMENT.length(), ""); //$NON-NLS-1$
+				index = string.lastIndexOf(OPEN_COMMENT, index - 1);
+				adjusted_length -= OPEN_COMMENT.length();
+			}
+
+			// remove close comments
+			string = document.get(offset, adjusted_length);
+			index = string.lastIndexOf(CLOSE_COMMENT);
+			while (index != -1) {
+				document.replace(offset + index, CLOSE_COMMENT.length(), ""); //$NON-NLS-1$
+				index = string.lastIndexOf(CLOSE_COMMENT, index - 1);
+			}
+		}
+		catch (BadLocationException e) {
+			Logger.log(Logger.WARNING_DEBUG, e.getMessage(), e);
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/handlers/ExpandAllHandler.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/handlers/ExpandAllHandler.java
new file mode 100644
index 0000000..9091399
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/handlers/ExpandAllHandler.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Standards for Technology in Automotive Retail 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:
+ *     David Carver - initial API and implementation, bug 212330
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.handlers;
+
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.handlers.HandlerUtil;
+import org.eclipse.wst.xml.ui.internal.tabletree.XMLTableTreeViewer;
+
+public class ExpandAllHandler extends ExpandCollapseAllHandler {
+
+	protected XMLTableTreeViewer viewer = null;
+
+	/**
+	 * 
+	 */
+	public ExpandAllHandler() {
+		super();
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.core.commands.AbstractHandler#execute(org.eclipse.core.commands.ExecutionEvent)
+	 */
+	public Object execute(ExecutionEvent event) throws ExecutionException {
+		
+		IEditorPart editorPart = HandlerUtil.getActiveEditor(event);
+		
+		viewer = getTableTreeViewerForEditorPart(editorPart);
+		
+		if (viewer != null) {
+			// temporarily set the visibility to false
+			// this has a HUGE performance benefit
+			boolean isVisible = viewer.getControl().getVisible();
+			viewer.getControl().setVisible(false);
+			viewer.expandAll();
+
+			// restore the previous visibility state
+			// 
+			viewer.getControl().setVisible(isVisible);
+		}		
+		
+		return null;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/handlers/ExpandCollapseAllHandler.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/handlers/ExpandCollapseAllHandler.java
new file mode 100644
index 0000000..52d40f4
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/handlers/ExpandCollapseAllHandler.java
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Standards for Technology in Automotive Retail 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:
+ *     David Carver - initial API and implementation, bug 212330
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.handlers;
+
+import java.util.Map;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.commands.IElementUpdater;
+import org.eclipse.ui.menus.UIElement;
+import org.eclipse.wst.xml.ui.internal.tabletree.IDesignViewer;
+import org.eclipse.wst.xml.ui.internal.tabletree.XMLTableTreeViewer;
+
+public class ExpandCollapseAllHandler extends AbstractHandler implements IElementUpdater {
+
+	protected XMLTableTreeViewer viewer = null;
+
+	/**
+	 * Command handler for handling Expand and Collapse for Tree Viewer 
+	 */
+	public ExpandCollapseAllHandler() {
+		super();
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.core.commands.AbstractHandler#execute(org.eclipse.core.commands.ExecutionEvent)
+	 */
+	public Object execute(ExecutionEvent event) throws ExecutionException {
+		// Implementors to put their code here.
+		
+		return null;
+	}
+	
+	protected XMLTableTreeViewer getTableTreeViewerForEditorPart(IEditorPart targetEditor) {
+		XMLTableTreeViewer result = null;
+		Object object = targetEditor.getAdapter(IDesignViewer.class);
+		if (object instanceof XMLTableTreeViewer) {
+			result = (XMLTableTreeViewer) object;
+		}
+		return result;
+	}
+	
+	public void updateElement(UIElement element, Map parameters) {
+		// TODO Auto-generated method stub
+		
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/handlers/NextSiblingNavigationHandler.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/handlers/NextSiblingNavigationHandler.java
new file mode 100644
index 0000000..c25951c
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/handlers/NextSiblingNavigationHandler.java
@@ -0,0 +1,19 @@
+/*******************************************************************************
+ * Copyright (c) 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.handlers;
+
+public class NextSiblingNavigationHandler extends AbstractSiblingNavigationHandler {
+
+	protected boolean moveForward() {
+		return true;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/handlers/PreviousSiblingNavigationHandler.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/handlers/PreviousSiblingNavigationHandler.java
new file mode 100644
index 0000000..3442a8b
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/handlers/PreviousSiblingNavigationHandler.java
@@ -0,0 +1,19 @@
+/*******************************************************************************
+ * Copyright (c) 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.handlers;
+
+public class PreviousSiblingNavigationHandler extends AbstractSiblingNavigationHandler {
+
+	protected boolean moveForward() {
+		return false;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/handlers/ReloadDependenciesHandler.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/handlers/ReloadDependenciesHandler.java
new file mode 100644
index 0000000..c371a18
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/handlers/ReloadDependenciesHandler.java
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Standards for Technology in Automotive Retail 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:
+ *     David Carver - initial API and implementation, bug 212330
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.handlers;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.commands.IHandler;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.handlers.HandlerUtil;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelqueryimpl.CMDocumentLoader;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelqueryimpl.InferredGrammarBuildingCMDocumentLoader;
+import org.eclipse.wst.xml.core.internal.modelquery.ModelQueryUtil;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
+import org.w3c.dom.Document;
+
+public class ReloadDependenciesHandler extends AbstractHandler implements IHandler {
+	protected IStructuredModel model;
+
+	/**
+	 * 
+	 */
+	public ReloadDependenciesHandler() {
+		// TODO Auto-generated constructor stub
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.core.commands.AbstractHandler#execute(org.eclipse.core.commands.ExecutionEvent)
+	 */
+	public Object execute(ExecutionEvent event) throws ExecutionException {
+		IEditorPart editor = HandlerUtil.getActiveEditor(event);
+		ITextEditor textEditor = null;
+		if (editor instanceof ITextEditor)
+			textEditor = (ITextEditor) editor;
+		else {
+			Object o = editor.getAdapter(ITextEditor.class);
+			if (o != null)
+				textEditor = (ITextEditor) o;
+		}
+		if (textEditor != null) {
+			IDocument document = textEditor.getDocumentProvider().getDocument(textEditor.getEditorInput());
+			IStructuredModel model = StructuredModelManager.getModelManager().getExistingModelForRead(document);
+			if (model != null) {
+				ModelQuery modelQuery = null;
+				try {
+					modelQuery = ModelQueryUtil.getModelQuery(model);
+				}
+				finally {
+					model.releaseFromRead();
+				}
+				Document domDocument = ((IDOMModel) model).getDocument();
+				if ((modelQuery != null) && (modelQuery.getCMDocumentManager() != null)) {
+					modelQuery.getCMDocumentManager().getCMDocumentCache().clear();
+					// TODO... need to figure out how to access the
+					// DOMObserver via ModelQuery
+					// ...why?
+					CMDocumentLoader loader = new InferredGrammarBuildingCMDocumentLoader(domDocument, modelQuery);
+					loader.loadCMDocuments();
+				}
+			}
+		}
+		return null;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/handlers/RemoveBlockCommentHandler.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/handlers/RemoveBlockCommentHandler.java
new file mode 100644
index 0000000..b4080bf
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/handlers/RemoveBlockCommentHandler.java
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Standards for Technology in Automotive Retail 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:
+ *     David Carver - initial API and implementation, bug 212330
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.handlers;
+
+import org.eclipse.core.commands.IHandler;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
+import org.eclipse.wst.xml.core.internal.document.CommentImpl;
+import org.eclipse.wst.xml.ui.internal.Logger;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+
+/**
+ * @author dcarver
+ * 
+ */
+public class RemoveBlockCommentHandler extends CommentHandler implements IHandler {
+
+	public RemoveBlockCommentHandler() {
+		super();
+	}
+
+	void processAction(ITextEditor textEditor, IDocument document, ITextSelection textSelection) {
+		IStructuredModel model = StructuredModelManager.getModelManager().getExistingModelForEdit(document);
+		if (model != null) {
+			try {
+				IndexedRegion selectionStartIndexedRegion = model.getIndexedRegion(textSelection.getOffset());
+				IndexedRegion selectionEndIndexedRegion = model.getIndexedRegion(textSelection.getOffset() + textSelection.getLength());
+
+				if ((selectionStartIndexedRegion == null) || (selectionEndIndexedRegion == null)) {
+					return;
+				}
+
+				int openCommentOffset = selectionStartIndexedRegion.getStartOffset();
+				int closeCommentOffset = selectionEndIndexedRegion.getEndOffset() - OPEN_COMMENT.length() - CLOSE_COMMENT.length();
+
+				model.beginRecording(this, XMLUIMessages.RemoveBlockComment_tooltip);
+				model.aboutToChangeModel();
+
+				try {
+					if (textSelection.getLength() == 0) {
+						if (selectionStartIndexedRegion instanceof CommentImpl) {
+							document.replace(openCommentOffset, OPEN_COMMENT.length(), ""); //$NON-NLS-1$
+							document.replace(closeCommentOffset, CLOSE_COMMENT.length(), ""); //$NON-NLS-1$
+						}
+					}
+					else {
+						if (selectionStartIndexedRegion instanceof CommentImpl) {
+							document.replace(openCommentOffset, OPEN_COMMENT.length(), ""); //$NON-NLS-1$
+						}
+
+						if (selectionEndIndexedRegion instanceof CommentImpl) {
+							document.replace(closeCommentOffset, CLOSE_COMMENT.length(), ""); //$NON-NLS-1$
+						}
+					}
+					removeOpenCloseComments(document, openCommentOffset + OPEN_COMMENT.length(), closeCommentOffset - openCommentOffset - CLOSE_COMMENT.length());
+				}
+				catch (BadLocationException e) {
+					Logger.log(Logger.WARNING_DEBUG, e.getMessage(), e);
+				}
+				finally {
+					model.changedModel();
+					model.endRecording(this);
+				}
+			}
+			finally {
+				model.releaseFromEdit();
+			}
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/handlers/StructuredSelectEnclosingXMLHandler.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/handlers/StructuredSelectEnclosingXMLHandler.java
new file mode 100644
index 0000000..f043b6e
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/handlers/StructuredSelectEnclosingXMLHandler.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.handlers;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.text.Region;
+import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
+import org.eclipse.wst.sse.ui.internal.handlers.AbstractStructuredSelectHandler;
+import org.w3c.dom.Node;
+
+public class StructuredSelectEnclosingXMLHandler extends AbstractStructuredSelectHandler {
+	protected IndexedRegion getCursorIndexedRegion(IDocument document, ITextSelection textSelection) {
+		IndexedRegion indexedRegion = null;
+
+		indexedRegion = getIndexedRegion(document, textSelection.getOffset());
+
+		return indexedRegion;
+	}
+
+	protected Region getNewSelectionRegion(IndexedRegion indexedRegion, ITextSelection textSelection) {
+		Region newRegion = null;
+		if (indexedRegion instanceof Node) {
+			Node cursorNode = (Node) indexedRegion;
+
+			// use parent node for empty text node
+			if ((cursorNode.getNodeType() == Node.TEXT_NODE) && (cursorNode.getNodeValue().trim().length() == 0)) {
+				cursorNode = cursorNode.getParentNode();
+
+				if (cursorNode instanceof IndexedRegion) {
+					indexedRegion = (IndexedRegion) cursorNode;
+				}
+			}
+
+			Region cursorNodeRegion = new Region(indexedRegion.getStartOffset(), indexedRegion.getEndOffset() - indexedRegion.getStartOffset());
+
+			if ((cursorNodeRegion.getOffset() >= textSelection.getOffset()) && (cursorNodeRegion.getOffset() <= textSelection.getOffset() + textSelection.getLength()) && (cursorNodeRegion.getOffset() + cursorNodeRegion.getLength() >= textSelection.getOffset()) && (cursorNodeRegion.getOffset() + cursorNodeRegion.getLength() <= textSelection.getOffset() + textSelection.getLength())) {
+				Node newNode = cursorNode.getParentNode();
+
+				if (newNode instanceof IndexedRegion) {
+					IndexedRegion newIndexedRegion = (IndexedRegion) newNode;
+					newRegion = new Region(newIndexedRegion.getStartOffset(), newIndexedRegion.getEndOffset() - newIndexedRegion.getStartOffset());
+				}
+			}
+			else {
+				newRegion = cursorNodeRegion;
+			}
+		}
+		return newRegion;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/handlers/StructuredSelectNextXMLHandler.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/handlers/StructuredSelectNextXMLHandler.java
new file mode 100644
index 0000000..366789f
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/handlers/StructuredSelectNextXMLHandler.java
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ * Copyright (c) 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.handlers;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jface.text.TextSelection;
+import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
+import org.eclipse.wst.sse.ui.internal.handlers.AbstractStructuredSelectHandler;
+import org.w3c.dom.Node;
+
+public class StructuredSelectNextXMLHandler extends AbstractStructuredSelectHandler {
+
+	protected IndexedRegion getCursorIndexedRegion(IDocument document, ITextSelection textSelection) {
+		int offset = textSelection.getOffset() + textSelection.getLength() - 1;
+		if (offset < 0) {
+			offset = 0;
+		}
+
+		IndexedRegion indexedRegion = null;
+
+		indexedRegion = getIndexedRegion(document, offset);
+
+		return indexedRegion;
+	}
+
+	protected Region getNewSelectionRegion(IndexedRegion indexedRegion, ITextSelection textSelection) {
+		Region newRegion = null;
+		if (indexedRegion instanceof Node) {
+			Node cursorNode = (Node) indexedRegion;
+
+			// use parent node for empty text node
+			if ((cursorNode.getNodeType() == Node.TEXT_NODE) && (cursorNode.getNodeValue().trim().length() == 0)) {
+				cursorNode = cursorNode.getParentNode();
+
+				if (cursorNode instanceof IndexedRegion) {
+					indexedRegion = (IndexedRegion) cursorNode;
+				}
+			}
+
+			Region cursorNodeRegion = new Region(indexedRegion.getStartOffset(), indexedRegion.getEndOffset() - indexedRegion.getStartOffset());
+			int currentOffset = textSelection.getOffset();
+			int currentEndOffset = currentOffset + textSelection.getLength();
+			if ((cursorNodeRegion.getOffset() >= currentOffset) && (cursorNodeRegion.getOffset() <= currentEndOffset) && (cursorNodeRegion.getOffset() + cursorNodeRegion.getLength() >= currentOffset) && (cursorNodeRegion.getOffset() + cursorNodeRegion.getLength() <= currentEndOffset)) {
+				newRegion = getNewSelectionRegion2(indexedRegion, textSelection);
+			}
+			else {
+				newRegion = cursorNodeRegion;
+			}
+		}
+		return newRegion;
+	}
+
+	/**
+	 * This method was separated out from getNewSelectionRegion2 because the
+	 * code in here is allowed to be called recursively.
+	 * 
+	 * @param indexedRegion
+	 * @param textSelection
+	 * @return new region to select or null if none
+	 */
+	private Region getNewSelectionRegion2(IndexedRegion indexedRegion, ITextSelection textSelection) {
+		Region newRegion = null;
+		if (indexedRegion instanceof Node) {
+			Node node = (Node) indexedRegion;
+			Node newNode = node.getNextSibling();
+			if (newNode == null) {
+				newNode = node.getParentNode();
+
+				if (newNode instanceof IndexedRegion) {
+					IndexedRegion newIndexedRegion = (IndexedRegion) newNode;
+					newRegion = new Region(newIndexedRegion.getStartOffset(), newIndexedRegion.getEndOffset() - newIndexedRegion.getStartOffset());
+				}
+			}
+			else {
+				if (newNode instanceof IndexedRegion) {
+					IndexedRegion newIndexedRegion = (IndexedRegion) newNode;
+					newRegion = new Region(textSelection.getOffset(), newIndexedRegion.getEndOffset() - textSelection.getOffset());
+
+					if (newNode.getNodeType() == Node.TEXT_NODE) {
+						newRegion = getNewSelectionRegion2(newIndexedRegion, new TextSelection(newRegion.getOffset(), newRegion.getLength()));
+					}
+				}
+			}
+		}
+		return newRegion;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/handlers/StructuredSelectPreviousXMLHandler.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/handlers/StructuredSelectPreviousXMLHandler.java
new file mode 100644
index 0000000..ab57447
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/handlers/StructuredSelectPreviousXMLHandler.java
@@ -0,0 +1,75 @@
+/*******************************************************************************
+ * Copyright (c) 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.handlers;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jface.text.TextSelection;
+import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
+import org.eclipse.wst.sse.ui.internal.handlers.AbstractStructuredSelectHandler;
+import org.w3c.dom.Node;
+
+public class StructuredSelectPreviousXMLHandler extends AbstractStructuredSelectHandler {
+
+	protected IndexedRegion getCursorIndexedRegion(IDocument document, ITextSelection textSelection) {
+		IndexedRegion indexedRegion = null;
+
+		indexedRegion = getIndexedRegion(document, textSelection.getOffset());
+
+		return indexedRegion;
+	}
+
+	protected Region getNewSelectionRegion(IndexedRegion indexedRegion, ITextSelection textSelection) {
+		Region newRegion = null;
+		if (indexedRegion instanceof Node) {
+			Node cursorNode = (Node) indexedRegion;
+
+			// use parent node for empty text node
+			if ((cursorNode.getNodeType() == Node.TEXT_NODE) && (cursorNode.getNodeValue().trim().length() == 0)) {
+				cursorNode = cursorNode.getParentNode();
+
+				if (cursorNode instanceof IndexedRegion) {
+					indexedRegion = (IndexedRegion) cursorNode;
+				}
+			}
+
+			Region cursorNodeRegion = new Region(indexedRegion.getStartOffset(), indexedRegion.getEndOffset() - indexedRegion.getStartOffset());
+
+			if ((cursorNodeRegion.getOffset() >= textSelection.getOffset()) && (cursorNodeRegion.getOffset() <= textSelection.getOffset() + textSelection.getLength()) && (cursorNodeRegion.getOffset() + cursorNodeRegion.getLength() >= textSelection.getOffset()) && (cursorNodeRegion.getOffset() + cursorNodeRegion.getLength() <= textSelection.getOffset() + textSelection.getLength())) {
+				Node newNode = cursorNode.getPreviousSibling();
+				if (newNode == null) {
+					newNode = cursorNode.getParentNode();
+
+					if (newNode instanceof IndexedRegion) {
+						IndexedRegion newIndexedRegion = (IndexedRegion) newNode;
+						newRegion = new Region(newIndexedRegion.getStartOffset(), newIndexedRegion.getEndOffset() - newIndexedRegion.getStartOffset());
+					}
+				}
+				else {
+					if (newNode instanceof IndexedRegion) {
+						IndexedRegion newIndexedRegion = (IndexedRegion) newNode;
+						newRegion = new Region(newIndexedRegion.getStartOffset(), textSelection.getOffset() + textSelection.getLength() - newIndexedRegion.getStartOffset());
+
+						if (newNode.getNodeType() == Node.TEXT_NODE) {
+							newRegion = getNewSelectionRegion(newIndexedRegion, new TextSelection(newRegion.getOffset(), newRegion.getLength()));
+						}
+					}
+				}
+
+			}
+			else {
+				newRegion = cursorNodeRegion;
+			}
+		}
+		return newRegion;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/handlers/ToggleCommentHandler.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/handlers/ToggleCommentHandler.java
new file mode 100644
index 0000000..0b75dca
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/handlers/ToggleCommentHandler.java
@@ -0,0 +1,193 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 Standards for Technology in Automotive Retail 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:
+ *     David Carver - initial API and implementation, bug 212330
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.handlers;
+
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.commands.IHandler;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.TextSelection;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.handlers.HandlerUtil;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.xml.ui.internal.Logger;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+
+public class ToggleCommentHandler extends CommentHandler implements IHandler {
+	public ToggleCommentHandler() {
+		super();
+	}
+
+	public Object execute(ExecutionEvent event) throws ExecutionException {
+		IEditorPart editor = HandlerUtil.getActiveEditor(event);
+		ITextEditor textEditor = null;
+		if (editor instanceof ITextEditor)
+			textEditor = (ITextEditor) editor;
+		else {
+			Object o = editor.getAdapter(ITextEditor.class);
+			if (o != null)
+				textEditor = (ITextEditor) o;
+		}
+		if (textEditor != null && super.validateEditorInput(textEditor)) {
+			IDocument document = textEditor.getDocumentProvider().getDocument(textEditor.getEditorInput());
+			if (document != null) {
+				// get current text selection
+				ITextSelection textSelection = getCurrentSelection(textEditor);
+				if (textSelection.isEmpty()) {
+					return null;
+				}
+
+				processAction(textEditor, document, textSelection);
+			}
+		}
+		return null;
+	}
+
+	void processAction(ITextEditor textEditor, IDocument document, ITextSelection textSelection) {
+		// get text selection lines info
+		int selectionStartLine = textSelection.getStartLine();
+		int selectionEndLine = textSelection.getEndLine();
+		try {
+			int selectionEndLineOffset = document.getLineOffset(selectionEndLine);
+			int selectionEndOffset = textSelection.getOffset() + textSelection.getLength();
+
+			// adjust selection end line
+			if ((selectionEndLine > selectionStartLine) && (selectionEndLineOffset == selectionEndOffset)) {
+				selectionEndLine--;
+			}
+
+		}
+		catch (BadLocationException e) {
+			Logger.log(Logger.WARNING_DEBUG, e.getMessage(), e);
+		}
+
+		// save the selection position since it will be changing
+		Position selectionPosition = null;
+		boolean updateStartOffset = false;
+		try {
+			selectionPosition = new Position(textSelection.getOffset(), textSelection.getLength());
+			document.addPosition(selectionPosition);
+
+			// extra check if commenting from beginning of line
+			int selectionStartLineOffset = document.getLineOffset(selectionStartLine);
+			if ((textSelection.getLength() > 0) && (selectionStartLineOffset == textSelection.getOffset()) && !isCommentLine(document, selectionStartLine)) {
+				updateStartOffset = true;
+			}
+		}
+		catch (BadLocationException e) {
+			Logger.log(Logger.WARNING_DEBUG, e.getMessage(), e);
+		}
+
+		processAction(document, selectionStartLine, selectionEndLine);
+
+		updateCurrentSelection(textEditor, selectionPosition, document, updateStartOffset);
+	}
+
+	private void processAction(IDocument document, int selectionStartLine, int selectionEndLine) {
+		IStructuredModel model = StructuredModelManager.getModelManager().getExistingModelForEdit(document);
+		if (model != null) {
+			try {
+				model.beginRecording(this, XMLUIMessages.ToggleComment_tooltip);
+				model.aboutToChangeModel();
+
+				for (int i = selectionStartLine; i <= selectionEndLine; i++) {
+					try {
+						if (document.getLineLength(i) > 0) {
+							if (isCommentLine(document, i)) {
+								int lineOffset = document.getLineOffset(i);
+								IRegion region = document.getLineInformation(i);
+								String string = document.get(region.getOffset(), region.getLength());
+								int openCommentOffset = lineOffset + string.indexOf(OPEN_COMMENT);
+								int closeCommentOffset = lineOffset + string.indexOf(CLOSE_COMMENT) - OPEN_COMMENT.length();
+								uncomment(document, openCommentOffset, closeCommentOffset);
+							}
+							else {
+								int openCommentOffset = document.getLineOffset(i);
+								int lineDelimiterLength = document.getLineDelimiter(i) == null ? 0 : document.getLineDelimiter(i).length();
+								int closeCommentOffset = openCommentOffset + document.getLineLength(i) - lineDelimiterLength + OPEN_COMMENT.length();
+								comment(document, openCommentOffset, closeCommentOffset);
+							}
+						}
+					}
+					catch (BadLocationException e) {
+						Logger.log(Logger.WARNING_DEBUG, e.getMessage(), e);
+					}
+				}
+			}
+			finally {
+				model.changedModel();
+				model.endRecording(this);
+				model.releaseFromEdit();
+			}
+		}
+	}
+
+	private boolean isCommentLine(IDocument document, int line) {
+		boolean isComment = false;
+
+		try {
+			IRegion region = document.getLineInformation(line);
+			String string = document.get(region.getOffset(), region.getLength()).trim();
+			isComment = (string.length() >= OPEN_COMMENT.length() + CLOSE_COMMENT.length()) && string.startsWith(OPEN_COMMENT) && string.endsWith(CLOSE_COMMENT);
+		}
+		catch (BadLocationException e) {
+			Logger.log(Logger.WARNING_DEBUG, e.getMessage(), e);
+		}
+		return isComment;
+	}
+
+	private void comment(IDocument document, int openCommentOffset, int closeCommentOffset) {
+		try {
+			document.replace(openCommentOffset, 0, OPEN_COMMENT);
+			document.replace(closeCommentOffset, 0, CLOSE_COMMENT);
+			removeOpenCloseComments(document, openCommentOffset + OPEN_COMMENT.length(), closeCommentOffset - openCommentOffset - CLOSE_COMMENT.length());
+		}
+		catch (BadLocationException e) {
+			Logger.log(Logger.WARNING_DEBUG, e.getMessage(), e);
+		}
+	}
+
+	private void uncomment(IDocument document, int openCommentOffset, int closeCommentOffset) {
+		try {
+			document.replace(openCommentOffset, OPEN_COMMENT.length(), ""); //$NON-NLS-1$
+			document.replace(closeCommentOffset, CLOSE_COMMENT.length(), ""); //$NON-NLS-1$
+		}
+		catch (BadLocationException e) {
+			Logger.log(Logger.WARNING_DEBUG, e.getMessage(), e);
+		}
+	}
+
+	private void updateCurrentSelection(ITextEditor textEditor, Position selectionPosition, IDocument document, boolean updateStartOffset) {
+		// update the selection if text selection changed
+		if (selectionPosition != null) {
+			ITextSelection selection = null;
+			if (updateStartOffset) {
+				selection = new TextSelection(document, selectionPosition.getOffset() - OPEN_COMMENT.length(), selectionPosition.getLength() + OPEN_COMMENT.length());
+			}
+			else {
+				selection = new TextSelection(document, selectionPosition.getOffset(), selectionPosition.getLength());
+			}
+			ISelectionProvider provider = textEditor.getSelectionProvider();
+			if (provider != null) {
+				provider.setSelection(selection);
+			}
+			document.removePosition(selectionPosition);
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/handlers/ToggleEditModeHandler.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/handlers/ToggleEditModeHandler.java
new file mode 100644
index 0000000..c36673f
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/handlers/ToggleEditModeHandler.java
@@ -0,0 +1,138 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Standards for Technology in Automotive Retail 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:
+ *     David Carver - initial API and implementation, bug 212330
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.handlers;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.commands.ICommandService;
+import org.eclipse.ui.commands.IElementUpdater;
+import org.eclipse.ui.handlers.HandlerUtil;
+import org.eclipse.ui.menus.UIElement;
+import org.eclipse.ui.services.IServiceScopes;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.modelquery.ModelQueryUtil;
+import org.eclipse.wst.xml.ui.internal.XMLUIPlugin;
+import org.eclipse.wst.xml.ui.internal.tabletree.XMLEditorMessages;
+import org.eclipse.wst.xml.ui.internal.util.SharedXMLEditorPluginImageHelper;
+
+public class ToggleEditModeHandler extends AbstractHandler implements IElementUpdater {
+	protected ImageDescriptor onImage = SharedXMLEditorPluginImageHelper.getImageDescriptor(SharedXMLEditorPluginImageHelper.IMG_ETOOL_CONSTRAINON);
+	protected ImageDescriptor offImage = SharedXMLEditorPluginImageHelper.getImageDescriptor(SharedXMLEditorPluginImageHelper.IMG_ETOOL_CONSTRAINOFF);
+
+	public ToggleEditModeHandler() {
+		super();
+	}
+
+	public Object execute(ExecutionEvent event) throws ExecutionException {
+		IEditorPart editor = HandlerUtil.getActiveEditor(event);
+		ITextEditor textEditor = null;
+		if (editor instanceof ITextEditor)
+			textEditor = (ITextEditor) editor;
+		else {
+			Object o = editor.getAdapter(ITextEditor.class);
+			if (o != null)
+				textEditor = (ITextEditor) o;
+		}
+		if (textEditor != null) {
+			IDocument document = textEditor.getDocumentProvider().getDocument(textEditor.getEditorInput());
+			IStructuredModel model = StructuredModelManager.getModelManager().getExistingModelForRead(document);
+			if (model != null) {
+				ModelQuery modelQuery;
+				try {
+					modelQuery = ModelQueryUtil.getModelQuery(model);
+				}
+				finally {
+					model.releaseFromRead();
+				}
+				if (modelQuery != null) {
+					int newState = getNextState(modelQuery.getEditMode());
+					modelQuery.setEditMode(newState);
+
+					// Force a Refresh on this command so that the image can
+					// be
+					// updated.
+					ICommandService commandService = (ICommandService) HandlerUtil.getActiveWorkbenchWindow(event).getService(ICommandService.class);
+					Map filter = new HashMap();
+					filter.put(IServiceScopes.WINDOW_SCOPE, HandlerUtil.getActiveWorkbenchWindow(event));
+					commandService.refreshElements(event.getCommand().getId(), filter);
+				}
+			}
+		}
+
+		return null;
+	}
+
+	public int getNextState(int editMode) {
+		int result = -1;
+		if (editMode == ModelQuery.EDIT_MODE_CONSTRAINED_STRICT) {
+			result = ModelQuery.EDIT_MODE_UNCONSTRAINED;
+		}
+		else {
+			result = ModelQuery.EDIT_MODE_CONSTRAINED_STRICT;
+		}
+		return result;
+	}
+
+
+	// Handlers that need to interact with the ui that the command came from
+	// need to use implement this method.
+	public void updateElement(UIElement element, Map parameters) {
+		IEditorPart editor = XMLUIPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor();
+		ITextEditor textEditor = null;
+		if (editor instanceof ITextEditor)
+			textEditor = (ITextEditor) editor;
+		else if (editor != null) {
+			Object o = editor.getAdapter(ITextEditor.class);
+			if (o != null)
+				textEditor = (ITextEditor) o;
+		}
+		if (textEditor != null) {
+			IDocument document = textEditor.getDocumentProvider().getDocument(textEditor.getEditorInput());
+			IStructuredModel model = StructuredModelManager.getModelManager().getExistingModelForRead(document);
+			if (model != null) {
+			    ModelQuery modelQuery;
+				try {
+					modelQuery = ModelQueryUtil.getModelQuery(model);
+				}
+				finally {
+					model.releaseFromRead();
+				}
+				if (modelQuery != null) {
+					setAppearanceForEditMode(modelQuery.getEditMode(), element);
+				}
+			}
+		}
+	}
+
+	public void setAppearanceForEditMode(int editMode, UIElement element) {
+		if (editMode == ModelQuery.EDIT_MODE_CONSTRAINED_STRICT) {
+			element.setTooltip(XMLEditorMessages.XMLTableTreeActionBarContributor_3);
+			element.setText(XMLEditorMessages.XMLTableTreeActionBarContributor_3);
+			element.setIcon(onImage);
+		}
+		else {
+			element.setTooltip(XMLEditorMessages.XMLTableTreeActionBarContributor_5);
+			element.setText(XMLEditorMessages.XMLTableTreeActionBarContributor_5);
+			element.setIcon(offImage);
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/handlers/XMLFindOccurencesHandler.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/handlers/XMLFindOccurencesHandler.java
new file mode 100644
index 0000000..591e5f1
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/handlers/XMLFindOccurencesHandler.java
@@ -0,0 +1,158 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 Standards for Technology in Automotive Retail 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:
+ *     David Carver - initial API and implementation - bug 212330 -
+ *                    Based off CleanupActionXMLDelegate
+ *******************************************************************************/
+
+package org.eclipse.wst.xml.ui.internal.handlers;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.commands.IHandler;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.text.ITypedRegion;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IFileEditorInput;
+import org.eclipse.ui.handlers.HandlerUtil;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.wst.sse.ui.StructuredTextEditor;
+import org.eclipse.wst.sse.ui.internal.ExtendedConfigurationBuilder;
+import org.eclipse.wst.sse.ui.internal.SSEUIMessages;
+import org.eclipse.wst.sse.ui.internal.search.FindOccurrencesProcessor;
+import org.eclipse.wst.sse.ui.internal.util.PlatformStatusLineUtil;
+import org.eclipse.wst.xml.ui.internal.search.XMLFindOccurrencesProcessor;
+
+public class XMLFindOccurencesHandler extends AbstractHandler implements IHandler {
+	private List fProcessors;
+
+	public void dispose() {
+	}
+
+	public Object execute(ExecutionEvent event) throws ExecutionException {
+		IEditorPart editor = HandlerUtil.getActiveEditor(event);
+		ITextEditor textEditor = null;
+		boolean okay = false;
+
+		if (editor instanceof ITextEditor)
+			textEditor = (ITextEditor) editor;
+		else {
+			Object o = editor.getAdapter(ITextEditor.class);
+			if (o != null)
+				textEditor = (ITextEditor) o;
+		}
+
+		if (textEditor != null) {
+			IDocument document = textEditor.getDocumentProvider().getDocument(textEditor.getEditorInput());
+			if (document != null) {
+				ITextSelection textSelection = getTextSelection(textEditor);
+				FindOccurrencesProcessor findOccurrenceProcessor = getProcessorForCurrentSelection(document, textSelection);
+				if (findOccurrenceProcessor != null) {
+					if (textEditor.getEditorInput() instanceof IFileEditorInput) {
+						IFile file = ((IFileEditorInput) textEditor.getEditorInput()).getFile();
+						okay = findOccurrenceProcessor.findOccurrences(document, textSelection, file);
+					}
+				}
+			}
+		}
+		if (okay) {
+			// clear status message
+			PlatformStatusLineUtil.clearStatusLine();
+		}
+		else {
+			String errorMessage = SSEUIMessages.FindOccurrencesActionProvider_0; //$NON-NLS-1$
+			if (textEditor instanceof StructuredTextEditor) {
+				PlatformStatusLineUtil.displayTemporaryErrorMessage(((StructuredTextEditor) textEditor).getTextViewer(), errorMessage);
+			}
+			else {
+				PlatformStatusLineUtil.displayErrorMessage(errorMessage);
+				PlatformStatusLineUtil.addOneTimeClearListener();
+			}
+		}
+
+		return null;
+	}
+
+	/**
+	 * Get the appropriate find occurrences processor
+	 * 
+	 * @param document -
+	 *            assumes not null
+	 * @param textSelection
+	 * @return FindOccurrencesProcessor
+	 */
+	private FindOccurrencesProcessor getProcessorForCurrentSelection(IDocument document, ITextSelection textSelection) {
+		// check if we have an action that's enabled on the current partition
+		ITypedRegion tr = getPartition(document, textSelection);
+		String partition = tr != null ? tr.getType() : ""; //$NON-NLS-1$
+
+		Iterator it = getProcessors().iterator();
+		FindOccurrencesProcessor processor = null;
+		while (it.hasNext()) {
+			processor = (FindOccurrencesProcessor) it.next();
+			// we just choose the first action that can handle the partition
+			if (processor.enabledForParitition(partition))
+				return processor;
+		}
+
+		List extendedFindOccurrencesProcessors = ExtendedConfigurationBuilder.getInstance().getConfigurations(FindOccurrencesProcessor.class.getName(), partition);
+		for (int i = 0; i < extendedFindOccurrencesProcessors.size(); i++) {
+			Object o = extendedFindOccurrencesProcessors.get(i);
+			if (o instanceof FindOccurrencesProcessor) {
+				/*
+				 * We just choose the first registered processor that
+				 * explicitly says it can handle the partition
+				 */
+				processor = (FindOccurrencesProcessor) o;
+				if (processor.enabledForParitition(partition))
+					return processor;
+			}
+		}
+		return null;
+	}
+
+	private ITypedRegion getPartition(IDocument document, ITextSelection textSelection) {
+		ITypedRegion region = null;
+		if (textSelection != null) {
+			try {
+				region = document.getPartition(textSelection.getOffset());
+			}
+			catch (BadLocationException e) {
+				region = null;
+			}
+		}
+		return region;
+	}
+
+	private ITextSelection getTextSelection(ITextEditor textEditor) {
+		ITextSelection textSelection = null;
+		ISelection selection = textEditor.getSelectionProvider().getSelection();
+		if (selection instanceof ITextSelection && !selection.isEmpty()) {
+			textSelection = (ITextSelection) selection;
+		}
+		return textSelection;
+	}
+
+	protected List getProcessors() {
+		if (fProcessors == null) {
+			fProcessors = new ArrayList();
+			XMLFindOccurrencesProcessor htmlProcessor = new XMLFindOccurrencesProcessor();
+			fProcessors.add(htmlProcessor);
+		}
+		return fProcessors;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/hyperlink/CatalogEntryHyperlink.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/hyperlink/CatalogEntryHyperlink.java
new file mode 100644
index 0000000..7ef2986
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/hyperlink/CatalogEntryHyperlink.java
@@ -0,0 +1,116 @@
+/*******************************************************************************
+ * Copyright (c) 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.hyperlink;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.hyperlink.IHyperlink;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalogEntry;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+
+class CatalogEntryHyperlink implements IHyperlink {
+
+	private IRegion fHyperlinkRegion = null;
+	private ICatalogEntry fEntry = null;
+
+	/**
+	 * @param hyperlinkRegion
+	 * @param entry
+	 */
+	CatalogEntryHyperlink(IRegion hyperlinkRegion, ICatalogEntry entry) {
+		super();
+		fHyperlinkRegion = hyperlinkRegion;
+		fEntry = entry;
+	}
+
+	/**
+	 * @return
+	 */
+	private IHyperlink getHyperlink() {
+		if (fEntry.getURI().startsWith("file:")) { //$NON-NLS-1$
+			return new ExternalFileHyperlink(fHyperlinkRegion, new File(fEntry.getURI().substring(5)));
+		}
+		else if (fEntry.getURI().startsWith("platform:/resource/")) { //$NON-NLS-1$
+			IPath path = new Path(fEntry.getURI().substring(20));
+			if (path.segmentCount() > 1)
+				return new WorkspaceFileHyperlink(fHyperlinkRegion, ResourcesPlugin.getWorkspace().getRoot().getFile(path));
+		}
+		else {
+			/*
+			 * the URL detector will already work on the literal text, so
+			 * offer to open the contents in an editor
+			 */
+			try {
+				if (fEntry.getURI().startsWith("jar:file:"))
+					return new URLStorageHyperlink(fHyperlinkRegion, new URL(fEntry.getURI())) {
+						public String getHyperlinkText() {
+							return NLS.bind(XMLUIMessages.Open, fEntry.getKey());
+						}
+					};
+			}
+			catch (MalformedURLException e) {
+				// not valid?
+			}
+		}
+		return null;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.hyperlink.IHyperlink#getHyperlinkRegion()
+	 */
+	public IRegion getHyperlinkRegion() {
+		return fHyperlinkRegion;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.hyperlink.IHyperlink#getHyperlinkText()
+	 */
+	public String getHyperlinkText() {
+		IHyperlink link = getHyperlink();
+		if (link != null)
+			return link.getHyperlinkText();
+		return NLS.bind(XMLUIMessages.Open, fEntry.getKey());
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.hyperlink.IHyperlink#getTypeLabel()
+	 */
+	public String getTypeLabel() {
+		IHyperlink link = getHyperlink();
+		if (link != null)
+			return link.getTypeLabel();
+		return null;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.hyperlink.IHyperlink#open()
+	 */
+	public void open() {
+		IHyperlink link = getHyperlink();
+		if (link != null)
+			link.open();
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/hyperlink/ExternalFileEditorInput.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/hyperlink/ExternalFileEditorInput.java
new file mode 100644
index 0000000..86e85d0
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/hyperlink/ExternalFileEditorInput.java
@@ -0,0 +1,171 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.hyperlink;
+
+import java.io.File;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IPathEditorInput;
+import org.eclipse.ui.IPersistableElement;
+import org.eclipse.ui.editors.text.ILocationProvider;
+import org.eclipse.ui.model.IWorkbenchAdapter;
+
+/**
+ * EditorInput for external files. Copied from
+ * org.eclipse.ui.internal.editors.text.JavaFileEditorInput
+ */
+class ExternalFileEditorInput implements IEditorInput, ILocationProvider {
+	// copies of this class exist in:
+	// org.eclipse.wst.xml.ui.internal.hyperlink
+	// org.eclipse.wst.html.ui.internal.hyperlink
+	// org.eclipse.jst.jsp.ui.internal.hyperlink
+
+	/**
+	 * The workbench adapter which simply provides the label.
+	 */
+	private class WorkbenchAdapter implements IWorkbenchAdapter {
+		/*
+		 * @see org.eclipse.ui.model.IWorkbenchAdapter#getChildren(java.lang.Object)
+		 */
+		public Object[] getChildren(Object o) {
+			return null;
+		}
+
+		/*
+		 * @see org.eclipse.ui.model.IWorkbenchAdapter#getImageDescriptor(java.lang.Object)
+		 */
+		public ImageDescriptor getImageDescriptor(Object object) {
+			return null;
+		}
+
+		/*
+		 * @see org.eclipse.ui.model.IWorkbenchAdapter#getLabel(java.lang.Object)
+		 */
+		public String getLabel(Object o) {
+			return ((ExternalFileEditorInput) o).getName();
+		}
+
+		/*
+		 * @see org.eclipse.ui.model.IWorkbenchAdapter#getParent(java.lang.Object)
+		 */
+		public Object getParent(Object o) {
+			return null;
+		}
+	}
+
+	private File fFile;
+	private WorkbenchAdapter fWorkbenchAdapter = new WorkbenchAdapter();
+
+	public ExternalFileEditorInput(File file) {
+		super();
+		fFile = file;
+		fWorkbenchAdapter = new WorkbenchAdapter();
+	}
+
+	/*
+	 * @see org.eclipse.ui.IEditorInput#exists()
+	 */
+	public boolean exists() {
+		return fFile.exists();
+	}
+
+	/*
+	 * @see org.eclipse.ui.IEditorInput#getImageDescriptor()
+	 */
+	public ImageDescriptor getImageDescriptor() {
+		return null;
+	}
+
+	/*
+	 * @see org.eclipse.ui.IEditorInput#getName()
+	 */
+	public String getName() {
+		return fFile.getName();
+	}
+
+	/*
+	 * @see org.eclipse.ui.IEditorInput#getPersistable()
+	 */
+	public IPersistableElement getPersistable() {
+		return null;
+	}
+
+	/*
+	 * @see org.eclipse.ui.IEditorInput#getToolTipText()
+	 */
+	public String getToolTipText() {
+		return fFile.getAbsolutePath();
+	}
+
+	/*
+	 * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class)
+	 */
+	public Object getAdapter(Class adapter) {
+		if (ILocationProvider.class.equals(adapter)) {
+			return this;
+		}
+		if (IWorkbenchAdapter.class.equals(adapter)) {
+			return fWorkbenchAdapter;
+		}
+		return Platform.getAdapterManager().getAdapter(this, adapter);
+	}
+
+	/*
+	 * @see org.eclipse.ui.editors.text.ILocationProvider#getPath(java.lang.Object)
+	 */
+	public IPath getPath(Object element) {
+		if (element instanceof ExternalFileEditorInput) {
+			ExternalFileEditorInput input = (ExternalFileEditorInput) element;
+			return Path.fromOSString(input.fFile.getAbsolutePath());
+		}
+		return null;
+	}
+
+	/*
+	 * @see org.eclipse.ui.IPathEditorInput#getPath()
+	 * @since 3.1
+	 */
+	public IPath getPath() {
+		return Path.fromOSString(fFile.getAbsolutePath());
+	}
+
+	/*
+	 * @see java.lang.Object#equals(java.lang.Object)
+	 */
+	public boolean equals(Object o) {
+		if (o == this) {
+			return true;
+		}
+
+		if (o instanceof ExternalFileEditorInput) {
+			ExternalFileEditorInput input = (ExternalFileEditorInput) o;
+			return fFile.equals(input.fFile);
+		}
+
+		if (o instanceof IPathEditorInput) {
+			IPathEditorInput input = (IPathEditorInput) o;
+			return getPath().equals(input.getPath());
+		}
+
+		return false;
+	}
+
+	/*
+	 * @see java.lang.Object#hashCode()
+	 */
+	public int hashCode() {
+		return fFile.hashCode();
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/hyperlink/ExternalFileHyperlink.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/hyperlink/ExternalFileHyperlink.java
new file mode 100644
index 0000000..6761969
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/hyperlink/ExternalFileHyperlink.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.hyperlink;
+
+import java.io.File;
+
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.hyperlink.IHyperlink;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.ui.IEditorDescriptor;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.ide.IDE;
+import org.eclipse.wst.xml.ui.internal.Logger;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+
+/**
+ * Hyperlink for external files.
+ */
+class ExternalFileHyperlink implements IHyperlink {
+	// copies of this class exist in:
+	// org.eclipse.wst.xml.ui.internal.hyperlink
+	// org.eclipse.wst.html.ui.internal.hyperlink
+	// org.eclipse.jst.jsp.ui.internal.hyperlink
+
+	private IRegion fHyperlinkRegion;
+	private File fHyperlinkFile;
+
+	public ExternalFileHyperlink(IRegion region, File file) {
+		fHyperlinkFile = file;
+		fHyperlinkRegion = region;
+	}
+
+	public IRegion getHyperlinkRegion() {
+		return fHyperlinkRegion;
+	}
+
+	public String getTypeLabel() {
+		return null;
+	}
+
+	public String getHyperlinkText() {
+		String path = fHyperlinkFile.getPath();
+		if (path.length() > 60) {
+			path = path.substring(0, 25) + "..." + path.substring(path.length() - 25, path.length());
+		}
+		return NLS.bind(XMLUIMessages.Open, path);
+	}
+
+	public void open() {
+		if (fHyperlinkFile != null) {
+			IEditorInput input = new ExternalFileEditorInput(fHyperlinkFile);
+			IEditorDescriptor descriptor;
+			try {
+				descriptor = IDE.getEditorDescriptor(input.getName(), true);
+				if (descriptor != null) {
+					IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
+					IDE.openEditor(page, input, descriptor.getId(), true);
+				}
+			}
+			catch (PartInitException e) {
+				Logger.log(Logger.WARNING_DEBUG, e.getMessage(), e);
+			}
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/hyperlink/URLStorageHyperlink.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/hyperlink/URLStorageHyperlink.java
new file mode 100644
index 0000000..bc4b03f
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/hyperlink/URLStorageHyperlink.java
@@ -0,0 +1,180 @@
+package org.eclipse.wst.xml.ui.internal.hyperlink;
+
+import java.io.InputStream;
+import java.net.URL;
+
+import org.eclipse.core.resources.IStorage;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.hyperlink.IHyperlink;
+import org.eclipse.jface.text.hyperlink.URLHyperlink;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.ui.IEditorDescriptor;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IPersistableElement;
+import org.eclipse.ui.IStorageEditorInput;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.ide.IDE;
+import org.eclipse.wst.sse.core.internal.util.JarUtilities;
+import org.eclipse.wst.xml.core.internal.Logger;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+import org.eclipse.wst.xml.ui.internal.XMLUIPlugin;
+
+/**
+ * Hyperlink for URLs (opens in read-only mode)
+ */
+class URLStorageHyperlink implements IHyperlink {
+	// copies of this class exist in:
+	// org.eclipse.wst.xml.ui.internal.hyperlink
+	// org.eclipse.wst.html.ui.internal.hyperlink
+	// org.eclipse.jst.jsp.ui.internal.hyperlink
+
+	static class StorageEditorInput implements IStorageEditorInput {
+		IStorage fStorage = null;
+
+		StorageEditorInput(IStorage storage) {
+			fStorage = storage;
+		}
+
+		public IStorage getStorage() throws CoreException {
+			return fStorage;
+		}
+
+		public boolean exists() {
+			return fStorage != null;
+		}
+
+		public boolean equals(Object obj) {
+			if (obj instanceof StorageEditorInput) {
+				return fStorage.equals(((StorageEditorInput) obj).fStorage);
+			}
+			return super.equals(obj);
+		}
+
+		public ImageDescriptor getImageDescriptor() {
+			return null;
+		}
+
+		public String getName() {
+			return fStorage.getName();
+		}
+
+		public IPersistableElement getPersistable() {
+			return null;
+		}
+
+		public String getToolTipText() {
+			return fStorage.getFullPath() != null ? fStorage.getFullPath().toString() : fStorage.getName();
+		}
+
+		public Object getAdapter(Class adapter) {
+			return null;
+		}
+	}
+
+	static class URLStorage implements IStorage {
+		URL fURL = null;
+
+		URLStorage(URL url) {
+			fURL = url;
+		}
+
+		public boolean equals(Object obj) {
+			if (obj instanceof URLStorage) {
+				return fURL.equals(((URLStorage) obj).fURL);
+			}
+			return super.equals(obj);
+		}
+
+		public InputStream getContents() throws CoreException {
+			InputStream stream = null;
+			try {
+				if (fURL.toString().startsWith("jar:file"))
+					stream = JarUtilities.getInputStream(fURL);
+				else
+					stream = fURL.openStream();
+			}
+			catch (Exception e) {
+				throw new CoreException(new Status(IStatus.ERROR, XMLUIPlugin.getDefault().getBundle().getSymbolicName(), IStatus.ERROR, fURL.toString(), e));
+			}
+			return stream;
+		}
+
+		public IPath getFullPath() {
+			return new Path(fURL.toString());
+		}
+
+		public String getName() {
+			return new Path(fURL.getFile()).lastSegment();
+		}
+
+		public boolean isReadOnly() {
+			return true;
+		}
+
+		public Object getAdapter(Class adapter) {
+			return null;
+		}
+
+	}
+
+	private IRegion fRegion;
+	private URL fURL;
+
+	public URLStorageHyperlink(IRegion region, URL url) {
+		fRegion = region;
+		fURL = url;
+	}
+
+	public IRegion getHyperlinkRegion() {
+		return fRegion;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.hyperlink.IHyperlink#getTypeLabel()
+	 */
+	public String getTypeLabel() {
+		return null;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.hyperlink.IHyperlink#getHyperlinkText()
+	 */
+	public String getHyperlinkText() {
+		return NLS.bind(XMLUIMessages.Open, fURL.toString());
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.hyperlink.IHyperlink#open()
+	 */
+	public void open() {
+		if (fURL != null) {
+			IEditorInput input = new StorageEditorInput(new URLStorage(fURL));
+			IEditorDescriptor descriptor;
+			try {
+				descriptor = IDE.getEditorDescriptor(input.getName());
+				if (descriptor != null) {
+					IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
+					IDE.openEditor(page, input, descriptor.getId(), true);
+				}
+			}
+			catch (PartInitException e) {
+				Logger.log(Logger.WARNING_DEBUG, e.getMessage(), e);
+				new URLHyperlink(fRegion, fURL.toString()).open();
+			}
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/hyperlink/WorkspaceFileHyperlink.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/hyperlink/WorkspaceFileHyperlink.java
new file mode 100644
index 0000000..0319952
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/hyperlink/WorkspaceFileHyperlink.java
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.hyperlink;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.hyperlink.IHyperlink;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.ide.IDE;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.wst.xml.ui.internal.Logger;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+
+/**
+ * Hyperlink for files within the workspace. (As long as there is an IFile,
+ * this can be used) Opens the default editor for the file.
+ */
+class WorkspaceFileHyperlink implements IHyperlink {
+	// copies of this class exist in:
+	// org.eclipse.wst.xml.ui.internal.hyperlink
+	// org.eclipse.wst.html.ui.internal.hyperlink
+	// org.eclipse.jst.jsp.ui.internal.hyperlink
+
+	private IRegion fRegion;
+	private IFile fFile;
+	private IRegion fHighlightRange;
+
+	public WorkspaceFileHyperlink(IRegion region, IFile file) {
+		fRegion = region;
+		fFile = file;
+	}
+
+	public WorkspaceFileHyperlink(IRegion region, IFile file, IRegion range) {
+		fRegion = region;
+		fFile = file;
+		fHighlightRange = range;
+	}
+
+	public IRegion getHyperlinkRegion() {
+		return fRegion;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.hyperlink.IHyperlink#getTypeLabel()
+	 */
+	public String getTypeLabel() {
+		return null;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.hyperlink.IHyperlink#getHyperlinkText()
+	 */
+	public String getHyperlinkText() {
+		String path = fFile.getFullPath().toString();
+		if (path.length() > 60) {
+			path = path.substring(0, 25) + "..." + path.substring(path.length() - 25, path.length());
+		}
+		return NLS.bind(XMLUIMessages.Open, path);
+	}
+
+	public void open() {
+		if ((fFile != null) && fFile.exists()) {
+			try {
+				IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
+				IEditorPart editor = IDE.openEditor(page, fFile, true);
+				// highlight range in editor if possible
+				if ((fHighlightRange != null) && (editor instanceof ITextEditor)) {
+					((ITextEditor) editor).setHighlightRange(fHighlightRange.getOffset(), fHighlightRange.getLength(), true);
+				}
+			}
+			catch (PartInitException pie) {
+				Logger.log(Logger.WARNING_DEBUG, pie.getMessage(), pie);
+			}
+		}
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/hyperlink/XMLHyperlinkDetector.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/hyperlink/XMLHyperlinkDetector.java
new file mode 100644
index 0000000..09abdc3
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/hyperlink/XMLHyperlinkDetector.java
@@ -0,0 +1,569 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.hyperlink;
+
+import java.io.File;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jface.text.hyperlink.AbstractHyperlinkDetector;
+import org.eclipse.jface.text.hyperlink.IHyperlink;
+import org.eclipse.wst.common.uriresolver.internal.provisional.URIResolverPlugin;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+import org.eclipse.wst.sse.core.utils.StringUtils;
+import org.eclipse.wst.xml.core.internal.XMLCorePlugin;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalog;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalogEntry;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.INextCatalog;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.contentmodel.basic.CMNamedNodeMapImpl;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.DOMNamespaceHelper;
+import org.eclipse.wst.xml.core.internal.modelquery.ModelQueryUtil;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMAttr;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.w3c.dom.Attr;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+import com.ibm.icu.util.StringTokenizer;
+
+/**
+ * Detects hyperlinks in XML tags. Includes detection in DOCTYPE and attribute
+ * values. Resolves references to schemas, dtds, etc using the Common URI
+ * Resolver.
+ * 
+ */
+public class XMLHyperlinkDetector extends AbstractHyperlinkDetector {
+	private final String NO_NAMESPACE_SCHEMA_LOCATION = "noNamespaceSchemaLocation"; //$NON-NLS-1$
+	private final String SCHEMA_LOCATION = "schemaLocation"; //$NON-NLS-1$
+	private final String XMLNS = "xmlns"; //$NON-NLS-1$
+	private final String XSI_NAMESPACE_URI = "http://www.w3.org/2001/XMLSchema-instance"; //$NON-NLS-1$
+
+	/**
+	 * Create the appropriate hyperlink
+	 * 
+	 * @param uriString
+	 * @param hyperlinkRegion
+	 * @return IHyperlink
+	 */
+	private IHyperlink createHyperlink(String uriString, IRegion hyperlinkRegion, IDocument document, Node node) {
+		IHyperlink link = null;
+
+		ICatalogEntry entry = getCatalogEntry(uriString);
+		if (entry != null) {
+			link = new CatalogEntryHyperlink(hyperlinkRegion, entry);
+		}
+		else {
+			// try to locate the file in the workspace
+			File systemFile = getFileFromUriString(uriString);
+			if (systemFile != null) {
+				String systemPath = systemFile.getPath();
+				IFile file = getFile(systemPath);
+				if (file != null) {
+					// this is a WorkspaceFileHyperlink since file exists in
+					// workspace
+					link = new WorkspaceFileHyperlink(hyperlinkRegion, file);
+				}
+				else {
+					// this is an ExternalFileHyperlink since file does not
+					// exist in workspace
+					link = new ExternalFileHyperlink(hyperlinkRegion, systemFile);
+				}
+			}
+		}
+		return link;
+	}
+
+	public IHyperlink[] detectHyperlinks(ITextViewer textViewer, IRegion region, boolean canShowMultipleHyperlinks) {
+		// for now, only capable of creating 1 hyperlink
+		List hyperlinks = new ArrayList(0);
+
+		if ((region != null) && (textViewer != null)) {
+			IDocument document = textViewer.getDocument();
+			Node currentNode = getCurrentNode(document, region.getOffset());
+			if (currentNode != null) {
+				String uriString = null;
+				if (currentNode.getNodeType() == Node.DOCUMENT_TYPE_NODE) {
+					// doctype nodes
+					uriString = getURIString(currentNode, document);
+				}
+				else if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
+					// element nodes
+					Attr currentAttr = getCurrentAttrNode(currentNode, region.getOffset());
+					if (currentAttr != null) {
+						// try to find link for current attribute
+						// resolve attribute value
+						uriString = getURIString(currentAttr, document);
+						// verify validity of uri string
+						if ((uriString == null) || !isValidURI(uriString)) {
+							// reset current attribute
+							currentAttr = null;
+						}
+					}
+					if (currentAttr == null) {
+						// try to find a linkable attribute within element
+						currentAttr = getLinkableAttr((Element) currentNode);
+						if (currentAttr != null) {
+							uriString = getURIString(currentAttr, document);
+						}
+					}
+					currentNode = currentAttr;
+				}
+				// try to create hyperlink from information gathered
+				if ((uriString != null) && (currentNode != null) && isValidURI(uriString)) {
+					IRegion hyperlinkRegion = getHyperlinkRegion(currentNode);
+					IHyperlink hyperlink = createHyperlink(uriString, hyperlinkRegion, document, currentNode);
+					if (hyperlink != null) {
+						hyperlinks.add(hyperlink);
+					}
+				}
+			}
+		}
+		if (hyperlinks.size() == 0) {
+			return null;
+		}
+		return (IHyperlink[]) hyperlinks.toArray(new IHyperlink[0]);
+	}
+
+	/**
+	 * Get the base location from the current model (local file system)
+	 */
+	private String getBaseLocation(IDocument document) {
+		String result = null;
+
+		// get the base location from the current model
+		IStructuredModel sModel = null;
+		try {
+			sModel = StructuredModelManager.getModelManager().getExistingModelForRead(document);
+			if (sModel != null) {
+				result = sModel.getBaseLocation();
+				
+				IPath path = new Path(result);
+				if (path.segmentCount() > 1) {
+					IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(path);
+					if (file.exists()) {
+						String baseLocation = null;
+						if (file.getLocation() != null) {
+							baseLocation = file.getLocation().toString();
+						}
+						if (baseLocation == null && file.getLocationURI() != null) {
+							baseLocation = file.getLocationURI().toString();
+						}
+						if (baseLocation == null) {
+							baseLocation = file.getFullPath().toString();
+						}
+						result = baseLocation;
+					}
+				}
+			}
+		}
+		finally {
+			if (sModel != null) {
+				sModel.releaseFromRead();
+			}
+		}
+		return result;
+	}
+
+	/**
+	 * Get the CMElementDeclaration for an element
+	 * 
+	 * @param element
+	 * @return CMElementDeclaration
+	 */
+	private CMElementDeclaration getCMElementDeclaration(Element element) {
+		CMElementDeclaration ed = null;
+
+		ModelQuery mq = ModelQueryUtil.getModelQuery(element.getOwnerDocument());
+		if (mq != null) {
+			ed = mq.getCMElementDeclaration(element);
+		}
+		return ed;
+	}
+
+	/**
+	 * Returns the attribute node within node at offset
+	 * 
+	 * @param node
+	 * @param offset
+	 * @return Attr
+	 */
+	private Attr getCurrentAttrNode(Node node, int offset) {
+		if ((node instanceof IndexedRegion) && ((IndexedRegion) node).contains(offset) && (node.hasAttributes())) {
+			NamedNodeMap attrs = node.getAttributes();
+			// go through each attribute in node and if attribute contains
+			// offset, return that attribute
+			for (int i = 0; i < attrs.getLength(); ++i) {
+				// assumption that if parent node is of type IndexedRegion,
+				// then its attributes will also be of type IndexedRegion
+				IndexedRegion attRegion = (IndexedRegion) attrs.item(i);
+				if (attRegion.contains(offset)) {
+					return (Attr) attrs.item(i);
+				}
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * Returns the node the cursor is currently on in the document. null if no
+	 * node is selected
+	 * 
+	 * @param offset
+	 * @return Node either element, doctype, text, or null
+	 */
+	private Node getCurrentNode(IDocument document, int offset) {
+		// get the current node at the offset (returns either: element,
+		// doctype, text)
+		IndexedRegion inode = null;
+		IStructuredModel sModel = null;
+		try {
+			sModel = StructuredModelManager.getModelManager().getExistingModelForRead(document);
+			if (sModel != null) {
+				inode = sModel.getIndexedRegion(offset);
+				if (inode == null) {
+					inode = sModel.getIndexedRegion(offset - 1);
+				}
+			}
+		}
+		finally {
+			if (sModel != null) {
+				sModel.releaseFromRead();
+			}
+		}
+
+		if (inode instanceof Node) {
+			return (Node) inode;
+		}
+		return null;
+	}
+
+	/**
+	 * Returns an IFile from the given uri if possible, null if cannot find
+	 * file from uri.
+	 * 
+	 * @param fileString
+	 *            file system path
+	 * @return returns IFile if fileString exists in the workspace
+	 */
+	private IFile getFile(String fileString) {
+		IFile file = null;
+
+		if (fileString != null) {
+			Path filePath = new Path(fileString);
+			if (filePath.segmentCount() > 1 && ResourcesPlugin.getWorkspace().getRoot().getFile(filePath).exists()) {
+				return ResourcesPlugin.getWorkspace().getRoot().getFile(filePath);
+			}
+			IFile[] files = ResourcesPlugin.getWorkspace().getRoot().findFilesForLocation(filePath);
+			for (int i = 0; (i < files.length) && (file == null); i++) {
+				if (files[i].exists()) {
+					file = files[i];
+				}
+			}
+		}
+
+		return file;
+	}
+
+	/**
+	 * Create a file from the given uri string
+	 * 
+	 * @param uriString -
+	 *            assumes uriString is not http://
+	 * @return File created from uriString if possible, null otherwise
+	 */
+	private File getFileFromUriString(String uriString) {
+		File file = null;
+		try {
+			// first just try to create a file directly from uriString as
+			// default in case create file from uri does not work
+			file = new File(uriString);
+
+			// try to create file from uri
+			URI uri = new URI(uriString);
+			file = new File(uri);
+		}
+		catch (Exception e) {
+			// if exception is thrown while trying to create File just ignore
+			// and file will be null
+		}
+		return file;
+	}
+
+	private IRegion getHyperlinkRegion(Node node) {
+		IRegion hyperRegion = null;
+
+		if (node != null) {
+			short nodeType = node.getNodeType();
+			if (nodeType == Node.DOCUMENT_TYPE_NODE) {
+				// handle doc type node
+				IDOMNode docNode = (IDOMNode) node;
+				hyperRegion = new Region(docNode.getStartOffset(), docNode.getEndOffset() - docNode.getStartOffset());
+			}
+			else if (nodeType == Node.ATTRIBUTE_NODE) {
+				// handle attribute nodes
+				IDOMAttr att = (IDOMAttr) node;
+				// do not include quotes in attribute value region
+				int regOffset = att.getValueRegionStartOffset();
+				ITextRegion valueRegion = att.getValueRegion();
+				if (valueRegion != null) {
+					int regLength = valueRegion.getTextLength();
+					String attValue = att.getValueRegionText();
+					if (StringUtils.isQuoted(attValue)) {
+						++regOffset;
+						regLength = regLength - 2;
+					}
+					hyperRegion = new Region(regOffset, regLength);
+				}
+			}
+		}
+		return hyperRegion;
+	}
+
+	/**
+	 * Attempts to find an attribute within element that is openable.
+	 * 
+	 * @param element -
+	 *            cannot be null
+	 * @return Attr attribute that can be used for open on, null if no
+	 *         attribute could be found
+	 */
+	private Attr getLinkableAttr(Element element) {
+		CMElementDeclaration ed = getCMElementDeclaration(element);
+		// get the list of attributes for this node
+		NamedNodeMap attrs = element.getAttributes();
+		for (int i = 0; i < attrs.getLength(); ++i) {
+			// check if this attribute is "openOn-able"
+			Attr att = (Attr) attrs.item(i);
+			if (isLinkableAttr(att, ed)) {
+				return att;
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * Find the location hint for the given namespaceURI if it exists
+	 * 
+	 * @param elementNode -
+	 *            cannot be null
+	 * @param namespaceURI -
+	 *            cannot be null
+	 * @return location hint (systemId) if it was found, null otherwise
+	 */
+	private String getLocationHint(Element elementNode, String namespaceURI) {
+		Attr schemaLocNode = elementNode.getAttributeNodeNS(XSI_NAMESPACE_URI, SCHEMA_LOCATION);
+		if (schemaLocNode != null) {
+			StringTokenizer st = new StringTokenizer(schemaLocNode.getValue());
+			while (st.hasMoreTokens()) {
+				String publicId = st.hasMoreTokens() ? st.nextToken() : null;
+				String systemId = st.hasMoreTokens() ? st.nextToken() : null;
+				// found location hint
+				if (namespaceURI.equalsIgnoreCase(publicId)) {
+					return systemId;
+				}
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * Returns the URI string
+	 * 
+	 * @param node -
+	 *            assumes not null
+	 */
+	private String getURIString(Node node, IDocument document) {
+		String resolvedURI = null;
+		// need the base location, publicId, and systemId for URIResolver
+		String baseLoc = null;
+		String publicId = null;
+		String systemId = null;
+
+		short nodeType = node.getNodeType();
+		// handle doc type node
+		if (nodeType == Node.DOCUMENT_TYPE_NODE) {
+			baseLoc = getBaseLocation(document);
+			publicId = ((DocumentType) node).getPublicId();
+			systemId = ((DocumentType) node).getSystemId();
+		}
+		else if (nodeType == Node.ATTRIBUTE_NODE) {
+			// handle attribute node
+			Attr attrNode = (Attr) node;
+			String attrName = attrNode.getName();
+			String attrValue = attrNode.getValue();
+			attrValue = StringUtils.strip(attrValue);
+			if ((attrValue != null) && (attrValue.length() > 0)) {
+				baseLoc = getBaseLocation(document);
+
+				// handle schemaLocation attribute
+				String prefix = DOMNamespaceHelper.getPrefix(attrName);
+				String unprefixedName = DOMNamespaceHelper.getUnprefixedName(attrName);
+				if ((XMLNS.equals(prefix)) || (XMLNS.equals(unprefixedName))) {
+					publicId = attrValue;
+					systemId = getLocationHint(attrNode.getOwnerElement(), publicId);
+					if (systemId == null) {
+						systemId = attrValue;
+					}
+				}
+				else if ((XSI_NAMESPACE_URI.equals(DOMNamespaceHelper.getNamespaceURI(attrNode))) && (SCHEMA_LOCATION.equals(unprefixedName))) {
+					// for now just use the first pair
+					// need to look into being more precise
+					StringTokenizer st = new StringTokenizer(attrValue);
+					publicId = st.hasMoreTokens() ? st.nextToken() : null;
+					systemId = st.hasMoreTokens() ? st.nextToken() : null;
+					// else check if xmlns publicId = value
+				}
+				else {
+					systemId = attrValue;
+				}
+			}
+		}
+
+		resolvedURI = resolveURI(baseLoc, publicId, systemId);
+		return resolvedURI;
+	}
+
+	/**
+	 * Checks to see if the given attribute is openable. Attribute is openable
+	 * if it is a namespace declaration attribute or if the attribute value is
+	 * of type URI.
+	 * 
+	 * @param attr
+	 *            cannot be null
+	 * @param cmElement
+	 *            CMElementDeclaration associated with the attribute (can be
+	 *            null)
+	 * @return true if this attribute is "openOn-able" false otherwise
+	 */
+	private boolean isLinkableAttr(Attr attr, CMElementDeclaration cmElement) {
+		String attrName = attr.getName();
+		String prefix = DOMNamespaceHelper.getPrefix(attrName);
+		String unprefixedName = DOMNamespaceHelper.getUnprefixedName(attrName);
+		// determine if attribute is namespace declaration
+		if ((XMLNS.equals(prefix)) || (XMLNS.equals(unprefixedName))) {
+			return true;
+		}
+
+		// determine if attribute contains schema location
+		if ((XSI_NAMESPACE_URI.equals(DOMNamespaceHelper.getNamespaceURI(attr))) && ((SCHEMA_LOCATION.equals(unprefixedName)) || (NO_NAMESPACE_SCHEMA_LOCATION.equals(unprefixedName)))) {
+			return true;
+		}
+
+		// determine if attribute value is of type URI
+		if (cmElement != null) {
+			CMNamedNodeMap attrDecls = cmElement.getAttributes();
+			CMNamedNodeMapImpl allAttributes = new CMNamedNodeMapImpl(attrDecls);
+			List nodes = ModelQueryUtil.getModelQuery(attr.getOwnerDocument()).getAvailableContent(attr.getOwnerElement(), cmElement, ModelQuery.INCLUDE_ATTRIBUTES);
+			for (int k = 0; k < nodes.size(); k++) {
+				CMNode cmnode = (CMNode) nodes.get(k);
+				if (cmnode.getNodeType() == CMNode.ATTRIBUTE_DECLARATION) {
+					allAttributes.put(cmnode);
+				}
+			}
+			attrDecls = allAttributes;
+
+			CMAttributeDeclaration attrDecl = (CMAttributeDeclaration) attrDecls.getNamedItem(attrName);
+			if ((attrDecl != null) && (attrDecl.getAttrType() != null) && (CMDataType.URI.equals(attrDecl.getAttrType().getDataTypeName()))) {
+				return true;
+			}
+		}
+		return false;
+	}
+
+	/**
+	 * Checks whether the given uriString is really pointing to a file
+	 * 
+	 * @param uriString
+	 * @return boolean
+	 */
+	private boolean isValidURI(String uriString) {
+		boolean isValid = false;
+
+		if (getCatalogEntry(uriString) != null) {
+			isValid = true;
+		}
+		else {
+			File file = getFileFromUriString(uriString);
+			if (file != null) {
+				isValid = file.isFile();
+			}
+			if(!isValid) {
+			}
+			
+		}
+		return isValid;
+	}
+
+	/**
+	 * @param uriString
+	 * @return
+	 */
+	private ICatalogEntry getCatalogEntry(String uriString) {
+		ICatalog defaultCatalog = XMLCorePlugin.getDefault().getDefaultXMLCatalog();
+		if (defaultCatalog != null) {
+			// Process default catalog
+			ICatalogEntry[] entries = defaultCatalog.getCatalogEntries();
+			for (int entry = 0; entry < entries.length; entry++) {
+				if (uriString.equals(entries[entry].getKey())||uriString.equals(entries[entry].getURI())) {
+					return entries[entry];
+				}
+			}
+
+			// Process declared OASIS nextCatalogs catalog
+			INextCatalog[] nextCatalogs = defaultCatalog.getNextCatalogs();
+			for (int nextCatalog = 0; nextCatalog < nextCatalogs.length; nextCatalog++) {
+				ICatalog catalog = nextCatalogs[nextCatalog].getReferencedCatalog();
+				ICatalogEntry[] entries2 = catalog.getCatalogEntries();
+				for (int entry = 0; entry < entries2.length; entry++) {
+					if (uriString.equals(entries2[entry].getKey())||uriString.equals(entries2[entry].getURI()))
+						return entries2[entry];
+				}
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * Resolves the given URI information
+	 * 
+	 * @param baseLocation
+	 * @param publicId
+	 * @param systemId
+	 * @return String resolved uri.
+	 */
+	private String resolveURI(String baseLocation, String publicId, String systemId) {
+		// dont resolve if there's nothing to resolve
+		if ((baseLocation == null) && (publicId == null) && (systemId == null)) {
+			return null;
+		}
+		return URIResolverPlugin.createResolver().resolve(baseLocation, publicId, systemId);
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/nsedit/CommonAddNamespacesControl.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/nsedit/CommonAddNamespacesControl.java
new file mode 100644
index 0000000..5a2d83c
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/nsedit/CommonAddNamespacesControl.java
@@ -0,0 +1,282 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.nsedit;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.part.PageBook;
+import org.eclipse.wst.common.uriresolver.internal.provisional.URIResolverPlugin;
+import org.eclipse.wst.common.uriresolver.internal.util.URIHelper;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.NamespaceInfo;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+import org.eclipse.wst.xml.ui.internal.dialogs.SelectFileOrXMLCatalogIdDialog;
+
+public class CommonAddNamespacesControl extends Composite implements SelectionListener {
+
+	class EditNamespaceControl extends Composite {
+		protected Button browseButton;
+		Text locationHintField;
+		Text prefixField;
+		Text uriField;
+
+		// protected NamespaceInfo info;
+
+		public EditNamespaceControl(Composite parent) {
+			super(parent, SWT.NONE); // BORDER);
+			setLayout(new GridLayout());
+			setLayoutData(new GridData(GridData.FILL_BOTH));
+
+			Label label = new Label(this, SWT.NONE);
+			label.setText(XMLUIMessages._UI_ENTER_REQ_PREFIX_AND_NAMESPACE);
+
+			Composite composite = new Composite(this, SWT.NONE);
+			GridLayout layout = new GridLayout();
+			layout.numColumns = 3;
+			layout.marginWidth = 0;
+			layout.verticalSpacing = 1;
+			composite.setLayout(layout);
+
+			GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+			gd.widthHint = 350;
+			composite.setLayoutData(gd);
+
+			// row 1
+			//
+			Label prefixLabel = new Label(composite, SWT.NONE);
+			prefixLabel.setText(XMLUIMessages._UI_LABEL_PREFIX_COLON);
+
+			prefixField = new Text(composite, SWT.SINGLE | SWT.BORDER);
+			prefixField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+			// prefixField.setText(getDisplayValue(info.prefix));
+			// prefixField.addModifyListener(modifyListener);
+			// prefixField.setEnabled(info.getProperty("prefix-readOnly") ==
+			// null);
+			new Label(composite, SWT.NONE);
+
+			// row 2
+			//
+			Label uriLabel = new Label(composite, SWT.NONE);
+			uriLabel.setText(XMLUIMessages._UI_LABEL_NAMESPACE_NAME_COLON);
+
+			uriField = new Text(composite, SWT.SINGLE | SWT.BORDER);
+			uriField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+			// uriField.setText(getDisplayValue(info.uri));
+			// uriField.addModifyListener(modifyListener);
+			// uriField.setEnabled(info.getProperty("uri-readOnly") == null);
+
+			new Label(composite, SWT.NONE);
+
+			// row 3
+			//
+			Label locationHintLabel = new Label(composite, SWT.NONE);
+			locationHintLabel.setText(XMLUIMessages._UI_LABEL_LOCATION_HINT_COLON);
+
+			locationHintField = new Text(composite, SWT.SINGLE | SWT.BORDER);
+			locationHintField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+			// locationHintField.setText(getDisplayValue(info.locationHint));
+			// locationHintField.addModifyListener(modifyListener);
+			// locationHintField.setEnabled(info.getProperty("locationHint-readOnly")
+			// == null);
+
+			SelectionListener selectionListener = new SelectionAdapter() {
+				public void widgetSelected(SelectionEvent e) {
+					performBrowse();
+				}
+			};
+
+			browseButton = new Button(composite, SWT.NONE);
+			browseButton.setText(XMLUIMessages._UI_LABEL_BROWSE);
+			browseButton.addSelectionListener(selectionListener);
+			browseButton.setEnabled(locationHintField.getEnabled());
+		}
+
+		protected void performBrowse() {
+			String[] extensions = {".xsd"}; //$NON-NLS-1$
+			SelectFileOrXMLCatalogIdDialog dialog = new SelectFileOrXMLCatalogIdDialog(getShell(), extensions);
+			dialog.create();
+			dialog.getShell().setText(XMLUIMessages._UI_LABEL_SELECT_FILE);
+			dialog.setBlockOnOpen(true);
+			dialog.open();
+
+			if (dialog.getReturnCode() == Window.OK) {
+				// String grammarURI = null;
+				IFile file = dialog.getFile();
+				String id = dialog.getId();
+				if (file != null) {
+					String uri = null;
+					if (resourceLocation != null) {
+						IResource resource = ResourcesPlugin.getWorkspace().getRoot().findMember(resourceLocation);
+						if (resource != null) {
+							IPath location = resource.getLocation();
+							if (location != null) {
+								uri = URIHelper.getRelativeURI(file.getLocation(), location);
+							}
+						}
+	                    else {
+	                      uri = URIHelper.getRelativeURI(file.getLocation(), resourceLocation);
+	                    }
+						// grammarURI = file.getLocation().toOSString();
+					}
+					else {
+						uri = file.getLocation().toOSString();
+						// grammarURI = uri;
+					}
+					locationHintField.setText(uri);
+				}
+				else if (id != null) {
+					locationHintField.setText(id);
+					// URIResolver resolver =
+					URIResolverPlugin.createResolver();
+					// grammarURI = resolver.resolve(null, id, id);
+				}
+
+				try {
+					// TODO CMDocument document =
+					// CMDocumentBuilderRegistry.getInstance().buildCMDocument(grammarURI);
+					// List namespaceInfoList =
+					// (List)document.getProperty("http://org.eclipse.wst/cm/properties/namespaceInfo");
+					// NamespaceInfo info =
+					// (NamespaceInfo)namespaceInfoList.get(0);
+					// if (uriField.getText().trim().length() == 0 && info.uri
+					// != null)
+					// {
+					// uriField.setText(info.uri);
+					// }
+					// if (prefixField.getText().trim().length() == 0 &&
+					// info.prefix != null)
+					// {
+					// prefixField.setText(info.prefix);
+					// }
+				}
+				catch (Exception e) {
+				}
+			}
+		}
+	}
+
+	protected Button deleteButton;
+	protected Button editButton;
+	protected EditNamespaceControl editNamespaceControl;
+	protected int heightHint = 250;
+	protected List namespaceInfoList = new ArrayList();
+	protected Button newButton;
+	protected PageBook pageBook;
+	protected Button radio1;
+	protected Button radio2;
+	protected IPath resourceLocation;
+	protected Composite tableSection;
+	protected CommonNamespaceInfoTable tableViewer;
+	protected int widthHint = 500;
+
+
+	public CommonAddNamespacesControl(Composite parent, int style, IPath resourceLocation) {
+		super(parent, style);
+		this.resourceLocation = resourceLocation;
+		GridData gd = new GridData(GridData.FILL_BOTH);
+		if (widthHint != -1) {
+			gd.widthHint = widthHint;
+		}
+		if (heightHint != -1) {
+			gd.heightHint = heightHint;
+		}
+		setLayoutData(gd);
+		setLayout(new GridLayout());
+
+		radio1 = new Button(this, SWT.RADIO);
+		radio1.setText(XMLUIMessages._UI_SELECT_REGISTERED_NAMESPACES);
+		radio1.setSelection(true);
+		radio1.addSelectionListener(this);
+
+		radio2 = new Button(this, SWT.RADIO);
+		radio2.setText(XMLUIMessages._UI_SPECIFY_NEW_NAMESPACE);
+		radio2.addSelectionListener(this);
+
+		Label separator = new Label(this, SWT.SEPARATOR | SWT.HORIZONTAL);
+		separator.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+		// Group namespaceInfoGroup = new Group(this, SWT.NONE);
+		// namespaceInfoGroup.setText("Namespace Declarations");
+		// //XMLCommonUIPlugin.getInstance().getString("_UI_LABEL_XML_SCHEMA_INFORMATION"));
+		// namespaceInfoGroup.setLayout(new GridLayout(2, false));
+		// namespaceInfoGroup.setLayoutData(new GridData(GridData.FILL_BOTH));
+		pageBook = new PageBook(this, SWT.NONE);
+		pageBook.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+		tableSection = new Composite(pageBook, SWT.NONE);
+		tableSection.setLayout(new GridLayout());
+		Label label = new Label(tableSection, SWT.NONE);
+		label.setText(XMLUIMessages._UI_SELECT_NAMESPACE_TO_ADD);
+
+		tableViewer = new CommonNamespaceInfoTable(tableSection, SWT.CHECK, 6);
+		editNamespaceControl = new EditNamespaceControl(pageBook);
+		pageBook.showPage(tableSection);
+
+		tableViewer.setInput(namespaceInfoList);
+	}
+
+
+
+	public List getNamespaceInfoList() {
+		List list = new ArrayList();
+		if (radio1.getSelection()) {
+			TableItem[] items = tableViewer.getTable().getItems();
+			for (int i = 0; i < items.length; i++) {
+				TableItem item = items[i];
+				if (item.getChecked()) {
+					list.add(item.getData());
+				}
+			}
+		}
+		else {
+			NamespaceInfo info = new NamespaceInfo();
+			info.prefix = editNamespaceControl.prefixField.getText();
+			info.uri = editNamespaceControl.uriField.getText();
+			info.locationHint = editNamespaceControl.locationHintField.getText();
+			list.add(info);
+		}
+		return list;
+	}
+
+	public void setNamespaceInfoList(List list) {
+		namespaceInfoList = list;
+		tableViewer.setInput(namespaceInfoList);
+	}
+
+	public void widgetDefaultSelected(SelectionEvent e) {
+	}
+
+	public void widgetSelected(SelectionEvent e) {
+		if (e.widget == radio1) {
+			pageBook.showPage(tableSection);
+		}
+		else if (e.widget == radio2) {
+			pageBook.showPage(editNamespaceControl);
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/nsedit/CommonAddNamespacesDialog.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/nsedit/CommonAddNamespacesDialog.java
new file mode 100644
index 0000000..269113f
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/nsedit/CommonAddNamespacesDialog.java
@@ -0,0 +1,205 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.nsedit;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.wst.xml.core.internal.XMLCorePlugin;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalog;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalogEntry;
+import org.eclipse.wst.xml.core.internal.catalog.provisional.INextCatalog;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.NamespaceInfo;
+
+
+
+public class CommonAddNamespacesDialog extends Dialog {
+	protected CommonAddNamespacesControl addNamespacesControl;
+	protected List existingNamespaces;
+	protected List namespaceInfoList;
+	protected Button okButton;
+	protected HashMap preferredPrefixTable = new HashMap();
+	protected IPath resourceLocation;
+	protected String title;
+
+	public CommonAddNamespacesDialog(Shell parentShell, String title, IPath resourceLocation, List existingNamespaces) {
+		super(parentShell);
+		this.resourceLocation = resourceLocation;
+		setShellStyle(getShellStyle() | SWT.RESIZE);
+		this.title = title;
+		this.existingNamespaces = existingNamespaces;
+		preferredPrefixTable.put("http://schemas.xmlsoap.org/wsdl/", "wsdl"); //$NON-NLS-1$ //$NON-NLS-2$
+		preferredPrefixTable.put("http://schemas.xmlsoap.org/wsdl/soap/", "soap"); //$NON-NLS-1$ //$NON-NLS-2$
+		preferredPrefixTable.put("http://schemas.xmlsoap.org/wsdl/http/", "http"); //$NON-NLS-1$ //$NON-NLS-2$
+		preferredPrefixTable.put("http://schemas.xmlsoap.org/wsdl/mime/", "mime"); //$NON-NLS-1$ //$NON-NLS-2$
+		preferredPrefixTable.put("http://schemas.xmlsoap.org/soap/encoding/", "soapenc"); //$NON-NLS-1$ //$NON-NLS-2$
+		preferredPrefixTable.put("http://schemas.xmlsoap.org/soap/envelope/", "soapenv"); //$NON-NLS-1$ //$NON-NLS-2$
+		preferredPrefixTable.put("http://www.w3.org/2001/XMLSchema-instance", "xsi"); //$NON-NLS-1$ //$NON-NLS-2$
+		preferredPrefixTable.put("http://www.w3.org/2001/XMLSchema", "xsd"); //$NON-NLS-1$ //$NON-NLS-2$
+	}
+
+	protected void addBuiltInNamespaces(List list) {
+		String xsiNamespace = "http://www.w3.org/2001/XMLSchema-instance"; //$NON-NLS-1$
+		String xsdNamespace = "http://www.w3.org/2001/XMLSchema"; //$NON-NLS-1$
+		if (!isAlreadyDeclared(xsiNamespace)) {
+			list.add(new NamespaceInfo("http://www.w3.org/2001/XMLSchema-instance", "xsi", null)); //$NON-NLS-1$ //$NON-NLS-2$
+		}
+		if (!isAlreadyDeclared(xsdNamespace)) {
+			list.add(new NamespaceInfo("http://www.w3.org/2001/XMLSchema", "xsd", null)); //$NON-NLS-1$ //$NON-NLS-2$
+		}
+	}
+
+	protected void addCatalogMapToList(ICatalog catalog, List list) {
+		ICatalogEntry[] entries = catalog.getCatalogEntries();
+		for (int i = 0; i < entries.length; i++) {
+			ICatalogEntry entry = entries[i];
+			if ((entry.getEntryType() == ICatalogEntry.ENTRY_TYPE_PUBLIC) && entry.getURI().endsWith(".xsd")) { //$NON-NLS-1$
+				if (!isAlreadyDeclared(entry.getKey())) {
+					NamespaceInfo namespaceInfo = new NamespaceInfo(entry.getKey(), "xx", null); //$NON-NLS-1$
+					list.add(namespaceInfo);
+				}
+			}
+		}
+	}
+
+	protected void buttonPressed(int buttonId) {
+		if (buttonId == IDialogConstants.OK_ID) {
+			namespaceInfoList = addNamespacesControl.getNamespaceInfoList();
+		}
+		super.buttonPressed(buttonId);
+	}
+
+	public void computeAddablePrefixes(List addableList, List exisitingList) {
+		HashMap map = new HashMap();
+		for (Iterator i = exisitingList.iterator(); i.hasNext();) {
+			NamespaceInfo info = (NamespaceInfo) i.next();
+			if (info.prefix != null) {
+				map.put(info.prefix, info);
+			}
+		}
+		for (Iterator i = addableList.iterator(); i.hasNext();) {
+			NamespaceInfo info = (NamespaceInfo) i.next();
+			if (info.uri != null) {
+				String prefix = (String) preferredPrefixTable.get(info.uri);
+				info.prefix = getUniquePrefix(map, prefix, info.uri);
+				map.put(info.prefix, info);
+			}
+		}
+	}
+
+	public int createAndOpen() {
+		create();
+		getShell().setText(title);
+		Rectangle r = getShell().getBounds();
+		getShell().setBounds(r.x + 80, r.y + 80, r.width, r.height);
+		setBlockOnOpen(true);
+		return open();
+	}
+
+	protected void createButtonsForButtonBar(Composite parent) {
+		okButton = createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
+		createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false);
+	}
+
+	protected Control createContents(Composite parent) {
+		Control control = super.createContents(parent);
+		return control;
+	}
+
+
+
+	protected Control createDialogArea(Composite parent) {
+		Composite dialogArea = (Composite) super.createDialogArea(parent);
+		addNamespacesControl = new CommonAddNamespacesControl(dialogArea, SWT.NONE, resourceLocation);
+		List list = new ArrayList();
+
+		addBuiltInNamespaces(list);
+		ICatalog defaultCatalog = XMLCorePlugin.getDefault().getDefaultXMLCatalog();
+		INextCatalog[] nextCatalogs = defaultCatalog.getNextCatalogs();
+		for (int i = 0; i < nextCatalogs.length; i++) {
+			INextCatalog catalog = nextCatalogs[i];
+			ICatalog referencedCatalog = catalog.getReferencedCatalog();
+			if (referencedCatalog != null) {
+				if (XMLCorePlugin.USER_CATALOG_ID.equals(referencedCatalog.getId())) {
+					ICatalog userCatalog = referencedCatalog;
+					addCatalogMapToList(userCatalog, list);
+
+				}
+				else if (XMLCorePlugin.SYSTEM_CATALOG_ID.equals(referencedCatalog.getId())) {
+					ICatalog systemCatalog = referencedCatalog;
+					addCatalogMapToList(systemCatalog, list);
+				}
+			}
+		}
+
+		computeAddablePrefixes(list, existingNamespaces);
+
+		addNamespacesControl.setNamespaceInfoList(list);
+		return dialogArea;
+	}
+
+	public List getNamespaceInfoList() {
+		return namespaceInfoList;
+	}
+
+	protected String getPreferredPrefix(String namespaceURI) {
+		return (String) preferredPrefixTable.get(namespaceURI);
+	}
+
+	private String getUniquePrefix(HashMap prefixMap, String prefix, String uri) {
+		if (prefix == null) {
+			int lastIndex = uri.lastIndexOf('/');
+			if (lastIndex == uri.length() - 1) {
+				uri = uri.substring(0, lastIndex);
+				lastIndex = uri.lastIndexOf('/');
+			}
+			prefix = uri.substring(lastIndex + 1);
+			if ((prefix.length() > 20) || (prefix.indexOf(':') != -1)) {
+				prefix = null;
+			}
+		}
+		if (prefix == null) {
+			prefix = "p"; //$NON-NLS-1$
+		}
+		if (prefixMap.get(prefix) != null) {
+			String base = prefix;
+			for (int count = 0; prefixMap.get(prefix) != null; count++) {
+				prefix = base + count;
+			}
+		}
+		return prefix;
+	}
+
+	protected boolean isAlreadyDeclared(String namespaceURI) {
+		boolean result = false;
+		for (Iterator i = existingNamespaces.iterator(); i.hasNext();) {
+			NamespaceInfo namespaceInfo = (NamespaceInfo) i.next();
+			if (namespaceURI.equals(namespaceInfo.uri)) {
+				result = true;
+				break;
+			}
+		}
+		return result;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/nsedit/CommonEditNamespacesDialog.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/nsedit/CommonEditNamespacesDialog.java
new file mode 100644
index 0000000..3a358cd
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/nsedit/CommonEditNamespacesDialog.java
@@ -0,0 +1,327 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2008 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.nsedit;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.NamespaceInfo;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+import org.eclipse.wst.xml.ui.internal.XMLUIPlugin;
+import org.eclipse.wst.xml.ui.internal.dialogs.EditNamespaceInfoDialog;
+import org.eclipse.wst.xml.ui.internal.dialogs.NamespaceInfoErrorHelper;
+
+public class CommonEditNamespacesDialog {
+	protected Composite commonComposite;
+	protected Button deleteButton;
+	protected Button editButton;
+
+	protected Label errorMessageLabel;
+	protected int heightHint = 250;
+	protected List namespaceInfoList = new ArrayList();
+
+	protected Button newButton;
+	protected IPath resourceLocation;
+
+	private boolean showLocationText = false;
+	protected String tableLabel = ""; //$NON-NLS-1$
+	protected CommonNamespaceInfoTable tableViewer;
+
+	protected Composite topComposite;
+	protected boolean useGroup;
+	protected int widthHint = 500;
+
+	public CommonEditNamespacesDialog(Composite parent, IPath resourceLocation, String stringTableLabel) {
+		this(parent, resourceLocation, stringTableLabel, false, false);
+	}
+
+	public CommonEditNamespacesDialog(Composite parent, IPath resourceLocation, String stringTableLabel, boolean useGroup, boolean showLocText) {
+		this.resourceLocation = resourceLocation;
+		tableLabel = stringTableLabel;
+		this.useGroup = useGroup;
+		showLocationText = showLocText;
+
+		GridData gd = new GridData(GridData.FILL_BOTH);
+		if (widthHint != -1) {
+			gd.widthHint = widthHint;
+		}
+		if (heightHint != -1) {
+			gd.heightHint = heightHint;
+		}
+
+		// Set GridData and GridLayout for the parent Composite
+		parent.setLayoutData(gd);
+		parent.setLayout(new GridLayout());
+
+		// Create the top Composite
+		topComposite = new Composite(parent, SWT.NONE);
+		GridData topData = new GridData(GridData.FILL_HORIZONTAL);
+		topData.heightHint = 0;
+		topComposite.setLayoutData(topData);
+		topComposite.setLayout(new GridLayout());
+
+		// Create the 'common'/middle Composite
+		if (useGroup) {
+			commonComposite = new Group(parent, SWT.NONE);
+		}
+		else {
+			commonComposite = new Composite(parent, SWT.NONE);
+		}
+		commonComposite.setLayoutData(new GridData(GridData.FILL_BOTH));
+		commonComposite.setLayout(new GridLayout(3, false));
+
+		// Add the error Message Label
+		errorMessageLabel = new Label(parent, SWT.NONE);
+		errorMessageLabel.setLayoutData(createHorizontalFill());
+		Color color = new Color(errorMessageLabel.getDisplay(), 200, 0, 0);
+		errorMessageLabel.setForeground(color);
+
+		createControlArea();
+	}
+
+
+	protected void createButtons(Composite parent) {
+		Composite composite = new Composite(parent, SWT.NONE);
+		composite.setLayoutData(new GridData(GridData.FILL_VERTICAL));
+		GridLayout gridLayout = new GridLayout();
+		gridLayout.numColumns = 1;
+		gridLayout.marginHeight = 0;
+		gridLayout.marginWidth = 0;
+		composite.setLayout(gridLayout);
+
+		SelectionListener selectionListener = new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				if (e.widget == newButton) {
+					performNew();
+				}
+				else if (e.widget == editButton) {
+					performEdit();
+				}
+				else if (e.widget == deleteButton) {
+					performDelete();
+				}
+			}
+		};
+
+		// create a composite to hold the three buttons
+		Composite buttonComposite = new Composite(composite, SWT.NONE);
+		buttonComposite.setLayoutData(createHorizontalFill());
+		GridLayout buttonGridLayout = new GridLayout();
+		// buttonGridLayout.numColumns = 3;
+		// buttonGridLayout.makeColumnsEqualWidth = true;
+		buttonComposite.setLayout(buttonGridLayout);
+
+		// add the New button
+		//
+		newButton = new Button(buttonComposite, SWT.NONE);
+		// newButton.setText(" " +
+		// XMLCommonUIPlugin.getInstance().getString("_UI_BUTTON_NEW") + " ");
+		newButton.setText("   " + XMLUIMessages.CommonEditNamespacesDialog_0 + "   "); //$NON-NLS-1$ //$NON-NLS-2$ 
+		newButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); // ViewUtility.createHorizontalFill());
+		newButton.addSelectionListener(selectionListener);
+
+		// add the Edit button
+		//
+		// gd = new GridData();
+		// gd.horizontalAlignment = gd.FILL;
+		// gd.grabExcessHorizontalSpace = true;
+
+		editButton = new Button(buttonComposite, SWT.NONE);
+		editButton.setText(XMLUIMessages._UI_BUTTON_EDIT);
+		editButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); // ViewUtility.createHorizontalFill());
+		editButton.addSelectionListener(selectionListener);
+
+		// add the Delete button
+		//
+		// gd = new GridData();
+		// gd.horizontalAlignment = gd.FILL;
+		// gd.grabExcessHorizontalSpace = true;
+
+		deleteButton = new Button(buttonComposite, SWT.NONE);
+		deleteButton.setText(XMLUIMessages._UI_BUTTON_DELETE);
+		deleteButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); // ViewUtility.createHorizontalFill());
+		deleteButton.addSelectionListener(selectionListener);
+	}
+
+	private void createControlArea() {
+		if (useGroup) {
+			((Group) commonComposite).setText(tableLabel);
+		}
+		else {
+			Label label = new Label(commonComposite, SWT.NONE);
+			label.setText(tableLabel);
+			label.setLayoutData(createGridData(false, 3));
+		}
+
+		tableViewer = new CommonNamespaceInfoTable(commonComposite, 6, showLocationText);
+		tableViewer.getControl().setLayoutData(createGridData(true, 2));
+		createButtons(commonComposite);
+
+		tableViewer.setInput(namespaceInfoList);
+		updateButtonEnabledState();
+		ISelectionChangedListener selectionChangedListener = new ISelectionChangedListener() {
+			public void selectionChanged(SelectionChangedEvent event) {
+				updateButtonEnabledState();
+			}
+		};
+		tableViewer.addSelectionChangedListener(selectionChangedListener);
+	}
+
+	protected GridData createGridData(boolean both, int span) {
+		GridData gd = new GridData(both ? GridData.FILL_BOTH : GridData.FILL_HORIZONTAL);
+		gd.horizontalSpan = 2;
+		return gd;
+	}
+
+	private GridData createHorizontalFill() {
+		GridData gd = new GridData();
+		gd.horizontalAlignment = GridData.FILL;
+		gd.grabExcessHorizontalSpace = true;
+		return gd;
+	}
+
+
+
+	public NamespaceInfo getNamespaceInfo(String namespace) {
+		NamespaceInfo result = null;
+		for (Iterator i = namespaceInfoList.iterator(); i.hasNext();) {
+			NamespaceInfo info = (NamespaceInfo) i.next();
+			if ((info.uri != null) && info.uri.equals(namespace)) {
+				result = info;
+				break;
+			}
+		}
+		return result;
+	}
+
+	protected Object getSelection(ISelection selection) {
+		if (selection == null) {
+			return null;
+		} // end of if ()
+
+		Object result = null;
+		if (selection instanceof IStructuredSelection) {
+			IStructuredSelection es = (IStructuredSelection) selection;
+			Iterator i = es.iterator();
+			if (i.hasNext()) {
+				result = i.next();
+			}
+		}
+		return result;
+	}
+
+	/*
+	 * Use the returned Composite to add content above the 'common contents'.
+	 * Note: The GridData for the returned Composite has a heightHint = 0.
+	 * This means when using the returned Composite, the GridData must be
+	 * reset, else the Composite and it's contents will not appear.
+	 */
+	protected Composite getTopComposite() {
+		return topComposite;
+	}
+
+	protected EditNamespaceInfoDialog invokeDialog(String title, NamespaceInfo info) {
+		Shell shell = XMLUIPlugin.getInstance().getWorkbench().getActiveWorkbenchWindow().getShell();
+		EditNamespaceInfoDialog dialog = new EditNamespaceInfoDialog(shell, info);
+		dialog.create();
+		dialog.getShell().setText(title);
+		dialog.setBlockOnOpen(true);
+		dialog.setResourceLocation(resourceLocation);
+		dialog.open();
+		return dialog;
+	}
+
+	protected void performDelayedUpdate() {
+		tableViewer.refresh();
+		/*
+		 * Runnable delayedUpdate = new Runnable() { public void run() {
+		 * tableViewer.refresh(); } };
+		 * Display.getCurrent().asyncExec(delayedUpdate);
+		 */
+		// if (updateListener != null)
+		// {
+		// updateListener.updateOccured(this, namespaceInfoList);
+		// }
+	}
+
+	public void performDelete() {
+		ISelection selection = tableViewer.getSelection();
+		if (selection instanceof IStructuredSelection) {
+			IStructuredSelection structuredSelection = (IStructuredSelection) selection;
+			namespaceInfoList.removeAll(structuredSelection.toList());
+			updateErrorMessage(namespaceInfoList);
+			performDelayedUpdate();
+		}
+	}
+
+	public void performEdit() {
+		Object selection = getSelection(tableViewer.getSelection());
+		if (selection != null) {
+			invokeDialog(XMLUIMessages._UI_LABEL_NEW_NAMESPACE_INFORMATION, (NamespaceInfo) selection);
+			updateErrorMessage(namespaceInfoList);
+			performDelayedUpdate();
+		}
+	}
+
+	public void performNew() {
+		Shell shell = XMLUIPlugin.getInstance().getWorkbench().getActiveWorkbenchWindow().getShell();
+		CommonAddNamespacesDialog dialog = new CommonAddNamespacesDialog(shell, XMLUIMessages._UI_ADD_NAMESPACE_DECLARATIONS, resourceLocation, namespaceInfoList);
+		dialog.createAndOpen();
+		if (dialog.getReturnCode() == Window.OK) {
+			namespaceInfoList.addAll(dialog.getNamespaceInfoList());
+			updateErrorMessage(namespaceInfoList);
+			performDelayedUpdate();
+		}
+	}
+
+	public void setNamespaceInfoList(List list) {
+		namespaceInfoList = list;
+		tableViewer.setInput(namespaceInfoList);
+	}
+
+	public void updateButtonEnabledState() {
+		Object selection = getSelection(tableViewer.getSelection());
+		NamespaceInfo info = (NamespaceInfo) selection;
+		editButton.setEnabled(info != null);
+		deleteButton.setEnabled((info != null) && (info.getProperty("unremovable") == null)); //$NON-NLS-1$
+	}
+
+	public void updateErrorMessage(List namespaceInfoList) {
+		NamespaceInfoErrorHelper helper = new NamespaceInfoErrorHelper();
+		String errorMessage = helper.computeErrorMessage(namespaceInfoList, null);
+		errorMessageLabel.setText(errorMessage != null ? errorMessage : ""); //$NON-NLS-1$
+	}
+	
+	public void setResourcePath(IPath path) {
+	  resourceLocation = path;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/nsedit/CommonEditNamespacesTargetFieldDialog.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/nsedit/CommonEditNamespacesTargetFieldDialog.java
new file mode 100644
index 0000000..1f6d85a
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/nsedit/CommonEditNamespacesTargetFieldDialog.java
@@ -0,0 +1,104 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.nsedit;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.NamespaceInfo;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+
+/*
+ * This class is an extension of CommonEditNamespacesDialog. This class adds
+ * the target namespaces dialog field.
+ */
+public class CommonEditNamespacesTargetFieldDialog extends CommonEditNamespacesDialog {
+
+	class TargetNamespaceModifyListener implements ModifyListener {
+		public void modifyText(ModifyEvent e) {
+			String oldTargetNamespace = targetNamespace;
+			targetNamespace = targetNamespaceField.getText();
+			updateTargetNamespaceAndNamespaceInfo(oldTargetNamespace, targetNamespace);
+		}
+	}
+
+	protected String targetNamespace;
+	protected Text targetNamespaceField;
+
+	public CommonEditNamespacesTargetFieldDialog(Composite parent, IPath resourceLocation1) {
+		super(parent, resourceLocation1, XMLUIMessages._UI_NAMESPACE_DECLARATIONS);
+
+		Composite targetComp = getTopComposite();
+		targetComp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+		GridData gd = new GridData(GridData.FILL_BOTH);
+		Label targetNamespaceLabel = new Label(targetComp, SWT.NONE);
+		targetNamespaceLabel.setLayoutData(gd);
+		targetNamespaceLabel.setText(XMLUIMessages._UI_TARGET_NAMESPACE);
+
+		targetNamespaceField = new Text(targetComp, SWT.BORDER);
+		targetNamespaceField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+		targetNamespaceField.addModifyListener(new TargetNamespaceModifyListener());
+
+		// createControlArea();
+	}
+
+	public String getTargetNamespace() {
+		return targetNamespace;
+	}
+
+	public void performEdit() {
+		Object selection = getSelection(tableViewer.getSelection());
+		if (selection != null) {
+			boolean editTargetNamespace = false;
+			NamespaceInfo nsInfo = (NamespaceInfo) selection;
+			if (getTargetNamespace().equals(nsInfo.uri)) {
+				editTargetNamespace = true;
+			}
+
+			invokeDialog(XMLUIMessages._UI_LABEL_NEW_NAMESPACE_INFORMATION, nsInfo);
+			updateErrorMessage(namespaceInfoList);
+			performDelayedUpdate();
+
+			if (editTargetNamespace) {
+				targetNamespaceField.setText(nsInfo.uri);
+			}
+		}
+	}
+
+	public void setTargetNamespace(String theTargetNamespace) {
+		targetNamespace = theTargetNamespace != null ? theTargetNamespace : ""; //$NON-NLS-1$
+		targetNamespaceField.setText(targetNamespace);
+		// updateTargetNamespaceAndNamespaceInfo(targetNamespace);
+	}
+
+	void updateTargetNamespaceAndNamespaceInfo(String oldTargetNamespace, String newTargetNamespace) {
+		NamespaceInfo info = getNamespaceInfo(newTargetNamespace);
+		if (info == null) {
+			info = getNamespaceInfo(oldTargetNamespace);
+			if (info == null) {
+				info = new NamespaceInfo(newTargetNamespace, "tns", null); //$NON-NLS-1$
+				namespaceInfoList.add(info);
+			}
+			else {
+				info.uri = targetNamespace;
+			}
+		}
+		tableViewer.refresh();
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/nsedit/CommonNamespaceInfoTable.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/nsedit/CommonNamespaceInfoTable.java
new file mode 100644
index 0000000..44162e4
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/nsedit/CommonNamespaceInfoTable.java
@@ -0,0 +1,346 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.nsedit;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jface.viewers.ColumnWeightData;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.TableLayout;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.MouseAdapter;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.NamespaceInfo;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+
+public class CommonNamespaceInfoTable extends TableViewer {
+
+	/**
+	 * NamespaceInfoTableLabelProvider
+	 */
+	protected class Provider extends LabelProvider implements ITableLabelProvider, IStructuredContentProvider {
+		Viewer viewer;
+
+		public Image getColumnImage(Object object, int columnIndex) {
+			Image result = null;
+			int columnCode = getColumnCode(columnIndex);
+			if (columnCode == COLUMN_LOCATION_HINT) {
+				NamespaceInfo info = (NamespaceInfo) object;
+				if ((info.locationHint == null) || info.locationHint.trim().equals("")) { //$NON-NLS-1$
+					// Comment this out until we solve the alignment/(space
+					// for image being allocated
+					// to prefix column) ......
+					// result =
+					// XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_WARNING_OBJ);
+				}
+			}
+
+			return result;
+		}
+
+		public String getColumnText(Object object, int column) {
+			NamespaceInfo info = (NamespaceInfo) object;
+			String result = null;
+			int columnCode = getColumnCode(column);
+			switch (columnCode) {
+				case COLUMN_PREFIX : {
+					result = info.prefix;
+					break;
+				}
+				case COLUMN_NAMESPACE_URI : {
+					result = info.uri;
+					break;
+				}
+				case COLUMN_CHECKBOX : {
+					result = ""; // info.locationHint; //$NON-NLS-1$
+					break;
+				}
+				case COLUMN_LOCATION_HINT : {
+					result = info.locationHint;
+					break;
+				}
+			}
+			result = result != null ? result : ""; //$NON-NLS-1$
+			if (result.equals("")) { //$NON-NLS-1$
+				switch (columnCode) {
+					case COLUMN_PREFIX : {
+						result = XMLUIMessages._UI_NO_PREFIX;
+						break;
+					}
+					case COLUMN_NAMESPACE_URI : {
+						result = XMLUIMessages._UI_NO_NAMESPACE_NAME;
+						break;
+					}
+				}
+			}
+			return result;
+		}
+
+		public Object[] getElements(Object inputElement) {
+			List list = (List) viewer.getInput();
+			return list != null ? list.toArray() : null;
+		}
+
+		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+			this.viewer = viewer;
+		}
+	}
+
+	class TableItemChecker extends MouseAdapter {
+		public void mouseDown(MouseEvent e) {
+			TableItem item = getTable().getItem(new Point(e.x, e.y));
+			if (item != null) {
+				Object obj = item.getData();
+				if (obj != null) {
+					NamespaceInfo info = (NamespaceInfo) obj;
+					TableColumn col = getTable().getColumn(0);
+					if (e.x < col.getWidth()) // if the point falls within
+												// the
+					// Select column then perform
+					// check/uncheck
+					{
+						String currentState = (String) info.getProperty("checked"); //$NON-NLS-1$
+						System.out.println("currentState" + currentState); //$NON-NLS-1$
+						if ((currentState == null) || currentState.equals("false")) //$NON-NLS-1$
+						{
+							info.setProperty("checked", "true"); //$NON-NLS-1$ //$NON-NLS-2$
+						}
+						else {
+							info.setProperty("checked", "false"); //$NON-NLS-1$ //$NON-NLS-2$
+						}
+						refresh();
+					}
+				}
+			}
+		}
+	}
+
+	protected static final int COLUMN_CHECKBOX = 1;
+	protected static final int COLUMN_LOCATION_HINT = 4;
+	protected static final int COLUMN_NAMESPACE_URI = 2;
+	protected static final int COLUMN_PREFIX = 3;
+
+	protected static final String LABEL_CHECKBOX = ""; //$NON-NLS-1$
+	protected static final String LABEL_LOCATION_HINT = XMLUIMessages._UI_LABEL_LOCATION_HINT;
+	protected static final String LABEL_NAMESPACE_URI = XMLUIMessages._UI_LABEL_NAMESPACE_NAME;
+	protected static final String LABEL_PREFIX = XMLUIMessages._UI_LABEL_PREFIX;
+	protected List checkedList = new ArrayList();
+
+	// protected List namespaceInfoList = new ArrayList();
+	protected int[] columnIndexMap;
+	protected boolean showCheckBoxes = true;
+	private boolean showLocationText = false;
+
+	private Table table;
+	protected int visibleRows = -1;
+
+	public CommonNamespaceInfoTable(Composite parent, int visibleRows) {
+		this(parent, SWT.FULL_SELECTION | SWT.MULTI | SWT.BORDER, visibleRows, false);
+	}
+
+	// protected CellEditor getCellEditor(int column)
+	// {
+	// return (column == COLUMN_CHECKBOX) ? checkBoxCellEditor :
+	// textCellEditor;
+	// }
+
+	public CommonNamespaceInfoTable(Composite parent, int visibleRows, boolean showLocationText) {
+		this(parent, SWT.FULL_SELECTION | SWT.MULTI | SWT.BORDER, visibleRows, showLocationText);
+	}
+
+	public CommonNamespaceInfoTable(Composite parent, int style, int visibleRows) {
+		this(parent, SWT.FULL_SELECTION | SWT.MULTI | SWT.BORDER | style, visibleRows, false);
+	}
+
+	public CommonNamespaceInfoTable(Composite parent, int style, int visibleRows, boolean showLocationText) {
+		super(new Table(parent, style));
+		getTable().setLinesVisible(true);
+		this.showCheckBoxes = (style & SWT.CHECK) != 0;
+		columnIndexMap = createColumnIndexMap();
+		this.showLocationText = showLocationText;
+
+		Provider provider = new Provider();
+		setContentProvider(provider);
+		setLabelProvider(provider);
+
+		String[] columnPropertiesArray = createColumnPropertiesArray();
+		setColumnProperties(columnPropertiesArray);
+
+		table = getTable();
+		table.setHeaderVisible(true);
+		table.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+		TableLayout layout = new TableLayout();
+
+		for (int i = 0; i < columnPropertiesArray.length; i++) {
+			TableColumn column = new TableColumn(table, i);
+			if ((columnPropertiesArray[i]).equals(LABEL_LOCATION_HINT)) {
+				if (showLocationText) {
+					column.setText(columnPropertiesArray[i]);
+				}
+				else {
+					// Comment this out until we solve the alignment/(space
+					// for image being allocated
+					// to prefix column) ......
+					// column.setImage(XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TXTEXT));
+				}
+			}
+			else {
+				column.setText(columnPropertiesArray[i]);
+			}
+			column.setAlignment(SWT.LEFT);
+			layout.addColumnData(new ColumnWeightData(getColumnWidth(i), true));
+		}
+		table.setLayout(layout);
+
+		this.visibleRows = visibleRows;
+		// for (int i = 0; i < visibleRows; i++)
+		// {
+		// TableItem item = new TableItem(table, SWT.NONE);
+		// item.setText("#######");
+		// }
+		// checkBoxCellEditor = new NamespaceInfoCheckboxCellEditor(table);
+		// textCellEditor = new TextCellEditor(table);
+
+		/*
+		 * CellEditor[] cellEditors = new
+		 * CellEditor[columnPropertiesArray.length]; for (int i = 0; i <
+		 * columnPropertiesArray.length; i++) { cellEditors[i] =
+		 * getCellEditor(i); } setCellEditors(cellEditors);
+		 */
+		// if (showCheckBoxes)
+		// {
+		// getTable().addMouseListener(new TableItemChecker());
+		// }
+	}
+
+	// protected CellEditor checkBoxCellEditor;
+	// protected CellEditor textCellEditor;
+
+	protected int[] createColumnIndexMap() {
+		int[] result = new int[showCheckBoxes ? 4 : 3];
+		int i = 0;
+		if (showCheckBoxes) {
+			result[i++] = COLUMN_CHECKBOX;
+		}
+		result[i++] = COLUMN_PREFIX;
+		result[i++] = COLUMN_NAMESPACE_URI;
+		if (!showCheckBoxes) {
+			result[i++] = COLUMN_LOCATION_HINT;
+		}
+		return result;
+	}
+
+	protected String[] createColumnPropertiesArray() {
+		String[] result = new String[3];
+		int i = 0;
+		if (showCheckBoxes) {
+			result[i++] = LABEL_CHECKBOX;
+		}
+		result[i++] = LABEL_PREFIX;
+		result[i++] = LABEL_NAMESPACE_URI;
+		if (!showCheckBoxes) {
+			result[i++] = LABEL_LOCATION_HINT;
+		}
+		return result;
+	}
+
+	protected int getColumnCode(int column) {
+		int result = 0;
+		if (column < columnIndexMap.length) {
+			result = columnIndexMap[column];
+		}
+		return result;
+	}
+
+	protected int getColumnWidth(int column) {
+		int result = 0;
+		switch (getColumnCode(column)) {
+			case COLUMN_PREFIX : {
+				result = 5;
+				break;
+			}
+			case COLUMN_NAMESPACE_URI : {
+				// Size columns differently when location hint text label is
+				// displayed
+				if (showLocationText) {
+					result = 10;
+				}
+				else {
+					result = 20;
+				}
+				break;
+			}
+			case COLUMN_CHECKBOX : {
+				result = 1; // info.locationHint;
+				break;
+			}
+			case COLUMN_LOCATION_HINT : {
+				// Size columns differently when location hint text label is
+				// displayed
+				if (showLocationText) {
+					result = 10;
+				}
+				else {
+					result = 2;
+				}
+				break;
+			}
+		}
+		return result;
+	}
+	/*
+	 * protected class NamespaceInfoCellModifier implements ICellModifier {
+	 * public NamespaceInfoCellModifier() { }
+	 * 
+	 * public boolean canModify(Object element, String property) { if
+	 * (property.equals(LABEL_CHECKBOX)) { return true; } else if
+	 * (property.equals(LABEL_PREFIX)) { return true; } return false; }
+	 * 
+	 * public Object getValue(Object element, String property) { int column =
+	 * 0; if (property.equals(LABEL_CHECKBOX)) { column = 0; } else if
+	 * (property.equals(LABEL_PREFIX)) { column = 1; } else if
+	 * (property.equals(LABEL_NAMESPACE_URI)) { column = 2; }
+	 * 
+	 * //if (element instanceof TableElement) //{ // return
+	 * provider.getColumnText(element, column); //} //else //{ // return null; // }
+	 * return "hello"; }
+	 * 
+	 * public void modify(Object element, String property, Object value) { } }
+	 * 
+	 * protected class NamespaceInfoCheckboxCellEditor extends
+	 * CheckboxCellEditor implements MouseListener { public
+	 * NamespaceInfoCheckboxCellEditor(Composite parent) { super(parent); }
+	 * 
+	 * protected void doSetValue(Object value) { }
+	 * 
+	 * public void activate() { super.activate(); deactivate();
+	 * Display.getCurrent().getFocusControl().redraw(); }
+	 * 
+	 * public void mouseDown(MouseEvent e) { if (getTable().getItem(new
+	 * Point(e.x, e.y)) != null) { } } public void mouseDoubleClick(MouseEvent
+	 * e) { } public void mouseUp(MouseEvent e) { } }
+	 */
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/perspective/XMLPerspectiveFactory.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/perspective/XMLPerspectiveFactory.java
new file mode 100644
index 0000000..93f579c
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/perspective/XMLPerspectiveFactory.java
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2010 Standards for Technology in Automotive Retail
+ * 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:
+ *     David Carver - bug 213883 - initial api 
+ *     IBM Corporation - bug 271619 - Move and rename XML perspective definition
+ *******************************************************************************/
+
+package org.eclipse.wst.xml.ui.internal.perspective;
+
+import org.eclipse.ui.IFolderLayout;
+import org.eclipse.ui.IPageLayout;
+import org.eclipse.ui.IPerspectiveFactory;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.wst.xml.ui.internal.IProductConstants;
+import org.eclipse.wst.xml.ui.internal.ProductProperties;
+
+
+/**
+ * @author dcarver
+ * 
+ */
+public class XMLPerspectiveFactory implements IPerspectiveFactory {
+
+//	private static final String SEARCH_VIEW_ID = "org.eclipse.search.ui.views.SearchView"; //$NON-NLS-1$
+//	private static final String XPATH_VIEW_ID = "org.eclipse.wst.xml.views.XPathView"; //$NON-NLS-1$
+//	private static final String SNIPPETS_VIEW_ID = "org.eclipse.wst.common.snippets.internal.ui.SnippetsView"; //$NON-NLS-1$
+//	private static final String TEXTEDITOR_TEMPLATES_VIEW_ID = "org.eclipse.ui.texteditor.TemplatesView"; //$NON-NLS-1$
+//	private static final String ID_CONSOLE_VIEW = "org.eclipse.ui.console.ConsoleView"; //$NON-NLS-1$
+
+	private static String HIERARCHY_VIEW_ID = "org.eclipse.ui.navigator.ProjectExplorer"; //$NON-NLS-1$
+
+	public XMLPerspectiveFactory() {
+		String viewerID = ProductProperties.getProperty(IProductConstants.PERSPECTIVE_EXPLORER_VIEW);
+		if (viewerID != null) {
+			// verify that the view actually exists
+			if (PlatformUI.getWorkbench().getViewRegistry().find(viewerID) != null){
+				HIERARCHY_VIEW_ID = viewerID;
+			}
+		}
+	}
+	/**
+	 * Creates the initial layout. This is what the layout is reset to when
+	 * the Reset Perspective is selected. It takes as input a IPageLayout
+	 * object.
+	 * 
+	 * @param layout
+	 */
+	public void createInitialLayout(IPageLayout layout) {
+		// Get the Editor Area
+//		String editorArea = layout.getEditorArea();
+
+		// Turn on the Editor Area
+		layout.setEditorAreaVisible(true);
+		layout.setFixed(false);
+
+		layout.addShowViewShortcut(HIERARCHY_VIEW_ID);
+
+		IFolderLayout topLeft = layout.createFolder("topLeft", IPageLayout.LEFT, 0.23f, layout.getEditorArea());//$NON-NLS-1$
+		topLeft.addView(HIERARCHY_VIEW_ID);
+
+		// Create the areas of the layout with their initial views
+//		IFolderLayout left = layout.createFolder("left", IPageLayout.LEFT, (float) 0.23, editorArea); //$NON-NLS-1$
+//		left.addView(IPageLayout.ID_PROJECT_EXPLORER);
+//
+//		IFolderLayout bottomLeft = layout.createFolder("bottom-left", IPageLayout.BOTTOM, (float) 0.50, "left"); //$NON-NLS-1$ //$NON-NLS-2$
+//		bottomLeft.addView(XPATH_VIEW_ID); //$NON-NLS-1$
+//
+//		IFolderLayout right = layout.createFolder("right", IPageLayout.RIGHT, (float) 0.70, editorArea); //$NON-NLS-1$
+//		right.addView(IPageLayout.ID_OUTLINE);
+//		
+//		IFolderLayout bottomRight = layout.createFolder("bottom-right", IPageLayout.BOTTOM, (float) 0.60, "right"); //$NON-NLS-1$//$NON-NLS-2$
+//		bottomRight.addView(TEXTEDITOR_TEMPLATES_VIEW_ID);
+//
+//		IFolderLayout bottom = layout.createFolder("bottom", IPageLayout.BOTTOM, (float) 0.75, editorArea); //$NON-NLS-1$
+//		bottom.addView(IPageLayout.ID_PROBLEM_VIEW);
+//		bottom.addView(IPageLayout.ID_PROP_SHEET);
+//		bottom.addView(ID_CONSOLE_VIEW);
+//		bottom.addView(SNIPPETS_VIEW_ID);
+//
+//		bottom.addPlaceholder(SEARCH_VIEW_ID);
+	}
+	
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/preferences/EmptyFilePreferencePage.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/preferences/EmptyFilePreferencePage.java
new file mode 100644
index 0000000..9870632
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/preferences/EmptyFilePreferencePage.java
@@ -0,0 +1,100 @@
+/*******************************************************************************
+ * Copyright (c) 2008 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.preferences;
+
+import org.eclipse.jface.preference.PreferencePage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.ScrolledComposite;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+
+public class EmptyFilePreferencePage extends PreferencePage implements IWorkbenchPreferencePage {
+
+	private Composite createComposite(Composite parent, int numColumns) {
+		noDefaultAndApplyButton();
+
+		Composite composite = new Composite(parent, SWT.NULL);
+
+		// GridLayout
+		GridLayout layout = new GridLayout();
+		layout.numColumns = numColumns;
+		composite.setLayout(layout);
+
+		// GridData
+		GridData data = new GridData(GridData.FILL);
+		data.horizontalIndent = 0;
+		data.verticalAlignment = GridData.FILL;
+		data.horizontalAlignment = GridData.FILL;
+		composite.setLayoutData(data);
+
+		return composite;
+	}
+
+	protected Control createContents(Composite parent) {
+		Composite composite = createScrolledComposite(parent);
+
+		String description = XMLUIMessages.EmptyFilePreferencePage_0; 
+		Text text = new Text(composite, SWT.READ_ONLY);
+		// some themes on GTK have different background colors for Text and Labels
+		text.setBackground(composite.getBackground());
+		text.setText(description);
+
+		setSize(composite);
+		return composite;
+	}
+
+	private Composite createScrolledComposite(Composite parent) {
+		// create scrollbars for this parent when needed
+		final ScrolledComposite sc1 = new ScrolledComposite(parent, SWT.H_SCROLL | SWT.V_SCROLL);
+		sc1.setLayoutData(new GridData(GridData.FILL_BOTH));
+		Composite composite = createComposite(sc1, 1);
+		sc1.setContent(composite);
+
+		// not calling setSize for composite will result in a blank composite,
+		// so calling it here initially
+		// setSize actually needs to be called after all controls are created,
+		// so scrolledComposite
+		// has correct minSize
+		setSize(composite);
+		return composite;
+	}
+
+	public void init(IWorkbench workbench) {
+	}
+
+	private void setSize(Composite composite) {
+		if (composite != null) {
+			// Note: The font is set here in anticipation that the class inheriting
+			//       this base class may add widgets to the dialog.   setSize
+			//       is assumed to be called just before we go live.
+			applyDialogFont(composite);
+			Point minSize = composite.computeSize(SWT.DEFAULT, SWT.DEFAULT);
+			composite.setSize(minSize);
+			// set scrollbar composite's min size so page is expandable but
+			// has scrollbars when needed
+			if (composite.getParent() instanceof ScrolledComposite) {
+				ScrolledComposite sc1 = (ScrolledComposite) composite.getParent();
+				sc1.setMinSize(minSize);
+				sc1.setExpandHorizontal(true);
+				sc1.setExpandVertical(true);
+			}
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/preferences/EncodingSettings.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/preferences/EncodingSettings.java
new file mode 100644
index 0000000..16fa130
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/preferences/EncodingSettings.java
@@ -0,0 +1,360 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2009 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.preferences;
+
+import java.util.Vector;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.wst.sse.core.internal.encoding.CommonCharsetNames;
+import org.eclipse.wst.xml.ui.internal.Logger;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+
+/**
+ * EncodingSettings is a composite that can be used to display the set of
+ * encoding values that are available to the user. The list of encoding values
+ * is based off the SupportedJavaEncoding class. As the user selects an
+ * encoding from the combo box, the readonly field below it changes to show
+ * the IANA tag for that particular encoding description. The labels for the
+ * widgets are configurable and the initial value to display to the user can
+ * be set using the setIANATag(). The currently selected entry's IANA tag can
+ * be retrieved with getIANATag(). Entries displayed to the user can be added
+ * and removed.
+ */
+public class EncodingSettings extends Composite {
+
+	private class ComboListener implements ModifyListener {
+		public void modifyText(ModifyEvent e) {
+			int i = encodingCombo.getSelectionIndex();
+			if ((i >= 0) && (i < ianaVector.size())) {
+				ianaText.setText((String) (ianaVector.elementAt(encodingCombo.getSelectionIndex())));
+			}
+		}
+	}
+
+	private static String ENCODING_LABEL = XMLUIMessages.EncodingSettings_1;
+
+	private static String IANA_LABEL = XMLUIMessages.EncodingSettings_0;
+
+	private ModifyListener comboListener = new ComboListener();
+	protected Combo encodingCombo;
+	protected Label encodingLabel, ianaLabel;
+	protected Text ianaText;
+	protected Vector ianaVector;
+
+	/**
+	 * Method EncodingSettings.
+	 * 
+	 * @param parent
+	 */
+	public EncodingSettings(Composite parent) {
+		super(parent, SWT.NONE);
+		init(IANA_LABEL, ENCODING_LABEL);
+	}
+
+	/**
+	 * Method EncodingSettings.
+	 * 
+	 * @param parent
+	 * @param encodingLabel -
+	 *            text label to use beside the locale sensitive description of
+	 *            the currently selected encoding
+	 */
+	public EncodingSettings(Composite parent, String encodingLabel) {
+		super(parent, SWT.NONE);
+		init(IANA_LABEL, encodingLabel);
+	}
+
+	/**
+	 * Method EncodingSettings.
+	 * 
+	 * @param parent
+	 * @param ianaLabel =
+	 *            text label to use beside the display only IANA field
+	 * @param encodingLabel -
+	 *            text label to use beside the locale sensitive description of
+	 *            the currently selected encoding
+	 */
+	public EncodingSettings(Composite parent, String ianaLabel, String encodingLabel) {
+		super(parent, SWT.NONE);
+		init(ianaLabel, encodingLabel);
+	}
+
+	/**
+	 * Method addEntry. Add an entry to the end of the Encoding Combobox
+	 * 
+	 * @param description -
+	 *            encoding description to display
+	 * @param ianaTag -
+	 *            IANA tag for the description
+	 */
+	public void addEntry(String description, String ianaTag) {
+		encodingCombo.add(description);
+		ianaVector.add(ianaTag);
+	}
+
+	/**
+	 * Method addEntry. Add an entry to the Encoding Combobox at index index
+	 * 
+	 * @param description -
+	 *            encoding description to display
+	 * @param ianaTag -
+	 *            IANA tag for the description
+	 * @param index -
+	 *            index into the combo to add to
+	 */
+	public void addEntry(String description, String ianaTag, int index) {
+		if (index == ianaVector.size()) {
+			// just add to the end
+			addEntry(description, ianaTag);
+			return;
+		}
+
+		if ((0 <= index) && (index < ianaVector.size())) {
+			encodingCombo.add(description, index);
+			ianaVector.add(index, ianaTag);
+		}
+	}
+
+	protected Combo createComboBox(Composite parent, boolean isReadOnly) {
+		int style = isReadOnly == true ? SWT.READ_ONLY : SWT.DROP_DOWN;
+
+		Combo combo = new Combo(parent, style);
+
+		GridData data = new GridData();
+		data.horizontalAlignment = GridData.FILL;
+		data.grabExcessHorizontalSpace = true;
+		combo.setLayoutData(data);
+		return combo;
+	}
+
+	/**
+	 * Helper method for creating labels.
+	 */
+	protected Label createLabel(Composite parent, String text) {
+		Label label = new Label(parent, SWT.LEFT);
+		label.setText(text);
+
+		GridData data = new GridData();
+		data.horizontalAlignment = GridData.FILL;
+		label.setLayoutData(data);
+		return label;
+	}
+
+	protected Text createTextField(Composite parent, int width) {
+		Text text = new Text(parent, SWT.SINGLE | SWT.READ_ONLY);
+
+		GridData data = new GridData();
+		data.horizontalAlignment = GridData.FILL;
+		data.grabExcessHorizontalSpace = true;
+		data.widthHint = width;
+		text.setLayoutData(data);
+
+		text.setBackground(text.getDisplay().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND));
+		return text;
+	}
+
+	/**
+	 * @see org.eclipse.swt.widgets.Widget#dispose()
+	 */
+	public void dispose() {
+		encodingCombo.removeModifyListener(comboListener);
+		super.dispose();
+	}
+
+	private void fillCombo() {
+		try {
+			String[] ianaTags = CommonCharsetNames.getCommonCharsetNames();
+			int totalNum = ianaTags.length;
+			for (int i = 0; i < totalNum; i++) {
+				String iana = ianaTags[i];
+				String enc = CommonCharsetNames.getDisplayString(iana);
+
+				if (enc != null) {
+					encodingCombo.add(enc);
+				}
+				else {
+					Logger.log(Logger.WARNING, "CommonCharsetNames.getDisplayString(" + iana + ") returned null"); //$NON-NLS-1$ //$NON-NLS-2$
+					encodingCombo.add(iana);
+				}
+				ianaVector.add(iana);
+			}
+		}
+		catch (Exception e) {
+			// e.printStackTrace();
+			// MessageDialog.openError(getShell(), "Resource exception",
+			// "Unable to obtain encoding strings. Check resource file");
+			// XMLEncodingPlugin.getPlugin().getMsgLogger().write(e.toString());
+			// XMLEncodingPlugin.getPlugin().getMsgLogger().writeCurrentThread();
+			Logger.log(Logger.ERROR, "Exception", e); //$NON-NLS-1$
+		}
+	}
+
+	/**
+	 * <code>getEncoding</code> Get the descriptive encoding name that was
+	 * selected.
+	 * 
+	 * @return a <code>String</code> value
+	 */
+	public String getEncoding() {
+		return encodingCombo.getText();
+	}
+
+	/**
+	 * Method getEncodingCombo. Returns the combo used to display the encoding
+	 * descriptions.
+	 * 
+	 * @return Combo
+	 */
+	public Combo getEncodingCombo() {
+		return encodingCombo;
+	}
+
+	/**
+	 * <code>getIANATag</code> Get the IANA tag equivalent of the selected
+	 * descriptive encoding name
+	 * 
+	 * @return a <code>String</code> value
+	 */
+	public String getIANATag() {
+		int i = encodingCombo.getSelectionIndex();
+		if (i >= 0) {
+			return (String) (ianaVector.elementAt(i));
+		}
+		return ""; //$NON-NLS-1$
+	}
+
+	protected void init(String ianaLabelStr, String encodingLabelStr) {
+		GridLayout layout = new GridLayout();
+		layout.numColumns = 2;
+		setLayout(layout);
+		GridData data = new GridData();
+		data.verticalAlignment = GridData.FILL;
+		data.horizontalAlignment = GridData.FILL;
+		data.grabExcessHorizontalSpace = true;
+		setLayoutData(data);
+
+		encodingLabel = createLabel(this, encodingLabelStr);
+		encodingCombo = createComboBox(this, true);
+		ianaLabel = createLabel(this, ianaLabelStr);
+		ianaText = createTextField(this, 20);
+		ianaVector = new Vector();
+
+		fillCombo();
+		resetToDefaultEncoding();
+		encodingCombo.addModifyListener(comboListener);
+	}
+
+	/**
+	 * <code>isEncodingInList</code> Checks whether the encoding name is in
+	 * the combo
+	 * 
+	 * @param enc
+	 *            a <code>string</code> value. The encoding name.
+	 * @return a <code>boolean</code> value. TRUE if encoding is in list.
+	 *         FALSE if encoding is not in list.
+	 */
+	public boolean isEncodingInList(String enc) {
+		int i = encodingCombo.indexOf(enc);
+		if (i >= 0) {
+			return true;
+		}
+		return false;
+	}
+
+	/**
+	 * <code>isIANATagInList</code> Checks whether the IANA tag is in the
+	 * combo
+	 * 
+	 * @param ianaTag
+	 *            a <code>string</code> value. The IANA tag.
+	 * @return a <code>boolean</code> value. TRUE if tag is in list. FALSE
+	 *         if tag is not in list.
+	 */
+	public boolean isIANATagInList(String ianaTag) {
+		int i = ianaVector.indexOf(ianaTag);
+		if (i >= 0) {
+			return true;
+		}
+		return false;
+	}
+
+	/**
+	 * Method removeEntry. Removes both the description and the IANA tag at
+	 * the specified index
+	 * 
+	 * @param index
+	 */
+	public void removeEntry(int index) {
+		if ((0 <= index) && (index < ianaVector.size())) {
+			encodingCombo.remove(index);
+			ianaVector.remove(index);
+		}
+	}
+
+	/**
+	 * Method resetToDefaultEncoding. Reset the control to the default
+	 * encoding. Currently UTF-8
+	 */
+	public void resetToDefaultEncoding() {
+		String defaultIANATag = "UTF-8"; //$NON-NLS-1$
+		ianaText.setText(defaultIANATag);
+		setIANATag(defaultIANATag);
+	}
+
+	/**
+	 * Method setEnabled. Enable/disable the EncodingSettings composite.
+	 * 
+	 * @param enabled
+	 */
+	public void setEnabled(boolean enabled) {
+		encodingCombo.setEnabled(enabled);
+		encodingLabel.setEnabled(enabled);
+		ianaLabel.setEnabled(enabled);
+		ianaText.setEnabled(enabled);
+	}
+
+	/**
+	 * <code>setEncoding</code> Set the selection in the combo to the
+	 * descriptive encoding name.
+	 * 
+	 * @param enc
+	 *            a <code>string</code> value. Note this is not the IANA
+	 *            tag.
+	 */
+	public void setEncoding(String enc) {
+		encodingCombo.setText(enc);
+		encodingCombo.select(encodingCombo.indexOf(enc));
+	}
+
+	/**
+	 * <code>setIANATag</code> Set the IANA tag for the combo
+	 * 
+	 * @param ianaTag
+	 *            a <code>string</code> value. The IANA tag.
+	 */
+	public void setIANATag(String ianaTag) {
+		int i = ianaVector.indexOf(ianaTag);
+		if (i >= 0) {
+			encodingCombo.select(i);
+		}
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/preferences/WorkbenchDefaultEncodingSettings.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/preferences/WorkbenchDefaultEncodingSettings.java
new file mode 100644
index 0000000..e7930ed
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/preferences/WorkbenchDefaultEncodingSettings.java
@@ -0,0 +1,141 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.preferences;
+
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.wst.sse.core.internal.encoding.CommonCharsetNames;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+
+/**
+ * WorkbenchDefaultEncodingSettings is an extension of EncodingSettings. This
+ * composite contains EncodingSettings for users to select the encoding they
+ * desire as well as a checkbox for users to select to use the default
+ * workbench encoding instead.
+ * 
+ * @see org.eclipse.wst.xml.ui.internal.preferences.EncodingSettings
+ */
+public class WorkbenchDefaultEncodingSettings extends Composite {
+
+	private final static int INDENT = 15;
+	private static final String WORKBENCH_DEFAULT = ""; //$NON-NLS-1$
+	private EncodingSettings fEncodingSettings;
+	private String fNonDefaultIANA = null;
+	private Button fUseDefaultButton;
+
+	public WorkbenchDefaultEncodingSettings(Composite parent) {
+		super(parent, SWT.NONE);
+		createControls();
+	}
+
+	private void createControls() {
+		GridLayout layout = new GridLayout();
+		layout.numColumns = 1;
+		layout.marginWidth = 0;
+		setLayout(layout);
+		GridData data = new GridData();
+		data.verticalAlignment = GridData.FILL;
+		data.horizontalAlignment = GridData.FILL;
+		data.grabExcessHorizontalSpace = true;
+		setLayoutData(data);
+
+		Composite defaultEncodingComposite = new Composite(this, SWT.NONE);
+		layout = new GridLayout();
+		layout.marginWidth = 0;
+		layout.marginHeight = 0;
+		data = new GridData(GridData.FILL_BOTH);
+		defaultEncodingComposite.setLayout(layout);
+		defaultEncodingComposite.setLayoutData(data);
+
+		fUseDefaultButton = new Button(defaultEncodingComposite, SWT.CHECK);
+		fUseDefaultButton.setText(XMLUIMessages.WorkbenchDefaultEncodingSettings_0);
+
+		fUseDefaultButton.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				handleUseDefaultButtonSelected();
+			}
+		});
+
+		fEncodingSettings = new EncodingSettings(this);
+		((GridLayout) fEncodingSettings.getLayout()).marginWidth = 0;
+		((GridData) fEncodingSettings.getLayoutData()).horizontalIndent = INDENT;
+
+	}
+
+	private Combo getEncodingCombo() {
+		return fEncodingSettings.getEncodingCombo();
+	}
+
+	/**
+	 * <code>getIANATag</code> Get the IANA tag equivalent of the selected
+	 * descriptive encoding name. Returns empty string if using workbench
+	 * encoding.
+	 * 
+	 * @return a <code>String</code> value
+	 */
+	public String getIANATag() {
+		if (!isDefault()) {
+			return fEncodingSettings.getIANATag();
+		}
+		return WORKBENCH_DEFAULT;
+	}
+
+	private String getWorkbenchEncoding() {
+		return ResourcesPlugin.getEncoding();
+	}
+
+	void handleUseDefaultButtonSelected() {
+		if (fUseDefaultButton.getSelection()) {
+			fNonDefaultIANA = fEncodingSettings.getIANATag();
+			String workbenchValue = getWorkbenchEncoding();
+			workbenchValue = CommonCharsetNames.getIanaPreferredCharsetName(workbenchValue);
+			fEncodingSettings.setIANATag(workbenchValue);
+		}
+		else if (fNonDefaultIANA != null) {
+			fEncodingSettings.setIANATag(fNonDefaultIANA);
+		}
+		getEncodingCombo().setEnabled(!fUseDefaultButton.getSelection());
+		fEncodingSettings.setEnabled(!fUseDefaultButton.getSelection());
+	}
+
+	private boolean isDefault() {
+		return fUseDefaultButton.getSelection();
+	}
+
+	/**
+	 * <code>setEncoding</code> Set the selection in the combo to the
+	 * descriptive encoding name. Selects use workbench encoding if ianaTag is
+	 * null or empty string.
+	 * 
+	 */
+	public void setIANATag(String ianaTag) {
+		if ((ianaTag == null) || ianaTag.equals(WORKBENCH_DEFAULT)) {
+			fUseDefaultButton.setSelection(true);
+			handleUseDefaultButtonSelected();
+		}
+		else {
+			fUseDefaultButton.setSelection(false);
+			handleUseDefaultButtonSelected();
+			if (!isDefault()) {
+				fEncodingSettings.setIANATag(ianaTag);
+			}
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/preferences/XMLColorPage.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/preferences/XMLColorPage.java
new file mode 100644
index 0000000..4f29d75
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/preferences/XMLColorPage.java
@@ -0,0 +1,288 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     Benjamin Muskalla, b.muskalla@gmx.net - [158660] character entities should have their own syntax highlighting preference 
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.preferences;
+
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.Iterator;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.IModelManager;
+import org.eclipse.wst.sse.ui.internal.SSEUIPlugin;
+import org.eclipse.wst.sse.ui.internal.preferences.OverlayPreferenceStore;
+import org.eclipse.wst.sse.ui.internal.preferences.OverlayPreferenceStore.OverlayKey;
+import org.eclipse.wst.sse.ui.internal.preferences.ui.AbstractColorPage;
+import org.eclipse.wst.sse.ui.internal.preferences.ui.StyledTextColorPicker;
+import org.eclipse.wst.xml.core.internal.provisional.contenttype.ContentTypeIdForXML;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+import org.eclipse.wst.xml.ui.internal.XMLUIPlugin;
+import org.eclipse.wst.xml.ui.internal.editor.IHelpContextIds;
+import org.eclipse.wst.xml.ui.internal.style.IStyleConstantsXML;
+
+/**
+ * @deprecated
+ */
+public class XMLColorPage extends AbstractColorPage {
+
+	protected Control createContents(Composite parent) {
+		Composite pageComponent = createComposite(parent, 1);
+		((GridData) pageComponent.getLayoutData()).horizontalAlignment = GridData.HORIZONTAL_ALIGN_FILL;
+
+		super.createContents(pageComponent);
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(pageComponent, IHelpContextIds.XML_PREFWEBX_STYLES_HELPID);
+		return pageComponent;
+	}
+
+	/**
+	 * Set up all the style preference keys in the overlay store
+	 */
+	protected OverlayKey[] createOverlayStoreKeys() {
+		ArrayList overlayKeys = new ArrayList();
+
+		ArrayList styleList = new ArrayList();
+		initStyleList(styleList);
+		Iterator i = styleList.iterator();
+		while (i.hasNext()) {
+			overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, (String) i.next()));
+		}
+
+		OverlayPreferenceStore.OverlayKey[] keys = new OverlayPreferenceStore.OverlayKey[overlayKeys.size()];
+		overlayKeys.toArray(keys);
+		return keys;
+	}
+
+	protected IPreferenceStore doGetPreferenceStore() {
+		return XMLUIPlugin.getDefault().getPreferenceStore();
+	}
+
+	public String getSampleText() {
+		return XMLUIMessages.Sample_XML_doc; // = "<?xml
+		// version=\"1.0\"?>\n<?customProcessingInstruction\n\tXML
+		// processor
+		// specific\n\tcontent
+		// ?>\n<!DOCTYPE
+		// colors\n\tPUBLIC
+		// \"//IBM/XML/COLORS/\"
+		// \"colors.dtd\">\n<colors>\n\t<!--
+		// begin color definitions
+		// -->\n\t<color
+		// name=\"plaintext\"
+		// foreground=\"#000000\"\n\t\tbackground=\"#D4D0C8\"/>\n\t<color
+		// name=\"bold\"
+		// foreground=\"#000000\"\n\t\tbackground=\"#B3ACA0\">\n\t<![CDATA[<123456789>]]>\n\tNormal
+		// text content.\n\t<color
+		// name=\"inverse\"
+		// foreground=\"#F0F0F0\"\n\t\tbackground=\"#D4D0C8\"/>\n\n</colors>\n";
+	}
+
+	protected void initCommonContextStyleMap(Dictionary contextStyleMap) {
+
+		contextStyleMap.put(DOMRegionContext.XML_COMMENT_OPEN, IStyleConstantsXML.COMMENT_BORDER);
+		contextStyleMap.put(DOMRegionContext.XML_COMMENT_TEXT, IStyleConstantsXML.COMMENT_TEXT);
+		contextStyleMap.put(DOMRegionContext.XML_COMMENT_CLOSE, IStyleConstantsXML.COMMENT_BORDER);
+
+		contextStyleMap.put(DOMRegionContext.XML_TAG_OPEN, IStyleConstantsXML.TAG_BORDER);
+		contextStyleMap.put(DOMRegionContext.XML_END_TAG_OPEN, IStyleConstantsXML.TAG_BORDER);
+		contextStyleMap.put(DOMRegionContext.XML_TAG_NAME, IStyleConstantsXML.TAG_NAME);
+		contextStyleMap.put(DOMRegionContext.XML_TAG_ATTRIBUTE_NAME, IStyleConstantsXML.TAG_ATTRIBUTE_NAME);
+		contextStyleMap.put(DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE, IStyleConstantsXML.TAG_ATTRIBUTE_VALUE);
+		contextStyleMap.put(DOMRegionContext.XML_TAG_CLOSE, IStyleConstantsXML.TAG_BORDER);
+		contextStyleMap.put(DOMRegionContext.XML_EMPTY_TAG_CLOSE, IStyleConstantsXML.TAG_BORDER);
+
+		contextStyleMap.put(DOMRegionContext.XML_DECLARATION_OPEN, IStyleConstantsXML.DECL_BORDER);
+		contextStyleMap.put(DOMRegionContext.XML_DECLARATION_CLOSE, IStyleConstantsXML.DECL_BORDER);
+		contextStyleMap.put(DOMRegionContext.XML_ELEMENT_DECLARATION, IStyleConstantsXML.DECL_BORDER);
+		contextStyleMap.put(DOMRegionContext.XML_ELEMENT_DECL_CLOSE, IStyleConstantsXML.DECL_BORDER);
+
+		contextStyleMap.put(DOMRegionContext.XML_CHAR_REFERENCE, IStyleConstantsXML.ENTITY_REFERENCE);
+		contextStyleMap.put(DOMRegionContext.XML_ENTITY_REFERENCE, IStyleConstantsXML.ENTITY_REFERENCE);
+		contextStyleMap.put(DOMRegionContext.XML_PE_REFERENCE, IStyleConstantsXML.ENTITY_REFERENCE);
+
+		contextStyleMap.put(DOMRegionContext.XML_CONTENT, IStyleConstantsXML.XML_CONTENT);
+	}
+
+	protected void initCommonDescriptions(Dictionary descriptions) {
+
+		// create descriptions for hilighting types
+		descriptions.put(IStyleConstantsXML.COMMENT_BORDER, XMLUIMessages.Comment_Delimiters_UI_); // =
+		// "Comment
+		// Delimiters"
+		descriptions.put(IStyleConstantsXML.COMMENT_TEXT, XMLUIMessages.Comment_Content_UI_); // =
+		// "Comment
+		// Content"
+		descriptions.put(IStyleConstantsXML.TAG_BORDER, XMLUIMessages.Tag_Delimiters_UI_); // =
+		// "Tag
+		// Delimiters"
+		descriptions.put(IStyleConstantsXML.TAG_NAME, XMLUIMessages.Tag_Names_UI_); // =
+		// "Tag
+		// Names"
+		descriptions.put(IStyleConstantsXML.TAG_ATTRIBUTE_NAME, XMLUIMessages.Attribute_Names_UI_); // =
+		// "Attribute
+		// Names"
+		descriptions.put(IStyleConstantsXML.TAG_ATTRIBUTE_VALUE, XMLUIMessages.Attribute_Values_UI_); // =
+		// "Attribute
+		// Values"
+		descriptions.put(IStyleConstantsXML.DECL_BORDER, XMLUIMessages.Declaration_Delimiters_UI_); // =
+		// "Declaration
+		// Delimiters"
+		descriptions.put(IStyleConstantsXML.XML_CONTENT, XMLUIMessages.Content_UI_); // =
+		// "Content"
+		descriptions.put(IStyleConstantsXML.ENTITY_REFERENCE, XMLUIMessages.Entity_Reference_UI_); //$NON-NLS-1$ = "Entity References"
+	}
+
+	protected void initCommonStyleList(ArrayList list) {
+
+		// list.add(IStyleConstantsXML.CDATA_BORDER);
+		// list.add(IStyleConstantsXML.CDATA_TEXT);
+		// list.add(IStyleConstantsXML.PI_BORDER);
+		// list.add(IStyleConstantsXML.PI_CONTENT);
+
+		list.add(IStyleConstantsXML.TAG_BORDER);
+		list.add(IStyleConstantsXML.TAG_NAME);
+		list.add(IStyleConstantsXML.TAG_ATTRIBUTE_NAME);
+		list.add(IStyleConstantsXML.TAG_ATTRIBUTE_VALUE);
+		list.add(IStyleConstantsXML.COMMENT_BORDER);
+		list.add(IStyleConstantsXML.COMMENT_TEXT);
+		list.add(IStyleConstantsXML.DECL_BORDER);
+		list.add(IStyleConstantsXML.XML_CONTENT);
+		list.add(IStyleConstantsXML.ENTITY_REFERENCE);
+	}
+
+	protected void initContextStyleMap(Dictionary contextStyleMap) {
+
+		initCommonContextStyleMap(contextStyleMap);
+		initDocTypeContextStyleMap(contextStyleMap);
+		contextStyleMap.put(DOMRegionContext.XML_CDATA_OPEN, IStyleConstantsXML.CDATA_BORDER);
+		contextStyleMap.put(DOMRegionContext.XML_CDATA_TEXT, IStyleConstantsXML.CDATA_TEXT);
+		contextStyleMap.put(DOMRegionContext.XML_CDATA_CLOSE, IStyleConstantsXML.CDATA_BORDER);
+
+		contextStyleMap.put(DOMRegionContext.XML_PI_OPEN, IStyleConstantsXML.PI_BORDER);
+		contextStyleMap.put(DOMRegionContext.XML_PI_CONTENT, IStyleConstantsXML.PI_CONTENT);
+		contextStyleMap.put(DOMRegionContext.XML_PI_CLOSE, IStyleConstantsXML.PI_BORDER);
+
+	}
+
+	protected void initDescriptions(Dictionary descriptions) {
+
+		initCommonDescriptions(descriptions);
+		initDocTypeDescriptions(descriptions);
+		descriptions.put(IStyleConstantsXML.CDATA_BORDER, XMLUIMessages.CDATA_Delimiters_UI_); // =
+		// "CDATA
+		// Delimiters"
+		descriptions.put(IStyleConstantsXML.CDATA_TEXT, XMLUIMessages.CDATA_Content_UI_); // =
+		// "CDATA
+		// Content"
+		descriptions.put(IStyleConstantsXML.PI_BORDER, XMLUIMessages.Processing_Instruction_Del_UI_); // =
+		// "Processing
+		// Instruction
+		// Delimiters"
+		descriptions.put(IStyleConstantsXML.PI_CONTENT, XMLUIMessages.Processing_Instruction_Con_UI__UI_); // =
+		// "Processing
+		// Instruction
+		// Content"
+	}
+
+	protected void initDocTypeContextStyleMap(Dictionary contextStyleMap) {
+
+		contextStyleMap.put(DOMRegionContext.XML_ELEMENT_DECL_NAME, IStyleConstantsXML.DOCTYPE_NAME);
+		contextStyleMap.put(DOMRegionContext.XML_DOCTYPE_DECLARATION, IStyleConstantsXML.TAG_NAME);
+		contextStyleMap.put(DOMRegionContext.XML_DOCTYPE_DECLARATION_CLOSE, IStyleConstantsXML.DECL_BORDER);
+
+		contextStyleMap.put(DOMRegionContext.XML_DOCTYPE_NAME, IStyleConstantsXML.DOCTYPE_NAME);
+		contextStyleMap.put(DOMRegionContext.XML_DOCTYPE_EXTERNAL_ID_PUBLIC, IStyleConstantsXML.DOCTYPE_EXTERNAL_ID);
+		contextStyleMap.put(DOMRegionContext.XML_DOCTYPE_EXTERNAL_ID_PUBREF, IStyleConstantsXML.DOCTYPE_EXTERNAL_ID_PUBREF);
+		contextStyleMap.put(DOMRegionContext.XML_DOCTYPE_EXTERNAL_ID_SYSTEM, IStyleConstantsXML.DOCTYPE_EXTERNAL_ID);
+		contextStyleMap.put(DOMRegionContext.XML_DOCTYPE_EXTERNAL_ID_SYSREF, IStyleConstantsXML.DOCTYPE_EXTERNAL_ID_SYSREF);
+	}
+
+	protected void initDocTypeDescriptions(Dictionary descriptions) {
+
+		// create descriptions for hilighting types for DOCTYPE related items
+		descriptions.put(IStyleConstantsXML.DOCTYPE_NAME, XMLUIMessages.DOCTYPE_Name_UI_); // =
+		// "DOCTYPE
+		// Name"
+		descriptions.put(IStyleConstantsXML.DOCTYPE_EXTERNAL_ID, XMLUIMessages.DOCTYPE_SYSTEM_PUBLIC_Keyw_UI_); // =
+		// "DOCTYPE
+		// SYSTEM/PUBLIC
+		// Keyword"
+		descriptions.put(IStyleConstantsXML.DOCTYPE_EXTERNAL_ID_PUBREF, XMLUIMessages.DOCTYPE_Public_Reference_UI_); // =
+		// "DOCTYPE
+		// Public
+		// Reference"
+		descriptions.put(IStyleConstantsXML.DOCTYPE_EXTERNAL_ID_SYSREF, XMLUIMessages.DOCTYPE_System_Reference_UI_); // =
+		// "DOCTYPE
+		// System
+		// Reference"
+	}
+
+	protected void initDocTypeStyleList(ArrayList list) {
+
+		list.add(IStyleConstantsXML.DOCTYPE_NAME);
+		list.add(IStyleConstantsXML.DOCTYPE_EXTERNAL_ID);
+		list.add(IStyleConstantsXML.DOCTYPE_EXTERNAL_ID_PUBREF);
+		list.add(IStyleConstantsXML.DOCTYPE_EXTERNAL_ID_SYSREF);
+	}
+
+	protected void initStyleList(ArrayList list) {
+		initCommonStyleList(list);
+		initDocTypeStyleList(list);
+		list.add(IStyleConstantsXML.CDATA_BORDER);
+		list.add(IStyleConstantsXML.CDATA_TEXT);
+		list.add(IStyleConstantsXML.PI_BORDER);
+		list.add(IStyleConstantsXML.PI_CONTENT);
+	}
+
+	public boolean performOk() {
+		// required since the superclass *removes* existing preferences before
+		// saving its own
+		super.performOk();
+
+		SSEUIPlugin.getDefault().savePluginPreferences();
+		return true;
+	}
+
+	protected void setupPicker(StyledTextColorPicker picker) {
+		IModelManager mmanager = StructuredModelManager.getModelManager();
+		picker.setParser(mmanager.createStructuredDocumentFor(ContentTypeIdForXML.ContentTypeID_XML).getParser());
+
+		Dictionary descriptions = new Hashtable();
+		initDescriptions(descriptions);
+
+		Dictionary contextStyleMap = new Hashtable();
+		initContextStyleMap(contextStyleMap);
+
+		ArrayList styleList = new ArrayList();
+		initStyleList(styleList);
+
+		picker.setContextStyleMap(contextStyleMap);
+		picker.setDescriptions(descriptions);
+		picker.setStyleList(styleList);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.wst.sse.ui.preferences.ui.AbstractColorPage#savePreferences()
+	 */
+	protected void savePreferences() {
+		XMLUIPlugin.getDefault().savePluginPreferences();
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/preferences/XMLCompletionProposalCategoriesConfiguration.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/preferences/XMLCompletionProposalCategoriesConfiguration.java
new file mode 100644
index 0000000..92a7ccc
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/preferences/XMLCompletionProposalCategoriesConfiguration.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.preferences;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.wst.sse.ui.preferences.AbstractCompletionProposalCategoriesConfiguration;
+import org.eclipse.wst.xml.ui.internal.XMLUIPlugin;
+
+/**
+ * <p>The readable and writable completion proposal categories configuration
+ * for the XML content type</p>
+ */
+public class XMLCompletionProposalCategoriesConfiguration extends AbstractCompletionProposalCategoriesConfiguration {
+
+	/** the ID of the preference page where users can change the preferences */
+	private static final String PREFERENCES_PAGE_ID = "org.eclipse.wst.sse.ui.preferences.xml.contentassist"; //$NON-NLS-1$
+	
+	/**
+	 * <p>Creates the configuration</p>
+	 */
+	public XMLCompletionProposalCategoriesConfiguration() {
+		//nothing to do.
+	}
+
+	/**
+	 * @see org.eclipse.wst.sse.ui.preferences.AbstractCompletionProposalCategoriesConfiguration#getPreferenceStore()
+	 */
+	protected IPreferenceStore getPreferenceStore() {
+		return XMLUIPlugin.getDefault().getPreferenceStore();
+	}
+	
+	/**
+	 * @see org.eclipse.wst.sse.ui.preferences.ICompletionProposalCategoriesConfigurationWriter#hasAssociatedPropertiesPage()
+	 */
+	public boolean hasAssociatedPropertiesPage() {
+		return true;
+	}
+
+	/**
+	 * @see org.eclipse.wst.sse.ui.preferences.ICompletionProposalCategoriesConfigurationWriter#getPropertiesPageID()
+	 */
+	public String getPropertiesPageID() {
+		return PREFERENCES_PAGE_ID;
+	}
+
+	/**
+	 * @see org.eclipse.wst.sse.ui.preferences.AbstractCompletionProposalCategoriesConfiguration#getShouldNotDisplayOnDefaultPagePrefKey()
+	 */
+	protected String getShouldNotDisplayOnDefaultPagePrefKey() {
+		return XMLUIPreferenceNames.CONTENT_ASSIST_DO_NOT_DISPLAY_ON_DEFAULT_PAGE;
+	}
+
+	/**
+	 * @see org.eclipse.wst.sse.ui.preferences.AbstractCompletionProposalCategoriesConfiguration#getShouldNotDisplayOnOwnPagePrefKey()
+	 */
+	protected String getShouldNotDisplayOnOwnPagePrefKey() {
+		return XMLUIPreferenceNames.CONTENT_ASSIST_DO_NOT_DISPLAY_ON_OWN_PAGE;
+	}
+
+	/**
+	 * @see org.eclipse.wst.sse.ui.preferences.AbstractCompletionProposalCategoriesConfiguration#getPageSortOrderPrefKey()
+	 */
+	protected String getPageSortOrderPrefKey() {
+		return XMLUIPreferenceNames.CONTENT_ASSIST_OWN_PAGE_SORT_ORDER;
+	}
+	
+	/**
+	 * @see org.eclipse.wst.sse.ui.preferences.AbstractCompletionProposalCategoriesConfiguration#getDefaultPageSortOrderPrefKey()
+	 */
+	protected String getDefaultPageSortOrderPrefKey() {
+		return XMLUIPreferenceNames.CONTENT_ASSIST_DEFAULT_PAGE_SORT_ORDER;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/preferences/XMLContentAssistPreferencePage.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/preferences/XMLContentAssistPreferencePage.java
new file mode 100644
index 0000000..3e9ec27
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/preferences/XMLContentAssistPreferencePage.java
@@ -0,0 +1,256 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.preferences;
+
+import java.util.Vector;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+import org.eclipse.wst.sse.ui.internal.Logger;
+import org.eclipse.wst.sse.ui.internal.contentassist.CompletionProposoalCatigoriesConfigurationRegistry;
+import org.eclipse.wst.sse.ui.internal.preferences.ui.AbstractPreferencePage;
+import org.eclipse.wst.sse.ui.preferences.CodeAssistCyclingConfigurationBlock;
+import org.eclipse.wst.sse.ui.preferences.ICompletionProposalCategoriesConfigurationWriter;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+import org.eclipse.wst.xml.ui.internal.XMLUIPlugin;
+
+/**
+ * <p>Defines the preference page for allowing the user to change the content
+ * assist preferences</p>
+ */
+public class XMLContentAssistPreferencePage extends AbstractPreferencePage implements
+		IWorkbenchPreferencePage {
+
+	private static final String XML_CONTENT_TYPE_ID = "org.eclipse.core.runtime.xml"; //$NON-NLS-1$
+	
+	// Auto Activation
+	private Button fAutoPropose;
+	private Label fAutoProposeLabel;
+	private Text fAutoProposeText;
+	private Combo fSuggestionStrategyCombo;
+	private Vector fSuggestionStrategies = null;
+	
+	/** configuration block for changing preference having to do with the content assist categories */
+	private CodeAssistCyclingConfigurationBlock fConfigurationBlock;
+	
+	/**
+	 * @see org.eclipse.wst.sse.ui.internal.preferences.ui.AbstractPreferencePage#createContents(org.eclipse.swt.widgets.Composite)
+	 */
+	protected Control createContents(Composite parent) {
+		final Composite composite = super.createComposite(parent, 1);
+		
+		createContentsForAutoActivationGroup(composite);
+		createContentsForCyclingGroup(composite);
+		
+		setSize(composite);
+		loadPreferences();
+		
+		return composite;
+	}
+	
+	/**
+	 * @see org.eclipse.wst.sse.ui.internal.preferences.ui.AbstractPreferencePage#performDefaults()
+	 */
+	protected void performDefaults() {
+		performDefaultsForAutoActivationGroup();
+		performDefaultsForCyclingGroup();
+
+		validateValues();
+		enableValues();
+
+		super.performDefaults();
+	}
+	
+	/**
+	 * @see org.eclipse.wst.sse.ui.internal.preferences.ui.AbstractPreferencePage#initializeValues()
+	 */
+	protected void initializeValues() {
+		initializeValuesForAutoActivationGroup();
+		initializeValuesForCyclingGroup();
+	}
+	
+	/**
+	 * @see org.eclipse.wst.sse.ui.internal.preferences.ui.AbstractPreferencePage#storeValues()
+	 */
+	protected void storeValues() {
+		storeValuesForAutoActivationGroup();
+		storeValuesForCyclingGroup();
+	}
+	
+	/**
+	 * @see org.eclipse.wst.sse.ui.internal.preferences.ui.AbstractPreferencePage#enableValues()
+	 */
+	protected void enableValues() {
+		if (fAutoPropose != null) {
+			if (fAutoPropose.getSelection()) {
+				fAutoProposeLabel.setEnabled(true);
+				fAutoProposeText.setEnabled(true);
+			}
+			else {
+				fAutoProposeLabel.setEnabled(false);
+				fAutoProposeText.setEnabled(false);
+			}
+		}
+	}
+	
+	/**
+	 * @see org.eclipse.jface.preference.PreferencePage#doGetPreferenceStore()
+	 */
+	protected IPreferenceStore doGetPreferenceStore() {
+		return XMLUIPlugin.getDefault().getPreferenceStore();
+	}
+
+	/**
+	 * <p>Create contents for the auto activation preference group</p>
+	 * @param parent {@link Composite} parent of the group
+	 */
+	private void createContentsForAutoActivationGroup(Composite parent) {
+		Group contentAssistGroup = createGroup(parent, 2);
+		contentAssistGroup.setText(XMLUIMessages.XMLContentAssistPreferencePage_Auto_Activation_UI_);
+
+		fAutoPropose = createCheckBox(contentAssistGroup, XMLUIMessages.Automatically_make_suggest_UI_);
+		((GridData) fAutoPropose.getLayoutData()).horizontalSpan = 2;
+		fAutoPropose.addSelectionListener(this);
+
+		fAutoProposeLabel = createLabel(contentAssistGroup, XMLUIMessages.Prompt_when_these_characte_UI_);
+		fAutoProposeText = createTextField(contentAssistGroup);
+
+		createLabel(contentAssistGroup, XMLUIMessages.Suggestion_Strategy);
+		fSuggestionStrategyCombo = new Combo(contentAssistGroup, SWT.READ_ONLY);
+		fSuggestionStrategies = new Vector();
+		fSuggestionStrategyCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+		fSuggestionStrategyCombo.add(XMLUIMessages.Suggestion_Strategy_Lax);
+		fSuggestionStrategies.add(XMLUIPreferenceNames.SUGGESTION_STRATEGY_VALUE_LAX);
+		fSuggestionStrategyCombo.add(XMLUIMessages.Suggestion_Strategy_Strict);
+		fSuggestionStrategies.add(XMLUIPreferenceNames.SUGGESTION_STRATEGY_VALUE_STRICT);
+	}
+	
+	/**
+	 * <p>Create the contents for the content assist cycling preference group</p>
+	 * @param parent {@link Composite} parent of the group
+	 */
+	private void createContentsForCyclingGroup(Composite parent) {
+		ICompletionProposalCategoriesConfigurationWriter configurationWriter = CompletionProposoalCatigoriesConfigurationRegistry.getDefault().getWritableConfiguration(XML_CONTENT_TYPE_ID);
+		
+		if(configurationWriter != null) {
+			fConfigurationBlock = new CodeAssistCyclingConfigurationBlock(XML_CONTENT_TYPE_ID, configurationWriter);
+			fConfigurationBlock.createContents(parent, XMLUIMessages.XMLContentAssistPreferencePage_Cycling_UI_);
+		} else {
+			Logger.log(Logger.ERROR, "There should be an ICompletionProposalCategoriesConfigurationWriter" + //$NON-NLS-1$
+					" specified for the XML content type, but can't fine it, thus can't create user" + //$NON-NLS-1$
+					" preference block for editing proposal categories preferences."); //$NON-NLS-1$
+		}
+	}
+	
+	/**
+	 * <p>Store the values for the auto activation group</p>
+	 */
+	private void storeValuesForAutoActivationGroup() {
+		getPreferenceStore().setValue(XMLUIPreferenceNames.AUTO_PROPOSE, fAutoPropose.getSelection());
+		getPreferenceStore().setValue(XMLUIPreferenceNames.AUTO_PROPOSE_CODE, fAutoProposeText.getText());
+		getPreferenceStore().setValue(XMLUIPreferenceNames.SUGGESTION_STRATEGY, getCurrentAutoActivationSuggestionStrategy());
+	}
+	
+	/**
+	 * <p>Store the values for the cycling group</p>
+	 */
+	private void storeValuesForCyclingGroup() {
+		if (fConfigurationBlock != null) {
+			fConfigurationBlock.storeValues();
+		}
+	}
+	
+	/**
+	 * <p>Initialize the values for the auto activation group</p>
+	 */
+	private void initializeValuesForAutoActivationGroup() {
+		fAutoPropose.setSelection(getPreferenceStore().getBoolean(XMLUIPreferenceNames.AUTO_PROPOSE));
+		fAutoProposeText.setText(getPreferenceStore().getString(XMLUIPreferenceNames.AUTO_PROPOSE_CODE));
+		String suggestionStrategy = getPreferenceStore().getString(XMLUIPreferenceNames.SUGGESTION_STRATEGY);
+		if (suggestionStrategy.length() > 0) {
+			setCurrentAutoActivationSuggestionStrategy(suggestionStrategy);
+		}
+		else {
+			setCurrentAutoActivationSuggestionStrategy(XMLUIPreferenceNames.SUGGESTION_STRATEGY_VALUE_LAX);
+		}
+	}
+	
+	/**
+	 * <p>Initialize the values for the cycling group</p>
+	 */
+	private void initializeValuesForCyclingGroup() {
+		if(fConfigurationBlock != null) {
+			fConfigurationBlock.initializeValues();
+		}
+	}
+	
+	/**
+	 * <p>Load the defaults for the auto activation group</p>
+	 */
+	private void performDefaultsForAutoActivationGroup() {
+		fAutoPropose.setSelection(getPreferenceStore().getDefaultBoolean(XMLUIPreferenceNames.AUTO_PROPOSE));
+		fAutoProposeText.setText(getPreferenceStore().getDefaultString(XMLUIPreferenceNames.AUTO_PROPOSE_CODE));
+		String suggestionStrategy = getPreferenceStore().getDefaultString(XMLUIPreferenceNames.SUGGESTION_STRATEGY);
+		if (suggestionStrategy.length() > 0) {
+			setCurrentAutoActivationSuggestionStrategy(suggestionStrategy);
+		}
+		else {
+			setCurrentAutoActivationSuggestionStrategy(XMLUIPreferenceNames.SUGGESTION_STRATEGY_VALUE_LAX);
+		}
+	}
+	
+	/**
+	 * <p>Load the defaults of the cycling group</p>
+	 */
+	private void performDefaultsForCyclingGroup() {
+		if(fConfigurationBlock != null) {
+			fConfigurationBlock.performDefaults();
+		}
+	}
+	
+	/**
+	 * Return the currently selected suggestion strategy preference
+	 * 
+	 * @return a suggestion strategy constant from XMLUIPreferenceNames
+	 */
+	private String getCurrentAutoActivationSuggestionStrategy() {
+		int i = fSuggestionStrategyCombo.getSelectionIndex();
+		if (i >= 0) {
+			return (String) (fSuggestionStrategies.elementAt(i));
+		}
+		return ""; //$NON-NLS-1$
+	}
+	
+	/**
+	 * Set a suggestion strategy in suggestion strategy combo box
+	 * 
+	 * @param strategy
+	 */
+	private void setCurrentAutoActivationSuggestionStrategy(String strategy) {
+		// Clear the current selection.
+		fSuggestionStrategyCombo.clearSelection();
+		fSuggestionStrategyCombo.deselectAll();
+
+		int i = fSuggestionStrategies.indexOf(strategy);
+		if (i >= 0) {
+			fSuggestionStrategyCombo.select(i);
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/preferences/XMLFilesPreferencePage.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/preferences/XMLFilesPreferencePage.java
new file mode 100644
index 0000000..8a19fca
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/preferences/XMLFilesPreferencePage.java
@@ -0,0 +1,178 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2009 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.preferences;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.core.runtime.content.IContentType;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.wst.sse.core.internal.encoding.CommonEncodingPreferenceNames;
+import org.eclipse.wst.sse.ui.internal.preferences.ui.AbstractPreferencePage;
+import org.eclipse.wst.xml.core.internal.XMLCorePlugin;
+import org.eclipse.wst.xml.core.internal.preferences.XMLCorePreferenceNames;
+import org.eclipse.wst.xml.core.internal.provisional.contenttype.ContentTypeIdForXML;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+import org.eclipse.wst.xml.ui.internal.editor.IHelpContextIds;
+
+public class XMLFilesPreferencePage extends AbstractPreferencePage {
+	protected EncodingSettings fEncodingSettings = null;
+
+	private Combo fDefaultSuffix;
+	private List fValidExtensions;
+
+	protected Control createContents(Composite parent) {
+		Composite composite = (Composite) super.createContents(parent);
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, IHelpContextIds.XML_PREFWEBX_FILES_HELPID);
+		createContentsForCreatingGroup(composite);
+
+		setSize(composite);
+		loadPreferences();
+
+		return composite;
+	}
+
+	protected void createContentsForCreatingGroup(Composite parent) {
+		Group creatingGroup = createGroup(parent, 2);
+		creatingGroup.setText(XMLUIMessages.Creating_files);
+
+		// Default extension for New file Wizard
+		createLabel(creatingGroup, XMLUIMessages.XMLFilesPreferencePage_ExtensionLabel);
+		fDefaultSuffix = createDropDownBox(creatingGroup);
+		String[] validExtensions = (String[]) getValidExtensions().toArray(new String[0]);
+		Arrays.sort(validExtensions);
+		fDefaultSuffix.setItems(validExtensions);
+		fDefaultSuffix.addSelectionListener(this);
+
+		Label label = createLabel(creatingGroup, XMLUIMessages.Encoding_desc);
+		((GridData) label.getLayoutData()).horizontalSpan = 2;
+		fEncodingSettings = new EncodingSettings(creatingGroup, XMLUIMessages.Encoding);
+		((GridData) fEncodingSettings.getLayoutData()).horizontalSpan = 2;
+	}
+
+	public void dispose() {
+		fDefaultSuffix.removeModifyListener(this);
+		super.dispose();
+	}
+
+	protected void doSavePreferenceStore() {
+		XMLCorePlugin.getDefault().savePluginPreferences(); // model
+	}
+
+	/**
+	 * Get content type associated with this new file wizard
+	 * 
+	 * @return IContentType
+	 */
+	protected IContentType getContentType() {
+		return Platform.getContentTypeManager().getContentType(ContentTypeIdForXML.ContentTypeID_XML);
+	}
+
+	/**
+	 * Get list of valid extensions
+	 * 
+	 * @return List
+	 */
+	private List getValidExtensions() {
+		if (fValidExtensions == null) {
+			IContentType type = getContentType();
+			fValidExtensions = new ArrayList(Arrays.asList(type.getFileSpecs(IContentType.FILE_EXTENSION_SPEC)));
+		}
+		return fValidExtensions;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.wst.sse.ui.preferences.ui.AbstractPreferencePage#getModelPreferences()
+	 */
+	protected Preferences getModelPreferences() {
+		return XMLCorePlugin.getDefault().getPluginPreferences();
+	}
+
+	protected void initializeValues() {
+		initializeValuesForCreatingGroup();
+	}
+
+	protected void initializeValuesForCreatingGroup() {
+		String suffix = getModelPreferences().getString(XMLCorePreferenceNames.DEFAULT_EXTENSION);
+		fDefaultSuffix.setText(suffix);
+
+		String encoding = getModelPreferences().getString(CommonEncodingPreferenceNames.OUTPUT_CODESET);
+
+		fEncodingSettings.setIANATag(encoding);
+	}
+
+	protected void performDefaults() {
+		performDefaultsForCreatingGroup();
+
+		super.performDefaults();
+	}
+
+	protected void performDefaultsForCreatingGroup() {
+		String suffix = getModelPreferences().getDefaultString(XMLCorePreferenceNames.DEFAULT_EXTENSION);
+		fDefaultSuffix.setText(suffix);
+
+		String encoding = getModelPreferences().getDefaultString(CommonEncodingPreferenceNames.OUTPUT_CODESET);
+
+		fEncodingSettings.setIANATag(encoding);
+		// fEncodingSettings.resetToDefaultEncoding();
+	}
+
+	public boolean performOk() {
+		boolean result = super.performOk();
+
+		doSavePreferenceStore();
+
+		return result;
+	}
+
+	protected void storeValues() {
+		storeValuesForCreatingGroup();
+	}
+
+	protected void storeValuesForCreatingGroup() {
+		String suffix = fDefaultSuffix.getText();
+		getModelPreferences().setValue(XMLCorePreferenceNames.DEFAULT_EXTENSION, suffix);
+
+		getModelPreferences().setValue(CommonEncodingPreferenceNames.OUTPUT_CODESET, fEncodingSettings.getIANATag());
+	}
+
+	protected void validateValues() {
+		boolean isValid = false;
+		Iterator i = getValidExtensions().iterator();
+		while (i.hasNext() && !isValid) {
+			String extension = (String) i.next();
+			isValid = extension.equalsIgnoreCase(fDefaultSuffix.getText());
+		}
+
+		if (!isValid) {
+			setErrorMessage(NLS.bind(XMLUIMessages.XMLFilesPreferencePage_ExtensionError, getValidExtensions().toString()));
+			setValid(false);
+		}
+		else {
+			setErrorMessage(null);
+			setValid(true);
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/preferences/XMLSourcePreferencePage.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/preferences/XMLSourcePreferencePage.java
new file mode 100644
index 0000000..6545689
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/preferences/XMLSourcePreferencePage.java
@@ -0,0 +1,306 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.preferences;
+
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.jface.layout.GridDataFactory;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Spinner;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.dialogs.PreferenceLinkArea;
+import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer;
+import org.eclipse.wst.sse.ui.internal.preferences.ui.AbstractPreferencePage;
+import org.eclipse.wst.xml.core.internal.XMLCorePlugin;
+import org.eclipse.wst.xml.core.internal.preferences.XMLCorePreferenceNames;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+import org.eclipse.wst.xml.ui.internal.XMLUIPlugin;
+import org.eclipse.wst.xml.ui.internal.editor.IHelpContextIds;
+
+public class XMLSourcePreferencePage extends AbstractPreferencePage implements ModifyListener, SelectionListener, IWorkbenchPreferencePage {
+	private final int MIN_INDENTATION_SIZE = 0;
+	private final int MAX_INDENTATION_SIZE = 16;
+
+	// Formatting
+	protected Label fLineWidthLabel;
+	protected Text fLineWidthText;
+	protected Button fSplitMultiAttrs;
+	private Button fIndentUsingTabs;
+	private Button fIndentUsingSpaces;
+	private Spinner fIndentationSize;
+	private Button fPreservePCDATAContent;
+	private Button fAlignEndBracket;
+	private Button fFormatComments;
+	private Button fFormatCommentsJoinLines;
+	// BUG195264 - Support for removing/adding a space before empty close tags
+	private Button fSpaceBeforeEmptyCloseTag;
+	protected Button fClearAllBlankLines;
+
+	// grammar constraints
+	protected Button fUseInferredGrammar;
+
+	protected Control createContents(Composite parent) {
+		final Composite composite = super.createComposite(parent, 1);
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, IHelpContextIds.XML_PREFWEBX_SOURCE_HELPID);
+
+		new PreferenceLinkArea(composite, SWT.WRAP | SWT.MULTI, "org.eclipse.wst.sse.ui.preferences.editor", XMLUIMessages._UI_STRUCTURED_TEXT_EDITOR_PREFS_LINK,//$NON-NLS-1$
+					(IWorkbenchPreferenceContainer) getContainer(), null).getControl().setLayoutData(GridDataFactory.fillDefaults().hint(150, SWT.DEFAULT).create());
+		new Label(composite, SWT.NONE).setLayoutData(GridDataFactory.swtDefaults().create());
+
+		createContentsForFormattingGroup(composite);
+		createContentsForGrammarConstraintsGroup(composite);
+		setSize(composite);
+		loadPreferences();
+
+		return composite;
+	}
+
+	protected void createContentsForFormattingGroup(Composite parent) {
+		Group formattingGroup = createGroup(parent, 2);
+		formattingGroup.setText(XMLUIMessages.Formatting_UI_);
+
+		fLineWidthLabel = createLabel(formattingGroup, XMLUIMessages.Line_width__UI_);
+		fLineWidthText = new Text(formattingGroup, SWT.SINGLE | SWT.BORDER);
+		GridData gData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING | GridData.BEGINNING);
+		gData.widthHint = 25;
+		fLineWidthText.setLayoutData(gData);
+		fLineWidthText.addModifyListener(this);
+
+		fSplitMultiAttrs = createCheckBox(formattingGroup, XMLUIMessages.Split_multiple_attributes);
+		((GridData) fSplitMultiAttrs.getLayoutData()).horizontalSpan = 2;
+		fAlignEndBracket = createCheckBox(formattingGroup, XMLUIMessages.Align_final_bracket);
+		((GridData) fAlignEndBracket.getLayoutData()).horizontalSpan = 2;
+		fPreservePCDATAContent = createCheckBox(formattingGroup, XMLUIMessages.Preserve_PCDATA_Content);
+		((GridData) fPreservePCDATAContent.getLayoutData()).horizontalSpan = 2;
+		fClearAllBlankLines = createCheckBox(formattingGroup, XMLUIMessages.Clear_all_blank_lines_UI_);
+		((GridData) fClearAllBlankLines.getLayoutData()).horizontalSpan = 2;
+		// formatting comments
+		fFormatComments = createCheckBox(formattingGroup, XMLUIMessages.Format_comments);
+		((GridData) fFormatComments.getLayoutData()).horizontalSpan = 2;
+		fFormatComments.addSelectionListener(this);
+		fFormatCommentsJoinLines = createCheckBox(formattingGroup, XMLUIMessages.Format_comments_join_lines);
+		((GridData) fFormatCommentsJoinLines.getLayoutData()).horizontalSpan = 2;
+		((GridData) fFormatCommentsJoinLines.getLayoutData()).horizontalIndent = 20;
+		// end formatting comments
+		fSpaceBeforeEmptyCloseTag = createCheckBox(formattingGroup, XMLUIMessages.Space_before_empty_close_tag);
+		((GridData) fSpaceBeforeEmptyCloseTag.getLayoutData()).horizontalSpan = 2;
+
+		// [269224] - Place the indent controls in their own composite for proper tab ordering
+		Composite indentComposite = createComposite(formattingGroup, 1);
+		((GridData) indentComposite.getLayoutData()).horizontalSpan = 2;
+		((GridLayout) indentComposite.getLayout()).marginWidth = 0;
+		((GridLayout) indentComposite.getLayout()).marginHeight = 0;
+
+		fIndentUsingTabs = createRadioButton(indentComposite, XMLUIMessages.Indent_using_tabs);
+		((GridData) fIndentUsingTabs.getLayoutData()).horizontalSpan = 1;
+
+		fIndentUsingSpaces = createRadioButton(indentComposite, XMLUIMessages.Indent_using_spaces);
+		((GridData) fIndentUsingSpaces.getLayoutData()).horizontalSpan = 1;
+
+		createLabel(formattingGroup, XMLUIMessages.Indentation_size);
+		fIndentationSize = new Spinner(formattingGroup, SWT.READ_ONLY | SWT.BORDER);
+		GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
+		fIndentationSize.setLayoutData(gd);
+		fIndentationSize.setToolTipText(XMLUIMessages.Indentation_size_tip);
+		fIndentationSize.setMinimum(MIN_INDENTATION_SIZE);
+		fIndentationSize.setMaximum(MAX_INDENTATION_SIZE);
+		fIndentationSize.setIncrement(1);
+		fIndentationSize.setPageIncrement(4);
+		fIndentationSize.addModifyListener(this);
+	}
+
+	protected void createContentsForGrammarConstraintsGroup(Composite parent) {
+		Group grammarConstraintsGroup = createGroup(parent, 1);
+		grammarConstraintsGroup.setText(XMLUIMessages.Grammar_Constraints);
+		grammarConstraintsGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL));
+
+		fUseInferredGrammar = createCheckBox(grammarConstraintsGroup, XMLUIMessages.Use_inferred_grammar_in_absence_of);
+	}
+
+	protected IPreferenceStore doGetPreferenceStore() {
+		return XMLUIPlugin.getDefault().getPreferenceStore();
+	}
+
+	protected void doSavePreferenceStore() {
+		XMLUIPlugin.getDefault().savePluginPreferences(); // editor
+		XMLCorePlugin.getDefault().savePluginPreferences(); // model
+	}
+
+	protected void enableValues() {
+		if (fFormatComments != null && fFormatCommentsJoinLines != null) {
+			fFormatCommentsJoinLines.setEnabled(fFormatComments.getSelection());
+		}
+	}
+
+	protected Preferences getModelPreferences() {
+		return XMLCorePlugin.getDefault().getPluginPreferences();
+	}
+
+	protected void initializeValues() {
+		initializeValuesForFormattingGroup();
+		initializeValuesForGrammarConstraintsGroup();
+	}
+
+	protected void initializeValuesForFormattingGroup() {
+		// Formatting
+		fLineWidthText.setText(getModelPreferences().getString(XMLCorePreferenceNames.LINE_WIDTH));
+		fSplitMultiAttrs.setSelection(getModelPreferences().getBoolean(XMLCorePreferenceNames.SPLIT_MULTI_ATTRS));
+		fAlignEndBracket.setSelection(getModelPreferences().getBoolean(XMLCorePreferenceNames.ALIGN_END_BRACKET));
+		fClearAllBlankLines.setSelection(getModelPreferences().getBoolean(XMLCorePreferenceNames.CLEAR_ALL_BLANK_LINES));
+		fPreservePCDATAContent.setSelection(getModelPreferences().getBoolean(XMLCorePreferenceNames.PRESERVE_CDATACONTENT));
+		fSpaceBeforeEmptyCloseTag.setSelection(getModelPreferences().getBoolean(XMLCorePreferenceNames.SPACE_BEFORE_EMPTY_CLOSE_TAG));
+		fFormatComments.setSelection(getModelPreferences().getBoolean(XMLCorePreferenceNames.FORMAT_COMMENT_TEXT));
+		fFormatCommentsJoinLines.setSelection(getModelPreferences().getBoolean(XMLCorePreferenceNames.FORMAT_COMMENT_JOIN_LINES));
+
+		if (XMLCorePreferenceNames.TAB.equals(getModelPreferences().getString(XMLCorePreferenceNames.INDENTATION_CHAR))) {
+			fIndentUsingTabs.setSelection(true);
+			fIndentUsingSpaces.setSelection(false);
+		}
+		else {
+			fIndentUsingSpaces.setSelection(true);
+			fIndentUsingTabs.setSelection(false);
+		}
+
+		fIndentationSize.setSelection(getModelPreferences().getInt(XMLCorePreferenceNames.INDENTATION_SIZE));
+	}
+
+	protected void initializeValuesForGrammarConstraintsGroup() {
+		fUseInferredGrammar.setSelection(getPreferenceStore().getBoolean(XMLUIPreferenceNames.USE_INFERRED_GRAMMAR));
+	}
+
+	protected void performDefaults() {
+		performDefaultsForFormattingGroup();
+		performDefaultsForGrammarConstraintsGroup();
+
+		validateValues();
+		enableValues();
+
+		super.performDefaults();
+	}
+
+	protected void performDefaultsForFormattingGroup() {
+		// Formatting
+		fLineWidthText.setText(getModelPreferences().getDefaultString(XMLCorePreferenceNames.LINE_WIDTH));
+		fSplitMultiAttrs.setSelection(getModelPreferences().getDefaultBoolean(XMLCorePreferenceNames.SPLIT_MULTI_ATTRS));
+		fAlignEndBracket.setSelection(getModelPreferences().getDefaultBoolean(XMLCorePreferenceNames.ALIGN_END_BRACKET));
+		fClearAllBlankLines.setSelection(getModelPreferences().getDefaultBoolean(XMLCorePreferenceNames.CLEAR_ALL_BLANK_LINES));
+		fPreservePCDATAContent.setSelection(getModelPreferences().getDefaultBoolean(XMLCorePreferenceNames.PRESERVE_CDATACONTENT));
+		// BUG195264 - Support for removing/adding a space before empty close tags
+		fSpaceBeforeEmptyCloseTag.setSelection(getModelPreferences().getDefaultBoolean(XMLCorePreferenceNames.SPACE_BEFORE_EMPTY_CLOSE_TAG));
+		fFormatComments.setSelection(getModelPreferences().getDefaultBoolean(XMLCorePreferenceNames.FORMAT_COMMENT_TEXT));
+		fFormatCommentsJoinLines.setSelection(getModelPreferences().getDefaultBoolean(XMLCorePreferenceNames.FORMAT_COMMENT_JOIN_LINES));
+
+		if (XMLCorePreferenceNames.TAB.equals(getModelPreferences().getDefaultString(XMLCorePreferenceNames.INDENTATION_CHAR))) {
+			fIndentUsingTabs.setSelection(true);
+			fIndentUsingSpaces.setSelection(false);
+		}
+		else {
+			fIndentUsingSpaces.setSelection(true);
+			fIndentUsingTabs.setSelection(false);
+		}
+		fIndentationSize.setSelection(getModelPreferences().getDefaultInt(XMLCorePreferenceNames.INDENTATION_SIZE));
+	}
+
+	protected void performDefaultsForGrammarConstraintsGroup() {
+		fUseInferredGrammar.setSelection(getPreferenceStore().getDefaultBoolean(XMLUIPreferenceNames.USE_INFERRED_GRAMMAR));
+	}
+
+	public boolean performOk() {
+		boolean result = super.performOk();
+
+		doSavePreferenceStore();
+
+		return result;
+	}
+
+	protected void storeValues() {
+		storeValuesForFormattingGroup();
+		storeValuesForGrammarConstraintsGroup();
+	}
+
+	protected void storeValuesForFormattingGroup() {
+		// Formatting
+		getModelPreferences().setValue(XMLCorePreferenceNames.LINE_WIDTH, fLineWidthText.getText());
+		getModelPreferences().setValue(XMLCorePreferenceNames.SPLIT_MULTI_ATTRS, fSplitMultiAttrs.getSelection());
+		getModelPreferences().setValue(XMLCorePreferenceNames.ALIGN_END_BRACKET, fAlignEndBracket.getSelection());
+		getModelPreferences().setValue(XMLCorePreferenceNames.CLEAR_ALL_BLANK_LINES, fClearAllBlankLines.getSelection());
+		getModelPreferences().setValue(XMLCorePreferenceNames.PRESERVE_CDATACONTENT, fPreservePCDATAContent.getSelection());
+		// BUG195264 - Support for removing/adding a space before empty close tags
+		getModelPreferences().setValue(XMLCorePreferenceNames.SPACE_BEFORE_EMPTY_CLOSE_TAG, fSpaceBeforeEmptyCloseTag.getSelection());
+		getModelPreferences().setValue(XMLCorePreferenceNames.FORMAT_COMMENT_TEXT, fFormatComments.getSelection());
+		getModelPreferences().setValue(XMLCorePreferenceNames.FORMAT_COMMENT_JOIN_LINES, fFormatCommentsJoinLines.getSelection());
+
+		if (fIndentUsingTabs.getSelection()) {
+			getModelPreferences().setValue(XMLCorePreferenceNames.INDENTATION_CHAR, XMLCorePreferenceNames.TAB);
+		}
+		else {
+			getModelPreferences().setValue(XMLCorePreferenceNames.INDENTATION_CHAR, XMLCorePreferenceNames.SPACE);
+		}
+		getModelPreferences().setValue(XMLCorePreferenceNames.INDENTATION_SIZE, fIndentationSize.getSelection());
+	}
+
+	protected void storeValuesForGrammarConstraintsGroup() {
+		getPreferenceStore().setValue(XMLUIPreferenceNames.USE_INFERRED_GRAMMAR, fUseInferredGrammar.getSelection());
+	}
+
+	protected void validateValues() {
+		boolean isError = false;
+		String widthText = null;
+
+		if (fLineWidthText != null) {
+			try {
+				widthText = fLineWidthText.getText();
+				int formattingLineWidth = Integer.parseInt(widthText);
+				if ((formattingLineWidth < WIDTH_VALIDATION_LOWER_LIMIT) || (formattingLineWidth > WIDTH_VALIDATION_UPPER_LIMIT)) {
+					throw new NumberFormatException();
+				}
+			}
+			catch (NumberFormatException nfexc) {
+				setInvalidInputMessage(widthText);
+				setValid(false);
+				isError = true;
+			}
+		}
+
+		int indentSize = 0;
+		if (fIndentationSize != null) {
+			try {
+				indentSize = fIndentationSize.getSelection();
+				if ((indentSize < MIN_INDENTATION_SIZE) || (indentSize > MAX_INDENTATION_SIZE)) {
+					throw new NumberFormatException();
+				}
+			}
+			catch (NumberFormatException nfexc) {
+				setInvalidInputMessage(Integer.toString(indentSize));
+				setValid(false);
+				isError = true;
+			}
+		}
+
+		if (!isError) {
+			setErrorMessage(null);
+			setValid(true);
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/preferences/XMLSyntaxColoringPage.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/preferences/XMLSyntaxColoringPage.java
new file mode 100644
index 0000000..245f0ab
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/preferences/XMLSyntaxColoringPage.java
@@ -0,0 +1,873 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.preferences;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.jface.preference.ColorSelector;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.preference.PreferencePage;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.text.TextAttribute;
+import org.eclipse.jface.text.source.SourceViewer;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.ListViewer;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.StructuredViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerComparator;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.accessibility.ACC;
+import org.eclipse.swt.accessibility.AccessibleAdapter;
+import org.eclipse.swt.accessibility.AccessibleEvent;
+import org.eclipse.swt.custom.SashForm;
+import org.eclipse.swt.custom.StyleRange;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.KeyListener;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.events.TraverseEvent;
+import org.eclipse.swt.events.TraverseListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Link;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.dialogs.PreferencesUtil;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+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.ITextRegionList;
+import org.eclipse.wst.sse.ui.internal.SSEUIMessages;
+import org.eclipse.wst.sse.ui.internal.SSEUIPlugin;
+import org.eclipse.wst.sse.ui.internal.preferences.OverlayPreferenceStore;
+import org.eclipse.wst.sse.ui.internal.preferences.OverlayPreferenceStore.OverlayKey;
+import org.eclipse.wst.sse.ui.internal.preferences.ui.ColorHelper;
+import org.eclipse.wst.sse.ui.internal.util.EditorUtility;
+import org.eclipse.wst.xml.core.internal.provisional.contenttype.ContentTypeIdForXML;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+import org.eclipse.wst.xml.ui.internal.XMLUIPlugin;
+import org.eclipse.wst.xml.ui.internal.editor.IHelpContextIds;
+import org.eclipse.wst.xml.ui.internal.style.IStyleConstantsXML;
+
+import com.ibm.icu.text.Collator;
+
+/**
+ * A preference page to configure our XML syntax color. It resembles the JDT
+ * and CDT pages far more than our original color page while retaining the
+ * extra "click-to-find" functionality.
+ */
+public final class XMLSyntaxColoringPage extends PreferencePage implements IWorkbenchPreferencePage {
+
+	private Button fBold;
+	private Label fForegroundLabel;
+	private Label fBackgroundLabel;
+	private Button fClearStyle;
+	private Map fContextToStyleMap;
+	private Color fDefaultForeground = null;
+	private Color fDefaultBackground = null;
+	private IStructuredDocument fDocument;
+	private ColorSelector fForegroundColorEditor;
+	private ColorSelector fBackgroundColorEditor;
+	private Button fItalic;
+	private OverlayPreferenceStore fOverlayStore;
+	private Button fStrike;
+	private Collection fStylePreferenceKeys;
+	private StructuredViewer fStylesViewer = null;
+	private Map fStyleToDescriptionMap;
+	private StyledText fText;
+	private Button fUnderline;
+
+	// activate controls based on the given local color type
+	private void activate(String namedStyle) {
+		Color foreground = fDefaultForeground;
+		Color background = fDefaultBackground;
+		if (namedStyle == null) {
+			fClearStyle.setEnabled(false);
+			fBold.setEnabled(false);
+			fItalic.setEnabled(false);
+			fStrike.setEnabled(false);
+			fUnderline.setEnabled(false);
+			fForegroundLabel.setEnabled(false);
+			fBackgroundLabel.setEnabled(false);
+			fForegroundColorEditor.setEnabled(false);
+			fBackgroundColorEditor.setEnabled(false);
+			fBold.setSelection(false);
+			fItalic.setSelection(false);
+			fStrike.setSelection(false);
+			fUnderline.setSelection(false);
+		}
+		else {
+			TextAttribute attribute = getAttributeFor(namedStyle);
+			fClearStyle.setEnabled(true);
+			fBold.setEnabled(true);
+			fItalic.setEnabled(true);
+			fStrike.setEnabled(true);
+			fUnderline.setEnabled(true);
+			fForegroundLabel.setEnabled(true);
+			fBackgroundLabel.setEnabled(true);
+			fForegroundColorEditor.setEnabled(true);
+			fBackgroundColorEditor.setEnabled(true);
+			fBold.setSelection((attribute.getStyle() & SWT.BOLD) != 0);
+			fItalic.setSelection((attribute.getStyle() & SWT.ITALIC) != 0);
+			fStrike.setSelection((attribute.getStyle() & TextAttribute.STRIKETHROUGH) != 0);
+			fUnderline.setSelection((attribute.getStyle() & TextAttribute.UNDERLINE) != 0);
+			if (attribute.getForeground() != null) {
+				foreground = attribute.getForeground();
+			}
+			if (attribute.getBackground() != null) {
+				background = attribute.getBackground();
+			}
+		}
+
+		fForegroundColorEditor.setColorValue(foreground.getRGB());
+		fBackgroundColorEditor.setColorValue(background.getRGB());
+	}
+
+	/**
+	 * Color the text in the sample area according to the current preferences
+	 */
+	void applyStyles() {
+		if (fText == null || fText.isDisposed())
+			return;
+		IStructuredDocumentRegion documentRegion = fDocument.getFirstStructuredDocumentRegion();
+		while (documentRegion != null) {
+			ITextRegionList regions = documentRegion.getRegions();
+			for (int i = 0; i < regions.size(); i++) {
+				ITextRegion currentRegion = regions.get(i);
+				// lookup the local coloring type and apply it
+				String namedStyle = (String) fContextToStyleMap.get(currentRegion.getType());
+				if (namedStyle == null)
+					continue;
+				TextAttribute attribute = getAttributeFor(namedStyle);
+				if (attribute == null)
+					continue;
+				StyleRange style = new StyleRange(documentRegion.getStartOffset(currentRegion), currentRegion.getTextLength(), attribute.getForeground(), attribute.getBackground(), attribute.getStyle());
+				style.strikeout = (attribute.getStyle() & TextAttribute.STRIKETHROUGH) != 0;
+				style.underline = (attribute.getStyle() & TextAttribute.UNDERLINE) != 0;
+				fText.setStyleRange(style);
+			}
+			documentRegion = documentRegion.getNext();
+		}
+	}
+
+	Button createCheckbox(Composite parent, String label) {
+		Button button = new Button(parent, SWT.CHECK);
+		button.setText(label);
+		button.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+		return button;
+	}
+
+	/**
+	 * Creates composite control and sets the default layout data.
+	 */
+	private Composite createComposite(Composite parent, int numColumns) {
+		Composite composite = new Composite(parent, SWT.NULL);
+
+		// GridLayout
+		GridLayout layout = new GridLayout();
+		layout.numColumns = numColumns;
+		layout.makeColumnsEqualWidth = false;
+		layout.marginHeight = 0;
+		layout.marginWidth = 0;
+		composite.setLayout(layout);
+
+		// GridData
+		GridData data = new GridData(SWT.FILL, SWT.FILL, true, false);
+		composite.setLayoutData(data);
+		return composite;
+	}
+
+	protected Control createContents(final Composite parent) {
+		initializeDialogUnits(parent);
+
+		fDefaultForeground = parent.getDisplay().getSystemColor(SWT.COLOR_LIST_FOREGROUND);
+		fDefaultBackground = parent.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND);
+		Composite pageComponent = createComposite(parent, 2);
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(pageComponent, IHelpContextIds.XML_PREFWEBX_STYLES_HELPID);
+
+		Link link = new Link(pageComponent, SWT.WRAP);
+		link.setText(SSEUIMessages.SyntaxColoring_Link);
+		link.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				PreferencesUtil.createPreferenceDialogOn(parent.getShell(), e.text, null, null);
+			}
+		});
+
+		GridData linkData= new GridData(SWT.FILL, SWT.BEGINNING, true, false, 2, 1);
+		linkData.widthHint= 150; // only expand further if anyone else requires it
+		link.setLayoutData(linkData);
+
+		new Label(pageComponent, SWT.NONE).setLayoutData(new GridData());
+		new Label(pageComponent, SWT.NONE).setLayoutData(new GridData());
+
+		SashForm editor = new SashForm(pageComponent, SWT.VERTICAL);
+		GridData gridData2 = new GridData(SWT.FILL, SWT.FILL, true, true);
+		gridData2.horizontalSpan = 2;
+		editor.setLayoutData(gridData2);
+		SashForm top = new SashForm(editor, SWT.HORIZONTAL);
+		Composite styleEditor = createComposite(top, 1);
+		((GridLayout) styleEditor.getLayout()).marginRight = 5;
+		((GridLayout) styleEditor.getLayout()).marginLeft = 0;
+		createLabel(styleEditor, XMLUIMessages.SyntaxColoringPage_0);
+		fStylesViewer = createStylesViewer(styleEditor);
+		GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
+		gridData.horizontalIndent = 0;
+		Iterator iterator = fStyleToDescriptionMap.values().iterator();
+		while (iterator.hasNext()) {
+			gridData.widthHint = Math.max(gridData.widthHint, convertWidthInCharsToPixels(iterator.next().toString().length()));
+		}
+		gridData.heightHint = convertHeightInCharsToPixels(5);
+		fStylesViewer.getControl().setLayoutData(gridData);
+
+		Composite editingComposite = createComposite(top, 1);
+		((GridLayout) styleEditor.getLayout()).marginLeft = 5;
+		createLabel(editingComposite, ""); //$NON-NLS-1$
+		Button enabler = createCheckbox(editingComposite, XMLUIMessages.SyntaxColoringPage_2);
+		enabler.setEnabled(false);
+		enabler.setSelection(true);
+		Composite editControls = createComposite(editingComposite, 2);
+		((GridLayout) editControls.getLayout()).marginLeft = 20;
+
+		fForegroundLabel = createLabel(editControls, SSEUIMessages.Foreground_UI_);
+		((GridData) fForegroundLabel.getLayoutData()).verticalAlignment = SWT.CENTER;
+		fForegroundLabel.setEnabled(false);
+
+		fForegroundColorEditor = new ColorSelector(editControls);
+		Button fForegroundColor = fForegroundColorEditor.getButton();
+		GridData gd = new GridData(SWT.BEGINNING, SWT.FILL, false, false);
+		fForegroundColor.setLayoutData(gd);
+		fForegroundColorEditor.setEnabled(false);
+
+		fBackgroundLabel = createLabel(editControls, SSEUIMessages.Background_UI_);
+		((GridData) fBackgroundLabel.getLayoutData()).verticalAlignment = SWT.CENTER;
+		fBackgroundLabel.setEnabled(false);
+
+		fBackgroundColorEditor = new ColorSelector(editControls);
+		Button fBackgroundColor = fBackgroundColorEditor.getButton();
+		gd = new GridData(SWT.BEGINNING, SWT.FILL, false, false);
+		fBackgroundColor.setLayoutData(gd);
+		fBackgroundColorEditor.setEnabled(false);
+
+		fBold = createCheckbox(editControls, XMLUIMessages.SyntaxColoringPage_3);
+		fBold.setEnabled(false);
+		((GridData) fBold.getLayoutData()).horizontalSpan = 2;
+		fItalic = createCheckbox(editControls, XMLUIMessages.SyntaxColoringPage_4);
+		fItalic.setEnabled(false);
+		((GridData) fItalic.getLayoutData()).horizontalSpan = 2;
+		fStrike = createCheckbox(editControls, XMLUIMessages.SyntaxColoringPage_5);
+		fStrike.setEnabled(false);
+		((GridData) fStrike.getLayoutData()).horizontalSpan = 2;
+		fUnderline = createCheckbox(editControls, XMLUIMessages.SyntaxColoringPage_6);
+		fUnderline.setEnabled(false);
+		((GridData) fUnderline.getLayoutData()).horizontalSpan = 2;
+		fClearStyle = new Button(editingComposite, SWT.PUSH);
+		fClearStyle.setText(SSEUIMessages.Restore_Default_UI_); //$NON-NLS-1$ = "Restore Default"
+		fClearStyle.setLayoutData(new GridData(SWT.BEGINNING));
+		((GridData) fClearStyle.getLayoutData()).horizontalIndent = 20;
+		fClearStyle.setEnabled(false);
+
+		Composite sampleArea = createComposite(editor, 1);
+
+		((GridLayout) sampleArea.getLayout()).marginLeft = 5;
+		((GridLayout) sampleArea.getLayout()).marginTop = 5;
+		createLabel(sampleArea, SSEUIMessages.Sample_text__UI_); //$NON-NLS-1$ = "&Sample text:"
+		SourceViewer viewer = new SourceViewer(sampleArea, null, SWT.BORDER | SWT.LEFT_TO_RIGHT | SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL | SWT.READ_ONLY);
+		fText = viewer.getTextWidget();
+		GridData gridData3 = new GridData(SWT.FILL, SWT.FILL, true, true);
+		gridData3.widthHint = convertWidthInCharsToPixels(20);
+		gridData3.heightHint = convertHeightInCharsToPixels(5);
+		gridData3.horizontalSpan = 2;
+		fText.setLayoutData(gridData3);
+		fText.setEditable(false);
+		fText.setFont(JFaceResources.getFont("org.eclipse.wst.sse.ui.textfont")); //$NON-NLS-1$
+		fText.addKeyListener(getTextKeyListener());
+		fText.addSelectionListener(getTextSelectionListener());
+		fText.addMouseListener(getTextMouseListener());
+		fText.addTraverseListener(getTraverseListener());
+		setAccessible(fText, SSEUIMessages.Sample_text__UI_);
+		fDocument = StructuredModelManager.getModelManager().createStructuredDocumentFor(ContentTypeIdForXML.ContentTypeID_XML);
+		fDocument.set(getExampleText());
+		viewer.setDocument(fDocument);
+
+		top.setWeights(new int[]{1, 1});
+		editor.setWeights(new int[]{1, 1});
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(pageComponent, IHelpContextIds.XML_PREFWEBX_STYLES_HELPID);
+
+		fStylesViewer.setInput(getStylePreferenceKeys());
+
+		applyStyles();
+
+		fStylesViewer.addSelectionChangedListener(new ISelectionChangedListener() {
+			public void selectionChanged(SelectionChangedEvent event) {
+				if (!event.getSelection().isEmpty()) {
+					Object o = ((IStructuredSelection) event.getSelection()).getFirstElement();
+					String namedStyle = o.toString();
+					activate(namedStyle);
+					if (namedStyle == null)
+						return;
+				}
+			}
+		});
+
+		fForegroundColorEditor.addListener(new IPropertyChangeListener() {
+			public void propertyChange(PropertyChangeEvent event) {
+				if (event.getProperty().equals(ColorSelector.PROP_COLORCHANGE)) {
+					Object o = ((IStructuredSelection) fStylesViewer.getSelection()).getFirstElement();
+					String namedStyle = o.toString();
+					String prefString = getOverlayStore().getString(namedStyle);
+					String[] stylePrefs = ColorHelper.unpackStylePreferences(prefString);
+					if (stylePrefs != null) {
+						String oldValue = stylePrefs[0];
+						// open color dialog to get new color
+						String newValue = ColorHelper.toRGBString(fForegroundColorEditor.getColorValue());
+
+						if (!newValue.equals(oldValue)) {
+							stylePrefs[0] = newValue;
+							String newPrefString = ColorHelper.packStylePreferences(stylePrefs);
+							getOverlayStore().setValue(namedStyle, newPrefString);
+							applyStyles();
+							fText.redraw();
+						}
+					}
+				}
+			}
+		});
+
+		fBackgroundColorEditor.addListener(new IPropertyChangeListener() {
+			public void propertyChange(PropertyChangeEvent event) {
+				if (event.getProperty().equals(ColorSelector.PROP_COLORCHANGE)) {
+					Object o = ((IStructuredSelection) fStylesViewer.getSelection()).getFirstElement();
+					String namedStyle = o.toString();
+					String prefString = getOverlayStore().getString(namedStyle);
+					String[] stylePrefs = ColorHelper.unpackStylePreferences(prefString);
+					if (stylePrefs != null) {
+						String oldValue = stylePrefs[1];
+						// open color dialog to get new color
+						String newValue = ColorHelper.toRGBString(fBackgroundColorEditor.getColorValue());
+
+						if (!newValue.equals(oldValue)) {
+							stylePrefs[1] = newValue;
+							String newPrefString = ColorHelper.packStylePreferences(stylePrefs);
+							getOverlayStore().setValue(namedStyle, newPrefString);
+							applyStyles();
+							fText.redraw();
+							activate(namedStyle);
+						}
+					}
+				}
+			}
+		});
+
+		fBold.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				super.widgetSelected(e);
+				// get current (newly old) style
+				Object o = ((IStructuredSelection) fStylesViewer.getSelection()).getFirstElement();
+				String namedStyle = o.toString();
+				String prefString = getOverlayStore().getString(namedStyle);
+				String[] stylePrefs = ColorHelper.unpackStylePreferences(prefString);
+				if (stylePrefs != null) {
+					String oldValue = stylePrefs[2];
+					String newValue = String.valueOf(fBold.getSelection());
+					if (!newValue.equals(oldValue)) {
+						stylePrefs[2] = newValue;
+						String newPrefString = ColorHelper.packStylePreferences(stylePrefs);
+						getOverlayStore().setValue(namedStyle, newPrefString);
+						applyStyles();
+						fText.redraw();
+					}
+				}
+			}
+		});
+
+		fItalic.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				super.widgetSelected(e);
+				// get current (newly old) style
+				Object o = ((IStructuredSelection) fStylesViewer.getSelection()).getFirstElement();
+				String namedStyle = o.toString();
+				String prefString = getOverlayStore().getString(namedStyle);
+				String[] stylePrefs = ColorHelper.unpackStylePreferences(prefString);
+				if (stylePrefs != null) {
+					String oldValue = stylePrefs[3];
+					String newValue = String.valueOf(fItalic.getSelection());
+					if (!newValue.equals(oldValue)) {
+						stylePrefs[3] = newValue;
+						String newPrefString = ColorHelper.packStylePreferences(stylePrefs);
+						getOverlayStore().setValue(namedStyle, newPrefString);
+						applyStyles();
+						fText.redraw();
+					}
+				}
+			}
+		});
+
+		fStrike.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				super.widgetSelected(e);
+				// get current (newly old) style
+				Object o = ((IStructuredSelection) fStylesViewer.getSelection()).getFirstElement();
+				String namedStyle = o.toString();
+				String prefString = getOverlayStore().getString(namedStyle);
+				String[] stylePrefs = ColorHelper.unpackStylePreferences(prefString);
+				if (stylePrefs != null) {
+					String oldValue = stylePrefs[4];
+					String newValue = String.valueOf(fStrike.getSelection());
+					if (!newValue.equals(oldValue)) {
+						stylePrefs[4] = newValue;
+						String newPrefString = ColorHelper.packStylePreferences(stylePrefs);
+						getOverlayStore().setValue(namedStyle, newPrefString);
+						applyStyles();
+						fText.redraw();
+					}
+				}
+			}
+		});
+
+		fUnderline.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				super.widgetSelected(e);
+				// get current (newly old) style
+				Object o = ((IStructuredSelection) fStylesViewer.getSelection()).getFirstElement();
+				String namedStyle = o.toString();
+				String prefString = getOverlayStore().getString(namedStyle);
+				String[] stylePrefs = ColorHelper.unpackStylePreferences(prefString);
+				if (stylePrefs != null) {
+					String oldValue = stylePrefs[5];
+					String newValue = String.valueOf(fUnderline.getSelection());
+					if (!newValue.equals(oldValue)) {
+						stylePrefs[5] = newValue;
+						String newPrefString = ColorHelper.packStylePreferences(stylePrefs);
+						getOverlayStore().setValue(namedStyle, newPrefString);
+						applyStyles();
+						fText.redraw();
+					}
+				}
+			}
+		});
+
+		fClearStyle.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				if (fStylesViewer.getSelection().isEmpty())
+					return;
+				String namedStyle = ((IStructuredSelection) fStylesViewer.getSelection()).getFirstElement().toString();
+				getOverlayStore().setToDefault(namedStyle);
+				applyStyles();
+				fText.redraw();
+				activate(namedStyle);
+			}
+		});
+
+		return pageComponent;
+	}
+
+	private Label createLabel(Composite parent, String text) {
+		Label label = new Label(parent, SWT.WRAP);
+		label.setText(text);
+		GridData data = new GridData(SWT.FILL, SWT.FILL, false, false);
+		label.setLayoutData(data);
+		label.setBackground(parent.getBackground());
+		return label;
+	}
+
+	// protected Label createDescriptionLabel(Composite parent) {
+	// return null;
+	// }
+
+	/**
+	 * Set up all the style preference keys in the overlay store
+	 */
+	private OverlayKey[] createOverlayStoreKeys() {
+		List overlayKeys = new ArrayList();
+
+		Iterator i = getStylePreferenceKeys().iterator();
+		while (i.hasNext()) {
+			overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, (String) i.next()));
+		}
+
+		OverlayPreferenceStore.OverlayKey[] keys = new OverlayPreferenceStore.OverlayKey[overlayKeys.size()];
+		overlayKeys.toArray(keys);
+		return keys;
+	}
+
+	/**
+	 * Creates the List viewer where we see the various syntax element display
+	 * names--would it ever be a Tree like JDT's?
+	 * 
+	 * @param parent
+	 * @return
+	 */
+	private StructuredViewer createStylesViewer(Composite parent) {
+		StructuredViewer stylesViewer = new ListViewer(parent, SWT.SINGLE | SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER);
+		stylesViewer.setComparator(new ViewerComparator(Collator.getInstance()));
+		stylesViewer.setLabelProvider(new LabelProvider() {
+			public String getText(Object element) {
+				Object description = fStyleToDescriptionMap.get(element);
+				if (description != null)
+					return description.toString();
+				return super.getText(element);
+			}
+		});
+		stylesViewer.setContentProvider(new ITreeContentProvider() {
+			public void dispose() {
+			}
+
+			public Object[] getChildren(Object parentElement) {
+				return getStylePreferenceKeys().toArray();
+			}
+
+			public Object[] getElements(Object inputElement) {
+				return getChildren(inputElement);
+			}
+
+			public Object getParent(Object element) {
+				return getStylePreferenceKeys();
+			}
+
+			public boolean hasChildren(Object element) {
+				return false;
+			}
+
+			public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+			}
+		});
+		return stylesViewer;
+	}
+
+	public void dispose() {
+		if (fOverlayStore != null) {
+			fOverlayStore.stop();
+		}
+		super.dispose();
+	}
+
+	protected IPreferenceStore doGetPreferenceStore() {
+		return XMLUIPlugin.getDefault().getPreferenceStore();
+	}
+
+	private TextAttribute getAttributeFor(String namedStyle) {
+		TextAttribute ta = new TextAttribute(fDefaultForeground, fDefaultBackground, SWT.NORMAL);
+
+		if (namedStyle != null && fOverlayStore != null) {
+			// note: "namedStyle" *is* the preference key
+			String prefString = getOverlayStore().getString(namedStyle);
+			String[] stylePrefs = ColorHelper.unpackStylePreferences(prefString);
+			if (stylePrefs != null) {
+				RGB foreground = ColorHelper.toRGB(stylePrefs[0]);
+				RGB background = ColorHelper.toRGB(stylePrefs[1]);
+
+				int fontModifier = SWT.NORMAL;
+
+				if (stylePrefs.length > 2) {
+					boolean on = Boolean.valueOf(stylePrefs[2]).booleanValue();
+					if (on)
+						fontModifier = fontModifier | SWT.BOLD;
+				}
+				if (stylePrefs.length > 3) {
+					boolean on = Boolean.valueOf(stylePrefs[3]).booleanValue();
+					if (on)
+						fontModifier = fontModifier | SWT.ITALIC;
+				}
+				if (stylePrefs.length > 4) {
+					boolean on = Boolean.valueOf(stylePrefs[4]).booleanValue();
+					if (on)
+						fontModifier = fontModifier | TextAttribute.STRIKETHROUGH;
+				}
+				if (stylePrefs.length > 5) {
+					boolean on = Boolean.valueOf(stylePrefs[5]).booleanValue();
+					if (on)
+						fontModifier = fontModifier | TextAttribute.UNDERLINE;
+				}
+
+				ta = new TextAttribute((foreground != null) ? EditorUtility.getColor(foreground) : null, (background != null) ? EditorUtility.getColor(background) : null, fontModifier);
+			}
+		}
+		return ta;
+	}
+
+	private String getExampleText() {
+		return XMLUIMessages.Sample_XML_doc;
+	}
+
+	private String getNamedStyleAtOffset(int offset) {
+		// ensure the offset is clean
+		if (offset >= fDocument.getLength())
+			return getNamedStyleAtOffset(fDocument.getLength() - 1);
+		else if (offset < 0)
+			return getNamedStyleAtOffset(0);
+		IStructuredDocumentRegion documentRegion = fDocument.getFirstStructuredDocumentRegion();
+		while (documentRegion != null && !documentRegion.containsOffset(offset)) {
+			documentRegion = documentRegion.getNext();
+		}
+		if (documentRegion != null) {
+			// find the ITextRegion's Context at this offset
+			ITextRegion interest = documentRegion.getRegionAtCharacterOffset(offset);
+			if (interest == null)
+				return null;
+			if (offset > documentRegion.getTextEndOffset(interest))
+				return null;
+			String regionContext = interest.getType();
+			if (regionContext == null)
+				return null;
+			// find the named style (internal/selectable name) for that
+			// context
+			String namedStyle = (String) fContextToStyleMap.get(regionContext);
+			if (namedStyle != null) {
+				return namedStyle;
+			}
+		}
+		return null;
+	}
+
+	private OverlayPreferenceStore getOverlayStore() {
+		return fOverlayStore;
+	}
+
+	private Collection getStylePreferenceKeys() {
+		if (fStylePreferenceKeys == null) {
+			List styles = new ArrayList();
+			styles.add(IStyleConstantsXML.DOCTYPE_NAME);
+			styles.add(IStyleConstantsXML.DOCTYPE_EXTERNAL_ID);
+			styles.add(IStyleConstantsXML.DOCTYPE_EXTERNAL_ID_PUBREF);
+			styles.add(IStyleConstantsXML.DOCTYPE_EXTERNAL_ID_SYSREF);
+			styles.add(IStyleConstantsXML.CDATA_BORDER);
+			styles.add(IStyleConstantsXML.CDATA_TEXT);
+			styles.add(IStyleConstantsXML.PI_BORDER);
+			styles.add(IStyleConstantsXML.PI_CONTENT);
+			styles.add(IStyleConstantsXML.TAG_BORDER);
+			styles.add(IStyleConstantsXML.TAG_NAME);
+			styles.add(IStyleConstantsXML.TAG_ATTRIBUTE_NAME);
+			styles.add(IStyleConstantsXML.TAG_ATTRIBUTE_EQUALS);
+			styles.add(IStyleConstantsXML.TAG_ATTRIBUTE_VALUE);
+			styles.add(IStyleConstantsXML.COMMENT_BORDER);
+			styles.add(IStyleConstantsXML.COMMENT_TEXT);
+			styles.add(IStyleConstantsXML.DECL_BORDER);
+			styles.add(IStyleConstantsXML.XML_CONTENT);
+			styles.add(IStyleConstantsXML.ENTITY_REFERENCE);
+			fStylePreferenceKeys = styles;
+		}
+		return fStylePreferenceKeys;
+	}
+
+	private KeyListener getTextKeyListener() {
+		return new KeyListener() {
+			public void keyPressed(KeyEvent e) {
+				if (e.widget instanceof StyledText) {
+					int x = ((StyledText) e.widget).getCaretOffset();
+					selectColorAtOffset(x);
+				}
+			}
+
+			public void keyReleased(KeyEvent e) {
+				if (e.widget instanceof StyledText) {
+					int x = ((StyledText) e.widget).getCaretOffset();
+					selectColorAtOffset(x);
+				}
+			}
+		};
+	}
+
+	private MouseListener getTextMouseListener() {
+		return new MouseListener() {
+			public void mouseDoubleClick(MouseEvent e) {
+			}
+
+			public void mouseDown(MouseEvent e) {
+			}
+
+			public void mouseUp(MouseEvent e) {
+				if (e.widget instanceof StyledText) {
+					int x = ((StyledText) e.widget).getCaretOffset();
+					selectColorAtOffset(x);
+				}
+			}
+		};
+	}
+
+	private SelectionListener getTextSelectionListener() {
+		return new SelectionListener() {
+			public void widgetDefaultSelected(SelectionEvent e) {
+				selectColorAtOffset(e.x);
+				if (e.widget instanceof StyledText) {
+					((StyledText) e.widget).setSelection(e.x);
+				}
+			}
+
+			public void widgetSelected(SelectionEvent e) {
+				selectColorAtOffset(e.x);
+				if (e.widget instanceof StyledText) {
+					((StyledText) e.widget).setSelection(e.x);
+				}
+			}
+		};
+	}
+
+	private TraverseListener getTraverseListener() {
+		return new TraverseListener() {
+			/**
+			 * @see org.eclipse.swt.events.TraverseListener#keyTraversed(TraverseEvent)
+			 */
+			public void keyTraversed(TraverseEvent e) {
+				if (e.widget instanceof StyledText) {
+					if ((e.detail == SWT.TRAVERSE_TAB_NEXT) || (e.detail == SWT.TRAVERSE_TAB_PREVIOUS))
+						e.doit = true;
+				}
+			}
+		};
+	}
+
+	public void init(IWorkbench workbench) {
+		setDescription(SSEUIMessages.SyntaxColoring_Description);
+
+		fStyleToDescriptionMap = new HashMap();
+		fContextToStyleMap = new HashMap();
+
+		initStyleToDescriptionMap();
+		initRegionContextToStyleMap();
+
+		fOverlayStore = new OverlayPreferenceStore(getPreferenceStore(), createOverlayStoreKeys());
+		fOverlayStore.load();
+		fOverlayStore.start();
+	}
+
+	private void initRegionContextToStyleMap() {
+		fContextToStyleMap.put(DOMRegionContext.XML_COMMENT_OPEN, IStyleConstantsXML.COMMENT_BORDER);
+		fContextToStyleMap.put(DOMRegionContext.XML_COMMENT_TEXT, IStyleConstantsXML.COMMENT_TEXT);
+		fContextToStyleMap.put(DOMRegionContext.XML_COMMENT_CLOSE, IStyleConstantsXML.COMMENT_BORDER);
+
+		fContextToStyleMap.put(DOMRegionContext.XML_TAG_OPEN, IStyleConstantsXML.TAG_BORDER);
+		fContextToStyleMap.put(DOMRegionContext.XML_END_TAG_OPEN, IStyleConstantsXML.TAG_BORDER);
+		fContextToStyleMap.put(DOMRegionContext.XML_TAG_NAME, IStyleConstantsXML.TAG_NAME);
+		fContextToStyleMap.put(DOMRegionContext.XML_TAG_ATTRIBUTE_NAME, IStyleConstantsXML.TAG_ATTRIBUTE_NAME);
+		fContextToStyleMap.put(DOMRegionContext.XML_TAG_ATTRIBUTE_EQUALS, IStyleConstantsXML.TAG_ATTRIBUTE_EQUALS);
+		fContextToStyleMap.put(DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE, IStyleConstantsXML.TAG_ATTRIBUTE_VALUE);
+		fContextToStyleMap.put(DOMRegionContext.XML_TAG_CLOSE, IStyleConstantsXML.TAG_BORDER);
+		fContextToStyleMap.put(DOMRegionContext.XML_EMPTY_TAG_CLOSE, IStyleConstantsXML.TAG_BORDER);
+
+		fContextToStyleMap.put(DOMRegionContext.XML_DECLARATION_OPEN, IStyleConstantsXML.DECL_BORDER);
+		fContextToStyleMap.put(DOMRegionContext.XML_DECLARATION_CLOSE, IStyleConstantsXML.DECL_BORDER);
+		fContextToStyleMap.put(DOMRegionContext.XML_ELEMENT_DECLARATION, IStyleConstantsXML.DECL_BORDER);
+		fContextToStyleMap.put(DOMRegionContext.XML_ELEMENT_DECL_CLOSE, IStyleConstantsXML.DECL_BORDER);
+
+		fContextToStyleMap.put(DOMRegionContext.XML_CONTENT, IStyleConstantsXML.XML_CONTENT);
+		fContextToStyleMap.put(DOMRegionContext.XML_CDATA_OPEN, IStyleConstantsXML.CDATA_BORDER);
+		fContextToStyleMap.put(DOMRegionContext.XML_CDATA_TEXT, IStyleConstantsXML.CDATA_TEXT);
+		fContextToStyleMap.put(DOMRegionContext.XML_CDATA_CLOSE, IStyleConstantsXML.CDATA_BORDER);
+
+		fContextToStyleMap.put(DOMRegionContext.XML_PI_OPEN, IStyleConstantsXML.PI_BORDER);
+		fContextToStyleMap.put(DOMRegionContext.XML_PI_CONTENT, IStyleConstantsXML.PI_CONTENT);
+		fContextToStyleMap.put(DOMRegionContext.XML_PI_CLOSE, IStyleConstantsXML.PI_BORDER);
+		fContextToStyleMap.put(DOMRegionContext.XML_ELEMENT_DECL_NAME, IStyleConstantsXML.DOCTYPE_NAME);
+		fContextToStyleMap.put(DOMRegionContext.XML_DOCTYPE_DECLARATION, IStyleConstantsXML.TAG_NAME);
+		fContextToStyleMap.put(DOMRegionContext.XML_DOCTYPE_DECLARATION_CLOSE, IStyleConstantsXML.DECL_BORDER);
+
+		fContextToStyleMap.put(DOMRegionContext.XML_DOCTYPE_NAME, IStyleConstantsXML.DOCTYPE_NAME);
+		fContextToStyleMap.put(DOMRegionContext.XML_DOCTYPE_EXTERNAL_ID_PUBLIC, IStyleConstantsXML.DOCTYPE_EXTERNAL_ID);
+		fContextToStyleMap.put(DOMRegionContext.XML_DOCTYPE_EXTERNAL_ID_PUBREF, IStyleConstantsXML.DOCTYPE_EXTERNAL_ID_PUBREF);
+		fContextToStyleMap.put(DOMRegionContext.XML_DOCTYPE_EXTERNAL_ID_SYSTEM, IStyleConstantsXML.DOCTYPE_EXTERNAL_ID);
+		fContextToStyleMap.put(DOMRegionContext.XML_DOCTYPE_EXTERNAL_ID_SYSREF, IStyleConstantsXML.DOCTYPE_EXTERNAL_ID_SYSREF);
+
+		fContextToStyleMap.put(DOMRegionContext.XML_CHAR_REFERENCE, IStyleConstantsXML.ENTITY_REFERENCE);
+		fContextToStyleMap.put(DOMRegionContext.XML_ENTITY_REFERENCE, IStyleConstantsXML.ENTITY_REFERENCE);
+		fContextToStyleMap.put(DOMRegionContext.XML_PE_REFERENCE, IStyleConstantsXML.ENTITY_REFERENCE);
+	}
+
+	private void initStyleToDescriptionMap() {
+		fStyleToDescriptionMap.put(IStyleConstantsXML.CDATA_BORDER, XMLUIMessages.CDATA_Delimiters_UI_);
+		fStyleToDescriptionMap.put(IStyleConstantsXML.CDATA_TEXT, XMLUIMessages.CDATA_Content_UI_);
+		fStyleToDescriptionMap.put(IStyleConstantsXML.PI_BORDER, XMLUIMessages.Processing_Instruction_Del_UI_);
+		fStyleToDescriptionMap.put(IStyleConstantsXML.PI_CONTENT, XMLUIMessages.Processing_Instruction_Con_UI__UI_);
+		fStyleToDescriptionMap.put(IStyleConstantsXML.COMMENT_BORDER, XMLUIMessages.Comment_Delimiters_UI_);
+		fStyleToDescriptionMap.put(IStyleConstantsXML.COMMENT_TEXT, XMLUIMessages.Comment_Content_UI_);
+		fStyleToDescriptionMap.put(IStyleConstantsXML.TAG_BORDER, XMLUIMessages.Tag_Delimiters_UI_);
+		fStyleToDescriptionMap.put(IStyleConstantsXML.TAG_NAME, XMLUIMessages.Tag_Names_UI_);
+		fStyleToDescriptionMap.put(IStyleConstantsXML.TAG_ATTRIBUTE_NAME, XMLUIMessages.Attribute_Names_UI_);
+		fStyleToDescriptionMap.put(IStyleConstantsXML.TAG_ATTRIBUTE_EQUALS, XMLUIMessages.Attribute_Equals_UI_);
+		fStyleToDescriptionMap.put(IStyleConstantsXML.TAG_ATTRIBUTE_VALUE, XMLUIMessages.Attribute_Values_UI_);
+		fStyleToDescriptionMap.put(IStyleConstantsXML.DECL_BORDER, XMLUIMessages.Declaration_Delimiters_UI_);
+		fStyleToDescriptionMap.put(IStyleConstantsXML.XML_CONTENT, XMLUIMessages.Content_UI_);
+		fStyleToDescriptionMap.put(IStyleConstantsXML.DOCTYPE_NAME, XMLUIMessages.DOCTYPE_Name_UI_);
+		fStyleToDescriptionMap.put(IStyleConstantsXML.DOCTYPE_EXTERNAL_ID, XMLUIMessages.DOCTYPE_SYSTEM_PUBLIC_Keyw_UI_);
+		fStyleToDescriptionMap.put(IStyleConstantsXML.DOCTYPE_EXTERNAL_ID_PUBREF, XMLUIMessages.DOCTYPE_Public_Reference_UI_);
+		fStyleToDescriptionMap.put(IStyleConstantsXML.DOCTYPE_EXTERNAL_ID_SYSREF, XMLUIMessages.DOCTYPE_System_Reference_UI_);
+		fStyleToDescriptionMap.put(IStyleConstantsXML.ENTITY_REFERENCE, XMLUIMessages.Entity_Reference_UI_);
+	}
+
+	protected void performDefaults() {
+		super.performDefaults();
+		getOverlayStore().loadDefaults();
+		applyStyles();
+		fStylesViewer.setSelection(StructuredSelection.EMPTY);
+		activate(null);
+		fText.redraw();
+	}
+
+	public boolean performOk() {
+		getOverlayStore().propagate();
+
+		XMLUIPlugin.getDefault().savePluginPreferences();
+		SSEUIPlugin.getDefault().savePluginPreferences();
+		return true;
+	}
+
+	private void selectColorAtOffset(int offset) {
+		String namedStyle = getNamedStyleAtOffset(offset);
+		if (namedStyle != null) {
+			fStylesViewer.setSelection(new StructuredSelection(namedStyle));
+			fStylesViewer.reveal(namedStyle);
+		}
+		else {
+			fStylesViewer.setSelection(StructuredSelection.EMPTY);
+		}
+		activate(namedStyle);
+	}
+
+	/**
+	 * Specifically set the reporting name of a control for accessibility
+	 */
+	private void setAccessible(Control control, String name) {
+		if (control == null)
+			return;
+		final String n = name;
+		control.getAccessible().addAccessibleListener(new AccessibleAdapter() {
+			public void getName(AccessibleEvent e) {
+				if (e.childID == ACC.CHILDID_SELF)
+					e.result = n;
+			}
+		});
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/preferences/XMLTemplatePreferencePage.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/preferences/XMLTemplatePreferencePage.java
new file mode 100644
index 0000000..ed6dea5
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/preferences/XMLTemplatePreferencePage.java
@@ -0,0 +1,169 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.preferences;
+
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.contentassist.ContentAssistant;
+import org.eclipse.jface.text.contentassist.IContentAssistant;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.text.source.SourceViewer;
+import org.eclipse.jface.text.source.SourceViewerConfiguration;
+import org.eclipse.jface.text.templates.ContextTypeRegistry;
+import org.eclipse.jface.text.templates.Template;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.texteditor.templates.TemplatePreferencePage;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.ui.StructuredTextViewerConfiguration;
+import org.eclipse.wst.sse.ui.internal.StructuredTextViewer;
+import org.eclipse.wst.sse.ui.internal.provisional.style.LineStyleProvider;
+import org.eclipse.wst.xml.core.internal.provisional.contenttype.ContentTypeIdForXML;
+import org.eclipse.wst.xml.ui.StructuredTextViewerConfigurationXML;
+import org.eclipse.wst.xml.ui.internal.XMLUIPlugin;
+import org.eclipse.wst.xml.ui.internal.editor.IHelpContextIds;
+
+
+/**
+ * Preference page for XML templates
+ */
+public class XMLTemplatePreferencePage extends TemplatePreferencePage {
+
+	class XMLEditTemplateDialog extends EditTemplateDialog {
+		public XMLEditTemplateDialog(Shell parent, Template template, boolean edit, boolean isNameModifiable, ContextTypeRegistry registry) {
+			super(parent, template, edit, isNameModifiable, registry);
+		}
+
+		protected SourceViewer createViewer(Composite parent) {
+			SourceViewerConfiguration sourceViewerConfiguration = new StructuredTextViewerConfiguration() {
+				StructuredTextViewerConfiguration baseConfiguration = new StructuredTextViewerConfigurationXML();
+
+				public String[] getConfiguredContentTypes(ISourceViewer sourceViewer) {
+					return baseConfiguration.getConfiguredContentTypes(sourceViewer);
+				}
+
+				public LineStyleProvider[] getLineStyleProviders(ISourceViewer sourceViewer, String partitionType) {
+					return baseConfiguration.getLineStyleProviders(sourceViewer, partitionType);
+				}
+
+				public IContentAssistant getContentAssistant(ISourceViewer sourceViewer) {
+					ContentAssistant assistant = new ContentAssistant();
+					assistant.enableAutoActivation(true);
+					assistant.enableAutoInsert(true);
+					assistant.setContentAssistProcessor(getTemplateProcessor(), IDocument.DEFAULT_CONTENT_TYPE);
+					return assistant;
+				}
+			};
+			return doCreateViewer(parent, sourceViewerConfiguration);
+		}
+	}
+
+	public XMLTemplatePreferencePage() {
+		XMLUIPlugin xmlEditorPlugin = XMLUIPlugin.getDefault();
+
+		setPreferenceStore(xmlEditorPlugin.getPreferenceStore());
+		setTemplateStore(xmlEditorPlugin.getTemplateStore());
+		setContextTypeRegistry(xmlEditorPlugin.getTemplateContextRegistry());
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.preference.PreferencePage#createContents(org.eclipse.swt.widgets.Composite)
+	 */
+	protected Control createContents(Composite ancestor) {
+		Control c = super.createContents(ancestor);
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(c, IHelpContextIds.XML_PREFWEBX_TEMPLATES_HELPID);
+		return c;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.ui.texteditor.templates.TemplatePreferencePage#createViewer(org.eclipse.swt.widgets.Composite)
+	 */
+	protected SourceViewer createViewer(Composite parent) {
+		SourceViewerConfiguration sourceViewerConfiguration = new StructuredTextViewerConfiguration() {
+			StructuredTextViewerConfiguration baseConfiguration = new StructuredTextViewerConfigurationXML();
+
+			public String[] getConfiguredContentTypes(ISourceViewer sourceViewer) {
+				return baseConfiguration.getConfiguredContentTypes(sourceViewer);
+			}
+
+			public LineStyleProvider[] getLineStyleProviders(ISourceViewer sourceViewer, String partitionType) {
+				return baseConfiguration.getLineStyleProviders(sourceViewer, partitionType);
+			}
+		};
+		return doCreateViewer(parent, sourceViewerConfiguration);
+	}
+
+	SourceViewer doCreateViewer(Composite parent, SourceViewerConfiguration viewerConfiguration) {
+		SourceViewer viewer = null;
+		String contentTypeID = ContentTypeIdForXML.ContentTypeID_XML;
+		viewer = new StructuredTextViewer(parent, null, null, false, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
+		viewer.getTextWidget().setFont(JFaceResources.getFont("org.eclipse.wst.sse.ui.textfont")); //$NON-NLS-1$
+		IStructuredModel scratchModel = StructuredModelManager.getModelManager().createUnManagedStructuredModelFor(contentTypeID);
+		IDocument document = scratchModel.getStructuredDocument();
+		viewer.configure(viewerConfiguration);
+		viewer.setDocument(document);
+		return viewer;
+	}
+
+	/**
+	 * Creates the edit dialog. Subclasses may override this method to provide
+	 * a custom dialog.
+	 * 
+	 * @param template
+	 *            the template being edited
+	 * @param edit
+	 *            whether the dialog should be editable
+	 * @param isNameModifiable
+	 *            whether the template name may be modified
+	 * @return the created or modified template, or <code>null</code> if the
+	 *         edition failed
+	 * @since 3.1
+	 */
+	protected Template editTemplate(Template template, boolean edit, boolean isNameModifiable) {
+		EditTemplateDialog dialog = new XMLEditTemplateDialog(getShell(), template, edit, isNameModifiable, getContextTypeRegistry());
+		if (dialog.open() == Window.OK) {
+			return dialog.getTemplate();
+		}
+		return null;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.ui.texteditor.templates.TemplatePreferencePage#isShowFormatterSetting()
+	 */
+	protected boolean isShowFormatterSetting() {
+		// template formatting has not been implemented
+		return false;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.preference.IPreferencePage#performOk()
+	 */
+	public boolean performOk() {
+		boolean ok = super.performOk();
+		XMLUIPlugin.getDefault().savePluginPreferences();
+		return ok;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/preferences/XMLTypingPreferencePage.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/preferences/XMLTypingPreferencePage.java
new file mode 100644
index 0000000..8487ab2
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/preferences/XMLTypingPreferencePage.java
@@ -0,0 +1,130 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.preferences;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.wst.sse.ui.internal.preferences.ui.AbstractPreferencePage;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+import org.eclipse.wst.xml.ui.internal.XMLUIPlugin;
+import org.eclipse.wst.xml.ui.internal.editor.IHelpContextIds;
+ 
+public class XMLTypingPreferencePage extends AbstractPreferencePage {
+
+	private Button fCloseComment;
+	private Button fCloseEndTag;
+	private Button fRemoveEndTag;
+	private Button fCloseElement;
+	private Button fCloseStrings;
+	private Button fCloseBrackets;
+
+	protected Control createContents(Composite parent) {
+		Composite composite = super.createComposite(parent, 1);
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, IHelpContextIds.XML_PREFWEBX_FILES_HELPID);
+
+		createStartTagGroup(composite);
+		createEndTagGroup(composite);
+		createAutoComplete(composite);
+		createAutoRemove(composite);
+		
+		setSize(composite);
+		loadPreferences();
+		
+		return composite;
+	}
+	
+	private void createStartTagGroup(Composite parent) {
+		Group group = createGroup(parent, 2);
+
+		group.setText(XMLUIMessages.XMLTyping_Start_Tag);
+
+		fCloseElement = createCheckBox(group, XMLUIMessages.XMLTyping_Complete_Elements);
+		((GridData) fCloseElement.getLayoutData()).horizontalSpan = 2;
+	}
+	
+	private void createEndTagGroup(Composite parent) {
+		Group group = createGroup(parent, 2);
+
+		group.setText(XMLUIMessages.XMLTyping_End_Tag);
+
+		fCloseEndTag = createCheckBox(group, XMLUIMessages.XMLTyping_Complete_End_Tags);
+		((GridData) fCloseEndTag.getLayoutData()).horizontalSpan = 2;
+	}
+	
+	private void createAutoComplete(Composite parent) {
+		Group group = createGroup(parent, 2);
+		
+		group.setText(XMLUIMessages.XMLTyping_Auto_Complete);
+		
+		fCloseComment = createCheckBox(group, XMLUIMessages.XMLTyping_Complete_Comments);
+		((GridData) fCloseComment.getLayoutData()).horizontalSpan = 2;
+
+		fCloseStrings = createCheckBox(group, XMLUIMessages.XMLTyping_Close_Strings);
+		((GridData) fCloseStrings.getLayoutData()).horizontalSpan = 2;
+
+		fCloseBrackets = createCheckBox(group, XMLUIMessages.XMLTyping_Close_Brackets);
+		((GridData) fCloseBrackets.getLayoutData()).horizontalSpan = 2;
+	}
+	
+	private void createAutoRemove(Composite parent) {
+		Group group = createGroup(parent, 2);
+		
+		group.setText(XMLUIMessages.XMLTyping_Auto_Remove);
+		
+		fRemoveEndTag = createCheckBox(group, XMLUIMessages.XMLTyping_Remove_End_Tags);
+		((GridData) fRemoveEndTag.getLayoutData()).horizontalSpan = 2;
+	}
+	
+	public boolean performOk() {
+		boolean result = super.performOk();
+		
+		XMLUIPlugin.getDefault().savePluginPreferences();
+		
+		return result;
+	}
+	
+	protected void initializeValues() {
+		initCheckbox(fCloseComment, XMLUIPreferenceNames.TYPING_COMPLETE_COMMENTS);
+		initCheckbox(fCloseEndTag, XMLUIPreferenceNames.TYPING_COMPLETE_END_TAGS);
+		initCheckbox(fCloseElement, XMLUIPreferenceNames.TYPING_COMPLETE_ELEMENTS);
+		initCheckbox(fRemoveEndTag, XMLUIPreferenceNames.TYPING_REMOVE_END_TAGS);
+		initCheckbox(fCloseStrings, XMLUIPreferenceNames.TYPING_CLOSE_STRINGS);
+		initCheckbox(fCloseBrackets, XMLUIPreferenceNames.TYPING_CLOSE_BRACKETS);
+	}
+	
+	protected void performDefaults() {
+		defaultCheckbox(fCloseComment, XMLUIPreferenceNames.TYPING_COMPLETE_COMMENTS);
+		defaultCheckbox(fCloseEndTag, XMLUIPreferenceNames.TYPING_COMPLETE_END_TAGS);
+		defaultCheckbox(fCloseElement, XMLUIPreferenceNames.TYPING_COMPLETE_ELEMENTS);
+		defaultCheckbox(fRemoveEndTag, XMLUIPreferenceNames.TYPING_REMOVE_END_TAGS);
+		defaultCheckbox(fCloseStrings, XMLUIPreferenceNames.TYPING_CLOSE_STRINGS);
+		defaultCheckbox(fCloseBrackets, XMLUIPreferenceNames.TYPING_CLOSE_BRACKETS);
+	}
+	
+	protected void storeValues() {
+		getPreferenceStore().setValue(XMLUIPreferenceNames.TYPING_COMPLETE_COMMENTS, (fCloseComment != null) ? fCloseComment.getSelection() : false);
+		getPreferenceStore().setValue(XMLUIPreferenceNames.TYPING_COMPLETE_END_TAGS, (fCloseEndTag != null) ? fCloseEndTag.getSelection() : false);
+		getPreferenceStore().setValue(XMLUIPreferenceNames.TYPING_COMPLETE_ELEMENTS, (fCloseElement != null) ? fCloseElement.getSelection() : false);
+		getPreferenceStore().setValue(XMLUIPreferenceNames.TYPING_REMOVE_END_TAGS, (fRemoveEndTag != null) ? fRemoveEndTag.getSelection() : false);
+		getPreferenceStore().setValue(XMLUIPreferenceNames.TYPING_CLOSE_STRINGS, (fCloseStrings != null) ? fCloseStrings.getSelection() : false);
+		getPreferenceStore().setValue(XMLUIPreferenceNames.TYPING_CLOSE_BRACKETS, (fCloseBrackets != null) ? fCloseBrackets.getSelection() : false);
+	}
+	
+	protected IPreferenceStore doGetPreferenceStore() {
+		return XMLUIPlugin.getDefault().getPreferenceStore();
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/preferences/XMLUIPreferenceInitializer.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/preferences/XMLUIPreferenceInitializer.java
new file mode 100644
index 0000000..7632e6b
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/preferences/XMLUIPreferenceInitializer.java
@@ -0,0 +1,127 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 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
+ *     Benjamin Muskalla, b.muskalla@gmx.net - [158660] character entities should have their own syntax highlighting preference 
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.preferences;
+
+import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.resource.ColorRegistry;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.wst.sse.ui.internal.preferences.ui.ColorHelper;
+import org.eclipse.wst.xml.ui.internal.XMLUIPlugin;
+import org.eclipse.wst.xml.ui.internal.style.IStyleConstantsXML;
+
+/**
+ * Sets default values for XML UI preferences
+ */
+public class XMLUIPreferenceInitializer extends AbstractPreferenceInitializer {
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer#initializeDefaultPreferences()
+	 */
+	public void initializeDefaultPreferences() {
+		IPreferenceStore store = XMLUIPlugin.getDefault().getPreferenceStore();
+		ColorRegistry registry = PlatformUI.getWorkbench().getThemeManager().getCurrentTheme().getColorRegistry();
+
+		store.setDefault(XMLUIPreferenceNames.AUTO_PROPOSE, true);
+		store.setDefault(XMLUIPreferenceNames.AUTO_PROPOSE_CODE, "<=:"); //$NON-NLS-1$
+		// https://bugs.eclipse.org/bugs/show_bug.cgi?id=140946
+		store.setDefault(XMLUIPreferenceNames.SUGGESTION_STRATEGY, XMLUIPreferenceNames.SUGGESTION_STRATEGY_VALUE_STRICT);
+		store.setDefault(XMLUIPreferenceNames.USE_INFERRED_GRAMMAR, true);
+
+		// XML Style Preferences
+		String NOBACKGROUNDBOLD = " | null | false"; //$NON-NLS-1$
+		String JUSTITALIC = " | null | false | true"; //$NON-NLS-1$
+		String styleValue = ColorHelper.findRGBString(registry, IStyleConstantsXML.TAG_ATTRIBUTE_NAME, 127, 0, 127) + NOBACKGROUNDBOLD;
+		store.setDefault(IStyleConstantsXML.TAG_ATTRIBUTE_NAME, styleValue);
+
+		styleValue = ColorHelper.findRGBString(registry, IStyleConstantsXML.TAG_ATTRIBUTE_VALUE, 42, 0, 255) + JUSTITALIC;
+		store.setDefault(IStyleConstantsXML.TAG_ATTRIBUTE_VALUE, styleValue);
+
+		styleValue = "null" + NOBACKGROUNDBOLD; //$NON-NLS-1$
+		store.setDefault(IStyleConstantsXML.TAG_ATTRIBUTE_EQUALS, styleValue); // specified
+		// value is black; leaving as widget default
+
+		styleValue = ColorHelper.findRGBString(registry, IStyleConstantsXML.COMMENT_BORDER, 63, 95, 191) + NOBACKGROUNDBOLD;
+		store.setDefault(IStyleConstantsXML.COMMENT_BORDER, styleValue);
+		styleValue = ColorHelper.findRGBString(registry, IStyleConstantsXML.COMMENT_TEXT, 63, 95, 191) + NOBACKGROUNDBOLD;
+		store.setDefault(IStyleConstantsXML.COMMENT_TEXT, styleValue);
+
+		styleValue = ColorHelper.findRGBString(registry, IStyleConstantsXML.DECL_BORDER, 0, 128, 128) + NOBACKGROUNDBOLD;
+		store.setDefault(IStyleConstantsXML.DECL_BORDER, styleValue);
+
+		styleValue = ColorHelper.findRGBString(registry, IStyleConstantsXML.DOCTYPE_NAME, 0, 0, 128) + NOBACKGROUNDBOLD;
+		store.setDefault(IStyleConstantsXML.DOCTYPE_NAME, styleValue);
+		styleValue = ColorHelper.findRGBString(registry, IStyleConstantsXML.DOCTYPE_EXTERNAL_ID_PUBREF, 0, 0, 128) + NOBACKGROUNDBOLD;
+		store.setDefault(IStyleConstantsXML.DOCTYPE_EXTERNAL_ID_PUBREF, styleValue);
+
+		styleValue = ColorHelper.findRGBString(registry, IStyleConstantsXML.DOCTYPE_EXTERNAL_ID, 128, 128, 128) + NOBACKGROUNDBOLD;
+		store.setDefault(IStyleConstantsXML.DOCTYPE_EXTERNAL_ID, styleValue);
+
+		styleValue = ColorHelper.findRGBString(registry, IStyleConstantsXML.DOCTYPE_EXTERNAL_ID_SYSREF, 63, 127, 95) + NOBACKGROUNDBOLD;
+		store.setDefault(IStyleConstantsXML.DOCTYPE_EXTERNAL_ID_SYSREF, styleValue);
+
+		styleValue = "null" + NOBACKGROUNDBOLD; //$NON-NLS-1$
+		store.setDefault(IStyleConstantsXML.XML_CONTENT, styleValue); // specified
+		// value is black; leaving as widget default
+
+		styleValue = ColorHelper.findRGBString(registry, IStyleConstantsXML.TAG_BORDER, 0, 128, 128) + NOBACKGROUNDBOLD;
+		store.setDefault(IStyleConstantsXML.TAG_BORDER, styleValue);
+
+		styleValue = ColorHelper.findRGBString(registry, IStyleConstantsXML.TAG_NAME, 63, 127, 127) + NOBACKGROUNDBOLD;
+		store.setDefault(IStyleConstantsXML.TAG_NAME, styleValue);
+
+		styleValue = ColorHelper.findRGBString(registry, IStyleConstantsXML.PI_BORDER, 0, 128, 128) + NOBACKGROUNDBOLD;
+		store.setDefault(IStyleConstantsXML.PI_BORDER, styleValue);
+
+		styleValue = "null" + NOBACKGROUNDBOLD; //$NON-NLS-1$
+		store.setDefault(IStyleConstantsXML.PI_CONTENT, styleValue); // specified
+		// value is black; leaving as widget default
+
+		styleValue = ColorHelper.findRGBString(registry, IStyleConstantsXML.CDATA_BORDER, 0, 128, 128) + NOBACKGROUNDBOLD;
+		store.setDefault(IStyleConstantsXML.CDATA_BORDER, styleValue);
+
+		styleValue = ColorHelper.findRGBString(registry, IStyleConstantsXML.CDATA_TEXT, 0, 0, 0) + NOBACKGROUNDBOLD;
+		store.setDefault(IStyleConstantsXML.CDATA_TEXT, styleValue);
+
+		styleValue = ColorHelper.findRGBString(registry, IStyleConstantsXML.ENTITY_REFERENCE, 42, 0, 255) + NOBACKGROUNDBOLD;
+		store.setDefault(IStyleConstantsXML.ENTITY_REFERENCE, styleValue);
+		
+		// set default new xml file template to use in new file wizard
+		/*
+		 * Need to find template name that goes with default template id (name
+		 * may change for different language)
+		 */
+		store.setDefault(XMLUIPreferenceNames.NEW_FILE_TEMPLATE_ID, "org.eclipse.wst.xml.ui.internal.templates.xmldeclaration"); //$NON-NLS-1$
+		
+		// Defaults for the Typing preference page
+		store.setDefault(XMLUIPreferenceNames.TYPING_COMPLETE_COMMENTS, true);
+		store.setDefault(XMLUIPreferenceNames.TYPING_COMPLETE_END_TAGS, true);
+		store.setDefault(XMLUIPreferenceNames.TYPING_COMPLETE_ELEMENTS, true);
+		store.setDefault(XMLUIPreferenceNames.TYPING_REMOVE_END_TAGS, true);
+		store.setDefault(XMLUIPreferenceNames.TYPING_CLOSE_STRINGS, true);
+		store.setDefault(XMLUIPreferenceNames.TYPING_CLOSE_BRACKETS, true);
+		
+		// Defaults for Content Assist preference page
+		store.setDefault(XMLUIPreferenceNames.CONTENT_ASSIST_DO_NOT_DISPLAY_ON_DEFAULT_PAGE, "");
+		store.setDefault(XMLUIPreferenceNames.CONTENT_ASSIST_DO_NOT_DISPLAY_ON_OWN_PAGE, "");
+		store.setDefault(XMLUIPreferenceNames.CONTENT_ASSIST_DEFAULT_PAGE_SORT_ORDER,
+				"org.eclipse.wst.xml.ui.proposalCategory.xmlTags\0" +
+				"org.eclipse.wst.xml.ui.proposalCategory.xmlTemplates");
+		store.setDefault(XMLUIPreferenceNames.CONTENT_ASSIST_OWN_PAGE_SORT_ORDER,
+				"org.eclipse.wst.xml.ui.proposalCategory.xmlTemplates\0"+ 
+				"org.eclipse.wst.xml.ui.proposalCategory.xmlTags");
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/preferences/XMLUIPreferenceNames.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/preferences/XMLUIPreferenceNames.java
new file mode 100644
index 0000000..f537341
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/preferences/XMLUIPreferenceNames.java
@@ -0,0 +1,206 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 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
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.preferences;
+
+/**
+ * Preference keys for XML UI
+ */
+public class XMLUIPreferenceNames {
+
+	public final static String SUGGESTION_STRATEGY_VALUE_LAX = "Lax"; //$NON-NLS-1$
+	public final static String SUGGESTION_STRATEGY_VALUE_STRICT = "Strict"; //$NON-NLS-1$
+	/**
+	 * A named preference that controls if code assist gets auto activated.
+	 * <p>
+	 * Value is of type <code>Boolean</code>.
+	 * </p>
+	 */
+	public static final String AUTO_PROPOSE = getAutoProposeKey();
+
+	private static String getAutoProposeKey() {
+		return "autoPropose";//$NON-NLS-1$
+	}
+
+	/**
+	 * A named preference that holds the characters that auto activate code
+	 * assist.
+	 * <p>
+	 * Value is of type <code>String</code>. All characters that trigger
+	 * auto code assist.
+	 * </p>
+	 */
+	public static final String AUTO_PROPOSE_CODE = getAutoProposeCodeKey();
+
+	private static String getAutoProposeCodeKey() {
+		return "autoProposeCode";//$NON-NLS-1$
+	}
+
+	/**
+	 * The key to store customized templates.
+	 * <p>
+	 * Value is of type <code>String</code>.
+	 * </p>
+	 */
+	public static final String TEMPLATES_KEY = getTemplatesKey();
+
+	private static String getTemplatesKey() {
+		return "org.eclipse.wst.sse.ui.custom_templates"; //$NON-NLS-1$
+	}
+
+	/**
+	 * A named preference that controls whether or grammar should be inferred
+	 * or not.
+	 * <p>
+	 * Value is of type <code>Boolean</code>.
+	 * </p>
+	 */
+	public static final String USE_INFERRED_GRAMMAR = getUseInferredGrammarKey();
+
+	public static class OUTLINE_BEHAVIOR {
+		public static final String ELEMENT_NODE = "outline-behavior.element-node"; //$NON-NLS-1$
+		public static final String ATTRIBUTE_NODE = "outline-behavior.attribute-node"; //$NON-NLS-1$
+		public static final String TEXT_NODE = "outline-behavior.text-node"; //$NON-NLS-1$
+		public static final String CDATA_SECTION_NODE = "outline-behavior.cdata-section-node"; //$NON-NLS-1$
+		public static final String ENTITY_REFERENCE_NODE = "outline-behavior.entity-reference-node"; //$NON-NLS-1$
+		public static final String ENTITY_NODE = "outline-behavior.entity-node"; //$NON-NLS-1$
+		public static final String PROCESSING_INSTRUCTION_NODE = "outline-behavior.instruction-node"; //$NON-NLS-1$
+		public static final String COMMENT_NODE = "outline-behavior.comment-node"; //$NON-NLS-1$
+		public static final String DOCUMENT_NODE = "outline-behavior.document-node"; //$NON-NLS-1$
+		public static final String DOCUMENT_TYPE_NODE = "outline-behavior.document-type-node"; //$NON-NLS-1$
+		public static final String DOCUMENT_FRAGMENT_NODE = "outline-behavior.document-fragment-node"; //$NON-NLS-1$
+		public static final String NOTATION_NODE = "outline-behavior.notation-node"; //$NON-NLS-1$
+	}
+	
+	private static String getUseInferredGrammarKey() {
+		return "useInferredGrammar"; //$NON-NLS-1$
+	}
+
+	/**
+	 * A named preference that holds the characters that auto activate code
+	 * assist.
+	 * <p>
+	 * Value is of type <code>String</code>. All characters that trigger
+	 * auto code assist.
+	 * </p>
+	 */
+	public static final String SUGGESTION_STRATEGY = getSuggestionStrategeyKey();
+
+	private static String getSuggestionStrategeyKey() {
+		return "suggestionStrategy";//$NON-NLS-1$
+	}
+
+	/**
+	 * The key to store the last template name used in new DTD file wizard.
+	 * Template name is stored instead of template id because user-created
+	 * templates do not have template ids.
+	 * <p>
+	 * Value is of type <code>String</code>.
+	 * </p>
+	 */
+	public static final String NEW_FILE_TEMPLATE_NAME = "newFileTemplateName"; //$NON-NLS-1$
+
+	/**
+	 * The initial template ID to be used in the new XML file wizard. In the absence
+	 * of {@link NEW_FILE_TEMPLATE_NAME}, this ID is used to find a template name
+	 */
+	public static final String NEW_FILE_TEMPLATE_ID = "newFileTemplateId"; //$NON-NLS-1$
+
+	/**
+	 * The key to store the option for auto-completing comments while
+	 * typing.
+	 * <p>
+	 * Value is of type <code>boolean</code>.
+	 * </p>
+	 */
+	public static final String TYPING_COMPLETE_COMMENTS = "completeComments"; //$NON-NLS-1$
+	
+	/**
+	 * The key to store the option for auto-completing end-tags after entering
+	 * <code>&lt;/</code>
+	 * <p>
+	 * Value is of type <code>boolean</code>.
+	 * </p>
+	 */
+	public static final String TYPING_COMPLETE_END_TAGS = "completeEndTags"; //$NON-NLS-1$
+	
+	/**
+	 * The key to store the option for auto-completing the element after entering
+	 * <code>&gt;</code>
+	 * <p>
+	 * Value is of type <code>boolean</code>.
+	 * </p>
+	 */
+	public static final String TYPING_COMPLETE_ELEMENTS = "completeElements"; //$NON-NLS-1$
+	
+	/**
+	 * The key to store the option for removing an end-tag if the start tag is
+	 * converted to an empty-tag.
+	 * <p>
+	 * Value is of type <code>boolean</code>.
+	 * </p>
+	 */
+	public static final String TYPING_REMOVE_END_TAGS = "removeEndTags"; //$NON-NLS-1$
+
+	/**
+	 * The key to store the option for auto-completing strings (" and ') while
+	 * typing.
+	 * <p>
+	 * Value is of type <code>boolean</code>.
+	 * </p>
+	 */
+	public static final String TYPING_CLOSE_STRINGS = "closeStrings"; //$NON-NLS-1$
+
+	/**
+	 * The key to store the option for auto-completing brackets ([ and () while
+	 * typing.
+	 * <p>
+	 * Value is of type <code>boolean</code>.
+	 * </p>
+	 */
+	public static final String TYPING_CLOSE_BRACKETS = "closeBrackets"; //$NON-NLS-1$
+	
+	/**
+	 * <p>preference key used for saving which categories should not display on the default page</p>
+	 * 
+	 * <p>Value is of type {@link String} consisting of
+	 * <tt>org.eclipse.wst.sse.ui.completionProposal/proposalCategory/@id</tt>s separated by the null
+	 * character (<tt>\0</tt>), ordered is ignored</p>
+	 */
+	public static final String CONTENT_ASSIST_DO_NOT_DISPLAY_ON_DEFAULT_PAGE = "xml_content_assist_display_on_default_page"; //$NON-NLS-1$
+	
+	/**
+	 * <p>preference key used for saving which categories should not display on their own page</p>
+	 * 
+	 * <p>Value is of type {@link String} consisting of
+	 * <tt>org.eclipse.wst.sse.ui.completionProposal/proposalCategory/@id</tt>s separated by the null
+	 * character (<tt>\0</tt>), order is ignored</p>
+	 */
+	public static final String CONTENT_ASSIST_DO_NOT_DISPLAY_ON_OWN_PAGE = "xml_content_assist_display_on_own_page"; //$NON-NLS-1$
+	
+	/**
+	 * <p>preference key for saving the sort order of the categories when displaying them on their own page</p>
+	 * 
+	 * <p>Value is of type {@link String} consisting of
+	 * <tt>org.eclipse.wst.sse.ui.completionProposal/proposalCategory/@id</tt>s separated by the null
+	 * character (<tt>\0</tt>) in the desired sort order.</p>
+	 */
+	public static final String CONTENT_ASSIST_OWN_PAGE_SORT_ORDER= "xml_content_assist_own_page_sort_order"; //$NON-NLS-1$
+	
+	/**
+	 * <p>preference key for saving the sort order of the categories when displaying them on the default page</p>
+	 * 
+	 * <p>Value is of type {@link String} consisting of
+	 * <tt>org.eclipse.wst.sse.ui.completionProposal/proposalCategory/@id</tt>s separated by the null
+	 * character (<tt>\0</tt>) in the desired sort order.</p>
+	 */
+	public static final String CONTENT_ASSIST_DEFAULT_PAGE_SORT_ORDER= "xml_content_assist_default_page_sort_order"; //$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/preferences/XMLValidatorPreferencePage.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/preferences/XMLValidatorPreferencePage.java
new file mode 100644
index 0000000..155bdaa
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/preferences/XMLValidatorPreferencePage.java
@@ -0,0 +1,518 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     David Carver - STAR - [205989] - [validation] validate XML after XInclude resolution
+ *******************************************************************************/
+
+package org.eclipse.wst.xml.ui.internal.preferences;
+
+
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.jface.dialogs.ControlEnableState;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.wst.sse.ui.internal.preferences.ui.AbstractPreferencePage;
+import org.eclipse.wst.xml.core.internal.XMLCorePlugin;
+import org.eclipse.wst.xml.core.internal.preferences.XMLCorePreferenceNames;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+import org.eclipse.wst.xml.ui.internal.editor.IHelpContextIds;
+
+
+public class XMLValidatorPreferencePage extends AbstractPreferencePage {
+  private Combo fIndicateNoGrammar;
+  
+  private Button fHonourAllSchemaLocations;
+
+  private Button fUseXinclude;
+  
+  private Button fExtendedMarkupValidation;
+  
+  private Combo fEmptyElementTag;
+  
+  private Combo fEndTagWithAttributes;
+  
+  private Combo fInvalidWhitespaceBeforeTagname;
+  
+  private Combo fMissingClosingBracket;
+  
+  private Combo fMissingClosingQuote;
+  
+  private Combo fMissingEndTag;
+  
+  private Combo fMissingStartTag;
+  
+  private Combo fMissingQuotes;
+  
+  private Combo fInvalidNamespaceInPI;
+  
+  private Combo fMissingTagName;
+  
+  private Combo fInvalidWhitespaceAtStart;
+
+  private Group fMarkupValidationGroup;
+  private ControlEnableState fMarkupState;
+ 
+  private static final String[] SEVERITIES = {XMLUIMessages.Indicate_no_grammar_specified_severities_error, XMLUIMessages.Indicate_no_grammar_specified_severities_warning, XMLUIMessages.Indicate_no_grammar_specified_severities_ignore};
+  private static final String[] MARKUP_SEVERITIES = {XMLUIMessages.Severity_error, XMLUIMessages.Severity_warning, XMLUIMessages.Severity_ignore};
+
+  protected Control createContents(Composite parent) {
+    Composite composite = (Composite)super.createContents(parent);
+    PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, IHelpContextIds.XML_PREFWEBX_VALIDATOR_HELPID);
+    createContentsForValidatingGroup(composite);
+    createContentsForMarkupValidationGroup(composite);
+    setSize(composite);
+    loadPreferences();
+
+    return composite;
+  }
+
+  protected void createContentsForValidatingGroup(Composite parent) {
+    Group validatingGroup = createGroup(parent, 2);
+    ((GridLayout)validatingGroup.getLayout()).makeColumnsEqualWidth = false;
+    validatingGroup.setText(XMLUIMessages.Validating_files);
+
+    if (fIndicateNoGrammar == null) {
+      createLabel(validatingGroup, XMLUIMessages.Indicate_no_grammar_specified);
+      fIndicateNoGrammar = createCombo(validatingGroup, SEVERITIES);
+    }
+    if (fUseXinclude == null) {
+      fUseXinclude = createCheckBox(validatingGroup, XMLUIMessages.Use_XInclude);
+      ((GridData)fUseXinclude.getLayoutData()).horizontalSpan = 2;
+    }
+    if (fHonourAllSchemaLocations == null) {
+      fHonourAllSchemaLocations = createCheckBox(validatingGroup, XMLUIMessages.Honour_all_schema_locations);
+      ((GridData)fHonourAllSchemaLocations.getLayoutData()).horizontalSpan = 2;
+    }
+  }
+  private void handleMarkupSeveritySelection(boolean selection){
+	  if (selection) {
+		  fMarkupState.restore();
+	  }
+	  else {
+		  fMarkupState = ControlEnableState.disable(fMarkupValidationGroup);
+	  }
+  }
+
+  protected void createContentsForMarkupValidationGroup(Composite parent) {
+	   
+	    if (fExtendedMarkupValidation == null) {
+		    fExtendedMarkupValidation = createCheckBox(parent, XMLUIMessages.MarkupValidation_files);
+		    ((GridData)fExtendedMarkupValidation.getLayoutData()).horizontalSpan = 2;
+		    fExtendedMarkupValidation.addSelectionListener(new SelectionAdapter() {
+				public void widgetSelected(SelectionEvent e) {
+					handleMarkupSeveritySelection(fExtendedMarkupValidation.getSelection());
+				}
+			});
+		}
+	    fMarkupValidationGroup = createGroup(parent, 3);
+	    ((GridLayout)fMarkupValidationGroup.getLayout()).makeColumnsEqualWidth = false;
+	    fMarkupValidationGroup.setText(XMLUIMessages.MarkupValidation_files_label);
+
+	    if (fMissingStartTag == null) {
+	        fMissingStartTag = createMarkupCombo(fMarkupValidationGroup, XMLUIMessages.Missing_start_tag, MARKUP_SEVERITIES);
+	    }
+	    if (fMissingEndTag == null) {
+	        fMissingEndTag = createMarkupCombo(fMarkupValidationGroup, XMLUIMessages.Missing_end_tag, MARKUP_SEVERITIES);
+	    }
+	    if (fMissingTagName == null) {
+	        fMissingTagName = createMarkupCombo(fMarkupValidationGroup, XMLUIMessages.Tag_name_missing, MARKUP_SEVERITIES);
+	    }
+	    if (fMissingQuotes == null) {
+	        fMissingQuotes = createMarkupCombo(fMarkupValidationGroup, XMLUIMessages.Missing_quotes, MARKUP_SEVERITIES);
+	    }
+	    if (fMissingClosingBracket == null) {
+	        fMissingClosingBracket = createMarkupCombo(fMarkupValidationGroup, XMLUIMessages.Missing_closing_bracket, MARKUP_SEVERITIES);
+	    }
+	    if (fMissingClosingQuote == null) {
+	        fMissingClosingQuote = createMarkupCombo(fMarkupValidationGroup, XMLUIMessages.Missing_closing_quote, MARKUP_SEVERITIES);
+	    }
+	    if (fEmptyElementTag == null) {
+	        fEmptyElementTag = createMarkupCombo(fMarkupValidationGroup, XMLUIMessages.Empty_element_tag, MARKUP_SEVERITIES);
+	    }
+	    if (fEndTagWithAttributes == null) {
+	        fEndTagWithAttributes = createMarkupCombo(fMarkupValidationGroup, XMLUIMessages.End_tag_with_attributes, MARKUP_SEVERITIES);
+	    }
+	    if (fInvalidWhitespaceBeforeTagname == null) {
+	        fInvalidWhitespaceBeforeTagname = createMarkupCombo(fMarkupValidationGroup, XMLUIMessages.Invalid_whitespace_before_tagname, MARKUP_SEVERITIES);
+	    }
+	    if (fInvalidNamespaceInPI == null) {
+	        fInvalidNamespaceInPI = createMarkupCombo(fMarkupValidationGroup, XMLUIMessages.Namespace_in_pi_target, MARKUP_SEVERITIES);
+	    }
+	    if (fInvalidWhitespaceAtStart == null) {
+	        fInvalidWhitespaceAtStart = createMarkupCombo(fMarkupValidationGroup, XMLUIMessages.Whitespace_at_start, MARKUP_SEVERITIES);
+	    }
+
+  }
+
+  /**
+   * @param parent 
+   * @return
+   */
+  private Combo createCombo(Composite parent, String[] items) {
+    Combo combo = new Combo(parent, SWT.DROP_DOWN | SWT.READ_ONLY);
+    combo.setItems(items);
+
+    //GridData
+    GridData data = new GridData(SWT.FILL, SWT.CENTER, true, true);
+    combo.setLayoutData(data);
+
+    return combo;
+  }
+
+  private Combo createMarkupCombo(Composite parent, String text, String[] items) {
+	  Label label = new Label(parent, SWT.LEFT);
+	  GridData gd = new GridData(GridData.FILL, GridData.CENTER, true, false, 2, 1);
+		label.setFont(JFaceResources.getDialogFont());
+		label.setText(text);
+		label.setLayoutData(gd);
+
+	  Combo combo = new Combo(parent, SWT.DROP_DOWN | SWT.READ_ONLY);
+	    combo.setItems(items);
+
+	    //GridData
+	   // GridData data = new GridData(SWT.FILL, SWT.CENTER, false, true);
+	    combo.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
+
+	    return combo;
+  }
+ 
+  protected void initializeValues() {
+    initializeValuesForValidatingGroup();
+    initializeValuesForMarkupValidationGroup();
+  }
+
+  protected void initializeValuesForValidatingGroup() {
+    Preferences modelPreferences = getModelPreferences();
+    int indicateNoGrammarButtonSelected = modelPreferences.getInt(XMLCorePreferenceNames.INDICATE_NO_GRAMMAR);
+    boolean useXIncludeButtonSelected = modelPreferences.getBoolean(XMLCorePreferenceNames.USE_XINCLUDE);
+
+    if (fIndicateNoGrammar != null) {
+      fIndicateNoGrammar.select(2 - indicateNoGrammarButtonSelected);
+      fIndicateNoGrammar.setText(SEVERITIES[2 - indicateNoGrammarButtonSelected]);
+    }
+    if (fUseXinclude != null) {
+      fUseXinclude.setSelection(useXIncludeButtonSelected);
+    }
+
+    boolean honourAllSelected = modelPreferences.getBoolean(XMLCorePreferenceNames.HONOUR_ALL_SCHEMA_LOCATIONS);
+    if (fHonourAllSchemaLocations != null) {
+      fHonourAllSchemaLocations.setSelection(honourAllSelected);
+    }
+  }
+  
+  protected void initializeValuesForMarkupValidationGroup() {
+	    Preferences modelPreferences = getModelPreferences();
+	    boolean useExtendedMarkupValidation = modelPreferences.getBoolean(XMLCorePreferenceNames.MARKUP_VALIDATION);
+
+	    
+	    if (fExtendedMarkupValidation != null) {
+	    	fExtendedMarkupValidation.setSelection(useExtendedMarkupValidation);
+	    }
+	    int emptyElementTag = modelPreferences.getInt(XMLCorePreferenceNames.ATTRIBUTE_HAS_NO_VALUE);
+	    
+	    if (fEmptyElementTag != null) {
+	    	fEmptyElementTag.select(2 - emptyElementTag);
+	    	fEmptyElementTag.setText(MARKUP_SEVERITIES[2 - emptyElementTag]);
+		}
+	    
+	    int endTagWithAttributes  = modelPreferences.getInt(XMLCorePreferenceNames.END_TAG_WITH_ATTRIBUTES);
+	    
+	    if (fEndTagWithAttributes != null) {
+	    	fEndTagWithAttributes.select(2 - endTagWithAttributes);
+	    	fEndTagWithAttributes.setText(MARKUP_SEVERITIES[2 - endTagWithAttributes]);
+		}
+	    
+	    int invalidWhitespaceBeforeTagname  = modelPreferences.getInt(XMLCorePreferenceNames.WHITESPACE_BEFORE_TAGNAME);
+	    
+	    if (fInvalidWhitespaceBeforeTagname != null) {
+	    	fInvalidWhitespaceBeforeTagname.select(2 - invalidWhitespaceBeforeTagname);
+	    	fInvalidWhitespaceBeforeTagname.setText(MARKUP_SEVERITIES[2 - invalidWhitespaceBeforeTagname]);
+		}
+	    
+	    int missingClosingBracket  = modelPreferences.getInt(XMLCorePreferenceNames.MISSING_CLOSING_BRACKET);
+	    
+	    if (fMissingClosingBracket != null) {
+	    	fMissingClosingBracket.select(2 - missingClosingBracket);
+	    	fMissingClosingBracket.setText(MARKUP_SEVERITIES[2 - missingClosingBracket]);
+		}
+	    
+	    int missingClosingQuote  = modelPreferences.getInt(XMLCorePreferenceNames.MISSING_CLOSING_QUOTE);
+	    
+	    if (fMissingClosingQuote != null) {
+	    	fMissingClosingQuote.select(2 - missingClosingQuote);
+	    	fMissingClosingQuote.setText(MARKUP_SEVERITIES[2 - missingClosingQuote]);
+		}
+	    
+	    int missingEndTag  = modelPreferences.getInt(XMLCorePreferenceNames.MISSING_END_TAG);
+	    
+	    if (fMissingEndTag != null) {
+	    	fMissingEndTag.select(2 - missingEndTag);
+	    	fMissingEndTag.setText(MARKUP_SEVERITIES[2 - missingEndTag]);
+		}
+	    
+	    int missingStartTag  = modelPreferences.getInt(XMLCorePreferenceNames.MISSING_START_TAG);
+	    
+	    if (fMissingStartTag != null) {
+	    	fMissingStartTag.select(2 - missingStartTag);
+	    	fMissingStartTag.setText(MARKUP_SEVERITIES[2 - missingStartTag]);
+		}
+	    
+	    int missingQuotes  = modelPreferences.getInt(XMLCorePreferenceNames.MISSING_QUOTES);
+	    
+	    if (fMissingQuotes != null) {
+	    	fMissingQuotes.select(2 - missingQuotes);
+	    	fMissingQuotes.setText(MARKUP_SEVERITIES[2 - missingQuotes]);
+		}
+	    
+	    int invalidNamespaceInPI  = modelPreferences.getInt(XMLCorePreferenceNames.NAMESPACE_IN_PI_TARGET);
+	    
+	    if (fInvalidNamespaceInPI != null) {
+	    	fInvalidNamespaceInPI.select(2 - invalidNamespaceInPI);
+	    	fInvalidNamespaceInPI.setText(MARKUP_SEVERITIES[2 - invalidNamespaceInPI]);
+		}
+	    
+	    int tagNameMissing  = modelPreferences.getInt(XMLCorePreferenceNames.MISSING_TAG_NAME);
+	    
+	    if (fMissingTagName != null) {
+	    	fMissingTagName.select(2 - tagNameMissing);
+	    	fMissingTagName.setText(MARKUP_SEVERITIES[2 - tagNameMissing]);
+		}
+	    
+	    int invalidWhitespaceAtStart  = modelPreferences.getInt(XMLCorePreferenceNames.WHITESPACE_AT_START);
+	    
+	    if (fInvalidWhitespaceAtStart != null) {
+	    	fInvalidWhitespaceAtStart.select(2 - invalidWhitespaceAtStart);
+	    	fInvalidWhitespaceAtStart.setText(MARKUP_SEVERITIES[2 - invalidWhitespaceAtStart]);
+		}
+
+	    if (!useExtendedMarkupValidation)
+	    	fMarkupState = ControlEnableState.disable(fMarkupValidationGroup);
+  }
+
+  protected void performDefaultsForValidatingGroup() {
+    Preferences modelPreferences = getModelPreferences();
+    int indicateNoGrammarButtonSelected = modelPreferences.getDefaultInt(XMLCorePreferenceNames.INDICATE_NO_GRAMMAR);
+    boolean useXIncludeButtonSelected = modelPreferences.getDefaultBoolean(XMLCorePreferenceNames.USE_XINCLUDE);
+
+    if (fIndicateNoGrammar != null) {
+      fIndicateNoGrammar.setSelection(new Point(indicateNoGrammarButtonSelected, 2 - indicateNoGrammarButtonSelected));
+      fIndicateNoGrammar.setText(SEVERITIES[indicateNoGrammarButtonSelected]);
+    }
+    if (fUseXinclude != null) {
+      fUseXinclude.setSelection(useXIncludeButtonSelected);
+    }
+
+    boolean honourAllButtonSelected = modelPreferences.getDefaultBoolean(XMLCorePreferenceNames.HONOUR_ALL_SCHEMA_LOCATIONS);
+    if (fHonourAllSchemaLocations != null) {
+      fHonourAllSchemaLocations.setSelection(honourAllButtonSelected);
+    }
+  }
+  
+  protected void performDefaultsForMarkupValidationGroup() {
+	  Preferences modelPreferences = getModelPreferences();
+	    boolean useExtendedMarkupValidation = modelPreferences.getDefaultBoolean(XMLCorePreferenceNames.MARKUP_VALIDATION);
+
+	    
+	    if (fExtendedMarkupValidation != null) {
+	    	if (fExtendedMarkupValidation.getSelection() != useExtendedMarkupValidation) {
+	    		handleMarkupSeveritySelection(useExtendedMarkupValidation);
+	    	}
+	    	fExtendedMarkupValidation.setSelection(useExtendedMarkupValidation);
+	    	
+	    }
+	    int emptyElementTag = modelPreferences.getDefaultInt(XMLCorePreferenceNames.ATTRIBUTE_HAS_NO_VALUE);
+	    
+	    if (fEmptyElementTag != null) {
+	    	fEmptyElementTag.setSelection(new Point(emptyElementTag,2 - emptyElementTag));
+	    	fEmptyElementTag.setText(MARKUP_SEVERITIES[2 - emptyElementTag]);
+		}
+	    
+	    int endTagWithAttributes  = modelPreferences.getDefaultInt(XMLCorePreferenceNames.END_TAG_WITH_ATTRIBUTES);
+	    
+	    if (fEndTagWithAttributes != null) {
+	    	fEndTagWithAttributes.setSelection(new Point(endTagWithAttributes,2 - endTagWithAttributes));
+	    	fEndTagWithAttributes.setText(MARKUP_SEVERITIES[2 - endTagWithAttributes]);
+		}
+	    
+	    int invalidWhitespaceBeforeTagname  = modelPreferences.getDefaultInt(XMLCorePreferenceNames.WHITESPACE_BEFORE_TAGNAME);
+	    
+	    if (fInvalidWhitespaceBeforeTagname != null) {
+	    	fInvalidWhitespaceBeforeTagname.setSelection(new Point(invalidWhitespaceBeforeTagname,2 - invalidWhitespaceBeforeTagname));
+	    	fInvalidWhitespaceBeforeTagname.setText(MARKUP_SEVERITIES[2 - invalidWhitespaceBeforeTagname]);
+		}
+	    
+	    int missingClosingBracket  = modelPreferences.getDefaultInt(XMLCorePreferenceNames.MISSING_CLOSING_BRACKET);
+	    
+	    if (fMissingClosingBracket != null) {
+	    	fMissingClosingBracket.setSelection(new Point(missingClosingBracket,2 - missingClosingBracket));
+	    	fMissingClosingBracket.setText(MARKUP_SEVERITIES[2 - missingClosingBracket]);
+		}
+	    
+	    int missingClosingQuote  = modelPreferences.getDefaultInt(XMLCorePreferenceNames.MISSING_CLOSING_QUOTE);
+	    
+	    if (fMissingClosingQuote != null) {
+	    	fMissingClosingQuote.setSelection(new Point(missingClosingQuote,2 - missingClosingQuote));
+	    	fMissingClosingQuote.setText(MARKUP_SEVERITIES[2 - missingClosingQuote]);
+		}
+	    
+	    int missingEndTag  = modelPreferences.getDefaultInt(XMLCorePreferenceNames.MISSING_END_TAG);
+	    
+	    if (fMissingEndTag != null) {
+	    	fMissingEndTag.setSelection(new Point(missingEndTag,2 - missingEndTag));
+	    	fMissingEndTag.setText(MARKUP_SEVERITIES[2 - missingEndTag]);
+		}
+	    
+	    int missingStartTag  = modelPreferences.getDefaultInt(XMLCorePreferenceNames.MISSING_START_TAG);
+	    
+	    if (fMissingStartTag != null) {
+	    	fMissingStartTag.setSelection(new Point(missingStartTag,2 - missingStartTag));
+	    	fMissingStartTag.setText(MARKUP_SEVERITIES[2 - missingStartTag]);
+		}
+	    
+	    int missingQuotes  = modelPreferences.getDefaultInt(XMLCorePreferenceNames.MISSING_QUOTES);
+	    
+	    if (fMissingQuotes != null) {
+	    	fMissingQuotes.setSelection(new Point(missingQuotes,2 - missingQuotes));
+	    	fMissingQuotes.setText(MARKUP_SEVERITIES[2 - missingQuotes]);
+		}
+	    
+	    int invalidNamespaceInPI  = modelPreferences.getDefaultInt(XMLCorePreferenceNames.NAMESPACE_IN_PI_TARGET);
+	    
+	    if (fInvalidNamespaceInPI != null) {
+	    	fInvalidNamespaceInPI.setSelection(new Point(invalidNamespaceInPI,2 - invalidNamespaceInPI));
+	    	fInvalidNamespaceInPI.setText(MARKUP_SEVERITIES[2 - invalidNamespaceInPI]);
+		}
+	    
+	    int tagNameMissing  = modelPreferences.getDefaultInt(XMLCorePreferenceNames.MISSING_TAG_NAME);
+	    
+	    if (fMissingTagName != null) {
+	    	fMissingTagName.setSelection(new Point(tagNameMissing,2 - tagNameMissing));
+	    	fMissingTagName.setText(MARKUP_SEVERITIES[2 - tagNameMissing]);
+		}
+	    
+	    int invalidWhitespaceAtStart  = modelPreferences.getDefaultInt(XMLCorePreferenceNames.WHITESPACE_AT_START);
+	    
+	    if (fInvalidWhitespaceAtStart != null) {
+	    	fInvalidWhitespaceAtStart.setSelection(new Point(invalidWhitespaceAtStart,2 - invalidWhitespaceAtStart));
+	    	fInvalidWhitespaceAtStart.setText(MARKUP_SEVERITIES[2 - invalidWhitespaceAtStart]);
+		}
+	  }
+
+  protected void storeValuesForValidatingGroup()
+  {
+    Preferences modelPreferences = getModelPreferences();
+    if (fIndicateNoGrammar != null) {
+      int warnNoGrammarButtonSelected = 2 - fIndicateNoGrammar.getSelectionIndex();
+      modelPreferences.setValue(XMLCorePreferenceNames.INDICATE_NO_GRAMMAR, warnNoGrammarButtonSelected);
+    }
+    if (fUseXinclude != null) {
+      boolean useXIncludeButtonSelected = fUseXinclude.getSelection();
+      modelPreferences.setValue(XMLCorePreferenceNames.USE_XINCLUDE, useXIncludeButtonSelected);
+    }
+    if (fHonourAllSchemaLocations != null) {
+      boolean honourAllButtonSelected = fHonourAllSchemaLocations.getSelection();
+      modelPreferences.setValue(XMLCorePreferenceNames.HONOUR_ALL_SCHEMA_LOCATIONS, honourAllButtonSelected);
+    }
+  }
+  protected void storeValuesForMarkupValidationGroup()
+  {
+    Preferences modelPreferences = getModelPreferences();
+    if (fExtendedMarkupValidation != null) {
+        boolean extendedMarkupValidation = fExtendedMarkupValidation.getSelection();
+        modelPreferences.setValue(XMLCorePreferenceNames.MARKUP_VALIDATION, extendedMarkupValidation);
+    }
+    if (fEmptyElementTag != null) {
+      int emptyElementTag = 2 - fEmptyElementTag.getSelectionIndex();
+      modelPreferences.setValue(XMLCorePreferenceNames.ATTRIBUTE_HAS_NO_VALUE, emptyElementTag);
+    }
+    if (fEndTagWithAttributes != null) {
+        int endTagWithAttributes = 2 - fEndTagWithAttributes.getSelectionIndex();
+        modelPreferences.setValue(XMLCorePreferenceNames.END_TAG_WITH_ATTRIBUTES, endTagWithAttributes);
+    }
+    if (fInvalidWhitespaceBeforeTagname != null) {
+        int invalidWhitespaceBeforeTagname = 2 - fInvalidWhitespaceBeforeTagname.getSelectionIndex();
+        modelPreferences.setValue(XMLCorePreferenceNames.WHITESPACE_BEFORE_TAGNAME, invalidWhitespaceBeforeTagname);
+    }
+    if (fMissingClosingBracket != null) {
+          int missingClosingBracket = 2 - fMissingClosingBracket.getSelectionIndex();
+          modelPreferences.setValue(XMLCorePreferenceNames.MISSING_CLOSING_BRACKET, missingClosingBracket);
+    }
+    if (fMissingClosingQuote != null) {
+        int missingClosingQuote = 2 - fMissingClosingQuote.getSelectionIndex();
+        modelPreferences.setValue(XMLCorePreferenceNames.MISSING_CLOSING_BRACKET, missingClosingQuote);
+    }
+    if (fMissingEndTag != null) {
+        int missingEndTag = 2 - fMissingEndTag.getSelectionIndex();
+        modelPreferences.setValue(XMLCorePreferenceNames.MISSING_END_TAG, missingEndTag);
+        modelPreferences.getInt(XMLCorePreferenceNames.MISSING_END_TAG);
+    }
+	if (fMissingStartTag != null) {
+        int missingStartTag = 2 - fMissingStartTag.getSelectionIndex();
+	    modelPreferences.setValue(XMLCorePreferenceNames.MISSING_START_TAG, missingStartTag);
+	}
+	if (fMissingQuotes != null) {
+        int missingQuotes = 2 - fMissingQuotes.getSelectionIndex();
+	    modelPreferences.setValue(XMLCorePreferenceNames.MISSING_QUOTES, missingQuotes);
+	}
+	if (fInvalidNamespaceInPI != null) {
+        int invalidNamespaceInPI = 2 - fInvalidNamespaceInPI.getSelectionIndex();
+	    modelPreferences.setValue(XMLCorePreferenceNames.NAMESPACE_IN_PI_TARGET, invalidNamespaceInPI);
+	}
+	if (fMissingTagName != null) {
+        int missingTagName = 2 - fMissingTagName.getSelectionIndex();
+	    modelPreferences.setValue(XMLCorePreferenceNames.MISSING_TAG_NAME, missingTagName);
+	}
+	if (fInvalidWhitespaceAtStart != null) {
+        int invalidWhitespaceAtStart = 2 - fInvalidWhitespaceAtStart.getSelectionIndex();
+	    modelPreferences.setValue(XMLCorePreferenceNames.WHITESPACE_AT_START, invalidWhitespaceAtStart);
+	}
+    
+    
+  }
+  
+  protected void storeValues() {
+    storeValuesForValidatingGroup();
+    storeValuesForMarkupValidationGroup();
+  }
+
+  protected void performDefaults() {
+    performDefaultsForValidatingGroup();
+    performDefaultsForMarkupValidationGroup();
+    super.performDefaults();
+  }
+  
+  protected Preferences getModelPreferences() {
+    return XMLCorePlugin.getDefault().getPluginPreferences();
+  }  
+  
+  protected void doSavePreferenceStore() {
+      XMLCorePlugin.getDefault().savePluginPreferences(); // model
+  }
+
+  public boolean performOk() {
+    boolean result = super.performOk();
+
+    doSavePreferenceStore();
+
+    return result;
+  }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/projection/XMLCommentFoldingPosition.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/projection/XMLCommentFoldingPosition.java
new file mode 100644
index 0000000..d9740e9
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/projection/XMLCommentFoldingPosition.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.projection;
+
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.ui.internal.projection.AbstractStructuredCommentFoldingPosition;
+
+/**
+ *
+ */
+public class XMLCommentFoldingPosition extends AbstractStructuredCommentFoldingPosition {
+
+	/**
+	 * The region covering an XML comment
+	 */
+	private IStructuredDocumentRegion fRegion;
+	
+	/**
+	 * Create a folding position to cover a XML comment region
+	 * 
+	 * @param region
+	 */
+	public XMLCommentFoldingPosition(IStructuredDocumentRegion region) {
+		//can't use region.getLength here because doesn't work in DTD docs for some reason
+		super(region.getStartOffset(), region.getEndOffset() - region.getStartOffset());
+		this.fRegion = region;
+	}
+	
+	/**
+	 * @see org.eclipse.wst.sse.ui.internal.projection.AbstractStructuredCommentFoldingPosition#getEndOffset()
+	 */
+	protected int getEndOffset() {
+		return fRegion.getEndOffset();
+	}
+
+	/**
+	 * @see org.eclipse.wst.sse.ui.internal.projection.AbstractStructuredCommentFoldingPosition#getStartOffset()
+	 */
+	protected int getStartOffset() {
+		return fRegion.getStartOffset();
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/projection/XMLElementFoldingPosition.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/projection/XMLElementFoldingPosition.java
new file mode 100644
index 0000000..233e301
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/projection/XMLElementFoldingPosition.java
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * Copyright (c) 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.projection;
+
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.ui.internal.projection.AbstractStructuredFoldingPosition;
+
+/**
+ * Folds an XML element
+ */
+public class XMLElementFoldingPosition extends AbstractStructuredFoldingPosition {
+
+	/**
+	 * The region representing the start of the folding region
+	 */
+	private IStructuredDocumentRegion fStartRegion;
+	
+	/**
+	 * The region representing the end of the folding region, or <code>null</code>
+	 * if the entire folding region is represented by <code>fStartRegion</code>
+	 */
+	private IStructuredDocumentRegion fEndRegion;
+	
+	/**
+	 * <p>Used to represent a folding position that covers a single
+	 * {@link IStructuredDocumentRegion}.</p>
+	 * 
+	 * @param region the region that covers the entire position of the folding region
+	 */
+	public XMLElementFoldingPosition(IStructuredDocumentRegion region) {
+		super(region.getStartOffset(), region.getEndOffset()-region.getStartOffset());
+		this.fStartRegion = region;
+		this.fEndRegion = null;
+	}
+	
+	/**
+	 * <p>Used to represent a folding position that covers more then one
+	 * {@link IStructuredDocumentRegion}.</p>
+	 * 
+	 * @param startRegion the first region covered by this position
+	 * @param endRegion the last region covered by this position
+	 */
+	public XMLElementFoldingPosition(IStructuredDocumentRegion startRegion, IStructuredDocumentRegion endRegion) {
+		super(startRegion.getStartOffset(), endRegion.getEndOffset()-startRegion.getStartOffset());
+		this.fStartRegion = startRegion;
+		this.fEndRegion = endRegion;
+	}
+
+	/**
+	 * @see org.eclipse.wst.sse.ui.internal.projection.AbstractStructuredFoldingPosition#getStartOffset()
+	 */
+	protected int getStartOffset() {
+		return fStartRegion.getStartOffset();
+	}
+	
+	/**
+	 * @see org.eclipse.wst.sse.ui.internal.projection.AbstractStructuredFoldingPosition#getEndOffset()
+	 */
+	protected int getEndOffset() {
+		int endOffset;
+		if(fEndRegion != null) {
+			endOffset = fEndRegion.getEndOffset();
+		} else {
+			endOffset = fStartRegion.getEndOffset();
+		}
+		return endOffset;
+	}
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/projection/XMLFoldingStrategy.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/projection/XMLFoldingStrategy.java
new file mode 100644
index 0000000..227f9d8
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/projection/XMLFoldingStrategy.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.projection;
+
+import org.eclipse.jface.text.Position;
+import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.ui.internal.projection.AbstractStructuredFoldingStrategy;
+import org.eclipse.wst.xml.core.internal.document.CommentImpl;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMText;
+
+
+/**
+ * A folding strategy for XML type structured documents.
+ * See AbstractStructuredFoldingStrategy for more details.
+ */
+public class XMLFoldingStrategy extends AbstractStructuredFoldingStrategy {
+
+	/**
+	 * Create an instance of the folding strategy.
+	 * Be sure to set the viewer and document after creation.
+	 */
+	public XMLFoldingStrategy() {
+		super();
+	}
+
+	/**
+	 * @see org.eclipse.wst.sse.ui.internal.projection.AbstractFoldingStrategy#calcNewFoldPosition(org.eclipse.wst.sse.core.internal.provisional.IndexedRegion)
+	 */
+	protected Position calcNewFoldPosition(IndexedRegion indexedRegion) {
+		Position retPos = null;
+		
+		//only want to fold regions of the valid type and with a valid range
+		if(indexedRegion.getStartOffset() >= 0 && indexedRegion.getLength() >= 0) {
+			IDOMNode node = (IDOMNode)indexedRegion;
+			IStructuredDocumentRegion startRegion = node.getStartStructuredDocumentRegion();
+			IStructuredDocumentRegion endRegion = node.getEndStructuredDocumentRegion();
+			
+			//if the node has an endRegion (end tag) then folding region is
+			//	between the start and end tag
+			//else if the region is a comment
+			//else if the region is only an open tag or an open/close tag then don't fold it
+			if(startRegion != null && endRegion != null) {
+				retPos = new XMLElementFoldingPosition(startRegion, endRegion);
+			} else if(startRegion != null && indexedRegion instanceof CommentImpl) {
+				retPos = new XMLCommentFoldingPosition(startRegion);
+			}
+		}
+		
+		return retPos;
+	}
+
+	/**
+	 * @see org.eclipse.wst.sse.ui.internal.projection.AbstractFoldingStrategy#indexedRegionValidType(org.eclipse.wst.sse.core.internal.provisional.IndexedRegion)
+	 */
+	protected boolean indexedRegionValidType(IndexedRegion indexedRegion) {
+		return (indexedRegion instanceof IDOMNode) && !(indexedRegion instanceof IDOMText);
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/properties/EnumeratedStringPropertyDescriptor.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/properties/EnumeratedStringPropertyDescriptor.java
new file mode 100644
index 0000000..a4bd9f6
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/properties/EnumeratedStringPropertyDescriptor.java
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.properties;
+
+
+
+import java.util.Arrays;
+
+import org.eclipse.jface.viewers.CellEditor;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.views.properties.PropertyDescriptor;
+
+/**
+ * This class should be used for properties which require a combo box cell
+ * editor and whose values consist of a list of enumerated strings.
+ */
+public class EnumeratedStringPropertyDescriptor extends PropertyDescriptor {
+	protected StringComboBoxCellEditor fEditor;
+	protected Composite fParent;
+
+	/**
+	 * The enumerated possible values for the described property
+	 */
+	protected String fValues[] = null;
+
+	public EnumeratedStringPropertyDescriptor(Object id, String newDisplayName, String[] valuesArray) {
+		super(id, newDisplayName);
+		setDescription((String) id);
+		fValues = valuesArray;
+	}
+
+	/**
+	 * Creates and returns a new cell editor for editing this property.
+	 * Returns <code>null</code> if the property is not editable.
+	 * 
+	 * @param parent
+	 *            the parent widget for the cell editor
+	 * @return the cell editor for this property, or <code>null</code> if
+	 *         this property cannot be edited
+	 */
+	public CellEditor createPropertyEditor(Composite parent) {
+		// Check to see if we already have a Cell Editor with a valid Control
+		// under the given parent.
+		// If any of that's not true, create and return a new Cell Editor
+		if ((fEditor == null) || (fEditor.getControl() == null) || fEditor.getControl().isDisposed() || (parent != fParent)) {
+			fEditor = new StringComboBoxCellEditor(parent, fValues);
+		}
+		fParent = parent;
+		return fEditor;
+	}
+
+	public void updateValues(String newValues[]) {
+		if (Arrays.equals(fValues, newValues)) {
+			return;
+		}
+		fValues = newValues;
+		if (fEditor != null) {
+			fEditor.setItems(newValues);
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/properties/StringComboBoxCellEditor.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/properties/StringComboBoxCellEditor.java
new file mode 100644
index 0000000..a6536be
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/properties/StringComboBoxCellEditor.java
@@ -0,0 +1,119 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.properties;
+
+
+
+import org.eclipse.jface.viewers.ComboBoxCellEditor;
+import org.eclipse.swt.custom.CCombo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.wst.sse.ui.internal.Logger;
+
+
+/**
+ * An extended ComboBoxCellEditor that selects and returns Strings
+ */
+
+public class StringComboBoxCellEditor extends ComboBoxCellEditor {
+	private boolean fSettingValue = false;
+
+	/**
+	 * 
+	 */
+	public StringComboBoxCellEditor() {
+		super();
+	}
+
+	/**
+	 * @param parent
+	 * @param items
+	 */
+	public StringComboBoxCellEditor(Composite parent, String[] items) {
+		super(parent, items);
+	}
+
+	/**
+	 * @param parent
+	 * @param items
+	 * @param style
+	 */
+	public StringComboBoxCellEditor(Composite parent, String[] items, int style) {
+		super(parent, items, style);
+	}
+
+	protected Object doGetValue() {
+		// otherwise limits to set of valid values
+		Object index = super.doGetValue();
+		int selection = -1;
+		if (index instanceof Integer) {
+			selection = ((Integer) index).intValue();
+		}
+		if (selection >= 0) {
+			return getItems()[selection];
+		}
+		else if (getControl() instanceof CCombo) {
+			// retrieve the actual text as the list of valid items doesn't
+			// contain the value
+			return ((CCombo) getControl()).getText();
+		}
+		return null;
+	}
+
+	protected void doSetValue(Object value) {
+		if (fSettingValue) {
+			return;
+		}
+		fSettingValue = true;
+		if (value instanceof Integer) {
+			super.doSetValue(value);
+		}
+		else {
+			String stringValue = value.toString();
+			int selection = -1;
+			for (int i = 0; i < getItems().length; i++) {
+				if (getItems()[i].equals(stringValue)) {
+					selection = i;
+				}
+			}
+			if (selection >= 0) {
+				super.doSetValue(new Integer(selection));
+			}
+			else {
+				super.doSetValue(new Integer(-1));
+				if ((getControl() instanceof CCombo) && !stringValue.equals(((CCombo) getControl()).getText())) {
+					// update the Text widget
+					((CCombo) getControl()).setText(stringValue);
+				}
+			}
+		}
+		fSettingValue = false;
+	}
+
+	public void setItems(String[] newItems) {
+		if ((getControl() == null) || getControl().isDisposed()) {
+			Logger.log(Logger.ERROR, "Attempted to update item list for disposed cell editor"); //$NON-NLS-1$
+			return;
+		}
+
+		// keep selection if possible
+		Object previousSelectedValue = getValue();
+		super.setItems(newItems);
+		if ((previousSelectedValue != null) && (getControl() instanceof CCombo)) {
+			for (int i = 0; i < newItems.length; i++) {
+				if (newItems[i].equals(previousSelectedValue)) {
+					setValue(previousSelectedValue);
+				}
+			}
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/properties/XMLPropertySource.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/properties/XMLPropertySource.java
new file mode 100644
index 0000000..d9c2ed4
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/properties/XMLPropertySource.java
@@ -0,0 +1,833 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2009 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.properties;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Stack;
+
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.views.properties.IPropertyDescriptor;
+import org.eclipse.ui.views.properties.IPropertySheetEntry;
+import org.eclipse.ui.views.properties.IPropertySource;
+import org.eclipse.ui.views.properties.IPropertySource2;
+import org.eclipse.ui.views.properties.TextPropertyDescriptor;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.sse.ui.views.properties.IPropertySourceExtension;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.contentmodel.basic.CMNamedNodeMapImpl;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.DOMNamespaceHelper;
+import org.eclipse.wst.xml.core.internal.document.DocumentTypeAdapter;
+import org.eclipse.wst.xml.core.internal.modelquery.ModelQueryUtil;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.eclipse.wst.xml.ui.internal.Logger;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+import org.w3c.dom.Attr;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+/**
+ * An IPropertySource implementation for a JFace viewer used to display
+ * properties of DOM nodes.
+ */
+public class XMLPropertySource implements IPropertySource, IPropertySourceExtension, IPropertySource2 {
+	protected final static String CATEGORY_ATTRIBUTES = XMLUIMessages.XMLPropertySourceAdapter_0;
+
+	/**
+	 * Controls whether optional attributes are marked as for "experts"
+	 */
+	private static final boolean fSetExpertFilter = false;
+
+	/**
+	 * Controls whether to derive categories from CMDataTypes; disabled by
+	 * default until display strings can be planned
+	 */
+	private boolean fShouldDeriveCategories = false;
+
+	private final static boolean fSortEnumeratedValues = true;
+
+	/**
+	 * Note: we want the default fCaseSensitive to be true, but, to avoid
+	 * meaningless double initialization, we leave default here, and set in
+	 * constructor only.
+	 */
+	private boolean fCaseSensitive;
+	private IPropertyDescriptor[] fDescriptors = null;
+	private Node fNode = null;
+
+	private Stack fValuesBeingSet = new Stack();
+
+	public XMLPropertySource(INodeNotifier target) {
+		super();
+		fNode = initNode(target);
+		fCaseSensitive = initCaseSensitive(fNode);
+	}
+
+	public XMLPropertySource(Node target, boolean useCategories) {
+		super();
+		initNode(target);
+		fNode = target;
+		fCaseSensitive = initCaseSensitive(fNode);
+		fShouldDeriveCategories = useCategories;
+	}
+
+	/** Separate method just to isolate error processing */
+	private static INodeNotifier initNode(Node target) {
+		if (target instanceof INodeNotifier) {
+			return (INodeNotifier) target;
+		}
+		throw new IllegalArgumentException("XMLPropertySource is only for INodeNotifiers"); //$NON-NLS-1$
+	}
+
+	/** Separate method just to isolate error processing */
+	private static Node initNode(INodeNotifier target) {
+		if (target instanceof Node) {
+			return (Node) target;
+		}
+		throw new IllegalArgumentException("XMLPropertySource is only for W3C DOM Nodes"); //$NON-NLS-1$
+	}
+
+	private boolean initCaseSensitive(Node node) {
+		// almost all tags are case sensitive, except that old HTML
+		boolean caseSensitive = true;
+		if (node instanceof IDOMNode) {
+			DocumentTypeAdapter adapter = getDocTypeFromDOMNode(node);
+			if (adapter != null) {
+				caseSensitive = (adapter.getTagNameCase() == DocumentTypeAdapter.STRICT_CASE);
+			}
+		}
+		return caseSensitive;
+	}
+
+	/**
+	 * by "internal spec" the DOCTYPE adapter is only available from Document
+	 * Node
+	 * 
+	 * @return {@link DocumentTypeAdapter}
+	 */
+	private DocumentTypeAdapter getDocTypeFromDOMNode(Node node) {
+		DocumentTypeAdapter adapter = null;
+		Document ownerDocument = node.getOwnerDocument();
+		if (ownerDocument == null) {
+			// if ownerDocument is null, then fNode must be the Document Node
+			// [old, old comment]
+			// hmmmm, guess not. See
+			// https://bugs.eclipse.org/bugs/show_bug.cgi?id=130233
+			// guess this is used for many INodeNotifiers, not just XML.
+			// (and DTD's use IDOMNode? ... that doesn't sound quite right
+			// ... but, maybe a separate issue).
+			if (node instanceof Document) {
+				ownerDocument = (Document) node;
+			}
+		}
+		if (ownerDocument != null) {
+			adapter = (DocumentTypeAdapter) ((INodeNotifier) ownerDocument).getAdapterFor(DocumentTypeAdapter.class);
+		}
+
+		return adapter;
+	}
+
+	private String[] _getValidFixedStrings(CMAttributeDeclaration attrDecl, CMDataType helper) {
+		String attributeName = DOMNamespaceHelper.computeName(attrDecl, fNode, null);
+		List values = new ArrayList(1);
+		String impliedValue = helper.getImpliedValue();
+		if (impliedValue != null) {
+			values.add(impliedValue);
+		}
+		boolean checkIfCurrentValueIsIncluded = ((fNode.getAttributes() != null) && (fNode.getAttributes().getNamedItem(attributeName) != null) && (fNode.getAttributes().getNamedItem(attributeName).getNodeValue() != null));
+		if (checkIfCurrentValueIsIncluded) {
+			String currentValue = null;
+			currentValue = fNode.getAttributes().getNamedItem(attributeName).getNodeValue();
+			if (!currentValue.equals(impliedValue)) {
+				values.add(currentValue);
+			}
+		}
+		String[] validStrings = new String[values.size()];
+		validStrings = (String[]) values.toArray(validStrings);
+		return validStrings;
+	}
+
+	private String[] _getValidStrings(CMAttributeDeclaration attrDecl, CMDataType valuesHelper) {
+		String attributeName = DOMNamespaceHelper.computeName(attrDecl, fNode, null);
+		List values = new ArrayList(1);
+		boolean currentValueKnown = false;
+		boolean checkIfCurrentValueIsKnown = ((fNode.getAttributes() != null) && (fNode.getAttributes().getNamedItem(attributeName) != null) && (fNode.getAttributes().getNamedItem(attributeName).getNodeValue() != null));
+		String currentValue = null;
+		if (checkIfCurrentValueIsKnown) {
+			currentValue = fNode.getAttributes().getNamedItem(attributeName).getNodeValue();
+		}
+
+		if ((valuesHelper.getImpliedValueKind() == CMDataType.IMPLIED_VALUE_FIXED) && (valuesHelper.getImpliedValue() != null)) {
+			// FIXED value
+			currentValueKnown = (currentValue != null) && valuesHelper.getImpliedValue().equals(currentValue);
+			values.add(valuesHelper.getImpliedValue());
+		}
+		else {
+			// ENUMERATED values
+			String[] valueStrings = null;
+			// valueStrings = valuesHelper.getEnumeratedValues();
+			ModelQuery modelQuery = ModelQueryUtil.getModelQuery(fNode.getOwnerDocument());
+			if ((modelQuery != null) && (fNode.getNodeType() == Node.ELEMENT_NODE)) {
+				valueStrings = modelQuery.getPossibleDataTypeValues((Element) fNode, attrDecl);
+			}
+			else {
+				valueStrings = attrDecl.getAttrType().getEnumeratedValues();
+			}
+			if (valueStrings != null) {
+				for (int i = 0; i < valueStrings.length; i++) {
+					if (checkIfCurrentValueIsKnown && valueStrings[i].equals(currentValue)) {
+						currentValueKnown = true;
+					}
+					values.add(valueStrings[i]);
+				}
+			}
+		}
+		if ((valuesHelper.getImpliedValueKind() != CMDataType.IMPLIED_VALUE_NONE) && (valuesHelper.getImpliedValue() != null)) {
+			if (!values.contains(valuesHelper.getImpliedValue())) {
+				values.add(valuesHelper.getImpliedValue());
+			}
+		}
+
+		if (checkIfCurrentValueIsKnown && !currentValueKnown && (currentValue != null) && (currentValue.length() > 0)) {
+			values.add(currentValue);
+		}
+		String[] validStrings = new String[values.size()];
+		validStrings = (String[]) values.toArray(validStrings);
+		return validStrings;
+	}
+
+	private IPropertyDescriptor createDefaultPropertyDescriptor(String attributeName) {
+		return createDefaultPropertyDescriptor(attributeName, false);
+	}
+
+	private IPropertyDescriptor createDefaultPropertyDescriptor(String attributeName, boolean hideOnFilter) {
+		// The descriptor class used here is also used in
+		// updatePropertyDescriptors()
+		TextPropertyDescriptor descriptor = new TextPropertyDescriptor(attributeName, attributeName);
+		descriptor.setCategory(getCategory(null, null));
+		descriptor.setDescription(attributeName);
+		if (hideOnFilter && fSetExpertFilter) {
+			descriptor.setFilterFlags(new String[]{IPropertySheetEntry.FILTER_ID_EXPERT});
+		}
+		return descriptor;
+	}
+
+	/**
+	 * Creates a property descriptor for an attribute with ENUMERATED values -
+	 * if the value does not exist, an editable combo box is returned - if the
+	 * value exists but is not one in the enumerated list of value, a combo
+	 * box featuring the current and correct values is returned - if the value
+	 * exists and it is a valid value, a combo box featuring the correct
+	 * values with the current one visible is returned
+	 */
+	private IPropertyDescriptor createEnumeratedPropertyDescriptor(CMAttributeDeclaration attrDecl, CMDataType valuesHelper, Attr attr) {
+		// the displayName MUST be set
+		String attrName = DOMNamespaceHelper.computeName(attrDecl, fNode, null);
+		EnumeratedStringPropertyDescriptor descriptor = new EnumeratedStringPropertyDescriptor(attrName, attrName, _getValidStrings(attrDecl, valuesHelper));
+		descriptor.setCategory(getCategory(attrDecl, attr));
+		descriptor.setDescription(attrName);
+		if ((attrDecl.getUsage() != CMAttributeDeclaration.REQUIRED) && fSetExpertFilter) {
+			descriptor.setFilterFlags(new String[]{IPropertySheetEntry.FILTER_ID_EXPERT});
+		}
+		return descriptor;
+	}
+
+	/**
+	 * Creates a property descriptor for an attribute with a FIXED value - if
+	 * the value does not exist, an editable combo box is returned - if the
+	 * value exists but is not the fixed/default value, a combo box featuring
+	 * the current and correct value is returned - if the value exists and it
+	 * is the fixed/default value, no cell editor is provided "locking" the
+	 * value in
+	 */
+	private IPropertyDescriptor createFixedPropertyDescriptor(CMAttributeDeclaration attrDecl, CMDataType helper, Attr attr) {
+		// the displayName MUST be set
+		String attrName = DOMNamespaceHelper.computeName(attrDecl, fNode, null);
+		EnumeratedStringPropertyDescriptor descriptor = new EnumeratedStringPropertyDescriptor(attrName, attrName, _getValidFixedStrings(attrDecl, helper));
+		descriptor.setCategory(getCategory(attrDecl, attr));
+		descriptor.setDescription(DOMNamespaceHelper.computeName(attrDecl, fNode, null));
+		return descriptor;
+	}
+
+	protected IPropertyDescriptor createPropertyDescriptor(CMAttributeDeclaration attrDecl, Attr attr) {
+		IPropertyDescriptor descriptor = null;
+		CMDataType attrType = attrDecl.getAttrType();
+
+		if (attrType != null) {
+			// handle declarations that provide FIXED/ENUMERATED values
+			if ((attrType.getEnumeratedValues() != null) && (attrType.getEnumeratedValues().length > 0)) {
+				descriptor = createEnumeratedPropertyDescriptor(attrDecl, attrType, attr);
+			}
+			else if (((attrDecl.getUsage() == CMAttributeDeclaration.FIXED) || (attrType.getImpliedValueKind() == CMDataType.IMPLIED_VALUE_FIXED)) && (attrType.getImpliedValue() != null)) {
+				descriptor = createFixedPropertyDescriptor(attrDecl, attrType, attr);
+			}
+			else {
+				// plain text
+				descriptor = createTextPropertyDescriptor(attrDecl, attr);
+			}
+		}
+		else {
+			// no extra information given
+			descriptor = createTextPropertyDescriptor(attrDecl, attr);
+		}
+		return descriptor;
+	}
+
+	/**
+	 * Returns the current collection of property descriptors.
+	 * 
+	 * @return all valid descriptors.
+	 */
+	private IPropertyDescriptor[] createPropertyDescriptors() {
+		CMNamedNodeMap attrMap = null;
+		CMElementDeclaration ed = getDeclaration();
+		if (ed != null) {
+			attrMap = ed.getAttributes();
+			CMNamedNodeMapImpl allAttributes = new CMNamedNodeMapImpl(attrMap);
+			List nodes = ModelQueryUtil.getModelQuery(fNode.getOwnerDocument()).getAvailableContent((Element) fNode, ed, ModelQuery.INCLUDE_ATTRIBUTES);
+			for (int k = 0; k < nodes.size(); k++) {
+				CMNode cmnode = (CMNode) nodes.get(k);
+				if (cmnode.getNodeType() == CMNode.ATTRIBUTE_DECLARATION) {
+					allAttributes.put(cmnode);
+				}
+			}
+			attrMap = allAttributes;
+		}
+
+		List descriptorList = new ArrayList();
+		List names = new ArrayList();
+		IPropertyDescriptor descriptor;
+
+		CMAttributeDeclaration attrDecl = null;
+
+		// add descriptors for existing attributes
+		NamedNodeMap attributes = fNode.getAttributes();
+		if (attributes != null) {
+			for (int i = 0; i < attributes.getLength(); i++) {
+				Attr attr = (Attr) attributes.item(i);
+				// if metainfo is present for this attribute, use the
+				// CMAttributeDeclaration to derive a descriptor
+				if (attrMap != null) {
+					String attrName = attr.getName();
+					if (fCaseSensitive) {
+						attrDecl = (CMAttributeDeclaration) attrMap.getNamedItem(attrName);
+					}
+					else {
+						attrDecl = null;
+						for (int j = 0; j < attrMap.getLength(); j++) {
+							if (!fCaseSensitive && attrMap.item(j).getNodeName().equalsIgnoreCase(attrName)) {
+								attrDecl = (CMAttributeDeclaration) attrMap.item(j);
+								break;
+							}
+						}
+					}
+				}
+				// be consistent: if there's metainfo, use *that* as the
+				// descriptor ID
+				descriptor = null;
+				if (attrDecl != null) {
+					String attrName = DOMNamespaceHelper.computeName(attrDecl, fNode, null);
+					if (!names.contains(attrName)) {
+						descriptor = createPropertyDescriptor(attrDecl, attr);
+						if (descriptor != null)
+							names.add(attrName);
+					}
+				}
+				else {
+					if (!names.contains(attr.getName())) {
+						descriptor = createDefaultPropertyDescriptor(attr.getName());
+						if (descriptor != null)
+							names.add(attr.getName());
+					}
+				}
+				if (descriptor != null) {
+					descriptorList.add(descriptor);
+				}
+			}
+		}
+
+		// add descriptors from the metainfo that are not yet listed
+		if (attrMap != null) {
+			for (int i = 0; i < attrMap.getLength(); i++) {
+				attrDecl = (CMAttributeDeclaration) attrMap.item(i);
+				String attrName = DOMNamespaceHelper.computeName(attrDecl, fNode, null);
+				if (!names.contains(attrName)) {
+					IPropertyDescriptor holdDescriptor = createPropertyDescriptor(attrDecl, null);
+					if (holdDescriptor != null) {
+						names.add(attrName);
+						descriptorList.add(holdDescriptor);
+					}
+				}
+			}
+		}
+
+		// add MQE-based descriptors
+		if (ed != null && fNode.getNodeType() == Node.ELEMENT_NODE) {
+			List nodes = ModelQueryUtil.getModelQuery(fNode.getOwnerDocument()).getAvailableContent((Element) fNode, ed, ModelQuery.INCLUDE_ATTRIBUTES);
+			for (int i = 0; i < nodes.size(); i++) {
+				CMNode node = (CMNode) nodes.get(i);
+				if (node.getNodeType() == CMNode.ATTRIBUTE_DECLARATION) {
+					attrDecl = (CMAttributeDeclaration) node;
+					String attrName = DOMNamespaceHelper.computeName(attrDecl, fNode, null);
+					if (!names.contains(attrName)) {
+						IPropertyDescriptor holdDescriptor = createPropertyDescriptor(attrDecl, null);
+						if (holdDescriptor != null) {
+							names.add(attrName);
+							descriptorList.add(holdDescriptor);
+						}
+					}
+				}
+			}
+		}
+
+
+		IPropertyDescriptor[] descriptors = new IPropertyDescriptor[descriptorList.size()];
+		for (int i = 0; i < descriptors.length; i++) {
+			descriptors[i] = (IPropertyDescriptor) descriptorList.get(i);
+		}
+		return descriptors;
+	}
+
+	private IPropertyDescriptor createTextPropertyDescriptor(CMAttributeDeclaration attrDecl, Attr attr) {
+		String attrName = DOMNamespaceHelper.computeName(attrDecl, fNode, null);
+		TextPropertyDescriptor descriptor = new TextPropertyDescriptor(attrName, attrName);
+		descriptor.setCategory(getCategory(attrDecl, attr));
+		descriptor.setDescription(attrName);
+		if ((attrDecl.getUsage() != CMAttributeDeclaration.REQUIRED) && fSetExpertFilter) {
+			descriptor.setFilterFlags(new String[]{IPropertySheetEntry.FILTER_ID_EXPERT});
+		}
+		return descriptor;
+	}
+
+	private String getCategory(CMAttributeDeclaration attrDecl, Attr attr) {
+		if (attr != null) {
+			String namespaceURI = attr.getNamespaceURI();
+			if (namespaceURI == null)
+				namespaceURI = attr.getOwnerElement().getNamespaceURI();
+			if (namespaceURI != null)
+				return namespaceURI;
+		}
+		if (attrDecl != null) {
+			if (attrDecl.supports("category")) { //$NON-NLS-1$
+				return (String) attrDecl.getProperty("category"); //$NON-NLS-1$
+			}
+			if (fShouldDeriveCategories && (attrDecl.getAttrType() != null) && (attrDecl.getAttrType().getDataTypeName() != null) && (attrDecl.getAttrType().getDataTypeName().length() > 0)) {
+				return attrDecl.getAttrType().getDataTypeName();
+			}
+		}
+		return CATEGORY_ATTRIBUTES;
+	}
+
+	private CMElementDeclaration getDeclaration() {
+		if ((fNode == null) || (fNode.getNodeType() != Node.ELEMENT_NODE)) {
+			return null;
+		}
+		ModelQuery modelQuery = ModelQueryUtil.getModelQuery(fNode.getOwnerDocument());
+		if (modelQuery != null) {
+			return modelQuery.getCMElementDeclaration((Element) fNode);
+		}
+		return null;
+	}
+
+	private Display getDisplay() {
+
+		return PlatformUI.getWorkbench().getDisplay();
+	}
+
+	/**
+	 * Returns a value for this Node that can be editted in a property sheet.
+	 * 
+	 * @return a value that can be editted
+	 */
+	public Object getEditableValue() {
+		return null;
+	}
+
+	/**
+	 * Returns the current collection of property descriptors.
+	 * 
+	 * @return all valid descriptors.
+	 */
+	public final IPropertyDescriptor[] getPropertyDescriptors() {
+		if ((fDescriptors == null) || (fDescriptors.length == 0)) {
+			fDescriptors = createPropertyDescriptors();
+		}
+		else {
+			updatePropertyDescriptors();
+		}
+		return fDescriptors;
+	}
+
+	/**
+	 * Returns the current value for the named property.
+	 * 
+	 */
+	public Object getPropertyValue(Object nameObject) {
+		String name = nameObject.toString();
+		String returnedValue = null;
+		NamedNodeMap attrMap = fNode.getAttributes();
+		if (attrMap != null) {
+			Node attribute = attrMap.getNamedItem(name);
+			if (attribute != null) {
+				if (attribute instanceof IDOMNode) {
+					returnedValue = ((IDOMNode) attribute).getValueSource();
+				}
+				else {
+					returnedValue = attribute.getNodeValue();
+				}
+			}
+		}
+		if (returnedValue == null) {
+			returnedValue = ""; //$NON-NLS-1$
+		}
+		return returnedValue;
+	}
+
+	private String[] getValidValues(CMAttributeDeclaration attrDecl) {
+		if (attrDecl == null) {
+			return new String[0];
+		}
+
+		String[] validValues = null;
+		CMDataType attrType = attrDecl.getAttrType();
+		if (attrType != null) {
+			validValues = _getValidStrings(attrDecl, attrType);
+			if (fSortEnumeratedValues) {
+				Arrays.sort(validValues);
+			}
+		}
+		if (validValues == null) {
+			validValues = new String[0];
+		}
+		return validValues;
+	}
+
+	public boolean isPropertyRemovable(Object id) {
+		return true;
+	}
+
+	public boolean isPropertyResettable(Object id) {
+		return fNode != null && fNode.getNodeType() == Node.ELEMENT_NODE;
+	}
+
+	/**
+	 * Returns whether the property value has changed from the default.
+	 * 
+	 * @return <code>true</code> if the value of the specified property has
+	 *         changed from its original default value; <code>false</code>
+	 *         otherwise.
+	 */
+	public boolean isPropertySet(Object propertyObject) {
+		String property = propertyObject.toString();
+
+		NamedNodeMap attrMap = fNode.getAttributes();
+		if (attrMap != null) {
+			return attrMap.getNamedItem(property) != null;
+		}
+		return false;
+	}
+
+	/**
+	 * Remove the given attribute from the Node
+	 * 
+	 * @param propertyObject
+	 */
+	public void removeProperty(Object propertyObject) {
+		NamedNodeMap attrMap = fNode.getAttributes();
+		if (attrMap != null) {
+			Node attribute = attrMap.getNamedItem(propertyObject.toString());
+			if (attribute != null) {
+				try {
+					attrMap.removeNamedItem(propertyObject.toString());
+				}
+				catch (DOMException e) {
+					if (e.code != DOMException.INVALID_MODIFICATION_ERR) {
+						Logger.logException(e);
+					}
+				}
+			}
+		}
+	}
+
+	/**
+	 * Resets the specified property's value to its default value.
+	 */
+	public void resetPropertyValue(Object propertyObject) {
+		String property = propertyObject.toString();
+		CMNamedNodeMap attrDecls = null;
+
+		CMElementDeclaration ed = getDeclaration();
+		if (ed != null) {
+			attrDecls = ed.getAttributes();
+			CMNamedNodeMapImpl allAttributes = new CMNamedNodeMapImpl(attrDecls);
+			List nodes = ModelQueryUtil.getModelQuery(fNode.getOwnerDocument()).getAvailableContent((Element) fNode, ed, ModelQuery.INCLUDE_ATTRIBUTES);
+			for (int k = 0; k < nodes.size(); k++) {
+				CMNode cmnode = (CMNode) nodes.get(k);
+				if (cmnode.getNodeType() == CMNode.ATTRIBUTE_DECLARATION) {
+					allAttributes.put(cmnode);
+				}
+			}
+			attrDecls = allAttributes;
+		}
+
+		NamedNodeMap attrMap = fNode.getAttributes();
+		if (attrDecls != null) {
+			CMAttributeDeclaration attrDecl = (CMAttributeDeclaration) attrDecls.getNamedItem(property);
+			String defValue = null;
+			if (attrDecl != null) {
+				if (attrDecl.getAttrType() != null) {
+					CMDataType helper = attrDecl.getAttrType();
+					if ((helper.getImpliedValueKind() != CMDataType.IMPLIED_VALUE_NONE) && (helper.getImpliedValue() != null)) {
+						defValue = helper.getImpliedValue();
+					}
+				}
+			}
+			if ((defValue != null) && (defValue.length() > 0)) {
+				((Attr) attrMap.getNamedItem(property)).setValue(defValue);
+			}
+			else {
+				// remember, this method is for reset, not remove
+				((Attr) attrMap.getNamedItem(property)).setValue(""); //$NON-NLS-1$
+			}
+		}
+		else {
+			// remember, this method is for reset, not remove
+			((Attr) attrMap.getNamedItem(property)).setValue(""); //$NON-NLS-1$
+		}
+	}
+
+	/**
+	 * Sets the named property to the given value.
+	 * 
+	 */
+	public void setPropertyValue(Object nameObject, Object value) {
+		// Avoid cycling - can happen if a closing cell editor causes a
+		// refresh
+		// on the PropertySheet page and the setInput again asks the editor to
+		// close; besides, why apply the same value twice?
+		if (!fValuesBeingSet.isEmpty() && (fValuesBeingSet.peek() == nameObject)) {
+			return;
+		}
+		fValuesBeingSet.push(nameObject);
+		String name = nameObject.toString();
+		String valueString = ""; //$NON-NLS-1$
+		if (value != null) {
+			valueString = value.toString();
+		}
+		NamedNodeMap attrMap = fNode.getAttributes();
+		try {
+			if (attrMap != null) {
+				Attr attr = (Attr) attrMap.getNamedItem(name);
+				if (attr != null) {
+					// EXISTING VALUE
+					// potential out of control loop if updating the value
+					// triggers a viewer update, forcing the
+					// active cell editor to save its value and causing the
+					// loop to continue
+					if ((attr.getValue() == null) || !attr.getValue().equals(valueString)) {
+						if (attr instanceof IDOMNode) {
+							((IDOMNode) attr).setValueSource(valueString);
+						}
+						else {
+							attr.setValue(valueString);
+						}
+					}
+				}
+				else {
+					// NEW(?) value
+					Attr newAttr = fNode.getOwnerDocument().createAttribute(name);
+					if (newAttr instanceof IDOMNode) {
+						((IDOMNode) newAttr).setValueSource(valueString);
+					}
+					else {
+						newAttr.setValue(valueString);
+					}
+					attrMap.setNamedItem(newAttr);
+				}
+			}
+			else {
+				if (fNode instanceof Element) {
+					((Element) fNode).setAttribute(name, valueString);
+				}
+			}
+		}
+		catch (DOMException e) {
+			Display d = getDisplay();
+			if (d != null) {
+				d.beep();
+			}
+		}
+		fValuesBeingSet.pop();
+	}
+
+	protected void updatePropertyDescriptors() {
+		if ((fDescriptors == null) || (fDescriptors.length == 0)) {
+			// Nothing to update
+			return;
+		}
+
+		// List of all names encountered in the tag and defined by the element
+		List declaredNames = new ArrayList();
+		// New descriptor list that will become fDescriptors after all
+		// processing is done
+		List descriptors = new ArrayList();
+		// Names of the descriptors in the above List
+		List descriptorNames = new ArrayList();
+
+		// Update any descriptors derived from the metainfo
+		CMElementDeclaration ed = getDeclaration();
+		CMNamedNodeMap attrMap = null;
+		if (ed != null) {
+			attrMap = ed.getAttributes();
+			CMNamedNodeMapImpl allAttributes = new CMNamedNodeMapImpl(attrMap);
+			ModelQuery modelQuery = ModelQueryUtil.getModelQuery(fNode.getOwnerDocument());
+			if(modelQuery != null) {
+			List nodes = modelQuery.getAvailableContent((Element) fNode, ed, ModelQuery.INCLUDE_ATTRIBUTES);
+				for (int k = 0; k < nodes.size(); k++) {
+					CMNode cmnode = (CMNode) nodes.get(k);
+					if (cmnode.getNodeType() == CMNode.ATTRIBUTE_DECLARATION) {
+						allAttributes.put(cmnode);
+					}
+				}
+			}
+			attrMap = allAttributes;
+		}
+		// Update exiting descriptors; not added to the final list here
+		if (attrMap != null) {
+			// Update existing descriptor types based on metainfo
+			CMAttributeDeclaration attrDecl = null;
+			for (int i = 0; i < attrMap.getLength(); i++) {
+				attrDecl = (CMAttributeDeclaration) attrMap.item(i);
+				String attrName = DOMNamespaceHelper.computeName(attrDecl, fNode, null);
+				if (!declaredNames.contains(attrName)) {
+					declaredNames.add(attrName);
+				}
+				for (int j = 0; j < fDescriptors.length; j++) {
+					boolean sameName = (fCaseSensitive && fDescriptors[j].getId().equals(attrDecl.getNodeName())) || (!fCaseSensitive && attrDecl.getNodeName().equals(fDescriptors[j].getId().toString()));
+					if (sameName) {
+						String[] validValues = getValidValues(attrDecl);
+						// Update the descriptor for this
+						// CMAttributeDeclaration (only enumerated values get
+						// updated for now)
+						if (fDescriptors[j] instanceof EnumeratedStringPropertyDescriptor) {
+							((EnumeratedStringPropertyDescriptor) fDescriptors[j]).updateValues(validValues);
+						}
+						// Replace with better descriptor
+						else if ((validValues != null) && (validValues.length > 0)) {
+							fDescriptors[j] = createPropertyDescriptor(attrDecl, null);
+						}
+					}
+				}
+			}
+		}
+		else {
+			// Update existing descriptors based on not having any metainfo
+			for (int j = 0; j < fDescriptors.length; j++) {
+				// Replace with basic descriptor
+				if (!(fDescriptors[j] instanceof TextPropertyDescriptor)) {
+					fDescriptors[j] = createDefaultPropertyDescriptor((String) fDescriptors[j].getId());
+				}
+			}
+		}
+
+		NamedNodeMap attributes = fNode.getAttributes();
+
+		// Remove descriptors for attributes that aren't present AND aren't
+		// known through metainfo,
+		// do this by only reusing existing descriptors for attributes that
+		// are present or declared
+		for (int i = 0; i < fDescriptors.length; i++) {
+			if (fDescriptors[i] != null) {
+				String descriptorName = fDescriptors[i].getId().toString();
+				if ((declaredNames.contains(descriptorName) || (attributes.getNamedItem(descriptorName) != null)) && !descriptorNames.contains(descriptorName)) {
+					descriptorNames.add(descriptorName);
+					descriptors.add(fDescriptors[i]);
+				}
+			}
+		}
+
+		// Add descriptors for declared attributes that don't already have one
+		if (attrMap != null) {
+			// Update existing descriptor types based on metainfo
+			CMAttributeDeclaration attrDecl = null;
+			for (int i = 0; i < attrMap.getLength(); i++) {
+				attrDecl = (CMAttributeDeclaration) attrMap.item(i);
+				String attrName = DOMNamespaceHelper.computeName(attrDecl, fNode, null);
+				if (fCaseSensitive) {
+					if (!descriptorNames.contains(attrName)) {
+						IPropertyDescriptor descriptor = createPropertyDescriptor(attrDecl, null);
+						if (descriptor != null) {
+							descriptorNames.add(attrName);
+							descriptors.add(descriptor);
+						}
+					}
+				}
+				else {
+					boolean exists = false;
+					for (int j = 0; j < descriptorNames.size(); j++) {
+						exists = (descriptorNames.get(j).toString().equalsIgnoreCase(attrName)) || exists;
+					}
+					if (!exists) {
+						descriptorNames.add(attrName);
+						IPropertyDescriptor descriptor = createPropertyDescriptor(attrDecl, null);
+						if (descriptor != null) {
+							descriptorNames.add(attrName);
+							descriptors.add(descriptor);
+						}
+					}
+				}
+			}
+		}
+
+		// Add descriptors for existing attributes that don't already have one
+		if (attributes != null) {
+			for (int i = 0; i < attributes.getLength(); i++) {
+				Attr attr = (Attr) attributes.item(i);
+				String attrName = attr.getName();
+				if (fCaseSensitive) {
+					if (!descriptorNames.contains(attrName)) {
+						descriptorNames.add(attrName);
+						descriptors.add(createDefaultPropertyDescriptor(attrName));
+					}
+				}
+				else {
+					boolean exists = false;
+					for (int j = 0; j < descriptorNames.size(); j++) {
+						exists = (descriptorNames.get(j).toString().equalsIgnoreCase(attrName)) || exists;
+					}
+					if (!exists) {
+						descriptorNames.add(attrName);
+						descriptors.add(createDefaultPropertyDescriptor(attrName));
+					}
+				}
+			}
+		}
+
+		// Update fDescriptors
+		IPropertyDescriptor[] newDescriptors = new IPropertyDescriptor[descriptors.size()];
+		for (int i = 0; i < newDescriptors.length; i++) {
+			newDescriptors[i] = (IPropertyDescriptor) descriptors.get(i);
+		}
+		fDescriptors = newDescriptors;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/provisional/IDOMSourceEditingTextTools.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/provisional/IDOMSourceEditingTextTools.java
new file mode 100644
index 0000000..a018b08
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/provisional/IDOMSourceEditingTextTools.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.provisional;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.wst.sse.ui.internal.provisional.extensions.ISourceEditingTextTools;
+import org.eclipse.wst.sse.ui.internal.provisional.extensions.breakpoint.NodeLocation;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+public interface IDOMSourceEditingTextTools extends ISourceEditingTextTools {
+	/**
+	 * Returns a W3C DOM document
+	 * 
+	 * @return Document object or <code>null</code> if corresponding
+	 *         document does not exist
+	 */
+	Document getDOMDocument();
+
+	/**
+	 * Returns the W3C DOM Node at the given offset
+	 * 
+	 * @param offset
+	 *            the offset within the IDocument
+	 * @return a Node at that location, if one is present
+	 * 
+	 * @throws BadLocationException
+	 *             for invalid offsets
+	 */
+	Node getNode(int offset) throws BadLocationException;
+
+	/**
+	 * Returns a NodeLocation object describing the position information of
+	 * the Node's start and end tags.
+	 * 
+	 * @param node
+	 * @return The NodeLocation for this Node, null for unsupported Node
+	 *         instances.
+	 */
+	NodeLocation getNodeLocation(Node node);
+
+	/**
+	 * Returns the current server-side page language for the Document of the
+	 * given Node.
+	 * 
+	 * @return The server-side page language for this nodem null for Nodes
+	 *         within unsupported Documents.
+	 */
+	String getPageLanguage(Node node);
+
+	/**
+	 * Returns start offset of given Node.
+	 * 
+	 * @param node
+	 *            w3c <code>Node</code> object to check
+	 * @return the start offset or -1 for unsupported Nodes
+	 */
+	int getStartOffset(Node node);
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/provisional/XMLSourceEditingTextTools.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/provisional/XMLSourceEditingTextTools.java
new file mode 100644
index 0000000..63a337e
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/provisional/XMLSourceEditingTextTools.java
@@ -0,0 +1,182 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.provisional;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapter;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.ui.StructuredTextEditor;
+import org.eclipse.wst.sse.ui.internal.StructuredTextViewer;
+import org.eclipse.wst.sse.ui.internal.provisional.extensions.ISourceEditingTextTools;
+import org.eclipse.wst.sse.ui.internal.provisional.extensions.breakpoint.NodeLocation;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMText;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+/**
+ * Implements ISourceEditingTextTools interface
+ */
+public class XMLSourceEditingTextTools implements IDOMSourceEditingTextTools, INodeAdapter {
+
+	protected class NodeLocationImpl implements NodeLocation {
+		private IDOMNode node;
+
+		public NodeLocationImpl(IDOMNode xmlnode) {
+			super();
+			node = xmlnode;
+		}
+
+		public int getEndTagEndOffset() {
+			if (node.getEndStructuredDocumentRegion() != null) {
+				return node.getEndStructuredDocumentRegion().getEndOffset();
+			}
+			return -1;
+		}
+
+		public int getEndTagStartOffset() {
+			if (node.getEndStructuredDocumentRegion() != null) {
+				return node.getEndStructuredDocumentRegion().getStartOffset();
+			}
+			return -1;
+		}
+
+		public int getStartTagEndOffset() {
+			if (node.getStartStructuredDocumentRegion() != null) {
+				return node.getStartStructuredDocumentRegion().getEndOffset();
+			}
+			return -1;
+		}
+
+		public int getStartTagStartOffset() {
+			if (node.getStartStructuredDocumentRegion() != null) {
+				return node.getStartStructuredDocumentRegion().getStartOffset();
+			}
+			return -1;
+		}
+	}
+
+	StructuredTextEditor fTextEditor = null;
+
+	public int getCaretOffset() {
+		StructuredTextViewer stv = fTextEditor.getTextViewer();
+		if ((stv != null) && (stv.getTextWidget() != null) && !stv.getTextWidget().isDisposed()) {
+			return stv.widgetOffset2ModelOffset(stv.getTextWidget().getCaretOffset());
+		}
+		return 0;
+	}
+
+	public IDocument getDocument() {
+		return fTextEditor.getDocumentProvider().getDocument(fTextEditor.getEditorInput());
+	}
+
+	public Document getDOMDocument() {
+		return (Document) fTextEditor.getModel().getAdapter(Document.class);
+	}
+
+	/*
+	 * If similar function is needed, composite it around the text editor's
+	 * instance. Removed also because it returns an alread-released model
+	 * 
+	 * public Document getDOMDocument(IMarker marker) { if (marker == null)
+	 * return null;
+	 * 
+	 * IResource res = marker.getResource(); if (res == null || !(res
+	 * instanceof IFile)) return null;
+	 * 
+	 * IModelManager mm = StructuredModelManager.getModelManager();
+	 * IStructuredModel model = null; try { model =
+	 * mm.getExistingModelForRead((IFile) res); if (model == null || !(model
+	 * instanceof IDOMModel)) return null;
+	 * 
+	 * return ((IDOMModel) model).getDocument(); } finally { if (model !=
+	 * null) model.releaseFromRead(); } }
+	 */
+
+	public IEditorPart getEditorPart() {
+		return fTextEditor.getEditorPart();
+	}
+
+	public Node getNode(int offset) throws BadLocationException {
+		Node node = null;
+		if ((0 <= offset) && (offset <= getDocument().getLength())) {
+			node = (Node) fTextEditor.getModel().getIndexedRegion(offset);
+		}
+		else {
+			throw new BadLocationException();
+		}
+		return node;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.wst.sse.ui.extensions.SourceEditingTextTools#getNodeLocation(org.w3c.dom.Node)
+	 */
+	public NodeLocation getNodeLocation(Node node) {
+		if ((node.getNodeType() == Node.ELEMENT_NODE) && (node instanceof IDOMNode)) {
+			return new NodeLocationImpl((IDOMNode) node);
+		}
+		return null;
+	}
+
+	public String getPageLanguage(Node node) {
+		return ""; //$NON-NLS-1$
+	}
+
+	public ITextSelection getSelection() {
+		return (ITextSelection) fTextEditor.getSelectionProvider().getSelection();
+	}
+
+	/**
+	 * IExtendedMarkupEditor method
+	 */
+	// public List getSelectedNodes() {
+	// ViewerSelectionManager vsm = getViewerSelectionManager();
+	// return (vsm != null) ? vsm.getSelectedNodes() : null;
+	// }
+	public int getStartOffset(Node node) {
+		if ((node == null) || !(node instanceof IDOMText)) {
+			return -1;
+		}
+
+		IStructuredDocumentRegion fnode = ((IDOMText) node).getFirstStructuredDocumentRegion();
+		return fnode.getStartOffset();
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.wst.sse.core.core.INodeAdapter#isAdapterForType(java.lang.Object)
+	 */
+	public boolean isAdapterForType(Object type) {
+		return ISourceEditingTextTools.class.equals(type);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.wst.sse.core.core.INodeAdapter#notifyChanged(org.eclipse.wst.sse.core.core.INodeNotifier,
+	 *      int, java.lang.Object, java.lang.Object, java.lang.Object, int)
+	 */
+	public void notifyChanged(INodeNotifier notifier, int eventType, Object changedFeature, Object oldValue, Object newValue, int pos) {
+	}
+
+	public void setTextEditor(StructuredTextEditor editor) {
+		fTextEditor = editor;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/quickoutline/XMLContentSelectionProvider.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/quickoutline/XMLContentSelectionProvider.java
new file mode 100644
index 0000000..a3c9c75
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/quickoutline/XMLContentSelectionProvider.java
@@ -0,0 +1,46 @@
+package org.eclipse.wst.xml.ui.internal.quickoutline;
+
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.wst.sse.ui.IContentSelectionProvider;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Node;
+
+public class XMLContentSelectionProvider implements IContentSelectionProvider {
+
+	public ISelection getSelection(TreeViewer viewer, ISelection selection) {
+		ISelection filteredSelection = selection;
+		if (selection instanceof IStructuredSelection) {
+			Object[] filteredNodes = getFilteredNodes(((IStructuredSelection) selection).toArray());
+			filteredSelection = new StructuredSelection(filteredNodes);
+		}
+		return filteredSelection;
+	}
+
+	private Object[] getFilteredNodes(Object[] filteredNodes) {
+		for (int i = 0; i < filteredNodes.length; i++) {
+			filteredNodes[i] = getFilteredNode(filteredNodes[i]);
+		}
+		return filteredNodes;
+	}
+
+	private Object getFilteredNode(Object object) {
+		if (object instanceof Node) {
+			Node node = (Node) object;
+			short nodeType = node.getNodeType();
+			// replace attribute node in selection with its parent
+			if (nodeType == Node.ATTRIBUTE_NODE) {
+				node = ((Attr) node).getOwnerElement();
+			}
+			// anything else not visible, replace with parent node
+			else if (nodeType == Node.TEXT_NODE) {
+				node = node.getParentNode();
+			}
+			return node;
+		}
+		return object;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/quickoutline/XMLQuickOutlineConfiguration.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/quickoutline/XMLQuickOutlineConfiguration.java
new file mode 100644
index 0000000..16d21a1
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/quickoutline/XMLQuickOutlineConfiguration.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.quickoutline;
+
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.wst.sse.ui.IContentSelectionProvider;
+import org.eclipse.wst.sse.ui.quickoutline.AbstractQuickOutlineConfiguration;
+import org.eclipse.wst.xml.ui.internal.contentoutline.JFaceNodeContentProvider;
+import org.eclipse.wst.xml.ui.internal.contentoutline.JFaceNodeLabelProvider;
+
+public class XMLQuickOutlineConfiguration extends AbstractQuickOutlineConfiguration {
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.sse.ui.IOutlineContentManager#getContentProvider()
+	 */
+	public ITreeContentProvider getContentProvider() {
+		return new JFaceNodeContentProvider();
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.sse.ui.IOutlineContentManager#getContentSelectionProvider()
+	 */
+	public IContentSelectionProvider getContentSelectionProvider() {
+		return new XMLContentSelectionProvider();
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.sse.ui.IOutlineContentManager#getLabelProvider()
+	 */
+	public ILabelProvider getLabelProvider() {
+		return new JFaceNodeLabelProvider();
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/registry/AdapterFactoryProviderForXML.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/registry/AdapterFactoryProviderForXML.java
new file mode 100644
index 0000000..3794a17
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/registry/AdapterFactoryProviderForXML.java
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.registry;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.wst.sse.core.internal.ltk.modelhandler.IDocumentTypeHandler;
+import org.eclipse.wst.sse.core.internal.model.FactoryRegistry;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapterFactory;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.util.Assert;
+import org.eclipse.wst.sse.ui.internal.contentoutline.IJFaceNodeAdapter;
+import org.eclipse.wst.sse.ui.internal.provisional.registry.AdapterFactoryProvider;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.CMDocumentManager;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.modelhandler.ModelHandlerForXML;
+import org.eclipse.wst.xml.core.internal.modelquery.ModelQueryUtil;
+import org.eclipse.wst.xml.ui.internal.DOMObserver;
+import org.eclipse.wst.xml.ui.internal.XMLUIPlugin;
+import org.eclipse.wst.xml.ui.internal.contentoutline.JFaceNodeAdapterFactory;
+import org.eclipse.wst.xml.ui.internal.preferences.XMLUIPreferenceNames;
+
+/**
+ * 
+ */
+public class AdapterFactoryProviderForXML implements AdapterFactoryProvider {
+
+	/*
+	 * @see AdapterFactoryProvider#addAdapterFactories(IStructuredModel)
+	 */
+	public void addAdapterFactories(IStructuredModel structuredModel) {
+
+		// add the normal content based factories to model's registry
+		addContentBasedFactories(structuredModel);
+	}
+
+	protected void addContentBasedFactories(IStructuredModel structuredModel) {
+		FactoryRegistry factoryRegistry = structuredModel.getFactoryRegistry();
+		Assert.isNotNull(factoryRegistry, "Program Error: client caller must ensure model has factory registry"); //$NON-NLS-1$
+		INodeAdapterFactory factory = null;
+
+		factory = factoryRegistry.getFactoryFor(IJFaceNodeAdapter.class);
+		if (factory == null) {
+			factory = new JFaceNodeAdapterFactory();
+			factoryRegistry.addFactory(factory);
+		}
+
+		// cs... added for inferred grammar support
+		//
+		if (structuredModel != null) {
+			ModelQuery modelQuery = ModelQueryUtil.getModelQuery(structuredModel);
+			if (modelQuery != null) {
+				CMDocumentManager documentManager = modelQuery.getCMDocumentManager();
+				if (documentManager != null) {
+					IPreferenceStore store = XMLUIPlugin.getDefault().getPreferenceStore();
+					boolean useInferredGrammar = (store != null) ? store.getBoolean(XMLUIPreferenceNames.USE_INFERRED_GRAMMAR) : true;
+
+					documentManager.setPropertyEnabled(CMDocumentManager.PROPERTY_ASYNC_LOAD, true);
+					documentManager.setPropertyEnabled(CMDocumentManager.PROPERTY_AUTO_LOAD, false);
+					documentManager.setPropertyEnabled(CMDocumentManager.PROPERTY_USE_CACHED_RESOLVED_URI, true);
+					DOMObserver domObserver = new DOMObserver(structuredModel);
+					domObserver.setGrammarInferenceEnabled(useInferredGrammar);
+					domObserver.init();
+				}
+			}
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.wst.sse.ui.internal.provisional.registry.AdapterFactoryProvider#isFor(org.eclipse.wst.sse.core.internal.ltk.modelhandler.IDocumentTypeHandler)
+	 */
+	public boolean isFor(IDocumentTypeHandler contentTypeDescription) {
+		return (contentTypeDescription instanceof ModelHandlerForXML);
+	}
+
+	public void reinitializeFactories(IStructuredModel structuredModel) {
+		// nothing to do, since no embedded type
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/search/XMLFindOccurrencesActionDelegate.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/search/XMLFindOccurrencesActionDelegate.java
new file mode 100644
index 0000000..84f2ec9
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/search/XMLFindOccurrencesActionDelegate.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+
+package org.eclipse.wst.xml.ui.internal.search;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.wst.sse.ui.internal.search.FindOccurrencesActionDelegate;
+
+/**
+ * Sets up FindOccurrencesActionDelegate for xml find occurrences processors
+ */
+public class XMLFindOccurrencesActionDelegate extends FindOccurrencesActionDelegate {
+	private List fProcessors;
+
+	protected List getProcessors() {
+		if (fProcessors == null) {
+			fProcessors = new ArrayList();
+			XMLFindOccurrencesProcessor htmlProcessor = new XMLFindOccurrencesProcessor();
+			fProcessors.add(htmlProcessor);
+		}
+		return fProcessors;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/search/XMLFindOccurrencesProcessor.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/search/XMLFindOccurrencesProcessor.java
new file mode 100644
index 0000000..6b12fec
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/search/XMLFindOccurrencesProcessor.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+
+package org.eclipse.wst.xml.ui.internal.search;
+
+import org.eclipse.wst.sse.ui.internal.search.FindOccurrencesProcessor;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+import org.eclipse.wst.xml.core.text.IXMLPartitions;
+
+/**
+ * Configures a FindOccurrencesProcessor with XML partitions and regions
+ */
+public class XMLFindOccurrencesProcessor extends FindOccurrencesProcessor {
+
+	protected String[] getPartitionTypes() {
+		return new String[]{IXMLPartitions.XML_DEFAULT};
+	}
+
+	protected String[] getRegionTypes() {
+		return new String[]{DOMRegionContext.XML_TAG_NAME, DOMRegionContext.XML_TAG_ATTRIBUTE_NAME, DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE};
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/selection/StructuredSelectEnclosingXMLActionDelegate.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/selection/StructuredSelectEnclosingXMLActionDelegate.java
new file mode 100644
index 0000000..258be52
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/selection/StructuredSelectEnclosingXMLActionDelegate.java
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+
+package org.eclipse.wst.xml.ui.internal.selection;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.text.Region;
+import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
+import org.eclipse.wst.sse.ui.internal.selection.StructuredSelectActionDelegate;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+import org.w3c.dom.Node;
+
+public class StructuredSelectEnclosingXMLActionDelegate extends StructuredSelectActionDelegate {
+
+	protected IndexedRegion getCursorIndexedRegion(IDocument document, ITextSelection textSelection) {
+		IndexedRegion indexedRegion = null;
+
+		indexedRegion = getIndexedRegion(document, textSelection.getOffset());
+
+		return indexedRegion;
+	}
+
+	protected Region getNewSelectionRegion(IndexedRegion indexedRegion, ITextSelection textSelection) {
+		Region newRegion = null;
+		if (indexedRegion instanceof Node) {
+			Node cursorNode = (Node) indexedRegion;
+
+			// use parent node for empty text node
+			if ((cursorNode.getNodeType() == Node.TEXT_NODE) && (cursorNode.getNodeValue().trim().length() == 0)) {
+				cursorNode = cursorNode.getParentNode();
+
+				if (cursorNode instanceof IndexedRegion) {
+					indexedRegion = (IndexedRegion) cursorNode;
+				}
+			}
+
+			Region cursorNodeRegion = new Region(indexedRegion.getStartOffset(), indexedRegion.getEndOffset() - indexedRegion.getStartOffset());
+
+			if ((cursorNodeRegion.getOffset() >= textSelection.getOffset()) && (cursorNodeRegion.getOffset() <= textSelection.getOffset() + textSelection.getLength()) && (cursorNodeRegion.getOffset() + cursorNodeRegion.getLength() >= textSelection.getOffset()) && (cursorNodeRegion.getOffset() + cursorNodeRegion.getLength() <= textSelection.getOffset() + textSelection.getLength())) {
+				Node newNode = cursorNode.getParentNode();
+
+				if (newNode instanceof IndexedRegion) {
+					IndexedRegion newIndexedRegion = (IndexedRegion) newNode;
+					newRegion = new Region(newIndexedRegion.getStartOffset(), newIndexedRegion.getEndOffset() - newIndexedRegion.getStartOffset());
+				}
+			}
+			else {
+				newRegion = cursorNodeRegion;
+			}
+		}
+		return newRegion;
+	}
+
+	public void init(IAction action) {
+		if (action != null) {
+			action.setText(XMLUIMessages.StructureSelectEnclosing_label);
+			action.setToolTipText(XMLUIMessages.StructureSelectEnclosing_tooltip);
+			action.setDescription(XMLUIMessages.StructureSelectEnclosing_description);
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/selection/StructuredSelectNextXMLActionDelegate.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/selection/StructuredSelectNextXMLActionDelegate.java
new file mode 100644
index 0000000..f5088c3
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/selection/StructuredSelectNextXMLActionDelegate.java
@@ -0,0 +1,109 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+
+package org.eclipse.wst.xml.ui.internal.selection;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jface.text.TextSelection;
+import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
+import org.eclipse.wst.sse.ui.internal.selection.StructuredSelectActionDelegate;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+import org.w3c.dom.Node;
+
+public class StructuredSelectNextXMLActionDelegate extends StructuredSelectActionDelegate {
+
+	protected IndexedRegion getCursorIndexedRegion(IDocument document, ITextSelection textSelection) {
+		int offset = textSelection.getOffset() + textSelection.getLength() - 1;
+		if (offset < 0) {
+			offset = 0;
+		}
+
+		IndexedRegion indexedRegion = null;
+
+		indexedRegion = getIndexedRegion(document, offset);
+
+		return indexedRegion;
+	}
+
+	protected Region getNewSelectionRegion(IndexedRegion indexedRegion, ITextSelection textSelection) {
+		Region newRegion = null;
+		if (indexedRegion instanceof Node) {
+			Node cursorNode = (Node) indexedRegion;
+
+			// use parent node for empty text node
+			if ((cursorNode.getNodeType() == Node.TEXT_NODE) && (cursorNode.getNodeValue().trim().length() == 0)) {
+				cursorNode = cursorNode.getParentNode();
+
+				if (cursorNode instanceof IndexedRegion) {
+					indexedRegion = (IndexedRegion) cursorNode;
+				}
+			}
+
+			Region cursorNodeRegion = new Region(indexedRegion.getStartOffset(), indexedRegion.getEndOffset() - indexedRegion.getStartOffset());
+			int currentOffset = textSelection.getOffset();
+			int currentEndOffset = currentOffset + textSelection.getLength();
+			if ((cursorNodeRegion.getOffset() >= currentOffset) && (cursorNodeRegion.getOffset() <= currentEndOffset) && (cursorNodeRegion.getOffset() + cursorNodeRegion.getLength() >= currentOffset) && (cursorNodeRegion.getOffset() + cursorNodeRegion.getLength() <= currentEndOffset)) {
+				newRegion = getNewSelectionRegion2(indexedRegion, textSelection);
+			}
+			else {
+				newRegion = cursorNodeRegion;
+			}
+		}
+		return newRegion;
+	}
+
+	public void init(IAction action) {
+		if (action != null) {
+			action.setText(XMLUIMessages.StructureSelectNext_label);
+			action.setToolTipText(XMLUIMessages.StructureSelectNext_tooltip);
+			action.setDescription(XMLUIMessages.StructureSelectNext_description);
+		}
+	}
+
+	/**
+	 * This method was separated out from getNewSelectionRegion2 because the
+	 * code in here is allowed to be called recursively.
+	 * 
+	 * @param indexedRegion
+	 * @param textSelection
+	 * @return new region to select or null if none
+	 */
+	private Region getNewSelectionRegion2(IndexedRegion indexedRegion, ITextSelection textSelection) {
+		Region newRegion = null;
+		if (indexedRegion instanceof Node) {
+			Node node = (Node) indexedRegion;
+			Node newNode = node.getNextSibling();
+			if (newNode == null) {
+				newNode = node.getParentNode();
+
+				if (newNode instanceof IndexedRegion) {
+					IndexedRegion newIndexedRegion = (IndexedRegion) newNode;
+					newRegion = new Region(newIndexedRegion.getStartOffset(), newIndexedRegion.getEndOffset() - newIndexedRegion.getStartOffset());
+				}
+			}
+			else {
+				if (newNode instanceof IndexedRegion) {
+					IndexedRegion newIndexedRegion = (IndexedRegion) newNode;
+					newRegion = new Region(textSelection.getOffset(), newIndexedRegion.getEndOffset() - textSelection.getOffset());
+
+					if (newNode.getNodeType() == Node.TEXT_NODE) {
+						newRegion = getNewSelectionRegion2(newIndexedRegion, new TextSelection(newRegion.getOffset(), newRegion.getLength()));
+					}
+				}
+			}
+		}
+		return newRegion;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/selection/StructuredSelectPreviousXMLActionDelegate.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/selection/StructuredSelectPreviousXMLActionDelegate.java
new file mode 100644
index 0000000..8939c32
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/selection/StructuredSelectPreviousXMLActionDelegate.java
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+
+package org.eclipse.wst.xml.ui.internal.selection;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jface.text.TextSelection;
+import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
+import org.eclipse.wst.sse.ui.internal.selection.StructuredSelectActionDelegate;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+import org.w3c.dom.Node;
+
+public class StructuredSelectPreviousXMLActionDelegate extends StructuredSelectActionDelegate {
+
+	protected IndexedRegion getCursorIndexedRegion(IDocument document, ITextSelection textSelection) {
+		IndexedRegion indexedRegion = null;
+
+		indexedRegion = getIndexedRegion(document, textSelection.getOffset());
+
+		return indexedRegion;
+	}
+
+	protected Region getNewSelectionRegion(IndexedRegion indexedRegion, ITextSelection textSelection) {
+		Region newRegion = null;
+		if (indexedRegion instanceof Node) {
+			Node cursorNode = (Node) indexedRegion;
+
+			// use parent node for empty text node
+			if ((cursorNode.getNodeType() == Node.TEXT_NODE) && (cursorNode.getNodeValue().trim().length() == 0)) {
+				cursorNode = cursorNode.getParentNode();
+
+				if (cursorNode instanceof IndexedRegion) {
+					indexedRegion = (IndexedRegion) cursorNode;
+				}
+			}
+
+			Region cursorNodeRegion = new Region(indexedRegion.getStartOffset(), indexedRegion.getEndOffset() - indexedRegion.getStartOffset());
+
+			if ((cursorNodeRegion.getOffset() >= textSelection.getOffset()) && (cursorNodeRegion.getOffset() <= textSelection.getOffset() + textSelection.getLength()) && (cursorNodeRegion.getOffset() + cursorNodeRegion.getLength() >= textSelection.getOffset()) && (cursorNodeRegion.getOffset() + cursorNodeRegion.getLength() <= textSelection.getOffset() + textSelection.getLength())) {
+				Node newNode = cursorNode.getPreviousSibling();
+				if (newNode == null) {
+					newNode = cursorNode.getParentNode();
+
+					if (newNode instanceof IndexedRegion) {
+						IndexedRegion newIndexedRegion = (IndexedRegion) newNode;
+						newRegion = new Region(newIndexedRegion.getStartOffset(), newIndexedRegion.getEndOffset() - newIndexedRegion.getStartOffset());
+					}
+				}
+				else {
+					if (newNode instanceof IndexedRegion) {
+						IndexedRegion newIndexedRegion = (IndexedRegion) newNode;
+						newRegion = new Region(newIndexedRegion.getStartOffset(), textSelection.getOffset() + textSelection.getLength() - newIndexedRegion.getStartOffset());
+
+						if (newNode.getNodeType() == Node.TEXT_NODE) {
+							newRegion = getNewSelectionRegion(newIndexedRegion, new TextSelection(newRegion.getOffset(), newRegion.getLength()));
+						}
+					}
+				}
+
+			}
+			else {
+				newRegion = cursorNodeRegion;
+			}
+		}
+		return newRegion;
+	}
+
+	public void init(IAction action) {
+		if (action != null) {
+			action.setText(XMLUIMessages.StructureSelectPrevious_label);
+			action.setToolTipText(XMLUIMessages.StructureSelectPrevious_tooltip);
+			action.setDescription(XMLUIMessages.StructureSelectPrevious_description);
+		}
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/spelling/SpellcheckDelegateAdapterFactory.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/spelling/SpellcheckDelegateAdapterFactory.java
new file mode 100644
index 0000000..d77bea1
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/spelling/SpellcheckDelegateAdapterFactory.java
@@ -0,0 +1,103 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.spelling;
+
+import org.eclipse.core.runtime.IAdapterFactory;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
+import org.eclipse.wst.sse.ui.internal.spelling.ISpellcheckDelegate;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.modelquery.ModelQueryUtil;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
+import org.w3c.dom.Comment;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.Text;
+
+/**
+ * An <code>IAdapterFactory</code> to adapt an <code>IDOMModel</code> to a
+ * <code>ISpellcheckDelegate</code>.
+ */
+public class SpellcheckDelegateAdapterFactory implements IAdapterFactory {
+	/**
+	 * This list of classes this factory adapts to.
+	 */
+	private static final Class[] ADAPTER_LIST = new Class[]{ISpellcheckDelegate.class};
+	
+	/**
+	 * The <code>ISpellcheckDelegate</code> this factory adapts to
+	 */
+	private static final ISpellcheckDelegate DELEGATE = new XMLSpellcheckDelegate();
+	
+	/**
+	 * Implementation of <code>ISpellcheckDelegate</code> for XML type documents.
+	 */
+	private static class XMLSpellcheckDelegate implements ISpellcheckDelegate {
+		
+		/**
+		 * If the region in the given <code>model</code> at the given <code>offset</code> is a
+		 * <code>Comment</code> region then it should be spell checked, otherwise it should not.
+		 * 
+		 * @see org.eclipse.wst.sse.ui.internal.spelling.ISpellcheckDelegate#shouldSpellcheck(org.eclipse.wst.sse.core.internal.provisional.IndexedRegion)
+		 */
+		public boolean shouldSpellcheck(int offset, IStructuredModel model) {
+			boolean shouldSpellcheck = true;
+			
+			IndexedRegion region = model.getIndexedRegion(offset);
+			if(region != null) {
+				shouldSpellcheck = region instanceof Comment;
+				if (!shouldSpellcheck && region instanceof Text) {
+					final Node parent = ((Text) (region)).getParentNode();
+					if (parent != null && parent.getNodeType() == Node.ELEMENT_NODE) {
+						final ModelQuery mq = ModelQueryUtil.getModelQuery(parent.getOwnerDocument());
+						if (mq != null) {
+							final CMElementDeclaration decl = mq.getCMElementDeclaration((Element) parent);
+							if (decl != null) {
+								final CMDataType type= decl.getDataType();
+								shouldSpellcheck = type == null || type.getEnumeratedValues() == null || type.getEnumeratedValues().length == 0;
+							}
+						}
+					}
+				}
+			}
+			
+			return shouldSpellcheck;
+		}
+		
+	}
+	
+	/** 
+	 * Adapts <code>IDOMModel</code> to <code>ISpellcheckDelegate</code>.
+	 * 
+	 * @see org.eclipse.core.runtime.IAdapterFactory#getAdapter(java.lang.Object, java.lang.Class)
+	 */
+	public Object getAdapter(Object adaptableObject, Class adapterType) {
+		ISpellcheckDelegate decision = null;
+		
+		if (adaptableObject instanceof IDOMModel && ISpellcheckDelegate.class.equals(adapterType)) {
+			decision = DELEGATE;
+		}
+		
+		return decision;
+	}
+
+	/**
+	 *  This adapter only adapts to <code>ISpellcheckDelegate</code>
+	 *  
+	 * @see org.eclipse.core.runtime.IAdapterFactory#getAdapterList()
+	 */
+	public Class[] getAdapterList() {
+		return ADAPTER_LIST;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/style/IStyleConstantsXML.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/style/IStyleConstantsXML.java
new file mode 100644
index 0000000..79055b6
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/style/IStyleConstantsXML.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     Benjamin Muskalla, b.muskalla@gmx.net - [158660] character entities should have their own syntax highlighting preference      
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.style;
+
+/**
+ * Contains the symbolic name of styles used by LineStyleProvider,
+ * ColorManager, and any others who may be interested
+ */
+public interface IStyleConstantsXML {
+	public static final String BACKGROUND = "background"; //$NON-NLS-1$
+	public static final String CDATA_BORDER = "cdataBorder";//$NON-NLS-1$
+	public static final String CDATA_TEXT = "cdataText";//$NON-NLS-1$
+	public static final String COMMENT_BORDER = "commentBorder";//$NON-NLS-1$
+	public static final String COMMENT_TEXT = "commentText";//$NON-NLS-1$
+	public static final String DECL_BORDER = "declBoder";//$NON-NLS-1$
+	public static final String DOCTYPE_EXTERNAL_ID = "doctypeExternalId";//$NON-NLS-1$
+	public static final String DOCTYPE_EXTERNAL_ID_PUBREF = "doctypeExternalPubref";//$NON-NLS-1$
+	public static final String DOCTYPE_EXTERNAL_ID_SYSREF = "doctypeExtrenalSysref";//$NON-NLS-1$
+	public static final String DOCTYPE_NAME = "doctypeName";//$NON-NLS-1$
+
+	public static final String FOREGROUND = "foreground"; //$NON-NLS-1$
+	public static final String PI_BORDER = "piBorder";//$NON-NLS-1$
+	public static final String PI_CONTENT = "piContent";//$NON-NLS-1$
+
+	public static final String TAG_ATTRIBUTE_EQUALS = "tagAttributeEquals"; //$NON-NLS-1$
+	public static final String TAG_ATTRIBUTE_NAME = "tagAttributeName";//$NON-NLS-1$
+	public static final String TAG_ATTRIBUTE_VALUE = "tagAttributeValue";//$NON-NLS-1$
+	public static final String TAG_BORDER = "tagBorder";//$NON-NLS-1$
+	public static final String TAG_NAME = "tagName";//$NON-NLS-1$
+	public static final String XML_CONTENT = "xmlContent";//$NON-NLS-1$
+	public static final String ENTITY_REFERENCE = "entityReference";//$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/style/LineStyleProviderForXML.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/style/LineStyleProviderForXML.java
new file mode 100644
index 0000000..1241201
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/style/LineStyleProviderForXML.java
@@ -0,0 +1,209 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     Benjamin Muskalla, b.muskalla@gmx.net - [158660] character entities should have their own syntax highlighting preference     
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.style;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.TextAttribute;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+import org.eclipse.wst.sse.ui.internal.provisional.style.AbstractLineStyleProvider;
+import org.eclipse.wst.sse.ui.internal.provisional.style.LineStyleProvider;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+import org.eclipse.wst.xml.ui.internal.XMLUIPlugin;
+
+public class LineStyleProviderForXML extends AbstractLineStyleProvider implements LineStyleProvider {
+	public LineStyleProviderForXML() {
+		super();
+	}
+
+	protected TextAttribute getAttributeFor(ITextRegion region) {
+		/**
+		 * a method to centralize all the "format rules" for regions
+		 * specifically associated for how to "open" the region.
+		 */
+		// not sure why this is coming through null, but just to catch it
+		if (region == null) {
+			return (TextAttribute) getTextAttributes().get(IStyleConstantsXML.CDATA_TEXT);
+		}
+		
+		String type = region.getType();
+		if ((type == DOMRegionContext.XML_CONTENT) || (type == DOMRegionContext.XML_DOCTYPE_INTERNAL_SUBSET) || (type == DOMRegionContext.UNDEFINED)) {
+			return (TextAttribute) getTextAttributes().get(IStyleConstantsXML.XML_CONTENT);
+		}
+		if ((type == DOMRegionContext.XML_TAG_OPEN) || (type == DOMRegionContext.XML_END_TAG_OPEN) || (type == DOMRegionContext.XML_TAG_CLOSE) || (type == DOMRegionContext.XML_EMPTY_TAG_CLOSE)) {
+			return (TextAttribute) getTextAttributes().get(IStyleConstantsXML.TAG_BORDER);
+		}
+		if ((type == DOMRegionContext.XML_CDATA_OPEN) || (type == DOMRegionContext.XML_CDATA_CLOSE)) {
+			return (TextAttribute) getTextAttributes().get(IStyleConstantsXML.CDATA_BORDER);
+		}
+		if (type == DOMRegionContext.XML_CDATA_TEXT) {
+			return (TextAttribute) getTextAttributes().get(IStyleConstantsXML.CDATA_TEXT);
+		}
+		if (type == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) {
+			return (TextAttribute) getTextAttributes().get(IStyleConstantsXML.TAG_ATTRIBUTE_NAME);
+		}
+		if (type == DOMRegionContext.XML_DOCTYPE_DECLARATION) {
+			return (TextAttribute) getTextAttributes().get(IStyleConstantsXML.TAG_NAME);
+		}
+		if (type == DOMRegionContext.XML_TAG_NAME) {
+			return (TextAttribute) getTextAttributes().get(IStyleConstantsXML.TAG_NAME);
+		}
+		if ((type == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE)) {
+			return (TextAttribute) getTextAttributes().get(IStyleConstantsXML.TAG_ATTRIBUTE_VALUE);
+		}
+		if (type == DOMRegionContext.XML_TAG_ATTRIBUTE_EQUALS) {
+			return (TextAttribute) getTextAttributes().get(IStyleConstantsXML.TAG_ATTRIBUTE_EQUALS);
+		}
+		if ((type == DOMRegionContext.XML_COMMENT_OPEN) || (type == DOMRegionContext.XML_COMMENT_CLOSE)) {
+			return (TextAttribute) getTextAttributes().get(IStyleConstantsXML.COMMENT_BORDER);
+		}
+		if (type == DOMRegionContext.XML_COMMENT_TEXT) {
+			return (TextAttribute) getTextAttributes().get(IStyleConstantsXML.COMMENT_TEXT);
+		}
+		if (type == DOMRegionContext.XML_DOCTYPE_NAME) {
+			return (TextAttribute) getTextAttributes().get(IStyleConstantsXML.DOCTYPE_NAME);
+		}
+		if ((type == DOMRegionContext.XML_CHAR_REFERENCE) || (type == DOMRegionContext.XML_ENTITY_REFERENCE) || (type == DOMRegionContext.XML_PE_REFERENCE)) {
+			return (TextAttribute) getTextAttributes().get(IStyleConstantsXML.ENTITY_REFERENCE);
+		}
+		if (type == DOMRegionContext.XML_PI_CONTENT) {
+			return (TextAttribute) getTextAttributes().get(IStyleConstantsXML.PI_CONTENT);
+		}
+		if ((type == DOMRegionContext.XML_PI_OPEN) || (type == DOMRegionContext.XML_PI_CLOSE)) {
+			return (TextAttribute) getTextAttributes().get(IStyleConstantsXML.PI_BORDER);
+		}
+		if ((type == DOMRegionContext.XML_DECLARATION_OPEN) || (type == DOMRegionContext.XML_DECLARATION_CLOSE)) {
+			return (TextAttribute) getTextAttributes().get(IStyleConstantsXML.DECL_BORDER);
+		}
+		if (type == DOMRegionContext.XML_DOCTYPE_EXTERNAL_ID_SYSREF) {
+			return (TextAttribute) getTextAttributes().get(IStyleConstantsXML.DOCTYPE_EXTERNAL_ID_SYSREF);
+		}
+		if (type == DOMRegionContext.XML_DOCTYPE_EXTERNAL_ID_PUBREF) {
+			return (TextAttribute) getTextAttributes().get(IStyleConstantsXML.DOCTYPE_EXTERNAL_ID_PUBREF);
+		}
+		if ((type == DOMRegionContext.XML_DOCTYPE_EXTERNAL_ID_PUBLIC) || (type == DOMRegionContext.XML_DOCTYPE_EXTERNAL_ID_SYSTEM)) {
+			return (TextAttribute) getTextAttributes().get(IStyleConstantsXML.DOCTYPE_EXTERNAL_ID);
+		}
+		if (type == DOMRegionContext.WHITE_SPACE) {
+			/*
+			 * White space is normally not on its own ... but when it is,
+			 * we'll treat as content
+			 */
+			return (TextAttribute) getTextAttributes().get(IStyleConstantsXML.XML_CONTENT);
+		}
+		/*
+		 * default, return null to signal "not handled" in which case, other
+		 * providers should be tried
+		 */
+		return null;
+	}
+
+	protected IPreferenceStore getColorPreferences() {
+		return XMLUIPlugin.getDefault().getPreferenceStore();
+	}
+
+	protected void handlePropertyChange(PropertyChangeEvent event) {
+		String styleKey = null;
+
+		if (event != null) {
+			String prefKey = event.getProperty();
+			// check if preference changed is a style preference
+			if (IStyleConstantsXML.TAG_NAME.equals(prefKey)) {
+				styleKey = IStyleConstantsXML.TAG_NAME;
+			}
+			else if (IStyleConstantsXML.TAG_BORDER.equals(prefKey)) {
+				styleKey = IStyleConstantsXML.TAG_BORDER;
+			}
+			else if (IStyleConstantsXML.TAG_ATTRIBUTE_NAME.equals(prefKey)) {
+				styleKey = IStyleConstantsXML.TAG_ATTRIBUTE_NAME;
+			}
+			else if (IStyleConstantsXML.TAG_ATTRIBUTE_VALUE.equals(prefKey)) {
+				styleKey = IStyleConstantsXML.TAG_ATTRIBUTE_VALUE;
+			}
+			else if (IStyleConstantsXML.TAG_ATTRIBUTE_EQUALS.equals(prefKey)) {
+				styleKey = IStyleConstantsXML.TAG_ATTRIBUTE_EQUALS;
+			}
+			else if (IStyleConstantsXML.COMMENT_BORDER.equals(prefKey)) {
+				styleKey = IStyleConstantsXML.COMMENT_BORDER;
+			}
+			else if (IStyleConstantsXML.COMMENT_TEXT.equals(prefKey)) {
+				styleKey = IStyleConstantsXML.COMMENT_TEXT;
+			}
+			else if (IStyleConstantsXML.ENTITY_REFERENCE.equals(prefKey)) {
+				styleKey = IStyleConstantsXML.ENTITY_REFERENCE;
+			}
+			else if (IStyleConstantsXML.CDATA_BORDER.equals(prefKey)) {
+				styleKey = IStyleConstantsXML.CDATA_BORDER;
+			}
+			else if (IStyleConstantsXML.CDATA_TEXT.equals(prefKey)) {
+				styleKey = IStyleConstantsXML.CDATA_TEXT;
+			}
+			else if (IStyleConstantsXML.DECL_BORDER.equals(prefKey)) {
+				styleKey = IStyleConstantsXML.DECL_BORDER;
+			}
+			else if (IStyleConstantsXML.DOCTYPE_EXTERNAL_ID.equals(prefKey)) {
+				styleKey = IStyleConstantsXML.DOCTYPE_EXTERNAL_ID;
+			}
+			else if (IStyleConstantsXML.DOCTYPE_EXTERNAL_ID_PUBREF.equals(prefKey)) {
+				styleKey = IStyleConstantsXML.DOCTYPE_EXTERNAL_ID_PUBREF;
+			}
+			else if (IStyleConstantsXML.DOCTYPE_EXTERNAL_ID_SYSREF.equals(prefKey)) {
+				styleKey = IStyleConstantsXML.DOCTYPE_EXTERNAL_ID_SYSREF;
+			}
+			else if (IStyleConstantsXML.DOCTYPE_NAME.equals(prefKey)) {
+				styleKey = IStyleConstantsXML.DOCTYPE_NAME;
+			}
+			else if (IStyleConstantsXML.PI_CONTENT.equals(prefKey)) {
+				styleKey = IStyleConstantsXML.PI_CONTENT;
+			}
+			else if (IStyleConstantsXML.PI_BORDER.equals(prefKey)) {
+				styleKey = IStyleConstantsXML.PI_BORDER;
+			}
+			else if (IStyleConstantsXML.XML_CONTENT.equals(prefKey)) {
+				styleKey = IStyleConstantsXML.XML_CONTENT;
+			}
+		}
+
+		if (styleKey != null) {
+			// overwrite style preference with new value
+			addTextAttribute(styleKey);
+			super.handlePropertyChange(event);
+		}
+	}
+
+	/**
+	 * Loads text attributes into map. Make sure map is cleared before calling
+	 * this.
+	 */
+	protected void loadColors() {
+		addTextAttribute(IStyleConstantsXML.TAG_NAME);
+		addTextAttribute(IStyleConstantsXML.TAG_BORDER);
+		addTextAttribute(IStyleConstantsXML.TAG_ATTRIBUTE_NAME);
+		addTextAttribute(IStyleConstantsXML.TAG_ATTRIBUTE_VALUE);
+		addTextAttribute(IStyleConstantsXML.TAG_ATTRIBUTE_EQUALS);
+		addTextAttribute(IStyleConstantsXML.COMMENT_BORDER);
+		addTextAttribute(IStyleConstantsXML.COMMENT_TEXT);
+		addTextAttribute(IStyleConstantsXML.CDATA_BORDER);
+		addTextAttribute(IStyleConstantsXML.CDATA_TEXT);
+		addTextAttribute(IStyleConstantsXML.DECL_BORDER);
+		addTextAttribute(IStyleConstantsXML.DOCTYPE_EXTERNAL_ID);
+		addTextAttribute(IStyleConstantsXML.DOCTYPE_EXTERNAL_ID_PUBREF);
+		addTextAttribute(IStyleConstantsXML.DOCTYPE_EXTERNAL_ID_SYSREF);
+		addTextAttribute(IStyleConstantsXML.DOCTYPE_NAME);
+		addTextAttribute(IStyleConstantsXML.PI_CONTENT);
+		addTextAttribute(IStyleConstantsXML.PI_BORDER);
+		addTextAttribute(IStyleConstantsXML.XML_CONTENT);
+		addTextAttribute(IStyleConstantsXML.ENTITY_REFERENCE);
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/taginfo/MarkupTagInfoProvider.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/taginfo/MarkupTagInfoProvider.java
new file mode 100644
index 0000000..9615ad4
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/taginfo/MarkupTagInfoProvider.java
@@ -0,0 +1,184 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.taginfo;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocumentation;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNodeList;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.CMDescriptionBuilder;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+
+/**
+ * Provides basic tag information such as element/attribute name, data type,
+ * and tag info/documentation for CMNodes. Uses HTML to enhance presentation.
+ */
+public class MarkupTagInfoProvider {
+	protected final static String BOLD_END = "</b>"; //$NON-NLS-1$
+	protected final static String BOLD_START = "<b>"; //$NON-NLS-1$
+	protected final static String HEADING_END = "</h5>"; //$NON-NLS-1$
+	protected final static String HEADING_START = "<h5>"; //$NON-NLS-1$
+	protected final static String LIST_BEGIN = "<ul>"; //$NON-NLS-1$
+	protected final static String LIST_ELEMENT = "<li>"; //$NON-NLS-1$
+	protected final static String NEW_LINE = "<dl>"; //$NON-NLS-1$
+	protected final static String PARAGRAPH_END = "</p>"; //$NON-NLS-1$
+	protected final static String PARAGRAPH_START = "<p>"; //$NON-NLS-1$
+	protected final static String SPACE = " "; //$NON-NLS-1$
+
+	/**
+	 * Returns basic tag information for display given a CMNode
+	 * 
+	 * @return String
+	 */
+	public String getInfo(CMNode node) {
+		if (node == null) {
+			return null;
+		}
+		StringBuffer sb = new StringBuffer();
+		// we assume that if there is tagInfo present, only display tagInfo
+		printTagInfo(sb, node);
+
+		// no tagInfo present, so try to display tag description
+		if (sb.length() == 0) {
+			printDescription(sb, node);
+		}
+
+		// no tag description present either, so display default info
+		if (sb.length() == 0) {
+			printDefaultInfo(node, sb);
+		}
+
+		return sb.toString();
+	}
+
+	/**
+	 * Adds dataType's data type information, including enumerated type values
+	 * to string buffer, sb
+	 * 
+	 */
+	protected void printDataTypeInfo(StringBuffer sb, CMDataType dataType) {
+		String dataTypeName = dataType.getNodeName();
+		if ((dataTypeName != null) && (dataTypeName.length() > 0)) {
+			sb.append(PARAGRAPH_START + BOLD_START + XMLUIMessages.Data_Type____4 + SPACE + BOLD_END);
+			sb.append(dataTypeName);
+			sb.append(PARAGRAPH_END);
+		}
+		String defaultValue = dataType.getImpliedValue();
+		if(defaultValue != null) {
+			sb.append(PARAGRAPH_START + BOLD_START + XMLUIMessages.Default_Value____6 + SPACE + BOLD_END);
+			sb.append(defaultValue);
+			sb.append(PARAGRAPH_END);
+		}
+		String[] enumeratedValue = dataType.getEnumeratedValues();
+		if ((enumeratedValue != null) && (enumeratedValue.length > 0)) {
+			sb.append(PARAGRAPH_START + BOLD_START + XMLUIMessages.Enumerated_Values____5 + SPACE + BOLD_END);
+			sb.append(LIST_BEGIN);
+			for (int i = 0; i < enumeratedValue.length; i++) {
+				sb.append(LIST_ELEMENT + enumeratedValue[i]);
+			}
+			sb.append(PARAGRAPH_END);
+		}
+	}
+
+	/**
+	 * Adds the default info (element name, content model, data type) of
+	 * CMNode to the string buffer, sb
+	 * 
+	 */
+	protected void printDefaultInfo(CMNode node, StringBuffer sb) {
+		{
+
+			if (node.getNodeType() == CMNode.ELEMENT_DECLARATION) {
+				CMElementDeclaration ed = (CMElementDeclaration) node;
+				sb.append(PARAGRAPH_START + BOLD_START + XMLUIMessages.Element____1 + SPACE + BOLD_END);
+				sb.append(node.getNodeName());
+				sb.append(PARAGRAPH_END);
+				printDocumentation(sb, node);
+				if (ed.getContentType() == CMElementDeclaration.PCDATA) {
+					CMDataType dataType = ed.getDataType();
+					if (dataType != null) {
+						printDataTypeInfo(sb, dataType);
+					}
+				}
+				else {
+					CMDescriptionBuilder builder = new CMDescriptionBuilder();
+					String description = builder.buildDescription(node);
+					if ((description != null) && (description.length() > 0)) {
+						sb.append(PARAGRAPH_START + BOLD_START + XMLUIMessages.Content_Model____2 + SPACE + BOLD_END);
+						sb.append(description + PARAGRAPH_END);
+					}
+				}
+			}
+			else if (node.getNodeType() == CMNode.ATTRIBUTE_DECLARATION) {
+				CMAttributeDeclaration ad = (CMAttributeDeclaration) node;
+				sb.append(PARAGRAPH_START + BOLD_START + XMLUIMessages.Attribute____3 + SPACE + BOLD_END);
+				sb.append(node.getNodeName());
+				sb.append(PARAGRAPH_END);
+				printDocumentation(sb, node);
+				CMDataType dataType = ad.getAttrType();
+				if (dataType != null) {
+					printDataTypeInfo(sb, dataType);
+				}
+			}
+			else if (node.getNodeType() == CMNode.DATA_TYPE) {
+				sb.append(PARAGRAPH_START + BOLD_START + XMLUIMessages.Data_Type____4 + SPACE + BOLD_END);
+				sb.append(node.getNodeName());
+				sb.append(PARAGRAPH_END);
+				printDocumentation(sb, node);
+			}
+		}
+	}
+
+	/**
+	 * Adds the description property of the CMNode to the string buffer, sb
+	 * 
+	 */
+	protected void printDescription(StringBuffer sb, CMNode node) {
+		String tagInfo = (String) node.getProperty("description"); //$NON-NLS-1$
+		if (tagInfo != null) {
+			sb.append(PARAGRAPH_START + tagInfo.trim() + PARAGRAPH_END);
+		}
+	}
+
+	/**
+	 * Adds the tag documentation property of the CMNode to the string buffer,
+	 * sb
+	 * 
+	 */
+	protected void printDocumentation(StringBuffer sb, CMNode node) {
+		CMNodeList nodeList = (CMNodeList) node.getProperty("documentation"); //$NON-NLS-1$
+		if ((nodeList != null) && (nodeList.getLength() > 0)) {
+			for (int i = 0; i < nodeList.getLength(); i++) {
+				CMDocumentation documentation = (CMDocumentation) nodeList.item(i);
+				String doc = documentation.getValue();
+				if (doc != null) {
+					sb.append(PARAGRAPH_START + doc.trim() + PARAGRAPH_END);
+				}
+			}
+			sb.append(NEW_LINE);
+		}
+	}
+
+	/**
+	 * Adds the tag info property of the CMNode to the string buffer, sb
+	 * 
+	 */
+	protected void printTagInfo(StringBuffer sb, CMNode node) {
+		String tagInfo = (String) node.getProperty("tagInfo"); //$NON-NLS-1$
+		if (tagInfo != null) {
+			sb.append(PARAGRAPH_START + tagInfo.trim() + PARAGRAPH_END);
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/taginfo/XMLInformationProvider.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/taginfo/XMLInformationProvider.java
new file mode 100644
index 0000000..fe76a69
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/taginfo/XMLInformationProvider.java
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.taginfo;
+
+
+
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextHover;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.information.IInformationProvider;
+import org.eclipse.jface.text.information.IInformationProviderExtension;
+import org.eclipse.wst.sse.ui.internal.SSEUIPlugin;
+
+/**
+ * Provides context information for XML tags (Shows tooltip description)
+ * 
+ * @deprecated StructuredTextViewerConfiguration creates the appropriate
+ *             information provider
+ */
+public class XMLInformationProvider implements IInformationProvider, IInformationProviderExtension {
+
+	private ITextHover fTextHover = null;
+
+	public XMLInformationProvider() {
+		fTextHover = SSEUIPlugin.getDefault().getTextHoverManager().createBestMatchHover(new XMLTagInfoHoverProcessor());
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.information.IInformationProvider#getInformation(org.eclipse.jface.text.ITextViewer,
+	 *      org.eclipse.jface.text.IRegion)
+	 */
+	public String getInformation(ITextViewer textViewer, IRegion subject) {
+		return (String) getInformation2(textViewer, subject);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.information.IInformationProviderExtension#getInformation2(org.eclipse.jface.text.ITextViewer,
+	 *      org.eclipse.jface.text.IRegion)
+	 */
+	public Object getInformation2(ITextViewer textViewer, IRegion subject) {
+		return fTextHover.getHoverInfo(textViewer, subject);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.information.IInformationProvider#getSubject(org.eclipse.jface.text.ITextViewer,
+	 *      int)
+	 */
+	public IRegion getSubject(ITextViewer textViewer, int offset) {
+		return fTextHover.getHoverRegion(textViewer, offset);
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/taginfo/XMLTagInfoHoverProcessor.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/taginfo/XMLTagInfoHoverProcessor.java
new file mode 100644
index 0000000..47276fc
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/taginfo/XMLTagInfoHoverProcessor.java
@@ -0,0 +1,362 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2008 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.taginfo;
+
+
+
+import java.util.List;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.Region;
+import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
+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.ITextRegionList;
+import org.eclipse.wst.sse.core.internal.util.Debug;
+import org.eclipse.wst.sse.ui.internal.contentassist.ContentAssistUtils;
+import org.eclipse.wst.sse.ui.internal.taginfo.AbstractHoverProcessor;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.contentmodel.basic.CMNamedNodeMapImpl;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.DOMNamespaceHelper;
+import org.eclipse.wst.xml.core.internal.modelquery.ModelQueryUtil;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+import org.eclipse.wst.xml.ui.internal.Logger;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+
+/**
+ * Provides hover help documentation for xml tags
+ * 
+ * @see org.eclipse.jface.text.ITextHover
+ */
+public class XMLTagInfoHoverProcessor extends AbstractHoverProcessor {
+	protected MarkupTagInfoProvider fInfoProvider = null;
+
+	/**
+	 * Constructor for XMLTextHoverProcessor.
+	 */
+	public XMLTagInfoHoverProcessor() {
+		// nothing
+	}
+
+	/**
+	 * Retreives documentation to display in the hover help popup.
+	 * 
+	 * @return String any documentation information to display
+	 *         <code>null</code> if there is nothing to display.
+	 * 
+	 */
+	protected String computeHoverHelp(ITextViewer textViewer, int documentPosition) {
+		String result = null;
+
+		IndexedRegion treeNode = ContentAssistUtils.getNodeAt(textViewer, documentPosition);
+		if (treeNode == null) {
+			return null;
+		}
+		Node node = (Node) treeNode;
+
+		while ((node != null) && (node.getNodeType() == Node.TEXT_NODE) && (node.getParentNode() != null)) {
+			node = node.getParentNode();
+		}
+		IDOMNode parentNode = (IDOMNode) node;
+
+		IStructuredDocumentRegion flatNode = ((IStructuredDocument) textViewer.getDocument()).getRegionAtCharacterOffset(documentPosition);
+		if (flatNode != null) {
+			ITextRegion region = flatNode.getRegionAtCharacterOffset(documentPosition);
+			if (region != null) {
+				result = computeRegionHelp(treeNode, parentNode, flatNode, region);
+			}
+		}
+
+		return result;
+	}
+
+	/**
+	 * Computes the hoverhelp based on region
+	 * 
+	 * @return String hoverhelp
+	 */
+	protected String computeRegionHelp(IndexedRegion treeNode, IDOMNode parentNode, IStructuredDocumentRegion flatNode, ITextRegion region) {
+		String result = null;
+		if (region == null) {
+			return null;
+		}
+		String regionType = region.getType();
+		if (regionType == DOMRegionContext.XML_TAG_NAME) {
+			result = computeTagNameHelp((IDOMNode) treeNode, parentNode, flatNode, region);
+		}
+		else if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) {
+			result = computeTagAttNameHelp((IDOMNode) treeNode, parentNode, flatNode, region);
+		}
+		else if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
+			result = computeTagAttValueHelp((IDOMNode) treeNode, parentNode, flatNode, region);
+		}
+		return result;
+	}
+
+	/**
+	 * Computes the hover help for the attribute name
+	 */
+	protected String computeTagAttNameHelp(IDOMNode xmlnode, IDOMNode parentNode, IStructuredDocumentRegion flatNode, ITextRegion region) {
+		CMElementDeclaration elementDecl = getCMElementDeclaration(xmlnode);
+		String attName = flatNode.getText(region);
+		CMAttributeDeclaration attDecl = getCMAttributeDeclaration(xmlnode, elementDecl, attName);
+		return getAdditionalInfo(elementDecl, attDecl);
+	}
+
+	/**
+	 * Computes the hover help for the attribute value (this is the same as
+	 * the attribute name's help)
+	 */
+	protected String computeTagAttValueHelp(IDOMNode xmlnode, IDOMNode parentNode, IStructuredDocumentRegion flatNode, ITextRegion region) {
+		CMElementDeclaration elementDecl = getCMElementDeclaration(xmlnode);
+		ITextRegion attrNameRegion = getAttrNameRegion(xmlnode, region);
+
+		String attName = flatNode.getText(attrNameRegion);
+		CMAttributeDeclaration attDecl = getCMAttributeDeclaration(xmlnode, elementDecl, attName);
+		return getAdditionalInfo(elementDecl, attDecl);
+	}
+
+	/**
+	 * Computes the hover help for the tag name
+	 */
+	protected String computeTagNameHelp(IDOMNode xmlnode, IDOMNode parentNode, IStructuredDocumentRegion flatNode, ITextRegion region) {
+		CMElementDeclaration elementDecl = getCMElementDeclaration(xmlnode);
+		CMElementDeclaration pelementDecl = getCMElementDeclaration(parentNode);
+		return getAdditionalInfo(pelementDecl, elementDecl);
+	}
+
+	/**
+	 * Retreives cmnode's documentation to display in the hover help popup. If
+	 * no documentation exists for cmnode, try displaying parentOrOwner's
+	 * documentation
+	 * 
+	 * @return String any documentation information to display for cmnode.
+	 *         <code>null</code> if there is nothing to display.
+	 */
+	protected String getAdditionalInfo(CMNode parentOrOwner, CMNode cmnode) {
+		String addlInfo = null;
+
+		if (cmnode == null) {
+			if (Debug.displayWarnings) {
+				new IllegalArgumentException("Null declaration!").printStackTrace(); //$NON-NLS-1$
+			}
+			return null;
+		}
+
+		addlInfo = getInfoProvider().getInfo(cmnode);
+		if ((addlInfo == null) && (parentOrOwner != null)) {
+			addlInfo = getInfoProvider().getInfo(parentOrOwner);
+		}
+		return addlInfo;
+	}
+
+	/**
+	 * Find the region of the attribute name for the given attribute value
+	 * region
+	 * 
+	 */
+	protected ITextRegion getAttrNameRegion(IDOMNode node, ITextRegion region) {
+		// Find the attribute name for which this position should have a value
+		IStructuredDocumentRegion open = node.getFirstStructuredDocumentRegion();
+		ITextRegionList openRegions = open.getRegions();
+		int i = openRegions.indexOf(region);
+		if (i < 0) {
+			return null;
+		}
+		ITextRegion nameRegion = null;
+		while (i >= 0) {
+			nameRegion = openRegions.get(i--);
+			if (nameRegion.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) {
+				break;
+			}
+		}
+		return nameRegion;
+	}
+
+	/**
+	 * Retreives CMAttributeDeclaration indicated by attribute name within
+	 * elementDecl
+	 */
+	protected CMAttributeDeclaration getCMAttributeDeclaration(IDOMNode node, CMElementDeclaration elementDecl, String attName) {
+		CMAttributeDeclaration attrDecl = null;
+
+		if (elementDecl != null) {
+			CMNamedNodeMap attributes = elementDecl.getAttributes();
+			
+			CMNamedNodeMapImpl allAttributes = new CMNamedNodeMapImpl(attributes);
+			List nodes = ModelQueryUtil.getModelQuery(node.getOwnerDocument()).getAvailableContent((Element) node, elementDecl, ModelQuery.INCLUDE_ATTRIBUTES);
+			for (int k = 0; k < nodes.size(); k++) {
+				CMNode cmnode = (CMNode) nodes.get(k);
+				if (cmnode.getNodeType() == CMNode.ATTRIBUTE_DECLARATION) {
+					allAttributes.put(cmnode);
+				}
+			}
+			attributes = allAttributes;
+
+			String noprefixName = DOMNamespaceHelper.getUnprefixedName(attName);
+			if (attributes != null) {
+				attrDecl = (CMAttributeDeclaration) attributes.getNamedItem(noprefixName);
+				if (attrDecl == null) {
+					attrDecl = (CMAttributeDeclaration) attributes.getNamedItem(attName);
+				}
+			}
+		}
+		return attrDecl;
+	}
+
+	/**
+	 * Retreives CMElementDeclaration for given node
+	 * 
+	 * @return CMElementDeclaration - CMElementDeclaration of node or
+	 *         <code>null</code> if not possible
+	 */
+	protected CMElementDeclaration getCMElementDeclaration(Node node) {
+		CMElementDeclaration result = null;
+		if (node.getNodeType() == Node.ELEMENT_NODE) {
+			ModelQuery modelQuery = ModelQueryUtil.getModelQuery(node.getOwnerDocument());
+			if (modelQuery != null) {
+				result = modelQuery.getCMElementDeclaration((Element) node);
+			}
+		}
+		return result;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.ITextHover#getHoverInfo(org.eclipse.jface.text.ITextViewer,
+	 *      org.eclipse.jface.text.IRegion)
+	 */
+	public String getHoverInfo(ITextViewer viewer, IRegion hoverRegion) {
+		if ((hoverRegion == null) || (viewer == null) || (viewer.getDocument() == null)) {
+			return null;
+		}
+
+		String displayText = null;
+		int documentOffset = hoverRegion.getOffset();
+		displayText = computeHoverHelp(viewer, documentOffset);
+
+		return displayText;
+	}
+
+	/**
+	 * Returns the region to hover the text over based on the offset.
+	 * 
+	 * @param textViewer
+	 * @param offset
+	 * 
+	 * @return IRegion region to hover over if offset is within tag name,
+	 *         attribute name, or attribute value and if offset is not over
+	 *         invalid whitespace. otherwise, returns <code>null</code>
+	 * 
+	 * @see org.eclipse.jface.text.ITextHover#getHoverRegion(ITextViewer, int)
+	 */
+	public IRegion getHoverRegion(ITextViewer textViewer, int offset) {
+		if ((textViewer == null) || (textViewer.getDocument() == null)) {
+			return null;
+		}
+
+		IStructuredDocumentRegion flatNode = ((IStructuredDocument) textViewer.getDocument()).getRegionAtCharacterOffset(offset);
+		ITextRegion region = null;
+
+		if (flatNode != null) {
+			region = flatNode.getRegionAtCharacterOffset(offset);
+		}
+
+		if (region != null) {
+			// only supply hoverhelp for tag name, attribute name, or
+			// attribute value
+			String regionType = region.getType();
+			if ((regionType == DOMRegionContext.XML_TAG_NAME) || (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) || (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE)) {
+				try {
+					// check if we are at whitespace before or after line
+					IRegion line = textViewer.getDocument().getLineInformationOfOffset(offset);
+					if ((offset > (line.getOffset())) && (offset < (line.getOffset() + line.getLength()))) {
+						// check if we are in region's trailing whitespace
+						// (whitespace after relevant info)
+						if (offset < flatNode.getTextEndOffset(region)) {
+							return new Region(flatNode.getStartOffset(region), region.getTextLength());
+						}
+					}
+				}
+				catch (BadLocationException e) {
+					Logger.logException(e);
+				}
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * @deprecated if enabled flag is false, dont call getHoverRegion in the
+	 *             first place if true, use getHoverRegion(ITextViewer, int)
+	 */
+	public IRegion getHoverRegion(ITextViewer textViewer, int offset, boolean enabled) {
+		if ((!enabled) || (textViewer == null) || (textViewer.getDocument() == null)) {
+			return null;
+		}
+
+		IStructuredDocumentRegion flatNode = ((IStructuredDocument) textViewer.getDocument()).getRegionAtCharacterOffset(offset);
+		ITextRegion region = null;
+
+		if (flatNode != null) {
+			region = flatNode.getRegionAtCharacterOffset(offset);
+		}
+
+		if (region != null) {
+			// only supply hoverhelp for tag name, attribute name, or
+			// attribute value
+			String regionType = region.getType();
+			if ((regionType == DOMRegionContext.XML_TAG_NAME) || (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) || (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE)) {
+				try {
+					// check if we are at whitespace before or after line
+					IRegion line = textViewer.getDocument().getLineInformationOfOffset(offset);
+					if ((offset > (line.getOffset())) && (offset < (line.getOffset() + line.getLength()))) {
+						// check if we are in region's trailing whitespace
+						// (whitespace after relevant info)
+						if (offset < flatNode.getTextEndOffset(region)) {
+							return new Region(flatNode.getStartOffset(region), region.getTextLength());
+						}
+					}
+				}
+				catch (BadLocationException e) {
+					Logger.logException(e);
+				}
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * Gets the infoProvider.
+	 * 
+	 * @return Returns fInfoProvider and if fInfoProvider was
+	 *         <code>null</code> set fInfoProvider to DefaultInfoProvider
+	 */
+	public MarkupTagInfoProvider getInfoProvider() {
+		if (fInfoProvider == null) {
+			fInfoProvider = new MarkupTagInfoProvider();
+		}
+		return fInfoProvider;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/templates/EncodingTemplateVariableResolverXML.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/templates/EncodingTemplateVariableResolverXML.java
new file mode 100644
index 0000000..079b042
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/templates/EncodingTemplateVariableResolverXML.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.templates;
+
+import org.eclipse.jface.text.templates.SimpleTemplateVariableResolver;
+import org.eclipse.jface.text.templates.TemplateContext;
+import org.eclipse.wst.sse.core.internal.encoding.CommonEncodingPreferenceNames;
+import org.eclipse.wst.xml.core.internal.XMLCorePlugin;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+
+
+public class EncodingTemplateVariableResolverXML extends SimpleTemplateVariableResolver {
+	private static final String ENCODING_TYPE = getEncodingType();
+
+	private static String getEncodingType() {
+		return "encoding"; //$NON-NLS-1$
+	}
+
+	/**
+	 * Creates a new encoding variable
+	 */
+	public EncodingTemplateVariableResolverXML() {
+		super(ENCODING_TYPE, XMLUIMessages.Creating_files_encoding);
+	}
+
+	protected String resolve(TemplateContext context) {
+		return XMLCorePlugin.getDefault().getPluginPreferences().getString(CommonEncodingPreferenceNames.OUTPUT_CODESET);
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/templates/TemplateContextTypeIdsXML.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/templates/TemplateContextTypeIdsXML.java
new file mode 100644
index 0000000..f7993e2
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/templates/TemplateContextTypeIdsXML.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.templates;
+
+public class TemplateContextTypeIdsXML {
+
+	public static final String ALL = getAll();
+
+	public static final String ATTRIBUTE = getAttribute();
+
+	public static final String ATTRIBUTE_VALUE = getAttributeValue();
+
+	public static final String NEW = getNew();
+
+	public static final String TAG = getTag();
+
+	private static String getAll() {
+		return getPrefix() + "_all"; //$NON-NLS-1$
+	}
+
+	private static String getAttribute() {
+		return getPrefix() + "_attribute"; //$NON-NLS-1$
+	}
+
+	private static String getAttributeValue() {
+		return getPrefix() + "_attribute_value"; //$NON-NLS-1$
+	}
+
+	private static String getNew() {
+		return getPrefix() + "_new"; //$NON-NLS-1$
+	}
+
+	private static String getPrefix() {
+		return "xml"; //$NON-NLS-1$
+	}
+
+	private static String getTag() {
+		return getPrefix() + "_tag"; //$NON-NLS-1$
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/templates/TemplateContextTypeXML.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/templates/TemplateContextTypeXML.java
new file mode 100644
index 0000000..43ccf20
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/templates/TemplateContextTypeXML.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.templates;
+
+import org.eclipse.jface.text.templates.GlobalTemplateVariables;
+import org.eclipse.jface.text.templates.TemplateContextType;
+
+/**
+ * Base class for XML template context types. Templates of this context type
+ * apply to any place within XML content type.
+ */
+public class TemplateContextTypeXML extends TemplateContextType {
+
+	public TemplateContextTypeXML() {
+		super();
+		addResolver(new GlobalTemplateVariables.Cursor());
+		addResolver(new GlobalTemplateVariables.Date());
+		addResolver(new GlobalTemplateVariables.Dollar());
+		addResolver(new GlobalTemplateVariables.LineSelection());
+		addResolver(new GlobalTemplateVariables.Time());
+		addResolver(new GlobalTemplateVariables.User());
+		addResolver(new GlobalTemplateVariables.WordSelection());
+		addResolver(new GlobalTemplateVariables.Year());
+		addResolver(new EncodingTemplateVariableResolverXML());
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/text/CharacterPairInserter.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/text/CharacterPairInserter.java
new file mode 100644
index 0000000..2f61324
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/text/CharacterPairInserter.java
@@ -0,0 +1,106 @@
+/*******************************************************************************

+ * Copyright (c) 2009, 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

+ *******************************************************************************/

+package org.eclipse.wst.xml.ui.internal.text;

+

+import org.eclipse.jface.preference.IPreferenceStore;

+import org.eclipse.jface.text.IDocument;

+import org.eclipse.jface.text.source.ISourceViewer;

+import org.eclipse.jface.util.IPropertyChangeListener;

+import org.eclipse.jface.util.PropertyChangeEvent;

+import org.eclipse.swt.graphics.Point;

+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.ui.typing.AbstractCharacterPairInserter;

+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;

+import org.eclipse.wst.xml.ui.internal.XMLUIPlugin;

+import org.eclipse.wst.xml.ui.internal.preferences.XMLUIPreferenceNames;

+

+public class CharacterPairInserter extends AbstractCharacterPairInserter implements IPropertyChangeListener {

+

+	// preferences

+	private boolean fCloseStrings = true;

+	private boolean fCloseBrackets = true;

+

+	protected boolean shouldPair(ISourceViewer viewer, char c) {

+		switch (c) {

+			case '\'':

+			case '"':

+				return fCloseStrings ? checkRegion(viewer) : false;

+			default:

+				return fCloseBrackets;

+		}

+	}

+

+	/**

+	 * Checks if the region should support paired quotes

+	 * @param viewer the viewer

+	 * @return true if the region is not in an XML attribute value

+	 */

+	private boolean checkRegion(ISourceViewer viewer) {

+		IDocument doc = viewer.getDocument();

+		final Point selection= viewer.getSelectedRange();

+		final int offset= selection.x;

+

+		if (doc instanceof IStructuredDocument) {

+			IStructuredDocumentRegion[] regions = ((IStructuredDocument) doc).getStructuredDocumentRegions(offset, 0);

+			if (regions != null && regions.length > 0) {

+				ITextRegion region = regions[0].getRegionAtCharacterOffset(offset);

+				return region != null && region.getType() != DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE;

+			}

+		}

+		return true;

+	}

+

+	public boolean hasPair(char c) {

+		switch (c) {

+			case '"':

+			case '\'':

+			case '[':

+			case '(':

+				return true;

+			default:

+				return false;

+		}

+	}

+

+	protected char getPair(char c) {

+		switch (c) {

+			case '\'':

+			case '"':

+				return c;

+			case '(':

+				return ')';

+			case '[':

+				return ']';

+			default:

+				throw new IllegalArgumentException();

+		}

+	}

+

+	public void initialize() {

+		IPreferenceStore store = XMLUIPlugin.getInstance().getPreferenceStore();

+		fCloseStrings = store.getBoolean(XMLUIPreferenceNames.TYPING_CLOSE_STRINGS);

+		fCloseBrackets = store.getBoolean(XMLUIPreferenceNames.TYPING_CLOSE_BRACKETS);

+		store.addPropertyChangeListener(this);

+	}

+

+	public void dispose() {

+		XMLUIPlugin.getInstance().getPreferenceStore().removePropertyChangeListener(this);

+	}

+

+	public void propertyChange(PropertyChangeEvent event) {

+		if (XMLUIPreferenceNames.TYPING_CLOSE_BRACKETS.equals(event.getProperty()))

+			fCloseBrackets = ((Boolean) event.getNewValue()).booleanValue();

+		else if (XMLUIPreferenceNames.TYPING_CLOSE_STRINGS.equals(event.getProperty()))

+			fCloseStrings = ((Boolean) event.getNewValue()).booleanValue();

+	}

+}

diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/text/XMLDocumentRegionEdgeMatcher.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/text/XMLDocumentRegionEdgeMatcher.java
new file mode 100644
index 0000000..b29fd9b
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/text/XMLDocumentRegionEdgeMatcher.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2008 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.text;
+
+import org.eclipse.jface.text.source.DefaultCharacterPairMatcher;
+import org.eclipse.wst.sse.ui.internal.text.DocumentRegionEdgeMatcher;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+
+
+public class XMLDocumentRegionEdgeMatcher extends DocumentRegionEdgeMatcher {
+
+	private static final char[] PAIRS = {'{', '}', '(', ')', '[', ']','"','"','\'','\''};
+
+	public XMLDocumentRegionEdgeMatcher() {
+		super(new String[]{DOMRegionContext.XML_TAG_NAME, DOMRegionContext.XML_COMMENT_TEXT, DOMRegionContext.XML_CDATA_TEXT, DOMRegionContext.XML_PI_OPEN, DOMRegionContext.XML_PI_CONTENT}, new DefaultCharacterPairMatcher(PAIRS));
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/util/SharedXMLEditorPluginImageHelper.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/util/SharedXMLEditorPluginImageHelper.java
new file mode 100644
index 0000000..9981244
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/util/SharedXMLEditorPluginImageHelper.java
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.util;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImageHelper;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImages;
+
+
+public class SharedXMLEditorPluginImageHelper {
+	public static final String IMG_DTOOL_CONSTRAINOFF = XMLEditorPluginImages.IMG_DTOOL_CONSTRAINOFF;
+	public static final String IMG_DTOOL_CONSTRAINON = XMLEditorPluginImages.IMG_DTOOL_CONSTRAINON;
+	public static final String IMG_DTOOL_RLDGRMR = XMLEditorPluginImages.IMG_DTOOL_RLDGRMR;
+	public static final String IMG_DTOOL_VALIDATE = XMLEditorPluginImages.IMG_DTOOL_VALIDATE;
+	public static final String IMG_ETOOL_CONSTRAINOFF = XMLEditorPluginImages.IMG_ETOOL_CONSTRAINOFF;
+	public static final String IMG_ETOOL_CONSTRAINON = XMLEditorPluginImages.IMG_ETOOL_CONSTRAINON;
+	public static final String IMG_ETOOL_RLDGRMR = XMLEditorPluginImages.IMG_ETOOL_RLDGRMR;
+	public static final String IMG_ETOOL_VALIDATE = XMLEditorPluginImages.IMG_ETOOL_VALIDATE;
+	public static final String IMG_OBJ_ATTRIBUTE = XMLEditorPluginImages.IMG_OBJ_ATTRIBUTE;
+	public static final String IMG_OBJ_CDATASECTION = XMLEditorPluginImages.IMG_OBJ_CDATASECTION;
+	public static final String IMG_OBJ_COMMENT = XMLEditorPluginImages.IMG_OBJ_COMMENT;
+	public static final String IMG_OBJ_DOCTYPE = XMLEditorPluginImages.IMG_OBJ_DOCTYPE;
+	public static final String IMG_OBJ_ELEMENT = XMLEditorPluginImages.IMG_OBJ_ELEMENT;
+	public static final String IMG_OBJ_ENTITY = XMLEditorPluginImages.IMG_OBJ_ENTITY;
+	public static final String IMG_OBJ_ENTITY_REFERENCE = XMLEditorPluginImages.IMG_OBJ_ENTITY_REFERENCE;
+	public static final String IMG_OBJ_NOTATION = XMLEditorPluginImages.IMG_OBJ_NOTATION;
+	public static final String IMG_OBJ_PROCESSINGINSTRUCTION = XMLEditorPluginImages.IMG_OBJ_PROCESSINGINSTRUCTION;
+	public static final String IMG_OBJ_TAG_GENERIC = XMLEditorPluginImages.IMG_OBJ_TAG_GENERIC;
+	public static final String IMG_OBJ_TAG_MACRO = XMLEditorPluginImages.IMG_OBJ_TAG_MACRO;
+	public static final String IMG_OBJ_TXTEXT = XMLEditorPluginImages.IMG_OBJ_TXTEXT;
+
+	/**
+	 * Retrieves the specified image from the xml source editor plugin's image
+	 * registry. Note: The returned <code>Image</code> is managed by the
+	 * workbench; clients must <b>not </b> dispose of the returned image.
+	 * 
+	 * @param symbolicName
+	 *            the symbolic name of the image; there are constants declared
+	 *            in this class for build-in images that come with the xml
+	 *            source editor
+	 * @return the image, or <code>null</code> if not found
+	 */
+	public static Image getImage(String symbolicName) {
+		return XMLEditorPluginImageHelper.getInstance().getImage(symbolicName);
+	}
+
+	/**
+	 * Retrieves the image descriptor for specified image from the xml source
+	 * editor plugin's image registry. Unlike <code>Image</code>s, image
+	 * descriptors themselves do not need to be disposed.
+	 * 
+	 * @param symbolicName
+	 *            the symbolic name of the image; there are constants declared
+	 *            in this interface for build-in images that come with the xml
+	 *            source editor
+	 * @return the image descriptor, or <code>null</code> if not found
+	 */
+	public static ImageDescriptor getImageDescriptor(String symbolicName) {
+		return XMLEditorPluginImageHelper.getInstance().getImageDescriptor(symbolicName);
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/util/XMLCommonResources.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/util/XMLCommonResources.java
new file mode 100644
index 0000000..a3ba0bb
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/util/XMLCommonResources.java
@@ -0,0 +1,95 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.util;
+
+import java.text.MessageFormat;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.eclipse.wst.xml.ui.internal.XMLUIPlugin;
+
+/**
+ * @deprecated use XMLUIPlugin.getResourceString() instead
+ */
+/**
+ * This class exists temporarily until the properties files can be
+ * re-organized and the various resource references can be updated
+ */
+public class XMLCommonResources {
+	protected static XMLCommonResources instance;
+
+	public synchronized static XMLCommonResources getInstance() {
+		if (instance == null) {
+			instance = new XMLCommonResources(XMLUIPlugin.getDefault());
+		}
+		return instance;
+	}
+
+	private XMLUIPlugin editorPlugin;
+
+	private ResourceBundle resourceBundle;
+
+	public XMLCommonResources(XMLUIPlugin editorPlugin) {
+		instance = this;
+		this.editorPlugin = editorPlugin;
+		try {
+			resourceBundle = ResourceBundle.getBundle("org.eclipse.wst.xml.ui.internal.XMLUIPluginResources"); //$NON-NLS-1$
+		}
+		catch (MissingResourceException exception) {
+			// TODO... log an error message
+			// B2BUtilPlugin.getPlugin().getMsgLogger().write(B2BUtilPlugin.getGUIString("_WARN_PLUGIN_PROPERTIES_MISSING")
+			// + descriptor.getLabel());
+			resourceBundle = null;
+		}
+	}
+
+	ImageDescriptor _getImageDescriptor(String iconName) {
+		return AbstractUIPlugin.imageDescriptorFromPlugin(XMLUIPlugin.ID, iconName);
+	}
+
+
+	public ResourceBundle getResourceBundle() {
+		return resourceBundle;
+	}
+
+	/**
+	 * This gets the string resource.
+	 */
+	public String getString(String key) {
+		return getResourceBundle().getString(key);
+	}
+
+	/**
+	 * This gets the string resource and does one substitution.
+	 */
+	public String getString(String key, Object s1) {
+		return MessageFormat.format(getString(key), new Object[]{s1});
+	}
+
+	/**
+	 * This gets the string resource and does two substitutions.
+	 */
+	public String getString(String key, Object s1, Object s2) {
+		return MessageFormat.format(getString(key), new Object[]{s1, s2});
+	}
+
+	public IWorkbench getWorkbench() {
+		return editorPlugin.getWorkbench();
+	}
+	/*
+	 * public ImageFactory getImageFactory() { return imageFactory; }
+	 */
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/util/XMLCommonUIContextIds.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/util/XMLCommonUIContextIds.java
new file mode 100644
index 0000000..763d502
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/util/XMLCommonUIContextIds.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+
+
+package org.eclipse.wst.xml.ui.internal.util;
+
+/**
+ * Context help id constants.
+ */
+public interface XMLCommonUIContextIds {
+	public static final String PLUGIN_NAME = "org.eclipse.wst.xml.ui"; //$NON-NLS-1$
+
+	/* CONTEXT_ID xcui0500 for Edit Attribute Instruction Dialog */
+	public static final String XCUI_ATTRIBUTE_DIALOG = PLUGIN_NAME + ".xcui0500"; //$NON-NLS-1$
+
+	/* CONTEXT_ID xcui0400 for Select XML Catalog ID Dialog */
+	public static final String XCUI_CATALOG_DIALOG = PLUGIN_NAME + ".xcui0400"; //$NON-NLS-1$
+
+	/* CONTEXT_IDs for XML Common UI use xcuixxx context IDs */
+
+	/* CONTEXT_ID xcui0010 for Edit Doctype Dialog */
+	public static final String XCUI_DOCTYPE_DIALOG = PLUGIN_NAME + ".xcui0010"; //$NON-NLS-1$
+	/* CONTEXT_ID xcui0030 for Public ID Text Edit */
+	public static final String XCUI_DOCTYPE_PUBLIC = PLUGIN_NAME + ".xcui0030"; //$NON-NLS-1$
+	/* CONTEXT_ID xcui0020 for Root Element Name Text Edit */
+	public static final String XCUI_DOCTYPE_ROOT = PLUGIN_NAME + ".xcui0020"; //$NON-NLS-1$
+	/* CONTEXT_ID xcui0040 for System ID Text Edit */
+	public static final String XCUI_DOCTYPE_SYSTEM = PLUGIN_NAME + ".xcui0050"; //$NON-NLS-1$
+
+	/* CONTEXT_ID xcui0300 for Edit Element Instruction Dialog */
+	public static final String XCUI_ELEMENT_DIALOG = PLUGIN_NAME + ".xcui0600"; //$NON-NLS-1$
+
+	/* CONTEXT_ID xcui0200 for Edit Namespace Dialog */
+	public static final String XCUI_NAMESPACE_DIALOG = PLUGIN_NAME + ".xcui0200"; //$NON-NLS-1$
+
+	/* CONTEXT_ID xcui0300 for Edit Processing Instruction Dialog */
+	public static final String XCUI_PROCESSING_DIALOG = PLUGIN_NAME + ".xcui0300"; //$NON-NLS-1$
+
+	/* CONTEXT_ID xcui0100 for Edit Schema Information Dialog */
+	public static final String XCUI_SCHEMA_INFO_DIALOG = PLUGIN_NAME + ".xcui0100"; //$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/validation/DelegatingSourceValidator.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/validation/DelegatingSourceValidator.java
new file mode 100644
index 0000000..9a2c070
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/validation/DelegatingSourceValidator.java
@@ -0,0 +1,654 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 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
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.validation;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.quickassist.IQuickAssistProcessor;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.IModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
+import org.eclipse.wst.sse.ui.internal.reconcile.validator.AnnotationInfo;
+import org.eclipse.wst.sse.ui.internal.reconcile.validator.IncrementalReporter;
+import org.eclipse.wst.validation.internal.core.IMessageAccess;
+import org.eclipse.wst.validation.internal.core.ValidationException;
+import org.eclipse.wst.validation.internal.provisional.core.IMessage;
+import org.eclipse.wst.validation.internal.provisional.core.IProjectValidationContext;
+import org.eclipse.wst.validation.internal.provisional.core.IReporter;
+import org.eclipse.wst.validation.internal.provisional.core.IValidationContext;
+import org.eclipse.wst.validation.internal.provisional.core.IValidator;
+import org.eclipse.wst.validation.internal.provisional.core.IValidatorJob;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMAttr;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
+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.provisional.document.IDOMText;
+import org.eclipse.wst.xml.core.internal.validation.AnnotationMsg;
+import org.eclipse.wst.xml.ui.internal.Logger;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * A DelegatingReconcileValidator calls its delegate validator to get a list
+ * of validation error IMessages. Using information in this IMessage the
+ * DelegatingReconcileValidator updates the IMessage with an offset and length
+ * to give a good range to be "squiggled" and adds the messages to the
+ * IReporter
+ * 
+ * @author Mark Hutchinson
+ * 
+ */
+public abstract class DelegatingSourceValidator implements IValidator {
+	// the selection strategies:
+	protected static final String ALL_ATTRIBUTES = "ALL_ATTRIBUTES"; //$NON-NLS-1$
+	protected static final String ATTRIBUTE_NAME = "ATTRIBUTE_NAME"; //$NON-NLS-1$
+	protected static final String ATTRIBUTE_VALUE = "ATTRIBUTE_VALUE"; //$NON-NLS-1$
+	protected static final String START_TAG = "START_TAG"; //$NON-NLS-1$
+	protected static final String TEXT = "TEXT"; //$NON-NLS-1$
+	protected static final String FIRST_NON_WHITESPACE_TEXT = "FIRST_NON_WHITESPACE_TEXT"; //$NON-NLS-1$
+	protected static final String TEXT_ENTITY_REFERENCE = "TEXT_ENTITY_REFERENCE"; //$NON-NLS-1$
+	protected static final String VALUE_OF_ATTRIBUTE_WITH_GIVEN_VALUE = "VALUE_OF_ATTRIBUTE_WITH_GIVEN_VALUE"; //$NON-NLS-1$
+	protected static final String END_TAG = "END_TAG"; //$NON-NLS-1$
+	private static final String QUICKASSISTPROCESSOR = IQuickAssistProcessor.class.getName();
+	
+
+
+	/**
+	 * This constant specifies the attribute name that specifies the side of
+	 * the 'start tag' that the validator has used to report an error. A
+	 * validator may choose to report a message at the left (the start of the
+	 * start tag)or at the right (the end of the start tag). When this
+	 * attribute is not specified error ERROR_SIDE_LEFT is the default.
+	 */
+	protected static final String ERROR_SIDE = "ERROR_SIDE"; //$NON-NLS-1$
+
+	/**
+	 * When the ERROR_SIDE attribute specifies the ERROR_SIDE_LEFT value it is
+	 * assumed that the message specifies a location to the left of the start
+	 * tag
+	 */
+	protected static final String ERROR_SIDE_LEFT = "ERROR_SIDE_LEFT"; //$NON-NLS-1$	
+
+	/**
+	 * When the ERROR_SIDE attribute specifies the ERROR_SIDE_RIGHT value it
+	 * is assumed that the message specifies a location to the right of the
+	 * start tag
+	 */
+	protected static final String ERROR_SIDE_RIGHT = "ERROR_SIDE_RIGHT"; //$NON-NLS-1$	
+
+	protected static final String COLUMN_NUMBER_ATTRIBUTE = "columnNumber"; //$NON-NLS-1$
+	protected static final String SQUIGGLE_SELECTION_STRATEGY_ATTRIBUTE = "squiggleSelectionStrategy"; //$NON-NLS-1$
+	protected static final String SQUIGGLE_NAME_OR_VALUE_ATTRIBUTE = "squiggleNameOrValue"; //$NON-NLS-1$
+
+	public DelegatingSourceValidator() {
+		super(); // constructor
+	}
+
+	public void cleanup(IReporter arg0) { // don't need to implement
+	}
+
+	// My Implementation of IHelper
+	class MyHelper implements IProjectValidationContext {
+		InputStream inputStream;
+
+		IFile file;
+
+		public MyHelper(InputStream inputStream, IFile file) {
+			this.inputStream = inputStream;
+			this.file = file;
+		}
+
+		public int getBuildKind() {
+			return 0;
+		}
+
+		public Object loadModel(String symbolicName, Object[] parms) {
+			if (symbolicName.equals("getFile")) { //$NON-NLS-1$
+				return file;
+			}
+			return null;
+		}
+
+		public Object loadModel(String symbolicName) {
+			if (symbolicName.equals("inputStream")) { //$NON-NLS-1$
+				return inputStream;
+			}
+			return null;
+		}
+
+		public String[] getURIs() {
+			if (file != null) {
+				return new String[]{file.getFullPath().toString()};
+			}
+			return new String[0];
+		}
+
+		public IProject getProject() {
+			if (file != null) {
+				return file.getProject();
+			}
+			return null;
+		}
+	}
+
+	// My Implementation of IReporter
+	class MyReporter implements IReporter {
+		List list = new ArrayList();
+
+		public MyReporter() {
+			super();
+		}
+
+		public void addMessage(IValidator origin, IMessage message) {
+			list.add(message);
+		}
+
+		public void displaySubtask(IValidator validator, IMessage message) {
+			/* do not need to implement */
+		}
+
+		public IMessageAccess getMessageAccess() {
+			return null;
+		}
+
+		public boolean isCancelled() {
+			return false;
+		}
+
+		public void removeAllMessages(IValidator origin, Object object) { // do
+			/* do not need to implement */
+		}
+
+		public void removeAllMessages(IValidator origin) {
+			/* do not need to implement */
+		}
+
+		public void removeMessageSubset(IValidator validator, Object obj, String groupName) {// do
+			/* do not need to implement */
+		}
+
+		public List getMessages() {
+			return list;
+		}
+	}
+
+	protected abstract IValidator getDelegateValidator();
+
+	/**
+	 * Calls a delegate validator getting and updates it's list of
+	 * ValidationMessages with a good squiggle offset and length.
+	 * 
+	 * @param helper
+	 *            loads an object.
+	 * @param reporter
+	 *            Is an instance of an IReporter interface, which is used for
+	 *            interaction with the user.
+	 */
+	public void validate(IValidationContext helper, IReporter reporter) throws ValidationException {
+		String[] delta = helper.getURIs();
+		if (delta.length > 0) {
+			// get the file, model and document:
+			IFile file = getFile(delta[0]);
+			IDOMModel xmlModel = null;
+			if (file != null)
+				xmlModel = getModelForResource(file);
+			// some problem occurred, abort
+			if (xmlModel == null)
+				return;
+			
+			try {
+				IDOMDocument document = xmlModel.getDocument();
+
+				// store the text in a byte array; make a full copy to ease
+				// any threading problems
+				byte[] byteArray;
+				try {
+					byteArray = xmlModel.getStructuredDocument().get().getBytes("UTF-8");
+				}
+				catch (UnsupportedEncodingException e) {
+					// Not likely to happen
+					byteArray = xmlModel.getStructuredDocument().get().getBytes();
+				}
+
+				if (isDelegateValidatorEnabled(file)) {
+					IValidator validator = getDelegateValidator();
+					if (validator != null) {
+						// Validate the file:
+						IValidationContext vHelper = new MyHelper(new ByteArrayInputStream(byteArray), file);
+						MyReporter vReporter = new MyReporter();
+						if (validator instanceof IValidatorJob) {
+							((IValidatorJob) validator).validateInJob(vHelper, vReporter);
+						}
+						else {
+							validator.validate(vHelper, vReporter);
+						}
+						List messages = vReporter.list;
+
+						// set the offset and length
+						updateValidationMessages(messages, document, reporter);
+					}
+				}
+			}
+
+
+			finally {
+				if (xmlModel != null) {
+					xmlModel.releaseFromRead();
+				}
+			}
+		}
+	}
+
+	/**
+	 * iterates through the messages and calculates a "better" offset and
+	 * length
+	 * 
+	 * @param messages -
+	 *            a List of IMessages
+	 * @param document -
+	 *            the document
+	 * @param reporter -
+	 *            the reporter the messages are to be added to
+	 */
+	protected void updateValidationMessages(List messages, IDOMDocument document, IReporter reporter) {
+		for (int i = 0; i < messages.size(); i++) {
+			IMessage message = (IMessage) messages.get(i);
+			try {
+				if (message.getAttribute(COLUMN_NUMBER_ATTRIBUTE) != null) {
+					int column = ((Integer) message.getAttribute(COLUMN_NUMBER_ATTRIBUTE)).intValue();
+					if (message.getAttribute(AnnotationMsg.PROBMLEM_ID) != null && reporter instanceof IncrementalReporter){
+						Integer problemId = (Integer)message.getAttribute(AnnotationMsg.PROBMLEM_ID);
+						MarkupQuickAssistProcessor processor = new MarkupQuickAssistProcessor();
+						processor.setProblemId(problemId.intValue());
+						message.setOffset(column);
+						Integer length = (Integer) message.getAttribute(AnnotationMsg.LENGTH);
+						message.setLength( length.intValue());
+						Object attrValue = message.getAttribute(AnnotationMsg.ATTRVALUETEXT);
+						if (attrValue != null)
+							processor.setAdditionalFixInfo(attrValue);
+						else{
+							Object attrValueNo = message.getAttribute(AnnotationMsg.ATTRVALUENO);
+							if (attrValueNo != null){
+								int len = ((Integer)attrValueNo).intValue();
+								Object[] objArray = new Object[len];
+								for ( int j=0; j<len; j++){
+									objArray[j] = message.getAttribute(AnnotationMsg.ATTRNO + j);
+								}
+								processor.setAdditionalFixInfo(objArray);
+							}
+							
+						}
+						message.setAttribute(QUICKASSISTPROCESSOR, processor);
+						AnnotationInfo info = new AnnotationInfo(message);
+						((IncrementalReporter) reporter).addAnnotationInfo(this, info);
+					}
+					else  {
+						String selectionStrategy = (String) message.getAttribute(SQUIGGLE_SELECTION_STRATEGY_ATTRIBUTE);
+						String nameOrValue = (String) message.getAttribute(SQUIGGLE_NAME_OR_VALUE_ATTRIBUTE);
+
+						// convert the line and Column numbers to an offset:
+						int start = document.getStructuredDocument().getLineOffset(message.getLineNumber() - 1) + column - 1;
+						int[] result = computeStartAndEndLocation(start, selectionStrategy, getErrorSide(message), nameOrValue, document);
+						if (result != null) {
+							message.setOffset(result[0]);
+							message.setLength(result[1] - result[0]);
+						
+							reporter.addMessage(this, message);
+						}
+					}
+					}
+				
+			}
+			catch (BadLocationException e) { // this exception should not
+				// occur - it is thrown if
+				// trying to convert an
+				// invalid line number to and
+				// offset
+			}
+
+		}
+	}
+
+	/**
+	 * @param delta
+	 *            the IFileDelta containing the file name to get
+	 * @return the IFile
+	 */
+	public IFile getFile(String delta) {
+		IPath path = new Path(delta);
+		if (path.segmentCount() > 1) {
+		  IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(path);
+		  if (file != null && file.exists())
+		    return file;
+		}
+		return null;
+	}
+
+	/**
+	 * 
+	 * @param file
+	 *            the file to get the model for
+	 * @return the file's XMLModel or null
+	 */
+	protected IDOMModel getModelForResource(IFile file) {
+		IStructuredModel model = null;
+		IModelManager manager = StructuredModelManager.getModelManager();
+
+		try {
+			model = manager.getModelForRead(file);
+			// TODO.. HTML validator tries again to get a model a 2nd way
+		}
+		catch (Exception e) {
+			Logger.log(Logger.ERROR_DEBUG, file.getFullPath().toString(), e);
+		}
+
+		if (model instanceof IDOMModel)
+			return (IDOMModel) model;
+		if (model != null)
+			model.releaseFromRead();
+		return null;
+	}
+
+	/**
+	 * @deprecated use computeStartEndLocation(int startOffset, String
+	 *             errorMessage, String selectionStrategy, boolean leftError,
+	 *             String nameOrValue, IDOMDocument document) {
+	 * 
+	 */
+	protected int[] computeStartEndLocation(int startOffset, String errorMessage, String selectionStrategy, String nameOrValue, IDOMDocument document) {
+		return computeStartAndEndLocation(startOffset, selectionStrategy, ERROR_SIDE_RIGHT, nameOrValue, document);
+	}
+
+	/**
+	 * Calculates the "better" offsets.
+	 * 
+	 * @param startOffset -
+	 *            the offset given by Xerces
+	 * @param errorMessage -
+	 *            the Xerces error Message
+	 * @param selectionStrategy -
+	 *            the selectionStrategy
+	 * @param document -
+	 *            the document
+	 * @return int[] - position 0 has the start offset of the squiggle range,
+	 *         position 1 has the endOffset
+	 */
+	/*
+	 * The way the offsets is calculated is: - find the indexed region
+	 * (element) closest to the given offset - if we are between two elements,
+	 * choosing left or right element will depend on parameter 'errorSide' -
+	 * based on the selectionStrategy choose the underlining strategy (eg
+	 * START_TAG means underline the start tag of that element) - use
+	 * information from nameOrValue and the DOM to get better offsets
+	 * 
+	 */
+	protected int[] computeStartAndEndLocation(int startOffset, String selectionStrategy, String errorSide, String nameOrValue, IDOMDocument document) {
+		try {
+			int startEndPositions[] = new int[2];
+
+			IndexedRegion region = document.getModel().getIndexedRegion(startOffset);
+			IndexedRegion prevRegion = document.getModel().getIndexedRegion(startOffset - 1);
+
+			if (prevRegion != region) {
+				// if between two regions we use the 'errorSide' to understand
+				// which
+				// element is applicable. if we know the error has been
+				// reported to the
+				// right of the tag, then we can assume we need to step back
+				// to the previous
+				// region to land at the 'correct location. Otherwise assume
+				// we're
+				// exactly where we need to be.
+				if (ERROR_SIDE_LEFT.equals(errorSide)) {
+					region = prevRegion;
+				}
+			}
+
+			// initialize start and end positions to be the start positions
+			// this means if the
+			// special case is not taken care of below the start and end
+			// offset are set to be
+			// the start of the region where the error was
+			if (region != null) {
+				startEndPositions[0] = region.getStartOffset();
+				startEndPositions[1] = startEndPositions[0];
+			}
+			else { // this will message will not get added to the IReporter
+				// since the length is 0
+				startEndPositions[0] = 0;
+				startEndPositions[1] = 0;
+			}
+			if (region instanceof Node) {
+				Node node = (Node) region;
+
+				if (START_TAG.equals(selectionStrategy)) {// then we want to
+					// underline the opening tag
+					if (node.getNodeType() == Node.ELEMENT_NODE) {
+						IDOMElement element = (IDOMElement) node;
+						startEndPositions[0] = element.getStartOffset() + 1;
+						startEndPositions[1] = startEndPositions[0] + element.getTagName().length();
+					}
+				}
+				else if (END_TAG.equals(selectionStrategy)) {// then we want to
+					// underline the end tag
+					if (node.getNodeType() == Node.ELEMENT_NODE) {
+						IDOMElement element = (IDOMElement) node;
+						startEndPositions[0] = element.getEndStartOffset();
+						startEndPositions[1] = element.getEndOffset();
+					}
+				}
+				else if (ATTRIBUTE_NAME.equals(selectionStrategy)) { // in
+					// underline the attribute's name
+					if (node.getNodeType() == Node.ELEMENT_NODE) {
+						IDOMElement element = (IDOMElement) node;
+						IDOMNode attributeNode = (IDOMNode) (element.getAttributeNode(nameOrValue));
+						if (attributeNode != null) {
+							startEndPositions[0] = attributeNode.getStartOffset();
+							startEndPositions[1] = attributeNode.getStartOffset() + nameOrValue.length();
+						}
+					}
+				}
+				else if (ATTRIBUTE_VALUE.equals(selectionStrategy)) {
+					// underline the attribute's value
+					if (node.getNodeType() == Node.ELEMENT_NODE) {
+						IDOMElement element = (IDOMElement) node;
+						IDOMAttr attributeNode = (IDOMAttr) (element.getAttributeNode(nameOrValue));
+						if (attributeNode != null) {
+							startEndPositions[0] = attributeNode.getValueRegionStartOffset();
+							String valueRegionText = attributeNode.getValueRegionText();
+							int valueRegionLength = valueRegionText == null ? 0 : valueRegionText.length(); 
+							startEndPositions[1] = startEndPositions[0] + valueRegionLength;
+						}
+					}
+				}
+				else if (ALL_ATTRIBUTES.equals(selectionStrategy)) {
+					// underline all attributes
+					if (node.getNodeType() == Node.ELEMENT_NODE) {
+						IDOMElement element = (IDOMElement) node;
+						NamedNodeMap attributes = element.getAttributes();
+						if (attributes != null) {
+							IDOMNode first = (IDOMNode) attributes.item(0);
+							IDOMNode last = (IDOMNode) attributes.item(attributes.getLength() - 1);
+							if ((first != null) && (last != null)) {
+								startEndPositions[0] = first.getStartOffset();
+								startEndPositions[1] = last.getEndOffset();
+							}
+						}
+					}
+				}
+				else if (TEXT.equals(selectionStrategy)) {
+					// underline the text between the tags
+					if (node.getNodeType() == Node.TEXT_NODE) {
+						IDOMText textNode = (IDOMText) node;
+						int start = textNode.getStartOffset();
+						String value = textNode.getNodeValue();
+						int index = 0;
+						char curChar = value.charAt(index);
+						// here we are finding start offset by skipping over
+						// whitespace:
+						while ((curChar == '\n') || (curChar == '\t') || (curChar == '\r') || (curChar == ' ')) {
+							curChar = value.charAt(index);
+							index++;
+						}
+						if (index > 0) {
+							index--;
+
+						}
+						start = start + index;
+						startEndPositions[0] = start;
+						startEndPositions[1] = start + value.trim().length();
+					}
+					else if (node.getNodeType() == Node.ELEMENT_NODE) {
+						IDOMElement element = (IDOMElement) node;
+						Node child = element.getFirstChild();
+						if (child instanceof IDOMNode) {
+							IDOMNode xmlChild = ((IDOMNode) child);
+							startEndPositions[0] = xmlChild.getStartOffset();
+							startEndPositions[1] = xmlChild.getEndOffset();
+						}
+					}
+				}
+				else if (FIRST_NON_WHITESPACE_TEXT.equals(selectionStrategy)) {
+					// search through all child nodes and return range of
+					// first non-whitespace
+					// text node
+					if (node.getNodeType() == Node.ELEMENT_NODE) {
+						NodeList nodes = node.getChildNodes();
+						for (int i = 0; i < nodes.getLength(); i++) {
+							Node currentNode = nodes.item(i);
+							if (currentNode.getNodeType() == Node.TEXT_NODE) {
+								// TODO (Trung) I don't think we should call
+								// getNodeValue(), trim(), length()
+								// repeatedly.
+								// This is inefficient, to improve use local
+								// variables to store values.
+								IDOMText textNode = (IDOMText) currentNode;
+								if (textNode.getNodeValue().trim().length() > 0) {
+									String value = textNode.getNodeValue();
+									int index = 0;
+									int start = textNode.getStartOffset();
+									char curChar = value.charAt(index);
+									// here we are finding start offset by
+									// skipping over whitespace:
+									while ((curChar == '\n') || (curChar == '\t') || (curChar == '\r') || (curChar == ' ')) {
+										curChar = value.charAt(index);
+										index++;
+									}
+									if (index > 0) {
+										index--;
+
+									}
+									start = start + index;
+									startEndPositions[0] = start;
+									startEndPositions[1] = start + value.trim().length();
+									break;
+								}
+							}
+
+						}
+					}
+				}
+
+				else if (TEXT_ENTITY_REFERENCE.equals(selectionStrategy)) {
+					if (node.getNodeType() == Node.ENTITY_REFERENCE_NODE) {
+						startEndPositions[0] = region.getStartOffset();
+						startEndPositions[1] = region.getEndOffset();
+					}
+					else if (node.getNodeType() == Node.ELEMENT_NODE) {
+						/*
+						 * In this case the undeclared entity might be in one
+						 * of the attribute values. Search through the
+						 * attributes to find the range of the undeclared
+						 * entity.
+						 */
+						String entity = "&" + nameOrValue + ";"; //$NON-NLS-1$ //$NON-NLS-2$
+						NamedNodeMap attributes = node.getAttributes();
+						for (int i = 0; i < attributes.getLength(); i++) {
+							IDOMAttr attr = (IDOMAttr) attributes.item(i);
+							String nodeValue = attr.getNodeValue();
+							int index = nodeValue.indexOf(entity);
+							if (index != -1) {
+								startEndPositions[0] = attr.getValueRegionStartOffset() + index + 1;
+								startEndPositions[1] = startEndPositions[0] + entity.length();
+							}
+						}
+					}
+
+				}
+				else if (VALUE_OF_ATTRIBUTE_WITH_GIVEN_VALUE.equals(selectionStrategy)) {
+					// TODO (Trung) do we really need this strategy ?
+					// If we know the name of the name of the attribute, we
+					// can retrieve its value.
+					// Hence, we can incoperate this strategy with
+					// ATTRIBUTE_VALUE ?
+					if (node.getNodeType() == Node.ELEMENT_NODE) {
+						// here we will search through all attributes for the
+						// one with the
+						// with the value we want:
+						// TODO (Trung) I see a potential problem here.
+						// What happens when there is another attribute having
+						// the same value
+						// with this attribute's buggy value ?
+						// Need to solve when time permits.
+						NamedNodeMap attributes = node.getAttributes();
+						for (int i = 0; i < attributes.getLength(); i++) {
+							IDOMAttr attr = (IDOMAttr) attributes.item(i);
+							String nodeValue = attr.getNodeValue().trim();
+							if (nodeValue.equals(nameOrValue)) {
+								startEndPositions[0] = attr.getValueRegionStartOffset() + 1;
+								startEndPositions[1] = startEndPositions[0] + nodeValue.length();
+								break;
+							}
+						}
+					}
+				}
+			}
+			return startEndPositions;
+		}
+		// catch (Exception e) { // e.printStackTrace();
+		// }
+		finally {
+		}
+		// return null;
+	}
+
+	/**
+	 * Returns true if delegate validator is enabled based on Validation
+	 * preferences
+	 * 
+	 * @param file
+	 * @return false if delegate validator is not enabled based on Validatoin
+	 *         preferences, true otherwise
+	 */
+	protected boolean isDelegateValidatorEnabled(IFile file) {
+		return true;
+	}
+
+	protected String getErrorSide(IMessage message) {
+		// note that if the ERROR_SIDE is unspecified we return the default
+		// value ERROR_SIDE_LEFT
+		Object value = message.getAttribute(ERROR_SIDE);
+		return ERROR_SIDE_RIGHT.equals(value) ? ERROR_SIDE_RIGHT : ERROR_SIDE_LEFT;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/validation/DelegatingSourceValidatorForXML.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/validation/DelegatingSourceValidatorForXML.java
new file mode 100644
index 0000000..414a85b
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/validation/DelegatingSourceValidatorForXML.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.xml.ui.internal.validation;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.wst.validation.ValidationFramework;
+import org.eclipse.wst.validation.Validator;
+import org.eclipse.wst.validation.internal.provisional.core.IValidator;
+
+/**
+ * This performs as you type validation for XML files
+ */
+public class DelegatingSourceValidatorForXML extends DelegatingSourceValidator
+{
+  private final static String Id = "org.eclipse.wst.xml.core.xml"; //$NON-NLS-1$
+
+  private Validator _validator;
+
+  public DelegatingSourceValidatorForXML()
+  {
+  }
+
+  private Validator getValidator()
+  {
+    if (_validator == null)
+      _validator = ValidationFramework.getDefault().getValidator(Id);
+    return _validator;
+  }
+
+  protected IValidator getDelegateValidator()
+  {
+    Validator v = getValidator();
+    if (v == null)
+      return null;
+    return v.asIValidator();
+  }
+
+  protected boolean isDelegateValidatorEnabled(IFile file)
+  {
+    Validator v = getValidator();
+    if (v == null)
+      return false;
+    if (!v.shouldValidate(file, false, false))
+      return false;
+    return v.isBuildValidation() || v.isManualValidation();
+  }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/validation/MarkupQuickAssistProcessor.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/validation/MarkupQuickAssistProcessor.java
new file mode 100644
index 0000000..c5bb299
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/validation/MarkupQuickAssistProcessor.java
@@ -0,0 +1,147 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 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
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.validation;
+
+import java.util.ArrayList;
+
+import org.eclipse.jface.text.contentassist.CompletionProposal;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.jface.text.quickassist.IQuickAssistInvocationContext;
+import org.eclipse.jface.text.quickassist.IQuickAssistProcessor;
+import org.eclipse.jface.text.source.Annotation;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.wst.xml.core.internal.validation.ProblemIDsXML;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+import org.eclipse.wst.xml.ui.internal.correction.RemoveUnknownElementQuickFixProposal;
+import org.eclipse.wst.xml.ui.internal.correction.RenameInFileQuickAssistProposal;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImageHelper;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImages;
+
+/**
+ * Quick assist processor for problems found by the markup validator
+ */
+class MarkupQuickAssistProcessor implements IQuickAssistProcessor {
+	private int fProblemId;
+	private Object fAdditionalFixInfo = null;
+
+	public boolean canAssist(IQuickAssistInvocationContext invocationContext) {
+		return false;
+	}
+
+	public boolean canFix(Annotation annotation) {
+		boolean result = false;
+
+		switch (fProblemId) {
+			case ProblemIDsXML.EmptyTag :
+			case ProblemIDsXML.MissingEndTag :
+			case ProblemIDsXML.AttrsInEndTag :
+			case ProblemIDsXML.MissingAttrValue :
+			case ProblemIDsXML.NoAttrValue :
+			case ProblemIDsXML.SpacesBeforeTagName :
+			case ProblemIDsXML.SpacesBeforePI :
+			case ProblemIDsXML.NamespaceInPI :
+			case ProblemIDsXML.UnknownElement :
+			case ProblemIDsXML.UnknownAttr :
+			case ProblemIDsXML.InvalidAttrValue :
+			case ProblemIDsXML.MissingRequiredAttr :
+			case ProblemIDsXML.AttrValueNotQuoted :
+			case ProblemIDsXML.MissingClosingBracket :
+				result = true;
+		}
+
+		return result;
+	}
+
+	public ICompletionProposal[] computeQuickAssistProposals(IQuickAssistInvocationContext invocationContext) {
+		ArrayList proposals = new ArrayList();
+
+		switch (fProblemId) {
+			case ProblemIDsXML.EmptyTag :
+				proposals.add(new CompletionProposal("", invocationContext.getOffset(), invocationContext.getLength(), 0, getImage(), XMLUIMessages.QuickFixProcessorXML_0, null, "")); //$NON-NLS-1$ //$NON-NLS-2$ 
+				break;
+			case ProblemIDsXML.MissingEndTag :
+				String tagName = (String) ((Object[]) fAdditionalFixInfo)[0];
+				String tagClose = (String) ((Object[]) fAdditionalFixInfo)[1];
+				int tagCloseOffset = ((Integer) ((Object[]) fAdditionalFixInfo)[2]).intValue();
+				int startTagEndOffset = ((Integer) ((Object[]) fAdditionalFixInfo)[3]).intValue();
+				int firstChildStartOffset = ((Integer) ((Object[]) fAdditionalFixInfo)[4]).intValue();
+				int endOffset = ((Integer) ((Object[]) fAdditionalFixInfo)[5]).intValue();
+				proposals.add(new CompletionProposal(tagClose, tagCloseOffset, 0, 0, getImage(), XMLUIMessages.QuickFixProcessorXML_1, null, "")); //$NON-NLS-1$ 
+				proposals.add(new CompletionProposal("", invocationContext.getOffset(), startTagEndOffset - invocationContext.getOffset(), 0, getImage(), XMLUIMessages.QuickFixProcessorXML_2, null, "")); //$NON-NLS-1$ //$NON-NLS-2$ 
+				proposals.add(new CompletionProposal("</" + tagName + ">", firstChildStartOffset, 0, 0, getImage(), XMLUIMessages.QuickFixProcessorXML_3, null, "")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ 
+				proposals.add(new CompletionProposal("</" + tagName + ">", endOffset, 0, 0, getImage(), XMLUIMessages.QuickFixProcessorXML_4, null, "")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ 
+				break;
+			case ProblemIDsXML.AttrsInEndTag :
+				proposals.add(new CompletionProposal("", invocationContext.getOffset(), invocationContext.getLength(), 0, getImage(), XMLUIMessages.QuickFixProcessorXML_5, null, "")); //$NON-NLS-1$ //$NON-NLS-2$ 
+				break;
+			case ProblemIDsXML.MissingAttrValue :
+				String defaultAttrValue = (String) ((Object[]) fAdditionalFixInfo)[0];
+				int insertOffset = ((Integer) ((Object[]) fAdditionalFixInfo)[1]).intValue();
+				proposals.add(new CompletionProposal("\"" + defaultAttrValue + "\"", invocationContext.getOffset() + invocationContext.getLength() + insertOffset, 0, defaultAttrValue.length() + 2, getImage(), XMLUIMessages.QuickFixProcessorXML_6, null, "")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ 
+				proposals.add(new CompletionProposal("", invocationContext.getOffset(), invocationContext.getLength(), 0, getImage(), XMLUIMessages.QuickFixProcessorXML_7, null, "")); //$NON-NLS-1$ //$NON-NLS-2$ 
+				break;
+			case ProblemIDsXML.NoAttrValue :
+				defaultAttrValue = (String) fAdditionalFixInfo;
+				proposals.add(new CompletionProposal("=\"" + defaultAttrValue + "\"", invocationContext.getOffset() + invocationContext.getLength(), 0, defaultAttrValue.length() + 3, getImage(), XMLUIMessages.QuickFixProcessorXML_6, null, "")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ 
+				proposals.add(new CompletionProposal("", invocationContext.getOffset(), invocationContext.getLength(), 0, getImage(), XMLUIMessages.QuickFixProcessorXML_7, null, "")); //$NON-NLS-1$ //$NON-NLS-2$ 
+				break;
+			case ProblemIDsXML.SpacesBeforeTagName :
+				proposals.add(new CompletionProposal("", invocationContext.getOffset(), invocationContext.getLength(), 0, getImage(), XMLUIMessages.QuickFixProcessorXML_8, null, "")); //$NON-NLS-1$ //$NON-NLS-2$ 
+				break;
+			case ProblemIDsXML.SpacesBeforePI :
+				proposals.add(new CompletionProposal("", invocationContext.getOffset(), invocationContext.getLength(), 0, getImage(), XMLUIMessages.QuickFixProcessorXML_9, null, "")); //$NON-NLS-1$ //$NON-NLS-2$ 
+				break;
+			case ProblemIDsXML.NamespaceInPI :
+				proposals.add(new CompletionProposal("", invocationContext.getOffset(), invocationContext.getLength(), 0, getImage(), XMLUIMessages.QuickFixProcessorXML_10, null, "")); //$NON-NLS-1$ //$NON-NLS-2$ 
+				break;
+			case ProblemIDsXML.UnknownElement :
+				proposals.add(new RemoveUnknownElementQuickFixProposal(fAdditionalFixInfo, getImage(), XMLUIMessages.QuickFixProcessorXML_11));
+				proposals.add(new RenameInFileQuickAssistProposal());
+				break;
+			case ProblemIDsXML.UnknownAttr :
+				proposals.add(new CompletionProposal("", invocationContext.getOffset(), invocationContext.getLength(), 0, getImage(), XMLUIMessages.QuickFixProcessorXML_7, null, "")); //$NON-NLS-1$ //$NON-NLS-2$ 
+				proposals.add(new RenameInFileQuickAssistProposal());
+				break;
+			case ProblemIDsXML.InvalidAttrValue :
+				proposals.add(new CompletionProposal("", invocationContext.getOffset(), invocationContext.getLength(), 0, getImage(), XMLUIMessages.QuickFixProcessorXML_12, null, "")); //$NON-NLS-1$ //$NON-NLS-2$ 
+				break;
+			case ProblemIDsXML.MissingRequiredAttr :
+				String requiredAttr = (String) ((Object[]) fAdditionalFixInfo)[0];
+				insertOffset = ((Integer) ((Object[]) fAdditionalFixInfo)[1]).intValue();
+				proposals.add(new CompletionProposal(requiredAttr, invocationContext.getOffset() + insertOffset, 0, requiredAttr.length(), getImage(), XMLUIMessages.QuickFixProcessorXML_13, null, "")); //$NON-NLS-1$ 
+				break;
+			case ProblemIDsXML.AttrValueNotQuoted :
+				String attrValue = (String) fAdditionalFixInfo;
+				proposals.add(new CompletionProposal("\"" + attrValue + "\"", invocationContext.getOffset(), invocationContext.getLength(), attrValue.length() + 2, getImage(), XMLUIMessages.QuickFixProcessorXML_14, null, "")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ 
+				break;
+			case ProblemIDsXML.MissingClosingBracket :
+				proposals.add(new CompletionProposal(">", invocationContext.getOffset() + invocationContext.getLength(), 0, 1, getImage(), XMLUIMessages.QuickFixProcessorXML_15, null, "")); //$NON-NLS-1$ //$NON-NLS-2$ 
+				break;
+		}
+		return (ICompletionProposal[]) proposals.toArray(new ICompletionProposal[proposals.size()]);
+	}
+
+	public String getErrorMessage() {
+		return null;
+	}
+
+	private Image getImage() {
+		return XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_CORRECTION_CHANGE);
+	}
+
+	public void setProblemId(int problemId) {
+		fProblemId = problemId;
+	}
+
+	public void setAdditionalFixInfo(Object fixInfo) {
+		fAdditionalFixInfo = fixInfo;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/validation/MarkupValidator.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/validation/MarkupValidator.java
new file mode 100644
index 0000000..d228699
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/validation/MarkupValidator.java
@@ -0,0 +1,1042 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.validation;
+
+import java.util.Locale;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceProxy;
+import org.eclipse.core.resources.IResourceProxyVisitor;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+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.content.IContentDescription;
+import org.eclipse.core.runtime.content.IContentType;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.quickassist.IQuickAssistProcessor;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+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.ITextRegionContainer;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList;
+import org.eclipse.wst.sse.ui.internal.reconcile.AbstractStructuredTextReconcilingStrategy;
+import org.eclipse.wst.sse.ui.internal.reconcile.ReconcileAnnotationKey;
+import org.eclipse.wst.sse.ui.internal.reconcile.validator.AnnotationInfo;
+import org.eclipse.wst.sse.ui.internal.reconcile.validator.ISourceValidator;
+import org.eclipse.wst.sse.ui.internal.reconcile.validator.IncrementalReporter;
+import org.eclipse.wst.validation.AbstractValidator;
+import org.eclipse.wst.validation.ValidationResult;
+import org.eclipse.wst.validation.ValidationState;
+import org.eclipse.wst.validation.internal.core.Message;
+import org.eclipse.wst.validation.internal.core.ValidationException;
+import org.eclipse.wst.validation.internal.operations.IWorkbenchContext;
+import org.eclipse.wst.validation.internal.operations.LocalizedMessage;
+import org.eclipse.wst.validation.internal.provisional.core.IMessage;
+import org.eclipse.wst.validation.internal.provisional.core.IReporter;
+import org.eclipse.wst.validation.internal.provisional.core.IValidationContext;
+import org.eclipse.wst.validation.internal.provisional.core.IValidator;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+import org.eclipse.wst.xml.core.internal.validation.ProblemIDsXML;
+import org.eclipse.wst.xml.ui.internal.Logger;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+import org.w3c.dom.Node;
+
+/**
+ * Basic XML syntax checking step.
+ * @deprecated No longer used as the source validator for XML documents. Instead {@link DelegatingSourceValidatorForXML}
+ * is the source validator, and the markup validation is done as a step in {@link XMLValidator} by {@link org.eclipse.wst.xml.core.internal.validation.MarkupValidator}.
+ * 
+ *  @see org.eclipse.wst.xml.core.internal.validation.MarkupValidator
+ *  @see DelegatingSourceValidatorForXML
+ *  @see XMLValidator
+ */
+public class MarkupValidator extends AbstractValidator implements IValidator, ISourceValidator {
+	private String DQUOTE = "\""; //$NON-NLS-1$
+	private String SQUOTE = "'"; //$NON-NLS-1$
+	private final String QUICKASSISTPROCESSOR = IQuickAssistProcessor.class.getName();
+
+	private IDocument fDocument;
+
+	private IContentType fRootContentType = null;
+
+    private int SEVERITY_ATTRIBUTE_HAS_NO_VALUE = IMessage.HIGH_SEVERITY;
+	private int SEVERITY_END_TAG_WITH_ATTRIBUTES = IMessage.HIGH_SEVERITY;
+	private int SEVERITY_INVALID_WHITESPACE_BEFORE_TAGNAME = IMessage.HIGH_SEVERITY;
+	private int SEVERITY_MISSING_CLOSING_BRACKET = IMessage.HIGH_SEVERITY;
+	private int SEVERITY_MISSING_CLOSING_QUOTE = IMessage.HIGH_SEVERITY;
+	private int SEVERITY_MISSING_END_TAG = IMessage.HIGH_SEVERITY;
+	private int SEVERITY_MISSING_START_TAG = IMessage.HIGH_SEVERITY;
+	private int SEVERITY_MISSING_QUOTES = IMessage.HIGH_SEVERITY;
+	private int SEVERITY_NAMESPACE_IN_PI_TARGET = IMessage.HIGH_SEVERITY;
+	private int SEVERITY_TAG_NAME_MISSING = IMessage.HIGH_SEVERITY;
+	private int SEVERITY_WHITESPACE_AT_START = IMessage.HIGH_SEVERITY;
+        
+	private void addAttributeError(String messageText, String attributeValueText, int start, int length, int problemId, IStructuredDocumentRegion sdRegion, IReporter reporter, int messageSeverity) {
+
+		if (sdRegion.isDeleted()) {
+			return;
+		}
+
+		int lineNo = getLineNumber(start);
+		LocalizedMessage message = new LocalizedMessage(messageSeverity, messageText);
+		message.setOffset(start);
+		message.setLength(length);
+		message.setLineNo(lineNo);
+
+
+		if (reporter instanceof IncrementalReporter) {
+			MarkupQuickAssistProcessor processor = new MarkupQuickAssistProcessor();
+			processor.setProblemId(problemId);
+			processor.setAdditionalFixInfo(attributeValueText);
+			message.setAttribute(QUICKASSISTPROCESSOR, processor);
+			AnnotationInfo info = new AnnotationInfo(message);
+			((IncrementalReporter) reporter).addAnnotationInfo(this, info);
+		}
+		else {
+			reporter.addMessage(this, message);
+		}
+	}
+
+	private void checkAttributesInEndTag(IStructuredDocumentRegion structuredDocumentRegion, IReporter reporter) {
+
+		if (structuredDocumentRegion.isDeleted()) {
+			return;
+		}
+
+		ITextRegionList textRegions = structuredDocumentRegion.getRegions();
+		int errorCount = 0;
+		int start = structuredDocumentRegion.getEndOffset();
+		int end = structuredDocumentRegion.getEndOffset();
+		for (int i = 0; (i < textRegions.size()) && (errorCount < AbstractStructuredTextReconcilingStrategy.ELEMENT_ERROR_LIMIT) && !structuredDocumentRegion.isDeleted(); i++) {
+			ITextRegion textRegion = textRegions.get(i);
+			if ((textRegion.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) || (textRegion.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_EQUALS) || (textRegion.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE)) {
+				if (start > structuredDocumentRegion.getStartOffset(textRegion)) {
+					start = structuredDocumentRegion.getStartOffset(textRegion);
+				}
+				end = structuredDocumentRegion.getEndOffset(textRegion);
+				errorCount++;
+			}
+		}
+		// create one error for all attributes in the end tag
+		if (errorCount > 0) {
+			// Position p = new Position(start, end - start);
+			String messageText = XMLUIMessages.End_tag_has_attributes;
+			LocalizedMessage message = new LocalizedMessage(SEVERITY_END_TAG_WITH_ATTRIBUTES, messageText);
+			message.setOffset(start);
+			message.setLength(end - start);
+			message.setLineNo(getLineNumber(start));
+
+			if (reporter instanceof IncrementalReporter) {
+				MarkupQuickAssistProcessor processor = new MarkupQuickAssistProcessor();
+				processor.setProblemId(ProblemIDsXML.AttrsInEndTag);
+				message.setAttribute(QUICKASSISTPROCESSOR, processor);
+
+				AnnotationInfo info = new AnnotationInfo(message);
+				((IncrementalReporter) reporter).addAnnotationInfo(this, info);
+			}
+			else {
+				reporter.addMessage(this, message);
+			}
+		}
+	}
+
+
+	private void checkClosingBracket(IStructuredDocumentRegion structuredDocumentRegion, IReporter reporter) {
+
+		if (structuredDocumentRegion.isDeleted()) {
+			return;
+		}
+
+		ITextRegionList regions = structuredDocumentRegion.getRegions();
+		ITextRegion r = null;
+		boolean closed = false;
+		for (int i = 0; (i < regions.size()) && !structuredDocumentRegion.isDeleted(); i++) {
+			r = regions.get(i);
+			if ((r.getType() == DOMRegionContext.XML_TAG_CLOSE) || (r.getType() == DOMRegionContext.XML_EMPTY_TAG_CLOSE)) {
+				closed = true;
+			}
+		}
+		if (!closed) {
+
+			String messageText = XMLUIMessages.ReconcileStepForMarkup_6;
+
+			int start = structuredDocumentRegion.getStartOffset();
+			int length = structuredDocumentRegion.getText().trim().length();
+			int lineNo = getLineNumber(start);
+
+			LocalizedMessage message = new LocalizedMessage(SEVERITY_MISSING_CLOSING_BRACKET , messageText);
+			message.setOffset(start);
+			message.setLength(length);
+			message.setLineNo(lineNo);
+
+			if (reporter instanceof IncrementalReporter) {
+				MarkupQuickAssistProcessor processor = new MarkupQuickAssistProcessor();
+				processor.setProblemId(ProblemIDsXML.MissingClosingBracket);
+				message.setAttribute(QUICKASSISTPROCESSOR, processor);
+
+				AnnotationInfo info = new AnnotationInfo(message);
+				((IncrementalReporter) reporter).addAnnotationInfo(this, info);
+			}
+			else {
+				reporter.addMessage(this, message);
+			}
+		}
+	}
+
+	private void checkEmptyTag(IStructuredDocumentRegion structuredDocumentRegion, IReporter reporter) {
+
+		if (structuredDocumentRegion.isDeleted()) {
+			return;
+		}
+
+		// navigate to name
+		ITextRegionList regions = structuredDocumentRegion.getRegions();
+		if (regions.size() == 2) {
+			// missing name region
+			if ((regions.get(0).getType() == DOMRegionContext.XML_TAG_OPEN) && (regions.get(1).getType() == DOMRegionContext.XML_TAG_CLOSE)) {
+				String messageText = XMLUIMessages.ReconcileStepForMarkup_3;
+				int start = structuredDocumentRegion.getStartOffset();
+				int length = structuredDocumentRegion.getLength();
+				int lineNo = getLineNumber(start);
+
+				LocalizedMessage message = new LocalizedMessage(SEVERITY_TAG_NAME_MISSING , messageText);
+				message.setOffset(start);
+				message.setLength(length);
+				message.setLineNo(lineNo);
+
+				if (reporter instanceof IncrementalReporter) {
+					MarkupQuickAssistProcessor processor = new MarkupQuickAssistProcessor();
+					processor.setProblemId(ProblemIDsXML.EmptyTag);
+					message.setAttribute(QUICKASSISTPROCESSOR, processor);
+
+					AnnotationInfo info = new AnnotationInfo(message);
+					((IncrementalReporter) reporter).addAnnotationInfo(this, info);
+				}
+				else {
+					reporter.addMessage(this, message);
+				}
+			}
+		}
+	}
+
+	private int getLineNumber(int start) {
+		int lineNo = -1;
+		try {
+			lineNo = getDocument().getLineOfOffset(start) + 1;
+		}
+		catch (BadLocationException e) {
+			Logger.logException(e);
+		}
+		return lineNo;
+	}
+
+	private void checkForAttributeValue(IStructuredDocumentRegion structuredDocumentRegion, IReporter reporter) {
+		if (structuredDocumentRegion.isDeleted()) {
+			return;
+		}
+
+		// check for attributes without a value
+		// track the attribute/equals/value sequence using a state of 0, 1 ,2
+		// representing the name, =, and value, respectively
+		int attrState = 0;
+		ITextRegionList textRegions = structuredDocumentRegion.getRegions();
+		// ReconcileAnnotationKey key = createKey(structuredDocumentRegion,
+		// getScope());
+
+		int errorCount = 0;
+		for (int i = 0; (i < textRegions.size()) && (errorCount < AbstractStructuredTextReconcilingStrategy.ELEMENT_ERROR_LIMIT); i++) {
+			ITextRegion textRegion = textRegions.get(i);
+			if ((textRegion.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) || isTagCloseTextRegion(textRegion)) {
+				// dangling name and '='
+				if ((attrState == 2) && (i >= 2)) {
+					// create annotation
+					ITextRegion nameRegion = textRegions.get(i - 2);
+					if (!(nameRegion instanceof ITextRegionContainer)) {
+						Object[] args = {structuredDocumentRegion.getText(nameRegion)};
+						String messageText = NLS.bind(XMLUIMessages.Attribute__is_missing_a_value, args);
+
+						int start = structuredDocumentRegion.getStartOffset(nameRegion);
+						int end = structuredDocumentRegion.getEndOffset();
+						int lineNo = getLineNumber(start);
+						int textLength = structuredDocumentRegion.getText(nameRegion).trim().length();
+
+						LocalizedMessage message = new LocalizedMessage(SEVERITY_ATTRIBUTE_HAS_NO_VALUE , messageText);
+						message.setOffset(start);
+						message.setLength(textLength);
+						message.setLineNo(lineNo);
+
+						// quick fix info
+						ITextRegion equalsRegion = textRegions.get(i - 2 + 1);
+						int insertOffset = structuredDocumentRegion.getTextEndOffset(equalsRegion) - end;
+						Object[] additionalFixInfo = {structuredDocumentRegion.getText(nameRegion), new Integer(insertOffset)};
+
+						if (reporter instanceof IncrementalReporter) {
+							MarkupQuickAssistProcessor processor = new MarkupQuickAssistProcessor();
+							processor.setProblemId(ProblemIDsXML.MissingAttrValue);
+							processor.setAdditionalFixInfo(additionalFixInfo);
+							message.setAttribute(QUICKASSISTPROCESSOR, processor);
+
+							AnnotationInfo info = new AnnotationInfo(message);
+							((IncrementalReporter) reporter).addAnnotationInfo(this, info);
+						}
+						else {
+							reporter.addMessage(this, message);
+						}
+						errorCount++;
+					}
+				}
+				// name but no '=' (XML only)
+				else if ((attrState == 1) && (i >= 1)) {
+					// create annotation
+					ITextRegion previousRegion = textRegions.get(i - 1);
+					if (!(previousRegion instanceof ITextRegionContainer)) {
+						Object[] args = {structuredDocumentRegion.getText(previousRegion)};
+						String messageText = NLS.bind(XMLUIMessages.Attribute__has_no_value, args);
+						int start = structuredDocumentRegion.getStartOffset(previousRegion);
+						int textLength = structuredDocumentRegion.getText(previousRegion).trim().length();
+						int lineNo = getLineNumber(start);
+
+						LocalizedMessage message = new LocalizedMessage(SEVERITY_ATTRIBUTE_HAS_NO_VALUE, messageText);
+						message.setOffset(start);
+						message.setLength(textLength);
+						message.setLineNo(lineNo);
+
+						if (reporter instanceof IncrementalReporter) {
+							MarkupQuickAssistProcessor processor = new MarkupQuickAssistProcessor();
+							processor.setProblemId(ProblemIDsXML.NoAttrValue);
+							processor.setAdditionalFixInfo(structuredDocumentRegion.getText(previousRegion));
+							message.setAttribute(QUICKASSISTPROCESSOR, processor);
+
+							AnnotationInfo info = new AnnotationInfo(message);
+							((IncrementalReporter) reporter).addAnnotationInfo(this, info);
+						}
+						else {
+							reporter.addMessage(this, message);
+						}
+
+						errorCount++;
+					}
+				}
+				attrState = 1;
+			}
+			else if (textRegion.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_EQUALS) {
+				attrState = 2;
+			}
+			else if (textRegion.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
+				attrState = 0;
+			}
+		}
+
+	}
+
+	private void checkForSpaceBeforeName(IStructuredDocumentRegion structuredDocumentRegion, IReporter reporter) {
+
+		if (structuredDocumentRegion.isDeleted()) {
+			return;
+		}
+
+		String sdRegionText = structuredDocumentRegion.getFullText();
+		if (sdRegionText.startsWith(" ")) { //$NON-NLS-1$
+			IStructuredDocumentRegion prev = structuredDocumentRegion.getPrevious();
+			if (prev != null) {
+				// this is possibly the case of "< tag"
+				if ((prev.getRegions().size() == 1) && isStartTag(prev)) {
+					// add the error for preceding space in tag name
+					String messageText = XMLUIMessages.ReconcileStepForMarkup_2;
+					int start = structuredDocumentRegion.getStartOffset();
+					// find length of whitespace
+					int length = sdRegionText.trim().equals("") ? sdRegionText.length() : sdRegionText.indexOf(sdRegionText.trim()); //$NON-NLS-1$
+
+					LocalizedMessage message = new LocalizedMessage(SEVERITY_INVALID_WHITESPACE_BEFORE_TAGNAME , messageText);
+					message.setOffset(start);
+					message.setLength(length);
+					message.setLineNo(getLineNumber(start));
+
+					if (reporter instanceof IncrementalReporter) {
+						MarkupQuickAssistProcessor processor = new MarkupQuickAssistProcessor();
+						processor.setProblemId(ProblemIDsXML.SpacesBeforeTagName);
+						message.setAttribute(QUICKASSISTPROCESSOR, processor);
+
+						AnnotationInfo info = new AnnotationInfo(message);
+						((IncrementalReporter) reporter).addAnnotationInfo(this, info);
+					}
+					else {
+						reporter.addMessage(this, message);
+					}
+				}
+			}
+		}
+	}
+
+	private void checkNoNamespaceInPI(IStructuredDocumentRegion structuredDocumentRegion, IReporter reporter) {
+
+		if (structuredDocumentRegion.isDeleted()) {
+			return;
+		}
+
+		// navigate to name
+		ITextRegionList regions = structuredDocumentRegion.getRegions();
+		ITextRegion r = null;
+		int errorCount = 0;
+		for (int i = 0; (i < regions.size()) && (errorCount < AbstractStructuredTextReconcilingStrategy.ELEMENT_ERROR_LIMIT) && !structuredDocumentRegion.isDeleted(); i++) {
+			r = regions.get(i);
+			if (r.getType() == DOMRegionContext.XML_TAG_NAME) {
+				String piText = structuredDocumentRegion.getText(r);
+				int index = piText.indexOf(":"); //$NON-NLS-1$
+				if (index != -1) {
+					String messageText = XMLUIMessages.ReconcileStepForMarkup_4;
+					int start = structuredDocumentRegion.getStartOffset(r) + index;
+					int length = piText.trim().length() - index;
+
+					LocalizedMessage message = new LocalizedMessage(SEVERITY_NAMESPACE_IN_PI_TARGET , messageText);
+					message.setOffset(start);
+					message.setLength(length);
+					message.setLineNo(getLineNumber(start));
+
+					if (reporter instanceof IncrementalReporter) {
+						MarkupQuickAssistProcessor processor = new MarkupQuickAssistProcessor();
+						processor.setProblemId(ProblemIDsXML.NamespaceInPI);
+						message.setAttribute(QUICKASSISTPROCESSOR, processor);
+
+						AnnotationInfo info = new AnnotationInfo(message);
+						((IncrementalReporter) reporter).addAnnotationInfo(this, info);
+					}
+					else {
+						reporter.addMessage(this, message);
+					}
+
+					errorCount++;
+				}
+			}
+		}
+	}
+
+	private void checkQuotesForAttributeValues(IStructuredDocumentRegion structuredDocumentRegion, IReporter reporter) {
+		ITextRegionList regions = structuredDocumentRegion.getRegions();
+		ITextRegion r = null;
+		String attrValueText = ""; //$NON-NLS-1$
+		int errorCount = 0;
+		for (int i = 0; (i < regions.size()) && (errorCount < AbstractStructuredTextReconcilingStrategy.ELEMENT_ERROR_LIMIT); i++) {
+			r = regions.get(i);
+			if (r.getType() != DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
+				continue;
+			}
+
+			attrValueText = structuredDocumentRegion.getText(r);
+			// attribute value includes quotes in the string
+			// split up attribute value on quotes
+			/*
+			 * WORKAROUND till
+			 * http://dev.icu-project.org/cgi-bin/icu-bugs/incoming?findid=5207
+			 * is fixed. (Also see BUG143628)
+			 */
+
+			java.util.StringTokenizer st = new java.util.StringTokenizer(attrValueText, "\"'", true); //$NON-NLS-1$
+			int size = st.countTokens();
+			// get the pieces of the attribute value
+			String one = "", two = ""; //$NON-NLS-1$ //$NON-NLS-2$
+			if (size > 0) {
+				one = st.nextToken();
+			}
+			if (size > 1) {
+				two = st.nextToken();
+			}
+			if (size > 2) {
+				// should be handled by parsing...
+				// as in we can't have an attribute value like: <element
+				// attr="a"b"c"/>
+				// and <element attr='a"b"c' /> is legal
+				continue;
+			}
+
+
+			if (size == 1) {
+				if (one.equals(DQUOTE) || one.equals(SQUOTE)) {
+					// missing closing quote
+					String message = XMLUIMessages.ReconcileStepForMarkup_0;
+					addAttributeError(message, attrValueText, structuredDocumentRegion.getStartOffset(r), attrValueText.trim().length(), ProblemIDsXML.Unclassified, structuredDocumentRegion, reporter, SEVERITY_MISSING_CLOSING_QUOTE);
+					errorCount++;
+				}
+				else {
+					// missing both
+					String message = XMLUIMessages.ReconcileStepForMarkup_1;
+					addAttributeError(message, attrValueText, structuredDocumentRegion.getStartOffset(r), attrValueText.trim().length(), ProblemIDsXML.AttrValueNotQuoted, structuredDocumentRegion, reporter, SEVERITY_MISSING_QUOTES);
+					errorCount++;
+				}
+			}
+			else if (size == 2) {
+				if ((one.equals(SQUOTE) && !two.equals(SQUOTE)) || (one.equals(DQUOTE) && !two.equals(DQUOTE))) {
+					// missing closing quote
+					String message = XMLUIMessages.ReconcileStepForMarkup_0;
+					addAttributeError(message, attrValueText, structuredDocumentRegion.getStartOffset(r), attrValueText.trim().length(), ProblemIDsXML.Unclassified, structuredDocumentRegion, reporter, SEVERITY_MISSING_CLOSING_QUOTE);
+					errorCount++;
+				}
+			}
+		}
+		// end of region for loop
+	}
+
+	private void checkStartEndTagPairs(IStructuredDocumentRegion sdRegion, IReporter reporter) {
+
+		if (sdRegion.isDeleted()) {
+			return;
+		}
+
+		// check start/end tag pairs
+		IDOMNode xmlNode = getXMLNode(sdRegion);
+
+		if (xmlNode == null) {
+			return;
+		}
+
+		boolean selfClosed = false;
+		String tagName = null;
+
+		/**
+		 * For tags that aren't meant to be EMPTY, make sure it's empty or has an end tag
+		 */
+		if (xmlNode.isContainer()) {
+			IStructuredDocumentRegion endRegion = xmlNode.getEndStructuredDocumentRegion();
+			if (endRegion == null) {
+				IStructuredDocumentRegion startRegion = xmlNode.getStartStructuredDocumentRegion();
+				if (startRegion != null && !startRegion.isDeleted() && DOMRegionContext.XML_TAG_OPEN.equals(startRegion.getFirstRegion().getType())) {
+					// analyze the tag (check self closing)
+					ITextRegionList regions = startRegion.getRegions();
+					ITextRegion r = null;
+					int start = sdRegion.getStart();
+					int length = sdRegion.getTextLength();
+					for (int i = 0; i < regions.size(); i++) {
+						r = regions.get(i);
+						if (r.getType() == DOMRegionContext.XML_TAG_NAME) {
+							tagName = sdRegion.getText(r);
+							start = sdRegion.getStartOffset(r);
+							length = r.getTextLength();
+						}
+						else if (r.getType() == DOMRegionContext.XML_EMPTY_TAG_CLOSE) {
+							selfClosed = true;
+						}
+					}
+
+
+					if (!selfClosed && (tagName != null)) {
+						Object[] args = {tagName};
+						String messageText = NLS.bind(XMLUIMessages.Missing_end_tag_, args);
+
+						int lineNumber = getLineNumber(start);
+
+						IMessage message = new LocalizedMessage(SEVERITY_MISSING_END_TAG , messageText);
+						message.setOffset(start);
+						message.setLength(length);
+						message.setLineNo(lineNumber);
+
+						if (reporter instanceof IncrementalReporter) {
+							Object[] additionalFixInfo = getStartEndFixInfo(xmlNode, tagName, r);
+
+							MarkupQuickAssistProcessor processor = new MarkupQuickAssistProcessor();
+							processor.setProblemId(ProblemIDsXML.MissingEndTag);
+							processor.setAdditionalFixInfo(additionalFixInfo);
+							message.setAttribute(QUICKASSISTPROCESSOR, processor);
+
+							AnnotationInfo info = new AnnotationInfo(message);
+
+							((IncrementalReporter) reporter).addAnnotationInfo(this, info);
+						}
+						else {
+							reporter.addMessage(this, message);
+						}
+					}
+				}
+			}
+			else {
+				IStructuredDocumentRegion startRegion = xmlNode.getStartStructuredDocumentRegion();
+				if (startRegion == null || startRegion.isDeleted()) {
+					// analyze the tag (check self closing)
+					ITextRegionList regions = endRegion.getRegions();
+					ITextRegion r = null;
+					int start = sdRegion.getStart();
+					int length = sdRegion.getTextLength();
+					for (int i = 0; i < regions.size(); i++) {
+						r = regions.get(i);
+						if (r.getType() == DOMRegionContext.XML_TAG_NAME) {
+							tagName = sdRegion.getText(r);
+							start = sdRegion.getStartOffset(r);
+							length = r.getTextLength();
+						}
+					}
+
+					if (tagName != null) {
+						Object[] args = {tagName};
+						String messageText = NLS.bind(XMLUIMessages.Missing_start_tag_, args);
+
+						int lineNumber = getLineNumber(start);
+
+						IMessage message = new LocalizedMessage(SEVERITY_MISSING_START_TAG, messageText);
+						message.setOffset(start);
+						message.setLength(length);
+						message.setLineNo(lineNumber);
+
+						if (reporter instanceof IncrementalReporter) {
+							Object[] additionalFixInfo = getStartEndFixInfo(xmlNode, tagName, r);
+
+							MarkupQuickAssistProcessor processor = new MarkupQuickAssistProcessor();
+							processor.setProblemId(ProblemIDsXML.MissingStartTag);
+							processor.setAdditionalFixInfo(additionalFixInfo);
+							message.setAttribute(QUICKASSISTPROCESSOR, processor);
+
+							AnnotationInfo info = new AnnotationInfo(message);
+
+							((IncrementalReporter) reporter).addAnnotationInfo(this, info);
+						}
+						else {
+							reporter.addMessage(this, message);
+						}
+					}
+				}
+			}
+
+		}
+		/*
+		 * Check for an end tag that has no start tag
+		 */
+		else {
+			IStructuredDocumentRegion startRegion = xmlNode.getStartStructuredDocumentRegion();
+			if (startRegion == null) {
+				IStructuredDocumentRegion endRegion = xmlNode.getEndStructuredDocumentRegion();
+				if (!endRegion.isDeleted()) {
+					// get name
+					ITextRegionList regions = endRegion.getRegions();
+					ITextRegion r = null;
+					for (int i = 0; i < regions.size(); i++) {
+						r = regions.get(i);
+						if (r.getType() == DOMRegionContext.XML_TAG_NAME) {
+							tagName = sdRegion.getText(r);
+						}
+					}
+
+					if (!selfClosed && (tagName != null)) {
+						String messageText = XMLUIMessages.Indicate_no_grammar_specified_severities_error;
+
+						int start = sdRegion.getStart();
+						int lineNumber = getLineNumber(start);
+
+						// SEVERITY_STRUCTURE == IMessage.HIGH_SEVERITY
+						IMessage message = new LocalizedMessage(IMessage.HIGH_SEVERITY, messageText);
+						message.setOffset(start);
+						message.setLength(sdRegion.getTextLength());
+						message.setLineNo(lineNumber);
+
+						reporter.addMessage(this, message);
+					}
+				}
+			}
+		}
+	}
+
+	private Object[] getStartEndFixInfo(IDOMNode xmlNode, String tagName, ITextRegion r) {
+		// quick fix info
+		String tagClose = "/>"; //$NON-NLS-1$
+		int tagCloseOffset = xmlNode.getFirstStructuredDocumentRegion().getEndOffset();
+		if ((r != null) && (r.getType() == DOMRegionContext.XML_TAG_CLOSE)) {
+			tagClose = "/"; //$NON-NLS-1$
+			tagCloseOffset--;
+		}
+		IDOMNode firstChild = (IDOMNode) xmlNode.getFirstChild();
+		while ((firstChild != null) && (firstChild.getNodeType() == Node.TEXT_NODE)) {
+			firstChild = (IDOMNode) firstChild.getNextSibling();
+		}
+		int endOffset = xmlNode.getEndOffset();
+		int firstChildStartOffset = firstChild == null ? endOffset : firstChild.getStartOffset();
+		Object[] additionalFixInfo = {tagName, tagClose, new Integer(tagCloseOffset), new Integer(xmlNode.getFirstStructuredDocumentRegion().getEndOffset()), // startTagEndOffset
+					new Integer(firstChildStartOffset), // firstChildStartOffset
+					new Integer(endOffset)}; // endOffset
+		return additionalFixInfo;
+	}
+
+	private void checkStartingSpaceForPI(IStructuredDocumentRegion structuredDocumentRegion, IReporter reporter) {
+
+		if (structuredDocumentRegion.isDeleted()) {
+			return;
+		}
+
+		IStructuredDocumentRegion prev = structuredDocumentRegion.getPrevious();
+		if ((prev != null) && prev.getStartOffset() == 0) {
+			if (prev.getType() == DOMRegionContext.XML_CONTENT) {
+				String messageText = XMLUIMessages.ReconcileStepForMarkup_5;
+				int start = prev.getStartOffset();
+				int length = prev.getLength();
+
+				LocalizedMessage message = new LocalizedMessage(SEVERITY_WHITESPACE_AT_START , messageText);
+				message.setOffset(start);
+				message.setLength(length);
+				message.setLineNo(getLineNumber(start));
+
+				if (reporter instanceof IncrementalReporter) {
+					MarkupQuickAssistProcessor processor = new MarkupQuickAssistProcessor();
+					processor.setProblemId(ProblemIDsXML.SpacesBeforePI);
+					message.setAttribute(QUICKASSISTPROCESSOR, processor);
+	
+					AnnotationInfo info = new AnnotationInfo(message);
+					((IncrementalReporter) reporter).addAnnotationInfo(this, info);
+				}
+				else {
+					reporter.addMessage(this, message);
+				}
+				// Position p = new Position(start, length);
+				//				
+				// ReconcileAnnotationKey key =
+				// createKey(structuredDocumentRegion, getScope());
+				// TemporaryAnnotation annotation = new TemporaryAnnotation(p,
+				// SEVERITY_SYNTAX_ERROR, message, key,
+				// ProblemIDsXML.SpacesBeforePI);
+				// results.add(annotation);
+			}
+		}
+	}
+
+	public int getScope() {
+		return ReconcileAnnotationKey.PARTIAL;
+	}
+
+	private IDOMNode getXMLNode(IStructuredDocumentRegion sdRegion) {
+
+		if (sdRegion == null) {
+			return null;
+		}
+
+		IStructuredModel xModel = null;
+		IDOMNode xmlNode = null;
+		// get/release models should always be in a try/finally block
+		try {
+			xModel = StructuredModelManager.getModelManager().getExistingModelForRead(getDocument());
+			// xModel is sometime null, when closing editor, for example
+			if (xModel != null) {
+				xmlNode = (IDOMNode) xModel.getIndexedRegion(sdRegion.getStart());
+			}
+		}
+		finally {
+			if (xModel != null) {
+				xModel.releaseFromRead();
+			}
+		}
+		return xmlNode;
+	}
+
+	/**
+	 * Determines whether the IStructuredDocumentRegion is a XML "end tag"
+	 * since they're not allowed to have attribute ITextRegions
+	 * 
+	 * @param structuredDocumentRegion
+	 */
+	private boolean isEndTag(IStructuredDocumentRegion structuredDocumentRegion) {
+		if ((structuredDocumentRegion == null) || structuredDocumentRegion.isDeleted()) {
+			return false;
+		}
+		return structuredDocumentRegion.getFirstRegion().getType() == DOMRegionContext.XML_END_TAG_OPEN;
+	}
+
+	/**
+	 * Determines if the IStructuredDocumentRegion is an XML Processing
+	 * Instruction
+	 * 
+	 * @param structuredDocumentRegion
+	 * 
+	 */
+	private boolean isPI(IStructuredDocumentRegion structuredDocumentRegion) {
+		if ((structuredDocumentRegion == null) || structuredDocumentRegion.isDeleted()) {
+			return false;
+		}
+		return structuredDocumentRegion.getFirstRegion().getType() == DOMRegionContext.XML_PI_OPEN;
+	}
+
+	/**
+	 * Determines whether the IStructuredDocumentRegion is a XML "start tag"
+	 * since they need to be checked for proper XML attribute region sequences
+	 * 
+	 * @param structuredDocumentRegion
+	 * 
+	 */
+	private boolean isStartTag(IStructuredDocumentRegion structuredDocumentRegion) {
+		if ((structuredDocumentRegion == null) || structuredDocumentRegion.isDeleted()) {
+			return false;
+		}
+		return structuredDocumentRegion.getFirstRegion().getType() == DOMRegionContext.XML_TAG_OPEN;
+	}
+
+	// Because we check the "proper" closing separately from attribute
+	// sequencing, we need to know what's
+	// an appropriate close.
+	private boolean isTagCloseTextRegion(ITextRegion textRegion) {
+		return (textRegion.getType() == DOMRegionContext.XML_TAG_CLOSE) || (textRegion.getType() == DOMRegionContext.XML_EMPTY_TAG_CLOSE);
+	}
+
+	/**
+	 * Determines if the IStructuredDocumentRegion is XML Content
+	 * 
+	 * @param structuredDocumentRegion
+	 * 
+	 */
+	private boolean isXMLContent(IStructuredDocumentRegion structuredDocumentRegion) {
+		if ((structuredDocumentRegion == null) || structuredDocumentRegion.isDeleted()) {
+			return false;
+		}
+		return structuredDocumentRegion.getFirstRegion().getType() == DOMRegionContext.XML_CONTENT;
+	}
+
+	private void setDocument(IDocument doc) {
+		fDocument = doc;
+	}
+
+	private IDocument getDocument() {
+		return fDocument;
+	}
+
+	public void connect(IDocument document) {
+		setDocument(document);
+	}
+
+	public void disconnect(IDocument document) {
+		setDocument(null);
+	}
+
+	public void validate(IRegion dirtyRegion, IValidationContext helper, IReporter reporter) {
+		if (getDocument() == null) {
+			return;
+		}
+		if (!(reporter instanceof IncrementalReporter)) {
+			return;
+		}
+		if (!(getDocument() instanceof IStructuredDocument)) {
+			return;
+		}
+
+		// remove old messages
+		reporter.removeAllMessages(this);
+
+		IStructuredDocumentRegion[] regions = ((IStructuredDocument) fDocument).getStructuredDocumentRegions(dirtyRegion.getOffset(), dirtyRegion.getLength());
+		for (int i = 0; i < regions.length; i++) {
+			validate(regions[i], reporter);
+		}
+	}
+
+	public void validate(IStructuredDocumentRegion structuredDocumentRegion, IReporter reporter) {
+
+		if (structuredDocumentRegion == null) {
+			return;
+		}
+
+		if (isStartTag(structuredDocumentRegion)) {
+			// check for attributes without a value
+			checkForAttributeValue(structuredDocumentRegion, reporter);
+			// check if started tag is ended
+			checkStartEndTagPairs(structuredDocumentRegion, reporter);
+			// check empty tag <>
+			checkEmptyTag(structuredDocumentRegion, reporter);
+			// check that each attribute has quotes
+			checkQuotesForAttributeValues(structuredDocumentRegion, reporter);
+			// check that the closing '>' is there
+			checkClosingBracket(structuredDocumentRegion, reporter);
+		}
+		else if (isEndTag(structuredDocumentRegion)) {
+			// check if ending tag was started
+			checkStartEndTagPairs(structuredDocumentRegion, reporter);
+			// check for attributes in an end tag
+			checkAttributesInEndTag(structuredDocumentRegion, reporter);
+			// check that the closing '>' is there
+			checkClosingBracket(structuredDocumentRegion, reporter);
+		}
+		else if (isPI(structuredDocumentRegion)) {
+			// check validity of processing instruction
+			checkStartingSpaceForPI(structuredDocumentRegion, reporter);
+			checkNoNamespaceInPI(structuredDocumentRegion, reporter);
+		}
+		else if (isXMLContent(structuredDocumentRegion)) {
+			checkForSpaceBeforeName(structuredDocumentRegion, reporter);
+		}
+		else if (isXMLDoctypeDeclaration(structuredDocumentRegion)) {
+			checkDocumentTypeReferences(structuredDocumentRegion, reporter);
+		}
+	}
+
+	/**
+	 * @param structuredDocumentRegion
+	 * @param reporter
+	 */
+	private void checkDocumentTypeReferences(IStructuredDocumentRegion structuredDocumentRegion, IReporter reporter) {
+	}
+
+	/**
+	 * @param structuredDocumentRegion
+	 * @return
+	 */
+	private boolean isXMLDoctypeDeclaration(IStructuredDocumentRegion structuredDocumentRegion) {
+		if ((structuredDocumentRegion == null) || structuredDocumentRegion.isDeleted()) {
+			return false;
+		}
+		return structuredDocumentRegion.getFirstRegion().getType() == DOMRegionContext.XML_DECLARATION_OPEN && structuredDocumentRegion.getType().equals(DOMRegionContext.XML_DOCTYPE_DECLARATION);
+	}
+
+	public void cleanup(IReporter reporter) {
+		fDocument = null;
+	}
+
+	public void validate(IValidationContext helper, IReporter reporter) throws ValidationException {
+		String[] uris = helper.getURIs();
+		IWorkspaceRoot wsRoot = ResourcesPlugin.getWorkspace().getRoot();
+		if (uris.length > 0) {
+			IFile currentFile = null;
+
+			for (int i = 0; i < uris.length && !reporter.isCancelled(); i++) {
+				// might be called with just project path?
+				IPath path = new Path(uris[i]);
+				if (path.segmentCount() > 1) {
+					currentFile = wsRoot.getFile(path);
+					if (shouldValidate(currentFile, true)) {
+						validateV1File(currentFile, reporter);
+					}
+				}
+				else if (uris.length == 1) {
+					validateV1Project(helper, reporter);
+				}
+			}
+		}
+		else
+			validateV1Project(helper, reporter);
+	}
+	
+	private boolean shouldValidate(IResourceProxy proxy) {
+		if(proxy.getType() == IResource.FILE) {
+			String name = proxy.getName();
+			if(name.toLowerCase(Locale.US).endsWith(".xml")) {
+				return true;
+			}
+		}
+		return shouldValidate(proxy.requestResource(), false);
+	}
+	
+	private boolean shouldValidate(IResource file, boolean checkExtension) {
+		if (file == null || !file.exists() || file.getType() != IResource.FILE)
+			return false;
+		if (checkExtension) {
+			String extension = file.getFileExtension();
+			if (extension != null && "xml".endsWith(extension.toLowerCase(Locale.US)))
+				return true;
+		}
+
+		IContentDescription contentDescription = null;
+		try {
+			contentDescription = ((IFile) file).getContentDescription();
+			if (contentDescription != null) {
+				IContentType contentType = contentDescription.getContentType();
+				return contentDescription != null && contentType.isKindOf(getXMLContentType());
+			}
+		}
+		catch (CoreException e) {
+			Logger.logException(e);
+		}
+		return false;
+	}
+
+	/**
+	 * @param helper
+	 * @param reporter
+	 */
+	private void validateV1Project(IValidationContext helper, final IReporter reporter) {
+		// if uris[] length 0 -> validate() gets called for each project
+		if (helper instanceof IWorkbenchContext) {
+			IProject project = ((IWorkbenchContext) helper).getProject();
+			IResourceProxyVisitor visitor = new IResourceProxyVisitor() {
+				public boolean visit(IResourceProxy proxy) throws CoreException {
+					if (shouldValidate(proxy)) {
+						validateV1File((IFile) proxy.requestResource(), reporter);
+					}
+					return true;
+				}
+			};
+			try {
+				// collect all jsp files for the project
+				project.accept(visitor, IResource.DEPTH_INFINITE);
+			}
+			catch (CoreException e) {
+				Logger.logException(e);
+			}
+		}
+	}
+	
+
+	/**
+	 * @param currentFile
+	 * @param reporter
+	 */
+	private void validateV1File(IFile currentFile, IReporter reporter) {
+		Message message = new LocalizedMessage(IMessage.LOW_SEVERITY, currentFile.getFullPath().toString().substring(1));
+		reporter.displaySubtask(MarkupValidator.this, message);
+
+		IStructuredModel model = null;
+		try {
+			model = StructuredModelManager.getModelManager().getModelForRead(currentFile);
+			IStructuredDocument document = null;
+			if (model != null) {
+				document = model.getStructuredDocument();
+				connect(document);
+				IStructuredDocumentRegion validationRegion = document.getFirstStructuredDocumentRegion();
+				while (validationRegion != null) {
+					validate(validationRegion, reporter);
+					validationRegion = validationRegion.getNext();
+				}
+				disconnect(document);
+			}
+		}
+		catch (Exception e) {
+			Logger.logException(e);
+		}
+		finally {
+			if (model != null) {
+				model.releaseFromRead();
+			}
+		}
+	}
+
+	/**
+	 * @return
+	 */
+	private IContentType getXMLContentType() {
+		if (fRootContentType == null) {
+			fRootContentType = Platform.getContentTypeManager().getContentType("org.eclipse.core.runtime.xml");
+		}
+		return fRootContentType;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.validation.AbstractValidator#validate(org.eclipse.core.resources.IResource, int, org.eclipse.wst.validation.ValidationState, org.eclipse.core.runtime.IProgressMonitor)
+	 */
+	public ValidationResult validate(IResource resource, int kind, ValidationState state, IProgressMonitor monitor) {
+		if (resource.getType() != IResource.FILE)
+			return null;
+		ValidationResult result = new ValidationResult();
+		IReporter reporter = result.getReporter(monitor);
+		validateV1File((IFile) resource, reporter);
+		return result;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/contentoutline/AbstractXMLContentOutlineConfiguration.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/contentoutline/AbstractXMLContentOutlineConfiguration.java
new file mode 100644
index 0000000..00b2cf5
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/contentoutline/AbstractXMLContentOutlineConfiguration.java
@@ -0,0 +1,342 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2009 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.views.contentoutline;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jface.action.IMenuListener;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.util.LocalSelectionTransfer;
+import org.eclipse.jface.util.SafeRunnable;
+import org.eclipse.jface.util.TransferDragSourceListener;
+import org.eclipse.jface.util.TransferDropTargetListener;
+import org.eclipse.jface.viewers.IContentProvider;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.swt.dnd.DND;
+import org.eclipse.swt.dnd.DragSourceEvent;
+import org.eclipse.swt.dnd.DropTargetEvent;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.swt.widgets.TreeItem;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.ui.internal.IReleasable;
+import org.eclipse.wst.sse.ui.views.contentoutline.ContentOutlineConfiguration;
+import org.eclipse.wst.xml.ui.internal.XMLUIPlugin;
+import org.eclipse.wst.xml.ui.internal.contentoutline.JFaceNodeContentProvider;
+import org.eclipse.wst.xml.ui.internal.contentoutline.JFaceNodeLabelProvider;
+import org.eclipse.wst.xml.ui.internal.contentoutline.XMLNodeActionManager;
+import org.eclipse.wst.xml.ui.internal.dnd.DragNodeCommand;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Node;
+
+/**
+ * Basic Outline Configuration for generic XML support.  Expects that the viewer's
+ * input will be the DOM Model, and provides basic label and content providers.
+ * 
+ * @see org.eclipse.wst.sse.ui.views.contentoutline.ContentOutlineConfiguration
+ * @since 3.1
+ */
+public abstract class AbstractXMLContentOutlineConfiguration extends ContentOutlineConfiguration {
+	private class ActionManagerMenuListener implements IMenuListener, IReleasable {
+		private XMLNodeActionManager fActionManager;
+		private TreeViewer fTreeViewer;
+
+		public ActionManagerMenuListener(TreeViewer viewer) {
+			fTreeViewer = viewer;
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see org.eclipse.jface.action.IMenuListener#menuAboutToShow(org.eclipse.jface.action.IMenuManager)
+		 */
+		public void menuAboutToShow(IMenuManager manager) {
+			if (fActionManager == null) {
+				fActionManager = createNodeActionManager(fTreeViewer);
+			}
+			if (fActionManager != null) {
+				fActionManager.fillContextMenu(manager, fTreeViewer.getSelection());
+			}
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see org.eclipse.wst.sse.ui.internal.IReleasable#release()
+		 */
+		public void release() {
+			fTreeViewer = null;
+			if (fActionManager != null) {
+				fActionManager.setModel(null);
+			}
+		}
+	}
+	
+	private static class StatusLineLabelProvider extends JFaceNodeLabelProvider {
+		public StatusLineLabelProvider() {
+			super();
+		}
+
+		public String getText(Object element) {
+			if (element == null)
+				return null;
+
+			if (!(element instanceof Node)) {
+				return super.getText(element);
+			}
+
+			StringBuffer s = new StringBuffer();
+			Node node = (Node) element;
+			while (node != null) {
+				if (node.getNodeType() != Node.DOCUMENT_NODE) {
+					s.insert(0, super.getText(node));
+				}
+				
+				if (node.getNodeType() == Node.ATTRIBUTE_NODE)
+					node = ((Attr) node).getOwnerElement();
+				else
+					node = node.getParentNode();
+			
+				if (node != null && node.getNodeType() != Node.DOCUMENT_NODE) {
+					s.insert(0, IPath.SEPARATOR);
+				}
+			}
+			return s.toString();
+		}
+	}
+
+	private IContentProvider fContentProvider = null;
+
+	private ActionManagerMenuListener fContextMenuFiller = null;
+
+	private ILabelProvider fLabelProvider = null;
+
+	boolean fShowAttributes = false;
+
+	private ILabelProvider fSimpleLabelProvider;
+	private TransferDragSourceListener[] fTransferDragSourceListeners;
+
+	private TransferDropTargetListener[] fTransferDropTargetListeners;
+
+	/**
+	 * Create new instance of XMLContentOutlineConfiguration
+	 */
+	public AbstractXMLContentOutlineConfiguration() {
+		// Must have empty constructor to createExecutableExtension
+		super();
+	}
+
+	/**
+	 * Returns the NodeActionManager to use for the given treeViewer.
+	 * <p>
+	 * Not API. May be removed in the future.
+	 * </p>
+	 * 
+	 * @param treeViewer
+	 *            the TreeViewer associated with this configuration
+	 * @return a node action manager for use with this tree viewer
+	 */
+	protected XMLNodeActionManager createNodeActionManager(TreeViewer treeViewer) {
+		return new XMLNodeActionManager((IStructuredModel) treeViewer.getInput(), treeViewer);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.wst.sse.ui.views.contentoutline.ContentOutlineConfiguration#getContentProvider(org.eclipse.jface.viewers.TreeViewer)
+	 */
+	public IContentProvider getContentProvider(TreeViewer viewer) {
+		if (fContentProvider == null) {
+			fContentProvider = new JFaceNodeContentProvider();
+		}
+		return fContentProvider;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.wst.sse.ui.views.contentoutline.ContentOutlineConfiguration#getLabelProvider(org.eclipse.jface.viewers.TreeViewer)
+	 */
+	public ILabelProvider getLabelProvider(TreeViewer viewer) {
+		if (fLabelProvider == null) {
+			fLabelProvider = new JFaceNodeLabelProvider();
+		}
+		return fLabelProvider;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.wst.sse.ui.views.contentoutline.ContentOutlineConfiguration#getMenuListener(org.eclipse.jface.viewers.TreeViewer)
+	 */
+	public IMenuListener getMenuListener(TreeViewer viewer) {
+		if (fContextMenuFiller == null) {
+			fContextMenuFiller = new ActionManagerMenuListener(viewer);
+		}
+		return fContextMenuFiller;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.wst.sse.ui.views.contentoutline.ContentOutlineConfiguration#getPreferenceStore()
+	 */
+	protected IPreferenceStore getPreferenceStore() {
+		return XMLUIPlugin.getDefault().getPreferenceStore();
+	}
+
+	public ILabelProvider getStatusLineLabelProvider(TreeViewer treeViewer) {
+		if (fSimpleLabelProvider == null) {
+			fSimpleLabelProvider = new StatusLineLabelProvider();
+		}
+		return fSimpleLabelProvider;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.wst.sse.ui.views.contentoutline.ContentOutlineConfiguration#getTransferDragSourceListeners(org.eclipse.jface.viewers.TreeViewer)
+	 */
+	public TransferDragSourceListener[] getTransferDragSourceListeners(final TreeViewer treeViewer) {
+		if (fTransferDragSourceListeners == null) {
+			fTransferDragSourceListeners = new TransferDragSourceListener[]{new TransferDragSourceListener() {
+
+				public void dragFinished(DragSourceEvent event) {
+					LocalSelectionTransfer.getTransfer().setSelection(null);
+				}
+
+				public void dragSetData(DragSourceEvent event) {
+				}
+
+				public void dragStart(DragSourceEvent event) {
+					LocalSelectionTransfer.getTransfer().setSelection(treeViewer.getSelection());
+				}
+
+				public Transfer getTransfer() {
+					return LocalSelectionTransfer.getTransfer();
+				}
+			}};
+		}
+
+		return fTransferDragSourceListeners;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.wst.sse.ui.views.contentoutline.ContentOutlineConfiguration#getTransferDropTargetListeners(org.eclipse.jface.viewers.TreeViewer)
+	 */
+	public TransferDropTargetListener[] getTransferDropTargetListeners(final TreeViewer treeViewer) {
+		if (fTransferDropTargetListeners == null) {
+			fTransferDropTargetListeners = new TransferDropTargetListener[]{new TransferDropTargetListener() {
+				public void dragEnter(DropTargetEvent event) {
+				}
+
+				public void dragLeave(DropTargetEvent event) {
+				}
+
+				public void dragOperationChanged(DropTargetEvent event) {
+				}
+
+				public void dragOver(DropTargetEvent event) {
+					event.feedback = DND.FEEDBACK_SELECT;
+					float feedbackFloat = getHeightInItem(event);
+					if (feedbackFloat > 0.75) {
+						event.feedback = DND.FEEDBACK_INSERT_AFTER;
+					}
+					else if (feedbackFloat < 0.25) {
+						event.feedback = DND.FEEDBACK_INSERT_BEFORE;
+					}
+					event.feedback |= DND.FEEDBACK_EXPAND | DND.FEEDBACK_SCROLL;
+				}
+
+				public void drop(DropTargetEvent event) {
+					if (event.operations != DND.DROP_NONE && LocalSelectionTransfer.getTransfer().getSelection() != null && !LocalSelectionTransfer.getTransfer().getSelection().isEmpty()) {
+						IStructuredSelection selection = (IStructuredSelection) LocalSelectionTransfer.getTransfer().getSelection();
+						if (selection != null && !selection.isEmpty() && event.item != null && event.item.getData() != null) {
+							/*
+							 * the command uses these numbers instead of the
+							 * feedback constants (even though it converts in
+							 * the other direction as well)
+							 */
+							float feedbackFloat = getHeightInItem(event);
+
+							final DragNodeCommand command = new DragNodeCommand(event.item.getData(), feedbackFloat, event.operations, event.detail, selection.toList(), treeViewer);
+							if (command != null && command.canExecute()) {
+								SafeRunnable.run(new SafeRunnable() {
+									public void run() throws Exception {
+										command.execute();
+									}
+								});
+							}
+						}
+					}
+				}
+
+				public void dropAccept(DropTargetEvent event) {
+				}
+
+				private float getHeightInItem(DropTargetEvent event) {
+					if (event.item == null)
+						return .5f;
+					if (event.item instanceof TreeItem) {
+						TreeItem treeItem = (TreeItem) event.item;
+						Control control = treeItem.getParent();
+						Point point = control.toControl(new Point(event.x, event.y));
+						Rectangle bounds = treeItem.getBounds();
+						return (float) (point.y - bounds.y) / (float) bounds.height;
+					}
+					else if (event.item instanceof TableItem) {
+						TableItem tableItem = (TableItem) event.item;
+						Control control = tableItem.getParent();
+						Point point = control.toControl(new Point(event.x, event.y));
+						Rectangle bounds = tableItem.getBounds(0);
+						return (float) (point.y - bounds.y) / (float) bounds.height;
+					}
+					else {
+						return 0.0F;
+					}
+				}
+
+				public Transfer getTransfer() {
+					return LocalSelectionTransfer.getTransfer();
+				}
+
+				public boolean isEnabled(DropTargetEvent event) {
+					return getTransfer().isSupportedType(event.currentDataType);
+				}
+			}};
+		}
+		return fTransferDropTargetListeners;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.wst.sse.ui.views.contentoutline.ContentOutlineConfiguration#unconfigure(org.eclipse.jface.viewers.TreeViewer)
+	 */
+	public void unconfigure(TreeViewer viewer) {
+		super.unconfigure(viewer);
+		fTransferDragSourceListeners = null;
+		fTransferDropTargetListeners = null;
+		if (fContextMenuFiller != null) {
+			fContextMenuFiller.release();
+			fContextMenuFiller = null;
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/contentoutline/XMLContentOutlineConfiguration.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/contentoutline/XMLContentOutlineConfiguration.java
new file mode 100644
index 0000000..ec3f156
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/contentoutline/XMLContentOutlineConfiguration.java
@@ -0,0 +1,411 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2008 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.views.contentoutline;
+
+import java.util.List;
+
+import org.eclipse.jface.action.IContributionItem;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.viewers.IContentProvider;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.wst.sse.core.utils.StringUtils;
+import org.eclipse.wst.sse.ui.internal.contentoutline.PropertyChangeUpdateAction;
+import org.eclipse.wst.sse.ui.internal.contentoutline.PropertyChangeUpdateActionContributionItem;
+import org.eclipse.wst.sse.ui.internal.editor.EditorPluginImageHelper;
+import org.eclipse.wst.sse.ui.internal.editor.EditorPluginImages;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.contentmodel.basic.CMNamedNodeMapImpl;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.modelquery.ModelQueryUtil;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+import org.eclipse.wst.xml.ui.internal.contentoutline.JFaceNodeContentProvider;
+import org.eclipse.wst.xml.ui.internal.contentoutline.JFaceNodeLabelProvider;
+import org.eclipse.wst.xml.ui.internal.preferences.XMLUIPreferenceNames;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+/**
+ * More advanced Outline Configuration for XML support.  Expects that the viewer's
+ * input will be the DOM Model.
+ * 
+ * @see AbstractXMLContentOutlineConfiguration
+ * @since 1.0
+ */
+public class XMLContentOutlineConfiguration extends AbstractXMLContentOutlineConfiguration {
+	static final String ATTR_NAME = "name";
+	static final String ATTR_ID = "id";
+
+	private class AttributeShowingLabelProvider extends JFaceNodeLabelProvider {
+		public boolean isLabelProperty(Object element, String property) {
+			return true;
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see org.eclipse.jface.viewers.ILabelProvider#getText(java.lang.Object)
+		 */
+		public String getText(Object o) {
+			StringBuffer text = null;
+			if (o instanceof Node) {
+				Node node = (Node) o;
+				if ((node.getNodeType() == Node.ELEMENT_NODE) && fShowAttributes) {
+					text = new StringBuffer(super.getText(o));
+					// https://bugs.eclipse.org/bugs/show_bug.cgi?id=88444
+					if (node.hasAttributes()) {
+						Element element = (Element) node;
+						NamedNodeMap attributes = element.getAttributes();
+						Node idTypedAttribute = null;
+						Node requiredAttribute = null;
+						boolean hasId = false;
+						boolean hasName = false;
+						Node shownAttribute = null;
+
+						// try to get content model element
+						// declaration
+						CMElementDeclaration elementDecl = null;
+						ModelQuery mq = ModelQueryUtil.getModelQuery(element.getOwnerDocument());
+						if (mq != null) {
+							elementDecl = mq.getCMElementDeclaration(element);
+						}
+						// find an attribute of type (or just named)
+						// ID
+						if (elementDecl != null) {
+							int i = 0;
+							while ((i < attributes.getLength()) && (idTypedAttribute == null)) {
+								Node attr = attributes.item(i);
+								String attrName = attr.getNodeName();
+								CMNamedNodeMap attributeDeclarationMap = elementDecl.getAttributes();
+								
+								CMNamedNodeMapImpl allAttributes = new CMNamedNodeMapImpl(attributeDeclarationMap);
+								List nodes = ModelQueryUtil.getModelQuery(node.getOwnerDocument()).getAvailableContent(element, elementDecl, ModelQuery.INCLUDE_ATTRIBUTES);
+								for (int k = 0; k < nodes.size(); k++) {
+									CMNode cmnode = (CMNode) nodes.get(k);
+									if (cmnode.getNodeType() == CMNode.ATTRIBUTE_DECLARATION) {
+										allAttributes.put(cmnode);
+									}
+								}
+								attributeDeclarationMap = allAttributes;
+
+								CMAttributeDeclaration attrDecl = (CMAttributeDeclaration) attributeDeclarationMap.getNamedItem(attrName);
+								if (attrDecl != null) {
+									if ((attrDecl.getAttrType() != null) && (CMDataType.ID.equals(attrDecl.getAttrType().getDataTypeName()))) {
+										idTypedAttribute = attr;
+									}
+									else if ((attrDecl.getUsage() == CMAttributeDeclaration.REQUIRED) && (requiredAttribute == null)) {
+										// as a backup, keep tabs on
+										// any required
+										// attributes
+										requiredAttribute = attr;
+									}
+									else {
+										hasId = hasId || attrName.equals(ATTR_ID);
+										hasName = hasName || attrName.equals(ATTR_NAME);
+									}
+								}
+								++i;
+							}
+						}
+
+						/*
+						 * If no suitable attribute was found, try using a
+						 * required attribute, if none, then prefer "id" or
+						 * "name", otherwise just use first attribute
+						 */
+						if (idTypedAttribute != null) {
+							shownAttribute = idTypedAttribute;
+						}
+						else if (requiredAttribute != null) {
+							shownAttribute = requiredAttribute;
+						}
+						else if (hasId) {
+							shownAttribute = attributes.getNamedItem(ATTR_ID);
+						}
+						else if (hasName) {
+							shownAttribute = attributes.getNamedItem(ATTR_NAME);
+						}
+						if (shownAttribute == null) {
+							shownAttribute = attributes.item(0);
+						}
+
+						// display the attribute and value (without quotes)
+						String attributeName = shownAttribute.getNodeName();
+						if ((attributeName != null) && (attributeName.length() > 0)) {
+							text.append(" "); //$NON-NLS-1$
+							text.append(attributeName);
+							String attributeValue = shownAttribute.getNodeValue();
+							if ((attributeValue != null) && (attributeValue.length() > 0)) {
+								text.append("="); //$NON-NLS-1$
+								text.append(StringUtils.strip(attributeValue));
+							}
+						}
+					}
+				}
+				else {
+					text = new StringBuffer(super.getText(o));
+				}
+			}
+			else {
+				return super.toString();
+			}
+			return text.toString();
+		}
+
+		/* (non-Javadoc)
+		 * @see org.eclipse.jface.viewers.CellLabelProvider#getToolTipText(java.lang.Object)
+		 */
+		public String getToolTipText(Object element) {
+			if (element instanceof Node) {
+				switch (((Node) element).getNodeType()) {
+					case Node.COMMENT_NODE :
+					case Node.CDATA_SECTION_NODE :
+					case Node.PROCESSING_INSTRUCTION_NODE :
+					case Node.TEXT_NODE : {
+						String nodeValue = ((Node) element).getNodeValue().trim();
+						return prepareText(nodeValue);
+					}
+					case Node.ELEMENT_NODE : {
+						// show the preceding comment's tooltip information
+						Node previous = ((Node) element).getPreviousSibling();
+						if (previous != null && previous.getNodeType() == Node.TEXT_NODE)
+							previous = previous.getPreviousSibling();
+						if (previous != null && previous.getNodeType() == Node.COMMENT_NODE)
+							return getToolTipText(previous);
+					}
+				}
+			}
+			return super.getToolTipText(element);
+		}
+
+		/**
+		 * Remove leading indentation from each line in the give string.
+		 * @param text
+		 * @return
+		 */
+		private String prepareText(String text) {
+			StringBuffer nodeText = new StringBuffer();
+			for (int i = 0; i < text.length(); i++) {
+				char c = text.charAt(i);
+				if (c != '\r' && c != '\n') {
+					nodeText.append(c);
+				}
+				else if (c == '\r' || c == '\n') {
+					nodeText.append('\n');
+					while (Character.isWhitespace(c) && i < text.length()) {
+						i++;
+						c = text.charAt(i);
+					}
+					nodeText.append(c);
+				}
+			}
+			return nodeText.toString();
+		}
+	}
+
+	/**
+	 * Toggle action for whether or not to display element's first attribute
+	 */
+	private class ToggleShowAttributeAction extends PropertyChangeUpdateAction {
+		// https://bugs.eclipse.org/bugs/show_bug.cgi?id=88444
+		private TreeViewer fTreeViewer;
+
+		public ToggleShowAttributeAction(IPreferenceStore store, String preference, TreeViewer treeViewer) {
+			super(XMLUIMessages.XMLContentOutlineConfiguration_0, store, preference, true);
+			setToolTipText(getText());
+			// images needed
+			// setDisabledImageDescriptor(SYNCED_D);
+			// (nsd) temporarily re-use Properties view image
+			setImageDescriptor(EditorPluginImageHelper.getInstance().getImageDescriptor(EditorPluginImages.IMG_OBJ_PROP_PS));
+			fTreeViewer = treeViewer;
+			update();
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see org.eclipse.ui.texteditor.IUpdate#update()
+		 */
+		public void update() {
+			super.update();
+			fShowAttributes = isChecked();
+
+			// notify the configuration of the change
+			enableShowAttributes(fShowAttributes, fTreeViewer);
+
+			// refresh the outline view
+			fTreeViewer.refresh(true);
+		}
+	}
+	
+	private ILabelProvider fAttributeShowingLabelProvider;
+	private IContentProvider fContentProvider = null;
+
+	boolean fShowAttributes = false;
+
+	/*
+	 * Preference key for Show Attributes
+	 */
+	private final String OUTLINE_SHOW_ATTRIBUTE_PREF = "outline-show-attribute"; //$NON-NLS-1$
+
+	/**
+	 * Create new instance of XMLContentOutlineConfiguration
+	 */
+	public XMLContentOutlineConfiguration() {
+		// Must have empty constructor to createExecutableExtension
+		super();
+
+		/**
+		 * Set up our preference store here. This is done so that subclasses
+		 * aren't required to set their own values, although if they have,
+		 * those will be used instead.
+		 */
+		IPreferenceStore store = getPreferenceStore();
+		if (store.getDefaultString(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.DOCUMENT_NODE).length() == 0)
+			store.setDefault(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.DOCUMENT_NODE, "1, true");
+		if (store.getDefaultString(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.PROCESSING_INSTRUCTION_NODE).length() == 0)
+			store.setDefault(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.PROCESSING_INSTRUCTION_NODE, "2, true");
+		if (store.getDefaultString(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.DOCUMENT_TYPE_NODE).length() == 0)
+			store.setDefault(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.DOCUMENT_TYPE_NODE, "3, true");
+		if (store.getDefaultString(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.DOCUMENT_FRAGMENT_NODE).length() == 0)
+			store.setDefault(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.DOCUMENT_FRAGMENT_NODE, "4, true");
+		if (store.getDefaultString(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.COMMENT_NODE).length() == 0)
+			store.setDefault(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.COMMENT_NODE, "5, true");
+		if (store.getDefaultString(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.ATTRIBUTE_NODE).length() == 0)
+			store.setDefault(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.ATTRIBUTE_NODE, "6, false");
+		if (store.getDefaultString(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.ELEMENT_NODE).length() == 0)
+			store.setDefault(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.ELEMENT_NODE, "7, true");
+		if (store.getDefaultString(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.ENTITY_REFERENCE_NODE).length() == 0)
+			store.setDefault(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.ENTITY_REFERENCE_NODE, "8, true");
+		if (store.getDefaultString(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.CDATA_SECTION_NODE).length() == 0)
+			store.setDefault(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.CDATA_SECTION_NODE, "9, true");
+		if (store.getDefaultString(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.ENTITY_NODE).length() == 0)
+			store.setDefault(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.ENTITY_NODE, "10, true");
+		if (store.getDefaultString(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.NOTATION_NODE).length() == 0)
+			store.setDefault(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.NOTATION_NODE, "11, true");
+		if (store.getDefaultString(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.TEXT_NODE).length() == 0)
+			store.setDefault(XMLUIPreferenceNames.OUTLINE_BEHAVIOR.TEXT_NODE, "12, false");
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.wst.sse.ui.views.contentoutline.ContentOutlineConfiguration#createMenuContributions(org.eclipse.jface.viewers.TreeViewer)
+	 */
+	protected IContributionItem[] createMenuContributions(TreeViewer viewer) {
+		IContributionItem[] items;
+		// https://bugs.eclipse.org/bugs/show_bug.cgi?id=88444
+		IContributionItem showAttributeItem = new PropertyChangeUpdateActionContributionItem(new ToggleShowAttributeAction(getPreferenceStore(), OUTLINE_SHOW_ATTRIBUTE_PREF, viewer));
+
+		items = super.createMenuContributions(viewer);
+		if (items == null) {
+			items = new IContributionItem[]{showAttributeItem};
+		}
+		else {
+			IContributionItem[] combinedItems = new IContributionItem[items.length + 1];
+			System.arraycopy(items, 0, combinedItems, 0, items.length);
+			combinedItems[items.length] = showAttributeItem;
+			items = combinedItems;
+		}
+		return items;
+	}
+
+	/**
+	 * Notifies this configuration that the flag that indicates whether or not
+	 * to show attribute values in the tree viewer has changed. The tree
+	 * viewer is automatically refreshed afterwards to update the labels.
+	 * 
+	 * Clients should not call this method, but rather should react to it.
+	 * 
+	 * @param showAttributes
+	 *            flag indicating whether or not to show attribute values in
+	 *            the tree viewer
+	 * @param treeViewer
+	 *            the TreeViewer associated with this configuration
+	 */
+	protected void enableShowAttributes(boolean showAttributes, TreeViewer treeViewer) {
+		// nothing by default
+	}
+	
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.wst.sse.ui.views.contentoutline.ContentOutlineConfiguration#getContentProvider(org.eclipse.jface.viewers.TreeViewer)
+	 */
+	public IContentProvider getContentProvider(TreeViewer viewer) {
+		if (fContentProvider == null) {
+			fContentProvider = new JFaceNodeContentProvider();
+		}
+		return fContentProvider;
+	}
+
+	private Object getFilteredNode(Object object) {
+		if (object instanceof Node) {
+			Node node = (Node) object;
+			short nodeType = node.getNodeType();
+			// replace attribute node in selection with its parent
+			if (nodeType == Node.ATTRIBUTE_NODE) {
+				node = ((Attr) node).getOwnerElement();
+			}
+			// anything else not visible, replace with parent node
+			else if (nodeType == Node.TEXT_NODE) {
+				node = node.getParentNode();
+			}
+			return node;
+		}
+		return object;
+	}
+
+	private Object[] getFilteredNodes(Object[] filteredNodes) {
+		for (int i = 0; i < filteredNodes.length; i++) {
+			filteredNodes[i] = getFilteredNode(filteredNodes[i]);
+		}
+		return filteredNodes;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.wst.sse.ui.views.contentoutline.ContentOutlineConfiguration#getLabelProvider(org.eclipse.jface.viewers.TreeViewer)
+	 */
+	public ILabelProvider getLabelProvider(TreeViewer viewer) {
+		if (fAttributeShowingLabelProvider == null) {
+			fAttributeShowingLabelProvider = new AttributeShowingLabelProvider();
+		}
+		return fAttributeShowingLabelProvider;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.wst.sse.ui.views.contentoutline.ContentOutlineConfiguration#getSelection(org.eclipse.jface.viewers.TreeViewer,
+	 *      org.eclipse.jface.viewers.ISelection)
+	 */
+	public ISelection getSelection(TreeViewer viewer, ISelection selection) {
+		ISelection filteredSelection = selection;
+		if (selection instanceof IStructuredSelection) {
+			Object[] filteredNodes = getFilteredNodes(((IStructuredSelection) selection).toArray());
+			filteredSelection = new StructuredSelection(filteredNodes);
+		}
+		return filteredSelection;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/properties/XMLPropertySheetConfiguration.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/properties/XMLPropertySheetConfiguration.java
new file mode 100644
index 0000000..a4f3a4e
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/properties/XMLPropertySheetConfiguration.java
@@ -0,0 +1,282 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2009 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.views.properties;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.progress.UIJob;
+import org.eclipse.ui.views.properties.IPropertySheetPage;
+import org.eclipse.ui.views.properties.IPropertySource;
+import org.eclipse.ui.views.properties.IPropertySourceProvider;
+import org.eclipse.ui.views.properties.PropertySheetPage;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapter;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+import org.eclipse.wst.sse.ui.views.properties.PropertySheetConfiguration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.CMDocumentManager;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.CMDocumentManagerListener;
+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.CMDocumentCache;
+import org.eclipse.wst.xml.core.internal.modelquery.ModelQueryUtil;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
+import org.eclipse.wst.xml.ui.internal.properties.XMLPropertySource;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+/**
+ * Configuration for property sheet page which shows XML content.
+ * 
+ * @see org.eclipse.wst.sse.ui.views.properties.PropertySheetConfiguration
+ * @since 1.0
+ */
+public class XMLPropertySheetConfiguration extends PropertySheetConfiguration {
+	private class CMDocumentManagerListenerImpl implements CMDocumentManagerListener {
+		public void cacheCleared(CMDocumentCache cache) {
+			// nothing to do
+		}
+
+		public void cacheUpdated(CMDocumentCache cache, final String uri, int oldStatus, int newStatus, CMDocument cmDocument) {
+			if ((newStatus == CMDocumentCache.STATUS_LOADED) || (newStatus == CMDocumentCache.STATUS_ERROR)) {
+				refreshPages();
+			}
+		}
+
+		public void propertyChanged(CMDocumentManager cmDocumentManager, String propertyName) {
+			if (cmDocumentManager.getPropertyEnabled(CMDocumentManager.PROPERTY_AUTO_LOAD)) {
+				refreshPages();
+			}
+		}
+
+		private void refreshPages() {
+			getPropertiesRefreshJob().addPropertySheetPage(fPropertySheetPage);
+			getPropertiesRefreshJob().schedule(PropertiesRefreshJob.UPDATE_DELAY);
+		}
+	}
+
+	private class PropertiesRefreshJob extends UIJob {
+		public static final int UPDATE_DELAY = 200;
+
+		Set propertySheetPages = null;
+
+		public PropertiesRefreshJob() {
+			super(XMLUIMessages.JFaceNodeAdapter_1);
+			setSystem(true);
+			setPriority(Job.SHORT);
+			propertySheetPages = new HashSet(1);
+		}
+
+		void addPropertySheetPage(IPropertySheetPage page) {
+			if (page != null && propertySheetPages != null) {
+				propertySheetPages.add(page);
+				schedule(UPDATE_DELAY);
+			}
+		}
+		
+		/* (non-Javadoc)
+		 * @see org.eclipse.core.runtime.jobs.Job#canceling()
+		 */
+		protected void canceling() {
+			propertySheetPages.clear();
+			super.canceling();
+		}
+
+		public IStatus runInUIThread(IProgressMonitor monitor) {
+			Object[] pages = propertySheetPages.toArray();
+			propertySheetPages.clear();
+
+			for (int i = 0; i < pages.length; i++) {
+				PropertySheetPage page = (PropertySheetPage) pages[i];
+				if ((page != null) && (page.getControl() != null) && !page.getControl().isDisposed()) {
+					page.refresh();
+				}
+			}
+
+			return Status.OK_STATUS;
+		}
+	}
+
+	private class XMLPropertySheetRefreshAdapter implements INodeAdapter {
+		public boolean isAdapterForType(Object type) {
+			return false;
+		}
+
+		public void notifyChanged(INodeNotifier notifier, int eventType, Object changedFeature, Object oldValue, Object newValue, int pos) {
+			if (fPropertySheetPage != null) {
+				getPropertiesRefreshJob().addPropertySheetPage(fPropertySheetPage);
+			}
+		}
+	}
+
+	private class XMLPropertySourceProvider implements IPropertySourceProvider {
+		private IPropertySource fPropertySource = null;
+		private INodeNotifier fSource = null;
+
+		public IPropertySource getPropertySource(Object object) {
+			if ((fSource != null) && object.equals(fSource)) {
+				return fPropertySource;
+			}
+
+			if (object instanceof IDOMNode) {
+				fSource = (INodeNotifier) object;
+				fPropertySource = (IPropertySource) fSource.getAdapterFor(IPropertySource.class);
+				if (fPropertySource == null) {
+					fPropertySource = new XMLPropertySource((INodeNotifier) object) {
+						public void setPropertyValue(Object nameObject, Object value) {
+							// https://bugs.eclipse.org/bugs/show_bug.cgi?id=218979
+							for (int i = 0; i < fSelectedNotifiers.length; i++) {
+								fSelectedNotifiers[i].removeAdapter(fRefreshAdapter);
+							}
+							super.setPropertyValue(nameObject, value);
+							for (int i = 0; i < fSelectedNotifiers.length; i++) {
+								fSelectedNotifiers[i].addAdapter(fRefreshAdapter);
+							}
+						}
+					};
+				}
+			}
+			else {
+				fSource = null;
+				fPropertySource = null;
+			}
+			return fPropertySource;
+		}
+	}
+
+	private CMDocumentManagerListenerImpl fCMDocumentManagerListener = new CMDocumentManagerListenerImpl();
+	private PropertiesRefreshJob fPropertiesRefreshJob = null;
+	IPropertySheetPage fPropertySheetPage = null;
+	private IPropertySourceProvider fPropertySourceProvider = null;
+	private INodeAdapter fRefreshAdapter = new XMLPropertySheetRefreshAdapter();
+	private CMDocumentManager[] fSelectedCMDocumentManagers = new CMDocumentManager[0];
+	private INodeNotifier[] fSelectedNotifiers = new INodeNotifier[0];
+
+
+	/**
+	 * Create new instance of XMLPropertySheetConfiguration
+	 */
+	public XMLPropertySheetConfiguration() {
+		// Must have empty constructor to createExecutableExtension
+		super();
+	}
+
+	public ISelection getInputSelection(IWorkbenchPart selectingPart, ISelection selection) {
+		if (fSelectedNotifiers != null) {
+			for (int i = 0; i < fSelectedNotifiers.length; i++) {
+				fSelectedNotifiers[i].removeAdapter(fRefreshAdapter);
+			}
+			fSelectedNotifiers = null;
+		}
+		for (int i = 0; i < fSelectedCMDocumentManagers.length; i++) {
+			fSelectedCMDocumentManagers[i].removeListener(fCMDocumentManagerListener);
+		}
+
+		ISelection preferredSelection = selection;
+		if (selection instanceof IStructuredSelection) {
+			IStructuredSelection structuredSel = (IStructuredSelection) selection;
+
+			/*
+			 * On Attr nodes, select the owner Element. On Text nodes, select
+			 * the parent Element.
+			 */
+			Object[] selectedObjects = new Object[structuredSel.size()];
+			System.arraycopy(structuredSel.toArray(), 0, selectedObjects, 0, selectedObjects.length);
+			for (int i = 0; i < selectedObjects.length; i++) {
+				Object inode = selectedObjects[i];
+				if (inode instanceof Node) {
+					Node node = (Node) inode;
+					// replace Attribute Node with its owner
+					Node parentNode = node.getParentNode();
+					if (node.getNodeType() == Node.ATTRIBUTE_NODE) {
+						Element ownerElement = ((Attr) node).getOwnerElement();
+						selectedObjects[i] = ownerElement;
+					}
+					// replace Text Node with its parent
+					else if (((node.getNodeType() == Node.TEXT_NODE) || (node.getNodeType() == Node.CDATA_SECTION_NODE)) && (parentNode != null)) {
+						selectedObjects[i] = parentNode;
+					}
+				}
+			}
+
+			if (selectedObjects.length > 0) {
+				Set managers = new HashSet(1);
+				Set selectedNotifiers = new HashSet(1);
+
+				for (int i = 0; i < selectedObjects.length; i++) {
+					if (selectedObjects[i] instanceof Node) {
+						ModelQuery query = ModelQueryUtil.getModelQuery(((Node) selectedObjects[i]).getOwnerDocument());
+						if (query != null) {
+							CMDocumentManager mgr = query.getCMDocumentManager();
+							if (mgr != null) {
+								managers.add(mgr);
+								mgr.addListener(fCMDocumentManagerListener);
+							}
+						}
+					}
+					/*
+					 * Add UI refresh adapters and remember notifiers for
+					 * later removal
+					 */
+					if (selectedObjects[i] instanceof INodeNotifier) {
+						selectedNotifiers.add(selectedObjects[i]);
+						((INodeNotifier) selectedObjects[i]).addAdapter(fRefreshAdapter);
+					}
+				}
+				fSelectedCMDocumentManagers = (CMDocumentManager[]) managers.toArray(new CMDocumentManager[managers.size()]);
+				fSelectedNotifiers = (INodeNotifier[]) selectedNotifiers.toArray(new INodeNotifier[selectedNotifiers.size()]);
+			}
+
+
+			preferredSelection = new StructuredSelection(selectedObjects);
+		}
+		return preferredSelection;
+	}
+
+	PropertiesRefreshJob getPropertiesRefreshJob() {
+		if (fPropertiesRefreshJob == null) {
+			fPropertiesRefreshJob = new PropertiesRefreshJob();
+		}
+		return fPropertiesRefreshJob;
+	}
+
+	public IPropertySourceProvider getPropertySourceProvider(IPropertySheetPage page) {
+		if (fPropertySourceProvider == null) {
+			fPropertySheetPage = page;
+			fPropertySourceProvider = new XMLPropertySourceProvider();
+		}
+		return fPropertySourceProvider;
+	}
+
+
+	public void unconfigure() {
+		super.unconfigure();
+		for (int i = 0; i < fSelectedCMDocumentManagers.length; i++) {
+			fSelectedCMDocumentManagers[i].removeListener(fCMDocumentManagerListener);
+		}
+		if(fPropertiesRefreshJob != null) {
+			fPropertiesRefreshJob.cancel();
+			fPropertiesRefreshJob.propertySheetPages = null;
+		}
+		fPropertySheetPage = null;
+	}
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/templates/xmldefault-templates.properties b/bundles/org.eclipse.wst.xml.ui/templates/xmldefault-templates.properties
new file mode 100644
index 0000000..8b5177a
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/templates/xmldefault-templates.properties
@@ -0,0 +1,26 @@
+###############################################################################
+# Copyright (c) 2001, 2005 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
+#     Jens Lukowski/Innoopract - initial renaming/restructuring
+#     
+###############################################################################
+Templates.comment.name=comment
+Templates.comment.desc=xml comment
+Templates.xmldeclaration.name=xml declaration
+Templates.xmldeclaration.desc=xml declaration
+Templates.xslpi.name=XSL processing instruction
+Templates.xslpi.desc=XSL processing instruction
+Templates.xsinsp.name=xsinsp
+Templates.xsinsp.desc=XML Schema name space
+Templates.schemaLoc.name=schemaLoc
+Templates.schemaLoc.desc=XML Schema location attribute
+Templates.noschemaLoc.name=noschemaLoc
+Templates.noschemaLoc.desc=No Namespace Schema Location
+Templates.defaultnsp.name=default namespace
+Templates.defaultnsp.desc=Default Namespace Attribute
diff --git a/bundles/org.eclipse.wst.xml.ui/templates/xmldefault-templates.xml b/bundles/org.eclipse.wst.xml.ui/templates/xmldefault-templates.xml
new file mode 100644
index 0000000..b4ad498
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/templates/xmldefault-templates.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 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
+ *     David Carver - added templates for xsi namespace, schemaLocation, and
+                      default namespace
+ *******************************************************************************/
+ -->
+<templates>
+  <template name="%Templates.xmldeclaration.name" description="%Templates.xmldeclaration.desc" id="org.eclipse.wst.xml.ui.internal.templates.xmldeclaration" context="xml_new" enabled="true">&lt;?xml version="1.0" encoding="${encoding}"?&gt;</template>
+  <template name="%Templates.comment.name" description="%Templates.comment.desc" id="org.eclipse.wst.xml.ui.internal.templates.comment" context="xml_tag" enabled="true">&lt;!-- ${cursor} --&gt;</template>
+  <template name="%Templates.xslpi.name" description="%Templates.xslpi.desc" id="org.eclipse.wst.xml.ui.internal.templates.xslpi" context="xml_tag" enabled="true">&lt;?xml-stylesheet type="text/xsl" href="${cursor}"?&gt;</template>
+  <template name="%Templates.xsinsp.name" description="%Templates.xsinsp.desc" id="org.eclipse.wst.xml.ui.internal.templates.xsinsp" context="xml_attribute" enabled="true">xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"</template>
+  <template name="%Templates.schemaLoc.name" description="%Templates.schemaLoc.desc" id="org.eclipse.wst.xml.ui.internal.templates.schemaLoc" context="xml_attribute" enabled="true">xsi:schemaLocation="{namespace} {location}"</template>
+  <template name="%Templates.noschemaLoc.name" description="%Templates.noschemaLoc.desc" id="org.eclipse.wst.xml.ui.internal.templates.noschemaLoc" context="xml_attribute" enabled="true">xsi:noNamespaceSchemaLocation="{location}"</template>
+  <template name="%Templates.defaultnsp.name" description="%Templates.defaultnsp.desc" id="org.eclipse.wst.xml.ui.internal.templates.defaultnsp" context="xml_attribute" enabled="true">xmlns="default namespace"</template>
+</templates>
diff --git a/bundles/org.eclipse.wst.xsd.core/.classpath b/bundles/org.eclipse.wst.xsd.core/.classpath
new file mode 100644
index 0000000..4710c45
--- /dev/null
+++ b/bundles/org.eclipse.wst.xsd.core/.classpath
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src-contentmodel" />
+	<classpathentry kind="src" path="src-validation" />
+	<classpathentry kind="src" path="src" />
+	<classpathentry kind="con"
+		path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.4">
+		<accessrules>
+			<accessrule kind="accessible"
+				pattern="org/apache/xerces/impl/Constants" />
+			<accessrule kind="accessible"
+				pattern="org/apache/xerces/parsers/XMLGrammarPreparser" />
+			<accessrule kind="accessible"
+				pattern="org/apache/xerces/util/XMLGrammarPoolImpl" />
+			<accessrule kind="accessible"
+				pattern="org/apache/xerces/xni/XMLResourceIdentifier" />
+			<accessrule kind="accessible"
+				pattern="org/apache/xerces/xni/XNIException" />
+			<accessrule kind="accessible"
+				pattern="org/apache/xerces/xni/grammars/XMLGrammarDescription" />
+			<accessrule kind="accessible"
+				pattern="org/apache/xerces/xni/parser/XMLEntityResolver" />
+			<accessrule kind="accessible"
+				pattern="org/apache/xerces/xni/parser/XMLErrorHandler" />
+			<accessrule kind="accessible"
+				pattern="org/apache/xerces/xni/parser/XMLInputSource" />
+			<accessrule kind="accessible"
+				pattern="org/apache/xerces/xni/parser/XMLParseException" />
+		</accessrules>
+	</classpathentry>
+	<classpathentry kind="con"
+		path="org.eclipse.pde.core.requiredPlugins">
+		<accessrules>
+			<accessrule kind="accessible"
+				pattern="org/eclipse/wst/validation/internal/provisional/core/IMessage" />
+			<accessrule kind="accessible"
+				pattern="org/eclipse/wst/validation/internal/delegates/DelegatingValidator" />
+		</accessrules>
+	</classpathentry>
+	<classpathentry kind="output" path="bin" />
+</classpath>
diff --git a/bundles/org.eclipse.wst.xsd.core/.cvsignore b/bundles/org.eclipse.wst.xsd.core/.cvsignore
new file mode 100644
index 0000000..33dd7de
--- /dev/null
+++ b/bundles/org.eclipse.wst.xsd.core/.cvsignore
@@ -0,0 +1,6 @@
+bin
+temp.folder
+build.xml
+@dot
+src.zip
+javaCompiler...args
diff --git a/bundles/org.eclipse.wst.xsd.core/.project b/bundles/org.eclipse.wst.xsd.core/.project
new file mode 100644
index 0000000..a95f8ef
--- /dev/null
+++ b/bundles/org.eclipse.wst.xsd.core/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.wst.xsd.core</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.ManifestBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.SchemaBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.PluginNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
diff --git a/bundles/org.eclipse.wst.xsd.core/.settings/org.eclipse.core.resources.prefs b/bundles/org.eclipse.wst.xsd.core/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..afa5c91
--- /dev/null
+++ b/bundles/org.eclipse.wst.xsd.core/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+#Tue Apr 04 03:36:32 EDT 2006
+eclipse.preferences.version=1
+encoding/<project>=ISO-8859-1
diff --git a/bundles/org.eclipse.wst.xsd.core/.settings/org.eclipse.core.runtime.prefs b/bundles/org.eclipse.wst.xsd.core/.settings/org.eclipse.core.runtime.prefs
new file mode 100644
index 0000000..7ec5750
--- /dev/null
+++ b/bundles/org.eclipse.wst.xsd.core/.settings/org.eclipse.core.runtime.prefs
@@ -0,0 +1,3 @@
+#Mon Apr 17 01:48:39 EDT 2006
+eclipse.preferences.version=1
+line.separator=\r\n
diff --git a/bundles/org.eclipse.wst.xsd.core/.settings/org.eclipse.jdt.core.prefs b/bundles/org.eclipse.wst.xsd.core/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..ab5558f
--- /dev/null
+++ b/bundles/org.eclipse.wst.xsd.core/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,79 @@
+#Sat Mar 24 02:19:12 EDT 2007
+eclipse.preferences.version=1
+org.eclipse.jdt.core.builder.cleanOutputFolder=clean
+org.eclipse.jdt.core.builder.duplicateResourceTask=warning
+org.eclipse.jdt.core.builder.invalidClasspath=ignore
+org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch
+org.eclipse.jdt.core.circularClasspath=error
+org.eclipse.jdt.core.classpath.exclusionPatterns=enabled
+org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=disabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.2
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.4
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.doc.comment.support=enabled
+org.eclipse.jdt.core.compiler.maxProblemPerUnit=100
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=warning
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.deprecation=ignore
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=enabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=warning
+org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=ignore
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=error
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=error
+org.eclipse.jdt.core.compiler.problem.invalidJavadoc=ignore
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=private
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=error
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=enabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public
+org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=enabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=private
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=error
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=error
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=error
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=enabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=error
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=ignore
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=error
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedImport=error
+org.eclipse.jdt.core.compiler.problem.unusedLabel=error
+org.eclipse.jdt.core.compiler.problem.unusedLocal=error
+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=error
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.3
+org.eclipse.jdt.core.incompatibleJDKLevel=ignore
+org.eclipse.jdt.core.incompleteClasspath=error
diff --git a/bundles/org.eclipse.wst.xsd.core/.settings/org.eclipse.jdt.ui.prefs b/bundles/org.eclipse.wst.xsd.core/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000..301c7ad
--- /dev/null
+++ b/bundles/org.eclipse.wst.xsd.core/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,4 @@
+#Mon Apr 17 01:48:39 EDT 2006
+eclipse.preferences.version=1
+internal.default.compliance=default
+org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8"?>\r\n<templates/>
diff --git a/bundles/org.eclipse.wst.xsd.core/.settings/org.eclipse.ltk.core.refactoring.prefs b/bundles/org.eclipse.wst.xsd.core/.settings/org.eclipse.ltk.core.refactoring.prefs
new file mode 100644
index 0000000..c59368c
--- /dev/null
+++ b/bundles/org.eclipse.wst.xsd.core/.settings/org.eclipse.ltk.core.refactoring.prefs
@@ -0,0 +1,3 @@
+#Tue Apr 04 03:36:32 EDT 2006
+eclipse.preferences.version=1
+org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false
diff --git a/bundles/org.eclipse.wst.xsd.core/.settings/org.eclipse.pde.prefs b/bundles/org.eclipse.wst.xsd.core/.settings/org.eclipse.pde.prefs
new file mode 100644
index 0000000..e70985d
--- /dev/null
+++ b/bundles/org.eclipse.wst.xsd.core/.settings/org.eclipse.pde.prefs
@@ -0,0 +1,16 @@
+#Wed Nov 15 02:13:10 EST 2006
+compilers.incompatible-environment=0
+compilers.p.build=0
+compilers.p.deprecated=1
+compilers.p.illegal-att-value=0
+compilers.p.no-required-att=0
+compilers.p.not-externalized-att=0
+compilers.p.unknown-attribute=0
+compilers.p.unknown-class=0
+compilers.p.unknown-element=1
+compilers.p.unknown-resource=0
+compilers.p.unresolved-ex-points=0
+compilers.p.unresolved-import=0
+compilers.p.unused-element-or-attribute=0
+compilers.use-project=true
+eclipse.preferences.version=1
diff --git a/bundles/org.eclipse.wst.xsd.core/META-INF/MANIFEST.MF b/bundles/org.eclipse.wst.xsd.core/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..36e0b49
--- /dev/null
+++ b/bundles/org.eclipse.wst.xsd.core/META-INF/MANIFEST.MF
@@ -0,0 +1,22 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %_UI_PLUGIN_NAME
+Bundle-SymbolicName: org.eclipse.wst.xsd.core; singleton:=true
+Bundle-Version: 1.1.503.qualifier
+Bundle-Activator: org.eclipse.wst.xsd.core.internal.XSDCorePlugin
+Bundle-Vendor: %Bundle-Vendor.0
+Bundle-Localization: plugin
+Export-Package: org.eclipse.wst.xsd.contentmodel.internal;x-friends:="org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.xsd.contentmodel.internal.util;x-internal:=true,
+ org.eclipse.wst.xsd.core.internal;x-friends:="org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.xsd.core.internal.preferences;x-friends:="org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.xsd.core.internal.validation;x-internal:=true,
+ org.eclipse.wst.xsd.core.internal.validation.eclipse;x-internal:=true 
+Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.2.0,4.0.0)",
+ org.eclipse.wst.common.uriresolver;bundle-version="[1.1.0,1.2.0)",
+ org.eclipse.xsd;bundle-version="[2.2.0,3.0.0)",
+ org.eclipse.wst.xml.core;bundle-version="[1.1.0,1.2.0)",
+ org.eclipse.wst.validation;bundle-version="[1.2.0,1.3.0)"
+Bundle-ActivationPolicy: lazy
+Bundle-RequiredExecutionEnvironment: J2SE-1.4
+
diff --git a/bundles/org.eclipse.wst.xsd.core/about.html b/bundles/org.eclipse.wst.xsd.core/about.html
new file mode 100644
index 0000000..2199df3
--- /dev/null
+++ b/bundles/org.eclipse.wst.xsd.core/about.html
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
+<HTML>
+
+<head>
+<title>About</title>
+<meta http-equiv=Content-Type content="text/html; charset=ISO-8859-1">
+</head>
+
+<BODY lang="EN-US">
+
+<H3>About This Content</H3>
+
+<P>June, 2008</P>
+
+<H3>License</H3>
+
+<P>The Eclipse Foundation makes available all content in this plug-in 
+("Content"). Unless otherwise indicated below, the Content is provided to you 
+under the terms and conditions of the Eclipse Public License Version 1.0 
+("EPL"). A copy of the EPL is available at
+<A href="http://www.eclipse.org/org/documents/epl-v10.php">http://www.eclipse.org/org/documents/epl-v10.php</A>. 
+For purposes of the EPL, "Program" will mean the Content.</P>
+
+<P>If you did not receive this Content directly from the Eclipse Foundation, the 
+Content is being redistributed by another party ("Redistributor") and different 
+terms and conditions may apply to your use of any object code in the Content. 
+Check the RedistributorÂ’s license that was provided with the Content. If no such 
+license exists, contact the Redistributor. Unless otherwise indicated below, the 
+terms and conditions of the EPL still apply to any source code in the Content 
+and such source code may be obtained at
+<A href="http://www.eclipse.org/">http://www.eclipse.org/</A>.</P>
+
+</BODY>
+</HTML>
diff --git a/bundles/org.eclipse.wst.xsd.core/build.properties b/bundles/org.eclipse.wst.xsd.core/build.properties
new file mode 100644
index 0000000..984631d
--- /dev/null
+++ b/bundles/org.eclipse.wst.xsd.core/build.properties
@@ -0,0 +1,21 @@
+###############################################################################
+# Copyright (c) 2001, 2005 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
+#     
+###############################################################################
+bin.includes = META-INF/,\
+               plugin.xml,\
+               plugin.properties,\
+               .,\
+               about.html
+jars.compile.order = .
+output.. = bin/
+source.. = src-contentmodel/,\
+           src-validation/,\
+           src/
diff --git a/bundles/org.eclipse.wst.xsd.core/plugin.properties b/bundles/org.eclipse.wst.xsd.core/plugin.properties
new file mode 100644
index 0000000..42ba557
--- /dev/null
+++ b/bundles/org.eclipse.wst.xsd.core/plugin.properties
@@ -0,0 +1,22 @@
+###############################################################################
+# Copyright (c) 2001, 2006 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
+###############################################################################
+! Properties file for component: XML Schema Validator
+
+!
+! Plugin
+!
+_UI_PLUGIN_NAME                           = XSD Core Plugin
+XSD_Content_Type=XSD
+
+_UI_XML_SCHEMA_VALIDATOR                  = XML Schema Validator
+_UI_XERCES_VALIDATOR_DELEGATE       	  = Xerces-based XML Schema Validator
+
+Bundle-Vendor.0 = Eclipse Web Tools Platform
diff --git a/bundles/org.eclipse.wst.xsd.core/plugin.xml b/bundles/org.eclipse.wst.xsd.core/plugin.xml
new file mode 100644
index 0000000..878e651
--- /dev/null
+++ b/bundles/org.eclipse.wst.xsd.core/plugin.xml
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+<plugin>
+
+	<extension point="org.eclipse.core.contenttype.contentTypes">
+		<content-type
+			priority="high"
+			name="%XSD_Content_Type"
+			id="xsdsource"
+			base-type="org.eclipse.core.runtime.xml"
+			default-charset="UTF-8"
+			file-extensions="xsd" />
+	</extension>
+
+	<extension point="org.eclipse.wst.xml.core.documentFactories">
+		<factory
+			type="xsd"
+			class="org.eclipse.wst.xsd.contentmodel.internal.CMDocumentFactoryXSD">
+		</factory>
+	</extension>
+	
+	<!-- ====================================================== -->
+	<!-- Register the XSD validator with the validation 		-->
+	<!-- framework. 										    -->
+	<!-- ====================================================== -->
+	<!--
+	<extension
+		id="xsdValidator"
+		name="%_UI_XML_SCHEMA_VALIDATOR"
+		point="org.eclipse.wst.validation.validator">
+		<validator>
+			<filter
+				objectClass="org.eclipse.core.resources.IFile"
+				caseSensitive="false"
+				nameFilter="*.xsd">
+			</filter>
+			
+			<helper
+				class="org.eclipse.wst.xml.core.internal.validation.core.Helper">
+			</helper>
+			
+			<run
+         async="true"
+         class="org.eclipse.wst.xsd.core.internal.validation.eclipse.XSDDelegatingValidator"
+         enabled="true"
+         fullBuild="true"
+         incremental="true">
+			</run>
+		</validator>
+	</extension>
+	-->
+	
+   <extension id="xsd" name="%_UI_XML_SCHEMA_VALIDATOR" point="org.eclipse.wst.validation.validatorV2">
+      <validator
+            build="true"
+            class="org.eclipse.wst.xsd.core.internal.validation.eclipse.XSDDelegatingValidator"
+            manual="true"
+            sourceid="org.eclipse.wst.xsd.ui.internal.validation.DelegatingSourceValidatorForXSD"
+            version="2"
+            markerId="org.eclipse.xsd.diagnostic">
+         <include>
+            <rules>
+               <fileext caseSensitive="false" ext="xsd"></fileext>
+            </rules>
+         </include>
+      </validator>
+   </extension>
+
+	<extension
+       point="org.eclipse.wst.validation.validatorDelegates">
+    	<delegate
+        	class="org.eclipse.wst.xsd.core.internal.validation.eclipse.Validator"
+			name="%_UI_XERCES_VALIDATOR_DELEGATE"
+        	target="org.eclipse.wst.xsd.core.internal.validation.eclipse.XSDDelegatingValidator"/>
+	 </extension>
+ 	 
+	 <!-- initialize xml core preferences -->
+	<extension point="org.eclipse.core.runtime.preferences">
+		<initializer
+			class="org.eclipse.wst.xsd.core.internal.preferences.XSDCorePreferenceInitializer" />
+	</extension>
+
+	<!-- ====================================================== -->
+	<!-- Add schemas to XML Catalog                             -->
+	<!-- ====================================================== -->
+	<extension
+		point="org.eclipse.wst.xml.core.catalogContributions">
+		<catalogContribution id="default">
+			<uri
+				name="http://www.w3.org/2001/XMLSchema"
+				uri="platform:/plugin/org.eclipse.xsd/cache/www.w3.org/2001/XMLSchema.xsd" />
+			<system
+				systemId="http://www.w3.org/2001/xml.xsd"
+				uri="platform:/plugin/org.eclipse.xsd/cache/www.w3.org/2001/xml.xsd"/>				
+		</catalogContribution>
+	</extension>
+
+</plugin>
diff --git a/bundles/org.eclipse.wst.xsd.core/src-contentmodel/org/eclipse/wst/xsd/contentmodel/internal/CMDocumentFactoryXSD.java b/bundles/org.eclipse.wst.xsd.core/src-contentmodel/org/eclipse/wst/xsd/contentmodel/internal/CMDocumentFactoryXSD.java
new file mode 100644
index 0000000..eaeb5d7
--- /dev/null
+++ b/bundles/org.eclipse.wst.xsd.core/src-contentmodel/org/eclipse/wst/xsd/contentmodel/internal/CMDocumentFactoryXSD.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *******************************************************************************/
+package org.eclipse.wst.xsd.contentmodel.internal;
+
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.contentmodel.factory.CMDocumentFactory;
+import org.eclipse.xsd.XSDPackage;
+
+/**
+ *  This builder handles building .dtd / .xsd grammar files
+ */
+public class CMDocumentFactoryXSD implements CMDocumentFactory
+{
+  public static final String XSD_FILE_TYPE = "XSD";
+
+  public CMDocumentFactoryXSD() 
+  {  
+    // here we call init on the XSD and DTD packages to avoid strange initialization bugs
+    //
+    XSDPackage.eINSTANCE.eClass();
+    XSDPackage.eINSTANCE.getXSDFactory();  
+  }
+
+ 
+  public CMDocument createCMDocument(String uri)
+  {                  	
+    CMDocument result = null;
+    try
+    {                                
+        result = XSDImpl.buildCMDocument(uri);     
+    }
+    catch (Exception e)
+    {
+    	e.printStackTrace();
+    }
+    return result;  
+  } 
+}
diff --git a/bundles/org.eclipse.wst.xsd.core/src-contentmodel/org/eclipse/wst/xsd/contentmodel/internal/CMNodeImpl.java b/bundles/org.eclipse.wst.xsd.core/src-contentmodel/org/eclipse/wst/xsd/contentmodel/internal/CMNodeImpl.java
new file mode 100644
index 0000000..9fca578
--- /dev/null
+++ b/bundles/org.eclipse.wst.xsd.core/src-contentmodel/org/eclipse/wst/xsd/contentmodel/internal/CMNodeImpl.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xsd.contentmodel.internal;
+
+import org.eclipse.emf.common.notify.impl.AdapterImpl;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+
+public abstract class CMNodeImpl extends AdapterImpl implements CMNode
+{
+  protected static final String PROPERTY_DOCUMENTATION = "documentation";
+  protected static final String PROPERTY_DOCUMENTATION_SOURCE = "documentationSource";
+  protected static final String PROPERTY_DOCUMENTATION_LANGUAGE = "documentationLanguage";
+  protected static final String PROPERTY_MOF_NOTIFIER = "key";
+  protected static final String PROPERTY_DEFINITION_INFO = "http://org.eclipse.wst/cm/properties/definitionInfo";
+  protected static final String PROPERTY_DEFINITION = "http://org.eclipse.wst/cm/properties/definition";
+
+  public abstract Object getKey();
+
+  public boolean supports(String propertyName)
+  {
+    return propertyName.equals(PROPERTY_MOF_NOTIFIER);
+  }
+
+  public Object getProperty(String propertyName)
+  {
+    return null;
+  }
+
+  public void setProperty(String propertyName, Object object)
+  {
+	  //no propertyes supported? 
+  }
+}
diff --git a/bundles/org.eclipse.wst.xsd.core/src-contentmodel/org/eclipse/wst/xsd/contentmodel/internal/XSDCMManager.java b/bundles/org.eclipse.wst.xsd.core/src-contentmodel/org/eclipse/wst/xsd/contentmodel/internal/XSDCMManager.java
new file mode 100644
index 0000000..3461a54
--- /dev/null
+++ b/bundles/org.eclipse.wst.xsd.core/src-contentmodel/org/eclipse/wst/xsd/contentmodel/internal/XSDCMManager.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xsd.contentmodel.internal;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.Plugin;
+
+public class XSDCMManager extends Plugin 
+{
+  private static XSDCMManager instance;
+  
+  public XSDCMManager() 
+  {
+    super();
+  }
+  
+  public static XSDCMManager getInstance() {
+    if (instance == null) {
+      instance = new XSDCMManager();
+    }
+    return instance;
+  }
+
+
+  public void startup() throws CoreException 
+  {
+    XSDTypeUtil.initialize();
+    //ContentModelManager.getInstance().setInferredGrammarFactory(new InferredGrammarFactoryImpl());
+  }
+}
diff --git a/bundles/org.eclipse.wst.xsd.core/src-contentmodel/org/eclipse/wst/xsd/contentmodel/internal/XSDImpl.java b/bundles/org.eclipse.wst.xsd.core/src-contentmodel/org/eclipse/wst/xsd/contentmodel/internal/XSDImpl.java
new file mode 100644
index 0000000..9abdc21
--- /dev/null
+++ b/bundles/org.eclipse.wst.xsd.core/src-contentmodel/org/eclipse/wst/xsd/contentmodel/internal/XSDImpl.java
@@ -0,0 +1,3141 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2009 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
+ *     David Carver - STAR - bug 157254 - referenced Attributes and Elements
+ *        were not being checked to see if they had the annotations if
+ *        none were defined locally. (Initial fix modified - see bug)
+ *******************************************************************************/
+package org.eclipse.wst.xsd.contentmodel.internal;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Vector;
+
+import org.eclipse.emf.common.notify.Adapter;
+import org.eclipse.emf.common.notify.Notifier;
+import org.eclipse.emf.common.notify.impl.AdapterFactoryImpl;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.resource.ResourceSet;
+import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
+import org.eclipse.emf.ecore.resource.impl.URIConverterImpl;
+import org.eclipse.wst.common.uriresolver.internal.provisional.URIResolverPlugin;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAnyElement;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMContent;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocumentation;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNamespace;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
+import org.eclipse.wst.xml.core.internal.contentmodel.CMNodeList;
+import org.eclipse.wst.xml.core.internal.contentmodel.annotation.AnnotationMap;
+import org.eclipse.wst.xml.core.internal.contentmodel.basic.CMAttributeDeclarationImpl;
+import org.eclipse.wst.xml.core.internal.contentmodel.basic.CMDataTypeImpl;
+import org.eclipse.wst.xml.core.internal.contentmodel.basic.CMDocumentImpl;
+import org.eclipse.wst.xml.core.internal.contentmodel.basic.CMEntityDeclarationImpl;
+import org.eclipse.wst.xml.core.internal.contentmodel.basic.CMGroupImpl;
+import org.eclipse.wst.xml.core.internal.contentmodel.basic.CMNamedNodeMapImpl;
+import org.eclipse.wst.xml.core.internal.contentmodel.basic.CMNodeListImpl;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.CMDescriptionBuilder;
+import org.eclipse.wst.xml.core.internal.contentmodel.util.NamespaceInfo;
+import org.eclipse.wst.xsd.contentmodel.internal.util.XSDSchemaLocatorAdapterFactory;
+import org.eclipse.xsd.XSDAnnotation;
+import org.eclipse.xsd.XSDAttributeDeclaration;
+import org.eclipse.xsd.XSDAttributeUse;
+import org.eclipse.xsd.XSDAttributeUseCategory;
+import org.eclipse.xsd.XSDComplexTypeDefinition;
+import org.eclipse.xsd.XSDCompositor;
+import org.eclipse.xsd.XSDConcreteComponent;
+import org.eclipse.xsd.XSDConstraint;
+import org.eclipse.xsd.XSDContentTypeCategory;
+import org.eclipse.xsd.XSDElementDeclaration;
+import org.eclipse.xsd.XSDEnumerationFacet;
+import org.eclipse.xsd.XSDForm;
+import org.eclipse.xsd.XSDImport;
+import org.eclipse.xsd.XSDModelGroup;
+import org.eclipse.xsd.XSDModelGroupDefinition;
+import org.eclipse.xsd.XSDParticle;
+import org.eclipse.xsd.XSDParticleContent;
+import org.eclipse.xsd.XSDSchema;
+import org.eclipse.xsd.XSDSchemaContent;
+import org.eclipse.xsd.XSDSimpleTypeDefinition;
+import org.eclipse.xsd.XSDTypeDefinition;
+import org.eclipse.xsd.XSDVariety;
+import org.eclipse.xsd.XSDWildcard;
+import org.eclipse.xsd.impl.XSDSchemaImpl;
+import org.eclipse.xsd.util.XSDConstants;
+import org.eclipse.xsd.util.XSDResourceImpl;
+import org.eclipse.xsd.util.XSDSwitch;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+
+/**
+ * Utility class to build cmnodes from XML Schema nodes. The XML Schema model is
+ * found in the org.eclipse.xsd plugin.
+ * 
+ * TODO: getNamespaceURI()currently always returns '##any'.
+ */
+public class XSDImpl
+{
+  /*
+   * properties common to all cmnodes the following properties defined in
+   * CMNodeImpl class: PROPERTY_DOCUMENTATION PROPERTY_DOCUMENTATION_SOURCE
+   * PROPERTY_DOCUMENTATION_LANGUAGE PROPERTY_MOF_NOTIFIER
+   * PROPERTY_DEFINITION_INFO PROPERTY_DEFINITION
+   * 
+   * the following properties defined in this class, XSDImpl:
+   * PROPERTY_CMDOCUMENT PROPERTY_USES_LOCAL_ELEMENT_DECLARATIONS
+   * PROPERTY_IS_NAME_SPACE_AWARE PROPERTY_NS_PREFIX_QUALIFICATION
+   * PROPERTY_NILLABLE PROPERTY_SPEC
+   */
+  public static final String PROPERTY_CMDOCUMENT = "CMDocument";
+  public static final String PROPERTY_USES_LOCAL_ELEMENT_DECLARATIONS = "http://org.eclipse.wst/cm/properties/usesLocalElementDeclarations";
+  public static final String PROPERTY_IS_NAME_SPACE_AWARE = "http://org.eclipse.wst/cm/properties/isNameSpaceAware";
+  public static final String PROPERTY_NS_PREFIX_QUALIFICATION = "http://org.eclipse.wst/cm/properties/nsPrefixQualification";
+  public static final String PROPERTY_NILLABLE = "http://org.eclipse.wst/cm/properties/nillable";
+  public static final String PROPERTY_SPEC = "spec";
+  /*
+   * properties common to all CMDocument nodes: PROPERTY_TARGET_NAMESPACE_URI
+   * PROPERTY_IMPORTED_NAMESPACE_INFO PROPERTY_NAMESPACE_INFO
+   * PROPERTY_ELEMENT_FORM_DEFAULT PROPERTY_ANNOTATION_MAP
+   */
+  public static final String PROPERTY_TARGET_NAMESPACE_URI = "http://org.eclipse.wst/cm/properties/targetNamespaceURI";
+  public static final String PROPERTY_IMPORTED_NAMESPACE_INFO = "http://org.eclipse.wst/cm/properties/importedNamespaceInfo";
+  public static final String PROPERTY_NAMESPACE_INFO = "http://org.eclipse.wst/cm/properties/namespaceInfo";
+  public static final String PROPERTY_ELEMENT_FORM_DEFAULT = "http://org.eclipse.wst/cm/properties/elementFormDefault";
+  public static final String PROPERTY_ANNOTATION_MAP = "annotationMap";
+  public static final String PROPERTY_COMPLETE_NAMESPACE_INFO = "http://org.eclipse.wst/cm/properties/completeNamespaceInfo";
+  /*
+   * properties common to all CMElementDeclaration nodes: PROPERTY_XSITYPES
+   * PROPERTY_DERIVED_ELEMENT_DECLARATION PROPERTY_SUBSTITUTION_GROUP
+   * PROPERTY_ABSTRACT
+   */
+  public static final String PROPERTY_XSITYPES = "XSITypes";
+  public static final String PROPERTY_DERIVED_ELEMENT_DECLARATION = "DerivedElementDeclaration";
+  public static final String PROPERTY_SUBSTITUTION_GROUP = "SubstitutionGroup";
+  public static final String PROPERTY_SUBSTITUTION_GROUP_VALUE = "SubstitutionGroupValue";
+  public static final String PROPERTY_ABSTRACT = "Abstract";
+  public static final String PROPERTY_WHITESPACE_FACET = "org.eclipse.wst.xsd.cm.properties/whitespace"; //$NON-NLS-1$
+  /**
+   * Definition info for element declarations.
+   */
+  public static final String DEFINITION_INFO_GLOBAL = "global";
+  public static final String DEFINITION_INFO_LOCAL = "local";
+  public static final String XML_LANG_ATTRIBUTE = "xml:lang";
+  public static final String PLATFORM_PROTOCOL = "platform:";
+  protected static XSDAdapterFactoryImpl xsdAdapterFactoryImpl = new XSDAdapterFactoryImpl();
+  protected static XSIDocument xsiDocument = new XSIDocument();
+
+  /**
+   * Given uri for an XML Schema document, parse the document and build
+   * corresponding CMDocument node.
+   * 
+   * @param uri -
+   *          the uri for an XML Schema document
+   * @param grammarErrorChecking -
+   *          grammar error checking flag
+   * @param errorList -
+   *          the resulting error list
+   * @return the corresponding CMDocument node.
+   * @deprecated -- use buildCMDocument(String uri)
+   */
+  public static CMDocument buildCMDocument(String uri, int grammarErrorChecking, List errorList)
+  {
+    return buildCMDocument(uri);
+  }
+
+  /**
+   * Given uri for an XML Schema document, parse the document and build
+   * corresponding CMDocument node.
+   * 
+   * @param uri -
+   *          the uri for an XML Schema document
+   * @return the corresponding CMDocument node.
+   */
+  public static CMDocument buildCMDocument(String uri)
+  {
+    CMDocument cmDocument = null;
+    XSDSchema xsdSchema = buildXSDModel(uri);
+    if (xsdSchema != null)
+    {
+      cmDocument = (CMDocument) getAdapter(xsdSchema);
+    }
+    return cmDocument;
+  }
+
+  /**
+   * Given uri for an XML Schema document, parse the document and build
+   * corresponding CMDocument node.
+   * 
+   * @param uri -
+   *          the uri for an XML Schema document
+   * @return the corresponding CMDocument node.
+   */
+  public static XSDSchema buildXSDModel(String uriString)
+  {
+    XSDSchema xsdSchema = null;
+ 
+    try
+    {
+      // if XML Schema for Schema is requested, get it through schema model 
+      if (uriString.endsWith("2001/XMLSchema.xsd"))
+      {
+      	xsdSchema = XSDSchemaImpl.getSchemaForSchema(XSDConstants.SCHEMA_FOR_SCHEMA_URI_2001);			
+      }
+      else
+      { 	
+        ResourceSet resourceSet = new ResourceSetImpl();
+        //resourceSet.getAdapterFactories().add(new XSDSchemaLocationResolverAdapterFactory());
+        resourceSet.getAdapterFactories().add(new XSDSchemaLocatorAdapterFactory());
+          
+        URI uri = createURI(uriString);   
+        
+        // CS : bug 113537 ensure we perform physical resolution before opening a stream for the resource
+        //
+        String physicalLocation = URIResolverPlugin.createResolver().resolvePhysicalLocation("", "", uriString);       
+        InputStream inputStream = resourceSet.getURIConverter().createInputStream(URI.createURI(physicalLocation));
+        XSDResourceImpl resource = (XSDResourceImpl)resourceSet.createResource(URI.createURI("*.xsd"));
+        resource.setURI(uri);
+        resource.load(inputStream, null);         
+        xsdSchema = resource.getSchema();      
+      }
+    }
+    catch (Exception e)
+    {
+    }
+    return xsdSchema;
+  }
+  
+  // TODO ... looks like we can remove this class?
+  //
+  static class InternalURIConverter extends URIConverterImpl
+  {
+    protected InputStream createURLInputStream(URI uri) throws IOException
+    {
+      if ("http".equals(uri.scheme()))
+      {
+        String theURI = uri.toString();
+        String mapped = URIResolverPlugin.createResolver().resolve(theURI, theURI, theURI);
+        if (mapped != null)
+        {
+          uri = createURI(mapped);
+        }
+      }
+      return super.createURLInputStream(uri);
+    }
+  }
+
+  /**
+   * Returns an appropriate URI based on a uri string.
+   * 
+   * @param uriString -
+   *          a uri string.
+   * @return an appropriate URI based on a uri string.
+   */
+  public static URI createURI(String uriString)
+  {
+    if (hasProtocol(uriString))
+      return URI.createURI(uriString);
+    else
+      return URI.createFileURI(uriString);
+  }
+
+  private static boolean hasProtocol(String uri)
+  {
+    boolean result = false;
+    if (uri != null)
+    {
+      int index = uri.indexOf(":");
+      if (index != -1 && index > 2) // assume protocol with be length 3 so that
+                                    // the'C' in 'C:/' is not interpreted as a
+                                    // protocol
+      {
+        result = true;
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Returns true if string begins with platform protocol.
+   * 
+   * @param uriString -
+   *          a uri string.
+   * @return true if string begins with platform protocol.
+   */
+  public static boolean withPlatformProtocol(String uriString)
+  {
+    return uriString.startsWith(PLATFORM_PROTOCOL);
+  }
+
+  /**
+   * Returns the value of the 'Min Occurs' attribute. The default value is "1".
+   * 
+   * @param component -
+   *          a concrete component.
+   * @return the value of the 'Min Occurs' attribute.
+   */
+  public static int getMinOccurs(XSDConcreteComponent component)
+  {
+    int minOccur = 1;
+    if (component != null)
+    {
+      Object o = component.getContainer();
+      if (o instanceof XSDParticle)
+      {
+        if (((XSDParticle) o).isSetMinOccurs())
+        {
+          try
+          {
+            minOccur = ((XSDParticle) o).getMinOccurs();
+          }
+          catch (Exception e)
+          {
+            minOccur = 1;
+          }
+        }
+      }
+    }
+    return minOccur;
+  }
+
+  /**
+   * Returns the value of the 'Max Occurs' attribute. The default value is "1".
+   * 
+   * @param component -
+   *          a concrete component.
+   * @return the value of the 'Max Occurs' attribute.
+   */
+  public static int getMaxOccurs(XSDConcreteComponent component)
+  {
+    int maxOccur = 1;
+    if (component != null)
+    {
+      Object o = component.getContainer();
+      if (o instanceof XSDParticle)
+      {
+        if (((XSDParticle) o).isSetMaxOccurs())
+        {
+          try
+          {
+            maxOccur = ((XSDParticle) o).getMaxOccurs();
+          }
+          catch (Exception e)
+          {
+            maxOccur = 1;
+          }
+        }
+      }
+    }
+    return maxOccur;
+  }
+
+  /**
+   * Returns the enumerated values for the given type.
+   * 
+   * @param type -
+   *          a type definition.
+   * @return the enumerated values for the given type.
+   */
+  private final static String TYPE_NAME_BOOLEAN = "boolean"; //$NON-NLS-1$
+  private final static String TYPE_VALUE_TRUE = "true"; //$NON-NLS-1$
+  private final static String TYPE_VALUE_FALSE= "false"; //$NON-NLS-1$  
+  
+  public static String[] getEnumeratedValuesForType(XSDTypeDefinition type)
+  {
+    List result = new ArrayList();
+    // See bug 214804 - Content assist not showing valid values when it's a complex
+    // type with simple content
+    if (type instanceof XSDComplexTypeDefinition)
+    {
+      type = ((XSDComplexTypeDefinition)type).getSimpleType();
+    }
+    if (type instanceof XSDSimpleTypeDefinition)
+    {         
+      if (TYPE_NAME_BOOLEAN.equals(type.getName()) && type.getSchema().getSchemaForSchema() == type.getSchema())
+      {
+        result.add(TYPE_VALUE_TRUE);
+        result.add(TYPE_VALUE_FALSE);
+      } 
+      else
+      {
+        // Simple types can be one of: atomic, list or union.
+        int varietyType = ((XSDSimpleTypeDefinition) type).getVariety().getValue();
+
+        switch (varietyType)
+        {
+          case XSDVariety.ATOMIC:
+            {
+              XSDTypeDefinition baseType = type.getBaseType();
+              if (baseType != null && !(type.getSchema().getSchemaForSchema() == baseType.getSchema()))
+              {
+                getEnumeratedValuesForSimpleType(baseType, result);
+              }
+              else
+              {
+                getEnumeratedValuesForSimpleType(type, result);
+              }
+            }
+            break;
+          case XSDVariety.LIST:
+            {
+              XSDSimpleTypeDefinition itemTypeDefinition = ((XSDSimpleTypeDefinition) type).getItemTypeDefinition();
+              String[] values = getEnumeratedValuesForType(itemTypeDefinition);
+              for (int j = 0; j < values.length; j++) {
+            	  if(result.indexOf(values[j]) == -1) {
+            		  result.add(values[j]);
+            	  }
+              }
+            }
+            break;
+          case XSDVariety.UNION:
+            {
+              List memberTypes = ((XSDSimpleTypeDefinition) type).getMemberTypeDefinitions();
+              if (memberTypes != null && memberTypes.size() > 0)
+              {
+                Iterator i = memberTypes.iterator();
+                while (i.hasNext())
+                {
+                  XSDSimpleTypeDefinition simpleType = (XSDSimpleTypeDefinition) i.next();
+                  String[] values = getEnumeratedValuesForType(simpleType);
+                  for (int j = 0; j < values.length; j++) {
+                	  if(result.indexOf(values[j]) == -1) {
+                		  result.add(values[j]);
+                	  }
+                  }
+                }
+              }
+            }
+            break;
+        }
+      }
+    }  
+    String[] array = new String[result.size()];
+    result.toArray(array);
+    return array;
+  }
+
+  private static void getEnumeratedValuesForSimpleType(XSDTypeDefinition type, List result)
+  {
+    List enumerationFacets = ((XSDSimpleTypeDefinition) type).getEnumerationFacets();
+    for (Iterator i = enumerationFacets.iterator(); i.hasNext();)
+    {
+      XSDEnumerationFacet enumFacet = (XSDEnumerationFacet) i.next();
+      List values = enumFacet.getValue();
+      for (Iterator j = values.iterator(); j.hasNext();)
+      {
+        Object o = j.next();
+        if (o != null)
+        {
+          if (!result.contains(o))
+          {
+            result.add(o.toString());
+          }
+        }
+      }
+    }
+  }
+
+  /**
+   * Return a list of documentation elements from the given annotation. Working
+   * with documentation elements requires dropping down into the DOM model.
+   * 
+   * @param annotation -
+   *          an XSDAnnotation node.
+   * @return a list of documentation elements.
+   */
+  public static CMNodeList getDocumentations(XSDAnnotation annotation)
+  {
+    CMNodeListImpl documentations = new CMNodeListImpl();
+    if (annotation != null)
+    {
+      List documentationsElements = annotation.getUserInformation();
+      for (Iterator i = documentationsElements.iterator(); i.hasNext();)
+      {
+        documentations.getList().add(new DocumentationImpl((Element) i.next()));
+      }
+    }
+    return documentations;
+  }
+
+  /**
+   * Adapted from public static List findTypesDerivedFrom(XSDSchema schema,
+   * String namespace, String localName) in class XSDSchemaQueryTools found in
+   * org.eclipse.xsd plugin.
+   * 
+   * Find typeDefinitions that derive from a given type.
+   * 
+   * @param type
+   *          the type derived from
+   * @return List of any XSDTypeDefinitions found
+   */
+  public static List findTypesDerivedFrom(XSDTypeDefinition type)
+  {
+    ArrayList typesDerivedFrom = new ArrayList();
+    if (type != null)
+    {
+      XSDSchema schema = type.getSchema();
+      String localName = type.getName();
+      if ((null != schema) && (null != localName))
+      {
+        String namespace = schema.getTargetNamespace();
+        // A handy convenience method quickly gets all
+        // typeDefinitions within our schema; note that
+        // whether or not this returns types in included,
+        // imported, or redefined schemas is subject to change
+        List typedefs = schema.getTypeDefinitions();
+        for (Iterator iter = typedefs.iterator(); iter.hasNext();)
+        {
+          XSDTypeDefinition typedef = (XSDTypeDefinition) iter.next();
+          if (typedef instanceof XSDComplexTypeDefinition)
+          {
+            // Walk the baseTypes from this typedef seeing if any
+            // of them match the requested one
+            if (isTypeDerivedFrom(typedef, namespace, localName))
+            {
+              // We found it, return the original one and continue
+              typesDerivedFrom.add(typedef);
+              continue;
+            }
+          }
+        }
+      }
+    }
+    return typesDerivedFrom;
+  }
+
+  /**
+   * Adapted from protected static boolean isTypeDerivedFrom(XSDTypeDefinition
+   * typedef, String namespace, String localName) in class XSDSchemaQueryTools
+   * found in org.eclipse.xsd plugin.
+   * 
+   * Recursive worker method to find typeDefinitions that derive from a named
+   * type.
+   * 
+   * @see #findTypesDerivedFrom(XSDSchema, String, String)
+   * @param typeDef
+   *          to see if it's derived from
+   * @param namespace
+   *          for the type derived from
+   * @param localName
+   *          for the type derived from
+   * @return true if it is; false otherwise
+   */
+  protected static boolean isTypeDerivedFrom(XSDTypeDefinition typedef, String namespace, String localName)
+  {
+    // Walk the baseTypes from this typedef seeing if any
+    // of them match the requested one
+    XSDTypeDefinition baseType = typedef.getBaseType();
+    if (baseType == null)
+   	{
+      // typedef is a root type like xsd:anyType, so it has no base
+      return false;
+    }
+    
+    // As this convenience method if our parameters match
+    if (baseType.hasNameAndTargetNamespace(localName, namespace))
+    {
+      return true;
+    }
+    XSDTypeDefinition rootType = typedef.getRootType();
+
+    if (rootType == baseType)
+    {
+      // If we've hit the root, we aren't derived from it
+      return false;
+    }
+    else
+    {
+      // Need to check if the base type is redefined/circular
+      // otherwise this will be an endless recursive call.
+      // Moved.  See https://bugs.eclipse.org/bugs/show_bug.cgi?id=213543
+      // This method should be replaced with     XSDConstants.isOrIsDerivedFrom(baseType, localName, namespace);
+      if (rootType.isCircular())
+      {
+        return true;
+      }
+      // Otherwise continue to traverse upwards
+      return isTypeDerivedFrom(baseType, namespace, localName);
+    }
+  }
+
+  /**
+   * Returns the corresponding cmnode of the specified XML Schema node.
+   * 
+   * @param target -
+   *          an XML Schema node
+   * @return the corresponding cmnode.
+   */
+  public static CMNode getAdapter(Notifier o)
+  {
+    return (CMNode) xsdAdapterFactoryImpl.adapt(o);
+  }
+
+  /**
+   * Adapted from public String getPrefix(String ns, boolean withColon) in class
+   * TypesHelper found in org.eclipse.wst.xsd.editor plugin.
+   * 
+   * @param schema -
+   *          the relevant schema
+   * @param ns -
+   *          the relevant namespace
+   */
+  public static String getPrefix(XSDSchema schema, String ns)
+  {
+    String key = "";
+    if ((schema != null) && (ns != null))
+    {
+      Map map = schema.getQNamePrefixToNamespaceMap();
+      Iterator iter = map.keySet().iterator();
+      while (iter.hasNext())
+      {
+        Object keyObj = iter.next();
+        Object value = map.get(keyObj);
+        if (value != null && value.toString().equals(ns))
+        {
+          if (keyObj != null)
+          {
+            key = keyObj.toString();
+          }
+          else
+          {
+            key = "";
+          }
+          break;
+        }
+      }
+    }
+    return key;
+  }
+  /**
+   * The Factory for the XSD adapter model. It provides a create method for each
+   * non-abstract class of the model.
+   */
+  public static class XSDAdapterFactoryImpl extends AdapterFactoryImpl
+  {
+    public Adapter createAdapter(Notifier target)
+    {
+      XSDSwitch xsdSwitch = new XSDSwitch()
+      {
+        public Object caseXSDWildcard(XSDWildcard object)
+        {
+          return new XSDWildcardAdapter(object);
+        }
+
+        public Object caseXSDModelGroupDefinition(XSDModelGroupDefinition object)
+        {
+          return new XSDModelGroupDefinitionAdapter(object);
+        }
+
+        public Object caseXSDAttributeUse(XSDAttributeUse object)
+        {
+          return new XSDAttributeUseAdapter(object);
+        }
+
+        public Object caseXSDElementDeclaration(XSDElementDeclaration object)
+        {
+          return new XSDElementDeclarationAdapter(object);
+        }
+
+        public Object caseXSDModelGroup(XSDModelGroup object)
+        {
+          return new XSDModelGroupAdapter(object);
+        }
+
+        public Object caseXSDSchema(XSDSchema object)
+        {
+          return new XSDSchemaAdapter(object);
+        }
+      };
+      Object o = xsdSwitch.doSwitch((EObject) target);
+      Adapter result = null;
+      if (o instanceof Adapter)
+      {
+        result = (Adapter) o;
+      }
+      else
+      {
+        Thread.dumpStack();
+      }
+      return result;
+    }
+
+    public Adapter adapt(Notifier target)
+    {
+      return adapt(target, this);
+    }
+  }
+  /**
+   * XSDBaseAdapter -- an abstract base node in the model. All other model nodes
+   * are derived from it.
+   */
+  public static abstract class XSDBaseAdapter extends CMNodeImpl
+  {
+    protected CMNodeListImpl documentation = new CMNodeListImpl();
+
+    /**
+     * Returns the name of the node. The default value is an empty string value.
+     * All derived classes must override this method if they do not want the
+     * default value.
+     * 
+     * @return the name of the node.
+     */
+    public String getNodeName()
+    {
+      return "";
+    }
+
+    /**
+     * Returns true of the given factory is the factory for this XSD adapter
+     * model.
+     * 
+     * @param type -
+     *          a factory
+     * @return true if the type is the adapter factory for this model.
+     */
+    public boolean isAdapterForType(Object type)
+    {
+      return type == xsdAdapterFactoryImpl;
+    }
+
+    /**
+     * Returns true if the property is supported for this class.
+     * 
+     * @param propertyName -
+     *          name of a property
+     * @return true if the property is supported.
+     */
+    public boolean supports(String propertyName)
+    {
+      return propertyName.equals(PROPERTY_NS_PREFIX_QUALIFICATION) || propertyName.equals(PROPERTY_NILLABLE) || propertyName.equals(PROPERTY_USES_LOCAL_ELEMENT_DECLARATIONS)
+          || propertyName.equals(PROPERTY_DOCUMENTATION) || propertyName.equals(PROPERTY_DOCUMENTATION_SOURCE) || propertyName.equals(PROPERTY_DOCUMENTATION_LANGUAGE)
+          || propertyName.equals(PROPERTY_MOF_NOTIFIER) || propertyName.equals(PROPERTY_DEFINITION_INFO) || propertyName.equals(PROPERTY_DEFINITION) || propertyName.equals(PROPERTY_CMDOCUMENT)
+          || propertyName.equals(PROPERTY_IS_NAME_SPACE_AWARE) || propertyName.equals(PROPERTY_SPEC) || super.supports(propertyName);
+    }
+
+    /**
+     * Returns the value of the 'Nillable' attribute. This represents the
+     * nillable infoset property. The default value is false. All derived
+     * classes must override this method if they do not want the default value.
+     * 
+     * @return the value of the 'Nillable' attribute.
+     */
+    public boolean isNillable()
+    {
+      return false;
+    }
+
+    /**
+     * Returns the cmdocument that is the owner of this cmnode. The default
+     * value is null; All derived classes must override this method if they do
+     * not want the default value.
+     * 
+     * @return the cmdocument corresponding to this cmnode.
+     */
+    public CMDocument getCMDocument()
+    {
+      return null;
+    }
+
+    /**
+     * Return a list of documentation elements. The default value is an empty
+     * CMNodeList; All derived classes must override this method if they do not
+     * want the default value.
+     * 
+     * @return a list of documentation elements.
+     */
+    protected CMNodeList getDocumentation()
+    {
+      return documentation;
+    }
+
+    /**
+     * Returns the property value for the property name. Returns null if the
+     * property is not supported.
+     * 
+     * @param propertyName -
+     *          name of a property
+     * @return the property value for the property name.
+     */
+    public Object getProperty(String propertyName)
+    {
+      Object result = null;
+      if (propertyName.equals(PROPERTY_CMDOCUMENT))
+      {
+        result = getCMDocument();
+      }
+      else if (propertyName.equals(PROPERTY_DOCUMENTATION))
+      {
+        result = getDocumentation();
+      }
+      else if (propertyName.equals(PROPERTY_USES_LOCAL_ELEMENT_DECLARATIONS))
+      {
+        result = Boolean.TRUE;
+      }
+      else if (propertyName.equals(PROPERTY_IS_NAME_SPACE_AWARE))
+      {
+        result = Boolean.TRUE;
+      }
+      else if (propertyName.equals(PROPERTY_NS_PREFIX_QUALIFICATION))
+      {
+        result = getNSPrefixQualification();
+      }
+      else if (propertyName.equals(PROPERTY_NILLABLE))
+      {
+        result = isNillable() ? xsiDocument.nilAttribute : null;
+      }
+      else if (propertyName.equals(PROPERTY_MOF_NOTIFIER))
+      {
+        result = getKey();
+      }
+      else if (propertyName.equals(PROPERTY_SPEC))
+      {
+        result = getSpec();
+      }
+      else
+      {
+        result = super.getProperty(propertyName);
+        {
+          CMDocument cmDocument = getCMDocument();
+          if (cmDocument instanceof XSDSchemaAdapter)
+          {
+            AnnotationMap map = ((XSDSchemaAdapter) cmDocument).annotationMap;
+            if (map != null)
+            {
+              String spec = getSpec();
+              if (spec != null)
+              {
+                result = map.getProperty(getSpec(), propertyName);
+              }
+            }
+          }
+        }
+      }
+      return result;
+    }
+       
+
+
+    /*
+     * Returns the value of the form [attribute] which affects the target
+     * namespace of locally scoped features. The default value is null. All
+     * derived classes must override this method if they do not want the default
+     * value. @return the value of the form [attribute].
+     */
+    public Object getNSPrefixQualification()
+    {
+      return null;
+    }
+
+    /**
+     * Returns a general XPath expression for the node.
+     * 
+     * @return a general XPath expression for the node.
+     */
+    public String getSpec()
+    {
+      return "//" + getNodeName();
+    }
+  }
+  /**
+   * XSDSchemaAdapter implements CMDocument. A representation of the model
+   * object 'Schema'.
+   */
+  public static class XSDSchemaAdapter extends XSDBaseAdapter implements CMDocument
+  {
+    protected XSDSchema xsdSchema;
+    protected CMNamedNodeMapImpl namedNodeMap;
+    protected CMNamedNodeMapImpl entityNodeMap;
+    protected AnnotationMap annotationMap = new AnnotationMap();
+    protected Hashtable substitutionGroupTable;
+
+    /**
+     * Constructor.
+     * 
+     * @param xsdSchema -
+     *          the schema node.
+     */
+    public XSDSchemaAdapter(XSDSchema xsdSchema)
+    {
+      this.xsdSchema = xsdSchema;
+    }
+
+    /**
+     * Returns the key for this cmnode which is the corresponding XML Schema
+     * node.
+     * 
+     * @return the key for this cmnode.
+     */
+    public Object getKey()
+    {
+      return xsdSchema;
+    }
+
+    /**
+     * Returns the filename.
+     * 
+     * @return the filename.
+     */
+    public String getNodeName()
+    {
+      // See buildCMDocument() above.
+      return xsdSchema.getSchemaLocation();
+    }
+
+    /**
+     * Returns true if the property is supported for this class.
+     * 
+     * @param propertyName -
+     *          name of a property
+     * @return true if the property is supported.
+     */
+    public boolean supports(String propertyName)
+    {
+      return propertyName.equals(PROPERTY_TARGET_NAMESPACE_URI) || propertyName.equals(PROPERTY_IMPORTED_NAMESPACE_INFO) || propertyName.equals(PROPERTY_NAMESPACE_INFO)
+          || propertyName.equals(PROPERTY_ELEMENT_FORM_DEFAULT) || propertyName.equals(PROPERTY_ANNOTATION_MAP) || super.supports(propertyName);
+    }
+
+    /**
+     * Returns true if a prefix is globally required for elements.
+     * 
+     * @param xsdSchema -
+     *          the corresponding schema node.
+     * @return true if a prefix is globally required for elements.
+     */
+    protected boolean isPrefixRequired(XSDSchema xsdSchema)
+    {
+      boolean result = true;
+      if (xsdSchema.isSetElementFormDefault())
+        result = !(xsdSchema.getElementFormDefault().getValue() == XSDForm.QUALIFIED);
+      return result;
+    }
+
+    /**
+     * Returns the property value for the property name. Returns null if the
+     * property is not supported.
+     * 
+     * @param propertyName -
+     *          name of a property
+     * @return the property value for the property name.
+     */
+    public Object getProperty(String propertyName)
+    {
+      Object result = null;
+      if (propertyName.equals(PROPERTY_TARGET_NAMESPACE_URI))
+      {
+        result = xsdSchema.getTargetNamespace();
+      }
+      else if (propertyName.equals(PROPERTY_IMPORTED_NAMESPACE_INFO))
+      {
+        List list = new Vector();
+        getImportedNamespaceInfo(xsdSchema, list);
+        result = list;
+      }
+      else if (propertyName.equals(PROPERTY_NAMESPACE_INFO))
+      {
+        List list = new Vector();
+        NamespaceInfo info = new NamespaceInfo();
+        info.uri = xsdSchema.getTargetNamespace();
+        info.prefix = getPrefix(xsdSchema, info.uri);
+        info.locationHint = null; // note that this locationHint info is null
+                                  // for the root xsd file
+        info.isPrefixRequired = isPrefixRequired(xsdSchema);
+        list.add(info);
+        getImportedNamespaceInfo(xsdSchema, list);
+        result = list;
+      }
+      else if (propertyName.equals(PROPERTY_COMPLETE_NAMESPACE_INFO))
+      {
+    	  result = getAllNamespaceInfo();
+      }
+      else if (propertyName.equals(PROPERTY_ELEMENT_FORM_DEFAULT))
+      {
+        result = xsdSchema.getElementFormDefault().getName();
+      }
+      else if (propertyName.equals(PROPERTY_ANNOTATION_MAP))
+      {
+        result = annotationMap;
+      }
+      else if (propertyName.equals("allElements"))
+      {
+        result = getAllElements();
+      }  
+      else if (propertyName.startsWith("getElementForType#"))
+      {
+        int index = propertyName.indexOf("#");
+        String typeName = propertyName.substring(index + 1, propertyName.length());
+        //
+        //
+        XSDTypeDefinition td = xsdSchema.resolveTypeDefinition(typeName);
+        if (td != null)
+        {
+          LocalElementVisitor localElementVisitor = new LocalElementVisitor();
+          localElementVisitor.visitTypeDefinition(td);
+          result = localElementVisitor.getCMNamedNodeMap();
+        }
+      }
+      else
+      {
+        result = super.getProperty(propertyName);
+      }
+      return result;
+    }
+
+    /**
+     * Gather information on namespaces used in external references.
+     * 
+     * @param theXSDSchema -
+     *          the corresponding schema node
+     * @param list -
+     *          the list of imported namespaces.
+     */
+    public void getImportedNamespaceInfo(XSDSchema theXSDSchema, List list)
+    {
+      for (Iterator iterator = theXSDSchema.getContents().iterator(); iterator.hasNext();)
+      {
+        XSDSchemaContent content = (XSDSchemaContent) iterator.next();
+        if (content instanceof XSDImport)
+        {
+          XSDImport xImport = (XSDImport) content;
+          XSDSchema importedXSDSchema = xImport.getResolvedSchema();
+          NamespaceInfo info = new NamespaceInfo();
+          info.uri = xImport.getNamespace();
+          info.prefix = getPrefix(importedXSDSchema, info.uri);
+          info.locationHint = xImport.getSchemaLocation();
+          if (importedXSDSchema != null)
+          {
+            info.isPrefixRequired = isPrefixRequired(importedXSDSchema);
+          }
+          list.add(info);
+        }
+      }
+    }
+
+    /**
+     * Returns set of named (top-level) element declarations for this schema
+     * node.
+     * 
+     * @return a set of named (top-level) element declarations.
+     */
+    public CMNamedNodeMap getElements()
+    {
+      if (namedNodeMap == null)
+      {
+        namedNodeMap = new CMNamedNodeMapImpl();
+        
+        // Note that if we call xsdSchema.getElementDeclarations()
+        // we get 'more' elements than we really want since we also
+        // get 'imported' elements.  Below we test to ensure the elements
+        // actually have the same target namespace as the schema.
+        String targetNamespace = xsdSchema.getTargetNamespace();
+        for (Iterator i = xsdSchema.getElementDeclarations().iterator(); i.hasNext();)
+        {
+          XSDElementDeclaration ed = (XSDElementDeclaration) i.next();
+          if (targetNamespace != null ? targetNamespace.equals(ed.getTargetNamespace()) : ed.getTargetNamespace() == null)
+          {
+            XSDElementDeclarationAdapter adapter = (XSDElementDeclarationAdapter) getAdapter(ed);
+            namedNodeMap.getHashtable().put(adapter.getNodeName(), adapter);
+          }
+        }
+      }
+      return namedNodeMap;
+    }
+
+    /**
+     * Returns the built-in entity declarations.
+     * 
+     * @return the built-in entity declarations.
+     */
+    public CMNamedNodeMap getEntities()
+    {
+      if (entityNodeMap == null)
+      {
+        entityNodeMap = new CMNamedNodeMapImpl();
+        // add the built in entity declarations
+        entityNodeMap.getHashtable().put("amp", new CMEntityDeclarationImpl("amp", "&"));
+        entityNodeMap.getHashtable().put("lt", new CMEntityDeclarationImpl("lt", "<"));
+        entityNodeMap.getHashtable().put("gt", new CMEntityDeclarationImpl("gt", ">"));
+        entityNodeMap.getHashtable().put("quot", new CMEntityDeclarationImpl("quot", "\""));
+        entityNodeMap.getHashtable().put("apos", new CMEntityDeclarationImpl("apos", "'"));
+      }
+      return entityNodeMap;
+    }
+
+    /**
+     * Returns the type of the node. The types are defined in CMNode class
+     * (ANY_ELEMENT, ATTRIBUTE_DECLARATION, DATA_TYPE, DOCUMENT,
+     * ELEMENT_DECLARATION, ENTITY_DECLARATION, GROUP, NAME_SPACE or
+     * DOCUMENTATION).
+     * 
+     * @return the type of this node.
+     */
+    public int getNodeType()
+    {
+      return DOCUMENT;
+    }
+
+    /*
+     * Returns null. !!! Why are we not implementing this???? @return null.
+     */
+    public CMNamespace getNamespace()
+    {
+      return null;
+    }
+
+    /**
+     * Returns this.
+     * 
+     * @return this.
+     */
+    public CMDocument getCMDocument()
+    {
+      return this;
+    }
+    
+    public CMNamedNodeMap getAllElements()
+    {
+      CMNamedNodeMapImpl map = new CMNamedNodeMapImpl();
+      for (Iterator i = getElements().iterator(); i.hasNext(); )
+      {
+        CMElementDeclaration ed = (CMElementDeclaration)i.next();
+        map.put(ed);           
+        addLocalElementDefinitions(map, ed);              
+      }     
+      return map;
+    }
+    
+    protected void addLocalElementDefinitions(CMNamedNodeMapImpl map, CMElementDeclaration parentElementDeclaration)
+    {
+      CMNamedNodeMap localElementMap = parentElementDeclaration.getLocalElements();
+      for (Iterator i = localElementMap.iterator(); i.hasNext(); )
+      {
+        CMElementDeclaration ed = (CMElementDeclaration)i.next();
+        if (map.getNamedItem(ed.getNodeName()) == null)
+        {  
+          map.put(ed);        
+          addLocalElementDefinitions(map, ed);
+        }  
+      }               
+    } 
+    
+    
+    /**
+     * Generates a List of NamespaceInfo objects corresponding to the target namespace of the given schema 
+     * and the target namespaces of all its recursively imported/included referenced schemas. All namespace
+     * prefixes in the list are guaranteed to be unique. Prefix collitions are resolved by concatenating
+     * integer numbers to each repeated prefix found i.e. tns, tns1, tns2...
+     * All schema locations in the list are formated as encoded URIs relative to the given schema.
+     * Schemas that are imported/included but not referenced will not appear in the list.
+     * @return List of NamespaceInfo objects
+     * 
+     */
+	public List getAllNamespaceInfo() {
+		List namespaceList = new ArrayList();
+		List resources  = xsdSchema.eResource().getResourceSet().getResources();
+		Iterator i = resources.iterator();
+		while(i.hasNext()) {
+			XSDResourceImpl resource = (XSDResourceImpl) i.next();
+			if(resource.isLoaded()) {
+				XSDSchema schema = resource.getSchema();
+				if(!isDataInNamespaceList(namespaceList, 0, schema.getTargetNamespace())) {
+					NamespaceInfo info = new NamespaceInfo();
+					info.uri = schema.getTargetNamespace();
+					info.isPrefixRequired = isPrefixRequired(schema);
+					info.prefix = getPrefix(schema,schema.getTargetNamespace());
+					if("http://www.w3.org/XML/1998/namespace".equals(info.uri)) {
+    					info.prefix = "xml";
+    				} else if("http://www.w3.org/2000/xmlns".equals(info.uri)) {
+    					info.prefix = "xmlns";
+    				} else {
+    					if(info.uri != null && info.uri != "") {
+	    					int n = 1;
+	    	    			if(info.prefix == null || info.prefix.equals("")) {
+	    	    				info.prefix = "p";
+	    	    			}
+	    	    			String prefix = info.prefix;
+	    	    			while(isDataInNamespaceList(namespaceList, 1, info.prefix)) {
+	    	    				info.prefix = prefix + n++;
+	    	    			}
+    					}
+    				}
+	    			URI relative = URI.createURI(xsdSchema.getSchemaLocation(), true);
+					URI absolute = URI.createURI(schema.getSchemaLocation(), true);
+					URI resolvedRelative = absolute.deresolve(relative);
+					info.locationHint = resolvedRelative.toString();
+	    			namespaceList.add(info);
+				}
+			}
+		}
+		return namespaceList;	
+	}
+
+
+    /**
+     * Searches for a given value in a list of namespaces.
+     * 
+     * @param namespaceList:	List of NamespaceInfo objects
+     * @param data:				integer representing the data in the namespace as follows:
+     * 								0:	uri
+     * 								1:	prefix
+     * 								2:	locationHint
+     * @param value				String containing the value for search
+     * @return					true if the value is found, false otherwise
+     */
+    private boolean isDataInNamespaceList(List namespaceList, int data, String value) {
+		if (namespaceList != null) {
+			Iterator i = namespaceList.iterator();
+			while (i.hasNext()) {
+				NamespaceInfo namespaceInfo = (NamespaceInfo) i.next();
+				switch(data) {
+					case 0:	if (namespaceInfo.uri != null && namespaceInfo.uri.equals(value)) {
+						return true;
+					}
+					case 1:	if (namespaceInfo.prefix != null && namespaceInfo.prefix.equals(value)) {
+						return true;
+					}
+					case 2:	if (namespaceInfo.locationHint != null && namespaceInfo.locationHint.equals(value)) {
+						return true;
+					}
+				}
+			}
+		}
+    	return false;
+    }
+  }
+  /**
+   * XSDAttributeUseAdapter implements CMAttributeDeclaration. A representation
+   * of the model object 'Attribute Use'.
+   */
+  public static class XSDAttributeUseAdapter extends XSDBaseAdapter implements CMAttributeDeclaration
+  {
+    // provides access to the XML Schema node
+    protected XSDAttributeUse xsdAttributeUse;
+    // provides access to the type of the attribute
+    protected CMDataType dataType = new DataTypeImpl();
+
+    /**
+     * Constructor.
+     * 
+     * @param xsdAttributeUse -
+     *          the XML Schema node.
+     */
+    public XSDAttributeUseAdapter(XSDAttributeUse xsdAttributeUse)
+    {
+      this.xsdAttributeUse = xsdAttributeUse;
+    }
+
+    /**
+     * Returns the key for this cmnode which is the corresponding XML Schema
+     * node.
+     * 
+     * @return the key for this cmnode.
+     */
+    public Object getKey()
+    {
+      return xsdAttributeUse;
+    }
+
+    /**
+     * Returns a general XPath expression for the node.
+     * 
+     * @return a general XPath expression for the node.
+     */
+    public String getSpec()
+    {
+      return "//@" + getAttrName();
+    }
+
+    /**
+     * Returns the type of the node. The types are defined in CMNode class
+     * (ANY_ELEMENT, ATTRIBUTE_DECLARATION, DATA_TYPE, DOCUMENT,
+     * ELEMENT_DECLARATION, ENTITY_DECLARATION, GROUP, NAME_SPACE or
+     * DOCUMENTATION).
+     * 
+     * @return the type of this node.
+     */
+    public int getNodeType()
+    {
+      return ATTRIBUTE_DECLARATION;
+    }
+
+    /**
+     * Returns the name of the node. Similar to getAttrName().
+     * 
+     * @return the name of the node.
+     */
+    public String getNodeName()
+    {
+      return getAttrName();
+    }
+
+    /**
+     * getEnumAttr method
+     * 
+     * @return java.util.Enumeration
+     * @deprecated -- to be replaced in future with additional CMDataType
+     *             methods (currently found on CMDataTypeHelper)
+     */
+    public Enumeration getEnumAttr()
+    {
+      return Collections.enumeration(Collections.EMPTY_LIST);
+    }
+
+    /**
+     * Returns the name of this attribute. Similar to getNodeName().
+     * 
+     * @return the name of this attribute.
+     */
+    public String getAttrName()
+    {
+      return xsdAttributeUse.getAttributeDeclaration().getName();
+    }
+
+    /**
+     * Returns the type of the attribute.
+     * 
+     * @return the type of the attribute.
+     */
+    public CMDataType getAttrType()
+    {
+      return dataType;
+    }
+
+    /**
+     * Returns the value of the default or fixed constraint.
+     * 
+     * @return the value of the default or fixed constraint.
+     */
+    public String getDefaultValue()
+    {
+      return dataType.getImpliedValue();
+    }
+
+    /**
+     * Returns the usage constraint for this attribute. The usages are defined
+     * in CMAttributeDeclaration class (OPTIONAL, REQUIRED, FIXED or
+     * PROHIBITED).
+     * 
+     * @return the usage constraint for this attribute.
+     */
+    public int getUsage()
+    {
+      int useKind = OPTIONAL;
+      switch (xsdAttributeUse.getUse().getValue())
+      {
+        case XSDAttributeUseCategory.OPTIONAL : {
+          useKind = OPTIONAL;
+          break;
+        }
+        case XSDAttributeUseCategory.PROHIBITED : {
+          useKind = PROHIBITED;
+          break;
+        }
+        case XSDAttributeUseCategory.REQUIRED : {
+          useKind = REQUIRED;
+          break;
+        }
+      }
+      return useKind;
+    }
+
+    /*
+     * Returns the value of the form [attribute] which affects the target
+     * namespace of locally scoped features. If the form is not set on this
+     * attribute, then see if there is a globally defined default. @return the
+     * value of the form [attribute].
+     */
+    public Object getNSPrefixQualification()
+    {
+      String form = null;
+      if (xsdAttributeUse.getContent() != xsdAttributeUse.getAttributeDeclaration())
+      {
+      	form =  "qualified";
+      }	
+      else if (xsdAttributeUse.getContent().isSetForm())
+      {
+        form = xsdAttributeUse.getContent().getForm().getName();
+      }
+      else
+      {
+        XSDSchema schema = xsdAttributeUse.getSchema();
+        if (schema != null)
+          form = schema.getAttributeFormDefault().getName();
+      }
+      return form;
+    }
+
+    /**
+     * Return a list of documentation elements.
+     * 
+     * @return a list of documentation elements.
+     */
+    protected CMNodeList getDocumentation()
+    {
+      // Check if it is an attribute reference first
+      XSDAttributeDeclaration xsdAttributeRef = xsdAttributeUse.getContent();
+      if (xsdAttributeRef != null && xsdAttributeRef.isAttributeDeclarationReference())
+      {
+        // Determine if it has annotations
+        boolean refHasDocumentation = false;
+        XSDAnnotation refAnnotation = xsdAttributeRef.getAnnotation();
+        if (refAnnotation != null)
+        {
+          // Determine if there is documentation
+          if (!refAnnotation.getUserInformation().isEmpty())
+          {
+            refHasDocumentation = true;
+          }
+        }
+        if (refHasDocumentation)
+          return getDocumentations(refAnnotation);
+      }
+      
+      // Otherwise proceed with getting the documentation as usual
+      XSDAttributeDeclaration xsdAttributeDeclaration =  xsdAttributeUse.getAttributeDeclaration();      
+      XSDAnnotation annotation = xsdAttributeDeclaration.getAnnotation();
+      
+      return getDocumentations(annotation);
+    }
+
+    /**
+     * Returns the cmdocument that is the owner of this cmnode.
+     * 
+     * @return the cmdocument corresponding to this cmnode.
+     */
+    public CMDocument getCMDocument()
+    {
+      return (CMDocument) getAdapter(xsdAttributeUse.getSchema());
+    }
+    /**
+     * XSDAttributeUseAdapter.DataTypeImpl An inner class to hold type
+     * information for this attribute.
+     */
+    public class DataTypeImpl implements CMDataType
+    {
+      /**
+       * Returns the type of the node. The types are defined in CMNode class
+       * (ANY_ELEMENT, ATTRIBUTE_DECLARATION, DATA_TYPE, DOCUMENT,
+       * ELEMENT_DECLARATION, ENTITY_DECLARATION, GROUP, NAME_SPACE or
+       * DOCUMENTATION).
+       * 
+       * @return the type of this node.
+       */
+      public int getNodeType()
+      {
+        return CMNode.DATA_TYPE;
+      }
+
+      /**
+       * Returns the name of the attribute type. Same as getDataTypeName().
+       * 
+       * @return the name of the attribute type.
+       */
+      public String getNodeName()
+      {
+        return getDataTypeName();
+      }
+
+      /**
+       * Returns true if the property is supported for this class.
+       * 
+       * @param propertyName -
+       *          name of a property
+       * @return true if the property is supported.
+       */
+      public boolean supports(String propertyName)
+      {
+    	  return (PROPERTY_WHITESPACE_FACET.equals(propertyName));
+      }
+
+      /**
+       * Returns the property value for the property name. Returns null if the
+       * property is not supported.
+       * 
+       * @param propertyName -
+       *          name of a property
+       * @return the property value for the property name.
+       */
+      public Object getProperty(String propertyName)
+      {
+    	  if(PROPERTY_WHITESPACE_FACET.equals(propertyName))
+		  	return getWhiteSpaceFacetValue();
+    	  return null;
+      }
+
+      /**
+       * Returns the name of the attribute type. Same as getNodeName().
+       * 
+       * @return the name of the attribute type.
+       */
+      public String getDataTypeName()
+      {
+        XSDSimpleTypeDefinition sc = xsdAttributeUse.getAttributeDeclaration().getTypeDefinition();
+        String typeName = sc.getName();
+        return typeName != null ? typeName : "string";  //$NON-NLS-1$
+      }
+
+      /**
+       * Returns the kind of constraint: none, default or fixed. The kinds are
+       * defined in CMDataType class (IMPLIED_VALUE_NONE, IMPLIED_VALUE_FIXED or
+       * IMPLIED_VALUE_DEFAULT).
+       * 
+       * @return the kind of constraint: none, default or fixed.
+       */
+      public int getImpliedValueKind()
+      {
+        int result = IMPLIED_VALUE_NONE;
+        if (xsdAttributeUse.isSetConstraint())
+        {
+          if (xsdAttributeUse.getConstraint().getValue() == XSDConstraint.DEFAULT)
+            result = IMPLIED_VALUE_DEFAULT;
+          else if (xsdAttributeUse.getConstraint().getValue() == XSDConstraint.FIXED)
+            result = IMPLIED_VALUE_FIXED;
+        }
+        return result;
+      }
+
+      /**
+       * Returns the value of the default or fixed constraint.
+       * 
+       * @return the value of the default or fixed constraint.
+       */
+      public String getImpliedValue()
+      {
+        String result = null;
+        if (xsdAttributeUse.isSetConstraint())
+        {
+          result = xsdAttributeUse.getLexicalValue();
+        }
+        return result;
+      }
+
+      /**
+       * Returns the enumerated values for the attribute type.
+       * 
+       * @return the enumerated values for the attribute type.
+       */
+      public String[] getEnumeratedValues()
+      {
+        return getEnumeratedValuesForType(getXSDType());
+      }
+
+      /**
+       * Generate a valid value for the attribute based on its type.
+       * 
+       * @return a valid value for the attribute based on its type.
+       */
+      public String generateInstanceValue()
+      {
+        XSDAttributeDeclaration attr = xsdAttributeUse.getAttributeDeclaration();
+        return XSDTypeUtil.getInstanceValue(attr.getResolvedAttributeDeclaration().getTypeDefinition());
+      }
+
+      /**
+       * Returns the corresponding XML Schema type definition.
+       * 
+       * @return the corresponding XML Schema type definition.
+       */
+      protected XSDTypeDefinition getXSDType()
+      {
+        XSDAttributeDeclaration attr = xsdAttributeUse.getAttributeDeclaration();
+        return attr.getResolvedAttributeDeclaration().getTypeDefinition();
+      }
+      
+      /**
+       * Obtains the whitespace facet of the XSD simple type.
+       * 
+       * @return The whitespace facet for the XSD type. If none is
+       * defined, or it is a complex type, null.
+       */
+      private String getWhiteSpaceFacetValue()
+      {
+        XSDSimpleTypeDefinition def = getXSDType().getSimpleType();
+        return (def != null && def.getEffectiveWhiteSpaceFacet() != null) ? def.getEffectiveWhiteSpaceFacet().getLexicalValue() : null ;
+      }
+    }
+  }
+  /**
+   * ElementDeclarationBaseImpl implements CMElementDeclaration. This is the
+   * base class for XSDElementDeclaration and DerivedElementDeclarationImpl.
+   * 
+   * Abstract methods in this class are: public abstract Object getKey(); public
+   * abstract Object getNSPrefixQualification(); public abstract
+   * XSDElementDeclaration getXSDElementDeclaration(); public abstract
+   * XSDTypeDefinition getXSDType(); public abstract List getXSITypes(); public
+   * abstract CMElementDeclaration getDerivedElementDeclaration(String
+   * uriQualifiedTypeName); public abstract CMNode getDefinition(); public
+   * abstract String getDefinitionInfo(); public abstract CMNodeListImpl
+   * getSubstitutionGroup();
+   */
+  public static abstract class ElementDeclarationBaseImpl extends XSDBaseAdapter implements CMElementDeclaration
+  {
+    protected CMDataType dataType = new DataTypeImpl();
+    protected CMNamedNodeMap namedNodeMap;
+
+    /**
+     * Returns corresponding XML Schema element declaration.
+     * 
+     * @return corresponding XML Schema element declaration.
+     */
+    protected abstract XSDElementDeclaration getXSDElementDeclaration();
+
+    /**
+     * Returns corresponding XML Schema element declaration.
+     * 
+     * @return corresponding XML Schema element declaration.
+     */
+    protected abstract XSDElementDeclaration getResolvedXSDElementDeclaration();
+
+    /**
+     * Returns the type of the node. The types are defined in CMNode class
+     * (ANY_ELEMENT, ATTRIBUTE_DECLARATION, DATA_TYPE, DOCUMENT,
+     * ELEMENT_DECLARATION, ENTITY_DECLARATION, GROUP, NAME_SPACE or
+     * DOCUMENTATION).
+     * 
+     * @return the type of this node.
+     */
+    public int getNodeType()
+    {
+      return ELEMENT_DECLARATION;
+    }
+
+    /**
+     * Returns the name of the node. The same as getElementName().
+     * 
+     * @return the name of the node.
+     */
+    public String getNodeName()
+    {
+      return getElementName();
+    }
+
+    /**
+     * Returns the name of this element. The same as getNodeName().
+     * 
+     * @return the name of this element.
+     */
+    public String getElementName()
+    {
+      String result = getResolvedXSDElementDeclaration().getName();
+      return result != null ? result : "";
+    }
+
+    /**
+     * Returns true if the property is supported for this class.
+     * 
+     * @param propertyName -
+     *          name of a property
+     * @return true if the property is supported.
+     */
+    public boolean supports(String propertyName)
+    {
+      return propertyName.equals(PROPERTY_XSITYPES) || propertyName.equals(PROPERTY_DERIVED_ELEMENT_DECLARATION) || propertyName.equals(PROPERTY_SUBSTITUTION_GROUP)
+          || propertyName.equals(PROPERTY_ABSTRACT) || super.supports(propertyName);
+    }
+
+    /**
+     * Returns the key for this cmnode which is the corresponding XML Schema
+     * node.
+     * 
+     * @return the key for this cmnode.
+     */
+    public abstract Object getKey();
+
+    /**
+     * Returns the set of attributes defined for this element.
+     * 
+     * @return the set of attributes defined for this element.
+     */
+    public CMNamedNodeMap getAttributes()
+    {
+      CMNamedNodeMapImpl map = new CMNamedNodeMapImpl();
+      XSDTypeDefinition td = getXSDType();
+      getAttributes(map, td);
+      addXSITypeAttribute(map);
+      return map;
+    }
+
+    /**
+     * Gather the set of attributes defined for this element.
+     * 
+     * @param map -
+     *          used for returning the set of attributes.
+     * @param xsdTypeDefinition -
+     *          the type definition for this element.
+     */
+    public void getAttributes(CMNamedNodeMapImpl map, XSDTypeDefinition xsdTypeDefinition)
+    {
+      if (xsdTypeDefinition instanceof XSDComplexTypeDefinition)
+      {
+        XSDComplexTypeDefinition ctd = (XSDComplexTypeDefinition) xsdTypeDefinition;
+        for (Iterator i = ctd.getAttributeUses().iterator(); i.hasNext();)
+        {
+          XSDAttributeUse xsdAttributeUse = (XSDAttributeUse) i.next();
+          XSDAttributeUseAdapter adapter = (XSDAttributeUseAdapter) getAdapter(xsdAttributeUse);
+          if (adapter != null && adapter.getNodeName() != null)
+          {
+            map.getHashtable().put(adapter.getNodeName(), adapter);
+          }
+        }
+      }
+    }
+
+    /**
+     * Returns the content for this element.
+     * 
+     * @return the content for this element.
+     */
+    public CMContent getContent()
+    {
+      CMContent result = null;
+      XSDTypeDefinition td = getXSDType();
+      if (td instanceof XSDComplexTypeDefinition)
+      {
+        DerivedChildVisitor dcv = new DerivedChildVisitor(td);
+        dcv.visitTypeDefinition(td);
+        CMNodeList nodeList = dcv.getChildNodeList();
+        if (nodeList.getLength() > 1)
+        {
+          result = new CMGroupImpl(nodeList, CMGroup.SEQUENCE);
+        }
+        else if (nodeList.getLength() > 0)
+        {
+          result = (CMContent) nodeList.item(0);
+        }
+      }
+      return result;
+    }
+
+    /**
+     * Returns the content type of this element. The content type is defined in
+     * CMElementDeclaration (ANY, EMPTY, ELEMENT, MIXED, PCDATA or CDATA).
+     * 
+     * @return the content type of this element.
+     */
+    public int getContentType()
+    {
+      int contentType = EMPTY;
+      XSDTypeDefinition td = getXSDType();
+      if (td instanceof XSDSimpleTypeDefinition)
+      {
+        String typeName = td.getName();
+        if (typeName != null && typeName.equals("anyType"))
+        {
+          contentType = ANY;
+        }
+        else
+        {
+          contentType = PCDATA;
+        }
+      }
+      else if (td instanceof XSDComplexTypeDefinition)
+      {
+        XSDContentTypeCategory category = ((XSDComplexTypeDefinition) td).getContentTypeCategory();
+        if (category != null)
+        {
+          switch (category.getValue())
+          {
+            case XSDContentTypeCategory.ELEMENT_ONLY :
+              contentType = ELEMENT;
+              break;
+            case XSDContentTypeCategory.EMPTY :
+              contentType = EMPTY;
+              break;
+            case XSDContentTypeCategory.MIXED :
+              contentType = MIXED;
+              break;
+            case XSDContentTypeCategory.SIMPLE :
+              contentType = PCDATA;
+              break;
+          }
+        }
+      }
+      return contentType;
+    }
+
+    /**
+     * Returns the name of the element type.
+     * 
+     * @return the name of the element type.
+     */
+    public CMDataType getDataType()
+    {
+      CMDataType result = null;
+      int contentType = getContentType();
+      boolean hasDataType = contentType == PCDATA || contentType == MIXED;
+      if (hasDataType)
+      {
+        result = dataType;
+      }
+      return result;
+    }
+
+    /**
+     * Returns the value of 'Min Occurs' attribute. The default value is "1".
+     * 
+     * @return the value of the 'Min Occurs' attribute.
+     */
+    public int getMinOccur()
+    {
+      return getMinOccurs(getXSDElementDeclaration());
+    }
+
+    /**
+     * Returns the value of the 'Max Occurs' attribute. The default value is
+     * "1".
+     * 
+     * @return the value of the 'Max Occurs' attribute.
+     */
+    public int getMaxOccur()
+    {
+      return getMaxOccurs(getXSDElementDeclaration());
+    }
+
+    /**
+     * Returns the referenced element declaration if this is an element
+     * reference. Otherwise it returns itself.
+     * 
+     * @return an element declaration.
+     */
+    protected abstract CMNode getDefinition();
+
+    /**
+     * Returns a string indicating whether the element declaration is global or
+     * local. Returns null if this is an element reference.
+     * 
+     * @return a string indicating whether the element declaration is global or
+     *         local.
+     */
+    protected abstract String getDefinitionInfo();
+
+    /**
+     * Returns the elements local to this element declaration.
+     * 
+     * @return the elements local to this element declaration.
+     */
+    public CMNamedNodeMap getLocalElements()
+    {
+      if (namedNodeMap == null)
+      {
+        LocalElementVisitor localElementVisitor = new LocalElementVisitor();
+        localElementVisitor.visitTypeDefinition(getXSDType());
+        namedNodeMap = localElementVisitor.getCMNamedNodeMap();
+      }
+      return namedNodeMap;
+    }
+
+    /**
+     * Returns the property value for the property name. Returns null if the
+     * property is not supported.
+     * 
+     * @param propertyName -
+     *          name of a property
+     * @return the property value for the property name.
+     */
+    public Object getProperty(String propertyName)
+    {
+      Object result = null;
+      if (propertyName.equals(PROPERTY_DEFINITION_INFO))
+      {
+        result = getDefinitionInfo();
+      }
+      else if (propertyName.equals(PROPERTY_DEFINITION))
+      {
+        result = getDefinition();
+      }
+      else if (propertyName.equals(PROPERTY_XSITYPES))
+      {
+        result = getXSITypes();
+      }
+      else if (propertyName.startsWith(PROPERTY_DERIVED_ELEMENT_DECLARATION))
+      {
+        int index = propertyName.indexOf("=");
+        if (index != -1)
+        {
+          String uriQualifiedTypeName = propertyName.substring(index + 1);
+          result = getDerivedElementDeclaration(uriQualifiedTypeName);
+        }
+      }
+      else if (propertyName.equals(PROPERTY_SUBSTITUTION_GROUP))
+      {
+        return getSubstitutionGroup();
+      }
+      else if (propertyName.equals(PROPERTY_SUBSTITUTION_GROUP_VALUE))
+      {
+        return getSubstitutionGroupValue();
+      }
+      else if (propertyName.equals(PROPERTY_ABSTRACT))
+      {
+        return getAbstract();
+      }
+      else
+      {
+        result = super.getProperty(propertyName);
+      }
+      return result;
+    }
+
+    /**
+     * Returns the value of the 'Nillable' attribute. This represents the
+     * nillable infoset property. The default value is false.
+     * 
+     * @return the value of the 'Nillable' attribute.
+     */
+    public boolean isNillable()
+    {
+      if (getXSDElementDeclaration().isSetNillable())
+        return getXSDElementDeclaration().isNillable();
+      else
+        return false;
+    }
+
+    /**
+     * Returns the value of the substitutionGroup attribute.
+     * 
+     * @return value of the substitutionGroup attribute
+     */
+    public String getSubstitutionGroupValue()
+    {
+    	XSDElementDeclaration xsdElementDeclaration = getResolvedXSDElementDeclaration();
+    	if(xsdElementDeclaration != null)
+    	{
+    		Element element = xsdElementDeclaration.getElement();
+    		if(element != null)
+    		{
+    			if (element.hasAttribute(XSDConstants.SUBSTITUTIONGROUP_ATTRIBUTE))
+    				return element.getAttribute(XSDConstants.SUBSTITUTIONGROUP_ATTRIBUTE);
+    			else return null;
+    		}
+    	}
+      return "";
+    }
+    
+    
+    /**
+     * Returns whether the element is 'Abstract'.
+     * 
+     * @return true if the element is 'Abstract'.
+     */
+    public Boolean getAbstract()
+    {
+      boolean result = getResolvedXSDElementDeclaration().isAbstract();
+      // TODO... how do we handle elements with abstract type's ?
+      return result ? Boolean.TRUE : Boolean.FALSE;
+    }
+
+    /**
+     * Returns a list of documentation elements.
+     * 
+     * @return a list of documentation elements.
+     */
+    protected CMNodeList getDocumentation()
+    {
+      XSDElementDeclaration xsdElementDeclaration = getXSDElementDeclaration();
+      XSDAnnotation annotation = xsdElementDeclaration.getAnnotation();
+      
+      // Need to check to see if there are any documentation elements.  Just because
+      // there is an annotation element doesn't mean that the documentation element is
+      // also there, as it could contain just appinfo elements.
+      
+      boolean hasDocumentation = false;
+      
+      if (annotation != null) {
+    	  if (!annotation.getUserInformation().isEmpty()) {
+    		  hasDocumentation = true;
+    	  }
+      }
+
+      // The element may not have annotation and if it is referenced
+      // check the referenced attribute for the annotations.
+      if (hasDocumentation == false) {
+          if (xsdElementDeclaration.isElementDeclarationReference()) {
+        	  annotation = xsdElementDeclaration.getResolvedElementDeclaration().getAnnotation();
+          }
+      }
+      
+      return getDocumentations(annotation);
+    }
+
+    /**
+     * Returns the corresponding XML Schema type definition.
+     * 
+     * @return the corresponding XML Schema type definition.
+     */
+    protected abstract XSDTypeDefinition getXSDType();
+
+    /**
+     * Returns a list of type names.
+     * 
+     * @return a list of type names.
+     */
+    protected abstract List getXSITypes();
+
+    /**
+     * Return the element declaration corresponding to the given uri qualified
+     * type name.
+     * 
+     * @param uriQualifiedTypeName -
+     *          a uri qualified type name
+     * @return corresponding element declaration.
+     */
+    protected abstract CMElementDeclaration getDerivedElementDeclaration(String uriQualifiedTypeName);
+
+    /**
+     * Returns a list of documentation elements.
+     * 
+     * @return a list of documentation elements.
+     */
+    protected void addXSITypeAttribute(CMNamedNodeMapImpl map)
+    {
+      List list = getXSITypes();
+      int listSize = list.size();
+      if (listSize > 1)
+      {
+        CMDataType dataType = new CMDataTypeImpl("typeNames", (String) null);
+        CMAttributeDeclarationImpl attribute = new CMAttributeDeclarationImpl("type", CMAttributeDeclaration.OPTIONAL, dataType);
+        attribute.setCMDocument(xsiDocument);
+        attribute.setPrefixQualification(true);
+        attribute.setXSITypes(list);
+
+        // See https://bugs.eclipse.org/bugs/show_bug.cgi?id=225447
+        // For now, don't clobber the attribute with the same 'type' name defined in the grammar
+        // with the xsi:type attribute.  The impact of this change will be that for content assist, the non-xsi
+        // type attribute will be presented; the generated XML from XSD will have this attribute created, and
+        // not the xsi:type attribute.
+        Hashtable hashTable = map.getHashtable();
+        String name = attribute.getNodeName();
+        if (!hashTable.containsKey(name))
+          hashTable.put(name, attribute);
+      }
+    }
+
+    /**
+     * Returns the cmdocument that is the owner of this cmnode.
+     * 
+     * @return the cmdocument corresponding to this cmnode.
+     */
+    public CMDocument getCMDocument()
+    {      
+      XSDSchema schema = getResolvedXSDElementDeclaration().getSchema();
+      if (schema == null)
+        return null;
+      else  
+        return (CMDocument) getAdapter(schema);
+    }
+
+    /**
+     * Returns the substitution group for this element. The group consists of:
+     * 1. the element declaration itself 2. and any element declaration that has
+     * a {substitution group affiliation} in the group
+     * 
+     * @return the substitution group for this element.
+     */
+    protected abstract CMNodeListImpl getSubstitutionGroup();
+    /*
+     * XSDElementDeclarationAdapter.DataTypeImpl An inner class to hold type
+     * information for this element.
+     */
+    public class DataTypeImpl implements CMDataType
+    {
+      /**
+       * Returns the type of the node. The types are defined in CMNode class
+       * (ANY_ELEMENT, ATTRIBUTE_DECLARATION, DATA_TYPE, DOCUMENT,
+       * ELEMENT_DECLARATION, ENTITY_DECLARATION, GROUP, NAME_SPACE or
+       * DOCUMENTATION).
+       * 
+       * @return the type of this node.
+       */
+      public int getNodeType()
+      {
+        return CMNode.DATA_TYPE;
+      }
+
+      /**
+       * Returns the name of the element type. Same as getDataTypeName().
+       * 
+       * @return the name of the element type.
+       */
+      public String getNodeName()
+      {
+        return getDataTypeName();
+      }
+
+      /**
+       * Returns true if the property is supported for this class.
+       * 
+       * @param propertyName -
+       *          name of a property
+       * @return true if the property is supported.
+       */
+      public boolean supports(String propertyName)
+      {
+        return (PROPERTY_WHITESPACE_FACET.equals(propertyName));
+      }
+
+      /**
+       * Returns the property value for the property name. Returns null if the
+       * property is not supported.
+       * 
+       * @param propertyName -
+       *          name of a property
+       * @return the property value for the property name.
+       */
+      public Object getProperty(String propertyName)
+      {
+        if(PROPERTY_WHITESPACE_FACET.equals(propertyName))
+        	return getWhiteSpaceFacetValue();
+        return null;
+      }
+
+      /**
+       * Returns the name of the element type. Same as getNodeName().
+       * 
+       * @return the name of the element type.
+       */
+      public String getDataTypeName()
+      {
+        String typeName = null;
+        XSDSimpleTypeDefinition std = getXSDType().getSimpleType();
+        if (std != null)
+          typeName = std.getName();
+        return typeName != null ? typeName : "string"; //$NON-NLS-1$
+      }
+
+      /**
+       * Returns the kind of constraint: none, default or fixed. The kinds are
+       * defined in CMDataType class (IMPLIED_VALUE_NONE, IMPLIED_VALUE_FIXED or
+       * IMPLIED_VALUE_DEFAULT).
+       * 
+       * @return the kind of constraint: none, default or fixed.
+       */
+      public int getImpliedValueKind()
+      {
+        int result = IMPLIED_VALUE_NONE;
+        if (getXSDElementDeclaration().isSetConstraint())
+        {
+          if (getXSDElementDeclaration().getConstraint().getValue() == XSDConstraint.DEFAULT)
+            result = IMPLIED_VALUE_DEFAULT;
+          else if (getXSDElementDeclaration().getConstraint().getValue() == XSDConstraint.FIXED)
+            result = IMPLIED_VALUE_FIXED;
+        }
+        return result;
+      }
+
+      /**
+       * Returns the value of the default or fixed constraint.
+       * 
+       * @return the value of the default or fixed constraint.
+       */
+      public String getImpliedValue()
+      {
+        String result = null;
+        if (getXSDElementDeclaration().isSetConstraint())
+        {
+          result = getXSDElementDeclaration().getLexicalValue();
+        }
+        return result;
+      }
+
+      /**
+       * Returns the enumerated values for the attribute type.
+       * 
+       * @return the enumerated values for the attribute type.
+       */
+      public String[] getEnumeratedValues()
+      {
+        return getEnumeratedValuesForType(getXSDType());
+      }
+
+      public String generateInstanceValue()
+      {
+        return XSDTypeUtil.getInstanceValue(getXSDType());
+      }
+
+      /**
+       * Returns the cmdocument that is the owner of this cmnode.
+       * 
+       * @return the cmdocument corresponding to this cmnode.
+       */
+      public CMDocument getCMDocument()
+      {
+        return (CMDocument) getAdapter(getXSDElementDeclaration().getSchema());
+      }
+      
+      /**
+       * Obtains the whitespace facet of the XSD simple type.
+       * 
+       * @return The whitespace facet for the XSD type. If none is
+       * defined, or it is a complex type, null.
+       */
+      private String getWhiteSpaceFacetValue()
+      {
+        XSDSimpleTypeDefinition def = getXSDType().getSimpleType();
+        return (def != null && def.getEffectiveWhiteSpaceFacet() != null) ? def.getEffectiveWhiteSpaceFacet().getLexicalValue() : null ;
+      }
+    }
+  }
+  /**
+   * XSDElementDeclarationAdapter implements CMElementDeclaration. A
+   * representation of the model object 'Element Declaration'.
+   */
+  public static class XSDElementDeclarationAdapter extends ElementDeclarationBaseImpl
+  {
+    protected List derivedElementDeclarations = null;
+    protected List xsiTypes = null;
+    protected XSDElementDeclaration xsdElementDeclaration;
+    protected CMNodeListImpl substitutionGroup;
+
+    /**
+     * Constructor.
+     * 
+     * @param xsdElementDeclaration -
+     *          the XML Schema node.
+     */
+    public XSDElementDeclarationAdapter(XSDElementDeclaration xsdElementDeclaration)
+    {
+      this.xsdElementDeclaration = xsdElementDeclaration;
+    }
+
+    /**
+     * Returns corresponding XML Schema element declaration.
+     * 
+     * @return corresponding XML Schema element declaration.
+     */
+    protected XSDElementDeclaration getXSDElementDeclaration()
+    {
+      return xsdElementDeclaration;
+    }
+
+    /**
+     * Returns corresponding XML Schema element declaration.
+     * 
+     * @return corresponding XML Schema element declaration.
+     */
+    protected XSDElementDeclaration getResolvedXSDElementDeclaration()
+    {
+      return xsdElementDeclaration.getResolvedElementDeclaration();
+    }
+
+    /**
+     * Returns the key for this cmnode which is the corresponding XML Schema
+     * node.
+     * 
+     * @return the key for this cmnode.
+     */
+    public Object getKey()
+    {
+      return xsdElementDeclaration;
+    }
+
+    /**
+     * Returns the referenced element declaration if this is an element
+     * reference. Otherwise it returns itself.
+     * 
+     * @return an element declaration.
+     */
+    public CMNode getDefinition()
+    {
+      return getAdapter(xsdElementDeclaration.getResolvedElementDeclaration());
+    }
+
+    /**
+     * Returns a string indicating whether the element declaration is global or
+     * local. Returns null if this is an element reference.
+     * 
+     * @return a string indicating whether the element declaration is global or
+     *         local.
+     */
+    protected String getDefinitionInfo()
+    {
+      if (xsdElementDeclaration.isElementDeclarationReference())
+        return null;
+      else if (xsdElementDeclaration.isGlobal())
+        return DEFINITION_INFO_GLOBAL;
+      else
+        return DEFINITION_INFO_LOCAL;
+    }
+
+    public Object getNSPrefixQualification()
+    {
+      String form = null;
+      if (xsdElementDeclaration.isElementDeclarationReference())
+      {
+        form = "qualified";
+      }
+      else
+      {
+        if (xsdElementDeclaration.isSetForm())
+        {
+          form = xsdElementDeclaration.getForm().getName();
+        }
+        else
+        {
+          XSDSchema schema = xsdElementDeclaration.getSchema();
+          if (schema != null)
+            form = schema.getElementFormDefault().getName();
+        }
+      }
+      return form;
+    }
+
+    /**
+     * Returns the corresponding XML Schema type definition.
+     * 
+     * @return the corresponding XML Schema type definition.
+     */
+    protected XSDTypeDefinition getXSDType()
+    {
+      return xsdElementDeclaration.getResolvedElementDeclaration().getTypeDefinition();
+    }
+
+    /**
+     * Returns a list of type names.
+     * 
+     * @return a list of type names.
+     */
+    protected List getXSITypes()
+    {
+      if (xsiTypes == null)
+      {
+        computeDerivedTypeInfo();
+      }
+      return xsiTypes;
+    }
+
+    protected void computeDerivedTypeInfo()
+    {
+      xsiTypes = new Vector();
+      derivedElementDeclarations = new Vector();
+      computeDerivedTypeInfoHelper(getXSDType(), xsiTypes, derivedElementDeclarations);
+    }
+
+    protected void computeDerivedTypeInfoHelper(XSDTypeDefinition type, List typeNameList, List edList)
+    {
+      if (type instanceof XSDComplexTypeDefinition)
+      {
+        List derivedTypes = findTypesDerivedFrom(type);
+        ArrayList inclusiveDerivedTypes = new ArrayList();
+        inclusiveDerivedTypes.add(type);
+        if ((derivedTypes != null) && (derivedTypes.size() > 0))
+        {
+          inclusiveDerivedTypes.addAll(derivedTypes);
+        }
+        for (Iterator i = inclusiveDerivedTypes.iterator(); i.hasNext();)
+        {
+          XSDTypeDefinition derivedType = (XSDTypeDefinition) i.next();
+          XSDSchema schema = derivedType.getSchema();
+          if (schema != null)
+          {
+            String uri = schema.getTargetNamespace();
+            String name = derivedType.getName();
+            if (name != null)
+            {
+              name = uri != null ? ("[" + uri + "]" + name) : name;
+              typeNameList.add(name);
+              DerivedElementDeclarationImpl ed = new DerivedElementDeclarationImpl(this, derivedType, name);
+              edList.add(ed);
+            }
+          }
+        }
+      }
+    }
+
+    /**
+     * Return the element declaration corresponding to the given uri qualified
+     * type name.
+     * 
+     * @param uriQualifiedTypeName -
+     *          a uri qualified type name
+     * @return corresponding element declaration.
+     */
+    protected CMElementDeclaration getDerivedElementDeclaration(String uriQualifiedTypeName)
+    {
+      CMElementDeclaration result = null;
+      if (derivedElementDeclarations == null)
+      {
+        computeDerivedTypeInfo();
+      }
+      for (Iterator i = derivedElementDeclarations.iterator(); i.hasNext();)
+      {
+        DerivedElementDeclarationImpl ed = (DerivedElementDeclarationImpl) i.next();
+        if ((ed != null) && (ed.uriQualifiedTypeName != null))
+        {
+          if (ed.uriQualifiedTypeName.equals(uriQualifiedTypeName))
+          {
+            result = ed;
+            break;
+          }
+        }
+      }
+      return result;
+    }
+
+    /**
+     * Returns the substitution group for this element. The group consists of:
+     * 1. the element declaration itself 2. and any element declaration that has
+     * a {substitution group affiliation} in the group
+     * 
+     * @return the substitution group for this element.
+     */
+    protected CMNodeListImpl getSubstitutionGroup()
+    {
+      if (substitutionGroup == null)
+      {
+        substitutionGroup = new CMNodeListImpl();
+        List sgroup = getResolvedXSDElementDeclaration().getSubstitutionGroup();
+        for (Iterator i = sgroup.iterator(); i.hasNext();)
+        {
+          XSDElementDeclaration ed = (XSDElementDeclaration) i.next();  
+          substitutionGroup.add(getAdapter(ed));
+        }
+      }
+      return substitutionGroup;
+    }
+  }
+  /**
+   * DerivedElementDeclarationImpl extends ElementDeclarationBaseImpl
+   *  
+   */
+  public static class DerivedElementDeclarationImpl extends ElementDeclarationBaseImpl
+  {
+    protected XSDElementDeclarationAdapter owner;
+    protected XSDTypeDefinition xsdType;
+    public String uriQualifiedTypeName;
+
+    /**
+     * Constructor.
+     * 
+     * @param owner -
+     * @param xsdType -
+     * @param uriQualifiedTypeName -
+     */
+    public DerivedElementDeclarationImpl(XSDElementDeclarationAdapter owner, XSDTypeDefinition xsdType, String uriQualifiedTypeName)
+    {
+      this.owner = owner;
+      this.xsdType = xsdType;
+      this.uriQualifiedTypeName = uriQualifiedTypeName;
+    }
+
+    /**
+     * Returns corresponding XML Schema element declaration.
+     * 
+     * @return corresponding XML Schema element declaration.
+     */
+    protected XSDElementDeclaration getXSDElementDeclaration()
+    {
+      return (XSDElementDeclaration) owner.getKey();
+    }
+
+    /**
+     * Returns corresponding XML Schema element declaration.
+     * 
+     * @return corresponding XML Schema element declaration.
+     */
+    protected XSDElementDeclaration getResolvedXSDElementDeclaration()
+    {
+      return ((XSDElementDeclaration) owner.getKey()).getResolvedElementDeclaration();
+    }
+
+    /**
+     * Returns the key for this cmnode which is the corresponding XML Schema
+     * node.
+     * 
+     * @return the key for this cmnode.
+     */
+    public Object getKey()
+    {
+      return owner.getKey();
+    }
+
+    /**
+     * Returns the corresponding XML Schema type definition.
+     * 
+     * @return the corresponding XML Schema type definition.
+     */
+    protected XSDTypeDefinition getXSDType()
+    {
+      return xsdType;
+    }
+
+    /**
+     * Returns a list of type names.
+     * 
+     * @return a list of type names.
+     */
+    protected List getXSITypes()
+    {
+      return owner.getXSITypes();
+    }
+
+    /**
+     * Return the element declaration corresponding to the given uri qualified
+     * type name.
+     * 
+     * @param uriQualifiedTypeName -
+     *          a uri qualified type name
+     * @return corresponding element declaration.
+     */
+    protected CMElementDeclaration getDerivedElementDeclaration(String uriQualifiedTypeName)
+    {
+      return owner.getDerivedElementDeclaration(uriQualifiedTypeName);
+    }
+
+    /**
+     * Returns the referenced element declaration if this is an element
+     * reference. Otherwise it returns itself.
+     * 
+     * @return an element declaration.
+     */
+    protected CMNode getDefinition()
+    {
+      return this;
+    }
+
+    /**
+     * Returns a string indicating whether the element declaration is global or
+     * local. Returns null if this is an element reference.
+     * 
+     * @return a string indicating whether the element declaration is global or
+     *         local.
+     */
+    protected String getDefinitionInfo()
+    {
+      return owner.getDefinitionInfo();
+    }
+
+    /*
+     * Returns the value of the form [attribute] which affects the target
+     * namespace of locally scoped features. @return the value of the form
+     * [attribute].
+     */
+    public Object getNSPrefixQualification()
+    {
+      return owner.getNSPrefixQualification();
+    }
+
+    /**
+     * Returns the substitution group for this element. The group consists of:
+     * 1. the element declaration itself 2. and any element declaration that has
+     * a {substitution group affiliation} in the group
+     * 
+     * @return the substitution group for this element.
+     */
+    protected CMNodeListImpl getSubstitutionGroup()
+    {
+      return owner.getSubstitutionGroup();
+    }
+  }
+  /**
+   * XSDWildcardAdapter
+   */
+  public static class XSDWildcardAdapter extends XSDBaseAdapter implements CMAnyElement
+  {
+    protected XSDWildcard xsdWildcard;
+
+    public XSDWildcardAdapter(XSDWildcard xsdWildcard)
+    {
+      this.xsdWildcard = xsdWildcard;
+    }
+
+    /**
+     * Returns the key for this cmnode which is the corresponding XML Schema
+     * node.
+     * 
+     * @return the key for this cmnode.
+     */
+    public Object getKey()
+    {
+      return xsdWildcard;
+    }
+
+    /**
+     * Returns the type of the node. The types are defined in CMNode class
+     * (ANY_ELEMENT, ATTRIBUTE_DECLARATION, DATA_TYPE, DOCUMENT,
+     * ELEMENT_DECLARATION, ENTITY_DECLARATION, GROUP, NAME_SPACE or
+     * DOCUMENTATION).
+     * 
+     * @return the type of this node.
+     */
+    public int getNodeType()
+    {
+      return ANY_ELEMENT;
+    }
+
+    /**
+     * Returns the name of the node. The default value is an empty string value.
+     * All derived classes must override this method if they do not want the
+     * default value.
+     * 
+     * @return the name of the node.
+     */
+    public String getNodeName()
+    {
+      return "any";
+    }
+
+    public String getNamespaceURI()
+    {
+    	if (xsdWildcard.getElement().hasAttribute(XSDConstants.NAMESPACE_ATTRIBUTE))
+    	{
+    		return xsdWildcard.getElement().getAttribute(XSDConstants.NAMESPACE_ATTRIBUTE);
+    	}
+    	else 
+    		return "##any";
+    }
+
+    /**
+     * Returns the value of 'Min Occurs' attribute. The default value is "1".
+     * 
+     * @return the value of the 'Min Occurs' attribute.
+     */
+    public int getMinOccur()
+    {
+      return getMinOccurs(xsdWildcard);
+    }
+
+    /**
+     * Returns the value of the 'Max Occurs' attribute. The default value is
+     * "1".
+     * 
+     * @return the value of the 'Max Occurs' attribute.
+     */
+    public int getMaxOccur()
+    {
+      return getMaxOccurs(xsdWildcard);
+    }
+
+    /**
+     * Returns the cmdocument that is the owner of this cmnode.
+     * 
+     * @return the cmdocument corresponding to this cmnode.
+     */
+    public CMDocument getCMDocument()
+    {
+      return (CMDocument) getAdapter(xsdWildcard.getSchema());
+    }
+
+    /**
+     * Returns a list of documentation elements.
+     * 
+     * @return a list of documentation elements.
+     */
+    protected CMNodeList getDocumentation()
+    {
+      XSDAnnotation annotation = xsdWildcard.getAnnotation();
+      return getDocumentations(annotation);
+    }
+  }
+  /**
+   * XSDModelGroupAdapter
+   */
+  public static class XSDModelGroupAdapter extends XSDBaseAdapter implements CMGroup
+  {
+    protected XSDModelGroup xsdModelGroup;
+
+    public XSDModelGroupAdapter()
+    {
+    }
+
+    public XSDModelGroupAdapter(XSDModelGroup xsdModelGroup)
+    {
+      this.xsdModelGroup = xsdModelGroup;
+    }
+
+    /**
+     * Returns the type of the node. The types are defined in CMNode class
+     * (ANY_ELEMENT, ATTRIBUTE_DECLARATION, DATA_TYPE, DOCUMENT,
+     * ELEMENT_DECLARATION, ENTITY_DECLARATION, GROUP, NAME_SPACE or
+     * DOCUMENTATION).
+     * 
+     * @return the type of this node.
+     */
+    public int getNodeType()
+    {
+      return GROUP;
+    }
+
+    /**
+     * Returns the key for this cmnode which is the corresponding XML Schema
+     * node.
+     * 
+     * @return the key for this cmnode.
+     */
+    public Object getKey()
+    {
+      return xsdModelGroup;
+    }
+
+    /**
+     * Returns a list of the children of this group.
+     * 
+     * @return a list of the children of this group.
+     */
+    public CMNodeList getChildNodes()
+    {
+      CMNodeListImpl nodeList = new CMNodeListImpl();
+      if (xsdModelGroup != null)
+      {
+        for (Iterator i = xsdModelGroup.getParticles().iterator(); i.hasNext();)
+        {
+          XSDParticle particle = (XSDParticle) i.next();
+          XSDParticleContent content = particle.getContent();
+          CMNode adapter = getAdapter(content);
+          if (adapter != null)
+          {
+            nodeList.getList().add(adapter);
+          }
+        }
+      }
+      return nodeList;
+    }
+
+    /**
+     * Returns the name of the node. The default value is an empty string value.
+     * All derived classes must override this method if they do not want the
+     * default value.
+     * 
+     * @return the name of the node.
+     */
+    public String getNodeName()
+    {
+      CMDescriptionBuilder descriptionBuilder = new CMDescriptionBuilder();
+      return descriptionBuilder.buildDescription(this);
+    }
+
+    /**
+     * Returns the value of 'Min Occurs' attribute. The default value is "1".
+     * 
+     * @return the value of the 'Min Occurs' attribute.
+     */
+    public int getMinOccur()
+    {
+      return getMinOccurs(xsdModelGroup);
+    }
+
+    /**
+     * Returns the value of the 'Max Occurs' attribute. The default value is
+     * "1".
+     * 
+     * @return the value of the 'Max Occurs' attribute.
+     */
+    public int getMaxOccur()
+    {
+      return getMaxOccurs(xsdModelGroup);
+    }
+
+    /**
+     * Return operator of this group -- CHOICE, SEQUENCE or ALL value.
+     * 
+     * @return the operator of this group.
+     */
+    public int getOperator()
+    {
+      int result = 0;
+      //todo... handle ALONE case by checkig if child count == 1
+      if (xsdModelGroup != null)
+      {
+        switch (xsdModelGroup.getCompositor().getValue())
+        {
+          case XSDCompositor.CHOICE : {
+            result = CHOICE;
+            break;
+          }
+          case XSDCompositor.SEQUENCE : {
+            result = SEQUENCE;
+            break;
+          }
+          case XSDCompositor.ALL : {
+            result = ALL;
+            break;
+          }
+        }
+      }
+      return result;
+    }
+
+    /**
+     * Returns a list of documentation elements.
+     * 
+     * @return a list of documentation elements.
+     */
+    protected CMNodeList getDocumentation()
+    {
+      XSDAnnotation annotation = xsdModelGroup.getAnnotation();
+      return getDocumentations(annotation);
+    }
+
+    /**
+     * Returns the cmdocument that is the owner of this cmnode.
+     * 
+     * @return the cmdocument corresponding to this cmnode.
+     */
+    public CMDocument getCMDocument()
+    {
+      return (CMDocument) getAdapter(xsdModelGroup.getSchema());
+    }
+  }
+  /**
+   * XSDModelGroupDefinitionAdapter
+   */
+  public static class XSDModelGroupDefinitionAdapter extends XSDBaseAdapter implements CMGroup
+  {
+    protected XSDModelGroupDefinition xsdModelGroupDefinition;
+
+    public XSDModelGroupDefinitionAdapter(XSDModelGroupDefinition xsdModelGroupDefinition)
+    {
+      this.xsdModelGroupDefinition = xsdModelGroupDefinition;
+    }
+
+    /**
+     * Returns the type of the node. The types are defined in CMNode class
+     * (ANY_ELEMENT, ATTRIBUTE_DECLARATION, DATA_TYPE, DOCUMENT,
+     * ELEMENT_DECLARATION, ENTITY_DECLARATION, GROUP, NAME_SPACE or
+     * DOCUMENTATION).
+     * 
+     * @return the type of this node.
+     */
+    public int getNodeType()
+    {
+      return GROUP;
+    }
+
+    /**
+     * Returns the key for this cmnode which is the corresponding XML Schema
+     * node.
+     * 
+     * @return the key for this cmnode.
+     */
+    public Object getKey()
+    {
+      return xsdModelGroupDefinition;
+    }
+
+    /**
+     * Returns a list of the children of this group.
+     * 
+     * @return a list of the children of this group.
+     */
+    public CMNodeList getChildNodes()
+    {
+      CMNodeListImpl nodeList = new CMNodeListImpl();
+      XSDModelGroup modelGroup = xsdModelGroupDefinition.getResolvedModelGroupDefinition().getModelGroup();
+      if (modelGroup != null)
+      {
+        CMNode adapter = getAdapter(modelGroup);
+        nodeList.add(adapter);
+      }
+      return nodeList;
+    }
+
+    /**
+     * Returns the name of the node. The default value is an empty string value.
+     * All derived classes must override this method if they do not want the
+     * default value.
+     * 
+     * @return the name of the node.
+     */
+    public String getNodeName()
+    {
+      CMDescriptionBuilder descriptionBuilder = new CMDescriptionBuilder();
+      return descriptionBuilder.buildDescription(this);
+    }
+
+    /**
+     * Returns the value of 'Min Occurs' attribute. The default value is "1".
+     * 
+     * @return the value of the 'Min Occurs' attribute.
+     */
+    public int getMinOccur()
+    {
+      return getMinOccurs(xsdModelGroupDefinition);
+    }
+
+    /**
+     * Returns the value of the 'Max Occurs' attribute. The default value is
+     * "1".
+     * 
+     * @return the value of the 'Max Occurs' attribute.
+     */
+    public int getMaxOccur()
+    {
+      return getMaxOccurs(xsdModelGroupDefinition);
+    }
+
+    /**
+     * Return operator of this group -- CHOICE, SEQUENCE or ALL value.
+     * 
+     * @return the operator of this group.
+     */
+    public int getOperator()
+    {
+      return XSDCompositor.SEQUENCE;
+    }
+
+    /**
+     * Returns a list of documentation elements.
+     * 
+     * @return a list of documentation elements.
+     */
+    protected CMNodeList getDocumentation()
+    {
+      XSDAnnotation annotation = xsdModelGroupDefinition.getAnnotation();
+      return getDocumentations(annotation);
+    }
+
+    /**
+     * Returns the cmdocument that is the owner of this cmnode.
+     * 
+     * @return the cmdocument corresponding to this cmnode.
+     */
+    public CMDocument getCMDocument()
+    {
+      return (CMDocument) getAdapter(xsdModelGroupDefinition.getSchema());
+    }
+  }
+  /**
+   * DocumentationImpl implements CMDocumentation. A representation of the
+   * documentation element part of the 'User Information' feature. Working with
+   * the documentation element requires dropping down into the DOM model.
+   */
+  public static class DocumentationImpl implements CMDocumentation
+  {
+    protected Element documentation;
+
+    /**
+     * Constructor.
+     * 
+     * @param documentation -
+     *          a documentation element.
+     */
+    public DocumentationImpl(Element documentation)
+    {
+      this.documentation = documentation;
+    }
+
+    /**
+     * Returns the type of the node. The types are defined in CMNode class
+     * (ANY_ELEMENT, ATTRIBUTE_DECLARATION, DATA_TYPE, DOCUMENT,
+     * ELEMENT_DECLARATION, ENTITY_DECLARATION, GROUP, NAME_SPACE or
+     * DOCUMENTATION).
+     * 
+     * @return the type of this node.
+     */
+    public int getNodeType()
+    {
+      return DOCUMENTATION;
+    }
+
+    /**
+     * Returns an empty string value.
+     * 
+     * @return an empty string value.
+     */
+    public String getNodeName()
+    {
+      return "";
+    }
+
+    /**
+     * Returns false. This class does not support any properties.
+     * 
+     * @param propertyName -
+     *          name of a property
+     * @return false.
+     */
+    public boolean supports(String propertyName)
+    {
+      return false;
+    }
+
+    /**
+     * Returns null. This class does not support any properties.
+     * 
+     * @param propertyName -
+     *          name of a property
+     * @return null.
+     */
+    public Object getProperty(String propertyName)
+    {
+      return null;
+    }
+
+    /**
+     * Returns the content of the documentation element.
+     * 
+     * @return the content of the documentation element.
+     */
+    public String getValue()
+    {
+      String content = "";
+      boolean contentFound = false;
+      NodeList nodes = documentation.getChildNodes();
+      for (int i = 0; i < nodes.getLength(); i++)
+      {
+        Node node = nodes.item(i);
+        if (node instanceof Text)
+        {
+          contentFound = true;
+          content += node.getNodeValue();
+        }
+      }
+      return contentFound ? content : null;
+    }
+
+    /**
+     * Returns the xml:lang attribute value of the documentation element.
+     * 
+     * @return the xml:lang attribute value of the documentation element.
+     */
+    public String getLanguage()
+    {
+      return documentation.hasAttributeNS(XSDConstants.XML_NAMESPACE_URI_1998, XML_LANG_ATTRIBUTE) ? documentation.getAttributeNS(XSDConstants.XML_NAMESPACE_URI_1998, XML_LANG_ATTRIBUTE) : null;
+    }
+
+    /**
+     * Returns the source attribute value of the documentation element.
+     * 
+     * @return the source attribute value of the documentation element.
+     */
+    public String getSource()
+    {
+      return documentation.hasAttributeNS(null, XSDConstants.SOURCE_ATTRIBUTE) ? documentation.getAttributeNS(null, XSDConstants.SOURCE_ATTRIBUTE) : null;
+    }
+  }
+  /**
+   * XSIDocument extends CMDocumentImpl. This class is used to hold those
+   * attributes that are for direct use in any XML documents. These attributes
+   * are in a different namespace, which has the namespace name
+   * http://www.w3.org/2001/XMLSchema-instance. Attributes in this namespace
+   * include: xsi:type xsi:nil xsi:schemaLocation xsi:noNamespaceSchemaLocation
+   */
+  public static class XSIDocument extends CMDocumentImpl
+  {
+    public CMAttributeDeclarationImpl nilAttribute;
+
+    /**
+     * Constructor. Creates the 'xsi:nil'
+     */
+    public XSIDocument()
+    {
+      super(XSDConstants.SCHEMA_INSTANCE_URI_2001);
+      // create the 'nill' attribute
+      String[] values = {"false", "true"};
+      nilAttribute = new CMAttributeDeclarationImpl("nil", CMAttributeDeclaration.REQUIRED, new CMDataTypeImpl("boolean", values));
+      nilAttribute.setPrefixQualification(true);
+      nilAttribute.setCMDocument(this);
+    }
+  }
+  /**
+   * Note this XSD model visitor differs from the XSD model visitor in
+   * org.eclipse.wst.xsd.editor plugin. In visitModelGroup method we call
+   * getParticles() instead of getContents(). This gathers all of the content of
+   * a derived type.
+   */
+  public static class XSDCMVisitor extends XSDVisitor
+  {
+    public void visitSimpleTypeDefinition(XSDSimpleTypeDefinition type)
+    {
+      XSDParticle ctd = type.getComplexType();
+      if (ctd != null)
+        visitParticle(ctd);
+    }
+
+    public void visitModelGroup(XSDModelGroup modelGroup)
+    {
+      if (modelGroup.getParticles() != null)
+      {
+        for (Iterator iterator = modelGroup.getParticles().iterator(); iterator.hasNext();)
+        {
+          XSDParticle particle = (XSDParticle) iterator.next();
+          visitParticle(particle);
+        }
+      }
+    }
+
+    public void visitModelGroupDefinition(XSDModelGroupDefinition modelGroupDef)
+    {
+      XSDModelGroup modelGroup = modelGroupDef.getResolvedModelGroupDefinition().getModelGroup();
+      if (modelGroup != null)
+      {
+        visitModelGroup(modelGroup);
+      }
+    }
+  }
+  /**
+   * A visitor class that walks the xsd model and computes the list of children
+   * that belong to the initially visited element type.
+   */
+  public static class DerivedChildVisitor extends XSDCMVisitor
+  {
+    protected CMNodeListImpl childNodeList = new CMNodeListImpl();
+    protected List baseTypeList = new Vector();
+    Object root;
+
+    DerivedChildVisitor(Object root)
+    {
+      this.root = root;
+    }
+
+    public CMNodeListImpl getChildNodeList()
+    {
+      return childNodeList;
+    }
+
+    public void visitWildcard(XSDWildcard wildcard)
+    {
+      childNodeList.getList().add(getAdapter(wildcard));
+    }
+
+    public void visitElementDeclaration(XSDElementDeclaration element)
+    {
+      childNodeList.getList().add(getAdapter(element));
+    }
+
+    public void visitModelGroup(XSDModelGroup modelGroup)
+    {
+      childNodeList.getList().add(getAdapter(modelGroup));
+    }
+
+    public void visitModelGroupDefinition(XSDModelGroupDefinition modelGroupDefinition)
+    {
+      childNodeList.getList().add(getAdapter(modelGroupDefinition));
+    }
+  }
+  /**
+   * A visitor class that gathers all of the elements within a type definition.
+   */
+  public static class LocalElementVisitor extends XSDCMVisitor
+  {
+    protected CMNamedNodeMapImpl namedNodeMap = new CMNamedNodeMapImpl();
+    protected List baseTypeList = new Vector();
+
+    public void visitElementDeclaration(XSDElementDeclaration element)
+    {
+      XSDElementDeclarationAdapter adapter = (XSDElementDeclarationAdapter) getAdapter(element);
+      namedNodeMap.getHashtable().put(adapter.getNodeName(), adapter);
+    }
+
+    public CMNamedNodeMap getCMNamedNodeMap()
+    {
+      return namedNodeMap;
+    }
+  }
+}
diff --git a/bundles/org.eclipse.wst.xsd.core/src-contentmodel/org/eclipse/wst/xsd/contentmodel/internal/XSDTypeUtil.java b/bundles/org.eclipse.wst.xsd.core/src-contentmodel/org/eclipse/wst/xsd/contentmodel/internal/XSDTypeUtil.java
new file mode 100644
index 0000000..1ab69ef
--- /dev/null
+++ b/bundles/org.eclipse.wst.xsd.core/src-contentmodel/org/eclipse/wst/xsd/contentmodel/internal/XSDTypeUtil.java
@@ -0,0 +1,121 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *******************************************************************************/
+package org.eclipse.wst.xsd.contentmodel.internal;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.xsd.XSDSimpleTypeDefinition;
+import org.eclipse.xsd.XSDTypeDefinition;
+
+/**
+ * Helper class to generate valid values for built-in simple types.
+ */
+
+public class XSDTypeUtil
+{
+  protected static Map defaultValue = new HashMap();
+
+  public static void initialize()
+  {
+    defaultValue.put("anySimpleType", null);
+    defaultValue.put("anyType", null);
+    defaultValue.put("anyURI", "http://tempuri.org");
+    defaultValue.put("base64Binary", "MA==");
+    defaultValue.put("boolean", "true");
+    defaultValue.put("byte", "0");
+    defaultValue.put("date", "2001-01-01");
+    defaultValue.put("dateTime", "2001-12-31T12:00:00");
+    defaultValue.put("decimal", "0.0");
+    defaultValue.put("double", "0.0");
+    defaultValue.put("duration", "P1D");
+    defaultValue.put("ENTITY", "entity");
+    defaultValue.put("ENTITIES", "entities");
+    defaultValue.put("float", "0.0");
+    defaultValue.put("gDay", "---01");
+    defaultValue.put("gMonth", "--01--");
+    defaultValue.put("gMonthDay", "--01-01");
+    defaultValue.put("gYear", "2001");
+    defaultValue.put("gYearMonth", "2001-01");
+    defaultValue.put("hexBinary", "0F00");
+    defaultValue.put("ID", null);
+    defaultValue.put("IDREF", null);
+    defaultValue.put("IDREFS", null);
+    defaultValue.put("int", "0");
+    defaultValue.put("integer", "0");
+    defaultValue.put("language", "EN");
+    defaultValue.put("long", "0");
+    defaultValue.put("Name", "Name");
+    defaultValue.put("NCName", "NCName");
+    defaultValue.put("negativeInteger", "-1");
+    defaultValue.put("NMTOKEN", "NMTOKEN");
+    defaultValue.put("NMTOKENS", "NMTOKENS");
+    defaultValue.put("nonNegativeInteger", "0");
+    defaultValue.put("nonPositiveInteger", "0");
+    defaultValue.put("normalizedString", null);
+    defaultValue.put("NOTATION", "NOTATION");
+    defaultValue.put("positiveInteger", "1");
+    defaultValue.put("QName", "QName");
+    defaultValue.put("short", "0");
+    defaultValue.put("string", null);
+    defaultValue.put("time", "12:00:00");
+    defaultValue.put("token", "token");
+    defaultValue.put("unsignedByte", "0");
+    defaultValue.put("unsignedInt", "0");
+    defaultValue.put("unsignedLong", "0");
+    defaultValue.put("unsignedShort", "0");
+  }
+
+
+  /*
+   * Returns true if the type is built-in.
+   * @param type - an XSDTypeDefinition object.
+   * @return true if the type is built-in.
+   */
+  public static boolean isBuiltIn(XSDTypeDefinition type)
+  { 
+    boolean result = false;
+    if (type instanceof XSDSimpleTypeDefinition)
+    {
+      String name = type.getName();
+      if (name != null)
+      {
+        return  defaultValue.containsKey(name); 
+      }
+    }
+    return result;
+  }
+
+
+  /**
+   * Returns a valid default value for the simple type.
+   * @param type - a simple built-in type.
+   * @return a valid default value for the simple type.
+   */
+  public static String getInstanceValue(XSDTypeDefinition type)
+  {
+    if (type != null)
+    {
+      if (isBuiltIn(type))
+      {
+        String nameID = type.getName();
+        return (String)defaultValue.get(nameID);
+      }
+      else
+      {
+        XSDTypeDefinition basetype = type.getBaseType();
+        if (basetype != type) return getInstanceValue(basetype);
+      }
+    }
+    return null;
+  }
+}
+
diff --git a/bundles/org.eclipse.wst.xsd.core/src-contentmodel/org/eclipse/wst/xsd/contentmodel/internal/XSDVisitor.java b/bundles/org.eclipse.wst.xsd.core/src-contentmodel/org/eclipse/wst/xsd/contentmodel/internal/XSDVisitor.java
new file mode 100644
index 0000000..59f5838
--- /dev/null
+++ b/bundles/org.eclipse.wst.xsd.core/src-contentmodel/org/eclipse/wst/xsd/contentmodel/internal/XSDVisitor.java
@@ -0,0 +1,203 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xsd.contentmodel.internal;
+
+import java.util.Iterator;
+import java.util.Stack;
+
+import org.eclipse.xsd.XSDAttributeDeclaration;
+import org.eclipse.xsd.XSDAttributeGroupDefinition;
+import org.eclipse.xsd.XSDComplexTypeContent;
+import org.eclipse.xsd.XSDComplexTypeDefinition;
+import org.eclipse.xsd.XSDElementDeclaration;
+import org.eclipse.xsd.XSDIdentityConstraintDefinition;
+import org.eclipse.xsd.XSDModelGroup;
+import org.eclipse.xsd.XSDModelGroupDefinition;
+import org.eclipse.xsd.XSDNotationDeclaration;
+import org.eclipse.xsd.XSDParticle;
+import org.eclipse.xsd.XSDParticleContent;
+import org.eclipse.xsd.XSDSchema;
+import org.eclipse.xsd.XSDSimpleTypeDefinition;
+import org.eclipse.xsd.XSDTypeDefinition;
+import org.eclipse.xsd.XSDWildcard;
+
+public class XSDVisitor
+{
+  public XSDVisitor()
+  {
+  }
+  
+  protected XSDSchema schema;
+  protected Stack particleStack = new Stack();
+  
+  public void visitSchema(XSDSchema schema)
+  {
+    this.schema = schema;
+    for (Iterator iterator = schema.getAttributeDeclarations().iterator(); iterator.hasNext();)
+    {
+      XSDAttributeDeclaration attr = (XSDAttributeDeclaration) iterator.next();
+      visitAttributeDeclaration(attr);
+    }
+    for (Iterator iterator = schema.getTypeDefinitions().iterator(); iterator.hasNext();)
+    {
+      XSDTypeDefinition type = (XSDTypeDefinition) iterator.next();
+      visitTypeDefinition(type);
+    }
+    for (Iterator iterator = schema.getElementDeclarations().iterator(); iterator.hasNext();)
+    {
+      XSDElementDeclaration element = (XSDElementDeclaration) iterator.next();
+      visitElementDeclaration(element);
+    }
+    for (Iterator iterator = schema.getIdentityConstraintDefinitions().iterator(); iterator.hasNext();)
+    {
+      XSDIdentityConstraintDefinition identityConstraint = (XSDIdentityConstraintDefinition) iterator.next();
+      visitIdentityConstraintDefinition(identityConstraint);
+    }
+    for (Iterator iterator = schema.getModelGroupDefinitions().iterator(); iterator.hasNext();)
+    {
+      XSDModelGroupDefinition modelGroup = (XSDModelGroupDefinition) iterator.next();
+      visitModelGroupDefinition(modelGroup);
+    }
+    for (Iterator iterator = schema.getAttributeGroupDefinitions().iterator(); iterator.hasNext();)
+    {
+      XSDAttributeGroupDefinition attributeGroup = (XSDAttributeGroupDefinition) iterator.next();
+      visitAttributeGroupDefinition(attributeGroup);
+    }
+    for (Iterator iterator = schema.getNotationDeclarations().iterator(); iterator.hasNext();)
+    {
+      XSDNotationDeclaration element = (XSDNotationDeclaration) iterator.next();
+      visitNotationDeclaration(element);
+    }
+    
+  }
+  
+  public void visitAttributeDeclaration(XSDAttributeDeclaration attr)
+  {
+  }
+  
+  public void visitTypeDefinition(XSDTypeDefinition type)
+  {
+    if (type instanceof XSDSimpleTypeDefinition)
+    {
+      visitSimpleTypeDefinition((XSDSimpleTypeDefinition)type);
+    }
+    else if (type instanceof XSDComplexTypeDefinition)
+    {
+      visitComplexTypeDefinition((XSDComplexTypeDefinition)type);
+    }
+  }
+  
+  public void visitElementDeclaration(XSDElementDeclaration element)
+  {
+    if (element.isElementDeclarationReference())
+    {
+    }
+    else if (element.getAnonymousTypeDefinition() != null)
+    {
+      visitTypeDefinition(element.getAnonymousTypeDefinition());
+    }
+  }
+  
+  public void visitIdentityConstraintDefinition(XSDIdentityConstraintDefinition identityConstraint)
+  {
+  }
+  
+  public void visitModelGroupDefinition(XSDModelGroupDefinition modelGroupDef)
+  {
+    if (!modelGroupDef.isModelGroupDefinitionReference())
+    {
+      if (modelGroupDef.getModelGroup() != null)
+      {
+        visitModelGroup(modelGroupDef.getModelGroup());
+      }
+    }
+  }
+  
+  public void visitAttributeGroupDefinition(XSDAttributeGroupDefinition attributeGroup)
+  {
+  }
+  
+  public void visitNotationDeclaration(XSDNotationDeclaration notation)
+  {
+  }
+  
+  public void visitSimpleTypeDefinition(XSDSimpleTypeDefinition type)
+  {
+  }
+  
+  public void visitComplexTypeDefinition(XSDComplexTypeDefinition type)
+  {
+    if (type.getContentType() != null)
+    {
+      XSDComplexTypeContent complexContent = type.getContentType();
+      if (complexContent instanceof XSDSimpleTypeDefinition)
+      {
+        visitSimpleTypeDefinition((XSDSimpleTypeDefinition)complexContent);
+      }
+      else if (complexContent instanceof XSDParticle)
+      {
+        visitParticle((XSDParticle) complexContent);
+      }
+    }
+  }
+  
+  public void visitParticle(XSDParticle particle)
+  {
+    visitParticleContent(particle.getContent());
+  }
+  
+  public void visitParticleContent(XSDParticleContent particleContent)
+  {
+    if (particleContent instanceof XSDModelGroupDefinition)
+    {
+      XSDModelGroupDefinition modelGroupDef = (XSDModelGroupDefinition) particleContent;
+
+      if (particleStack.contains(modelGroupDef))
+      {
+        return;
+      }
+        
+      particleStack.push(modelGroupDef);
+      
+      visitModelGroupDefinition(modelGroupDef);
+      
+      particleStack.pop();
+    }
+    else if (particleContent instanceof XSDModelGroup)
+    {
+      visitModelGroup((XSDModelGroup)particleContent);
+    }
+    else if (particleContent instanceof XSDElementDeclaration)
+    {
+      visitElementDeclaration((XSDElementDeclaration)particleContent);
+    }
+    else if (particleContent instanceof XSDWildcard)
+    {
+      visitWildcard((XSDWildcard)particleContent);
+    }
+  }
+  
+  public void visitModelGroup(XSDModelGroup modelGroup)
+  {
+    if (modelGroup.getContents() != null)
+    {
+      for (Iterator iterator = modelGroup.getContents().iterator(); iterator.hasNext();)
+      {
+        XSDParticle particle = (XSDParticle) iterator.next();
+        visitParticle(particle);
+      }
+    }
+  }
+  
+  public void visitWildcard(XSDWildcard wildcard)
+  {
+  }
+}
diff --git a/bundles/org.eclipse.wst.xsd.core/src-contentmodel/org/eclipse/wst/xsd/contentmodel/internal/util/XSDSchemaLocatorAdapterFactory.java b/bundles/org.eclipse.wst.xsd.core/src-contentmodel/org/eclipse/wst/xsd/contentmodel/internal/util/XSDSchemaLocatorAdapterFactory.java
new file mode 100644
index 0000000..c0309f1
--- /dev/null
+++ b/bundles/org.eclipse.wst.xsd.core/src-contentmodel/org/eclipse/wst/xsd/contentmodel/internal/util/XSDSchemaLocatorAdapterFactory.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xsd.contentmodel.internal.util;
+
+import org.eclipse.emf.common.notify.Adapter;
+import org.eclipse.emf.common.notify.Notifier;
+import org.eclipse.emf.common.notify.impl.AdapterFactoryImpl;
+import org.eclipse.xsd.util.XSDSchemaLocator;
+
+public class XSDSchemaLocatorAdapterFactory extends AdapterFactoryImpl
+{
+    protected XSDSchemaLocatorImpl schemaLocator = new XSDSchemaLocatorImpl();
+
+    public boolean isFactoryForType(Object type)
+    {
+      return type == XSDSchemaLocator.class;
+    }
+
+    public Adapter adaptNew(Notifier target, Object type)
+    {
+      return schemaLocator;
+    }
+}
diff --git a/bundles/org.eclipse.wst.xsd.core/src-contentmodel/org/eclipse/wst/xsd/contentmodel/internal/util/XSDSchemaLocatorImpl.java b/bundles/org.eclipse.wst.xsd.core/src-contentmodel/org/eclipse/wst/xsd/contentmodel/internal/util/XSDSchemaLocatorImpl.java
new file mode 100644
index 0000000..cbf0183
--- /dev/null
+++ b/bundles/org.eclipse.wst.xsd.core/src-contentmodel/org/eclipse/wst/xsd/contentmodel/internal/util/XSDSchemaLocatorImpl.java
@@ -0,0 +1,75 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xsd.contentmodel.internal.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.eclipse.emf.common.notify.impl.AdapterImpl;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.resource.ResourceSet;
+import org.eclipse.wst.common.uriresolver.internal.provisional.URIResolverPlugin;
+import org.eclipse.xsd.XSDSchema;
+import org.eclipse.xsd.util.XSDResourceImpl;
+import org.eclipse.xsd.util.XSDSchemaLocator;
+
+public class XSDSchemaLocatorImpl extends AdapterImpl implements XSDSchemaLocator
+{
+    /**
+     * @see org.eclipse.xsd.util.XSDSchemaLocator#locateSchema(org.eclipse.xsd.XSDSchema,
+     *      java.lang.String, java.lang.String, java.lang.String)
+     */
+    public XSDSchema locateSchema(XSDSchema xsdSchema, String namespaceURI, String rawSchemaLocationURI, String resolvedSchemaLocationURI)
+    {
+      XSDSchema result = null;
+      String baseLocation = xsdSchema.getSchemaLocation();      
+      String resolvedURI = URIResolverPlugin.createResolver().resolve(baseLocation, namespaceURI, rawSchemaLocationURI); 
+      if (resolvedURI == null) 
+      {
+        resolvedURI = resolvedSchemaLocationURI;       
+      }
+      try
+      {        
+        ResourceSet resourceSet = xsdSchema.eResource().getResourceSet();
+        URI uri = URI.createURI(resolvedURI);
+        Resource r = resourceSet.getResource(uri, false); 
+        XSDResourceImpl resolvedResource = null;
+        if (r instanceof XSDResourceImpl)
+        {
+          resolvedResource = (XSDResourceImpl)r;
+        }
+        else        
+        {  
+          String physicalLocation = URIResolverPlugin.createResolver().resolvePhysicalLocation(baseLocation, namespaceURI, resolvedURI);     
+          InputStream inputStream = resourceSet.getURIConverter().createInputStream(URI.createURI(physicalLocation));
+          resolvedResource = (XSDResourceImpl)resourceSet.createResource(URI.createURI("*.xsd"));
+          resolvedResource.setURI(uri);
+          resolvedResource.load(inputStream, null);           
+        }
+
+        result = resolvedResource.getSchema();
+      }
+      catch (IOException exception)
+      {
+        // It is generally not an error to fail to resolve.
+        // If a resource is actually created, 
+        // which happens only when we can create an input stream,
+        // then it's an error if it's not a good schema
+      }
+      return result;
+    }
+
+    public boolean isAdatperForType(Object type)
+    {
+      return type == XSDSchemaLocator.class;
+    }  
+}
diff --git a/bundles/org.eclipse.wst.xsd.core/src-validation/org/eclipse/wst/xsd/core/internal/validation/XSDValidationConfiguration.java b/bundles/org.eclipse.wst.xsd.core/src-validation/org/eclipse/wst/xsd/core/internal/validation/XSDValidationConfiguration.java
new file mode 100644
index 0000000..0a57f95
--- /dev/null
+++ b/bundles/org.eclipse.wst.xsd.core/src-validation/org/eclipse/wst/xsd/core/internal/validation/XSDValidationConfiguration.java
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     David Carver, Standards for Technology in Automotive Retail, bug 1147033
+ *******************************************************************************/
+package org.eclipse.wst.xsd.core.internal.validation;
+
+/**
+ * An XSD validation configuration allows setting specific configuration
+ * information for a WTP XSD validation run. Any features and properties
+ * set on this configuration should not be confused with those from
+ * parsers such as Xerces. (This object does not by default wrap features
+ * and properties from specific parsers.)
+ */
+public class XSDValidationConfiguration 
+{
+  public static String HONOUR_ALL_SCHEMA_LOCATIONS = "HONOUR_ALL_SCHEMA_LOCATIONS"; //$NON-NLS-1$
+  public static String FULL_SCHEMA_CONFORMANCE = "FULL_SCHEMA_CONFORMANCE"; //$NON-NLS-1$
+  private boolean honour_all_schema_locations = false;
+  private boolean fullSchemaConformance = true;
+  
+  /**
+   * Set a feature of this configuration.
+   * 
+   * @param feature
+   * 		The feature to set.
+   * @param value
+   * 		The value to set for the feature.
+   * @throws 
+   * 		An exception is thrown if the feature is not recognized.
+   */
+  public void setFeature(String feature, boolean value) throws Exception
+  {
+	if(HONOUR_ALL_SCHEMA_LOCATIONS.equals(feature))
+	  honour_all_schema_locations = value;
+	else if (FULL_SCHEMA_CONFORMANCE.equals(feature))
+		fullSchemaConformance = value;
+	else
+	  throw new Exception("Feature not recognized."); //$NON-NLS-1$
+	
+  }
+  
+  
+  /**
+   * Get the value for a given feature. If the feature is not defined
+   * this method will throw an exception.
+   * 
+   * @param feature
+   * 		The feature for which to retrieve the value.
+   * @return
+   * 		The feature's value, true or false.
+   * @throws 
+   * 		An exception is thrown if the feature is not recognized.
+   */
+  public boolean getFeature(String feature) throws Exception
+  {
+	if(HONOUR_ALL_SCHEMA_LOCATIONS.equals(feature))
+	  return honour_all_schema_locations;
+	else if (FULL_SCHEMA_CONFORMANCE.equals(feature))
+      return fullSchemaConformance;
+	
+	throw new Exception("Feature not recognized."); //$NON-NLS-1$
+  }
+
+}
diff --git a/bundles/org.eclipse.wst.xsd.core/src-validation/org/eclipse/wst/xsd/core/internal/validation/XSDValidator.java b/bundles/org.eclipse.wst.xsd.core/src-validation/org/eclipse/wst/xsd/core/internal/validation/XSDValidator.java
new file mode 100644
index 0000000..1a6b5e9
--- /dev/null
+++ b/bundles/org.eclipse.wst.xsd.core/src-validation/org/eclipse/wst/xsd/core/internal/validation/XSDValidator.java
@@ -0,0 +1,250 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     David Carver, Standards for Technology in Automotive Retail, bug 1147033
+ *******************************************************************************/
+package org.eclipse.wst.xsd.core.internal.validation;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.xerces.impl.Constants;
+import org.apache.xerces.parsers.XMLGrammarPreparser;
+import org.apache.xerces.util.XMLGrammarPoolImpl;
+import org.apache.xerces.xni.XMLResourceIdentifier;
+import org.apache.xerces.xni.XNIException;
+import org.apache.xerces.xni.grammars.XMLGrammarDescription;
+import org.apache.xerces.xni.parser.XMLEntityResolver;
+import org.apache.xerces.xni.parser.XMLErrorHandler;
+import org.apache.xerces.xni.parser.XMLInputSource;
+import org.apache.xerces.xni.parser.XMLParseException;
+import org.eclipse.wst.common.uriresolver.internal.provisional.URIResolver;
+import org.eclipse.wst.xml.core.internal.validation.XMLValidator;
+import org.eclipse.wst.xml.core.internal.validation.core.ValidationInfo;
+import org.eclipse.wst.xml.core.internal.validation.core.ValidationReport;
+import org.w3c.dom.DOMError;
+
+/**
+ * The XSDValidator will validate XSD files.
+ */
+public class XSDValidator
+{
+  protected URIResolver uriresolver = null;
+
+  public ValidationReport validate(String uri)
+  {
+    return validate(uri, null);
+  }
+  
+  public ValidationReport validate(String uri, InputStream inputStream)
+  {
+	return validate(uri, null, null);
+  }
+  
+  /**
+   * Validate the XSD file specified by the URI.
+   * 
+   * @param uri
+   * 		The URI of the XSD file to validate.
+   * @param inputStream 
+   * 		An input stream representing the XSD file to validate.
+   * @param configuration
+   * 		A configuration for this validation run.
+   */
+  public ValidationReport validate(String uri, InputStream inputStream, XSDValidationConfiguration configuration)
+  {
+	if(configuration == null)
+	{
+	  configuration = new XSDValidationConfiguration();
+	}
+	ValidationInfo valinfo = new ValidationInfo(uri);
+	XSDErrorHandler errorHandler = new XSDErrorHandler(valinfo);
+	try
+	{
+	  XMLGrammarPreparser grammarPreparser = new XMLGrammarPreparser();
+	  grammarPreparser.registerPreparser(XMLGrammarDescription.XML_SCHEMA,null/*schemaLoader*/);
+		  
+	  grammarPreparser.setProperty(Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY, new XMLGrammarPoolImpl());
+	  grammarPreparser.setFeature(Constants.XERCES_FEATURE_PREFIX + Constants.CONTINUE_AFTER_FATAL_ERROR_FEATURE, false);
+      grammarPreparser.setFeature(Constants.XERCES_FEATURE_PREFIX + Constants.NAMESPACES_FEATURE, true);
+      grammarPreparser.setFeature(Constants.XERCES_FEATURE_PREFIX + Constants.NAMESPACE_PREFIXES_FEATURE, true);
+	  grammarPreparser.setFeature(Constants.XERCES_FEATURE_PREFIX + Constants.VALIDATION_FEATURE, true);
+	  grammarPreparser.setFeature(Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_VALIDATION_FEATURE, true);
+
+	  grammarPreparser.setFeature(Constants.XERCES_FEATURE_PREFIX + Constants.EXTERNAL_GENERAL_ENTITIES_FEATURE, true);
+	  grammarPreparser.setFeature(Constants.XERCES_FEATURE_PREFIX + Constants.EXTERNAL_PARAMETER_ENTITIES_FEATURE, true);
+	  grammarPreparser.setFeature(Constants.XERCES_FEATURE_PREFIX + Constants.WARN_ON_DUPLICATE_ATTDEF_FEATURE, true);
+	     
+	  if(configuration.getFeature(XSDValidationConfiguration.HONOUR_ALL_SCHEMA_LOCATIONS))
+	  {
+	    try
+	    {
+	      grammarPreparser.setFeature(Constants.XERCES_FEATURE_PREFIX + "honour-all-schemaLocations", true); //$NON-NLS-1$
+	    }
+        catch (Exception e)
+	    {
+	      // catch the exception and ignore
+	    }
+	  }
+	  
+	  if(configuration.getFeature(XSDValidationConfiguration.FULL_SCHEMA_CONFORMANCE)) {
+		try
+		{
+		  grammarPreparser.setFeature(Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_FULL_CHECKING, true);
+		}
+		catch (Exception e)
+		{
+			// ignore since we don't want to set it or can't.
+		}
+		
+	  }
+	      
+	  grammarPreparser.setErrorHandler(errorHandler);
+	  if (uriresolver != null)
+	  {
+	    XSDEntityResolver resolver = new XSDEntityResolver(uriresolver, uri);
+	    if (resolver != null)
+	    {
+	      grammarPreparser.setEntityResolver(resolver);
+	    }
+	  }
+
+	  try
+	  {
+	  	XMLInputSource is = new XMLInputSource(null, uri, uri, inputStream, null);
+	    grammarPreparser.getLoader(XMLGrammarDescription.XML_SCHEMA);
+		grammarPreparser.preparseGrammar(XMLGrammarDescription.XML_SCHEMA,is);
+	  }
+	  catch (Exception e)
+	  {
+	    //parser will return null pointer exception if the document is structurally invalid
+		//TODO: log error message
+		//System.out.println(e);
+      }
+	}
+	catch (Exception e)
+	{
+      // TODO: log error.
+	  //System.out.println(e);
+	}
+	return valinfo;
+  }
+
+  /**
+   * Set the URI resolver to use with XSD validation.
+   * 
+   * @param uriresolver
+   *          The URI resolver to use.
+   */
+  public void setURIResolver(URIResolver uriresolver)
+  {
+    this.uriresolver = uriresolver;
+  }
+
+  /**
+   * The XSDErrorHandler handle Xerces parsing errors and puts the errors
+   * into the given ValidationInfo object.
+   */
+  protected class XSDErrorHandler implements XMLErrorHandler
+  {
+	  
+    private final ValidationInfo valinfo;
+
+    public XSDErrorHandler(ValidationInfo valinfo)
+    {
+      this.valinfo = valinfo;
+    }
+    
+    /**
+     * Add a validation message with the given severity.
+     * 
+     * @param errorKey The Xerces error key.
+     * @param exception The exception that contains the information about the message.
+     * @param severity The severity of the validation message.
+     */
+    protected void addValidationMessage(String errorKey, XMLParseException exception, int severity)
+    { 
+      String systemId = exception.getExpandedSystemId();
+      if (systemId != null)
+      {
+        if (severity == DOMError.SEVERITY_WARNING)
+        {
+          valinfo.addWarning(exception.getLocalizedMessage(), exception.getLineNumber(), exception.getColumnNumber(), systemId);
+        }
+        else
+        {
+          valinfo.addError(exception.getLocalizedMessage(), exception.getLineNumber(), exception.getColumnNumber(), systemId, errorKey, null);
+        }
+      }
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.xerces.xni.parser.XMLErrorHandler#warning(java.lang.String, java.lang.String, org.apache.xerces.xni.parser.XMLParseException)
+     */
+    public void warning(String domain, String key, XMLParseException exception) throws XNIException
+	{
+    	addValidationMessage(key, exception, DOMError.SEVERITY_WARNING);
+	}
+
+    /* (non-Javadoc)
+     * @see org.apache.xerces.xni.parser.XMLErrorHandler#error(java.lang.String, java.lang.String, org.apache.xerces.xni.parser.XMLParseException)
+     */
+    public void error(String domain, String key, XMLParseException exception) throws XNIException
+    {
+    	addValidationMessage(key, exception, DOMError.SEVERITY_ERROR);
+	}
+
+    /* (non-Javadoc)
+     * @see org.apache.xerces.xni.parser.XMLErrorHandler#fatalError(java.lang.String, java.lang.String, org.apache.xerces.xni.parser.XMLParseException)
+     */
+    public void fatalError(String domain, String key, XMLParseException exception) throws XNIException
+	{
+    	addValidationMessage(key, exception, DOMError.SEVERITY_FATAL_ERROR);
+	}
+  }
+
+  /**
+   * The XSDEntityResolver wraps an idresolver to provide entity resolution to
+   * the XSD validator.
+   */
+  protected class XSDEntityResolver implements XMLEntityResolver
+  {
+    private URIResolver uriresolver = null;
+
+    /**
+     * Constructor.
+     * 
+     * @param idresolver
+     *          The idresolver this entity resolver wraps.
+     * @param baselocation The base location to resolve with.
+     */
+    public XSDEntityResolver(URIResolver uriresolver, String baselocation)
+    {
+      this.uriresolver = uriresolver;
+    }
+    
+    /* (non-Javadoc)
+     * @see org.apache.xerces.xni.parser.XMLEntityResolver#resolveEntity(org.apache.xerces.xni.XMLResourceIdentifier)
+     */
+    public XMLInputSource resolveEntity(XMLResourceIdentifier resourceIdentifier) throws XNIException, IOException
+    {
+      String literalSystemId = resourceIdentifier.getLiteralSystemId();
+      if(literalSystemId != null)
+      {
+    	resourceIdentifier.setLiteralSystemId(literalSystemId.replace('\\','/'));
+      }
+        // TODO cs: In revision 1.1 we explicitly opened a stream to ensure
+        // file I/O problems produced messages. I've remove this fudge for now
+        // since I can't seem to reproduce the problem it was intended to fix.
+        // I'm hoping the newer Xerces code base has fixed this problem and the fudge is defunct.
+        return XMLValidator._internalResolveEntity(uriresolver, resourceIdentifier);
+      
+    }
+  }   
+}
diff --git a/bundles/org.eclipse.wst.xsd.core/src-validation/org/eclipse/wst/xsd/core/internal/validation/eclipse/Validator.java b/bundles/org.eclipse.wst.xsd.core/src-validation/org/eclipse/wst/xsd/core/internal/validation/eclipse/Validator.java
new file mode 100644
index 0000000..5da031b
--- /dev/null
+++ b/bundles/org.eclipse.wst.xsd.core/src-validation/org/eclipse/wst/xsd/core/internal/validation/eclipse/Validator.java
@@ -0,0 +1,115 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2009 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
+ *     David Carver, Standards for Technology in Automotive Retail, bug 1147033
+ *******************************************************************************/
+
+package org.eclipse.wst.xsd.core.internal.validation.eclipse;
+
+import java.io.InputStream;
+import java.util.HashMap;
+
+import org.eclipse.wst.validation.internal.provisional.core.IMessage;
+import org.eclipse.wst.xml.core.internal.XMLCorePlugin;
+import org.eclipse.wst.xml.core.internal.preferences.XMLCorePreferenceNames;
+import org.eclipse.wst.xml.core.internal.validation.core.AbstractNestedValidator;
+import org.eclipse.wst.xml.core.internal.validation.core.NestedValidatorContext;
+import org.eclipse.wst.xml.core.internal.validation.core.ValidationMessage;
+import org.eclipse.wst.xml.core.internal.validation.core.ValidationReport;
+import org.eclipse.wst.xsd.core.internal.XSDCorePlugin;
+import org.eclipse.wst.xsd.core.internal.preferences.XSDCorePreferenceNames;
+import org.eclipse.wst.xsd.core.internal.validation.XSDValidationConfiguration;
+
+public class Validator extends AbstractNestedValidator
+{
+  protected HashMap xsdConfigurations = new HashMap();
+  
+  /* (non-Javadoc)
+   * @see org.eclipse.wst.xml.core.internal.validation.core.AbstractNestedValidator#setupValidation(org.eclipse.wst.xml.core.internal.validation.core.NestedValidatorContext)
+   */
+  protected void setupValidation(NestedValidatorContext context) 
+  {
+	XSDValidationConfiguration configuration = new XSDValidationConfiguration();
+	boolean honourAllSchemaLocations = XMLCorePlugin.getDefault().getPluginPreferences().getBoolean(XMLCorePreferenceNames.HONOUR_ALL_SCHEMA_LOCATIONS);
+	boolean fullSchemaConformance = XSDCorePlugin.getDefault().getPluginPreferences().getBoolean(XSDCorePreferenceNames.FULL_SCHEMA_CONFORMANCE);
+	try
+	{
+	  configuration.setFeature(XSDValidationConfiguration.HONOUR_ALL_SCHEMA_LOCATIONS, honourAllSchemaLocations);
+	  configuration.setFeature(XSDValidationConfiguration.FULL_SCHEMA_CONFORMANCE, fullSchemaConformance);
+	}
+	catch(Exception e)
+	{
+	  // Unable to set the honour all schema locations option. Do nothing.
+	}
+	xsdConfigurations.put(context, configuration);
+	
+	super.setupValidation(context);
+  }
+
+  /* (non-Javadoc)
+   * @see org.eclipse.wst.xml.core.internal.validation.core.AbstractNestedValidator#teardownValidation(org.eclipse.wst.xml.core.internal.validation.core.NestedValidatorContext)
+   */
+  protected void teardownValidation(NestedValidatorContext context) 
+  {
+	xsdConfigurations.remove(context);
+	
+	super.teardownValidation(context);
+  }
+
+  /* (non-Javadoc)
+   * @see org.eclipse.wst.xml.core.internal.validation.core.AbstractNestedValidator#validate(java.lang.String, java.io.InputStream, org.eclipse.wst.xml.core.internal.validation.core.NestedValidatorContext)
+   */
+  public ValidationReport validate(String uri, InputStream inputstream, NestedValidatorContext context)
+  {  
+	XSDValidator validator = XSDValidator.getInstance();
+	
+	XSDValidationConfiguration configuration = (XSDValidationConfiguration)xsdConfigurations.get(context);
+
+	ValidationReport valreport = null;
+	
+	valreport = validator.validate(uri, inputstream, configuration);
+		        
+	return valreport;
+  }
+	  
+  /**
+   * Store additional information in the message parameters. For XSD validation there
+   * are three additional pieces of information to store:
+   * param[0] = the column number of the error
+   * param[1] = the 'squiggle selection strategy' for which DOM part to squiggle
+   * param[2] = the name or value of what is to be squiggled
+   * 
+   * @see org.eclipse.wst.xml.core.internal.validation.core.AbstractNestedValidator#addInfoToMessage(org.eclipse.wst.xml.core.internal.validation.core.ValidationMessage, org.eclipse.wst.validation.internal.provisional.core.IMessage)
+   */
+  protected void addInfoToMessage(ValidationMessage validationMessage, IMessage message)
+  { 
+	String key = validationMessage.getKey();
+	if(key != null)
+	{
+	  XSDMessageInfoHelper messageInfoHelper = new XSDMessageInfoHelper();
+	  String[] messageInfo = messageInfoHelper.createMessageInfo(key, validationMessage.getMessage());
+
+	  message.setAttribute(COLUMN_NUMBER_ATTRIBUTE, new Integer(validationMessage.getColumnNumber()));
+	  message.setAttribute(SQUIGGLE_SELECTION_STRATEGY_ATTRIBUTE, messageInfo[0]);
+	  message.setAttribute(SQUIGGLE_NAME_OR_VALUE_ATTRIBUTE, messageInfo[1]);
+	}
+  }
+
+  /*
+   * (non-Javadoc)
+   * @see org.eclipse.wst.xml.core.internal.validation.core.AbstractNestedValidator#getValidatorID()
+   */
+  protected String getValidatorID()
+  {
+    // Because this class is used as a delegate, return the id of the validator
+    // which delegates to this class.
+
+    return XSDDelegatingValidator.class.getName();
+  }
+}
diff --git a/bundles/org.eclipse.wst.xsd.core/src-validation/org/eclipse/wst/xsd/core/internal/validation/eclipse/XSDDelegatingValidator.java b/bundles/org.eclipse.wst.xsd.core/src-validation/org/eclipse/wst/xsd/core/internal/validation/eclipse/XSDDelegatingValidator.java
new file mode 100644
index 0000000..3f615ba
--- /dev/null
+++ b/bundles/org.eclipse.wst.xsd.core/src-validation/org/eclipse/wst/xsd/core/internal/validation/eclipse/XSDDelegatingValidator.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.xsd.core.internal.validation.eclipse;
+
+import org.eclipse.wst.validation.internal.delegates.DelegatingValidator;
+
+/**
+ * This class provides a unique name (class name) which the validation framework
+ * will use to identify the XSD validator. The actual delegating validator
+ * functionality is provided by the base class. The actual validation
+ * functionality is provided by the delegates registered with this class as
+ * their target.
+ */
+public class XSDDelegatingValidator extends DelegatingValidator
+{
+  /**
+   * Default constructor.
+   */
+  public XSDDelegatingValidator()
+  {
+  }
+}
diff --git a/bundles/org.eclipse.wst.xsd.core/src-validation/org/eclipse/wst/xsd/core/internal/validation/eclipse/XSDMessageInfoHelper.java b/bundles/org.eclipse.wst.xsd.core/src-validation/org/eclipse/wst/xsd/core/internal/validation/eclipse/XSDMessageInfoHelper.java
new file mode 100644
index 0000000..5de3299
--- /dev/null
+++ b/bundles/org.eclipse.wst.xsd.core/src-validation/org/eclipse/wst/xsd/core/internal/validation/eclipse/XSDMessageInfoHelper.java
@@ -0,0 +1,120 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xsd.core.internal.validation.eclipse;
+
+
+/**
+ * The XSDMessageInfoHelper creates a string with the
+ */
+public class XSDMessageInfoHelper
+{
+  public XSDMessageInfoHelper()
+  { super();
+  }
+
+  public String[] createMessageInfo(String errorKey, String errorMessage)
+  { 
+    //Now map the error key to what we would want to underline:
+    String nameOrValue = "";
+    String selectionStrategy = "";
+    if(errorKey != null)
+    {
+      if (errorKey.equals("s4s-elt-invalid-content.1") || errorKey.equals("s4s-elt-must-match.1") || 
+    		  errorKey.equals("s4s-att-must-appear") || errorKey.equals("s4s-elt-invalid-content.2"))  //$NON-NLS-1$  //$NON-NLS-2$  //$NON-NLS-3$  //$NON-NLS-4$
+      { 
+    	selectionStrategy = "START_TAG"; //$NON-NLS-1$
+      }
+      else if (errorKey.equals("s4s-att-not-allowed")) //$NON-NLS-1$
+      { 
+    	selectionStrategy = "ATTRIBUTE_NAME"; //$NON-NLS-1$
+        nameOrValue = getFirstStringBetweenSingleQuotes(errorMessage);
+      }
+      else if (errorKey.equals("s4s-att-invalid-value")) //$NON-NLS-1$
+      { 
+    	selectionStrategy = "ATTRIBUTE_VALUE"; //$NON-NLS-1$
+        nameOrValue = getFirstStringBetweenSingleQuotes(errorMessage);
+      }
+      else if (errorKey.equals("s4s-elt-character")) //$NON-NLS-1$
+      { 
+    	selectionStrategy = "TEXT"; //$NON-NLS-1$
+      }
+      else if (errorKey.equals("src-resolve.4.2") || errorKey.equals("src-resolve"))  //$NON-NLS-1$  //$NON-NLS-2$
+      { 
+    	selectionStrategy = "VALUE_OF_ATTRIBUTE_WITH_GIVEN_VALUE"; //$NON-NLS-1$
+        nameOrValue = getFirstStringBetweenSingleQuotes(errorMessage);
+      }
+      else if (errorKey.equals("EqRequiredInAttribute") || errorKey.equals("OpenQuoteExpected") || 
+    		  errorKey.equals("LessthanInAttValue")) //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+      {
+      	selectionStrategy = "ATTRIBUTE_NAME"; //$NON-NLS-1$
+        nameOrValue = getFirstStringBetweenQuotes(errorMessage);
+      }
+      else if (errorKey.equals("ElementUnterminated")) //$NON-NLS-1$
+      {
+        selectionStrategy = "ENTIRE_ELEMENT"; //$NON-NLS-1$
+      }
+      else if (errorKey.equals("ETagUnterminated") || errorKey.equals("ETagRequired")) //$NON-NLS-1$  //$NON-NLS-2$
+      {
+        selectionStrategy = "END_TAG"; //$NON-NLS-1$
+      }
+    }
+    String messageInfo[] = new String[2];
+    messageInfo[0] = selectionStrategy;
+    messageInfo[1] = nameOrValue;
+    return messageInfo;    
+  }
+
+  /**
+   * This method is used to get the value between the first pair of single quotes
+   * It is used to extract information from the error Message (for example
+   * an attribute name)
+   * 
+   * @param s
+   * 		The string to extract the value from.
+   */
+  protected String getFirstStringBetweenSingleQuotes(String s)
+  {
+    return getFirstStringBetweenDelimiters(s, '\'');
+  }
+
+  /**
+   * This method is used to get the value between the first pair of quotes
+   * It is used to extract information from the error Message (for example
+   * an attribute name)
+   * 
+   * @param s
+   * 		The string to extract the value from.
+   */
+  protected String getFirstStringBetweenQuotes(String s)
+  {
+    return getFirstStringBetweenDelimiters(s, '\"');
+  }
+
+  /**
+   * This method is used to get the value between the first start and end occurrences of the given delimiter character.
+   * 
+   * @param s
+   * 		The string to extract the value from.
+   * @param delimiter 
+   * 		The start and end character
+   */
+  protected String getFirstStringBetweenDelimiters(String s, char delimiter)
+  {
+    int first = s.indexOf(delimiter);
+    int second = s.indexOf(delimiter, first + 1);
+    String stringBetweenDelimiters = null;
+    if (first != -1 && second != -1)
+    { 
+      stringBetweenDelimiters = s.substring(first + 1, second);
+    }
+    return stringBetweenDelimiters;
+  }
+}
diff --git a/bundles/org.eclipse.wst.xsd.core/src-validation/org/eclipse/wst/xsd/core/internal/validation/eclipse/XSDValidator.java b/bundles/org.eclipse.wst.xsd.core/src-validation/org/eclipse/wst/xsd/core/internal/validation/eclipse/XSDValidator.java
new file mode 100644
index 0000000..fbe1a03
--- /dev/null
+++ b/bundles/org.eclipse.wst.xsd.core/src-validation/org/eclipse/wst/xsd/core/internal/validation/eclipse/XSDValidator.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.xsd.core.internal.validation.eclipse;
+
+import org.eclipse.wst.common.uriresolver.internal.provisional.URIResolverPlugin;
+
+
+/**
+ * An XSD validator specific to Eclipse. This validator will wrap the internal
+ * XSD validator an provide automatic URI resolution support.
+ * Using this class is equivalent to using the internal XSD validator and registering
+ * the URI resolver from the URI resolution framework.
+ */
+public class XSDValidator extends org.eclipse.wst.xsd.core.internal.validation.XSDValidator
+{
+  private static XSDValidator instance = null;
+  
+  /**
+   * Return the one and only instance of the XSD validator. The validator
+   * can be reused and cannot be customized so there should only be one instance of it.
+   * 
+   * @return The one and only instance of the XSD validator.
+   */
+  public static XSDValidator getInstance()
+  {
+    if(instance == null)
+    {
+      instance = new XSDValidator();
+    }
+    return instance;
+  }
+  /**
+   * Constructor. Create the XSD validator and set the URI resolver.
+   */
+  protected XSDValidator()
+  {
+    this.setURIResolver(URIResolverPlugin.createResolver());
+  }
+}
diff --git a/bundles/org.eclipse.wst.xsd.core/src/org/eclipse/wst/xsd/core/internal/XSDCorePlugin.java b/bundles/org.eclipse.wst.xsd.core/src/org/eclipse/wst/xsd/core/internal/XSDCorePlugin.java
new file mode 100644
index 0000000..7b30f26
--- /dev/null
+++ b/bundles/org.eclipse.wst.xsd.core/src/org/eclipse/wst/xsd/core/internal/XSDCorePlugin.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+* Copyright (c) 2004, 2005 IBM Corporation and others.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/epl-v10.html
+* 
+* Contributors:
+*     IBM Corporation - Initial API and implementation
+*******************************************************************************/
+package org.eclipse.wst.xsd.core.internal;
+
+import org.eclipse.core.runtime.Plugin;
+import org.eclipse.wst.xsd.contentmodel.internal.XSDCMManager;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The main plugin class to be used in the desktop.
+ */
+public class XSDCorePlugin extends Plugin {
+	//The shared instance.
+	private static XSDCorePlugin plugin;
+	
+	/**
+	 * The constructor.
+	 */
+	public XSDCorePlugin() {
+		super();
+		plugin = this;
+	}
+
+	/**
+	 * This method is called upon plug-in activation
+	 */
+	public void start(BundleContext context) throws Exception {
+		super.start(context);
+    XSDCMManager.getInstance().startup();
+	}
+
+	/**
+	 * This method is called when the plug-in is stopped
+	 */
+	public void stop(BundleContext context) throws Exception {
+		super.stop(context);
+		plugin = null;
+	}
+
+	/**
+	 * Returns the shared instance.
+	 */
+	public static XSDCorePlugin getDefault() {
+		return plugin;
+	}
+
+
+}
diff --git a/bundles/org.eclipse.wst.xsd.core/src/org/eclipse/wst/xsd/core/internal/preferences/XSDCorePreferenceInitializer.java b/bundles/org.eclipse.wst.xsd.core/src/org/eclipse/wst/xsd/core/internal/preferences/XSDCorePreferenceInitializer.java
new file mode 100644
index 0000000..f81f24d
--- /dev/null
+++ b/bundles/org.eclipse.wst.xsd.core/src/org/eclipse/wst/xsd/core/internal/preferences/XSDCorePreferenceInitializer.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.xsd.core.internal.preferences;
+
+import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer;
+import org.eclipse.core.runtime.preferences.DefaultScope;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences;
+import org.eclipse.wst.xsd.core.internal.XSDCorePlugin;
+
+/**
+ * Sets default values for XSD Core preferences
+ */
+public class XSDCorePreferenceInitializer extends AbstractPreferenceInitializer {
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer#initializeDefaultPreferences()
+	 */
+	public void initializeDefaultPreferences() {
+		IEclipsePreferences node = new DefaultScope().getNode(XSDCorePlugin.getDefault().getBundle().getSymbolicName());
+		
+		// In order to provide the best compatibility and conformance to the XML Schema
+		// specification it is recommended that this be defaulted to true.
+		node.putBoolean(XSDCorePreferenceNames.FULL_SCHEMA_CONFORMANCE, true);
+		
+	}
+}
diff --git a/bundles/org.eclipse.wst.xsd.core/src/org/eclipse/wst/xsd/core/internal/preferences/XSDCorePreferenceNames.java b/bundles/org.eclipse.wst.xsd.core/src/org/eclipse/wst/xsd/core/internal/preferences/XSDCorePreferenceNames.java
new file mode 100644
index 0000000..06fc74e
--- /dev/null
+++ b/bundles/org.eclipse.wst.xsd.core/src/org/eclipse/wst/xsd/core/internal/preferences/XSDCorePreferenceNames.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.xsd.core.internal.preferences;
+
+/**
+ * Common preference keys used by XSD core
+ */
+public class XSDCorePreferenceNames {
+	private XSDCorePreferenceNames() {
+		// empty private constructor so users cannot instantiate class
+	}
+	/**
+	 * Indicates whether or not all schema locations should be honoured
+	 * during XSD validation.
+	 * <p>
+	 * Value is of type <code>boolean</code>.<br />
+	 * Possible values: {TRUE, FALSE}
+	 * </p>
+	 * @deprecated
+	 */
+	public static final String HONOUR_ALL_SCHEMA_LOCATIONS = "honourAllSchemaLocations";//$NON-NLS-1$
+	public static final String FULL_SCHEMA_CONFORMANCE = "fullSchemaConformance";//$NON-NLS-1$
+}
diff --git a/features/org.eclipse.wst.web_core.feature.patch/.project b/features/org.eclipse.wst.web_core.feature.patch/.project
new file mode 100644
index 0000000..1825661
--- /dev/null
+++ b/features/org.eclipse.wst.web_core.feature.patch/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.wst.web_core.feature.patch</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.pde.FeatureBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.FeatureNature</nature>
+	</natures>
+</projectDescription>
diff --git a/features/org.eclipse.wst.web_core.feature.patch/build.properties b/features/org.eclipse.wst.web_core.feature.patch/build.properties
new file mode 100644
index 0000000..cb50260
--- /dev/null
+++ b/features/org.eclipse.wst.web_core.feature.patch/build.properties
@@ -0,0 +1,5 @@
+bin.includes = feature.xml,\
+               license.html,\
+               feature.properties,\
+               epl-v10.html,\
+               eclipse_update_120.jpg
diff --git a/features/org.eclipse.wst.web_core.feature.patch/buildnotes_org.eclipse.wst.web_core.feature.patch.html b/features/org.eclipse.wst.web_core.feature.patch/buildnotes_org.eclipse.wst.web_core.feature.patch.html
new file mode 100644
index 0000000..8b3d25d
--- /dev/null
+++ b/features/org.eclipse.wst.web_core.feature.patch/buildnotes_org.eclipse.wst.web_core.feature.patch.html
@@ -0,0 +1,20 @@
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<html>
+
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<meta name="Build" content="Build">
+<title>WTP 3.2.2 Patches</title>
+</head>
+
+<body>
+
+<h1>WTP 3.2.2 Patches</h1>
+
+<h2>org.eclipse.wst.web_core.feature</h2>
+<h3>org.eclipse.wst.html.core</h3>
+<p>Bug <a href="https://bugs.eclipse.org/326470">326470</a>. Script element for HTML5 is lacking attribute declarations</p>
+<p>Bug <a href="https://bugs.eclipse.org/326482">326482</a>. [content model] target attribute in <a> tag incorrectly flagged as warning in HTML5 page</p>
+<p>Bug <a href='https://bugs.eclipse.org/326632'>326632</a>. [ui] Project web content settings is not saved when Document type is set to HTML5</p> 
+</body>
+</html>
\ No newline at end of file
diff --git a/features/org.eclipse.wst.web_core.feature.patch/eclipse_update_120.jpg b/features/org.eclipse.wst.web_core.feature.patch/eclipse_update_120.jpg
new file mode 100644
index 0000000..bfdf708
--- /dev/null
+++ b/features/org.eclipse.wst.web_core.feature.patch/eclipse_update_120.jpg
Binary files differ
diff --git a/features/org.eclipse.wst.web_core.feature.patch/epl-v10.html b/features/org.eclipse.wst.web_core.feature.patch/epl-v10.html
new file mode 100644
index 0000000..abeecc4
--- /dev/null
+++ b/features/org.eclipse.wst.web_core.feature.patch/epl-v10.html
@@ -0,0 +1,262 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
+<title>Eclipse Public License - Version 1.0</title>
+<style type="text/css">
+  body {
+    size: 8.5in 11.0in;
+    margin: 0.25in 0.5in 0.25in 0.5in;
+    tab-interval: 0.5in;
+    }
+  p {  	
+    margin-left: auto;
+    margin-top:  0.5em;
+    margin-bottom: 0.5em;
+    }
+  p.list {
+  	margin-left: 0.5in;
+    margin-top:  0.05em;
+    margin-bottom: 0.05em;
+    }
+  </style>
+
+</head>
+
+<body lang="EN-US">
+
+<h2>Eclipse Public License - v 1.0</h2>
+
+<p>THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE
+PUBLIC LICENSE (&quot;AGREEMENT&quot;). ANY USE, REPRODUCTION OR
+DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS
+AGREEMENT.</p>
+
+<p><b>1. DEFINITIONS</b></p>
+
+<p>&quot;Contribution&quot; means:</p>
+
+<p class="list">a) in the case of the initial Contributor, the initial
+code and documentation distributed under this Agreement, and</p>
+<p class="list">b) in the case of each subsequent Contributor:</p>
+
+<p class="list">i) changes to the Program, and</p>
+<p class="list">ii) additions to the Program;</p>
+<p class="list">where such changes and/or additions to the Program
+originate from and are distributed by that particular Contributor. A
+Contribution 'originates' from a Contributor if it was added to the
+Program by such Contributor itself or anyone acting on such
+Contributor's behalf. Contributions do not include additions to the
+Program which: (i) are separate modules of software distributed in
+conjunction with the Program under their own license agreement, and (ii)
+are not derivative works of the Program.</p>
+
+<p>&quot;Contributor&quot; means any person or entity that distributes
+the Program.</p>
+
+<p>&quot;Licensed Patents&quot; mean patent claims licensable by a
+Contributor which are necessarily infringed by the use or sale of its
+Contribution alone or when combined with the Program.</p>
+
+<p>&quot;Program&quot; means the Contributions distributed in accordance
+with this Agreement.</p>
+
+<p>&quot;Recipient&quot; means anyone who receives the Program under
+this Agreement, including all Contributors.</p>
+
+<p><b>2. GRANT OF RIGHTS</b></p>
+
+<p class="list">a) Subject to the terms of this Agreement, each
+Contributor hereby grants Recipient a non-exclusive, worldwide,
+royalty-free copyright license to reproduce, prepare derivative works
+of, publicly display, publicly perform, distribute and sublicense the
+Contribution of such Contributor, if any, and such derivative works, in
+source code and object code form.</p>
+
+<p class="list">b) Subject to the terms of this Agreement, each
+Contributor hereby grants Recipient a non-exclusive, worldwide,
+royalty-free patent license under Licensed Patents to make, use, sell,
+offer to sell, import and otherwise transfer the Contribution of such
+Contributor, if any, in source code and object code form. This patent
+license shall apply to the combination of the Contribution and the
+Program if, at the time the Contribution is added by the Contributor,
+such addition of the Contribution causes such combination to be covered
+by the Licensed Patents. The patent license shall not apply to any other
+combinations which include the Contribution. No hardware per se is
+licensed hereunder.</p>
+
+<p class="list">c) Recipient understands that although each Contributor
+grants the licenses to its Contributions set forth herein, no assurances
+are provided by any Contributor that the Program does not infringe the
+patent or other intellectual property rights of any other entity. Each
+Contributor disclaims any liability to Recipient for claims brought by
+any other entity based on infringement of intellectual property rights
+or otherwise. As a condition to exercising the rights and licenses
+granted hereunder, each Recipient hereby assumes sole responsibility to
+secure any other intellectual property rights needed, if any. For
+example, if a third party patent license is required to allow Recipient
+to distribute the Program, it is Recipient's responsibility to acquire
+that license before distributing the Program.</p>
+
+<p class="list">d) Each Contributor represents that to its knowledge it
+has sufficient copyright rights in its Contribution, if any, to grant
+the copyright license set forth in this Agreement.</p>
+
+<p><b>3. REQUIREMENTS</b></p>
+
+<p>A Contributor may choose to distribute the Program in object code
+form under its own license agreement, provided that:</p>
+
+<p class="list">a) it complies with the terms and conditions of this
+Agreement; and</p>
+
+<p class="list">b) its license agreement:</p>
+
+<p class="list">i) effectively disclaims on behalf of all Contributors
+all warranties and conditions, express and implied, including warranties
+or conditions of title and non-infringement, and implied warranties or
+conditions of merchantability and fitness for a particular purpose;</p>
+
+<p class="list">ii) effectively excludes on behalf of all Contributors
+all liability for damages, including direct, indirect, special,
+incidental and consequential damages, such as lost profits;</p>
+
+<p class="list">iii) states that any provisions which differ from this
+Agreement are offered by that Contributor alone and not by any other
+party; and</p>
+
+<p class="list">iv) states that source code for the Program is available
+from such Contributor, and informs licensees how to obtain it in a
+reasonable manner on or through a medium customarily used for software
+exchange.</p>
+
+<p>When the Program is made available in source code form:</p>
+
+<p class="list">a) it must be made available under this Agreement; and</p>
+
+<p class="list">b) a copy of this Agreement must be included with each
+copy of the Program.</p>
+
+<p>Contributors may not remove or alter any copyright notices contained
+within the Program.</p>
+
+<p>Each Contributor must identify itself as the originator of its
+Contribution, if any, in a manner that reasonably allows subsequent
+Recipients to identify the originator of the Contribution.</p>
+
+<p><b>4. COMMERCIAL DISTRIBUTION</b></p>
+
+<p>Commercial distributors of software may accept certain
+responsibilities with respect to end users, business partners and the
+like. While this license is intended to facilitate the commercial use of
+the Program, the Contributor who includes the Program in a commercial
+product offering should do so in a manner which does not create
+potential liability for other Contributors. Therefore, if a Contributor
+includes the Program in a commercial product offering, such Contributor
+(&quot;Commercial Contributor&quot;) hereby agrees to defend and
+indemnify every other Contributor (&quot;Indemnified Contributor&quot;)
+against any losses, damages and costs (collectively &quot;Losses&quot;)
+arising from claims, lawsuits and other legal actions brought by a third
+party against the Indemnified Contributor to the extent caused by the
+acts or omissions of such Commercial Contributor in connection with its
+distribution of the Program in a commercial product offering. The
+obligations in this section do not apply to any claims or Losses
+relating to any actual or alleged intellectual property infringement. In
+order to qualify, an Indemnified Contributor must: a) promptly notify
+the Commercial Contributor in writing of such claim, and b) allow the
+Commercial Contributor to control, and cooperate with the Commercial
+Contributor in, the defense and any related settlement negotiations. The
+Indemnified Contributor may participate in any such claim at its own
+expense.</p>
+
+<p>For example, a Contributor might include the Program in a commercial
+product offering, Product X. That Contributor is then a Commercial
+Contributor. If that Commercial Contributor then makes performance
+claims, or offers warranties related to Product X, those performance
+claims and warranties are such Commercial Contributor's responsibility
+alone. Under this section, the Commercial Contributor would have to
+defend claims against the other Contributors related to those
+performance claims and warranties, and if a court requires any other
+Contributor to pay any damages as a result, the Commercial Contributor
+must pay those damages.</p>
+
+<p><b>5. NO WARRANTY</b></p>
+
+<p>EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS
+PROVIDED ON AN &quot;AS IS&quot; BASIS, WITHOUT WARRANTIES OR CONDITIONS
+OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION,
+ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY
+OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely
+responsible for determining the appropriateness of using and
+distributing the Program and assumes all risks associated with its
+exercise of rights under this Agreement , including but not limited to
+the risks and costs of program errors, compliance with applicable laws,
+damage to or loss of data, programs or equipment, and unavailability or
+interruption of operations.</p>
+
+<p><b>6. DISCLAIMER OF LIABILITY</b></p>
+
+<p>EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT
+NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING
+WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR
+DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.</p>
+
+<p><b>7. GENERAL</b></p>
+
+<p>If any provision of this Agreement is invalid or unenforceable under
+applicable law, it shall not affect the validity or enforceability of
+the remainder of the terms of this Agreement, and without further action
+by the parties hereto, such provision shall be reformed to the minimum
+extent necessary to make such provision valid and enforceable.</p>
+
+<p>If Recipient institutes patent litigation against any entity
+(including a cross-claim or counterclaim in a lawsuit) alleging that the
+Program itself (excluding combinations of the Program with other
+software or hardware) infringes such Recipient's patent(s), then such
+Recipient's rights granted under Section 2(b) shall terminate as of the
+date such litigation is filed.</p>
+
+<p>All Recipient's rights under this Agreement shall terminate if it
+fails to comply with any of the material terms or conditions of this
+Agreement and does not cure such failure in a reasonable period of time
+after becoming aware of such noncompliance. If all Recipient's rights
+under this Agreement terminate, Recipient agrees to cease use and
+distribution of the Program as soon as reasonably practicable. However,
+Recipient's obligations under this Agreement and any licenses granted by
+Recipient relating to the Program shall continue and survive.</p>
+
+<p>Everyone is permitted to copy and distribute copies of this
+Agreement, but in order to avoid inconsistency the Agreement is
+copyrighted and may only be modified in the following manner. The
+Agreement Steward reserves the right to publish new versions (including
+revisions) of this Agreement from time to time. No one other than the
+Agreement Steward has the right to modify this Agreement. The Eclipse
+Foundation is the initial Agreement Steward. The Eclipse Foundation may
+assign the responsibility to serve as the Agreement Steward to a
+suitable separate entity. Each new version of the Agreement will be
+given a distinguishing version number. The Program (including
+Contributions) may always be distributed subject to the version of the
+Agreement under which it was received. In addition, after a new version
+of the Agreement is published, Contributor may elect to distribute the
+Program (including its Contributions) under the new version. Except as
+expressly stated in Sections 2(a) and 2(b) above, Recipient receives no
+rights or licenses to the intellectual property of any Contributor under
+this Agreement, whether expressly, by implication, estoppel or
+otherwise. All rights in the Program not expressly granted under this
+Agreement are reserved.</p>
+
+<p>This Agreement is governed by the laws of the State of New York and
+the intellectual property laws of the United States of America. No party
+to this Agreement will bring a legal action under this Agreement more
+than one year after the cause of action arose. Each party waives its
+rights to a jury trial in any resulting litigation.</p>
+
+</body>
+
+</html>
diff --git a/features/org.eclipse.wst.web_core.feature.patch/feature.properties b/features/org.eclipse.wst.web_core.feature.patch/feature.properties
new file mode 100644
index 0000000..254b306
--- /dev/null
+++ b/features/org.eclipse.wst.web_core.feature.patch/feature.properties
@@ -0,0 +1,175 @@
+###############################################################################
+# Copyright (c) 2008 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
+###############################################################################
+# feature.properties
+# contains externalized strings for feature.xml
+# "%foo" in feature.xml corresponds to the key "foo" in this file
+# java.io.Properties file (ISO 8859-1 with "\" escapes)
+# This file should be translated.
+
+# "featureName" property - name of the feature
+featureName=WTP Patches for org.eclipse.wst.web_core.feature
+
+# "providerName" property - name of the company that provides the feature
+providerName=Eclipse Web Tools Platform
+
+# "updateSiteName" property - label for the update site
+updateSiteName=The Eclipse Web Tools Platform (WTP) Project update site
+
+# "description" property - description of the feature
+description=\
+The bugs and fixes are described in the following bugzilla entries:\n\
+\n\
+Bug https://bugs.eclipse.org/326470 Script element for HTML5 is lacking attribute declarations\n\
+Bug https://bugs.eclipse.org/326482 [content model] target attribute in <a> tag incorrectly flagged as warning in HTML5 page\n\
+Bug https://bugs.eclipse.org/326632 [ui] Project web content settings is not saved when Document type is set to HTML5\n\
+\n\
+# "copyright" property - text of the "Feature Update Copyright"
+copyright=\
+Copyright (c) 2010 IBM Corporation and others.\n\
+All rights reserved. This program and the accompanying materials\n\
+are made available under the terms of the Eclipse Public License v1.0\n\
+which accompanies this distribution, and is available at\n\
+http://www.eclipse.org/legal/epl-v10.html\n\
+\n\
+Contributors:\n\
+    IBM Corporation - initial API and implementation\n
+################ end of copyright property ####################################
+
+# "licenseURL" property - URL of the "Feature License"
+# do not translate value - just change to point to a locale-specific HTML page
+licenseURL=license.html
+
+# "license" property - text of the "Feature Update License"
+# should be plain text version of license agreement pointed to be "licenseURL"
+license=\
+Eclipse Foundation Software User Agreement\n\
+April 14, 2010\n\
+\n\
+Usage Of Content\n\
+\n\
+THE ECLIPSE FOUNDATION MAKES AVAILABLE SOFTWARE, DOCUMENTATION, INFORMATION AND/OR\n\
+OTHER MATERIALS FOR OPEN SOURCE PROJECTS (COLLECTIVELY "CONTENT").\n\
+USE OF THE CONTENT IS GOVERNED BY THE TERMS AND CONDITIONS OF THIS\n\
+AGREEMENT AND/OR THE TERMS AND CONDITIONS OF LICENSE AGREEMENTS OR\n\
+NOTICES INDICATED OR REFERENCED BELOW.  BY USING THE CONTENT, YOU\n\
+AGREE THAT YOUR USE OF THE CONTENT IS GOVERNED BY THIS AGREEMENT\n\
+AND/OR THE TERMS AND CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS\n\
+OR NOTICES INDICATED OR REFERENCED BELOW.  IF YOU DO NOT AGREE TO THE\n\
+TERMS AND CONDITIONS OF THIS AGREEMENT AND THE TERMS AND CONDITIONS\n\
+OF ANY APPLICABLE LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED\n\
+BELOW, THEN YOU MAY NOT USE THE CONTENT.\n\
+\n\
+Applicable Licenses\n\
+\n\
+Unless otherwise indicated, all Content made available by the\n\
+Eclipse Foundation is provided to you under the terms and conditions of\n\
+the Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is\n\
+provided with this Content and is also available at http://www.eclipse.org/legal/epl-v10.html.\n\
+For purposes of the EPL, "Program" will mean the Content.\n\
+\n\
+Content includes, but is not limited to, source code, object code,\n\
+documentation and other files maintained in the Eclipse Foundation source code\n\
+repository ("Repository") in software modules ("Modules") and made available\n\
+as downloadable archives ("Downloads").\n\
+\n\
+       - Content may be structured and packaged into modules to facilitate delivering,\n\
+         extending, and upgrading the Content. Typical modules may include plug-ins ("Plug-ins"),\n\
+         plug-in fragments ("Fragments"), and features ("Features").\n\
+       - Each Plug-in or Fragment may be packaged as a sub-directory or JAR (Java(TM) ARchive)\n\
+         in a directory named "plugins".\n\
+       - A Feature is a bundle of one or more Plug-ins and/or Fragments and associated material.\n\
+         Each Feature may be packaged as a sub-directory in a directory named "features".\n\
+         Within a Feature, files named "feature.xml" may contain a list of the names and version\n\
+         numbers of the Plug-ins and/or Fragments associated with that Feature.\n\
+       - Features may also include other Features ("Included Features"). Within a Feature, files\n\
+         named "feature.xml" may contain a list of the names and version numbers of Included Features.\n\
+\n\
+The terms and conditions governing Plug-ins and Fragments should be\n\
+contained in files named "about.html" ("Abouts"). The terms and\n\
+conditions governing Features and Included Features should be contained\n\
+in files named "license.html" ("Feature Licenses"). Abouts and Feature\n\
+Licenses may be located in any directory of a Download or Module\n\
+including, but not limited to the following locations:\n\
+\n\
+       - The top-level (root) directory\n\
+       - Plug-in and Fragment directories\n\
+       - Inside Plug-ins and Fragments packaged as JARs\n\
+       - Sub-directories of the directory named "src" of certain Plug-ins\n\
+       - Feature directories\n\
+\n\
+Note: if a Feature made available by the Eclipse Foundation is installed using the\n\
+Provisioning Technology (as defined below), you must agree to a license ("Feature \n\
+Update License") during the installation process. If the Feature contains\n\
+Included Features, the Feature Update License should either provide you\n\
+with the terms and conditions governing the Included Features or inform\n\
+you where you can locate them. Feature Update Licenses may be found in\n\
+the "license" property of files named "feature.properties" found within a Feature.\n\
+Such Abouts, Feature Licenses, and Feature Update Licenses contain the\n\
+terms and conditions (or references to such terms and conditions) that\n\
+govern your use of the associated Content in that directory.\n\
+\n\
+THE ABOUTS, FEATURE LICENSES, AND FEATURE UPDATE LICENSES MAY REFER\n\
+TO THE EPL OR OTHER LICENSE AGREEMENTS, NOTICES OR TERMS AND CONDITIONS.\n\
+SOME OF THESE OTHER LICENSE AGREEMENTS MAY INCLUDE (BUT ARE NOT LIMITED TO):\n\
+\n\
+       - Common Public License Version 1.0 (available at http://www.eclipse.org/legal/cpl-v10.html)\n\
+       - Apache Software License 1.1 (available at http://www.apache.org/licenses/LICENSE)\n\
+       - Apache Software License 2.0 (available at http://www.apache.org/licenses/LICENSE-2.0)\n\
+       - Metro Link Public License 1.00 (available at http://www.opengroup.org/openmotif/supporters/metrolink/license.html)\n\
+       - Mozilla Public License Version 1.1 (available at http://www.mozilla.org/MPL/MPL-1.1.html)\n\
+\n\
+IT IS YOUR OBLIGATION TO READ AND ACCEPT ALL SUCH TERMS AND CONDITIONS PRIOR\n\
+TO USE OF THE CONTENT. If no About, Feature License, or Feature Update License\n\
+is provided, please contact the Eclipse Foundation to determine what terms and conditions\n\
+govern that particular Content.\n\
+\n\
+\n\Use of Provisioning Technology\n\
+\n\
+The Eclipse Foundation makes available provisioning software, examples of which include,\n\
+but are not limited to, p2 and the Eclipse Update Manager ("Provisioning Technology") for\n\
+the purpose of allowing users to install software, documentation, information and/or\n\
+other materials (collectively "Installable Software"). This capability is provided with\n\
+the intent of allowing such users to install, extend and update Eclipse-based products.\n\
+Information about packaging Installable Software is available at\n\
+http://eclipse.org/equinox/p2/repository_packaging.html ("Specification").\n\
+\n\
+You may use Provisioning Technology to allow other parties to install Installable Software.\n\
+You shall be responsible for enabling the applicable license agreements relating to the\n\
+Installable Software to be presented to, and accepted by, the users of the Provisioning Technology\n\
+in accordance with the Specification. By using Provisioning Technology in such a manner and\n\
+making it available in accordance with the Specification, you further acknowledge your\n\
+agreement to, and the acquisition of all necessary rights to permit the following:\n\
+\n\
+       1. A series of actions may occur ("Provisioning Process") in which a user may execute\n\
+          the Provisioning Technology on a machine ("Target Machine") with the intent of installing,\n\
+          extending or updating the functionality of an Eclipse-based product.\n\
+       2. During the Provisioning Process, the Provisioning Technology may cause third party\n\
+          Installable Software or a portion thereof to be accessed and copied to the Target Machine.\n\
+       3. Pursuant to the Specification, you will provide to the user the terms and conditions that\n\
+          govern the use of the Installable Software ("Installable Software Agreement") and such\n\
+          Installable Software Agreement shall be accessed from the Target Machine in accordance\n\
+          with the Specification. Such Installable Software Agreement must inform the user of the\n\
+          terms and conditions that govern the Installable Software and must solicit acceptance by\n\
+          the end user in the manner prescribed in such Installable Software Agreement. Upon such\n\
+          indication of agreement by the user, the provisioning Technology will complete installation\n\
+          of the Installable Software.\n\
+\n\
+Cryptography\n\
+\n\
+Content may contain encryption software. The country in which you are\n\
+currently may have restrictions on the import, possession, and use,\n\
+and/or re-export to another country, of encryption software. BEFORE\n\
+using any encryption software, please check the country's laws,\n\
+regulations and policies concerning the import, possession, or use, and\n\
+re-export of encryption software, to see if this is permitted.\n\
+\n\
+Java and all Java-based trademarks are trademarks of Oracle Corporation in the United States, other countries, or both.\n
+########### end of license property ##########################################
diff --git a/features/org.eclipse.wst.web_core.feature.patch/feature.xml b/features/org.eclipse.wst.web_core.feature.patch/feature.xml
new file mode 100644
index 0000000..312f05a
--- /dev/null
+++ b/features/org.eclipse.wst.web_core.feature.patch/feature.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<feature
+      id="org.eclipse.wst.web_core.feature.patch"
+      label="%featureName"
+      version="3.2.2.qualifier"
+      provider-name="%providerName">
+
+      <description>%description</description>
+
+      <copyright>%copyright</copyright>
+
+      <license url="%licenseURL">%license</license>
+
+
+
+   <requires>
+      <import feature="org.eclipse.wst.web_core.feature" version="3.2.2.v201008100100-7E7AFHwAJrn5PM15pUYBwJLkSG8j" patch="true"/>
+   </requires>
+
+   <plugin
+         id="org.eclipse.wst.html.core"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+</feature>
diff --git a/features/org.eclipse.wst.web_core.feature.patch/license.html b/features/org.eclipse.wst.web_core.feature.patch/license.html
new file mode 100644
index 0000000..c184ca3
--- /dev/null
+++ b/features/org.eclipse.wst.web_core.feature.patch/license.html
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
+<title>Eclipse Foundation Software User Agreement</title>
+</head>
+
+<body lang="EN-US">
+<h2>Eclipse Foundation Software User Agreement</h2>
+<p>April 14, 2010</p>
+
+<h3>Usage Of Content</h3>
+
+<p>THE ECLIPSE FOUNDATION MAKES AVAILABLE SOFTWARE, DOCUMENTATION, INFORMATION AND/OR OTHER MATERIALS FOR OPEN SOURCE PROJECTS
+   (COLLECTIVELY &quot;CONTENT&quot;).  USE OF THE CONTENT IS GOVERNED BY THE TERMS AND CONDITIONS OF THIS AGREEMENT AND/OR THE TERMS AND
+   CONDITIONS OF LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW.  BY USING THE CONTENT, YOU AGREE THAT YOUR USE
+   OF THE CONTENT IS GOVERNED BY THIS AGREEMENT AND/OR THE TERMS AND CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS OR
+   NOTICES INDICATED OR REFERENCED BELOW.  IF YOU DO NOT AGREE TO THE TERMS AND CONDITIONS OF THIS AGREEMENT AND THE TERMS AND
+   CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW, THEN YOU MAY NOT USE THE CONTENT.</p>
+
+<h3>Applicable Licenses</h3>
+
+<p>Unless otherwise indicated, all Content made available by the Eclipse Foundation is provided to you under the terms and conditions of the Eclipse Public License Version 1.0
+   (&quot;EPL&quot;).  A copy of the EPL is provided with this Content and is also available at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+   For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
+
+<p>Content includes, but is not limited to, source code, object code, documentation and other files maintained in the Eclipse Foundation source code
+   repository (&quot;Repository&quot;) in software modules (&quot;Modules&quot;) and made available as downloadable archives (&quot;Downloads&quot;).</p>
+
+<ul>
+       <li>Content may be structured and packaged into modules to facilitate delivering, extending, and upgrading the Content.  Typical modules may include plug-ins (&quot;Plug-ins&quot;), plug-in fragments (&quot;Fragments&quot;), and features (&quot;Features&quot;).</li>
+       <li>Each Plug-in or Fragment may be packaged as a sub-directory or JAR (Java&trade; ARchive) in a directory named &quot;plugins&quot;.</li>
+       <li>A Feature is a bundle of one or more Plug-ins and/or Fragments and associated material.  Each Feature may be packaged as a sub-directory in a directory named &quot;features&quot;.  Within a Feature, files named &quot;feature.xml&quot; may contain a list of the names and version numbers of the Plug-ins
+      and/or Fragments associated with that Feature.</li>
+       <li>Features may also include other Features (&quot;Included Features&quot;). Within a Feature, files named &quot;feature.xml&quot; may contain a list of the names and version numbers of Included Features.</li>
+</ul>
+
+<p>The terms and conditions governing Plug-ins and Fragments should be contained in files named &quot;about.html&quot; (&quot;Abouts&quot;). The terms and conditions governing Features and
+Included Features should be contained in files named &quot;license.html&quot; (&quot;Feature Licenses&quot;).  Abouts and Feature Licenses may be located in any directory of a Download or Module
+including, but not limited to the following locations:</p>
+
+<ul>
+       <li>The top-level (root) directory</li>
+       <li>Plug-in and Fragment directories</li>
+       <li>Inside Plug-ins and Fragments packaged as JARs</li>
+       <li>Sub-directories of the directory named &quot;src&quot; of certain Plug-ins</li>
+       <li>Feature directories</li>
+</ul>
+
+<p>Note: if a Feature made available by the Eclipse Foundation is installed using the Provisioning Technology (as defined below), you must agree to a license (&quot;Feature Update License&quot;) during the
+installation process.  If the Feature contains Included Features, the Feature Update License should either provide you with the terms and conditions governing the Included Features or
+inform you where you can locate them.  Feature Update Licenses may be found in the &quot;license&quot; property of files named &quot;feature.properties&quot; found within a Feature.
+Such Abouts, Feature Licenses, and Feature Update Licenses contain the terms and conditions (or references to such terms and conditions) that govern your use of the associated Content in
+that directory.</p>
+
+<p>THE ABOUTS, FEATURE LICENSES, AND FEATURE UPDATE LICENSES MAY REFER TO THE EPL OR OTHER LICENSE AGREEMENTS, NOTICES OR TERMS AND CONDITIONS.  SOME OF THESE
+OTHER LICENSE AGREEMENTS MAY INCLUDE (BUT ARE NOT LIMITED TO):</p>
+
+<ul>
+       <li>Common Public License Version 1.0 (available at <a href="http://www.eclipse.org/legal/cpl-v10.html">http://www.eclipse.org/legal/cpl-v10.html</a>)</li>
+       <li>Apache Software License 1.1 (available at <a href="http://www.apache.org/licenses/LICENSE">http://www.apache.org/licenses/LICENSE</a>)</li>
+       <li>Apache Software License 2.0 (available at <a href="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</a>)</li>
+       <li>Metro Link Public License 1.00 (available at <a href="http://www.opengroup.org/openmotif/supporters/metrolink/license.html">http://www.opengroup.org/openmotif/supporters/metrolink/license.html</a>)</li>
+       <li>Mozilla Public License Version 1.1 (available at <a href="http://www.mozilla.org/MPL/MPL-1.1.html">http://www.mozilla.org/MPL/MPL-1.1.html</a>)</li>
+</ul>
+
+<p>IT IS YOUR OBLIGATION TO READ AND ACCEPT ALL SUCH TERMS AND CONDITIONS PRIOR TO USE OF THE CONTENT.  If no About, Feature License, or Feature Update License is provided, please
+contact the Eclipse Foundation to determine what terms and conditions govern that particular Content.</p>
+
+
+<h3>Use of Provisioning Technology</h3>
+
+<p>The Eclipse Foundation makes available provisioning software, examples of which include, but are not limited to, p2 and the Eclipse
+   Update Manager (&quot;Provisioning Technology&quot;) for the purpose of allowing users to install software, documentation, information and/or
+   other materials (collectively &quot;Installable Software&quot;). This capability is provided with the intent of allowing such users to
+   install, extend and update Eclipse-based products. Information about packaging Installable Software is available at <a
+       href="http://eclipse.org/equinox/p2/repository_packaging.html">http://eclipse.org/equinox/p2/repository_packaging.html</a>
+   (&quot;Specification&quot;).</p>
+
+<p>You may use Provisioning Technology to allow other parties to install Installable Software. You shall be responsible for enabling the
+   applicable license agreements relating to the Installable Software to be presented to, and accepted by, the users of the Provisioning Technology
+   in accordance with the Specification. By using Provisioning Technology in such a manner and making it available in accordance with the
+   Specification, you further acknowledge your agreement to, and the acquisition of all necessary rights to permit the following:</p>
+
+<ol>
+       <li>A series of actions may occur (&quot;Provisioning Process&quot;) in which a user may execute the Provisioning Technology
+       on a machine (&quot;Target Machine&quot;) with the intent of installing, extending or updating the functionality of an Eclipse-based
+       product.</li>
+       <li>During the Provisioning Process, the Provisioning Technology may cause third party Installable Software or a portion thereof to be
+       accessed and copied to the Target Machine.</li>
+       <li>Pursuant to the Specification, you will provide to the user the terms and conditions that govern the use of the Installable
+       Software (&quot;Installable Software Agreement&quot;) and such Installable Software Agreement shall be accessed from the Target
+       Machine in accordance with the Specification. Such Installable Software Agreement must inform the user of the terms and conditions that govern
+       the Installable Software and must solicit acceptance by the end user in the manner prescribed in such Installable Software Agreement. Upon such
+       indication of agreement by the user, the provisioning Technology will complete installation of the Installable Software.</li>
+</ol>
+
+<h3>Cryptography</h3>
+
+<p>Content may contain encryption software. The country in which you are currently may have restrictions on the import, possession, and use, and/or re-export to
+   another country, of encryption software. BEFORE using any encryption software, please check the country's laws, regulations and policies concerning the import,
+   possession, or use, and re-export of encryption software, to see if this is permitted.</p>
+
+<p><small>Java and all Java-based trademarks are trademarks of Oracle Corporation in the United States, other countries, or both.</small></p>
+</body>
+</html>
diff --git a/features/org.eclipse.wst.web_ui.feature.patch/.project b/features/org.eclipse.wst.web_ui.feature.patch/.project
new file mode 100644
index 0000000..3a1805e
--- /dev/null
+++ b/features/org.eclipse.wst.web_ui.feature.patch/.project
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.wst.web_ui.feature.patch</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.pde.FeatureBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+	</natures>
+</projectDescription>
diff --git a/features/org.eclipse.wst.web_ui.feature.patch/build.properties b/features/org.eclipse.wst.web_ui.feature.patch/build.properties
new file mode 100644
index 0000000..cb50260
--- /dev/null
+++ b/features/org.eclipse.wst.web_ui.feature.patch/build.properties
@@ -0,0 +1,5 @@
+bin.includes = feature.xml,\
+               license.html,\
+               feature.properties,\
+               epl-v10.html,\
+               eclipse_update_120.jpg
diff --git a/features/org.eclipse.wst.web_ui.feature.patch/buildnotes_org.eclipse.wst.web_ui.feature.patch.html b/features/org.eclipse.wst.web_ui.feature.patch/buildnotes_org.eclipse.wst.web_ui.feature.patch.html
new file mode 100644
index 0000000..1a4e09e
--- /dev/null
+++ b/features/org.eclipse.wst.web_ui.feature.patch/buildnotes_org.eclipse.wst.web_ui.feature.patch.html
@@ -0,0 +1,22 @@
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<html>
+
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<meta name="Build" content="Build">
+<title>WTP 3.2.2 Patches</title>
+</head>
+
+<body>
+
+<h1>WTP 3.2.2 Patches</h1>
+
+<h2>org.eclipse.wst.web_ui.feature</h2>
+
+<p>Bug <a href='https://bugs.eclipse.org/326602'>326602</a>. Auto activation does not work in javascript regions in webpages</p>
+<p>Bug <a href='https://bugs.eclipse.org/326632'>326632</a>. [ui] Project web content settings is not saved when Document type is set to HTML5</p>
+<p>Bug <a href='https://bugs.eclipse.org/326817'>326817</a>. [editor] Leading and trailing HTML style comments in a JS region are not syntax highlighted as expected</p>
+<p>Bug <a href='https://bugs.eclipse.org/326818'>326818</a>. [validation] Text after HTML style comment in JavaScript region marked as validation error</p>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/features/org.eclipse.wst.web_ui.feature.patch/eclipse_update_120.jpg b/features/org.eclipse.wst.web_ui.feature.patch/eclipse_update_120.jpg
new file mode 100644
index 0000000..bfdf708
--- /dev/null
+++ b/features/org.eclipse.wst.web_ui.feature.patch/eclipse_update_120.jpg
Binary files differ
diff --git a/features/org.eclipse.wst.web_ui.feature.patch/epl-v10.html b/features/org.eclipse.wst.web_ui.feature.patch/epl-v10.html
new file mode 100644
index 0000000..abeecc4
--- /dev/null
+++ b/features/org.eclipse.wst.web_ui.feature.patch/epl-v10.html
@@ -0,0 +1,262 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
+<title>Eclipse Public License - Version 1.0</title>
+<style type="text/css">
+  body {
+    size: 8.5in 11.0in;
+    margin: 0.25in 0.5in 0.25in 0.5in;
+    tab-interval: 0.5in;
+    }
+  p {  	
+    margin-left: auto;
+    margin-top:  0.5em;
+    margin-bottom: 0.5em;
+    }
+  p.list {
+  	margin-left: 0.5in;
+    margin-top:  0.05em;
+    margin-bottom: 0.05em;
+    }
+  </style>
+
+</head>
+
+<body lang="EN-US">
+
+<h2>Eclipse Public License - v 1.0</h2>
+
+<p>THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE
+PUBLIC LICENSE (&quot;AGREEMENT&quot;). ANY USE, REPRODUCTION OR
+DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS
+AGREEMENT.</p>
+
+<p><b>1. DEFINITIONS</b></p>
+
+<p>&quot;Contribution&quot; means:</p>
+
+<p class="list">a) in the case of the initial Contributor, the initial
+code and documentation distributed under this Agreement, and</p>
+<p class="list">b) in the case of each subsequent Contributor:</p>
+
+<p class="list">i) changes to the Program, and</p>
+<p class="list">ii) additions to the Program;</p>
+<p class="list">where such changes and/or additions to the Program
+originate from and are distributed by that particular Contributor. A
+Contribution 'originates' from a Contributor if it was added to the
+Program by such Contributor itself or anyone acting on such
+Contributor's behalf. Contributions do not include additions to the
+Program which: (i) are separate modules of software distributed in
+conjunction with the Program under their own license agreement, and (ii)
+are not derivative works of the Program.</p>
+
+<p>&quot;Contributor&quot; means any person or entity that distributes
+the Program.</p>
+
+<p>&quot;Licensed Patents&quot; mean patent claims licensable by a
+Contributor which are necessarily infringed by the use or sale of its
+Contribution alone or when combined with the Program.</p>
+
+<p>&quot;Program&quot; means the Contributions distributed in accordance
+with this Agreement.</p>
+
+<p>&quot;Recipient&quot; means anyone who receives the Program under
+this Agreement, including all Contributors.</p>
+
+<p><b>2. GRANT OF RIGHTS</b></p>
+
+<p class="list">a) Subject to the terms of this Agreement, each
+Contributor hereby grants Recipient a non-exclusive, worldwide,
+royalty-free copyright license to reproduce, prepare derivative works
+of, publicly display, publicly perform, distribute and sublicense the
+Contribution of such Contributor, if any, and such derivative works, in
+source code and object code form.</p>
+
+<p class="list">b) Subject to the terms of this Agreement, each
+Contributor hereby grants Recipient a non-exclusive, worldwide,
+royalty-free patent license under Licensed Patents to make, use, sell,
+offer to sell, import and otherwise transfer the Contribution of such
+Contributor, if any, in source code and object code form. This patent
+license shall apply to the combination of the Contribution and the
+Program if, at the time the Contribution is added by the Contributor,
+such addition of the Contribution causes such combination to be covered
+by the Licensed Patents. The patent license shall not apply to any other
+combinations which include the Contribution. No hardware per se is
+licensed hereunder.</p>
+
+<p class="list">c) Recipient understands that although each Contributor
+grants the licenses to its Contributions set forth herein, no assurances
+are provided by any Contributor that the Program does not infringe the
+patent or other intellectual property rights of any other entity. Each
+Contributor disclaims any liability to Recipient for claims brought by
+any other entity based on infringement of intellectual property rights
+or otherwise. As a condition to exercising the rights and licenses
+granted hereunder, each Recipient hereby assumes sole responsibility to
+secure any other intellectual property rights needed, if any. For
+example, if a third party patent license is required to allow Recipient
+to distribute the Program, it is Recipient's responsibility to acquire
+that license before distributing the Program.</p>
+
+<p class="list">d) Each Contributor represents that to its knowledge it
+has sufficient copyright rights in its Contribution, if any, to grant
+the copyright license set forth in this Agreement.</p>
+
+<p><b>3. REQUIREMENTS</b></p>
+
+<p>A Contributor may choose to distribute the Program in object code
+form under its own license agreement, provided that:</p>
+
+<p class="list">a) it complies with the terms and conditions of this
+Agreement; and</p>
+
+<p class="list">b) its license agreement:</p>
+
+<p class="list">i) effectively disclaims on behalf of all Contributors
+all warranties and conditions, express and implied, including warranties
+or conditions of title and non-infringement, and implied warranties or
+conditions of merchantability and fitness for a particular purpose;</p>
+
+<p class="list">ii) effectively excludes on behalf of all Contributors
+all liability for damages, including direct, indirect, special,
+incidental and consequential damages, such as lost profits;</p>
+
+<p class="list">iii) states that any provisions which differ from this
+Agreement are offered by that Contributor alone and not by any other
+party; and</p>
+
+<p class="list">iv) states that source code for the Program is available
+from such Contributor, and informs licensees how to obtain it in a
+reasonable manner on or through a medium customarily used for software
+exchange.</p>
+
+<p>When the Program is made available in source code form:</p>
+
+<p class="list">a) it must be made available under this Agreement; and</p>
+
+<p class="list">b) a copy of this Agreement must be included with each
+copy of the Program.</p>
+
+<p>Contributors may not remove or alter any copyright notices contained
+within the Program.</p>
+
+<p>Each Contributor must identify itself as the originator of its
+Contribution, if any, in a manner that reasonably allows subsequent
+Recipients to identify the originator of the Contribution.</p>
+
+<p><b>4. COMMERCIAL DISTRIBUTION</b></p>
+
+<p>Commercial distributors of software may accept certain
+responsibilities with respect to end users, business partners and the
+like. While this license is intended to facilitate the commercial use of
+the Program, the Contributor who includes the Program in a commercial
+product offering should do so in a manner which does not create
+potential liability for other Contributors. Therefore, if a Contributor
+includes the Program in a commercial product offering, such Contributor
+(&quot;Commercial Contributor&quot;) hereby agrees to defend and
+indemnify every other Contributor (&quot;Indemnified Contributor&quot;)
+against any losses, damages and costs (collectively &quot;Losses&quot;)
+arising from claims, lawsuits and other legal actions brought by a third
+party against the Indemnified Contributor to the extent caused by the
+acts or omissions of such Commercial Contributor in connection with its
+distribution of the Program in a commercial product offering. The
+obligations in this section do not apply to any claims or Losses
+relating to any actual or alleged intellectual property infringement. In
+order to qualify, an Indemnified Contributor must: a) promptly notify
+the Commercial Contributor in writing of such claim, and b) allow the
+Commercial Contributor to control, and cooperate with the Commercial
+Contributor in, the defense and any related settlement negotiations. The
+Indemnified Contributor may participate in any such claim at its own
+expense.</p>
+
+<p>For example, a Contributor might include the Program in a commercial
+product offering, Product X. That Contributor is then a Commercial
+Contributor. If that Commercial Contributor then makes performance
+claims, or offers warranties related to Product X, those performance
+claims and warranties are such Commercial Contributor's responsibility
+alone. Under this section, the Commercial Contributor would have to
+defend claims against the other Contributors related to those
+performance claims and warranties, and if a court requires any other
+Contributor to pay any damages as a result, the Commercial Contributor
+must pay those damages.</p>
+
+<p><b>5. NO WARRANTY</b></p>
+
+<p>EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS
+PROVIDED ON AN &quot;AS IS&quot; BASIS, WITHOUT WARRANTIES OR CONDITIONS
+OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION,
+ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY
+OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely
+responsible for determining the appropriateness of using and
+distributing the Program and assumes all risks associated with its
+exercise of rights under this Agreement , including but not limited to
+the risks and costs of program errors, compliance with applicable laws,
+damage to or loss of data, programs or equipment, and unavailability or
+interruption of operations.</p>
+
+<p><b>6. DISCLAIMER OF LIABILITY</b></p>
+
+<p>EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT
+NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING
+WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR
+DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.</p>
+
+<p><b>7. GENERAL</b></p>
+
+<p>If any provision of this Agreement is invalid or unenforceable under
+applicable law, it shall not affect the validity or enforceability of
+the remainder of the terms of this Agreement, and without further action
+by the parties hereto, such provision shall be reformed to the minimum
+extent necessary to make such provision valid and enforceable.</p>
+
+<p>If Recipient institutes patent litigation against any entity
+(including a cross-claim or counterclaim in a lawsuit) alleging that the
+Program itself (excluding combinations of the Program with other
+software or hardware) infringes such Recipient's patent(s), then such
+Recipient's rights granted under Section 2(b) shall terminate as of the
+date such litigation is filed.</p>
+
+<p>All Recipient's rights under this Agreement shall terminate if it
+fails to comply with any of the material terms or conditions of this
+Agreement and does not cure such failure in a reasonable period of time
+after becoming aware of such noncompliance. If all Recipient's rights
+under this Agreement terminate, Recipient agrees to cease use and
+distribution of the Program as soon as reasonably practicable. However,
+Recipient's obligations under this Agreement and any licenses granted by
+Recipient relating to the Program shall continue and survive.</p>
+
+<p>Everyone is permitted to copy and distribute copies of this
+Agreement, but in order to avoid inconsistency the Agreement is
+copyrighted and may only be modified in the following manner. The
+Agreement Steward reserves the right to publish new versions (including
+revisions) of this Agreement from time to time. No one other than the
+Agreement Steward has the right to modify this Agreement. The Eclipse
+Foundation is the initial Agreement Steward. The Eclipse Foundation may
+assign the responsibility to serve as the Agreement Steward to a
+suitable separate entity. Each new version of the Agreement will be
+given a distinguishing version number. The Program (including
+Contributions) may always be distributed subject to the version of the
+Agreement under which it was received. In addition, after a new version
+of the Agreement is published, Contributor may elect to distribute the
+Program (including its Contributions) under the new version. Except as
+expressly stated in Sections 2(a) and 2(b) above, Recipient receives no
+rights or licenses to the intellectual property of any Contributor under
+this Agreement, whether expressly, by implication, estoppel or
+otherwise. All rights in the Program not expressly granted under this
+Agreement are reserved.</p>
+
+<p>This Agreement is governed by the laws of the State of New York and
+the intellectual property laws of the United States of America. No party
+to this Agreement will bring a legal action under this Agreement more
+than one year after the cause of action arose. Each party waives its
+rights to a jury trial in any resulting litigation.</p>
+
+</body>
+
+</html>
diff --git a/features/org.eclipse.wst.web_ui.feature.patch/feature.properties b/features/org.eclipse.wst.web_ui.feature.patch/feature.properties
new file mode 100644
index 0000000..d2832c2
--- /dev/null
+++ b/features/org.eclipse.wst.web_ui.feature.patch/feature.properties
@@ -0,0 +1,176 @@
+###############################################################################
+# Copyright (c) 2008 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
+###############################################################################
+# feature.properties
+# contains externalized strings for feature.xml
+# "%foo" in feature.xml corresponds to the key "foo" in this file
+# java.io.Properties file (ISO 8859-1 with "\" escapes)
+# This file should be translated.
+
+# "featureName" property - name of the feature
+featureName=WTP Patch for org.eclipse.wst.web_ui.feature
+
+# "providerName" property - name of the company that provides the feature
+providerName=Eclipse Web Tools Platform
+
+# "updateSiteName" property - label for the update site
+updateSiteName=The Eclipse Web Tools Platform (WTP) Project update site
+
+# "description" property - description of the feature
+description=\
+Contains fixes for the following bugs: \n\
+\n\
+Bug https://bugs.eclipse.org/326602 Auto activation does not work in javascript regions in webpages\n\
+Bug https://bugs.eclipse.org/326632 [ui] Project web content settings is not saved when Document type is set to HTML5\n\
+Bug https://bugs.eclipse.org/326817 [editor] Leading and trailing HTML style comments in a JS region are not syntax highlighted as expected\n\
+Bug https://bugs.eclipse.org/326818 [validation] Text after HTML style comment in JavaScript region marked as validation error\n\
+\n\
+# "copyright" property - text of the "Feature Update Copyright"
+copyright=\
+Copyright (c) 2010 IBM Corporation and others.\n\
+All rights reserved. This program and the accompanying materials\n\
+are made available under the terms of the Eclipse Public License v1.0\n\
+which accompanies this distribution, and is available at\n\
+http://www.eclipse.org/legal/epl-v10.html\n\
+\n\
+Contributors:\n\
+    IBM Corporation - initial API and implementation\n
+################ end of copyright property ####################################
+
+# "licenseURL" property - URL of the "Feature License"
+# do not translate value - just change to point to a locale-specific HTML page
+licenseURL=license.html
+
+# "license" property - text of the "Feature Update License"
+# should be plain text version of license agreement pointed to be "licenseURL"
+license=\
+Eclipse Foundation Software User Agreement\n\
+April 14, 2010\n\
+\n\
+Usage Of Content\n\
+\n\
+THE ECLIPSE FOUNDATION MAKES AVAILABLE SOFTWARE, DOCUMENTATION, INFORMATION AND/OR\n\
+OTHER MATERIALS FOR OPEN SOURCE PROJECTS (COLLECTIVELY "CONTENT").\n\
+USE OF THE CONTENT IS GOVERNED BY THE TERMS AND CONDITIONS OF THIS\n\
+AGREEMENT AND/OR THE TERMS AND CONDITIONS OF LICENSE AGREEMENTS OR\n\
+NOTICES INDICATED OR REFERENCED BELOW.  BY USING THE CONTENT, YOU\n\
+AGREE THAT YOUR USE OF THE CONTENT IS GOVERNED BY THIS AGREEMENT\n\
+AND/OR THE TERMS AND CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS\n\
+OR NOTICES INDICATED OR REFERENCED BELOW.  IF YOU DO NOT AGREE TO THE\n\
+TERMS AND CONDITIONS OF THIS AGREEMENT AND THE TERMS AND CONDITIONS\n\
+OF ANY APPLICABLE LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED\n\
+BELOW, THEN YOU MAY NOT USE THE CONTENT.\n\
+\n\
+Applicable Licenses\n\
+\n\
+Unless otherwise indicated, all Content made available by the\n\
+Eclipse Foundation is provided to you under the terms and conditions of\n\
+the Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is\n\
+provided with this Content and is also available at http://www.eclipse.org/legal/epl-v10.html.\n\
+For purposes of the EPL, "Program" will mean the Content.\n\
+\n\
+Content includes, but is not limited to, source code, object code,\n\
+documentation and other files maintained in the Eclipse Foundation source code\n\
+repository ("Repository") in software modules ("Modules") and made available\n\
+as downloadable archives ("Downloads").\n\
+\n\
+       - Content may be structured and packaged into modules to facilitate delivering,\n\
+         extending, and upgrading the Content. Typical modules may include plug-ins ("Plug-ins"),\n\
+         plug-in fragments ("Fragments"), and features ("Features").\n\
+       - Each Plug-in or Fragment may be packaged as a sub-directory or JAR (Java(TM) ARchive)\n\
+         in a directory named "plugins".\n\
+       - A Feature is a bundle of one or more Plug-ins and/or Fragments and associated material.\n\
+         Each Feature may be packaged as a sub-directory in a directory named "features".\n\
+         Within a Feature, files named "feature.xml" may contain a list of the names and version\n\
+         numbers of the Plug-ins and/or Fragments associated with that Feature.\n\
+       - Features may also include other Features ("Included Features"). Within a Feature, files\n\
+         named "feature.xml" may contain a list of the names and version numbers of Included Features.\n\
+\n\
+The terms and conditions governing Plug-ins and Fragments should be\n\
+contained in files named "about.html" ("Abouts"). The terms and\n\
+conditions governing Features and Included Features should be contained\n\
+in files named "license.html" ("Feature Licenses"). Abouts and Feature\n\
+Licenses may be located in any directory of a Download or Module\n\
+including, but not limited to the following locations:\n\
+\n\
+       - The top-level (root) directory\n\
+       - Plug-in and Fragment directories\n\
+       - Inside Plug-ins and Fragments packaged as JARs\n\
+       - Sub-directories of the directory named "src" of certain Plug-ins\n\
+       - Feature directories\n\
+\n\
+Note: if a Feature made available by the Eclipse Foundation is installed using the\n\
+Provisioning Technology (as defined below), you must agree to a license ("Feature \n\
+Update License") during the installation process. If the Feature contains\n\
+Included Features, the Feature Update License should either provide you\n\
+with the terms and conditions governing the Included Features or inform\n\
+you where you can locate them. Feature Update Licenses may be found in\n\
+the "license" property of files named "feature.properties" found within a Feature.\n\
+Such Abouts, Feature Licenses, and Feature Update Licenses contain the\n\
+terms and conditions (or references to such terms and conditions) that\n\
+govern your use of the associated Content in that directory.\n\
+\n\
+THE ABOUTS, FEATURE LICENSES, AND FEATURE UPDATE LICENSES MAY REFER\n\
+TO THE EPL OR OTHER LICENSE AGREEMENTS, NOTICES OR TERMS AND CONDITIONS.\n\
+SOME OF THESE OTHER LICENSE AGREEMENTS MAY INCLUDE (BUT ARE NOT LIMITED TO):\n\
+\n\
+       - Common Public License Version 1.0 (available at http://www.eclipse.org/legal/cpl-v10.html)\n\
+       - Apache Software License 1.1 (available at http://www.apache.org/licenses/LICENSE)\n\
+       - Apache Software License 2.0 (available at http://www.apache.org/licenses/LICENSE-2.0)\n\
+       - Metro Link Public License 1.00 (available at http://www.opengroup.org/openmotif/supporters/metrolink/license.html)\n\
+       - Mozilla Public License Version 1.1 (available at http://www.mozilla.org/MPL/MPL-1.1.html)\n\
+\n\
+IT IS YOUR OBLIGATION TO READ AND ACCEPT ALL SUCH TERMS AND CONDITIONS PRIOR\n\
+TO USE OF THE CONTENT. If no About, Feature License, or Feature Update License\n\
+is provided, please contact the Eclipse Foundation to determine what terms and conditions\n\
+govern that particular Content.\n\
+\n\
+\n\Use of Provisioning Technology\n\
+\n\
+The Eclipse Foundation makes available provisioning software, examples of which include,\n\
+but are not limited to, p2 and the Eclipse Update Manager ("Provisioning Technology") for\n\
+the purpose of allowing users to install software, documentation, information and/or\n\
+other materials (collectively "Installable Software"). This capability is provided with\n\
+the intent of allowing such users to install, extend and update Eclipse-based products.\n\
+Information about packaging Installable Software is available at\n\
+http://eclipse.org/equinox/p2/repository_packaging.html ("Specification").\n\
+\n\
+You may use Provisioning Technology to allow other parties to install Installable Software.\n\
+You shall be responsible for enabling the applicable license agreements relating to the\n\
+Installable Software to be presented to, and accepted by, the users of the Provisioning Technology\n\
+in accordance with the Specification. By using Provisioning Technology in such a manner and\n\
+making it available in accordance with the Specification, you further acknowledge your\n\
+agreement to, and the acquisition of all necessary rights to permit the following:\n\
+\n\
+       1. A series of actions may occur ("Provisioning Process") in which a user may execute\n\
+          the Provisioning Technology on a machine ("Target Machine") with the intent of installing,\n\
+          extending or updating the functionality of an Eclipse-based product.\n\
+       2. During the Provisioning Process, the Provisioning Technology may cause third party\n\
+          Installable Software or a portion thereof to be accessed and copied to the Target Machine.\n\
+       3. Pursuant to the Specification, you will provide to the user the terms and conditions that\n\
+          govern the use of the Installable Software ("Installable Software Agreement") and such\n\
+          Installable Software Agreement shall be accessed from the Target Machine in accordance\n\
+          with the Specification. Such Installable Software Agreement must inform the user of the\n\
+          terms and conditions that govern the Installable Software and must solicit acceptance by\n\
+          the end user in the manner prescribed in such Installable Software Agreement. Upon such\n\
+          indication of agreement by the user, the provisioning Technology will complete installation\n\
+          of the Installable Software.\n\
+\n\
+Cryptography\n\
+\n\
+Content may contain encryption software. The country in which you are\n\
+currently may have restrictions on the import, possession, and use,\n\
+and/or re-export to another country, of encryption software. BEFORE\n\
+using any encryption software, please check the country's laws,\n\
+regulations and policies concerning the import, possession, or use, and\n\
+re-export of encryption software, to see if this is permitted.\n\
+\n\
+Java and all Java-based trademarks are trademarks of Oracle Corporation in the United States, other countries, or both.\n
+########### end of license property ##########################################
diff --git a/features/org.eclipse.wst.web_ui.feature.patch/feature.xml b/features/org.eclipse.wst.web_ui.feature.patch/feature.xml
new file mode 100644
index 0000000..f0b56c2
--- /dev/null
+++ b/features/org.eclipse.wst.web_ui.feature.patch/feature.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<feature
+      id="org.eclipse.wst.web_ui.feature.patch"
+      label="%featureName"
+      version="3.2.2.qualifier"
+      provider-name="%providerName">
+
+   <description>
+      %description
+   </description>
+
+   <copyright>
+      %copyright
+   </copyright>
+
+   <license url="%licenseURL">
+      %license
+   </license>
+
+   <requires>
+      <import feature="org.eclipse.wst.web_ui.feature" version="3.2.2.v201008100100-7O7CFbKEMf84nUlEJyX7-SPQjhYZ" patch="true"/>
+   </requires>
+
+   <plugin
+         id="org.eclipse.wst.jsdt.web.core"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.wst.jsdt.web.ui"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.wst.html.ui"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+</feature>
diff --git a/features/org.eclipse.wst.web_ui.feature.patch/license.html b/features/org.eclipse.wst.web_ui.feature.patch/license.html
new file mode 100644
index 0000000..c184ca3
--- /dev/null
+++ b/features/org.eclipse.wst.web_ui.feature.patch/license.html
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
+<title>Eclipse Foundation Software User Agreement</title>
+</head>
+
+<body lang="EN-US">
+<h2>Eclipse Foundation Software User Agreement</h2>
+<p>April 14, 2010</p>
+
+<h3>Usage Of Content</h3>
+
+<p>THE ECLIPSE FOUNDATION MAKES AVAILABLE SOFTWARE, DOCUMENTATION, INFORMATION AND/OR OTHER MATERIALS FOR OPEN SOURCE PROJECTS
+   (COLLECTIVELY &quot;CONTENT&quot;).  USE OF THE CONTENT IS GOVERNED BY THE TERMS AND CONDITIONS OF THIS AGREEMENT AND/OR THE TERMS AND
+   CONDITIONS OF LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW.  BY USING THE CONTENT, YOU AGREE THAT YOUR USE
+   OF THE CONTENT IS GOVERNED BY THIS AGREEMENT AND/OR THE TERMS AND CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS OR
+   NOTICES INDICATED OR REFERENCED BELOW.  IF YOU DO NOT AGREE TO THE TERMS AND CONDITIONS OF THIS AGREEMENT AND THE TERMS AND
+   CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW, THEN YOU MAY NOT USE THE CONTENT.</p>
+
+<h3>Applicable Licenses</h3>
+
+<p>Unless otherwise indicated, all Content made available by the Eclipse Foundation is provided to you under the terms and conditions of the Eclipse Public License Version 1.0
+   (&quot;EPL&quot;).  A copy of the EPL is provided with this Content and is also available at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+   For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
+
+<p>Content includes, but is not limited to, source code, object code, documentation and other files maintained in the Eclipse Foundation source code
+   repository (&quot;Repository&quot;) in software modules (&quot;Modules&quot;) and made available as downloadable archives (&quot;Downloads&quot;).</p>
+
+<ul>
+       <li>Content may be structured and packaged into modules to facilitate delivering, extending, and upgrading the Content.  Typical modules may include plug-ins (&quot;Plug-ins&quot;), plug-in fragments (&quot;Fragments&quot;), and features (&quot;Features&quot;).</li>
+       <li>Each Plug-in or Fragment may be packaged as a sub-directory or JAR (Java&trade; ARchive) in a directory named &quot;plugins&quot;.</li>
+       <li>A Feature is a bundle of one or more Plug-ins and/or Fragments and associated material.  Each Feature may be packaged as a sub-directory in a directory named &quot;features&quot;.  Within a Feature, files named &quot;feature.xml&quot; may contain a list of the names and version numbers of the Plug-ins
+      and/or Fragments associated with that Feature.</li>
+       <li>Features may also include other Features (&quot;Included Features&quot;). Within a Feature, files named &quot;feature.xml&quot; may contain a list of the names and version numbers of Included Features.</li>
+</ul>
+
+<p>The terms and conditions governing Plug-ins and Fragments should be contained in files named &quot;about.html&quot; (&quot;Abouts&quot;). The terms and conditions governing Features and
+Included Features should be contained in files named &quot;license.html&quot; (&quot;Feature Licenses&quot;).  Abouts and Feature Licenses may be located in any directory of a Download or Module
+including, but not limited to the following locations:</p>
+
+<ul>
+       <li>The top-level (root) directory</li>
+       <li>Plug-in and Fragment directories</li>
+       <li>Inside Plug-ins and Fragments packaged as JARs</li>
+       <li>Sub-directories of the directory named &quot;src&quot; of certain Plug-ins</li>
+       <li>Feature directories</li>
+</ul>
+
+<p>Note: if a Feature made available by the Eclipse Foundation is installed using the Provisioning Technology (as defined below), you must agree to a license (&quot;Feature Update License&quot;) during the
+installation process.  If the Feature contains Included Features, the Feature Update License should either provide you with the terms and conditions governing the Included Features or
+inform you where you can locate them.  Feature Update Licenses may be found in the &quot;license&quot; property of files named &quot;feature.properties&quot; found within a Feature.
+Such Abouts, Feature Licenses, and Feature Update Licenses contain the terms and conditions (or references to such terms and conditions) that govern your use of the associated Content in
+that directory.</p>
+
+<p>THE ABOUTS, FEATURE LICENSES, AND FEATURE UPDATE LICENSES MAY REFER TO THE EPL OR OTHER LICENSE AGREEMENTS, NOTICES OR TERMS AND CONDITIONS.  SOME OF THESE
+OTHER LICENSE AGREEMENTS MAY INCLUDE (BUT ARE NOT LIMITED TO):</p>
+
+<ul>
+       <li>Common Public License Version 1.0 (available at <a href="http://www.eclipse.org/legal/cpl-v10.html">http://www.eclipse.org/legal/cpl-v10.html</a>)</li>
+       <li>Apache Software License 1.1 (available at <a href="http://www.apache.org/licenses/LICENSE">http://www.apache.org/licenses/LICENSE</a>)</li>
+       <li>Apache Software License 2.0 (available at <a href="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</a>)</li>
+       <li>Metro Link Public License 1.00 (available at <a href="http://www.opengroup.org/openmotif/supporters/metrolink/license.html">http://www.opengroup.org/openmotif/supporters/metrolink/license.html</a>)</li>
+       <li>Mozilla Public License Version 1.1 (available at <a href="http://www.mozilla.org/MPL/MPL-1.1.html">http://www.mozilla.org/MPL/MPL-1.1.html</a>)</li>
+</ul>
+
+<p>IT IS YOUR OBLIGATION TO READ AND ACCEPT ALL SUCH TERMS AND CONDITIONS PRIOR TO USE OF THE CONTENT.  If no About, Feature License, or Feature Update License is provided, please
+contact the Eclipse Foundation to determine what terms and conditions govern that particular Content.</p>
+
+
+<h3>Use of Provisioning Technology</h3>
+
+<p>The Eclipse Foundation makes available provisioning software, examples of which include, but are not limited to, p2 and the Eclipse
+   Update Manager (&quot;Provisioning Technology&quot;) for the purpose of allowing users to install software, documentation, information and/or
+   other materials (collectively &quot;Installable Software&quot;). This capability is provided with the intent of allowing such users to
+   install, extend and update Eclipse-based products. Information about packaging Installable Software is available at <a
+       href="http://eclipse.org/equinox/p2/repository_packaging.html">http://eclipse.org/equinox/p2/repository_packaging.html</a>
+   (&quot;Specification&quot;).</p>
+
+<p>You may use Provisioning Technology to allow other parties to install Installable Software. You shall be responsible for enabling the
+   applicable license agreements relating to the Installable Software to be presented to, and accepted by, the users of the Provisioning Technology
+   in accordance with the Specification. By using Provisioning Technology in such a manner and making it available in accordance with the
+   Specification, you further acknowledge your agreement to, and the acquisition of all necessary rights to permit the following:</p>
+
+<ol>
+       <li>A series of actions may occur (&quot;Provisioning Process&quot;) in which a user may execute the Provisioning Technology
+       on a machine (&quot;Target Machine&quot;) with the intent of installing, extending or updating the functionality of an Eclipse-based
+       product.</li>
+       <li>During the Provisioning Process, the Provisioning Technology may cause third party Installable Software or a portion thereof to be
+       accessed and copied to the Target Machine.</li>
+       <li>Pursuant to the Specification, you will provide to the user the terms and conditions that govern the use of the Installable
+       Software (&quot;Installable Software Agreement&quot;) and such Installable Software Agreement shall be accessed from the Target
+       Machine in accordance with the Specification. Such Installable Software Agreement must inform the user of the terms and conditions that govern
+       the Installable Software and must solicit acceptance by the end user in the manner prescribed in such Installable Software Agreement. Upon such
+       indication of agreement by the user, the provisioning Technology will complete installation of the Installable Software.</li>
+</ol>
+
+<h3>Cryptography</h3>
+
+<p>Content may contain encryption software. The country in which you are currently may have restrictions on the import, possession, and use, and/or re-export to
+   another country, of encryption software. BEFORE using any encryption software, please check the country's laws, regulations and policies concerning the import,
+   possession, or use, and re-export of encryption software, to see if this is permitted.</p>
+
+<p><small>Java and all Java-based trademarks are trademarks of Oracle Corporation in the United States, other countries, or both.</small></p>
+</body>
+</html>
diff --git a/features/org.eclipse.wst.xml_core.feature.patch/.cvsignore b/features/org.eclipse.wst.xml_core.feature.patch/.cvsignore
new file mode 100644
index 0000000..b1d6d30
--- /dev/null
+++ b/features/org.eclipse.wst.xml_core.feature.patch/.cvsignore
@@ -0,0 +1,2 @@
+build.xml
+feature.temp.folder
diff --git a/features/org.eclipse.wst.xml_core.feature.patch/.project b/features/org.eclipse.wst.xml_core.feature.patch/.project
new file mode 100644
index 0000000..648c793
--- /dev/null
+++ b/features/org.eclipse.wst.xml_core.feature.patch/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.wst.xml_core.feature.patch</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.pde.FeatureBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.FeatureNature</nature>
+	</natures>
+</projectDescription>
diff --git a/features/org.eclipse.wst.xml_core.feature.patch/build.properties b/features/org.eclipse.wst.xml_core.feature.patch/build.properties
new file mode 100644
index 0000000..bfd58ab
--- /dev/null
+++ b/features/org.eclipse.wst.xml_core.feature.patch/build.properties
@@ -0,0 +1,6 @@
+bin.includes = feature.xml,\
+               license.html,\
+               feature.properties,\
+               epl-v10.html,\
+               eclipse_update_120.jpg,\
+               buildnotes_bug-165215.html
diff --git a/features/org.eclipse.wst.xml_core.feature.patch/buildnotes_org.eclipse.wst.xml_core.feature.patch.html b/features/org.eclipse.wst.xml_core.feature.patch/buildnotes_org.eclipse.wst.xml_core.feature.patch.html
new file mode 100644
index 0000000..a7a08db
--- /dev/null
+++ b/features/org.eclipse.wst.xml_core.feature.patch/buildnotes_org.eclipse.wst.xml_core.feature.patch.html
@@ -0,0 +1,14 @@
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>Web Tools Platform Patch Build Notes</title>
+</head>
+<body>
+
+
+<h1>WTP 3.2.2 Patches</h1>
+
+<p>Bug <a href='https://bugs.eclipse.org/325818'>325818</a>. Attribute value parsed incorrectly in a jsp</p>
+</body>
+</head>
\ No newline at end of file
diff --git a/features/org.eclipse.wst.xml_core.feature.patch/eclipse_update_120.jpg b/features/org.eclipse.wst.xml_core.feature.patch/eclipse_update_120.jpg
new file mode 100644
index 0000000..bfdf708
--- /dev/null
+++ b/features/org.eclipse.wst.xml_core.feature.patch/eclipse_update_120.jpg
Binary files differ
diff --git a/features/org.eclipse.wst.xml_core.feature.patch/epl-v10.html b/features/org.eclipse.wst.xml_core.feature.patch/epl-v10.html
new file mode 100644
index 0000000..abeecc4
--- /dev/null
+++ b/features/org.eclipse.wst.xml_core.feature.patch/epl-v10.html
@@ -0,0 +1,262 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
+<title>Eclipse Public License - Version 1.0</title>
+<style type="text/css">
+  body {
+    size: 8.5in 11.0in;
+    margin: 0.25in 0.5in 0.25in 0.5in;
+    tab-interval: 0.5in;
+    }
+  p {  	
+    margin-left: auto;
+    margin-top:  0.5em;
+    margin-bottom: 0.5em;
+    }
+  p.list {
+  	margin-left: 0.5in;
+    margin-top:  0.05em;
+    margin-bottom: 0.05em;
+    }
+  </style>
+
+</head>
+
+<body lang="EN-US">
+
+<h2>Eclipse Public License - v 1.0</h2>
+
+<p>THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE
+PUBLIC LICENSE (&quot;AGREEMENT&quot;). ANY USE, REPRODUCTION OR
+DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS
+AGREEMENT.</p>
+
+<p><b>1. DEFINITIONS</b></p>
+
+<p>&quot;Contribution&quot; means:</p>
+
+<p class="list">a) in the case of the initial Contributor, the initial
+code and documentation distributed under this Agreement, and</p>
+<p class="list">b) in the case of each subsequent Contributor:</p>
+
+<p class="list">i) changes to the Program, and</p>
+<p class="list">ii) additions to the Program;</p>
+<p class="list">where such changes and/or additions to the Program
+originate from and are distributed by that particular Contributor. A
+Contribution 'originates' from a Contributor if it was added to the
+Program by such Contributor itself or anyone acting on such
+Contributor's behalf. Contributions do not include additions to the
+Program which: (i) are separate modules of software distributed in
+conjunction with the Program under their own license agreement, and (ii)
+are not derivative works of the Program.</p>
+
+<p>&quot;Contributor&quot; means any person or entity that distributes
+the Program.</p>
+
+<p>&quot;Licensed Patents&quot; mean patent claims licensable by a
+Contributor which are necessarily infringed by the use or sale of its
+Contribution alone or when combined with the Program.</p>
+
+<p>&quot;Program&quot; means the Contributions distributed in accordance
+with this Agreement.</p>
+
+<p>&quot;Recipient&quot; means anyone who receives the Program under
+this Agreement, including all Contributors.</p>
+
+<p><b>2. GRANT OF RIGHTS</b></p>
+
+<p class="list">a) Subject to the terms of this Agreement, each
+Contributor hereby grants Recipient a non-exclusive, worldwide,
+royalty-free copyright license to reproduce, prepare derivative works
+of, publicly display, publicly perform, distribute and sublicense the
+Contribution of such Contributor, if any, and such derivative works, in
+source code and object code form.</p>
+
+<p class="list">b) Subject to the terms of this Agreement, each
+Contributor hereby grants Recipient a non-exclusive, worldwide,
+royalty-free patent license under Licensed Patents to make, use, sell,
+offer to sell, import and otherwise transfer the Contribution of such
+Contributor, if any, in source code and object code form. This patent
+license shall apply to the combination of the Contribution and the
+Program if, at the time the Contribution is added by the Contributor,
+such addition of the Contribution causes such combination to be covered
+by the Licensed Patents. The patent license shall not apply to any other
+combinations which include the Contribution. No hardware per se is
+licensed hereunder.</p>
+
+<p class="list">c) Recipient understands that although each Contributor
+grants the licenses to its Contributions set forth herein, no assurances
+are provided by any Contributor that the Program does not infringe the
+patent or other intellectual property rights of any other entity. Each
+Contributor disclaims any liability to Recipient for claims brought by
+any other entity based on infringement of intellectual property rights
+or otherwise. As a condition to exercising the rights and licenses
+granted hereunder, each Recipient hereby assumes sole responsibility to
+secure any other intellectual property rights needed, if any. For
+example, if a third party patent license is required to allow Recipient
+to distribute the Program, it is Recipient's responsibility to acquire
+that license before distributing the Program.</p>
+
+<p class="list">d) Each Contributor represents that to its knowledge it
+has sufficient copyright rights in its Contribution, if any, to grant
+the copyright license set forth in this Agreement.</p>
+
+<p><b>3. REQUIREMENTS</b></p>
+
+<p>A Contributor may choose to distribute the Program in object code
+form under its own license agreement, provided that:</p>
+
+<p class="list">a) it complies with the terms and conditions of this
+Agreement; and</p>
+
+<p class="list">b) its license agreement:</p>
+
+<p class="list">i) effectively disclaims on behalf of all Contributors
+all warranties and conditions, express and implied, including warranties
+or conditions of title and non-infringement, and implied warranties or
+conditions of merchantability and fitness for a particular purpose;</p>
+
+<p class="list">ii) effectively excludes on behalf of all Contributors
+all liability for damages, including direct, indirect, special,
+incidental and consequential damages, such as lost profits;</p>
+
+<p class="list">iii) states that any provisions which differ from this
+Agreement are offered by that Contributor alone and not by any other
+party; and</p>
+
+<p class="list">iv) states that source code for the Program is available
+from such Contributor, and informs licensees how to obtain it in a
+reasonable manner on or through a medium customarily used for software
+exchange.</p>
+
+<p>When the Program is made available in source code form:</p>
+
+<p class="list">a) it must be made available under this Agreement; and</p>
+
+<p class="list">b) a copy of this Agreement must be included with each
+copy of the Program.</p>
+
+<p>Contributors may not remove or alter any copyright notices contained
+within the Program.</p>
+
+<p>Each Contributor must identify itself as the originator of its
+Contribution, if any, in a manner that reasonably allows subsequent
+Recipients to identify the originator of the Contribution.</p>
+
+<p><b>4. COMMERCIAL DISTRIBUTION</b></p>
+
+<p>Commercial distributors of software may accept certain
+responsibilities with respect to end users, business partners and the
+like. While this license is intended to facilitate the commercial use of
+the Program, the Contributor who includes the Program in a commercial
+product offering should do so in a manner which does not create
+potential liability for other Contributors. Therefore, if a Contributor
+includes the Program in a commercial product offering, such Contributor
+(&quot;Commercial Contributor&quot;) hereby agrees to defend and
+indemnify every other Contributor (&quot;Indemnified Contributor&quot;)
+against any losses, damages and costs (collectively &quot;Losses&quot;)
+arising from claims, lawsuits and other legal actions brought by a third
+party against the Indemnified Contributor to the extent caused by the
+acts or omissions of such Commercial Contributor in connection with its
+distribution of the Program in a commercial product offering. The
+obligations in this section do not apply to any claims or Losses
+relating to any actual or alleged intellectual property infringement. In
+order to qualify, an Indemnified Contributor must: a) promptly notify
+the Commercial Contributor in writing of such claim, and b) allow the
+Commercial Contributor to control, and cooperate with the Commercial
+Contributor in, the defense and any related settlement negotiations. The
+Indemnified Contributor may participate in any such claim at its own
+expense.</p>
+
+<p>For example, a Contributor might include the Program in a commercial
+product offering, Product X. That Contributor is then a Commercial
+Contributor. If that Commercial Contributor then makes performance
+claims, or offers warranties related to Product X, those performance
+claims and warranties are such Commercial Contributor's responsibility
+alone. Under this section, the Commercial Contributor would have to
+defend claims against the other Contributors related to those
+performance claims and warranties, and if a court requires any other
+Contributor to pay any damages as a result, the Commercial Contributor
+must pay those damages.</p>
+
+<p><b>5. NO WARRANTY</b></p>
+
+<p>EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS
+PROVIDED ON AN &quot;AS IS&quot; BASIS, WITHOUT WARRANTIES OR CONDITIONS
+OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION,
+ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY
+OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely
+responsible for determining the appropriateness of using and
+distributing the Program and assumes all risks associated with its
+exercise of rights under this Agreement , including but not limited to
+the risks and costs of program errors, compliance with applicable laws,
+damage to or loss of data, programs or equipment, and unavailability or
+interruption of operations.</p>
+
+<p><b>6. DISCLAIMER OF LIABILITY</b></p>
+
+<p>EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT
+NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING
+WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR
+DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.</p>
+
+<p><b>7. GENERAL</b></p>
+
+<p>If any provision of this Agreement is invalid or unenforceable under
+applicable law, it shall not affect the validity or enforceability of
+the remainder of the terms of this Agreement, and without further action
+by the parties hereto, such provision shall be reformed to the minimum
+extent necessary to make such provision valid and enforceable.</p>
+
+<p>If Recipient institutes patent litigation against any entity
+(including a cross-claim or counterclaim in a lawsuit) alleging that the
+Program itself (excluding combinations of the Program with other
+software or hardware) infringes such Recipient's patent(s), then such
+Recipient's rights granted under Section 2(b) shall terminate as of the
+date such litigation is filed.</p>
+
+<p>All Recipient's rights under this Agreement shall terminate if it
+fails to comply with any of the material terms or conditions of this
+Agreement and does not cure such failure in a reasonable period of time
+after becoming aware of such noncompliance. If all Recipient's rights
+under this Agreement terminate, Recipient agrees to cease use and
+distribution of the Program as soon as reasonably practicable. However,
+Recipient's obligations under this Agreement and any licenses granted by
+Recipient relating to the Program shall continue and survive.</p>
+
+<p>Everyone is permitted to copy and distribute copies of this
+Agreement, but in order to avoid inconsistency the Agreement is
+copyrighted and may only be modified in the following manner. The
+Agreement Steward reserves the right to publish new versions (including
+revisions) of this Agreement from time to time. No one other than the
+Agreement Steward has the right to modify this Agreement. The Eclipse
+Foundation is the initial Agreement Steward. The Eclipse Foundation may
+assign the responsibility to serve as the Agreement Steward to a
+suitable separate entity. Each new version of the Agreement will be
+given a distinguishing version number. The Program (including
+Contributions) may always be distributed subject to the version of the
+Agreement under which it was received. In addition, after a new version
+of the Agreement is published, Contributor may elect to distribute the
+Program (including its Contributions) under the new version. Except as
+expressly stated in Sections 2(a) and 2(b) above, Recipient receives no
+rights or licenses to the intellectual property of any Contributor under
+this Agreement, whether expressly, by implication, estoppel or
+otherwise. All rights in the Program not expressly granted under this
+Agreement are reserved.</p>
+
+<p>This Agreement is governed by the laws of the State of New York and
+the intellectual property laws of the United States of America. No party
+to this Agreement will bring a legal action under this Agreement more
+than one year after the cause of action arose. Each party waives its
+rights to a jury trial in any resulting litigation.</p>
+
+</body>
+
+</html>
diff --git a/features/org.eclipse.wst.xml_core.feature.patch/feature.properties b/features/org.eclipse.wst.xml_core.feature.patch/feature.properties
new file mode 100644
index 0000000..26345db
--- /dev/null
+++ b/features/org.eclipse.wst.xml_core.feature.patch/feature.properties
@@ -0,0 +1,173 @@
+###############################################################################
+# Copyright (c) 2008 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
+###############################################################################
+# feature.properties
+# contains externalized strings for feature.xml
+# "%foo" in feature.xml corresponds to the key "foo" in this file
+# java.io.Properties file (ISO 8859-1 with "\" escapes)
+# This file should be translated.
+
+# "featureName" property - name of the feature
+featureName=WTP Patches for org.eclipse.wst.xml_core.feature
+
+# "providerName" property - name of the company that provides the feature
+providerName=Eclipse Web Tools Platform
+
+# "updateSiteName" property - label for the update site
+updateSiteName=The Eclipse Web Tools Platform (WTP) Project update site
+
+# "description" property - description of the feature
+description=\
+The bugs and fixes are described in the following bugzilla entries:\n\
+\n\
+Bug https://bugs.eclipse.org/325818 Attribute value parsed incorrectly in a jsp\n\
+\n\
+# "copyright" property - text of the "Feature Update Copyright"
+copyright=\
+Copyright (c) 2010 IBM Corporation and others.\n\
+All rights reserved. This program and the accompanying materials\n\
+are made available under the terms of the Eclipse Public License v1.0\n\
+which accompanies this distribution, and is available at\n\
+http://www.eclipse.org/legal/epl-v10.html\n\
+\n\
+Contributors:\n\
+    IBM Corporation - initial API and implementation\n
+################ end of copyright property ####################################
+
+# "licenseURL" property - URL of the "Feature License"
+# do not translate value - just change to point to a locale-specific HTML page
+licenseURL=license.html
+
+# "license" property - text of the "Feature Update License"
+# should be plain text version of license agreement pointed to be "licenseURL"
+license=\
+Eclipse Foundation Software User Agreement\n\
+April 14, 2010\n\
+\n\
+Usage Of Content\n\
+\n\
+THE ECLIPSE FOUNDATION MAKES AVAILABLE SOFTWARE, DOCUMENTATION, INFORMATION AND/OR\n\
+OTHER MATERIALS FOR OPEN SOURCE PROJECTS (COLLECTIVELY "CONTENT").\n\
+USE OF THE CONTENT IS GOVERNED BY THE TERMS AND CONDITIONS OF THIS\n\
+AGREEMENT AND/OR THE TERMS AND CONDITIONS OF LICENSE AGREEMENTS OR\n\
+NOTICES INDICATED OR REFERENCED BELOW.  BY USING THE CONTENT, YOU\n\
+AGREE THAT YOUR USE OF THE CONTENT IS GOVERNED BY THIS AGREEMENT\n\
+AND/OR THE TERMS AND CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS\n\
+OR NOTICES INDICATED OR REFERENCED BELOW.  IF YOU DO NOT AGREE TO THE\n\
+TERMS AND CONDITIONS OF THIS AGREEMENT AND THE TERMS AND CONDITIONS\n\
+OF ANY APPLICABLE LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED\n\
+BELOW, THEN YOU MAY NOT USE THE CONTENT.\n\
+\n\
+Applicable Licenses\n\
+\n\
+Unless otherwise indicated, all Content made available by the\n\
+Eclipse Foundation is provided to you under the terms and conditions of\n\
+the Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is\n\
+provided with this Content and is also available at http://www.eclipse.org/legal/epl-v10.html.\n\
+For purposes of the EPL, "Program" will mean the Content.\n\
+\n\
+Content includes, but is not limited to, source code, object code,\n\
+documentation and other files maintained in the Eclipse Foundation source code\n\
+repository ("Repository") in software modules ("Modules") and made available\n\
+as downloadable archives ("Downloads").\n\
+\n\
+       - Content may be structured and packaged into modules to facilitate delivering,\n\
+         extending, and upgrading the Content. Typical modules may include plug-ins ("Plug-ins"),\n\
+         plug-in fragments ("Fragments"), and features ("Features").\n\
+       - Each Plug-in or Fragment may be packaged as a sub-directory or JAR (Java(TM) ARchive)\n\
+         in a directory named "plugins".\n\
+       - A Feature is a bundle of one or more Plug-ins and/or Fragments and associated material.\n\
+         Each Feature may be packaged as a sub-directory in a directory named "features".\n\
+         Within a Feature, files named "feature.xml" may contain a list of the names and version\n\
+         numbers of the Plug-ins and/or Fragments associated with that Feature.\n\
+       - Features may also include other Features ("Included Features"). Within a Feature, files\n\
+         named "feature.xml" may contain a list of the names and version numbers of Included Features.\n\
+\n\
+The terms and conditions governing Plug-ins and Fragments should be\n\
+contained in files named "about.html" ("Abouts"). The terms and\n\
+conditions governing Features and Included Features should be contained\n\
+in files named "license.html" ("Feature Licenses"). Abouts and Feature\n\
+Licenses may be located in any directory of a Download or Module\n\
+including, but not limited to the following locations:\n\
+\n\
+       - The top-level (root) directory\n\
+       - Plug-in and Fragment directories\n\
+       - Inside Plug-ins and Fragments packaged as JARs\n\
+       - Sub-directories of the directory named "src" of certain Plug-ins\n\
+       - Feature directories\n\
+\n\
+Note: if a Feature made available by the Eclipse Foundation is installed using the\n\
+Provisioning Technology (as defined below), you must agree to a license ("Feature \n\
+Update License") during the installation process. If the Feature contains\n\
+Included Features, the Feature Update License should either provide you\n\
+with the terms and conditions governing the Included Features or inform\n\
+you where you can locate them. Feature Update Licenses may be found in\n\
+the "license" property of files named "feature.properties" found within a Feature.\n\
+Such Abouts, Feature Licenses, and Feature Update Licenses contain the\n\
+terms and conditions (or references to such terms and conditions) that\n\
+govern your use of the associated Content in that directory.\n\
+\n\
+THE ABOUTS, FEATURE LICENSES, AND FEATURE UPDATE LICENSES MAY REFER\n\
+TO THE EPL OR OTHER LICENSE AGREEMENTS, NOTICES OR TERMS AND CONDITIONS.\n\
+SOME OF THESE OTHER LICENSE AGREEMENTS MAY INCLUDE (BUT ARE NOT LIMITED TO):\n\
+\n\
+       - Common Public License Version 1.0 (available at http://www.eclipse.org/legal/cpl-v10.html)\n\
+       - Apache Software License 1.1 (available at http://www.apache.org/licenses/LICENSE)\n\
+       - Apache Software License 2.0 (available at http://www.apache.org/licenses/LICENSE-2.0)\n\
+       - Metro Link Public License 1.00 (available at http://www.opengroup.org/openmotif/supporters/metrolink/license.html)\n\
+       - Mozilla Public License Version 1.1 (available at http://www.mozilla.org/MPL/MPL-1.1.html)\n\
+\n\
+IT IS YOUR OBLIGATION TO READ AND ACCEPT ALL SUCH TERMS AND CONDITIONS PRIOR\n\
+TO USE OF THE CONTENT. If no About, Feature License, or Feature Update License\n\
+is provided, please contact the Eclipse Foundation to determine what terms and conditions\n\
+govern that particular Content.\n\
+\n\
+\n\Use of Provisioning Technology\n\
+\n\
+The Eclipse Foundation makes available provisioning software, examples of which include,\n\
+but are not limited to, p2 and the Eclipse Update Manager ("Provisioning Technology") for\n\
+the purpose of allowing users to install software, documentation, information and/or\n\
+other materials (collectively "Installable Software"). This capability is provided with\n\
+the intent of allowing such users to install, extend and update Eclipse-based products.\n\
+Information about packaging Installable Software is available at\n\
+http://eclipse.org/equinox/p2/repository_packaging.html ("Specification").\n\
+\n\
+You may use Provisioning Technology to allow other parties to install Installable Software.\n\
+You shall be responsible for enabling the applicable license agreements relating to the\n\
+Installable Software to be presented to, and accepted by, the users of the Provisioning Technology\n\
+in accordance with the Specification. By using Provisioning Technology in such a manner and\n\
+making it available in accordance with the Specification, you further acknowledge your\n\
+agreement to, and the acquisition of all necessary rights to permit the following:\n\
+\n\
+       1. A series of actions may occur ("Provisioning Process") in which a user may execute\n\
+          the Provisioning Technology on a machine ("Target Machine") with the intent of installing,\n\
+          extending or updating the functionality of an Eclipse-based product.\n\
+       2. During the Provisioning Process, the Provisioning Technology may cause third party\n\
+          Installable Software or a portion thereof to be accessed and copied to the Target Machine.\n\
+       3. Pursuant to the Specification, you will provide to the user the terms and conditions that\n\
+          govern the use of the Installable Software ("Installable Software Agreement") and such\n\
+          Installable Software Agreement shall be accessed from the Target Machine in accordance\n\
+          with the Specification. Such Installable Software Agreement must inform the user of the\n\
+          terms and conditions that govern the Installable Software and must solicit acceptance by\n\
+          the end user in the manner prescribed in such Installable Software Agreement. Upon such\n\
+          indication of agreement by the user, the provisioning Technology will complete installation\n\
+          of the Installable Software.\n\
+\n\
+Cryptography\n\
+\n\
+Content may contain encryption software. The country in which you are\n\
+currently may have restrictions on the import, possession, and use,\n\
+and/or re-export to another country, of encryption software. BEFORE\n\
+using any encryption software, please check the country's laws,\n\
+regulations and policies concerning the import, possession, or use, and\n\
+re-export of encryption software, to see if this is permitted.\n\
+\n\
+Java and all Java-based trademarks are trademarks of Oracle Corporation in the United States, other countries, or both.\n
+########### end of license property ##########################################
diff --git a/features/org.eclipse.wst.xml_core.feature.patch/feature.xml b/features/org.eclipse.wst.xml_core.feature.patch/feature.xml
new file mode 100644
index 0000000..5835104
--- /dev/null
+++ b/features/org.eclipse.wst.xml_core.feature.patch/feature.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<feature
+      id="org.eclipse.wst.xml_core.feature.patch"
+      label="%featureName"
+      version="3.2.2.qualifier"
+      provider-name="%providerName">
+
+   <description>
+      %description
+   </description>
+
+   <copyright>
+      %copyright
+   </copyright>
+
+   <license url="%licenseURL">
+      %license
+   </license>
+
+   <url>
+      <update label="%updateSiteName" url="http://download.eclipse.org/webtools/updates/"/>
+   </url>
+
+   <requires>
+      <import feature="org.eclipse.wst.xml_core.feature" version="3.2.2.v201008170029-7C7OFXYF7RZHQHI5PyJwPT" patch="true"/>
+   </requires>
+
+   <plugin
+         id="org.eclipse.wst.sse.core"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   </feature>
diff --git a/features/org.eclipse.wst.xml_core.feature.patch/license.html b/features/org.eclipse.wst.xml_core.feature.patch/license.html
new file mode 100644
index 0000000..c184ca3
--- /dev/null
+++ b/features/org.eclipse.wst.xml_core.feature.patch/license.html
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
+<title>Eclipse Foundation Software User Agreement</title>
+</head>
+
+<body lang="EN-US">
+<h2>Eclipse Foundation Software User Agreement</h2>
+<p>April 14, 2010</p>
+
+<h3>Usage Of Content</h3>
+
+<p>THE ECLIPSE FOUNDATION MAKES AVAILABLE SOFTWARE, DOCUMENTATION, INFORMATION AND/OR OTHER MATERIALS FOR OPEN SOURCE PROJECTS
+   (COLLECTIVELY &quot;CONTENT&quot;).  USE OF THE CONTENT IS GOVERNED BY THE TERMS AND CONDITIONS OF THIS AGREEMENT AND/OR THE TERMS AND
+   CONDITIONS OF LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW.  BY USING THE CONTENT, YOU AGREE THAT YOUR USE
+   OF THE CONTENT IS GOVERNED BY THIS AGREEMENT AND/OR THE TERMS AND CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS OR
+   NOTICES INDICATED OR REFERENCED BELOW.  IF YOU DO NOT AGREE TO THE TERMS AND CONDITIONS OF THIS AGREEMENT AND THE TERMS AND
+   CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW, THEN YOU MAY NOT USE THE CONTENT.</p>
+
+<h3>Applicable Licenses</h3>
+
+<p>Unless otherwise indicated, all Content made available by the Eclipse Foundation is provided to you under the terms and conditions of the Eclipse Public License Version 1.0
+   (&quot;EPL&quot;).  A copy of the EPL is provided with this Content and is also available at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+   For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
+
+<p>Content includes, but is not limited to, source code, object code, documentation and other files maintained in the Eclipse Foundation source code
+   repository (&quot;Repository&quot;) in software modules (&quot;Modules&quot;) and made available as downloadable archives (&quot;Downloads&quot;).</p>
+
+<ul>
+       <li>Content may be structured and packaged into modules to facilitate delivering, extending, and upgrading the Content.  Typical modules may include plug-ins (&quot;Plug-ins&quot;), plug-in fragments (&quot;Fragments&quot;), and features (&quot;Features&quot;).</li>
+       <li>Each Plug-in or Fragment may be packaged as a sub-directory or JAR (Java&trade; ARchive) in a directory named &quot;plugins&quot;.</li>
+       <li>A Feature is a bundle of one or more Plug-ins and/or Fragments and associated material.  Each Feature may be packaged as a sub-directory in a directory named &quot;features&quot;.  Within a Feature, files named &quot;feature.xml&quot; may contain a list of the names and version numbers of the Plug-ins
+      and/or Fragments associated with that Feature.</li>
+       <li>Features may also include other Features (&quot;Included Features&quot;). Within a Feature, files named &quot;feature.xml&quot; may contain a list of the names and version numbers of Included Features.</li>
+</ul>
+
+<p>The terms and conditions governing Plug-ins and Fragments should be contained in files named &quot;about.html&quot; (&quot;Abouts&quot;). The terms and conditions governing Features and
+Included Features should be contained in files named &quot;license.html&quot; (&quot;Feature Licenses&quot;).  Abouts and Feature Licenses may be located in any directory of a Download or Module
+including, but not limited to the following locations:</p>
+
+<ul>
+       <li>The top-level (root) directory</li>
+       <li>Plug-in and Fragment directories</li>
+       <li>Inside Plug-ins and Fragments packaged as JARs</li>
+       <li>Sub-directories of the directory named &quot;src&quot; of certain Plug-ins</li>
+       <li>Feature directories</li>
+</ul>
+
+<p>Note: if a Feature made available by the Eclipse Foundation is installed using the Provisioning Technology (as defined below), you must agree to a license (&quot;Feature Update License&quot;) during the
+installation process.  If the Feature contains Included Features, the Feature Update License should either provide you with the terms and conditions governing the Included Features or
+inform you where you can locate them.  Feature Update Licenses may be found in the &quot;license&quot; property of files named &quot;feature.properties&quot; found within a Feature.
+Such Abouts, Feature Licenses, and Feature Update Licenses contain the terms and conditions (or references to such terms and conditions) that govern your use of the associated Content in
+that directory.</p>
+
+<p>THE ABOUTS, FEATURE LICENSES, AND FEATURE UPDATE LICENSES MAY REFER TO THE EPL OR OTHER LICENSE AGREEMENTS, NOTICES OR TERMS AND CONDITIONS.  SOME OF THESE
+OTHER LICENSE AGREEMENTS MAY INCLUDE (BUT ARE NOT LIMITED TO):</p>
+
+<ul>
+       <li>Common Public License Version 1.0 (available at <a href="http://www.eclipse.org/legal/cpl-v10.html">http://www.eclipse.org/legal/cpl-v10.html</a>)</li>
+       <li>Apache Software License 1.1 (available at <a href="http://www.apache.org/licenses/LICENSE">http://www.apache.org/licenses/LICENSE</a>)</li>
+       <li>Apache Software License 2.0 (available at <a href="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</a>)</li>
+       <li>Metro Link Public License 1.00 (available at <a href="http://www.opengroup.org/openmotif/supporters/metrolink/license.html">http://www.opengroup.org/openmotif/supporters/metrolink/license.html</a>)</li>
+       <li>Mozilla Public License Version 1.1 (available at <a href="http://www.mozilla.org/MPL/MPL-1.1.html">http://www.mozilla.org/MPL/MPL-1.1.html</a>)</li>
+</ul>
+
+<p>IT IS YOUR OBLIGATION TO READ AND ACCEPT ALL SUCH TERMS AND CONDITIONS PRIOR TO USE OF THE CONTENT.  If no About, Feature License, or Feature Update License is provided, please
+contact the Eclipse Foundation to determine what terms and conditions govern that particular Content.</p>
+
+
+<h3>Use of Provisioning Technology</h3>
+
+<p>The Eclipse Foundation makes available provisioning software, examples of which include, but are not limited to, p2 and the Eclipse
+   Update Manager (&quot;Provisioning Technology&quot;) for the purpose of allowing users to install software, documentation, information and/or
+   other materials (collectively &quot;Installable Software&quot;). This capability is provided with the intent of allowing such users to
+   install, extend and update Eclipse-based products. Information about packaging Installable Software is available at <a
+       href="http://eclipse.org/equinox/p2/repository_packaging.html">http://eclipse.org/equinox/p2/repository_packaging.html</a>
+   (&quot;Specification&quot;).</p>
+
+<p>You may use Provisioning Technology to allow other parties to install Installable Software. You shall be responsible for enabling the
+   applicable license agreements relating to the Installable Software to be presented to, and accepted by, the users of the Provisioning Technology
+   in accordance with the Specification. By using Provisioning Technology in such a manner and making it available in accordance with the
+   Specification, you further acknowledge your agreement to, and the acquisition of all necessary rights to permit the following:</p>
+
+<ol>
+       <li>A series of actions may occur (&quot;Provisioning Process&quot;) in which a user may execute the Provisioning Technology
+       on a machine (&quot;Target Machine&quot;) with the intent of installing, extending or updating the functionality of an Eclipse-based
+       product.</li>
+       <li>During the Provisioning Process, the Provisioning Technology may cause third party Installable Software or a portion thereof to be
+       accessed and copied to the Target Machine.</li>
+       <li>Pursuant to the Specification, you will provide to the user the terms and conditions that govern the use of the Installable
+       Software (&quot;Installable Software Agreement&quot;) and such Installable Software Agreement shall be accessed from the Target
+       Machine in accordance with the Specification. Such Installable Software Agreement must inform the user of the terms and conditions that govern
+       the Installable Software and must solicit acceptance by the end user in the manner prescribed in such Installable Software Agreement. Upon such
+       indication of agreement by the user, the provisioning Technology will complete installation of the Installable Software.</li>
+</ol>
+
+<h3>Cryptography</h3>
+
+<p>Content may contain encryption software. The country in which you are currently may have restrictions on the import, possession, and use, and/or re-export to
+   another country, of encryption software. BEFORE using any encryption software, please check the country's laws, regulations and policies concerning the import,
+   possession, or use, and re-export of encryption software, to see if this is permitted.</p>
+
+<p><small>Java and all Java-based trademarks are trademarks of Oracle Corporation in the United States, other countries, or both.</small></p>
+</body>
+</html>